fix(housekeeping): clear poll question options

This commit is contained in:
Simo committed 2026-09-02 20:17:28 +02:00
1 parent 51eecd0e72
commit 766e7e20c8
2 files changed
+69 -1

No files matched your search

@@ -1,5 +1,6 @@
import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, it } from "vitest";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { executeHousekeepingCommand } from "@/actions/housekeeping-command";
import { PERMS } from "@/lib/permission-slugs";
import {
fail,
@@ -12,6 +13,30 @@ import type {
} from "../queries/content-queries";
import { ContentPollWorkflow } from "./poll-workflow";
const { actionCallbacks } = vi.hoisted(() => ({
actionCallbacks: [] as Array<
(previous: unknown, formData: FormData) => Promise<unknown>
>,
}));
vi.mock("react", async (importOriginal) => {
const actual = await importOriginal<typeof import("react")>();
return {
...actual,
useActionState: (
action: (previous: unknown, formData: FormData) => Promise<unknown>,
initialState: unknown,
) => {
actionCallbacks.push(action);
return [initialState, vi.fn(), false] as const;
},
};
});
vi.mock("@/actions/housekeeping-command", () => ({
executeHousekeepingCommand: vi.fn(),
}));
function context(granted: readonly string[]): HousekeepingCapabilityContext {
const permissions = new Set(granted);
return {
@@ -118,6 +143,11 @@ function renderList(
}
describe("Content Poll workflow", () => {
beforeEach(() => {
actionCallbacks.length = 0;
vi.clearAllMocks();
});
it("renders explicit loading, forbidden, dependency-error, empty, and malformed states", () => {
expect(renderList(viewer)).toContain('data-housekeeping-state="loading"');
expect(
@@ -286,6 +316,43 @@ describe("Content Poll workflow", () => {
expect(html.match(/name="reason"/gu)).toHaveLength(3);
});
it("submits empty options when changing a choice question to text", async () => {
vi.mocked(executeHousekeepingCommand).mockResolvedValue(
ok({}, "question-text-update"),
);
renderToStaticMarkup(
<ContentPollWorkflow
title="Poll detail"
context={editor}
result={ok(data([pollItem]), "detail-edit-submit")}
routeId="content.engagement.poll-detail"
list={list}
/>,
);
const questionUpdate = actionCallbacks[1];
if (!questionUpdate)
throw new Error("Question update action was not bound");
const formData = new FormData();
formData.set("question", "Pick a colour");
formData.set("type", "text");
formData.set("sortOrder", "0");
formData.set("options", "");
await questionUpdate(null, formData);
expect(executeHousekeepingCommand).toHaveBeenCalledWith({
commandId: "content.engagement.poll-question.change",
input: {
action: "update",
id: "21",
question: "Pick a colour",
type: "text",
sortOrder: 0,
options: "",
},
});
});
it("distinguishes true not-found detail from malformed successful data", () => {
const render = (items: ContentQueryData["items"]) =>
renderToStaticMarkup(
@@ -184,6 +184,7 @@ function questionFields(
name: "options",
label: "Options (one per line)",
type: "textarea",
emptyValue: "",
maxLength: 20_000,
defaultValue: question?.options.join("\n"),
},