Route kebab Customize through the prefilled policy wizard so existing methods and values can be renamed, reordered, and kept in that field order on the card after Finalize.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
adilallo
2026-08-21 13:51:37 -06:00
co-authored by Cursor
parent e9951f260b
commit 4006fe5c6c
31 changed files with 3062 additions and 1530 deletions
@@ -13,6 +13,12 @@ describe("CoreValuesSelectScreen", () => {
fireEvent.click(await screen.findByRole("button", { name: "Discard" }));
}
async function editMeaningInOpenDialog(next: string) {
const dialog = await screen.findByRole("dialog");
const fields = within(dialog).getAllByRole("textbox");
fireEvent.change(fields[0], { target: { value: next } });
}
it("opens core value detail modal when a preset chip is clicked", async () => {
renderWithProviders(<CoreValuesSelectScreen />);
fireEvent.click(screen.getByText("Accessibility"));
@@ -20,20 +26,36 @@ describe("CoreValuesSelectScreen", () => {
expect(
within(dialog).getByRole("button", { name: "Add Value" }),
).toBeInTheDocument();
expect(
screen.queryByRole("menuitem", { name: "Customize" }),
).not.toBeInTheDocument();
fireEvent.click(within(dialog).getByRole("button", { name: "More options" }));
expect(
screen.queryByRole("menuitem", { name: "Customize" }),
screen.getByRole("menuitem", { name: "Customize" }),
).toBeInTheDocument();
expect(
screen.getByRole("menuitem", { name: "Duplicate" }),
).toBeInTheDocument();
expect(
screen.queryByRole("menuitem", { name: "Remove" }),
).not.toBeInTheDocument();
});
it("asks to discard when closing a pending value, then unselects on Discard", async () => {
it("closes a pending value without confirm when fields are unchanged", async () => {
renderWithProviders(<CoreValuesSelectScreen />);
fireEvent.click(screen.getByText("Accessibility"));
await screen.findByRole("dialog");
fireEvent.keyDown(document, { key: "Escape" });
await waitFor(() => {
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
});
expect(
screen.queryByRole("button", { name: "Keep editing" }),
).not.toBeInTheDocument();
});
it("asks to discard when closing a pending value after an edit", async () => {
renderWithProviders(<CoreValuesSelectScreen />);
fireEvent.click(screen.getByText("Accessibility"));
await editMeaningInOpenDialog("Changed meaning");
fireEvent.keyDown(document, { key: "Escape" });
expect(
await screen.findByRole("button", { name: "Keep editing" }),
).toBeInTheDocument();
@@ -46,7 +68,7 @@ describe("CoreValuesSelectScreen", () => {
it("keeps the pending value modal open when Keep editing is chosen", async () => {
renderWithProviders(<CoreValuesSelectScreen />);
fireEvent.click(screen.getByText("Accessibility"));
await screen.findByRole("dialog");
await editMeaningInOpenDialog("Changed meaning");
fireEvent.keyDown(document, { key: "Escape" });
fireEvent.click(await screen.findByRole("button", { name: "Keep editing" }));
const dialog = await screen.findByRole("dialog");
@@ -78,6 +100,162 @@ describe("CoreValuesSelectScreen", () => {
}
});
it("shows Remove only after the value has been added", async () => {
renderWithProviders(<CoreValuesSelectScreen />);
fireEvent.click(screen.getByText("Accessibility"));
const pending = await screen.findByRole("dialog");
fireEvent.click(within(pending).getByRole("button", { name: "Add Value" }));
await waitFor(() => {
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
});
fireEvent.click(screen.getByText("Accessibility"));
const editing = await screen.findByRole("dialog");
fireEvent.click(
within(editing).getByRole("button", { name: "More options" }),
);
expect(screen.getByRole("menuitem", { name: "Remove" })).toBeInTheDocument();
expect(
screen.getByRole("menuitem", { name: "Customize" }),
).toBeInTheDocument();
expect(
screen.getByRole("menuitem", { name: "Duplicate" }),
).toBeInTheDocument();
});
it("Customize walks name and description before policy details", async () => {
renderWithProviders(<CoreValuesSelectScreen />);
fireEvent.click(screen.getByText("Accessibility"));
const dialog = await screen.findByRole("dialog");
fireEvent.click(
within(dialog).getByRole("button", { name: "More options" }),
);
fireEvent.click(screen.getByRole("menuitem", { name: "Customize" }));
expect(await screen.findByPlaceholderText("Policy name")).toHaveValue(
"Accessibility",
);
expect(screen.queryByText("Custom policy details")).not.toBeInTheDocument();
fireEvent.click(screen.getByRole("button", { name: "Next" }));
fireEvent.click(screen.getByRole("button", { name: "Next" }));
expect(
await screen.findByText("Custom policy details"),
).toBeInTheDocument();
expect(
screen.getByRole("button", {
name: "What does this value mean to your group?",
}),
).toBeInTheDocument();
});
it("Customize shows meaning saved from the value modal", async () => {
renderWithProviders(<CoreValuesSelectScreen />);
fireEvent.click(screen.getByText("Accessibility"));
const pending = await screen.findByRole("dialog");
const fields = within(pending).getAllByRole("textbox");
fireEvent.change(fields[0], {
target: { value: "Edited meaning from value modal" },
});
fireEvent.click(within(pending).getByRole("button", { name: "Add Value" }));
await waitFor(() => {
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
});
fireEvent.click(screen.getByText("Accessibility"));
const editing = await screen.findByRole("dialog");
fireEvent.click(
within(editing).getByRole("button", { name: "More options" }),
);
fireEvent.click(screen.getByRole("menuitem", { name: "Customize" }));
expect(await screen.findByPlaceholderText("Policy name")).toBeInTheDocument();
fireEvent.click(screen.getByRole("button", { name: "Next" }));
fireEvent.click(screen.getByRole("button", { name: "Next" }));
fireEvent.click(
await screen.findByRole("button", {
name: "What does this value mean to your group?",
}),
);
expect(
screen.getByDisplayValue("Edited meaning from value modal"),
).toBeInTheDocument();
});
it("closing Customize without Finalize returns to the value modal", async () => {
renderWithProviders(<CoreValuesSelectScreen />);
fireEvent.click(screen.getByText("Accessibility"));
const dialog = await screen.findByRole("dialog");
fireEvent.click(
within(dialog).getByRole("button", { name: "More options" }),
);
fireEvent.click(screen.getByRole("menuitem", { name: "Customize" }));
expect(
await screen.findByPlaceholderText("Policy name"),
).toBeInTheDocument();
fireEvent.keyDown(document, { key: "Escape" });
await waitFor(() => {
expect(
screen.queryByPlaceholderText("Policy name"),
).not.toBeInTheDocument();
});
const valueDialog = screen.getByRole("dialog");
expect(
within(valueDialog).getByRole("button", { name: "Add Value" }),
).toBeInTheDocument();
});
it("Customize Finalize shows reordered fields in the value modal", async () => {
renderWithProviders(<CoreValuesSelectScreen />);
fireEvent.click(screen.getByText("Accessibility"));
const dialog = await screen.findByRole("dialog");
fireEvent.click(
within(dialog).getByRole("button", { name: "More options" }),
);
fireEvent.click(screen.getByRole("menuitem", { name: "Customize" }));
fireEvent.click(await screen.findByRole("button", { name: "Next" }));
fireEvent.click(screen.getByRole("button", { name: "Next" }));
expect(
await screen.findByText("Custom policy details"),
).toBeInTheDocument();
const handles = screen.getAllByRole("button", {
name: "Drag to reorder this field",
});
const rows = screen.getAllByRole("listitem");
const store: Record<string, string> = {};
const dataTransfer = {
effectAllowed: "all",
dropEffect: "move",
setData(type: string, value: string) {
store[type] = value;
},
getData(type: string) {
return store[type] ?? "";
},
};
fireEvent.pointerDown(handles[0]);
fireEvent.dragStart(rows[0], { dataTransfer });
fireEvent.drop(rows[1], { dataTransfer });
fireEvent.click(screen.getByRole("button", { name: "Finalize" }));
await waitFor(() => {
expect(
screen.queryByPlaceholderText("Policy name"),
).not.toBeInTheDocument();
});
const result = screen.getByRole("dialog");
const labels = within(result)
.getAllByRole("textbox")
.map((el) => {
const labelledby = el.getAttribute("aria-labelledby");
return labelledby
? (document.getElementById(labelledby)?.textContent ?? "").trim()
: "";
});
expect(labels[0]).toMatch(/Signals of Violation/);
expect(labels[1]).toMatch(/What does this value mean to your group/);
});
// The "Add value" → custom-chip → modal flow uses a `customPending`
// session: dismissing the modal must drop the brand-new chip entirely
// (not just unselect it), because the user never confirmed it via
@@ -118,7 +296,6 @@ describe("CoreValuesSelectScreen", () => {
expect(countCustomChips(CUSTOM_LABEL)).toBe(1);
fireEvent.keyDown(document, { key: "Escape" });
fireEvent.click(await screen.findByRole("button", { name: "Discard" }));
await waitFor(() => {
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
});