write-tests

von sentry

Schreibe Tests gemäß den Projektkonventionen. Verwende dies, wenn neue Tests hinzugefügt oder bestehende geändert werden.

npx skills add https://github.com/getsentry/abacus --skill write-tests

Write Tests Skill

Write tests using Vitest. Tests are colocated next to source files.

Structure

src/lib/utils.ts
src/lib/utils.test.ts        # colocated
src/app/api/stats/route.ts
src/app/api/stats/route.test.ts
src/test-utils/
├── setup.ts        # global setup (PGlite, MSW, auth mock)
├── msw-handlers.ts # external API mocks
└── auth.ts         # auth test helpers

Auth Testing

Auth is globally mocked. Use helpers to control auth state:

import { mockAuthenticated, mockUnauthenticated } from '@/test-utils/auth';

it('returns 401 when unauthenticated', async () => {
  await mockUnauthenticated();
  const response = await GET(new Request('http://localhost/api/foo'));
  expect(response.status).toBe(401);
});

it('returns data when authenticated', async () => {
  await mockAuthenticated(); // uses default test user
  // or with overrides:
  await mockAuthenticated({ email: 'custom@example.com' });

  const response = await GET(new Request('http://localhost/api/foo'));
  expect(response.status).toBe(200);
});

Default test user: test@example.com / Test User

Database Testing

Uses PGlite (in-memory PostgreSQL). No Docker required.

  • Schema pushed automatically on boot
  • Each test runs in a transaction that rolls back
  • Use insertUsageRecord from @/lib/queries to seed data
import { insertUsageRecord, getOverallStats } from '@/lib/queries';

beforeEach(async () => {
  await insertUsageRecord({
    date: '2025-01-01',
    email: 'user@example.com',
    tool: 'claude_code',
    model: 'sonnet-4',
    rawModel: 'claude-sonnet-4-20250514',
    inputTokens: 1000,
    outputTokens: 500,
    cacheWriteTokens: 0,
    cacheReadTokens: 0,
    cost: 0.01,
  });
});

Running Tests

pnpm test        # run all
pnpm test:watch  # watch mode

Key Rules

  1. Colocate tests next to source (foo.tsfoo.test.ts)
  2. Use mockAuthenticated()/mockUnauthenticated() for auth
  3. Use insertUsageRecord for seeding database
  4. External APIs mocked via MSW in src/test-utils/msw-handlers.ts

CRITICAL: Auth Tests Required

Every protected route MUST have an auth test. This is non-negotiable.

Session-Authenticated Routes

Routes using getSession() must verify 401 on unauthenticated requests:

it('returns 401 for unauthenticated requests', async () => {
  await mockUnauthenticated();
  const response = await GET(new Request('http://localhost/api/your-route'));
  expect(response.status).toBe(401);
});

Cron Routes

Routes using CRON_SECRET must verify auth:

beforeEach(() => {
  vi.stubEnv('CRON_SECRET', 'test-secret');
});

it('returns 401 without authorization header', async () => {
  const response = await GET(new Request('http://localhost/api/cron/your-route'));
  expect(response.status).toBe(401);
});

it('returns 401 with invalid authorization', async () => {
  const response = await GET(
    new Request('http://localhost/api/cron/your-route', {
      headers: { Authorization: 'Bearer wrong-secret' },
    })
  );
  expect(response.status).toBe(401);
});

Webhook Routes

Routes with signature verification must test invalid signatures:

it('returns 401 without signature', async () => {
  const response = await POST(
    new Request('http://localhost/api/webhooks/github', {
      method: 'POST',
      body: '{}',
    })
  );
  expect(response.status).toBe(401);
});

it('returns 401 with invalid signature', async () => {
  const response = await POST(
    new Request('http://localhost/api/webhooks/github', {
      method: 'POST',
      body: '{}',
      headers: { 'x-hub-signature-256': 'sha256=invalid' },
    })
  );
  expect(response.status).toBe(401);
});

When adding a new route, always ask: "What auth does this route require?" and add the corresponding auth test.

Mehr Skills von sentry

generate-frontend-forms
sentry
Leitfaden zur Erstellung von Formularen mit Sentrys neuem Formularsystem. Verwenden Sie dies bei der Implementierung von Formularen, Formularfeldern, Validierung oder Auto-Save-Funktionalität.
official
sentry-snapshots-cocoa
sentry
Vollständige Sentry-Snapshots-Einrichtung für Apple/Cocoa-Projekte. Verwenden, wenn aufgefordert, "SnapshotPreviews einzurichten", "Apple-Snapshot-Tests einzurichten", "Apple-Snapshots hochzuladen nach…
official
architecture-review
sentry
Codebase-Gesundheitsprüfung auf Mitarbeiterebene. Erkennt monolithische Module, stille Fehler, Typsicherheitslücken, Testabdeckungslücken und LLM-Freundlichkeitsprobleme.
official
linear-type-labeler
sentry
Klassifiziert Linear-Issues und weist ein Typ-Label aus der Label-Taxonomie des Sentry-Workspace zu, basierend auf dem Inhalt des Titels und der Beschreibung jedes Issues.
official
sentry-flutter-sdk
sentry
Vollständige Sentry SDK-Einrichtung für Flutter und Dart. Verwenden, wenn aufgefordert wird, "Sentry zu Flutter hinzuzufügen", "sentry_flutter zu installieren", "Sentry in Dart einzurichten" oder Fehlerkonfiguration…
official
sentry-svelte-sdk
sentry
Vollständige Sentry-SDK-Einrichtung für Svelte und SvelteKit. Verwenden, wenn aufgefordert wird, "Sentry zu Svelte hinzuzufügen", "Sentry zu SvelteKit hinzuzufügen", "@sentry/sveltekit zu installieren" oder zu konfigurieren…
official
vercel-react-best-practices
sentry
Richtlinien zur Leistungsoptimierung von React und Next.js von Vercel Engineering. Diese Fähigkeit sollte beim Schreiben, Überprüfen oder Refaktorisieren von React/Next.js…
official
sentry-tanstack-start-sdk
sentry
Vollständige Sentry SDK-Einrichtung für TanStack Start React. Verwenden, wenn aufgefordert wird, "Sentry zu TanStack Start hinzuzufügen", "@sentry/tanstackstart-react zu installieren" oder Fehlerkonfiguration…
official