Przejdź do treści
Biblioteka skilli
Programowanie · Testowanie

vitest-test

/vitest-test

Tworzy testy integracyjne Vitest dla tras API, server actions i komponentów Next.js z Testcontainers do zewnętrznych zależności.

Licencja
Apache-2.0
Ostatnia zmiana repozytorium
25.09.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
4
Skrypty
3
Komentarze HTML
0
Adresy URL w SKILL.md
4
Przestarzałość

Brak sygnałów. Repozytorium zmienione 25.09.2026, bez odwołań do wycofanych modeli i API.

Licencja

Apache-2.0, otwarta: można używać i zmieniać, z zachowaniem licencji i informacji o zmianach.

Co sprawdzić przed instalacją
  • 3 skrypty w paczce. Przejrzyj je przed instalacją, bo Claude może je uruchomić.

Skrypty: templates/example.test.ts, templates/global-setup.ts, templates/test-prisma.ts

Co robi i kiedy

Tworzy testy integracyjne Vitest dla tras API, server actions i komponentów Next.js z Testcontainers do zewnętrznych zależności.

Wyzwalacze z opisu

write integration teststest with a real databasecreate Vitest integration tests
Oryginalny opis (EN)

Creates Vitest integration tests for Next.js API route handlers, server actions, and components using Testcontainers for external dependencies. Use when the user asks to "write integration tests", "test with a real database", "create Vitest integration tests", or mentions Vitest integration testing or Testcontainers. Unit tests are created by the implement skill.

Jak działa

  1. Instructions
  2. DO NOT
  3. Nexa Rules Gate
  4. Worktree Gate
  5. Test Data Conventions
  6. Testcontainers Global Setup
  7. Test Data Strategy
  8. Templates
  9. Common Patterns
  10. Assertions Reference
Sekcje z nagłówków SKILL.md, w oryginale · 289 linii, 1 102 słów
Podgląd SKILL.md
---
name: vitest-test
description: >
  Creates Vitest integration tests for Next.js API route handlers,
  server actions, and components using Testcontainers for external dependencies.
  Use when the user asks to "write integration tests", "test with a real database",
  "create Vitest integration tests", or mentions Vitest integration testing or
  Testcontainers. Unit tests are created by the implement skill.
---

# Vitest Integration Test

## Instructions

Create Vitest integration tests for Next.js API routes, server actions, and components based on the use case $ARGUMENTS.
Unit tests are already created by the `/implement` skill — this skill focuses on integration tests that hit real dependencies via Testcontainers.

Use the context7 MCP server for Next.js documentation when needed.

## DO NOT

- Test implementation details (test behavior, not internals)
- Use `any` type in test code
- Skip error case testing
- Mock Prisma Client — integration tests use a real database via Testcontainers
- Hard-code database connection strings — `DATABASE_URL` is injected by global setup

## Nexa Rules Gate

Read and follow `${CLAUDE_PLUGIN_ROOT}/shared/readiness/NEXA_RULES_GATE.md`.

## Worktree Gate

Read and follow `${CLAUDE_PLUGIN_ROOT}/shared/readiness/WORKTREE_GATE.md`.

## Test Data Conventions

- Use only `example.com` for test emails and accounts (e.g., `user@example.com`, `admin@example.com`). This is an IANA-reserved domain that will never route real mail.

## Testcontainers Global Setup

Before writing tests, ensure the project has a global setup file that starts a PostgreSQL
Testcontainer, runs Prisma migrations, and exports the `DATABASE_URL`.

If `src/test/global-setup.ts` does not exist, create it using [templates/global-setup.ts](templates/global-setup.ts).

If `src/test/test-prisma.ts` does not exist, create it using [templates/test-prisma.ts](templates/test-prisma.ts).

Ensure `vitest.config.ts` references the global setup:

```typescript
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
import tsconfigPaths from 'vite-tsconfig-paths';

export default defineConfig({
  plugins: [react(), tsconfigPaths()],
  test: {
    environment: 'jsdom',
    globalSetup: ['src/test/global-setup.ts'],
    setupFiles: ['src/test/setup.ts'],
    env: {
      // Load static test variables; DATABASE_URL is set by global setup
      NODE_ENV: 'test',
    },
    coverage: {
      provider: 'v8',
      include: ['src/**/*.{ts,tsx}'],
      exclude: [
        'src/test/**',
        'src/**/*.test.{ts,tsx}',
        'src/**/*.d.ts',
        'src/**/generated/**',
      ],
      thresholds: {
        statements: 80,
        branches: 80,
        functions: 80,
        lines: 80,
      },
    },
  },
});
```

