120 lines
3.7 KiB
React
120 lines
3.7 KiB
React
import {
|
|
renderWithProviders as render,
|
|
screen,
|
|
cleanup,
|
|
waitFor,
|
|
} from "../utils/test-utils";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { describe, test, expect, afterEach, beforeEach, vi } from "vitest";
|
|
import { useSearchParams } from "next/navigation";
|
|
import TemplatesPageClient from "../../app/(marketing)/templates/TemplatesPageClient";
|
|
import { testRouter } from "../mocks/navigation";
|
|
import { GOVERNANCE_TEMPLATE_CATALOG } from "../../lib/templates/governanceTemplateCatalog";
|
|
import { CREATE_FLOW_ANONYMOUS_KEY } from "../../app/(app)/create/utils/anonymousDraftStorage";
|
|
import { CORE_VALUE_DETAILS_STORAGE_KEY } from "../../app/(app)/create/utils/coreValueDetailsLocalStorage";
|
|
|
|
/** Seed localStorage as if a stale anonymous draft were already in place. */
|
|
function seedStaleDraft() {
|
|
window.localStorage.setItem(
|
|
CREATE_FLOW_ANONYMOUS_KEY,
|
|
JSON.stringify({ title: "Stale Community" }),
|
|
);
|
|
window.localStorage.setItem(
|
|
CORE_VALUE_DETAILS_STORAGE_KEY,
|
|
JSON.stringify({ "1": { meaning: "stale", signals: "stale" } }),
|
|
);
|
|
}
|
|
|
|
beforeEach(() => {
|
|
testRouter.push.mockClear();
|
|
vi.mocked(useSearchParams).mockReturnValue(new URLSearchParams());
|
|
window.localStorage.clear();
|
|
});
|
|
|
|
afterEach(() => {
|
|
cleanup();
|
|
window.localStorage.clear();
|
|
});
|
|
|
|
describe("Templates page (/templates)", () => {
|
|
test("renders title, intro, and full catalog", () => {
|
|
render(
|
|
<TemplatesPageClient initialGridEntries={GOVERNANCE_TEMPLATE_CATALOG} />,
|
|
);
|
|
|
|
expect(
|
|
screen.getByRole("heading", { name: "Templates", level: 1 }),
|
|
).toBeInTheDocument();
|
|
expect(
|
|
screen.getByText(/mutual aid and open source communities/i),
|
|
).toBeInTheDocument();
|
|
|
|
for (const entry of GOVERNANCE_TEMPLATE_CATALOG) {
|
|
expect(screen.getByText(entry.title)).toBeInTheDocument();
|
|
}
|
|
});
|
|
|
|
test("each template card is a link to review flow for its slug", () => {
|
|
render(
|
|
<TemplatesPageClient initialGridEntries={GOVERNANCE_TEMPLATE_CATALOG} />,
|
|
);
|
|
|
|
for (const entry of GOVERNANCE_TEMPLATE_CATALOG) {
|
|
expect(
|
|
screen.getByRole("link", {
|
|
name: `Learn more about ${entry.title} governance pattern`,
|
|
}),
|
|
).toHaveAttribute("href", `/create/review-template/${entry.slug}`);
|
|
}
|
|
});
|
|
|
|
test("direct entry (no ?fromFlow=1): wipes anonymous draft before navigating", async () => {
|
|
seedStaleDraft();
|
|
const user = userEvent.setup();
|
|
render(
|
|
<TemplatesPageClient initialGridEntries={GOVERNANCE_TEMPLATE_CATALOG} />,
|
|
);
|
|
|
|
await user.click(
|
|
screen.getByRole("link", { name: /Consensus/i }),
|
|
);
|
|
|
|
await waitFor(() => {
|
|
expect(window.localStorage.getItem(CREATE_FLOW_ANONYMOUS_KEY)).toBeNull();
|
|
expect(
|
|
window.localStorage.getItem(CORE_VALUE_DETAILS_STORAGE_KEY),
|
|
).toBeNull();
|
|
});
|
|
});
|
|
|
|
test("in-flow entry (?fromFlow=1): preserves the anonymous draft", async () => {
|
|
vi.mocked(useSearchParams).mockReturnValue(
|
|
new URLSearchParams("fromFlow=1"),
|
|
);
|
|
seedStaleDraft();
|
|
const user = userEvent.setup();
|
|
render(
|
|
<TemplatesPageClient initialGridEntries={GOVERNANCE_TEMPLATE_CATALOG} />,
|
|
);
|
|
|
|
await user.click(
|
|
screen.getByRole("link", { name: /Consensus/i }),
|
|
);
|
|
|
|
expect(window.localStorage.getItem(CREATE_FLOW_ANONYMOUS_KEY)).toBe(
|
|
JSON.stringify({ title: "Stale Community" }),
|
|
);
|
|
expect(
|
|
window.localStorage.getItem(CORE_VALUE_DETAILS_STORAGE_KEY),
|
|
).toBe(
|
|
JSON.stringify({ "1": { meaning: "stale", signals: "stale" } }),
|
|
);
|
|
expect(
|
|
screen.getByRole("link", { name: /Consensus/i }),
|
|
).toHaveAttribute(
|
|
"href",
|
|
"/create/review-template/consensus?fromFlow=1",
|
|
);
|
|
});
|
|
});
|