Files

4.1 KiB

Agent Skill: toldo-tdd-vitest

Metadata

name: toldo-tdd-vitest
description: Workflow TDD con Vitest para Vite+Capacitor. Mock de plugins, fake-indexeddb, Testing Library. Ciclo Red-Green-Refactor estricto.

When to use

Use this skill when:

  • Writing tests
  • Implementing features with TDD
  • Setting up test infrastructure
  • Mocking dependencies (Capacitor plugins, Dexie)
  • Testing components

TDD Workflow (Red-Green-Refactor)

For Domain/Core (MANDATORY TDD)

  1. RED: Write a failing test that describes the behavior
  2. GREEN: Write minimal code to make the test pass
  3. REFACTOR: Improve code while keeping tests green
  4. REPEAT: Next test case

For Data/Services

Write tests, can use mocks/fake DB. Still prefer test-first when possible.

For UI

Test behavior and user interactions, not implementation details.

Setup

Dependencies

{
  "devDependencies": {
    "vitest": "^1.0.0",
    "jsdom": "^23.0.0",
    "@testing-library/vue": "^8.0.0", // or @testing-library/react/svelte
    "@testing-library/user-event": "^14.0.0",
    "fake-indexeddb": "^5.0.0"
  }
}

vitest.config.ts

import { defineConfig } from 'vitest/config';
import path from 'path';

export default defineConfig({
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: ['./tests/setup.ts'],
  },
  resolve: {
    alias: {
      '@core': path.resolve(__dirname, '../../packages/core/src'),
      '@data': path.resolve(__dirname, '../../packages/data/src'),
      '@services': path.resolve(__dirname, '../../packages/services/src'),
      '@ui': path.resolve(__dirname, '../../packages/ui/src'),
    },
  },
});

tests/setup.ts

import 'fake-indexeddb/auto';

Mocking Capacitor Plugins

NEVER test against real Capacitor plugins. Always mock.

import { vi } from 'vitest';

vi.mock('@capacitor/core', () => ({
  Capacitor: {
    isNativePlatform: () => false,
    getPlatform: () => 'web',
  },
}));

vi.mock('@capacitor/filesystem', () => ({
  Filesystem: {
    writeFile: vi.fn(),
    readFile: vi.fn(),
  },
}));

Testing with Dexie (fake-indexeddb)

import { describe, it, expect, beforeEach } from 'vitest';
import { db } from '../db';

describe('ProductorRepository', () => {
  beforeEach(async () => {
    await db.delete();
    await db.open();
  });

  it('should create productor', async () => {
    // test...
  });
});

Testing UI Components

Use @testing-library best practices:

  • Query by role, label, text (accessible queries)
  • Use userEvent for interactions
  • Test behavior, not implementation
  • Avoid testing internal state
import { render, screen } from '@testing-library/vue';
import userEvent from '@testing-library/user-event';
import Button from './Button.vue';

it('calls onClick when clicked', async () => {
  const user = userEvent.setup();
  const onClick = vi.fn();
  render(Button, { props: { onClick } });
  
  await user.click(screen.getByRole('button'));
  expect(onClick).toHaveBeenCalled();
});

Commands

# Run tests in watch mode (TDD)
npm test -- --watch

# Run all tests
npm test

# Run with coverage
npm test -- --coverage

# Run specific file
npm test path/to/file.test.ts

Rules

  • Core tests: Pure unit tests, no mocks needed, fast
  • Data tests: Use fake-indexeddb, test in isolation
  • Services tests: Mock repositories
  • UI tests: Use Testing Library, mock services/composables
  • Capacitor: Always mock in unit/integration tests
  • No tests in APK/emulator for initial development - web tests are sufficient
  • Keep tests fast - if slow, something is wrong
  • One assertion concept per test when possible

TDD Checklist

  • Test written before implementation (for core)
  • Test fails initially (RED)
  • Minimal implementation makes it pass (GREEN)
  • Code refactored (REFACTOR)
  • All tests still pass
  • Test is meaningful and tests behavior

Resources