Ensure `src/test/setup.ts` exists to load `.env.test` for static variables:

```typescript
import { loadEnvFile } from 'node:process';

try {
  loadEnvFile('.env.test');
} catch {
  // .env.test is optional — DATABASE_URL comes from global setup
}
```

## Test Data Strategy

| Approach        | Location                      | Purpose              |
|-----------------|-------------------------------|----------------------|
| Prisma seed     | prisma/seed.ts                | Baseline test data   |
| Test fixtures   | src/test/fixtures/            | Reusable test data   |
| Inline creation | Within test setup             | Test-specific data   |
| Manual cleanup  | afterEach / afterAll hooks    | Remove created data  |

## Templates

- Global setup: [templates/global-setup.ts](templates/global-setup.ts)
- Prisma test client: [templates/test-prisma.ts](templates/test-prisma.ts)
- Test example: [templates/example.test.ts](templates/example.test.ts)

## Common Patterns

### API Route Handler Tests

```typescript
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { GET, POST } from '@/app/api/examples/route';
import { NextRequest } from 'next/server';
import { getTestPrisma } from '@/test/test-prisma';

const prisma = getTestPrisma();

describe('GET /api/examples', () => {
  afterEach(async () => {
    await prisma.example.deleteMany();
  });

  it('should return all records', async () => {
    await prisma.example.createMany({
      data: [
        { name: 'Item 1', description: 'First item' },
        { name: 'Item 2', description: 'Second item' },
      ],
    });

    const request = new NextRequest('http://localhost/api/examples');
    const response = await GET(request);
    const body = await response.json();

    expect(response.status).toBe(200);
    expect(body).toHaveLength(2);
  });

  it('should return empty array when no records exist', async () => {
    const request = new NextRequest('http://localhost/api/examples');
    const response = await GET(request);
    const body = await response.json();

    expect(response.status).toBe(200);
    expect(body).toEqual([]);
  });
});

describe('POST /api/examples', () => {
  afterEach(async () => {
    await prisma.example.deleteMany();
  });

  it('should create a new record', async () => {
    const request = new NextRequest('http://localhost/api/examples', {
      method: 'POST',
      body: JSON.stringify({ name: 'New Item', description: 'A new item' }),
    });
    const response = await POST(request);
    const body = await response.json();

    expect(response.status).toBe(201);
    expect(body.name).toBe('New Item');

    // Verify it was persisted
    const stored = await prisma.example.findFirst({ where: { name: 'New Item' } });
    expect(stored).not.toBeNull();
  });

  it('should return 400 for invalid input', async () => {
    const request = new NextRequest('http://localhost/api/examples', {
      method: 'POST',
      body: JSON.stringify({ description: 'Missing name' }),
    });
    const response = await POST(request);

    expect(response.status).toBe(400);
  });
});
```

### Server Action Tests

```typescript
import { describe, it, expect, vi, afterEach } from 'vitest';
import { createExample } from '@/app/actions/examples';
import { getTestPrisma } from '@/test/test-prisma';
import { revalidatePath } from 'next/cache';

vi.mock('next/cache', () => ({
  revalidatePath: vi.fn(),
}));

const prisma = getTestPrisma();

describe('createExample', () => {
  afterEach(async () => {
    await prisma.example.deleteMany();
  });

  it('should create a record and revalidate', async () => {
    const formData = new FormData();
    formData.set('name', 'Test');
    formData.set('description', 'Desc');

    const result = await createExample(formData);

    expect(result.name).toBe('Test');
    expect(revalidatePath).toHaveBeenCalledWith('/examples');

    // Verify persistence
    const stored = await prisma.example.findFirst({ where: { name: 'Test' } });
    expect(stored).not.toBeNull();
  });
});
```

### Component Tests

