write-tests

oleh sentry

Menulis tes sesuai dengan konvensi proyek. Gunakan saat menambahkan tes baru atau memodifikasi tes yang sudah ada.

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.

Lebih banyak skill dari sentry

generate-frontend-forms
sentry
Panduan untuk membuat formulir menggunakan sistem formulir baru Sentry. Gunakan saat mengimplementasikan formulir, kolom formulir, validasi, atau fungsionalitas penyimpanan otomatis.
official
sentry-snapshots-cocoa
sentry
Pengaturan lengkap Sentry Snapshots untuk proyek Apple/Cocoa. Gunakan saat diminta untuk "setup SnapshotPreviews", "setup Apple snapshot testing", "upload Apple snapshots to…
official
architecture-review
sentry
Tinjauan kesehatan basis kode setara staf. Menemukan modul monolitik, kegagalan diam, celah keamanan tipe, lubang cakupan pengujian, dan masalah keramahan LLM.
official
linear-type-labeler
sentry
Mengklasifikasikan isu Linear dan menerapkan label Tipe dari taksonomi label ruang kerja Sentry berdasarkan konten judul dan deskripsi setiap isu.
official
sentry-flutter-sdk
sentry
Pengaturan SDK Sentry lengkap untuk Flutter dan Dart. Gunakan saat diminta untuk "menambahkan Sentry ke Flutter", "menginstal sentry_flutter", "menyiapkan Sentry di Dart", atau mengonfigurasi error…
official
sentry-svelte-sdk
sentry
Pengaturan SDK Sentry lengkap untuk Svelte dan SvelteKit. Gunakan saat diminta untuk "menambahkan Sentry ke Svelte", "menambahkan Sentry ke SvelteKit", "menginstal @sentry/sveltekit", atau mengonfigurasi…
official
vercel-react-best-practices
sentry
Panduan optimasi performa React dan Next.js dari Vercel Engineering. Skill ini harus digunakan saat menulis, meninjau, atau merefaktor kode React/Next.js…
official
sentry-tanstack-start-sdk
sentry
Pengaturan SDK Sentry lengkap untuk TanStack Start React. Gunakan saat diminta untuk "menambahkan Sentry ke TanStack Start", "menginstal @sentry/tanstackstart-react", atau mengonfigurasi error…
official