8.9 KiB
8.9 KiB
Testing Patterns
Analysis Date: 2026-04-20
Test Framework
Runner:
- Use
vitestviavitest.config.tsandpnpm testfrompackage.json. vitest.config.tssetsenvironment: "node", resolves@to./src, disables watch mode, and only includessrc/**/*.test.ts.- Current verification on 2026-04-20:
pnpm testpassed with 8 test files and 26 tests.
Assertion Library:
- Use Vitest built-ins from
vitest, includingdescribe,it,expect,beforeEach,afterEach, andvi, as seen insrc/lib/auth.test.ts,src/lib/prisma-url.test.ts, andsrc/app/api/tags/maintenance/route.test.ts.
Run Commands:
pnpm test # Run all configured Vitest suites
pnpm lint # Run ESLint quality checks
pnpm build # Run production build checks
AGENTS.mdalso reservespnpm test:e2efor Playwright, but notest:e2escript orplaywright.config.*file is present in the current workspace.
Test File Organization
Location:
- Keep tests co-located beside the code they exercise under
src, for examplesrc/lib/auth.test.ts,src/lib/prisma-url.test.ts,src/app/api/tags/route.test.ts, andsrc/app/api/tags/maintenance/service.test.ts. - No
e2e/directory is present in the repository snapshot analyzed on 2026-04-20.
Naming:
- Use
*.test.ts. No*.spec.tsor*.test.tsxfiles were detected byrg --filesor included byvitest.config.ts. - Keep route tests adjacent to
route.tsorservice.tsfiles, for examplesrc/app/api/tags/reset-projects/route.test.tsnext tosrc/app/api/tags/reset-projects/route.ts.
Structure:
src/
lib/
auth.ts
auth.test.ts
prisma-url.ts
prisma-url.test.ts
app/api/tags/
route.ts
route.test.ts
maintenance/
route.ts
route.test.ts
service.ts
service.test.ts
Test Structure
Suite Organization:
import { beforeEach, describe, expect, it, vi } from "vitest";
import { NextRequest } from "next/server";
import { POST } from "./route";
const { transactionMock, revalidatePathMock, txMock } = vi.hoisted(() => {
const tx = {
projectTag: {
deleteMany: vi.fn(),
createMany: vi.fn(),
},
};
return {
transactionMock: vi.fn(async (callback) => callback(tx)),
revalidatePathMock: vi.fn(),
txMock: tx,
};
});
Patterns:
- Use one top-level
describe(...)block per module or endpoint, with behavior-based test names such asreturns 401 for wrong API keyinsrc/app/api/tags/maintenance/route.test.tsandreturns 500 when prisma query failsinsrc/app/api/tags/route.test.ts. - Build local request helpers for route tests, such as
buildRequest(...)insrc/app/api/tags/maintenance/route.test.tsandsrc/app/api/tags/reset-projects/route.test.ts. - Use inline fixture builders for reusable payloads, such as
buildValidPayload(...)insrc/app/api/tags/reset-projects/route.test.tsandbaseProjectInputinsrc/lib/validations.test.ts. - Reset mocks and environment state in
beforeEachorafterEach, as seen insrc/app/api/tags/route.test.ts,src/app/api/tags/maintenance/route.test.ts, andsrc/lib/prisma-url.test.ts.
Mocking
Framework:
- Use Vitest mocks via
vi.fn,vi.mock,vi.hoisted,mockResolvedValue, andmockRejectedValue.
Patterns:
vi.mock("@/lib/prisma", () => ({
prisma: {
tag: {
findMany: findManyMock,
},
},
}));
vi.mock("next/cache", () => ({
revalidatePath: revalidatePathMock,
}));
- Hoist shared mocks before module import so route modules capture mocked dependencies, as in
src/app/api/tags/route.test.ts,src/app/api/tags/maintenance/route.test.ts, andsrc/app/api/tags/reset-projects/route.test.ts. - Mock Prisma reads and writes rather than using a real database in route tests.
- Mock
next/cacheside effects when mutation routes callrevalidatePath, as insrc/app/api/tags/maintenance/route.test.tsandsrc/app/api/tags/reset-projects/route.test.ts.
What to Mock:
- Mock Prisma modules for handler and service tests, as in
src/app/api/tags/route.test.ts,src/app/api/tags/maintenance/route.test.ts, andsrc/app/api/tags/reset-projects/route.test.ts. - Set
process.env.WEBHOOK_API_KEYinline for auth-path tests, as insrc/app/api/tags/maintenance/route.test.tsandsrc/app/api/tags/reset-projects/route.test.ts. - Mock cache revalidation side effects instead of asserting real filesystem or ISR behavior.
What NOT to Mock:
- Test pure helpers directly without mocks when possible, as in
src/lib/auth.test.tsandsrc/lib/validations.tag-maintenance.test.ts. - There is no current pattern for DOM, browser, or component mocking because no component tests are checked in.
Fixtures and Environment Handling
Test Data:
const baseProjectInput = {
name: "Agent Park",
description: "A curated list of practical AI agent tools.",
tags: [{ name: "ai-agent" }],
links: [{ type: "GITHUB" as const, url: "https://github.com/example/repo" }],
};
const ENV_KEYS = [
"DATABASE_URL",
"PG_SSL_ROOT_CERT_B64",
"PG_SSL_IDENTITY_P12_B64",
"PG_SSL_IDENTITY_PASSWORD",
"PG_SSL_MODE",
"PG_SSL_CERT_DIR",
] as const;
src/lib/prisma-url.test.tssnapshots selected env vars and restores them inafterEach, which is the current pattern for tests that mutateprocess.env.- Fixtures are inline per file. No shared
test-utilsor factory directory exists.
Coverage
Requirements:
- No coverage thresholds or coverage command are configured in
package.jsonorvitest.config.ts. - No CI workflow, coverage upload, or Playwright setup was detected under
.github/or repository root.
View Coverage:
Not configured
Test Types
Unit Tests:
- Pure utility coverage exists for
src/lib/auth.ts,src/lib/prisma-url.ts,src/lib/validations.ts, and tag-maintenance schema rules insrc/lib/validations.tag-maintenance.test.ts.
Service Tests:
- Business logic in
src/app/api/tags/maintenance/service.tsis tested separately insrc/app/api/tags/maintenance/service.test.ts, including deduped tag migration and validation failure behavior.
Route-Level Tests:
- Direct route-handler tests exist for
src/app/api/tags/route.ts,src/app/api/tags/maintenance/route.ts, andsrc/app/api/tags/reset-projects/route.ts. - These tests assert status codes, JSON bodies, auth failures, validation failures, and
revalidatePath(...)side effects.
n8n-Related Coverage:
src/app/api/search/ai/route.tshas no correspondingsrc/app/api/search/ai/route.test.ts.src/app/api/webhook/signals/route.tshas no correspondingsrc/app/api/webhook/signals/route.test.ts.- This means the n8n-facing search proxy and the authenticated signals webhook currently rely on runtime behavior rather than automated handler tests.
E2E Tests:
- Not detected.
AGENTS.mdreservese2e/for Playwright, but there is noe2e/directory, no Playwright config, and nopnpm test:e2escript inpackage.json.
Common Patterns
Async Route Testing:
const response = await POST(buildRequest(payload));
const json = await response.json();
expect(response.status).toBe(200);
expect(json.success).toBe(true);
Error Testing:
findManyMock.mockRejectedValue(new Error("db unavailable"));
const response = await GET();
const json = await response.json();
expect(response.status).toBe(500);
expect(json.error).toBe("Internal server error");
expect(json.details).toContain("db unavailable");
Current Gaps
Untested API Routes:
- No tests were detected for
src/app/api/projects/route.ts,src/app/api/projects/[slug]/route.ts,src/app/api/signals/route.ts,src/app/api/search/ai/route.ts, orsrc/app/api/webhook/signals/route.ts. - The missing n8n-related tests are especially important because
src/app/api/search/ai/route.tsdepends on theN8N_AI_SEARCH_WEBHOOKcontract andsrc/app/api/webhook/signals/route.tshandles authenticated ingestion plus Prisma upserts.
Untested Query and UI Modules:
- No tests were detected for
src/hooks/useProjects.ts,src/hooks/useHome.ts,src/lib/cache.ts,src/lib/signal-hotness.ts,src/lib/tag-taxonomy.ts,src/lib/github/badges.ts, or large client components undersrc/componentsandsrc/app/[locale].
Infrastructure Gaps:
- No shared fixture library, no DOM test environment, no Playwright harness, and no CI workflow files were detected.
Verification Signals
Current Quality Checks:
pnpm testpassed on 2026-04-20 with 8 test files and 26 tests.pnpm lintpassed on 2026-04-20 with no warnings or errors.
Observed Output Notes:
pnpm testprints expected stderr from the deliberate error-path assertion insrc/app/api/tags/route.test.tsbecausesrc/app/api/tags/route.tslogs failures withconsole.error.- The current Vitest run emits a Vite deprecation notice about the CJS Node API. This is a tooling signal, not a failing test.
Testing analysis: 2026-04-20