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:
1 parent
64a542f456
commit
772370c4e7
2 files changed
+176
-3
No files matched your search
@@ -66,6 +66,7 @@ import { uploadCreateFlowFile } from "../../../../lib/create/uploadToServer";
|
||||
import CustomMethodCardWizard from "./CustomMethodCardWizard";
|
||||
import {
|
||||
duplicateCoreValueChipInDraft,
|
||||
MAX_SELECTED_CORE_VALUES,
|
||||
removeCoreValueChipFromDraft,
|
||||
} from "../../../../lib/create/coreValueChipFacet";
|
||||
import {
|
||||
@@ -650,7 +651,7 @@ export function FinalReviewChipEditModal({
|
||||
if ((state.editingPublishedRuleId?.trim() ?? "") !== "") {
|
||||
return;
|
||||
}
|
||||
if ((state.selectedCoreValueIds ?? []).length >= 5) {
|
||||
if ((state.selectedCoreValueIds ?? []).length >= MAX_SELECTED_CORE_VALUES) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
@@ -725,7 +726,7 @@ export function FinalReviewChipEditModal({
|
||||
onCustomize: handleCustomize,
|
||||
onDuplicate:
|
||||
(state.editingPublishedRuleId?.trim() ?? "") !== "" ||
|
||||
(state.selectedCoreValueIds ?? []).length >= 5
|
||||
(state.selectedCoreValueIds ?? []).length >= MAX_SELECTED_CORE_VALUES
|
||||
? undefined
|
||||
: handleDuplicateCoreValue,
|
||||
});
|
||||
@@ -775,8 +776,12 @@ export function FinalReviewChipEditModal({
|
||||
return;
|
||||
}
|
||||
onInteract?.();
|
||||
const existingBlocks =
|
||||
const persistedBlocks =
|
||||
state.customMethodCardFieldBlocksById?.[target.overrideKey];
|
||||
const existingBlocks =
|
||||
draftFieldBlocks && draftFieldBlocks.length > 0
|
||||
? draftFieldBlocks
|
||||
: persistedBlocks;
|
||||
onSave({
|
||||
groupKey: "coreValues",
|
||||
overrideKey: target.overrideKey,
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user