Implement about page
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import Stat from "../../../app/components/cards/Stat";
|
||||
|
||||
describe("Stat", () => {
|
||||
it("renders value and label", () => {
|
||||
render(
|
||||
<Stat
|
||||
value="420M+"
|
||||
label="open source projects"
|
||||
asOf="as of June 30, 2024"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText("420M+")).toBeInTheDocument();
|
||||
expect(screen.getByText("open source projects")).toBeInTheDocument();
|
||||
expect(screen.getByText("as of June 30, 2024")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import Accordion from "../../../app/components/layout/Accordion";
|
||||
|
||||
describe("Accordion", () => {
|
||||
it("toggles panel content", async () => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
render(
|
||||
<Accordion title="Question" defaultOpen={false}>
|
||||
Answer copy
|
||||
</Accordion>,
|
||||
);
|
||||
|
||||
expect(screen.queryByText("Answer copy")).not.toBeInTheDocument();
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Question" }));
|
||||
|
||||
expect(screen.getByText("Answer copy")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import Stats from "../../../app/components/sections/Stats";
|
||||
|
||||
describe("Stats", () => {
|
||||
it("renders heading and stat cards", () => {
|
||||
render(
|
||||
<Stats
|
||||
titlePrefix="From"
|
||||
titleEmphasis="projects"
|
||||
titleSuffix="to communities"
|
||||
items={[
|
||||
{
|
||||
value: "27%",
|
||||
label: "year over year growth",
|
||||
asOf: "as of June 30, 2024",
|
||||
shapeVariant: "purple",
|
||||
},
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByRole("heading", { name: /From projects to communities/i }),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText("27%")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import AboutHeader from "../../../app/components/type/AboutHeader";
|
||||
|
||||
describe("AboutHeader", () => {
|
||||
it("renders segmented headline", () => {
|
||||
render(
|
||||
<AboutHeader
|
||||
segments={[
|
||||
{ type: "word", text: "CommunityRule" },
|
||||
{ type: "word", text: "helps" },
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByRole("heading", { name: /CommunityRule helps/i }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import TripleTextBlock from "../../../app/components/type/TripleTextBlock";
|
||||
import {
|
||||
renderWithProviders as render,
|
||||
screen,
|
||||
} from "../../utils/test-utils";
|
||||
|
||||
describe("TripleTextBlock", () => {
|
||||
it("renders stacked and lg copy when lgTitle/lgDescription provided", () => {
|
||||
render(
|
||||
<TripleTextBlock
|
||||
columns={[
|
||||
{
|
||||
title: "Stacked headline",
|
||||
description: "Long stacked body.",
|
||||
lgTitle: "Wide headline",
|
||||
lgDescription: "Short wide body.",
|
||||
},
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByRole("heading", { name: "Stacked headline" }),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole("heading", { name: "Wide headline" }),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText("Long stacked body.")).toBeInTheDocument();
|
||||
expect(screen.getByText("Short wide body.")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders a single column variant when lg fields omitted", () => {
|
||||
render(
|
||||
<TripleTextBlock
|
||||
columns={[
|
||||
{
|
||||
title: "Only headline",
|
||||
description: "Only body.",
|
||||
},
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getAllByRole("heading", { name: "Only headline" })).toHaveLength(
|
||||
1,
|
||||
);
|
||||
expect(screen.getByText("Only body.")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -222,4 +222,41 @@ describe("QuoteBlock Component", () => {
|
||||
screen.queryByText("The Tyranny of Structurelessness"),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("statement variant renders dual paragraphs without attribution", () => {
|
||||
render(
|
||||
<QuoteBlock
|
||||
variant="statement"
|
||||
id="about-test-quote"
|
||||
quote="First paragraph of the statement."
|
||||
quoteSecondary="Second paragraph of the statement."
|
||||
/>,
|
||||
);
|
||||
|
||||
const region = screen.getByRole("region", {
|
||||
name: /first paragraph of the statement/i,
|
||||
});
|
||||
expect(region).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText("Second paragraph of the statement."),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.queryByRole("cite")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("statement variant logs when quoteSecondary is missing", () => {
|
||||
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
||||
|
||||
render(
|
||||
<QuoteBlock
|
||||
variant="statement"
|
||||
quote="Only one paragraph"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
"QuoteBlock: statement variant requires non-empty quote and quoteSecondary",
|
||||
);
|
||||
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,11 +9,16 @@ vi.mock("../../lib/server/mail", () => ({
|
||||
}));
|
||||
|
||||
const rateLimitKeyMock = vi.hoisted(() =>
|
||||
vi.fn(() => ({ ok: true as const })),
|
||||
vi.fn(
|
||||
(_key: string, _minIntervalMs: number): { ok: true } | { ok: false; retryAfterMs: number } => ({
|
||||
ok: true,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
vi.mock("../../lib/server/rateLimit", () => ({
|
||||
rateLimitKey: (...args: unknown[]) => rateLimitKeyMock(...args),
|
||||
rateLimitKey: (key: string, minIntervalMs: number) =>
|
||||
rateLimitKeyMock(key, minIntervalMs),
|
||||
}));
|
||||
|
||||
import { POST } from "../../app/api/organizer-inquiry/route";
|
||||
|
||||
Reference in New Issue
Block a user