Create use cases pages

This commit is contained in:
adilallo
2026-05-18 16:50:44 -06:00
parent 40ce5064d6
commit 7c46cbd87b
28 changed files with 836 additions and 58 deletions
+17
View File
@@ -81,4 +81,21 @@ describe("AskOrganizer (behavioral tests)", () => {
}),
).toBeInTheDocument();
});
it("use-case-detail variant uses inverse lockup and figma node", () => {
const { container } = render(
<AskOrganizer
title="Still have questions?"
subtitle="Get answers from an experienced organizer"
buttonText="Ask an Organizer"
variant="use-case-detail"
/>,
);
expect(
container.querySelector('[data-figma-node="22015-42624"]'),
).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "Still have questions?" }),
).toBeInTheDocument();
});
});
+25 -1
View File
@@ -1,6 +1,7 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import { screen } from "@testing-library/react";
import { describe, it, expect, vi } from "vitest";
import { renderWithProviders as render } from "../utils/test-utils";
import ContentBanner from "../../app/components/sections/ContentBanner";
import type { BlogPost } from "../../lib/content";
@@ -61,6 +62,29 @@ describe("ContentBanner", () => {
expect(screen.getByText("Test description")).toBeInTheDocument();
});
it("renders useCase variant with ContentContainer copy and rule preview", () => {
const { container } = render(
<ContentBanner
post={mockPost}
variant="useCase"
rulePreview={{
title: "Sample Operating Manual",
description: "Governance preview for the case study.",
backgroundColor: "bg-[var(--color-surface-invert-brand-lavender)]",
iconPath: "assets/case-study/case-study-mutual-aid.svg",
}}
/>,
);
expect(
screen.getByRole("heading", { name: "Test Article" }),
).toBeInTheDocument();
expect(screen.getByText("Sample Operating Manual")).toBeInTheDocument();
expect(
container.querySelector('[data-figma-node="22015:42621"]'),
).toBeInTheDocument();
});
it("renders guide variant with left-aligned copy and logo mark", () => {
const { container } = render(
<ContentBanner post={mockPost} variant="guide" />,
+85
View File
@@ -0,0 +1,85 @@
import { describe, test, expect, vi } from "vitest";
import { screen } from "@testing-library/react";
import { renderWithProviders as render } from "../utils/test-utils";
import UseCaseDetailPage from "../../app/(marketing)/use-cases/[slug]/page";
import messages from "../../messages/en/index";
import { USE_CASE_DETAIL_SLUGS } from "../../lib/useCaseSyntheticPost";
vi.mock("next/navigation", () => ({
notFound: vi.fn(),
}));
vi.mock("../../app/components/sections/ContentBanner", () => ({
default: ({ post, variant, rulePreview }) => (
<section data-testid="content-banner" data-variant={variant}>
<h1>{post.frontmatter.title}</h1>
<p>{post.frontmatter.description}</p>
{rulePreview ? (
<>
<p>{rulePreview.title}</p>
<p>{rulePreview.description}</p>
</>
) : null}
</section>
),
}));
vi.mock("../../app/components/sections/AskOrganizer", () => ({
default: ({ title, subtitle, buttonText, variant }) => (
<section data-testid="ask-organizer" data-variant={variant}>
<h2>{title}</h2>
<p>{subtitle}</p>
<button type="button">{buttonText}</button>
</section>
),
}));
describe("UseCaseDetailPage", () => {
test.each(USE_CASE_DETAIL_SLUGS)(
"renders banner, body, footer, and ask organizer for %s",
async (slug) => {
const detail = messages.pages.useCasesDetail;
const contentKey =
slug === "mutual-aid-colorado"
? "mutualAidColorado"
: slug === "food-not-bombs"
? "foodNotBombs"
: "boulderCountyStreetMedics";
const entry = detail[contentKey];
render(
await UseCaseDetailPage({
params: Promise.resolve({ slug }),
}),
);
expect(screen.getByTestId("content-banner")).toHaveAttribute(
"data-variant",
"useCase",
);
expect(
screen.getByRole("heading", { name: entry.banner.title }),
).toBeInTheDocument();
expect(screen.getByText(entry.ruleCard.description)).toBeInTheDocument();
const bodySnippet =
slug === "mutual-aid-colorado"
? /Coordinating a statewide network/
: slug === "food-not-bombs"
? /Food Not Bombs operates on a fundamentally decentralized model/
: /When communities like the BoCo Street Medics operate/;
expect(screen.getByText(bodySnippet)).toBeInTheDocument();
expect(
document.querySelector('[data-figma-node="22015:42622"]'),
).toBeInTheDocument();
expect(screen.getByTestId("ask-organizer")).toHaveAttribute(
"data-variant",
"use-case-detail",
);
expect(
screen.getByRole("button", { name: /ask an organizer/i }),
).toBeInTheDocument();
},
);
});
+35
View File
@@ -0,0 +1,35 @@
import { describe, test, expect, vi } from "vitest";
import { screen } from "@testing-library/react";
import { renderWithProviders as render } from "../utils/test-utils";
import UseCasesPage from "../../app/(marketing)/use-cases/page";
import messages from "../../messages/en/index";
vi.mock("next/dynamic", () => ({
default: () => {
const Component = vi.fn(() => (
<section data-testid="related-articles">Related articles</section>
));
return Component;
},
}));
vi.mock("next/link", () => ({
default: ({ children, href, ...props }) => (
<a href={href} {...props}>
{children}
</a>
),
}));
describe("UseCasesPage", () => {
const links = messages.pages.useCases.caseStudyTiles.links;
test("renders case study tiles as links to detail pages", () => {
render(<UseCasesPage />);
for (const link of links) {
const anchor = screen.getByRole("link", { name: link.ariaLabel });
expect(anchor).toHaveAttribute("href", link.href);
}
});
});
+8
View File
@@ -130,6 +130,14 @@ describe("Rule Component", () => {
expect(card).toHaveClass("w-[568px]");
});
it("fluidWidth expanded cards fill the container", () => {
render(<Rule {...defaultProps} expanded={true} size="L" fluidWidth />);
const card = screen.getByRole("button");
expect(card).not.toHaveClass("w-[568px]");
expect(card).toHaveClass("w-full");
});
it("applies proper accessibility attributes", () => {
render(<Rule {...defaultProps} expanded={true} />);