Import the remade decks on stable ids and recommend one card per job, so a saved draft still loads after a chip is renamed.

The real-group profiles stay as a test, so a change that moves a pick fails.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
adilalloandCursor committed 2026-11-04 14:22:54 -07:00
1 parent 96ca15d8e3
commit bcbc6f30d9
89 files changed
+36555 -2828

No files matched your search

@@ -35,7 +35,7 @@ async function declineDiscardCustomizeEdits() {
/**
* Mounts the screen with optional starting state and exposes the latest
* `state` to the test harness so we can assert the persistence side of
* the Add Platform flow without driving the wizard's Next chain.
* the Add card flow without driving the wizard's Next chain.
*/
const EMPTY_STATE: CreateFlowState = {};
@@ -62,7 +62,7 @@ function ScreenWithStateProbe({
* snapping back to preset copy. See {@link CommunicationMethodEditFields}
* and `buildPublishPayload` for the read side.
*/
describe("CommunicationMethodsScreen — Add Platform persistence", () => {
describe("CommunicationMethodsScreen — Add card persistence", () => {
it("starts empty and Generate draft inserts the catalog preset", async () => {
let latest: CreateFlowState = {};
render(
@@ -74,7 +74,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const dialog = await screen.findByRole("dialog");
@@ -96,7 +96,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
fireEvent.change(corePrincipleField, { target: { value: "Custom principle" } });
fireEvent.click(
within(dialog).getByRole("button", {
name: "Add Platform",
name: "Add card",
}),
);
@@ -122,7 +122,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const dialog = await screen.findByRole("dialog");
void dialog;
@@ -157,7 +157,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
void latest;
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const dialog = await screen.findByRole("dialog");
const textareas = within(dialog).getAllByRole(
@@ -190,7 +190,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const dialog = await screen.findByRole("dialog");
const textareas = within(dialog).getAllByRole(
@@ -259,7 +259,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const dialog = await screen.findByRole("dialog");
const textareas = within(dialog).getAllByRole(
@@ -283,7 +283,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const dialog = await screen.findByRole("dialog");
fireEvent.click(within(dialog).getByRole("button", { name: "More options" }));
@@ -312,7 +312,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const dialog = await screen.findByRole("dialog");
fireEvent.click(within(dialog).getByRole("button", { name: "More options" }));
@@ -344,7 +344,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const dialog = await screen.findByRole("dialog");
const textboxes = within(dialog).getAllByRole(
@@ -387,7 +387,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const dialog = await screen.findByRole("dialog");
const textboxes = within(dialog).getAllByRole(
@@ -448,7 +448,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
await screen.findByText("Custom policy details"),
).toBeInTheDocument();
expect(
screen.getByRole("button", { name: "Core Principle & Scope" }),
screen.getByRole("button", { name: "Core principle and scope" }),
).toBeInTheDocument();
fireEvent.click(screen.getByRole("button", { name: "Finalize policy" }));
@@ -470,7 +470,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const dialog = await screen.findByRole("dialog");
for (const button of within(dialog).getAllByRole("button", {
@@ -490,11 +490,11 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
await screen.findByText("Custom policy details"),
).toBeInTheDocument();
fireEvent.click(
screen.getByRole("button", { name: "Core Principle & Scope" }),
screen.getByRole("button", { name: "Core principle and scope" }),
);
expect(await screen.findByText("Add text block")).toBeInTheDocument();
expect(
screen.getByDisplayValue(/We prioritize privacy and security/i),
screen.getByDisplayValue(/Signal encrypts every message/i),
).toBeInTheDocument();
fireEvent.click(screen.getByRole("button", { name: "Back" }));
fireEvent.click(screen.getByRole("button", { name: "Back" }));
@@ -526,7 +526,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const cardDialog = await screen.findByRole("dialog");
fireEvent.click(
@@ -585,9 +585,9 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
? (document.getElementById(labelledby)?.textContent ?? "").trim()
: "";
});
expect(labels[0]).toMatch(/Logistics, Admin/);
expect(labels[1]).toMatch(/Code of Conduct/);
expect(labels[2]).toMatch(/Core Principle/);
expect(labels[0]).toMatch(/How it works/);
expect(labels[1]).toMatch(/Norms/);
expect(labels[2]).toMatch(/Core principle/);
});
it("does not block tab close when the create modal is unchanged", async () => {
@@ -600,7 +600,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
await screen.findByRole("dialog");
expect(dispatchBeforeUnload()).toBe(false);
@@ -616,7 +616,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const dialog = await screen.findByRole("dialog");
const textboxes = within(dialog).getAllByRole(
@@ -636,7 +636,7 @@ describe("CommunicationMethodsScreen — Add Platform persistence", () => {
);
fireEvent.click(
screen.getAllByRole("button", { name: /Signal: Encrypted messaging/ })[0],
screen.getAllByRole("button", { name: /Signal: We coordinate in encrypted Signal groups/ })[0],
);
const dialog = await screen.findByRole("dialog");
fireEvent.click(within(dialog).getByRole("button", { name: "More options" }));
@@ -21,7 +21,7 @@ describe("CommunityStructureSelectScreen", () => {
renderWithProviders(<CommunityStructureSelectScreen />);
expect(
screen.getByRole("button", { name: "Select Worker cooperative" }),
screen.getByRole("button", { name: "Select Worker co-op" }),
).toBeInTheDocument();
expect(
screen.getByRole("button", { name: "Select Local" }),
@@ -18,7 +18,7 @@ describe("ConflictManagementScreen", () => {
render(<ConflictManagementScreen />);
fireEvent.click(
screen.getAllByRole("button", {
name: /Peer Mediation: Trained members/,
name: /Conflict ladder: We talk one-on-one/,
})[0],
);
const dialog = await screen.findByRole("dialog");
@@ -58,7 +58,7 @@ describe("CoreValuesSelectScreen", () => {
fireEvent.click(
within(dialog).getAllByRole("button", { name: "Generate draft" })[0],
);
expect(fields[0].value).toMatch(/everyone can use/i);
expect(fields[0].value).toMatch(/usable by everyone/i);
});
it("closes a pending value without confirm when fields are unchanged", async () => {
@@ -408,7 +408,7 @@ describe("CoreValuesSelectScreen", () => {
});
});
describe("five-value limit", () => {
describe("six-value limit", () => {
async function addPresetValue(label: string) {
fireEvent.click(screen.getByText(label));
const dialog = await screen.findByRole("dialog");
@@ -420,22 +420,23 @@ describe("CoreValuesSelectScreen", () => {
it("shows a counter, disables remaining chips, and announces the limit", async () => {
renderWithProviders(<CoreValuesSelectScreen />);
expect(screen.getByText("0 of 5")).toBeInTheDocument();
expect(screen.getByText("0 of 6")).toBeInTheDocument();
await addPresetValue("Accessibility");
await addPresetValue("Accountability");
await addPresetValue("Adaptability");
await addPresetValue("Agency");
await addPresetValue("Altruism");
await addPresetValue("Anti-oppression");
await addPresetValue("Autonomy");
expect(screen.getByText("5 of 5")).toBeInTheDocument();
expect(screen.getByText("6 of 6")).toBeInTheDocument();
expect(
screen.getByText(
"Five of five values selected. Remaining values are unavailable until one is removed.",
"Six of six values selected. Remaining values are unavailable until one is removed.",
),
).toBeInTheDocument();
expect(
screen.getByRole("button", { name: "Select Anti-oppression" }),
screen.getByRole("button", { name: "Select Capacity building" }),
).toBeDisabled();
expect(screen.getByRole("button", { name: "Add value" })).toBeDisabled();
expect(screen.getByRole("button", { name: /^add$/i })).toBeDisabled();
+35 -12
View File
@@ -205,9 +205,9 @@ function FinalReviewWithCustomizeSelections() {
{ id: "2", label: "Accountability", state: "unselected" },
],
selectedCommunicationMethodIds: ["signal"],
selectedMembershipMethodIds: ["open-access"],
selectedMembershipMethodIds: ["open-admission"],
selectedDecisionApproachIds: ["lazy-consensus"],
selectedConflictManagementIds: ["peer-mediation"],
selectedConflictManagementIds: ["conflict-ladder"],
});
}, [replaceState]);
return <FinalReviewScreen />;
@@ -220,16 +220,39 @@ describe("FinalReviewScreen — prefilled selections", () => {
expect(screen.getByText("Accessibility")).toBeInTheDocument();
});
expect(screen.getByText("Signal")).toBeInTheDocument();
expect(screen.getByText("Open Access")).toBeInTheDocument();
expect(screen.getByText("Lazy Consensus")).toBeInTheDocument();
expect(screen.getByText("Peer Mediation")).toBeInTheDocument();
expect(screen.getByText("Open admission")).toBeInTheDocument();
expect(screen.getByText("Lazy consensus")).toBeInTheDocument();
expect(screen.getByText("Conflict ladder")).toBeInTheDocument();
// Demo chips from `finalReview.json` must not leak through once the
// user has real selections: "Open Admission" is shipped as fallback,
// while the customize flow resolves to "Open Access".
// user has real selections. The fallback still says "Open Admission".
expect(screen.queryByText("Open Admission")).not.toBeInTheDocument();
expect(screen.queryByText("Consciousness")).not.toBeInTheDocument();
});
it("warns when binding arbitration sits next to a join that records no yes", async () => {
function ReviewWithOpenJoinAndArbitration() {
const { replaceState } = useCreateFlow();
useLayoutEffect(() => {
replaceState({
title: "Oak Park Commons",
selectedMembershipMethodIds: ["open-admission"],
selectedConflictManagementIds: ["binding-arbitration"],
});
}, [replaceState]);
return <FinalReviewScreen />;
}
render(<ReviewWithOpenJoinAndArbitration />);
expect(
await screen.findByText(/Binding arbitration needs each member.s own yes/),
).toBeInTheDocument();
expect(
screen.getByText(
/Each member still has to agree separately before binding arbitration applies/,
),
).toBeInTheDocument();
});
});
describe("FinalReviewScreen — chip detail modal", () => {
@@ -245,7 +268,7 @@ describe("FinalReviewScreen — chip detail modal", () => {
await waitFor(() => {
expect(
screen.getByText(
/Encrypted messaging for high-security, private coordination\./i,
/encrypted Signal groups/i,
),
).toBeInTheDocument();
});
@@ -277,7 +300,7 @@ describe("FinalReviewScreen — chip detail modal", () => {
);
fireEvent.click(
await screen.findByRole("button", { name: catalogChipName("Video Meetings") }),
await screen.findByRole("button", { name: catalogChipName("Video meetings") }),
);
const dialog = await screen.findByRole("dialog");
expect(within(dialog).getAllByRole("textbox")).toHaveLength(3);
@@ -1021,9 +1044,9 @@ describe("FinalReviewScreen — chip edit modal save semantics", () => {
? (document.getElementById(labelledby)?.textContent ?? "").trim()
: "";
});
expect(labels[0]).toMatch(/Logistics, Admin/);
expect(labels[1]).toMatch(/Code of Conduct/);
expect(labels[2]).toMatch(/Core Principle/);
expect(labels[0]).toMatch(/How it works/);
expect(labels[1]).toMatch(/Norms/);
expect(labels[2]).toMatch(/Core principle/);
});
});
@@ -18,7 +18,7 @@ describe("MembershipMethodsScreen", () => {
render(<MembershipMethodsScreen />);
fireEvent.click(
screen.getAllByRole("button", {
name: /Open Access: Maximum inclusion/,
name: /Open admission: Anyone who agrees/,
})[0],
);
const dialog = await screen.findByRole("dialog");