Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    getsentry

    write-tests

    getsentry/write-tests
    Coding
    64
    1 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Write tests following project conventions. Use when adding new tests or modifying existing ones.

    SKILL.md

    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.ts → foo.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.

    Recommended Servers
    Postman
    Postman
    OpenZeppelin
    OpenZeppelin
    Linear
    Linear
    Repository
    getsentry/abacus
    Files