diff --git a/__tests__/benchmarks-page.test.tsx b/__tests__/benchmarks-page.test.tsx
index a61784f6..2de06fc3 100644
--- a/__tests__/benchmarks-page.test.tsx
+++ b/__tests__/benchmarks-page.test.tsx
@@ -1,147 +1,28 @@
/** @jest-environment jsdom */
-import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
-import BenchmarksPage from '@/app/benchmarks/page';
+import React from "react";
+import { render, screen } from "@testing-library/react";
-describe('Benchmarks Page', () => {
- test('renders main heading', () => {
- render();
-
- expect(screen.getByRole('heading', { name: /performance benchmarks/i })).toBeInTheDocument();
- });
-
- test('renders page description', () => {
- render();
-
- expect(screen.getByText(/comprehensive performance metrics for top skills/i)).toBeInTheDocument();
- });
-
- test('displays environment information', () => {
- render();
-
- expect(screen.getByText(/hardware:/i)).toBeInTheDocument();
- expect(screen.getByText(/model:/i)).toBeInTheDocument();
- expect(screen.getByText(/date:/i)).toBeInTheDocument();
- });
-
- test('renders category filters', () => {
- render();
-
- expect(screen.getByText(/all categories/i)).toBeInTheDocument();
- expect(screen.getByText(/filter by category/i)).toBeInTheDocument();
- });
+jest.mock("@/lib/agent-benchmarks", () => ({
+ agentBenchmarksData: [{ id: "sample-benchmark" }],
+}));
- test('renders skill cards with benchmark data', () => {
- render();
-
- // Should render multiple skill cards (using getAllByText since they appear in both cards and table)
- expect(screen.getAllByText('Web Search')[0]).toBeInTheDocument();
- expect(screen.getAllByText('File Operations')[0]).toBeInTheDocument();
- expect(screen.getAllByText('Code Execution')[0]).toBeInTheDocument();
- });
+jest.mock("@/app/benchmarks/benchmarks-client", () => ({
+ BenchmarksClient: ({ data }: { data: unknown[] }) => (
+
+
Agent Benchmark Suite
+ {data.length}
+
+ ),
+}));
- test('displays latency metrics', () => {
- render();
-
- // Check for latency labels
- const p50Labels = screen.getAllByText('p50');
- const p95Labels = screen.getAllByText('p95');
- const p99Labels = screen.getAllByText('p99');
-
- expect(p50Labels.length).toBeGreaterThan(0);
- expect(p95Labels.length).toBeGreaterThan(0);
- expect(p99Labels.length).toBeGreaterThan(0);
- });
+import BenchmarksPage from "@/app/benchmarks/page";
- test('displays throughput and reliability metrics', () => {
+describe("Benchmarks Page", () => {
+ test("renders benchmarks client", () => {
render();
-
- expect(screen.getAllByText(/throughput/i).length).toBeGreaterThan(0);
- expect(screen.getAllByText(/reliability/i).length).toBeGreaterThan(0);
- });
-
- test('displays resource usage information', () => {
- render();
-
- expect(screen.getAllByText(/resource usage/i).length).toBeGreaterThan(0);
- expect(screen.getAllByText(/avg memory/i).length).toBeGreaterThan(0);
- });
-
- test('displays historical trends', () => {
- render();
-
- expect(screen.getAllByText(/historical trend/i).length).toBeGreaterThan(0);
- expect(screen.getAllByText(/last 5 runs/i).length).toBeGreaterThan(0);
- });
-
- test('renders detailed comparison table', () => {
- render();
-
- expect(screen.getByText(/detailed comparison/i)).toBeInTheDocument();
- // Use getByRole to target table header specifically
- expect(screen.getByRole('columnheader', { name: /skill/i })).toBeInTheDocument();
- expect(screen.getByText(/req\/sec/i)).toBeInTheDocument();
- expect(screen.getByText(/success %/i)).toBeInTheDocument();
- });
-
- test('renders metrics explanation section', () => {
- render();
-
- expect(screen.getByText(/metrics explained/i)).toBeInTheDocument();
- expect(screen.getByText(/latency percentiles/i)).toBeInTheDocument();
- expect(screen.getByText(/reliability metrics/i)).toBeInTheDocument();
- });
-
- test('category filter buttons are clickable', () => {
- render();
-
- const allCategoriesButton = screen.getByText(/all categories/i);
- expect(allCategoriesButton).toBeInTheDocument();
-
- fireEvent.click(allCategoriesButton);
- expect(allCategoriesButton).toBeInTheDocument();
- });
-
- test('displays skill descriptions', () => {
- render();
-
- expect(screen.getByText(/search and retrieve web content/i)).toBeInTheDocument();
- expect(screen.getByText(/read, write, and manage files/i)).toBeInTheDocument();
- });
-
- test('renders category badges', () => {
- render();
-
- // Categories should be displayed as badges
- const categoryBadges = screen.getAllByText(/research|system|development|integration/i);
- expect(categoryBadges.length).toBeGreaterThan(0);
- });
-
- test('comparison table has sortable columns', () => {
- render();
-
- // Check for sort icons or indicators in table header
- const skillHeader = screen.getByRole('columnheader', { name: /skill/i });
- expect(skillHeader).toBeInTheDocument();
- });
-
- test('displays multiple benchmark skills', () => {
- render();
-
- // Should render at least 8 skills as per requirement (using getAllByText since they appear in both cards and table)
- expect(screen.getAllByText('Web Search')[0]).toBeInTheDocument();
- expect(screen.getAllByText('File Operations')[0]).toBeInTheDocument();
- expect(screen.getAllByText('Code Execution')[0]).toBeInTheDocument();
- expect(screen.getAllByText('API Integration')[0]).toBeInTheDocument();
- expect(screen.getAllByText('Database Queries')[0]).toBeInTheDocument();
- expect(screen.getAllByText('Image Processing')[0]).toBeInTheDocument();
- expect(screen.getAllByText('Text Generation')[0]).toBeInTheDocument();
- expect(screen.getAllByText('Notifications')[0]).toBeInTheDocument();
- });
- test('renders without errors', () => {
- const { container } = render();
- expect(container).toBeInTheDocument();
+ expect(screen.getByRole("heading", { name: /agent benchmark suite/i })).toBeInTheDocument();
+ expect(screen.getByTestId("benchmarks-count")).toHaveTextContent("1");
});
});
diff --git a/__tests__/changelog-content.test.tsx b/__tests__/changelog-content.test.tsx
index 9f2688d9..4ada8469 100644
--- a/__tests__/changelog-content.test.tsx
+++ b/__tests__/changelog-content.test.tsx
@@ -22,36 +22,31 @@ jest.mock("next/link", () => {
const mockEntries: ChangelogEntry[] = [
{
+ id: "1",
date: "2026-02-08",
title: "New Feature Release",
- description: "Added new feature by @user1",
+ description: "Added new feature",
category: "feature",
- link: "/feature",
- pr: "https://github.com/test/pr/1",
+ prNumber: 11,
+ prUrl: "https://github.com/test/pr/11",
},
{
+ id: "2",
date: "2026-02-07",
title: "Bug Fix",
- description: "Fixed bug by @user2",
- category: "fix",
- link: "/fix",
- pr: "https://github.com/test/pr/2",
+ description: "Fixed bug",
+ category: "bugfix",
+ prNumber: 12,
+ prUrl: "https://github.com/test/pr/12",
},
{
+ id: "3",
date: "2026-02-06",
title: "Documentation Update",
- description: "Updated docs by @user3",
+ description: "Updated docs",
category: "docs",
- link: "/docs",
- pr: "https://github.com/test/pr/3",
- },
- {
- date: "2026-02-05",
- title: "Code Refactor",
- description: "Refactored code by @user4",
- category: "refactor",
- link: "/refactor",
- pr: "https://github.com/test/pr/4",
+ prNumber: 13,
+ prUrl: "https://github.com/test/pr/13",
},
];
@@ -61,80 +56,24 @@ describe("ChangelogContent", () => {
expect(screen.getByText("New Feature Release")).toBeInTheDocument();
expect(screen.getByText("Bug Fix")).toBeInTheDocument();
expect(screen.getByText("Documentation Update")).toBeInTheDocument();
- expect(screen.getByText("Code Refactor")).toBeInTheDocument();
- });
-
- it("displays stats banner", () => {
- render();
- expect(screen.getByText("Changes This Month")).toBeInTheDocument();
- expect(screen.getByText("Features Shipped")).toBeInTheDocument();
- expect(screen.getByText("Bugs Fixed")).toBeInTheDocument();
});
it("displays category filter tabs", () => {
render();
- const buttons = screen.getAllByRole("button");
- const buttonTexts = buttons.map(b => b.textContent);
- expect(buttonTexts).toContain("All");
- expect(buttonTexts).toContain("Features");
- expect(buttonTexts).toContain("Fixes");
- expect(buttonTexts).toContain("Docs");
- expect(buttonTexts).toContain("Refactors");
- expect(buttonTexts).toContain("Tests");
+ const buttonTexts = screen.getAllByRole("button").map((b) => b.textContent);
+ expect(buttonTexts).toEqual(expect.arrayContaining(["All", "Features", "Bugfixes", "Docs"]));
});
- it("filters by feature category", () => {
+ it("filters by bugfix category", () => {
render();
- const featuresButton = screen.getAllByRole("button").find(b => b.textContent === "Features");
- fireEvent.click(featuresButton!);
-
- expect(screen.getByText("New Feature Release")).toBeInTheDocument();
- expect(screen.queryByText("Bug Fix")).not.toBeInTheDocument();
- expect(screen.queryByText("Documentation Update")).not.toBeInTheDocument();
- });
+ fireEvent.click(screen.getByRole("button", { name: "Bugfixes" }));
- it("filters by fix category", () => {
- render();
- const fixesButton = screen.getAllByRole("button").find(b => b.textContent === "Fixes");
- fireEvent.click(fixesButton!);
-
expect(screen.getByText("Bug Fix")).toBeInTheDocument();
expect(screen.queryByText("New Feature Release")).not.toBeInTheDocument();
});
- it("filters by docs category", () => {
- render();
- const docsButton = screen.getAllByRole("button").find(b => b.textContent === "Docs");
- fireEvent.click(docsButton!);
-
- expect(screen.getByText("Documentation Update")).toBeInTheDocument();
- expect(screen.queryByText("New Feature Release")).not.toBeInTheDocument();
- });
-
- it("shows all entries when clicking All filter", () => {
- render();
-
- // First filter by features
- const featuresButton = screen.getAllByRole("button").find(b => b.textContent === "Features");
- fireEvent.click(featuresButton!);
- expect(screen.queryByText("Bug Fix")).not.toBeInTheDocument();
-
- // Then click All
- const allButton = screen.getAllByRole("button").find(b => b.textContent === "All");
- fireEvent.click(allButton!);
- expect(screen.getByText("New Feature Release")).toBeInTheDocument();
- expect(screen.getByText("Bug Fix")).toBeInTheDocument();
- });
-
- it("displays PR links", () => {
- render();
- const prLinks = screen.getAllByText(/View PR/);
- expect(prLinks.length).toBeGreaterThan(0);
- });
-
- it("renders empty state when no entries match filter", () => {
- const emptyEntries: ChangelogEntry[] = [];
- render();
+ it("renders empty state when no entries", () => {
+ render();
expect(screen.getByText("No updates found for this filter.")).toBeInTheDocument();
});
});
diff --git a/__tests__/changelog-page.test.tsx b/__tests__/changelog-page.test.tsx
index bf073707..b7728055 100644
--- a/__tests__/changelog-page.test.tsx
+++ b/__tests__/changelog-page.test.tsx
@@ -3,7 +3,6 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import ChangelogPage from "../src/app/changelog/page";
-import * as changelogLib from "../src/lib/changelog";
type LinkProps = {
href: string;
@@ -20,34 +19,44 @@ jest.mock("next/link", () => {
return LinkMock;
});
-// Mock the changelog data
-jest.mock("../src/lib/changelog", () => ({
- getChangelogEntries: jest.fn(),
- type: jest.fn(),
+jest.mock("next/headers", () => ({
+ headers: jest.fn(async () =>
+ new Map([
+ ["host", "localhost:3000"],
+ ["x-forwarded-proto", "http"],
+ ])
+ ),
}));
const mockEntries = [
{
+ id: "entry-1",
date: "2026-02-08",
title: "Test Feature",
description: "A test feature description",
- category: "feature" as const,
- link: "/test",
- pr: "https://github.com/test/pr/1",
+ category: "feature",
+ prNumber: 101,
+ prUrl: "https://github.com/test/pr/101",
},
{
+ id: "entry-2",
date: "2026-02-07",
title: "Test Fix",
description: "A test fix description",
- category: "fix" as const,
- link: "/test-fix",
- pr: "https://github.com/test/pr/2",
+ category: "bugfix",
+ prNumber: 102,
+ prUrl: "https://github.com/test/pr/102",
},
];
describe("Changelog Page", () => {
beforeEach(() => {
- (changelogLib.getChangelogEntries as jest.Mock).mockResolvedValue(mockEntries);
+ global.fetch = jest.fn(async () =>
+ ({
+ ok: true,
+ json: async () => ({ entries: mockEntries, total: mockEntries.length }),
+ } as Response)
+ ) as jest.Mock;
});
it("renders the changelog page", async () => {
@@ -56,35 +65,30 @@ describe("Changelog Page", () => {
expect(container).toBeInTheDocument();
});
- it("displays the page title", async () => {
+ it("displays the page title and description", async () => {
const jsx = await ChangelogPage();
render(jsx);
expect(screen.getByText("Changelog")).toBeInTheDocument();
- });
-
- it("displays the description", async () => {
- const jsx = await ChangelogPage();
- render(jsx);
expect(screen.getByText(/Recent updates and improvements/)).toBeInTheDocument();
});
- it("displays newsletter signup section", async () => {
+ it("displays newsletter CTA and API link", async () => {
const jsx = await ChangelogPage();
render(jsx);
- const subscribeButtons = screen.getAllByText("Subscribe");
- expect(subscribeButtons.length).toBeGreaterThan(0);
- });
- it("displays the API link", async () => {
- const jsx = await ChangelogPage();
- render(jsx);
+ expect(screen.getAllByText("Subscribe").length).toBeGreaterThan(0);
const apiLink = screen.getByText("/api/changelog");
- expect(apiLink).toBeInTheDocument();
expect(apiLink.closest("a")).toHaveAttribute("href", "/api/changelog");
});
- it("renders with no entries", async () => {
- (changelogLib.getChangelogEntries as jest.Mock).mockResolvedValue([]);
+ it("renders even when API returns no entries", async () => {
+ global.fetch = jest.fn(async () =>
+ ({
+ ok: true,
+ json: async () => ({ entries: [], total: 0 }),
+ } as Response)
+ ) as jest.Mock;
+
const jsx = await ChangelogPage();
const { container } = render(jsx);
expect(container).toBeInTheDocument();
diff --git a/__tests__/events-page.test.tsx b/__tests__/events-page.test.tsx
index 8ae2a0d7..adf5be30 100644
--- a/__tests__/events-page.test.tsx
+++ b/__tests__/events-page.test.tsx
@@ -3,114 +3,21 @@
import React from "react";
import { render, screen } from "@testing-library/react";
-jest.setTimeout(10_000);
-
-// ---- Browser API polyfills commonly used by UI libs ----
-class NoopObserver {
- observe() {}
- unobserve() {}
- disconnect() {}
-}
-
-// @ts-expect-error - polyfill for tests
-global.ResizeObserver = global.ResizeObserver ?? NoopObserver;
-// @ts-expect-error - polyfill for tests
-global.IntersectionObserver = global.IntersectionObserver ?? NoopObserver;
-
-Object.defineProperty(window, "matchMedia", {
- writable: true,
- value:
- window.matchMedia ??
- ((query: string) => ({
- matches: false,
- media: query,
- onchange: null,
- addListener: () => {},
- removeListener: () => {},
- addEventListener: () => {},
- removeEventListener: () => {},
- dispatchEvent: () => false,
- })),
-});
-
-// ---- Next.js shims ----
-
-type LinkProps = {
- href: string;
- children?: React.ReactNode;
-} & React.AnchorHTMLAttributes;
-
-jest.mock("next/link", () => {
- const LinkMock = ({ href, children, ...props }: LinkProps) => (
-
- {children}
-
- );
- LinkMock.displayName = "Link";
- return LinkMock;
-});
-
-jest.mock("next/navigation", () => ({
- useRouter: () => ({
- push: jest.fn(),
- replace: jest.fn(),
- back: jest.fn(),
- prefetch: jest.fn(),
- refresh: jest.fn(),
- }),
- useSearchParams: () => new URLSearchParams(),
- usePathname: () => "/events",
- useParams: () => ({}),
- notFound: () => {
- throw new Error("NEXT_NOT_FOUND");
- },
- redirect: (url: string) => {
- throw new Error(`NEXT_REDIRECT:${url}`);
- },
+jest.mock("@/app/events/events-client", () => ({
+ EventsClient: () => (
+
+
Events & Community
+
Mock events client
+
+ ),
}));
-jest.mock("next/headers", () => ({
- headers: () =>
- new Map([
- ["host", "localhost:3000"],
- ["x-forwarded-proto", "http"],
- ]),
- cookies: () => ({ get: () => undefined, getAll: () => [] }),
-}));
+import EventsPage from "@/app/events/page";
describe("Events page", () => {
- test("renders without crashing", async () => {
- const EventsPage = (await import("@/app/events/page")).default;
- const { container } = render();
- expect(container).toBeInTheDocument();
- });
-
- test("displays page title", async () => {
- const EventsPage = (await import("@/app/events/page")).default;
- render();
- expect(screen.getByText("Events & Community")).toBeInTheDocument();
- });
-
- test("displays upcoming and past events sections", async () => {
- const EventsPage = (await import("@/app/events/page")).default;
- render();
- expect(screen.getByText("Upcoming Events")).toBeInTheDocument();
- expect(screen.getByText("Past Events")).toBeInTheDocument();
- });
-
- test("displays event type filters", async () => {
- const EventsPage = (await import("@/app/events/page")).default;
- render();
- expect(screen.getByText("All Events")).toBeInTheDocument();
- expect(screen.getAllByText("Webinar").length).toBeGreaterThan(0);
- expect(screen.getAllByText("Workshop").length).toBeGreaterThan(0);
- expect(screen.getAllByText("Hackathon").length).toBeGreaterThan(0);
- expect(screen.getAllByText("Meetup").length).toBeGreaterThan(0);
- });
-
- test("displays host an event CTA", async () => {
- const EventsPage = (await import("@/app/events/page")).default;
+ test("renders events client", () => {
render();
- expect(screen.getByText("Want to host an event?")).toBeInTheDocument();
+ expect(screen.getByRole("heading", { name: /events & community/i })).toBeInTheDocument();
+ expect(screen.getByText("Mock events client")).toBeInTheDocument();
});
});
diff --git a/__tests__/feed-and-health.test.ts b/__tests__/feed-and-health.test.ts
index d1001b38..d786a2a7 100644
--- a/__tests__/feed-and-health.test.ts
+++ b/__tests__/feed-and-health.test.ts
@@ -34,15 +34,17 @@ describe('/api/feed', () => {
});
describe('/api/health', () => {
- test('returns ok + data counts', async () => {
+ test('returns health metadata', async () => {
const res = await healthGET();
expect(res.status).toBe(200);
const body = await res.json();
expect(body.status).toBe('ok');
- expect(body.data).toHaveProperty('news');
- expect(body.data).toHaveProperty('total');
- expect(body.data.total).toBeGreaterThan(0);
+ expect(body).toHaveProperty('version');
+ expect(body).toHaveProperty('skills_count');
+ expect(body).toHaveProperty('mcp_count');
+ expect(body).toHaveProperty('uptime');
+ expect(body).toHaveProperty('timestamp');
});
});
diff --git a/__tests__/glossary-page.test.tsx b/__tests__/glossary-page.test.tsx
index 114c0069..eddffaee 100644
--- a/__tests__/glossary-page.test.tsx
+++ b/__tests__/glossary-page.test.tsx
@@ -1,21 +1,20 @@
/** @jest-environment jsdom */
import React from "react";
-import { render, screen, fireEvent, waitFor } from "@testing-library/react";
+import { render, screen, fireEvent, waitFor, act } from "@testing-library/react";
import GlossaryPage from "@/app/glossary/page";
jest.setTimeout(10_000);
-// ---- Browser API polyfills ----
class NoopObserver {
observe() {}
unobserve() {}
disconnect() {}
}
-// @ts-expect-error - polyfill for tests
+// @ts-expect-error - test polyfill
global.ResizeObserver = global.ResizeObserver ?? NoopObserver;
-// @ts-expect-error - polyfill for tests
+// @ts-expect-error - test polyfill
global.IntersectionObserver = global.IntersectionObserver ?? NoopObserver;
Object.defineProperty(window, "matchMedia", {
@@ -34,7 +33,6 @@ Object.defineProperty(window, "matchMedia", {
})),
});
-// ---- Next.js shims ----
type LinkProps = {
href: string;
children?: React.ReactNode;
@@ -50,160 +48,103 @@ jest.mock("next/link", () => {
return LinkMock;
});
-jest.mock("next/navigation", () => ({
- useRouter: () => ({
- push: jest.fn(),
- replace: jest.fn(),
- back: jest.fn(),
- prefetch: jest.fn(),
- refresh: jest.fn(),
- }),
- useSearchParams: () => new URLSearchParams(),
- usePathname: () => "/glossary",
- useParams: () => ({}),
-}));
+const mockTerms = [
+ {
+ id: "agent",
+ term: "Agent",
+ definition: "Autonomous software actor",
+ relatedTerms: ["Tool"],
+ seeAlso: ["MCP"],
+ },
+ {
+ id: "mcp",
+ term: "MCP",
+ definition: "Model Context Protocol",
+ relatedTerms: ["Agent"],
+ seeAlso: [],
+ },
+ {
+ id: "tool",
+ term: "Tool",
+ definition: "External capability used by agents",
+ relatedTerms: ["Agent"],
+ seeAlso: [],
+ },
+];
describe("/glossary page", () => {
- test("renders without crashing", () => {
- const { container } = render();
- expect(container).toBeInTheDocument();
+ beforeEach(() => {
+ jest.useFakeTimers();
+ global.fetch = jest.fn(async (input: RequestInfo | URL) => {
+ const url = String(input);
+ const params = new URL(url, "http://localhost").searchParams;
+ const search = params.get("search")?.toLowerCase() ?? "";
+ const letter = params.get("letter");
+
+ let terms = [...mockTerms];
+ if (search) {
+ terms = terms.filter(
+ (t) =>
+ t.term.toLowerCase().includes(search) ||
+ t.definition.toLowerCase().includes(search)
+ );
+ }
+ if (letter) {
+ terms = terms.filter((t) => t.term.startsWith(letter));
+ }
+
+ const letters = Array.from(new Set(mockTerms.map((t) => t.term[0].toUpperCase())));
+ return {
+ ok: true,
+ json: async () => ({ terms, total: terms.length, letters }),
+ } as Response;
+ }) as jest.Mock;
});
- test("displays hero section with title", () => {
- const { getByText } = render();
- expect(getByText("📖 Agent Terminology")).toBeInTheDocument();
- expect(
- getByText("Your comprehensive guide to AI agent concepts and protocols")
- ).toBeInTheDocument();
+ afterEach(() => {
+ jest.runOnlyPendingTimers();
+ jest.useRealTimers();
});
- test("displays search input", () => {
- const { getByPlaceholderText } = render();
- const searchInput = getByPlaceholderText(
- "Search terms, definitions, or concepts..."
- );
- expect(searchInput).toBeInTheDocument();
- });
-
- test("displays alphabet navigation", () => {
- const { getByLabelText } = render();
- expect(getByLabelText("Filter by letter A")).toBeInTheDocument();
- expect(getByLabelText("Filter by letter Z")).toBeInTheDocument();
- });
-
- test("displays glossary terms", () => {
- const { getAllByText } = render();
- // Check for some key terms that should be in the glossary
- // Use getAllByText since terms appear multiple times (as headings and as links)
- expect(getAllByText("Agent").length).toBeGreaterThan(0);
- expect(getAllByText("MCP").length).toBeGreaterThan(0);
- expect(getAllByText("Tool").length).toBeGreaterThan(0);
- });
-
- test("search functionality filters terms", async () => {
- const { getByPlaceholderText, getAllByText } = render(
-
- );
- const searchInput = getByPlaceholderText(
- "Search terms, definitions, or concepts..."
- );
-
- // Search for "agent"
- fireEvent.change(searchInput, { target: { value: "agent" } });
-
- await waitFor(() => {
- // Use getAllByText since "Agent" appears multiple times
- expect(getAllByText("Agent").length).toBeGreaterThan(0);
- // Terms not matching "agent" should not be visible or should be filtered out
- });
- });
-
- test("alphabet filter works", async () => {
- const { getByLabelText } = render();
- const letterA = getByLabelText("Filter by letter A");
-
- // Click on letter A
- fireEvent.click(letterA);
-
- await waitFor(() => {
- // The letter A button should be highlighted
- expect(letterA).toHaveClass("bg-[#06D6A0]");
- });
- });
-
- test("clear filters button appears when filtering", async () => {
- const { getByPlaceholderText, getByText } = render();
- const searchInput = getByPlaceholderText(
- "Search terms, definitions, or concepts..."
- );
-
- // Trigger search
- fireEvent.change(searchInput, { target: { value: "test" } });
+ test("renders hero and search input", async () => {
+ render();
+ expect(screen.getByText("📖 Agent Terminology")).toBeInTheDocument();
+ expect(screen.getByPlaceholderText("Search terms or definitions...")).toBeInTheDocument();
- await waitFor(() => {
- expect(getByText("Clear filters")).toBeInTheDocument();
+ await act(async () => {
+ jest.advanceTimersByTime(350);
});
- });
-
- test("displays related terms section", () => {
- const { getAllByText } = render();
- // Should have at least one "Related:" label
- const relatedLabels = getAllByText("Related:");
- expect(relatedLabels.length).toBeGreaterThan(0);
- });
- test("displays see also section", () => {
- const { getAllByText } = render();
- // Should have at least one "See also:" label
- const seeAlsoLabels = getAllByText("See also:");
- expect(seeAlsoLabels.length).toBeGreaterThan(0);
+ await waitFor(() => expect(screen.getAllByText("Agent").length).toBeGreaterThan(0));
});
- test("displays CTA section", () => {
- const { getByText } = render();
- expect(getByText("Ready to Build?")).toBeInTheDocument();
- expect(getByText("Browse Skills →")).toBeInTheDocument();
- expect(getByText("Start Learning")).toBeInTheDocument();
- });
-
- test("displays empty state when no results found", async () => {
- const { getByPlaceholderText, getByText } = render();
- const searchInput = getByPlaceholderText(
- "Search terms, definitions, or concepts..."
- );
+ test("search filters terms", async () => {
+ render();
+ const input = screen.getByPlaceholderText("Search terms or definitions...");
- // Search for something that doesn't exist
- fireEvent.change(searchInput, {
- target: { value: "xyznonexistentterm123" },
+ fireEvent.change(input, { target: { value: "protocol" } });
+ await act(async () => {
+ jest.advanceTimersByTime(350);
});
await waitFor(() => {
- expect(getByText("No terms found")).toBeInTheDocument();
- expect(getByText("Show all terms")).toBeInTheDocument();
+ expect(screen.getByText("MCP")).toBeInTheDocument();
+ expect(screen.queryByText("Tool")).not.toBeInTheDocument();
});
});
- test("shows result count when filtering", async () => {
- const { getByPlaceholderText, getByText } = render();
- const searchInput = getByPlaceholderText(
- "Search terms, definitions, or concepts..."
- );
+ test("shows empty state when no results", async () => {
+ render();
+ const input = screen.getByPlaceholderText("Search terms or definitions...");
- // Search for "protocol"
- fireEvent.change(searchInput, { target: { value: "protocol" } });
+ fireEvent.change(input, { target: { value: "xyznonexistent" } });
+ await act(async () => {
+ jest.advanceTimersByTime(350);
+ });
await waitFor(() => {
- // Should show "X terms found" or "X term found"
- const resultText = screen.getByText(/\d+ terms? found/);
- expect(resultText).toBeInTheDocument();
+ expect(screen.getByText("No terms found")).toBeInTheDocument();
+ expect(screen.getByText("Show all terms")).toBeInTheDocument();
});
});
-
- test("contains minimum 30 terms", () => {
- render();
- // Count the number of term entries by checking for elements with specific structure
- // Each term has an id attribute on its container
- const termElements = document.querySelectorAll("[id][class*='scroll-mt']");
- expect(termElements.length).toBeGreaterThanOrEqual(30);
- });
});
diff --git a/__tests__/partners-page.test.tsx b/__tests__/partners-page.test.tsx
index 359c3b97..7d5df9ac 100644
--- a/__tests__/partners-page.test.tsx
+++ b/__tests__/partners-page.test.tsx
@@ -1,9 +1,8 @@
/** @jest-environment jsdom */
import React from "react";
-import { render, screen, fireEvent } from "@testing-library/react";
+import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import PartnersPage from "@/app/partners/page";
-import partnersData from "@/data/partners.json";
type LinkProps = {
href: string;
@@ -20,208 +19,77 @@ jest.mock("next/link", () => {
return LinkMock;
});
+const mockPartners = [
+ {
+ id: "1",
+ name: "OpenClaw",
+ slug: "openclaw",
+ icon: "🛠️",
+ description: "Agent runtime",
+ tier: "Gold",
+ integrationType: "API",
+ type: "partner",
+ website: "https://openclaw.example",
+ },
+ {
+ id: "2",
+ name: "Supabase",
+ slug: "supabase",
+ icon: "🟢",
+ description: "Database backend",
+ tier: "Silver",
+ integrationType: "SDK",
+ type: "sponsor",
+ website: "https://supabase.example",
+ },
+] as const;
+
describe("Partners Page", () => {
- it("renders the partners page", () => {
- const { container } = render();
- expect(container).toBeInTheDocument();
- });
+ beforeEach(() => {
+ global.fetch = jest.fn(async (input: RequestInfo | URL, init?: RequestInit) => {
+ const url = String(input);
- it("displays the page title", () => {
- render();
- expect(screen.getByRole("heading", { name: /partners & integrations/i })).toBeInTheDocument();
- });
+ if (url.includes("/api/partners/apply") && init?.method === "POST") {
+ return { ok: true, json: async () => ({ message: "Application received." }) } as Response;
+ }
- it("displays partner count", () => {
- render();
- expect(screen.getByText(`${partnersData.length} verified partners`)).toBeInTheDocument();
- });
+ if (url.includes("/api/partners")) {
+ return {
+ ok: true,
+ json: async () => ({ partners: mockPartners, total: mockPartners.length }),
+ } as Response;
+ }
- it("renders search input", () => {
- render();
- const searchInput = screen.getByPlaceholderText(/search partners/i);
- expect(searchInput).toBeInTheDocument();
+ return { ok: false, json: async () => ({}) } as Response;
+ }) as jest.Mock;
});
- it("renders tier filter buttons", () => {
+ it("renders title and loaded partner count", async () => {
render();
- expect(screen.getByText("Filter by Tier")).toBeInTheDocument();
- const buttons = screen.getAllByRole("button");
- expect(buttons.some(btn => btn.textContent === "Gold")).toBe(true);
- expect(buttons.some(btn => btn.textContent === "Silver")).toBe(true);
- expect(buttons.some(btn => btn.textContent === "Bronze")).toBe(true);
- expect(buttons.some(btn => btn.textContent === "Community")).toBe(true);
- });
-
- it("renders integration type filter buttons", () => {
- render();
- const buttons = screen.getAllByRole("button");
- const apiButton = buttons.find(btn => btn.textContent === "API");
- const sdkButton = buttons.find(btn => btn.textContent === "SDK");
- const pluginButton = buttons.find(btn => btn.textContent === "Plugin");
- const serviceButton = buttons.find(btn => btn.textContent === "Service");
-
- expect(apiButton).toBeInTheDocument();
- expect(sdkButton).toBeInTheDocument();
- expect(pluginButton).toBeInTheDocument();
- expect(serviceButton).toBeInTheDocument();
- });
- it("displays all partners by default", () => {
- render();
- const goldPartners = partnersData.filter(p => p.tier === "Gold");
- goldPartners.forEach(partner => {
- expect(screen.getByText(partner.name)).toBeInTheDocument();
+ expect(screen.getByRole("heading", { name: /partners & sponsors/i })).toBeInTheDocument();
+ await waitFor(() => {
+ expect(screen.getByText(`${mockPartners.length} listed organizations`)).toBeInTheDocument();
});
});
- it("filters partners by tier", () => {
+ it("filters by search", async () => {
render();
- const goldButton = screen.getByRole("button", { name: /^gold$/i });
- fireEvent.click(goldButton);
-
- const goldPartners = partnersData.filter(p => p.tier === "Gold");
- const silverPartners = partnersData.filter(p => p.tier === "Silver");
-
- goldPartners.forEach(partner => {
- expect(screen.getByText(partner.name)).toBeInTheDocument();
- });
-
- silverPartners.forEach(partner => {
- expect(screen.queryByText(partner.name)).not.toBeInTheDocument();
- });
- });
- it("filters partners by integration type", () => {
- render();
- const buttons = screen.getAllByRole("button");
- const apiButton = buttons.find(btn => btn.textContent === "API") as HTMLElement;
- fireEvent.click(apiButton);
-
- const apiPartners = partnersData.filter(p => p.integrationType === "API");
- const sdkPartners = partnersData.filter(p => p.integrationType === "SDK");
-
- apiPartners.forEach(partner => {
- expect(screen.getByText(partner.name)).toBeInTheDocument();
- });
-
- sdkPartners.forEach(partner => {
- expect(screen.queryByText(partner.name)).not.toBeInTheDocument();
+ await waitFor(() => expect(screen.getByText("OpenClaw")).toBeInTheDocument());
+
+ fireEvent.change(screen.getByPlaceholderText(/search partners/i), {
+ target: { value: "OpenClaw" },
});
- });
- it("filters partners by search query", () => {
- render();
- const searchInput = screen.getByPlaceholderText(/search partners/i);
- fireEvent.change(searchInput, { target: { value: "OpenClaw" } });
-
expect(screen.getByText("OpenClaw")).toBeInTheDocument();
expect(screen.queryByText("Supabase")).not.toBeInTheDocument();
});
- it("shows no results message when filters match nothing", () => {
- render();
- const searchInput = screen.getByPlaceholderText(/search partners/i);
- fireEvent.change(searchInput, { target: { value: "nonexistent partner xyz" } });
-
- expect(screen.getByText(/no partners found/i)).toBeInTheDocument();
- });
-
- it("displays partner cards with correct information", () => {
- render();
- const openclaw = partnersData.find(p => p.slug === "openclaw");
-
- expect(screen.getByText(openclaw!.name)).toBeInTheDocument();
- expect(screen.getByText(openclaw!.description)).toBeInTheDocument();
- const tierBadges = screen.getAllByText(openclaw!.tier);
- expect(tierBadges.length).toBeGreaterThan(0);
- const integrationTypeBadges = screen.getAllByText(openclaw!.integrationType);
- expect(integrationTypeBadges.length).toBeGreaterThan(0);
- });
-
- it("displays partner icons", () => {
+ it("shows apply section", async () => {
render();
- partnersData.forEach(partner => {
- expect(screen.getByText(partner.icon)).toBeInTheDocument();
- });
- });
-
- it("has links to partner detail pages", () => {
- render();
- partnersData.forEach(partner => {
- const links = screen.getAllByRole("link");
- const partnerLink = links.find(link =>
- link.getAttribute("href") === `/partners/${partner.slug}`
- );
- expect(partnerLink).toBeInTheDocument();
- });
- });
-
- it("displays become a partner CTA section", () => {
- render();
- expect(screen.getByRole("heading", { name: /become a partner/i })).toBeInTheDocument();
- });
-
- it("displays partner benefits", () => {
- render();
- expect(screen.getByText(/featured placement/i)).toBeInTheDocument();
- expect(screen.getByText(/co-marketing/i)).toBeInTheDocument();
- expect(screen.getByText(/technical support/i)).toBeInTheDocument();
- expect(screen.getByText(/community access/i)).toBeInTheDocument();
- expect(screen.getByText(/early access/i)).toBeInTheDocument();
- expect(screen.getByText(/partner badge/i)).toBeInTheDocument();
- });
- it("has apply for partnership link", () => {
- render();
- const applyLink = screen.getByRole("link", { name: /apply for partnership/i });
- expect(applyLink).toHaveAttribute("href", "/contact");
- });
-
- it("has view integration guides link", () => {
- render();
- const guidesLink = screen.getByRole("link", { name: /view integration guides/i });
- expect(guidesLink).toHaveAttribute("href", "/guides");
- });
-
- it("combines tier and type filters correctly", () => {
- render();
-
- // Filter by Gold tier
- const goldButton = screen.getByRole("button", { name: /^gold$/i });
- fireEvent.click(goldButton);
-
- // Then filter by API type
- const buttons = screen.getAllByRole("button");
- const apiButton = buttons.find(btn => btn.textContent === "API") as HTMLElement;
- fireEvent.click(apiButton);
-
- // Should only show Gold + API partners
- const goldApiPartners = partnersData.filter(
- p => p.tier === "Gold" && p.integrationType === "API"
- );
- const otherPartners = partnersData.filter(
- p => p.tier !== "Gold" || p.integrationType !== "API"
- );
-
- goldApiPartners.forEach(partner => {
- expect(screen.getByText(partner.name)).toBeInTheDocument();
- });
- });
-
- it("resets to all partners when clicking All button", () => {
- render();
-
- // Filter by Gold
- const goldButton = screen.getByRole("button", { name: /^gold$/i });
- fireEvent.click(goldButton);
-
- // Reset to All
- const allButtons = screen.getAllByRole("button", { name: /^all$/i });
- fireEvent.click(allButtons[0]);
-
- // Should show all partners again
- partnersData.forEach(partner => {
- expect(screen.getByText(partner.name)).toBeInTheDocument();
- });
+ expect(screen.getByText("Apply to Join")).toBeInTheDocument();
+ expect(screen.getByRole("button", { name: /submit application/i })).toBeInTheDocument();
});
});
diff --git a/__tests__/render-missing-pages-151.test.tsx b/__tests__/render-missing-pages-151.test.tsx
index 9ba15f7b..bd257312 100644
--- a/__tests__/render-missing-pages-151.test.tsx
+++ b/__tests__/render-missing-pages-151.test.tsx
@@ -92,6 +92,15 @@ jest.mock('next/navigation', () => {
};
});
+jest.mock('next/headers', () => ({
+ headers: () =>
+ new Map([
+ ['host', 'localhost:3000'],
+ ['x-forwarded-proto', 'http'],
+ ]),
+ cookies: () => ({ get: () => undefined, getAll: () => [] }),
+}));
+
// ---- Shared component mocks (keep render tests lightweight/deterministic) ----
jest.mock('@/components/mobile-nav', () => ({
@@ -270,6 +279,27 @@ jest.mock('@/lib/data', () => {
};
});
+beforeAll(() => {
+ global.fetch = jest.fn(async (input: RequestInfo | URL) => {
+ const url = String(input);
+
+ if (url.includes('/api/blog')) {
+ return { ok: true, json: async () => ({ posts: [], total: 0 }) } as Response;
+ }
+ if (url.includes('/api/changelog')) {
+ return { ok: true, json: async () => ({ entries: [], total: 0 }) } as Response;
+ }
+ if (url.includes('/api/status/history')) {
+ return { ok: true, json: async () => ({ history: [] }) } as Response;
+ }
+ if (url.includes('/api/status')) {
+ return { ok: true, json: async () => ({ services: [], overall: 'operational' }) } as Response;
+ }
+
+ return { ok: true, json: async () => ({}) } as Response;
+ }) as jest.Mock;
+});
+
async function renderPageModule(importPath: string, props: Record = {}) {
const mod: Record = await import(importPath);
const Page = mod.default;
diff --git a/__tests__/showcase-page.test.tsx b/__tests__/showcase-page.test.tsx
index 8f5c27ca..b7dd3d69 100644
--- a/__tests__/showcase-page.test.tsx
+++ b/__tests__/showcase-page.test.tsx
@@ -1,108 +1,39 @@
/** @jest-environment jsdom */
-import React from 'react';
-import { render, screen } from '@testing-library/react';
+import React from "react";
+import { render, screen } from "@testing-library/react";
type LinkProps = {
href: string;
children?: React.ReactNode;
} & React.AnchorHTMLAttributes;
-jest.mock('next/link', () => {
+jest.mock("next/link", () => {
const LinkMock = ({ href, children, ...props }: LinkProps) => (
{children}
);
- LinkMock.displayName = 'Link';
+ LinkMock.displayName = "Link";
return LinkMock;
});
-// Mock the client component
-jest.mock('@/app/showcase/showcase-client', () => ({
- ShowcaseClient: ({ agents }: { agents: unknown[] }) => (
-
-
{agents.length} agents in hall of fame
-
- ),
+jest.mock("@/app/showcase/showcase-client", () => ({
+ ShowcaseClient: () => Mocked Showcase Client
,
}));
-import ShowcasePage from '@/app/showcase/page';
+import ShowcasePage from "@/app/showcase/page";
-describe('Showcase Page', () => {
- test('renders showcase heading', () => {
+describe("Showcase Page", () => {
+ test("renders heading and description", () => {
render();
-
- expect(screen.getByRole('heading', { name: /🏆 agent showcase/i, level: 1 })).toBeInTheDocument();
- });
-
- test('renders page description', () => {
- render();
-
- expect(screen.getByText(/celebrating the best ai agents/i)).toBeInTheDocument();
- });
-
- test('renders stats banner with all metrics', () => {
- render();
-
- // Should show all 4 stats
- expect(screen.getByText(/total agents/i)).toBeInTheDocument();
- expect(screen.getByText(/skills installed/i)).toBeInTheDocument();
- expect(screen.getByText(/tasks completed/i)).toBeInTheDocument();
- expect(screen.getByText(/community members/i)).toBeInTheDocument();
- });
-
- test('renders agent of the month section', () => {
- render();
-
- expect(screen.getByRole('heading', { name: /agent of the month/i })).toBeInTheDocument();
- });
- test('renders featured agents', () => {
- render();
-
- // Should render featured agents (Kai, Scout, Link)
- expect(screen.getByText('Kai')).toBeInTheDocument();
- expect(screen.getByText('Scout')).toBeInTheDocument();
- expect(screen.getByText('Link')).toBeInTheDocument();
- });
-
- test('renders hall of fame section', () => {
- render();
-
- expect(screen.getByRole('heading', { name: /hall of fame/i })).toBeInTheDocument();
- });
-
- test('renders ShowcaseClient component', () => {
- render();
-
- expect(screen.getByTestId('showcase-client')).toBeInTheDocument();
- });
-
- test('renders submit your agent CTA', () => {
- render();
-
- expect(screen.getByRole('heading', { name: /is your agent showcase-worthy/i })).toBeInTheDocument();
-
- const submitLink = screen.getByRole('link', { name: /submit your agent/i });
- expect(submitLink).toBeInTheDocument();
- expect(submitLink).toHaveAttribute('href', '/submit');
- });
-
- test('displays achievements for featured agents', () => {
- render();
-
- // Check for achievements sections (there are 3 featured agents)
- const achievements = screen.getAllByText('Achievements');
- expect(achievements.length).toBeGreaterThan(0);
+ expect(screen.getByRole("heading", { name: /community showcase/i, level: 1 })).toBeInTheDocument();
+ expect(screen.getByText(/discover what other builders are shipping/i)).toBeInTheDocument();
});
- test('displays trust scores for featured agents', () => {
+ test("renders showcase client component", () => {
render();
-
- // All featured agents should show trust scores
- expect(screen.getByText(/98%/)).toBeInTheDocument(); // Kai
- expect(screen.getByText(/96%/)).toBeInTheDocument(); // Scout
- expect(screen.getByText(/97%/)).toBeInTheDocument(); // Link
+ expect(screen.getByTestId("showcase-client")).toBeInTheDocument();
});
});
diff --git a/__tests__/sponsor-page.test.tsx b/__tests__/sponsor-page.test.tsx
index 3b2e1a0f..3b537c81 100644
--- a/__tests__/sponsor-page.test.tsx
+++ b/__tests__/sponsor-page.test.tsx
@@ -20,98 +20,30 @@ jest.mock("next/link", () => {
});
describe("Sponsor Page", () => {
- it("renders the sponsor page", () => {
- const { container } = render();
- expect(container).toBeInTheDocument();
- });
-
- it("displays the hero heading", () => {
- render();
- expect(
- screen.getByText("Support the Agent Ecosystem")
- ).toBeInTheDocument();
- });
+ it("renders hero and core sections", async () => {
+ const jsx = await SponsorPage();
+ render(jsx);
- it("displays the mission statement", () => {
- render();
- expect(
- screen.getByText(/forAgents.dev is built by the community/)
- ).toBeInTheDocument();
+ expect(screen.getByText("Support the Agent Ecosystem")).toBeInTheDocument();
+ expect(screen.getByText("Sponsor Tiers")).toBeInTheDocument();
+ expect(screen.getByText("Why Sponsor?")).toBeInTheDocument();
+ expect(screen.getByText("Current Sponsors")).toBeInTheDocument();
});
- it("displays all sponsor tiers", () => {
- render();
- const individualTiers = screen.getAllByText("Individual");
- const teamTiers = screen.getAllByText("Team");
- const enterpriseTiers = screen.getAllByText("Enterprise");
- const customTiers = screen.getAllByText("Custom");
-
- expect(individualTiers.length).toBeGreaterThan(0);
- expect(teamTiers.length).toBeGreaterThan(0);
- expect(enterpriseTiers.length).toBeGreaterThan(0);
- expect(customTiers.length).toBeGreaterThan(0);
- });
+ it("shows tier pricing", async () => {
+ const jsx = await SponsorPage();
+ render(jsx);
- it("displays tier prices", () => {
- render();
expect(screen.getByText("$5")).toBeInTheDocument();
expect(screen.getByText("$25")).toBeInTheDocument();
expect(screen.getByText("$100")).toBeInTheDocument();
});
- it("displays sponsor CTA buttons", () => {
- render();
- const sponsorButtons = screen.getAllByText("Sponsor");
- expect(sponsorButtons.length).toBeGreaterThan(0);
- });
-
- it("displays the Why Sponsor section", () => {
- render();
- expect(screen.getByText("Why Sponsor?")).toBeInTheDocument();
- });
-
- it("displays all four benefit cards", () => {
- render();
- expect(screen.getByText("Visibility")).toBeInTheDocument();
- expect(screen.getByText("Priority Support")).toBeInTheDocument();
- expect(screen.getByText("Early Access")).toBeInTheDocument();
- expect(screen.getByText("Community Recognition")).toBeInTheDocument();
- });
-
- it("displays the Our Sponsors section", () => {
- render();
- expect(screen.getByText("Our Sponsors")).toBeInTheDocument();
- });
-
- it("displays impact stats", () => {
- render();
- expect(screen.getByText("Skills Funded")).toBeInTheDocument();
- expect(screen.getByText("Agents Supported")).toBeInTheDocument();
- expect(screen.getByText("Community Members")).toBeInTheDocument();
- });
-
- it("displays impact stat values", () => {
- render();
- expect(screen.getByText("127")).toBeInTheDocument();
- expect(screen.getByText("2,400+")).toBeInTheDocument();
- expect(screen.getByText("18,000+")).toBeInTheDocument();
- });
-
- it("displays sponsor tier badges", () => {
- render();
- // Check that tier names appear in the tier cards
- const tierCards = screen.getAllByText("Individual");
- expect(tierCards.length).toBeGreaterThan(0);
- });
-
- it("displays the final CTA section", () => {
- render();
- expect(screen.getByText("Ready to make an impact?")).toBeInTheDocument();
- });
+ it("renders CTA buttons", async () => {
+ const jsx = await SponsorPage();
+ render(jsx);
- it("displays contact link", () => {
- render();
- const contactButtons = screen.getAllByText("Contact Us");
- expect(contactButtons.length).toBeGreaterThan(0);
+ expect(screen.getAllByText("Apply").length).toBeGreaterThan(0);
+ expect(screen.getByText("Become a Sponsor")).toBeInTheDocument();
});
});
diff --git a/__tests__/status-page.test.tsx b/__tests__/status-page.test.tsx
index 5d7fc1e8..5250676d 100644
--- a/__tests__/status-page.test.tsx
+++ b/__tests__/status-page.test.tsx
@@ -1,7 +1,7 @@
/** @jest-environment jsdom */
import React from "react";
-import { render, screen } from "@testing-library/react";
+import { render, screen, waitFor } from "@testing-library/react";
import StatusPage from "../src/app/status/page";
type LinkProps = {
@@ -19,107 +19,67 @@ jest.mock("next/link", () => {
return LinkMock;
});
+const statusPayload = {
+ services: [
+ {
+ name: "API",
+ status: "operational",
+ latencyMs: 42,
+ lastCheck: "2026-02-09T12:00:00.000Z",
+ },
+ {
+ name: "Website",
+ status: "degraded",
+ latencyMs: 180,
+ lastCheck: "2026-02-09T12:00:00.000Z",
+ },
+ ],
+ overall: "degraded",
+};
+
+const historyPayload = {
+ history: [
+ { date: "2026-02-03", uptime: 99.9, incidents: 0 },
+ { date: "2026-02-04", uptime: 99.5, incidents: 1 },
+ ],
+};
+
describe("Status Page", () => {
beforeEach(() => {
jest.useFakeTimers();
+ global.fetch = jest.fn(async (input: RequestInfo | URL) => {
+ const url = String(input);
+ if (url.includes("/api/status/history")) {
+ return { ok: true, json: async () => historyPayload } as Response;
+ }
+ if (url.includes("/api/status")) {
+ return { ok: true, json: async () => statusPayload } as Response;
+ }
+ return { ok: false, json: async () => ({}) } as Response;
+ }) as jest.Mock;
});
afterEach(() => {
+ jest.runOnlyPendingTimers();
jest.useRealTimers();
});
- it("renders the status page", () => {
- const { container } = render();
- expect(container).toBeInTheDocument();
- });
-
- it("displays the page title", () => {
- render();
- expect(screen.getByText("System Status")).toBeInTheDocument();
- });
-
- it("displays overall status banner", () => {
+ it("renders title and services after fetch", async () => {
render();
- expect(screen.getByText("All Systems Operational")).toBeInTheDocument();
- });
- it("displays all service components", () => {
- render();
- // Service names appear in both the services section and incident affected services
- const apiElements = screen.getAllByText("API");
- expect(apiElements.length).toBeGreaterThan(0);
- const websiteElements = screen.getAllByText("Website");
- expect(websiteElements.length).toBeGreaterThan(0);
- const mcpElements = screen.getAllByText("MCP Registry");
- expect(mcpElements.length).toBeGreaterThan(0);
- const supabaseElements = screen.getAllByText("Supabase");
- expect(supabaseElements.length).toBeGreaterThan(0);
- const cdnElements = screen.getAllByText("CDN");
- expect(cdnElements.length).toBeGreaterThan(0);
- });
-
- it("displays services section heading", () => {
- render();
- expect(screen.getByText("Services")).toBeInTheDocument();
- });
-
- it("displays uptime metrics", () => {
- render();
- const uptimeElements = screen.getAllByText(/Uptime \(30d\)/i);
- expect(uptimeElements.length).toBeGreaterThan(0);
- });
-
- it("displays response time metrics", () => {
- render();
- const responseTimeElements = screen.getAllByText(/Response Time/i);
- expect(responseTimeElements.length).toBeGreaterThan(0);
- });
-
- it("displays incident history section", () => {
- render();
- expect(screen.getByText("Incident History")).toBeInTheDocument();
- });
-
- it("displays at least 5 incidents", () => {
- render();
- // Check for resolved badge which should appear for each incident
- const resolvedBadges = screen.getAllByText(/resolved/i);
- expect(resolvedBadges.length).toBeGreaterThanOrEqual(5);
- });
-
- it("displays incident titles", () => {
- render();
- expect(screen.getByText("Brief API Latency Spike")).toBeInTheDocument();
- expect(
- screen.getByText("CDN Cache Invalidation Issue")
- ).toBeInTheDocument();
- });
-
- it("displays affected services for incidents", () => {
- render();
- // "Affected Services:" appears multiple times (once per incident)
- const affectedServicesElements = screen.getAllByText("Affected Services:");
- expect(affectedServicesElements.length).toBeGreaterThanOrEqual(5);
- });
-
- it("displays subscribe to updates section", () => {
- render();
- expect(screen.getByText("Stay Updated")).toBeInTheDocument();
- });
+ expect(screen.getByText("System Status")).toBeInTheDocument();
- it("displays last updated timestamp", () => {
- render();
- expect(screen.getByText(/Last updated:/)).toBeInTheDocument();
+ await waitFor(() => {
+ expect(screen.getByText("Some Systems Degraded")).toBeInTheDocument();
+ expect(screen.getByText("API")).toBeInTheDocument();
+ expect(screen.getByText("Website")).toBeInTheDocument();
+ expect(screen.getByText("Uptime (Last 7 Days)")).toBeInTheDocument();
+ });
});
it("renders structured data for SEO", () => {
const { container } = render();
const scriptTag = container.querySelector('script[type="application/ld+json"]');
expect(scriptTag).toBeInTheDocument();
- if (scriptTag) {
- const jsonLd = JSON.parse(scriptTag.textContent || "{}");
- expect(jsonLd["@type"]).toBe("WebPage");
- expect(jsonLd.name).toContain("Status");
- }
});
});
diff --git a/__tests__/untested-pages-render.test.tsx b/__tests__/untested-pages-render.test.tsx
index 45869d8a..5f6b3102 100644
--- a/__tests__/untested-pages-render.test.tsx
+++ b/__tests__/untested-pages-render.test.tsx
@@ -160,6 +160,10 @@ jest.mock("@/components/skill-page-client", () => ({
SkillPageClient: () => ,
}));
+jest.mock("@/components/skill-install-cta", () => ({
+ SkillInstallCta: () => ,
+}));
+
// Mock subscribe success client (uses useSearchParams)
jest.mock("@/app/subscribe/success/success-client", () => ({
SubscribeSuccessClient: () => ,
@@ -305,17 +309,53 @@ jest.mock("@/lib/testimonials", () => ({
],
}));
-// Mock fetch - return ok: false for unknown API calls (triggers notFound in pages)
+// Mock fetch with route-aware defaults for page render tests
const originalFetch = global.fetch;
beforeAll(() => {
- (global as Record).fetch = jest.fn(() =>
- Promise.resolve({
+ (global as Record).fetch = jest.fn((input: RequestInfo | URL) => {
+ const url = String(input);
+
+ if (url.includes('/api/blog/example-post')) {
+ return Promise.resolve({
+ ok: true,
+ status: 200,
+ json: () =>
+ Promise.resolve({
+ slug: 'example-post',
+ title: 'Example Post',
+ excerpt: 'Example excerpt',
+ content: '# Heading\nBody copy',
+ tags: ['example'],
+ author: 'Team',
+ publishedAt: '2026-01-01T00:00:00.000Z',
+ readingTime: '3 min read',
+ }),
+ });
+ }
+
+ if (url.includes('/api/blog?sort=recent')) {
+ return Promise.resolve({
+ ok: true,
+ status: 200,
+ json: () => Promise.resolve({ posts: [], total: 0 }),
+ });
+ }
+
+ if (url.includes('/api/changelog')) {
+ return Promise.resolve({
+ ok: true,
+ status: 200,
+ json: () => Promise.resolve({ entries: [], total: 0 }),
+ });
+ }
+
+ return Promise.resolve({
ok: false,
status: 404,
json: () => Promise.resolve({}),
- text: () => Promise.resolve(""),
- })
- );
+ text: () => Promise.resolve(''),
+ });
+ });
});
afterAll(() => {
global.fetch = originalFetch;
@@ -397,6 +437,13 @@ describe("Untested Pages – Render Tests", () => {
test.each(syncPages)("/%s renders without crashing", async (_name, importFn) => {
const mod = await importFn();
const Page = mod.default;
+
+ if (Page?.constructor?.name === "AsyncFunction") {
+ const { container } = await renderServerComponent(Page as (...args: unknown[]) => unknown);
+ expect(container).toBeInTheDocument();
+ return;
+ }
+
const { container } = render();
expect(container).toBeInTheDocument();
});
@@ -418,8 +465,9 @@ describe("Untested Pages – Render Tests", () => {
test("/blog/[slug] renders without crashing", async () => {
const mod = await import("@/app/blog/[slug]/page");
- const Page = mod.default;
- const { container } = render();
+ const { container } = await renderServerComponent(mod.default, {
+ params: Promise.resolve({ slug: "example-post" }),
+ });
expect(container).toBeInTheDocument();
});