Cleanup, add tests and storybook

This commit is contained in:
adilallo
2026-04-04 10:57:01 -06:00
parent 5d6530e914
commit 427dc44476
26 changed files with 700 additions and 7 deletions
-1
View File
@@ -1,4 +1,3 @@
import React from "react";
import { describe, it, expect } from "vitest";
import { renderWithProviders as render, screen } from "../utils/test-utils";
import "@testing-library/jest-dom/vitest";
@@ -0,0 +1,40 @@
import { describe, it, expect } from "vitest";
import userEvent from "@testing-library/user-event";
import { renderWithProviders as render, screen } from "../utils/test-utils";
import "@testing-library/jest-dom/vitest";
import ConfirmStakeholdersPage from "../../app/create/confirm-stakeholders/page";
describe("ConfirmStakeholdersPage", () => {
it("renders title and description", () => {
render(<ConfirmStakeholdersPage />);
expect(
screen.getByRole("heading", {
name: /Do other stakeholders need to be involved/i,
}),
).toBeInTheDocument();
expect(
screen.getByText(
/Adding people at this step will invite them to see your proposed CommunityRule/i,
),
).toBeInTheDocument();
});
it("renders Add stakeholder control", () => {
render(<ConfirmStakeholdersPage />);
expect(
screen.getByRole("button", { name: "Add stakeholder" }),
).toBeInTheDocument();
});
it("shows draft toast and can dismiss it", async () => {
const user = userEvent.setup();
render(<ConfirmStakeholdersPage />);
expect(
screen.getByText(/Congratulations! You've drafted your CommunityRule!/i),
).toBeInTheDocument();
await user.click(screen.getByRole("button", { name: "Close alert" }));
expect(
screen.queryByText(/Congratulations! You've drafted your CommunityRule!/i),
).not.toBeInTheDocument();
});
});
+4
View File
@@ -37,6 +37,10 @@ const mockPost: BlogPost = {
author: "Test Author",
date: "2025-04-15",
},
content: "",
htmlContent: "",
filePath: "test-article.md",
lastModified: new Date("2025-04-15"),
};
describe("ContentBanner", () => {
@@ -0,0 +1,38 @@
import { describe, it, expect } from "vitest";
import { renderWithProviders as render, screen } from "../utils/test-utils";
import "@testing-library/jest-dom/vitest";
import DecisionMakingSidebar from "../../app/components/utility/DecisionMakingSidebar";
describe("DecisionMakingSidebar", () => {
const messageBoxItems = [{ id: "1", label: "Consensus" }];
it("renders title and description", () => {
render(
<DecisionMakingSidebar
title="How are decisions made?"
description="Pick approaches for your group."
messageBoxTitle="Select methods"
messageBoxItems={messageBoxItems}
/>,
);
expect(
screen.getByRole("heading", { name: "How are decisions made?" }),
).toBeInTheDocument();
expect(
screen.getByText("Pick approaches for your group."),
).toBeInTheDocument();
});
it("renders InfoMessageBox section", () => {
render(
<DecisionMakingSidebar
title="Decisions"
description="Desc"
messageBoxTitle="Select methods"
messageBoxItems={messageBoxItems}
/>,
);
expect(screen.getByText("Select methods")).toBeInTheDocument();
expect(screen.getByText("Consensus")).toBeInTheDocument();
});
});
@@ -1,4 +1,3 @@
import React from "react";
import { describe, it, expect } from "vitest";
import { renderWithProviders as render, screen } from "../utils/test-utils";
import "@testing-library/jest-dom/vitest";
+37
View File
@@ -0,0 +1,37 @@
import { describe, it, expect, vi } from "vitest";
import userEvent from "@testing-library/user-event";
import { renderWithProviders as render, screen } from "../utils/test-utils";
import "@testing-library/jest-dom/vitest";
import InfoMessageBox from "../../app/components/utility/InfoMessageBox";
describe("InfoMessageBox", () => {
const items = [
{ id: "a", label: "Option A" },
{ id: "b", label: "Option B" },
];
it("renders title and item labels", () => {
render(
<InfoMessageBox title="Important" items={items} />,
);
expect(screen.getByRole("region", { name: "Important" })).toBeInTheDocument();
expect(screen.getByText("Important")).toBeInTheDocument();
expect(screen.getByText("Option A")).toBeInTheDocument();
expect(screen.getByText("Option B")).toBeInTheDocument();
});
it("calls onCheckboxChange when toggling", async () => {
const u = userEvent.setup();
const onCheckboxChange = vi.fn();
render(
<InfoMessageBox
title="Pick one"
items={[{ id: "x", label: "Choice X" }]}
onCheckboxChange={onCheckboxChange}
/>,
);
const checkbox = screen.getByRole("checkbox", { name: /Choice X/i });
await u.click(checkbox);
expect(onCheckboxChange).toHaveBeenCalled();
});
});
@@ -0,0 +1,31 @@
import { describe, it, expect } from "vitest";
import { renderWithProviders as render, screen } from "../utils/test-utils";
import "@testing-library/jest-dom/vitest";
import InformationalPage from "../../app/create/informational/page";
describe("InformationalPage", () => {
it("renders without crashing", () => {
render(<InformationalPage />);
expect(
screen.getByRole("heading", {
name: "How CommunityRule helps groups like yours",
}),
).toBeInTheDocument();
});
it("renders lockup description", () => {
render(<InformationalPage />);
expect(
screen.getByText(
/This flow will give you recommendations to improve your community/i,
),
).toBeInTheDocument();
});
it("renders first numbered list item title", () => {
render(<InformationalPage />);
expect(
screen.getByText("Tell us about your organization"),
).toBeInTheDocument();
});
});
@@ -43,6 +43,10 @@ const mockPosts: BlogPost[] = [
author: "Author",
date: "2025-04-10",
},
content: "",
htmlContent: "",
filePath: "article-1.md",
lastModified: new Date("2025-04-10"),
},
{
slug: "article-2",
@@ -52,6 +56,10 @@ const mockPosts: BlogPost[] = [
author: "Author",
date: "2025-04-11",
},
content: "",
htmlContent: "",
filePath: "article-2.md",
lastModified: new Date("2025-04-11"),
},
];
-1
View File
@@ -1,4 +1,3 @@
import React from "react";
import { describe, it, expect } from "vitest";
import { renderWithProviders as render, screen } from "../utils/test-utils";
import "@testing-library/jest-dom/vitest";
+29
View File
@@ -0,0 +1,29 @@
import { describe, it, expect } from "vitest";
import { renderWithProviders as render, screen } from "../utils/test-utils";
import "@testing-library/jest-dom/vitest";
import SelectPage from "../../app/create/select/page";
describe("SelectPage", () => {
it("renders HeaderLockup title", () => {
render(<SelectPage />);
expect(
screen.getByRole("heading", {
name: "What is your community called?",
}),
).toBeInTheDocument();
});
it("renders MultiSelect add control", () => {
render(<SelectPage />);
const addButtons = screen.getAllByRole("button", {
name: "Add organization type",
});
expect(addButtons.length).toBeGreaterThanOrEqual(1);
});
it("renders preset chip labels", () => {
render(<SelectPage />);
expect(screen.getByText("1 member")).toBeInTheDocument();
expect(screen.getByText("Non-profit")).toBeInTheDocument();
});
});
+25
View File
@@ -0,0 +1,25 @@
import { describe, it, expect } from "vitest";
import { renderWithProviders as render, screen } from "../utils/test-utils";
import "@testing-library/jest-dom/vitest";
import TextPage from "../../app/create/text/page";
describe("TextPage", () => {
it("renders main heading", () => {
render(<TextPage />);
expect(
screen.getByRole("heading", {
name: "What is your community called?",
}),
).toBeInTheDocument();
});
it("renders description and text field", () => {
render(<TextPage />);
expect(
screen.getByText("This will be the name of your community"),
).toBeInTheDocument();
expect(
screen.getByPlaceholderText("Enter your community name"),
).toBeInTheDocument();
});
});
+23
View File
@@ -0,0 +1,23 @@
import { describe, it, expect } from "vitest";
import { renderWithProviders as render, screen } from "../utils/test-utils";
import "@testing-library/jest-dom/vitest";
import UploadPage from "../../app/create/upload/page";
describe("UploadPage", () => {
it("renders HeaderLockup", () => {
render(<UploadPage />);
expect(
screen.getByRole("heading", {
name: "How should conflicts be resolved?",
}),
).toBeInTheDocument();
});
it("renders Upload control and helper copy", () => {
render(<UploadPage />);
expect(screen.getByRole("button", { name: "Upload" })).toBeInTheDocument();
expect(
screen.getByText(/Add images, PDFs, and other files to the policy/i),
).toBeInTheDocument();
});
});
+49
View File
@@ -0,0 +1,49 @@
import { describe, it, expect } from "vitest";
import {
FLOW_STEP_ORDER,
getNextStep,
getPreviousStep,
isValidStep,
getStepIndex,
} from "../../app/create/utils/flowSteps";
describe("flowSteps", () => {
it("places confirm-stakeholders immediately before final-review", () => {
const i = FLOW_STEP_ORDER.indexOf("confirm-stakeholders");
const j = FLOW_STEP_ORDER.indexOf("final-review");
expect(i).toBeGreaterThanOrEqual(0);
expect(j).toBe(i + 1);
});
it("getNextStep returns next step in order", () => {
expect(getNextStep("right-rail")).toBe("confirm-stakeholders");
expect(getNextStep("confirm-stakeholders")).toBe("final-review");
});
it("getNextStep returns null for last step or invalid", () => {
expect(getNextStep("completed")).toBeNull();
expect(getNextStep(null)).toBeNull();
// @ts-expect-error — exercise invalid step id at runtime
expect(getNextStep("not-a-step")).toBeNull();
});
it("getPreviousStep returns prior step or null", () => {
expect(getPreviousStep("final-review")).toBe("confirm-stakeholders");
expect(getPreviousStep("informational")).toBeNull();
expect(getPreviousStep(null)).toBeNull();
});
it("isValidStep reflects FLOW_STEP_ORDER membership", () => {
expect(isValidStep("select")).toBe(true);
expect(isValidStep("confirm-stakeholders")).toBe(true);
expect(isValidStep("nope")).toBe(false);
expect(isValidStep(null)).toBe(false);
});
it("getStepIndex matches position in FLOW_STEP_ORDER", () => {
expect(getStepIndex("informational")).toBe(0);
expect(getStepIndex("completed")).toBe(FLOW_STEP_ORDER.length - 1);
// @ts-expect-error — invalid step id
expect(getStepIndex("bogus")).toBe(-1);
});
});