import { renderWithProviders as render, screen, cleanup, within, } from "../utils/test-utils"; import userEvent from "@testing-library/user-event"; import { describe, test, expect, afterEach } from "vitest"; import { useLayoutEffect } from "react"; import { DecisionApproachesScreen } from "../../app/(app)/create/screens/right-rail/DecisionApproachesScreen"; import { useCreateFlow } from "../../app/(app)/create/context/CreateFlowContext"; const CUSTOM_APPROACH_ID = "550e8400-e29b-41d4-a716-446655440000"; function DecisionApproachesScreenWithState({ initial }) { const { replaceState } = useCreateFlow(); useLayoutEffect(() => { replaceState(initial); }, [replaceState, initial]); return ; } afterEach(() => { cleanup(); }); describe("Create flow decision-approaches page", () => { test("renders without error", () => { render(); expect( screen.getByRole("heading", { name: "How should this community make difficult decisions?", }), ).toBeInTheDocument(); }); test("renders sidebar description with add link", () => { render(); const addControl = screen.getByRole("button", { name: /^Add$/i, }); expect(addControl).toBeInTheDocument(); const description = addControl.parentElement; expect(description).not.toBeNull(); expect(description?.textContent).toMatch(/Select as many as you need/); expect(description?.textContent).toMatch(/new decision making approaches/); }); test("with a finalized custom approach, sidebar still shows add (not Remove policy)", () => { render( , ); expect( screen.queryByRole("button", { name: "Remove policy" }), ).not.toBeInTheDocument(); const addControl = screen.getByRole("button", { name: /^Add$/i }); expect(addControl).toBeInTheDocument(); const description = addControl.parentElement; expect(description?.textContent).toMatch(/Select as many as you need/); expect(description?.textContent).toMatch(/new decision making approaches/); }); test("renders message box with title and checkboxes", () => { render(); const region = screen.getByRole("region", { name: "Consider defining approaches to steward key resources:", }); expect(region).toBeInTheDocument(); expect( within(region).getByRole("checkbox", { name: "Amend your CommunityRule", }), ).toBeInTheDocument(); expect( within(region).getByRole("checkbox", { name: "Steward finances" }), ).toBeInTheDocument(); expect( within(region).getByRole("checkbox", { name: "Project level decisions" }), ).toBeInTheDocument(); expect( within(region).getByRole("checkbox", { name: "Discipline and member termination", }), ).toBeInTheDocument(); }); test("renders card stack with See all decision approaches toggle", () => { render(); expect( screen.getByRole("button", { name: "See all decision approaches" }), ).toBeInTheDocument(); }); test("renders recommended approach cards", () => { render(); expect( screen.getByRole("button", { name: /Lazy Consensus: A decision is assumed approved/, }), ).toBeInTheDocument(); expect( screen.getByRole("button", { name: /Do-ocracy: Decisions are made by those who take initiative/, }), ).toBeInTheDocument(); expect( screen.getByRole("button", { name: /Consensus Decision-Making: All members must agree/, }), ).toBeInTheDocument(); }); test("toggle expands and shows Show less", async () => { const user = userEvent.setup(); render(); const toggle = screen.getByRole("button", { name: "See all decision approaches", }); await user.click(toggle); expect( screen.getByRole("button", { name: "Show less" }), ).toBeInTheDocument(); expect(screen.getAllByRole("button", { name: /^add$/i })).toHaveLength(2); }); test("expanded view reveals additional non-recommended approaches", async () => { const user = userEvent.setup(); render(); expect( screen.queryByRole("button", { name: /^Sociocracy:/ }), ).not.toBeInTheDocument(); const toggle = screen.getByRole("button", { name: "See all decision approaches", }); await user.click(toggle); expect( screen.getByRole("button", { name: /^Sociocracy:/ }), ).toBeInTheDocument(); }); test("clicking a card opens the create modal and confirming selects it", async () => { const user = userEvent.setup(); render(); const card = screen.getByRole("button", { name: /Lazy Consensus: A decision is assumed approved/, }); await user.click(card); const dialog = await screen.findByRole("dialog"); expect(dialog).toBeInTheDocument(); const confirmButton = within(dialog).getByRole("button", { name: "Add Approach", }); await user.click(confirmButton); expect(screen.getByText("SELECTED")).toBeInTheDocument(); }); test("re-opening a selected approach shows Remove as the modal primary action", async () => { const user = userEvent.setup(); render(); const card = screen.getByRole("button", { name: /Lazy Consensus: A decision is assumed approved/, }); await user.click(card); const dialog = await screen.findByRole("dialog"); await user.click( within(dialog).getByRole("button", { name: "Add Approach", }), ); await user.click(card); const dialogAgain = screen.getByRole("dialog"); expect( within(dialogAgain).getByRole("button", { name: "Remove" }), ).toBeInTheDocument(); }); test("Remove in the modal deselects the approach", async () => { const user = userEvent.setup(); render(); const card = screen.getByRole("button", { name: /Lazy Consensus: A decision is assumed approved/, }); await user.click(card); await user.click( within(await screen.findByRole("dialog")).getByRole("button", { name: "Add Approach", }), ); expect(card).toHaveTextContent("SELECTED"); await user.click(card); await user.click( within(screen.getByRole("dialog")).getByRole("button", { name: "Remove" }), ); expect(card).not.toHaveTextContent("SELECTED"); }); test("message box checkboxes are interactive", async () => { const user = userEvent.setup(); render(); const amendCheckbox = screen.getByRole("checkbox", { name: "Amend your CommunityRule", }); expect(amendCheckbox).not.toBeChecked(); await user.click(amendCheckbox); expect(amendCheckbox).toBeChecked(); }); });