```typescript
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ExampleForm } from '@/components/example-form';

describe('ExampleForm', () => {
  it('should call onSubmit with form data', async () => {
    const onSubmit = vi.fn();
    render(<ExampleForm onSubmit={onSubmit} />);

    await userEvent.type(screen.getByLabelText('Name'), 'Test');
    await userEvent.click(screen.getByRole('button', { name: 'Save' }));

    expect(onSubmit).toHaveBeenCalled();
  });

  it('should show validation error for empty name', async () => {
    render(<ExampleForm onSubmit={vi.fn()} />);

    await userEvent.click(screen.getByRole('button', { name: 'Save' }));

    expect(screen.getByText('Name is required')).toBeInTheDocument();
  });
});
```

## Assertions Reference

| Assertion Type      | Example                                           |
|---------------------|---------------------------------------------------|
| Defined             | `expect(result).toBeDefined()`                    |
| Equality            | `expect(result.name).toBe('Test')`                |
| Array length        | `expect(result).toHaveLength(5)`                  |
| Object match        | `expect(result).toMatchObject({ name: 'Test' })`  |
| Exception           | `await expect(fn()).rejects.toThrow(Error)`        |
| HTTP status         | `expect(response.status).toBe(200)`               |
| Called with         | `expect(fn).toHaveBeenCalledWith('/path')`         |
| DOM element         | `expect(screen.getByText('Hi')).toBeInTheDocument()` |
| Not null            | `expect(result).not.toBeNull()`                   |

## Workflow

1. Read the use case specification
2. Use TodoWrite to create a task for each test scenario
3. Ensure Testcontainers global setup exists (`src/test/global-setup.ts`); create from template if missing
4. Ensure test Prisma client exists (`src/test/test-prisma.ts`); create from template if missing
5. Ensure `vitest.config.ts` references the global setup
6. Create test file using the template
7. For each test:
    - Set up test data using the real Prisma client from `src/test/test-prisma.ts`
    - Create test input (NextRequest, FormData, or component props)
    - Execute the operation under test
    - Assert expected outcomes (including database persistence where applicable)
    - Clean up test data in afterEach/afterAll hooks
8. Only mock Next.js framework modules (`next/cache`, `next/navigation`) — never mock Prisma
9. Run the `/code-quality` skill
10. Run tests with `npx vitest run` to verify they pass
11. Run tests with coverage to verify thresholds: `npx vitest run --coverage`
    - If coverage falls below 80% on any metric (statements, branches, functions, lines), add tests until thresholds are met
    - Focus on uncovered branches and functions first — they have the highest impact on coverage
12. If a test fails:
    - Check that Testcontainers started successfully (Docker must be running)
    - Verify Prisma migrations are up to date
    - Ensure async operations are properly awaited
    - Check test data cleanup is not interfering with other tests
13. Mark todos complete

## Resources

- Use the context7 MCP server for Next.js documentation
Pliki w paczce (4)
  • SKILL.md 10 KB
  • templates/example.test.ts 2 KB
  • templates/global-setup.ts 1 KB
  • templates/test-prisma.ts 1 KB

Wersje

W bazie nie ma innych skilli o nazwie vitest-test.

Migawka bazy z 28.10.2026 · wersja paczki 5a837e1a5262 (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 100integration-test
    Tworzy testy integracyjne w Go dla handlerów net/http, serwisów i zapytań sqlc na prawdziwej bazie PostgreSQL uruchamianej przez testcontainers-go.
  • 100vitest-testing-patterns
    Pisze testy w Vitest i React Testing Library: testy jednostkowe, komponentów i integracyjne, mockowanie zależności, pokrycie i dobre praktyki.
  • 100vitest-testing-patterns
    Pisze testy w Vitest i React Testing Library: testy jednostkowe, komponentów i integracyjne, mockowanie zależności, pokrycie i dobre praktyki.
  • 100testcontainers
    Pomaga uruchamiać testy integracyjne z prawdziwymi zależnościami w kontenerach Docker zarządzanych przez Testcontainers, na przykład z prawdziwą bazą danych.
  • 100frontend-testing
    Generuje testy Vitest i React Testing Library dla komponentów, hooków i funkcji pomocniczych we frontendzie, w tym pliki spec, pokrycie kodu oraz testy jednostkowe i integracyjne.
  • 90Vitest
    Pomaga pisać testy w Vitest dla aplikacji opartych na Vite: jednostkowe i integracyjne, mocki, pokrycie, React Testing Library i testy TypeScript.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.