172 lines
5.3 KiB
TypeScript
172 lines
5.3 KiB
TypeScript
import { useSearchParams } from "next/navigation";
|
||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||
import { renderWithProviders as render, screen } from "../utils/test-utils";
|
||
import "@testing-library/jest-dom/vitest";
|
||
import { CompletedScreen } from "../../app/(app)/create/screens/completed/CompletedScreen";
|
||
import { CREATE_FLOW_LAST_PUBLISHED_KEY } from "../../lib/create/lastPublishedRule";
|
||
import {
|
||
CREATE_FLOW_COMPLETED_CELEBRATE_QUERY,
|
||
CREATE_FLOW_COMPLETED_CELEBRATE_VALUE,
|
||
} from "../../app/(app)/create/utils/flowSteps";
|
||
|
||
const storedRuleFixture = {
|
||
id: "rule-fixture-1",
|
||
title: "Fixture Community Rule",
|
||
summary: "A short summary for tests.",
|
||
document: {
|
||
sections: [
|
||
{
|
||
categoryName: "Values",
|
||
entries: [
|
||
{
|
||
title: "Fixture value title",
|
||
body: "Fixture value body text for the test document.",
|
||
},
|
||
],
|
||
},
|
||
{
|
||
categoryName: "Communication",
|
||
entries: [
|
||
{
|
||
title: "Fixture channel",
|
||
body: "How we talk to each other.",
|
||
},
|
||
],
|
||
},
|
||
],
|
||
},
|
||
};
|
||
|
||
function mockSearchParams(record?: Record<string, string>) {
|
||
vi.mocked(useSearchParams).mockReturnValue(
|
||
new URLSearchParams(record ?? undefined) as NonNullable<
|
||
ReturnType<typeof useSearchParams>
|
||
>,
|
||
);
|
||
}
|
||
|
||
describe("CompletedScreen", () => {
|
||
beforeEach(() => {
|
||
sessionStorage.removeItem(CREATE_FLOW_LAST_PUBLISHED_KEY);
|
||
mockSearchParams();
|
||
});
|
||
|
||
afterEach(() => {
|
||
sessionStorage.removeItem(CREATE_FLOW_LAST_PUBLISHED_KEY);
|
||
});
|
||
|
||
it("renders without crashing", () => {
|
||
render(<CompletedScreen />);
|
||
expect(screen.getByRole("heading", { level: 1 })).toBeInTheDocument();
|
||
});
|
||
|
||
it("shows no placeholder title or document when session is empty", () => {
|
||
render(<CompletedScreen />);
|
||
const h1 = screen.getByRole("heading", { level: 1 });
|
||
expect(h1.textContent).toBe("");
|
||
expect(screen.queryByText("Values")).not.toBeInTheDocument();
|
||
});
|
||
|
||
it("keeps the heading in place while the Rule column scrolls", () => {
|
||
sessionStorage.setItem(
|
||
CREATE_FLOW_LAST_PUBLISHED_KEY,
|
||
JSON.stringify(storedRuleFixture),
|
||
);
|
||
render(<CompletedScreen />);
|
||
const heading = screen.getByRole("heading", {
|
||
name: "Fixture Community Rule",
|
||
});
|
||
const column = heading.closest("div[class*='md:justify-center']");
|
||
expect(column).toBeTruthy();
|
||
expect(column.className).toMatch(/\bshrink-0\b/);
|
||
const ruleColumn = screen
|
||
.getByText("Fixture value title")
|
||
.closest("div[class*='overflow-y-auto']");
|
||
expect(ruleColumn?.className).toMatch(/overflow-y-auto/);
|
||
});
|
||
|
||
it("offers Ask an organizer under the finished Rule heading", () => {
|
||
sessionStorage.setItem(
|
||
CREATE_FLOW_LAST_PUBLISHED_KEY,
|
||
JSON.stringify(storedRuleFixture),
|
||
);
|
||
render(<CompletedScreen />);
|
||
expect(
|
||
screen.getByText("Has your Rule changed how your community works?"),
|
||
).toBeInTheDocument();
|
||
expect(
|
||
screen.getByRole("button", { name: "Tell an organizer what changed." }),
|
||
).toBeInTheDocument();
|
||
});
|
||
|
||
it("renders header and document from sessionStorage", () => {
|
||
sessionStorage.setItem(
|
||
CREATE_FLOW_LAST_PUBLISHED_KEY,
|
||
JSON.stringify(storedRuleFixture),
|
||
);
|
||
render(<CompletedScreen />);
|
||
expect(
|
||
screen.getByRole("heading", {
|
||
name: "Fixture Community Rule",
|
||
}),
|
||
).toBeInTheDocument();
|
||
expect(screen.getByText("A short summary for tests.")).toBeInTheDocument();
|
||
expect(screen.getByText("Values")).toBeInTheDocument();
|
||
expect(screen.getByText("Communication")).toBeInTheDocument();
|
||
expect(screen.getByText("Fixture value title")).toBeInTheDocument();
|
||
});
|
||
|
||
it("does not show post-publish toast without celebrate query", () => {
|
||
render(<CompletedScreen />);
|
||
expect(
|
||
screen.queryByText(
|
||
"Your Rule is finished",
|
||
),
|
||
).not.toBeInTheDocument();
|
||
expect(
|
||
screen.queryByText(
|
||
"This is what the people you invite will see.",
|
||
),
|
||
).not.toBeInTheDocument();
|
||
});
|
||
|
||
it("shows copy-ready toast when copied query is set", () => {
|
||
sessionStorage.setItem(
|
||
CREATE_FLOW_LAST_PUBLISHED_KEY,
|
||
JSON.stringify({
|
||
...storedRuleFixture,
|
||
copiedFromTitle: "Juniper Street Food Share",
|
||
}),
|
||
);
|
||
mockSearchParams({ copied: "1" });
|
||
render(<CompletedScreen />);
|
||
expect(screen.getByText("Your copy is ready")).toBeInTheDocument();
|
||
expect(
|
||
screen.getByText(
|
||
"It started from Juniper Street Food Share’s Rule. Read it through and change what does not fit before you invite your members.",
|
||
),
|
||
).toBeInTheDocument();
|
||
});
|
||
|
||
it("shows post-publish toast in status region when celebrate query is set", () => {
|
||
mockSearchParams({
|
||
[CREATE_FLOW_COMPLETED_CELEBRATE_QUERY]:
|
||
CREATE_FLOW_COMPLETED_CELEBRATE_VALUE,
|
||
});
|
||
render(<CompletedScreen />);
|
||
expect(
|
||
screen.getByText("Your Rule is finished"),
|
||
).toBeInTheDocument();
|
||
expect(
|
||
screen.getByText("This is what the people you invite will see."),
|
||
).toBeInTheDocument();
|
||
const statusRegions = screen.getAllByRole("status");
|
||
expect(statusRegions.length).toBeGreaterThanOrEqual(1);
|
||
expect(
|
||
statusRegions.some((el) =>
|
||
el.textContent?.includes("Your Rule is finished"),
|
||
),
|
||
).toBe(true);
|
||
});
|
||
});
|