Save final-review value field-block edits from the open card, and keep Duplicate available until six values are picked.

This commit is contained in:
adilallo committed 2026-11-05 22:09:14 -07:00
1 parent 64a542f456
commit 772370c4e7
2 files changed
+176 -3

No files matched your search

+168
View File
@@ -10,6 +10,7 @@ import {
import "@testing-library/jest-dom/vitest";
import { FinalReviewScreen } from "../../app/(app)/create/screens/review/FinalReviewScreen";
import { useCreateFlow } from "../../app/(app)/create/context/CreateFlowContext";
import { clearCoreValueDetailsLocalStorage } from "../../app/(app)/create/utils/coreValueDetailsLocalStorage";
import type { CreateFlowState } from "../../app/(app)/create/types";
function catalogChipName(label: string) {
@@ -363,6 +364,173 @@ describe("FinalReviewScreen — chip detail modal", () => {
).not.toBeInTheDocument();
});
it("offers Duplicate with five values picked and hides it at six", async () => {
function CoreValuesHarness({ count }: { count: number }) {
const { replaceState } = useCreateFlow();
useLayoutEffect(() => {
const ids = Array.from({ length: count }, (_, i) => String(i + 1));
replaceState({
selectedCoreValueIds: ids,
coreValuesChipsSnapshot: ids.map((id, i) => ({
id,
label: `Value ${i + 1}`,
state: "selected" as const,
})),
});
}, [count, replaceState]);
return <FinalReviewScreen />;
}
const { unmount } = render(<CoreValuesHarness count={5} />);
fireEvent.click(
await screen.findByRole("button", { name: catalogChipName("Value 1") }),
);
fireEvent.click(
within(await screen.findByRole("dialog")).getByRole("button", {
name: /more options/i,
}),
);
expect(
await screen.findByRole("menuitem", { name: /^duplicate$/i }),
).toBeInTheDocument();
unmount();
render(<CoreValuesHarness count={6} />);
fireEvent.click(
await screen.findByRole("button", { name: catalogChipName("Value 1") }),
);
fireEvent.click(
within(await screen.findByRole("dialog")).getByRole("button", {
name: /more options/i,
}),
);
await waitFor(() => {
expect(
screen.getByRole("menuitem", { name: /^customize$/i }),
).toBeInTheDocument();
});
expect(
screen.queryByRole("menuitem", { name: /^duplicate$/i }),
).not.toBeInTheDocument();
});
it("duplicates a fifth value into the remaining slot", async () => {
let latest: CreateFlowState = {};
render(
<FinalReviewWithStateProbe
onState={(s) => {
latest = s;
}}
initial={{
selectedCoreValueIds: ["1", "2", "3", "4", "5"],
coreValuesChipsSnapshot: ["1", "2", "3", "4", "5"].map((id, i) => ({
id,
label: `Value ${i + 1}`,
state: "selected" as const,
})),
}}
/>,
);
fireEvent.click(
await screen.findByRole("button", { name: catalogChipName("Value 1") }),
);
fireEvent.click(
within(await screen.findByRole("dialog")).getByRole("button", {
name: /more options/i,
}),
);
fireEvent.click(
await screen.findByRole("menuitem", { name: /^duplicate$/i }),
);
await waitFor(() => {
expect(latest.selectedCoreValueIds).toHaveLength(6);
});
expect(latest.coreValuesChipsSnapshot?.map((row) => row.label)).toContain(
"Value 1 (copy)",
);
});
it("saves in-modal edits to extra value field blocks", async () => {
let latest: CreateFlowState = {};
let view: ReturnType<typeof render> | undefined;
try {
view = render(
<FinalReviewWithStateProbe
onState={(s) => {
latest = s;
}}
initial={{
selectedCoreValueIds: ["1"],
coreValuesChipsSnapshot: [
{ id: "1", label: "Accessibility", state: "selected" },
],
coreValueDetailsByChipId: {
"1": {
meaning: "Everyone can participate.",
signals: "Captions and ramps.",
},
},
customMethodCardFieldBlocksById: {
"1": [
{
kind: "text",
id: "extra-note",
blockTitle: "House note",
placeholderText: "Be kind.",
},
{
kind: "text",
id: "facet-meaning",
blockTitle: "What this value means",
placeholderText: "Everyone can participate.",
},
{
kind: "text",
id: "facet-signals",
blockTitle: "Signals",
placeholderText: "Captions and ramps.",
},
],
},
}}
/>,
);
fireEvent.click(
await screen.findByRole("button", {
name: catalogChipName("Accessibility"),
}),
);
const dialog = await screen.findByRole("dialog");
fireEvent.change(
within(dialog).getByRole("textbox", { name: "House note" }),
{ target: { value: "Leave the ramp clear." } },
);
const save = within(dialog).getByRole("button", { name: "Save" });
await waitFor(() => {
expect(save).toBeEnabled();
});
fireEvent.click(save);
await waitFor(() => {
expect(
latest.customMethodCardFieldBlocksById?.["1"]?.map(
(block) => block.id,
),
).toEqual(["extra-note", "facet-meaning", "facet-signals"]);
});
const extra = latest.customMethodCardFieldBlocksById?.["1"]?.find(
(block) => block.id === "extra-note",
);
expect(extra?.kind === "text" ? extra.placeholderText : "").toBe(
"Leave the ramp clear.",
);
} finally {
view?.unmount();
clearCoreValueDetailsLocalStorage();
}
});
it("values Customize starts on the policy name step", async () => {
function CoreValuesHarness() {
const { replaceState } = useCreateFlow();