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:
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();
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in new issue
Block a user