tdd-vitest-typescript

Test-Driven Development (TDD) using Vitest and TypeScript. Use when the user requests help with TDD, writing tests before code, test-first development, Vitest test setup, TypeScript testing patterns, unit testing, integration testing, or following the Red-Green-Refactor cycle with Vitest.

242 stars

Best use case

tdd-vitest-typescript is best used when you need a repeatable AI agent workflow instead of a one-off prompt. It is especially useful for teams working in multi. Test-Driven Development (TDD) using Vitest and TypeScript. Use when the user requests help with TDD, writing tests before code, test-first development, Vitest test setup, TypeScript testing patterns, unit testing, integration testing, or following the Red-Green-Refactor cycle with Vitest.

Test-Driven Development (TDD) using Vitest and TypeScript. Use when the user requests help with TDD, writing tests before code, test-first development, Vitest test setup, TypeScript testing patterns, unit testing, integration testing, or following the Red-Green-Refactor cycle with Vitest.

Users should expect a more consistent workflow output, faster repeated execution, and less time spent rewriting prompts from scratch.

Practical example

Example input

Use the "tdd-vitest-typescript" skill to help with this workflow task. Context: Test-Driven Development (TDD) using Vitest and TypeScript. Use when the user requests help with TDD, writing tests before code, test-first development, Vitest test setup, TypeScript testing patterns, unit testing, integration testing, or following the Red-Green-Refactor cycle with Vitest.

Example output

A structured workflow result with clearer steps, more consistent formatting, and an output that is easier to reuse in the next run.

When to use this skill

  • Use this skill when you want a reusable workflow rather than writing the same prompt again and again.

When not to use this skill

  • Do not use this when you only need a one-off answer and do not need a reusable workflow.
  • Do not use it if you cannot install or maintain the related files, repository context, or supporting tools.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/tdd-vitest-typescript/SKILL.md --create-dirs "https://raw.githubusercontent.com/aiskillstore/marketplace/main/skills/emz1998/tdd-vitest-typescript/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/tdd-vitest-typescript/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How tdd-vitest-typescript Compares

Feature / Agenttdd-vitest-typescriptStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Test-Driven Development (TDD) using Vitest and TypeScript. Use when the user requests help with TDD, writing tests before code, test-first development, Vitest test setup, TypeScript testing patterns, unit testing, integration testing, or following the Red-Green-Refactor cycle with Vitest.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# TDD with Vitest and TypeScript

Guide Claude through Test-Driven Development workflows using Vitest and TypeScript.

## Core TDD Cycle: Red-Green-Refactor

Always follow this three-phase cycle:

1. **Red**: Write a failing test that defines desired behavior
2. **Green**: Write minimal code to make the test pass
3. **Refactor**: Improve code quality while keeping tests green

### Workflow Pattern

```typescript
// 1. RED: Write the test first
describe('Calculator', () => {
  it('adds two numbers', () => {
    const calc = new Calculator();
    expect(calc.add(2, 3)).toBe(5);
  });
});

// Run test → Watch it fail (Red)
// 2. GREEN: Implement minimal code
class Calculator {
  add(a: number, b: number): number {
    return a + b;
  }
}

// Run test → Watch it pass (Green)
// 3. REFACTOR: Improve if needed while keeping tests green
```

## Vitest Setup and Configuration

### Basic Vitest Config

Create `vitest.config.ts`:

```typescript
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true,
    environment: 'node', // or 'jsdom' for DOM testing
    coverage: {
      provider: 'v8',
      reporter: ['text', 'json', 'html'],
    },
  },
});
```

### TypeScript Configuration

Ensure `tsconfig.json` includes:

```json
{
  "compilerOptions": {
    "types": ["vitest/globals"],
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}
```

## Test File Organization

### Naming Conventions

- Test files: `*.test.ts` or `*.spec.ts`
- Place tests adjacent to source files or in `__tests__` directories
- Match test file names to source files: `calculator.ts` → `calculator.test.ts`

### Structure Pattern

```typescript
import { describe, it, expect, beforeEach, afterEach } from 'vitest';

describe('FeatureName', () => {
  // Setup
  beforeEach(() => {
    // Runs before each test
  });

  afterEach(() => {
    // Cleanup after each test
  });

  describe('specific behavior', () => {
    it('does something specific', () => {
      // Arrange
      const input = setupTestData();
      
      // Act
      const result = performAction(input);
      
      // Assert
      expect(result).toBe(expected);
    });
  });
});
```

## TypeScript Testing Patterns

### Type-Safe Test Data

```typescript
interface User {
  id: number;
  name: string;
  email: string;
}

function createTestUser(overrides?: Partial<User>): User {
  return {
    id: 1,
    name: 'Test User',
    email: 'test@example.com',
    ...overrides,
  };
}

it('processes user data', () => {
  const user = createTestUser({ name: 'Custom Name' });
  expect(processUser(user)).toBeDefined();
});
```

### Testing Generic Functions

```typescript
describe('generic array utilities', () => {
  it('filters array by predicate', () => {
    const numbers = [1, 2, 3, 4, 5];
    const result = filter(numbers, (n: number) => n > 3);
    expect(result).toEqual([4, 5]);
  });
});
```

### Testing Async/Promise Code

```typescript
describe('async operations', () => {
  it('fetches user data', async () => {
    const user = await fetchUser(1);
    expect(user.id).toBe(1);
  });

  it('handles errors', async () => {
    await expect(fetchUser(-1)).rejects.toThrow('Invalid ID');
  });
});
```

## Mocking and Stubbing

### Module Mocks

```typescript
import { vi } from 'vitest';
import { fetchData } from './api';

vi.mock('./api');

describe('data processing', () => {
  it('processes fetched data', async () => {
    vi.mocked(fetchData).mockResolvedValue({ data: 'test' });
    
    const result = await processData();
    expect(result).toBe('processed: test');
  });
});
```

### Function Spies

```typescript
describe('event handling', () => {
  it('calls callback on event', () => {
    const callback = vi.fn();
    const handler = new EventHandler(callback);
    
    handler.trigger('test-event');
    
    expect(callback).toHaveBeenCalledWith('test-event');
    expect(callback).toHaveBeenCalledTimes(1);
  });
});
```

### Partial Mocks

```typescript
import * as utils from './utils';

vi.spyOn(utils, 'helperFunction').mockReturnValue('mocked');

it('uses mocked helper', () => {
  const result = mainFunction();
  expect(utils.helperFunction).toHaveBeenCalled();
  expect(result).toContain('mocked');
});
```

## Common Testing Patterns

### Testing Classes

```typescript
describe('UserService', () => {
  let service: UserService;
  let mockRepository: MockRepository;

  beforeEach(() => {
    mockRepository = new MockRepository();
    service = new UserService(mockRepository);
  });

  it('creates user with valid data', async () => {
    const userData = { name: 'John', email: 'john@example.com' };
    
    const user = await service.createUser(userData);
    
    expect(user.id).toBeDefined();
    expect(mockRepository.save).toHaveBeenCalledWith(
      expect.objectContaining(userData)
    );
  });
});
```

### Testing Pure Functions

```typescript
describe('pure utility functions', () => {
  it('capitalizes first letter', () => {
    expect(capitalize('hello')).toBe('Hello');
    expect(capitalize('')).toBe('');
    expect(capitalize('WORLD')).toBe('WORLD');
  });
});
```

### Testing Error Handling

```typescript
describe('error scenarios', () => {
  it('throws on invalid input', () => {
    expect(() => divide(10, 0)).toThrow('Division by zero');
  });

  it('returns error result', () => {
    const result = parseJSON('invalid json');
    expect(result.success).toBe(false);
    expect(result.error).toBeDefined();
  });
});
```

### Parametric Tests

```typescript
import { describe, it, expect } from 'vitest';

describe.each([
  { input: 2, expected: 4 },
  { input: 3, expected: 9 },
  { input: 4, expected: 16 },
])('square function', ({ input, expected }) => {
  it(`squares ${input} to ${expected}`, () => {
    expect(square(input)).toBe(expected);
  });
});
```

## Test Coverage Guidelines

### Running Coverage

```bash
vitest --coverage
```

### Coverage Targets

- Aim for 80%+ coverage on business logic
- 100% coverage on critical paths (authentication, payments, etc.)
- Don't obsess over 100% everywhere—focus on meaningful tests

### What to Test

**Always test:**
- Business logic and domain rules
- Error handling and edge cases
- Public APIs and interfaces
- Data transformations

**Consider skipping:**
- Simple getters/setters
- Framework/library code
- Trivial type definitions
- Configuration files

## TDD Best Practices

### Write Tests First

Always start with the test, not the implementation:

```typescript
// ❌ BAD: Writing implementation first
class Calculator {
  add(a: number, b: number) { return a + b; }
}

// ✅ GOOD: Test first
it('adds two numbers', () => {
  expect(new Calculator().add(2, 3)).toBe(5);
});
```

### One Assertion Per Test

Keep tests focused:

```typescript
// ❌ BAD: Multiple concerns
it('user operations', () => {
  const user = createUser();
  expect(user.id).toBeDefined();
  expect(updateUser(user)).toBeTruthy();
  expect(deleteUser(user.id)).toBeUndefined();
});

// ✅ GOOD: Single concern
it('creates user with ID', () => {
  const user = createUser();
  expect(user.id).toBeDefined();
});

it('updates existing user', () => {
  const user = createUser();
  expect(updateUser(user)).toBeTruthy();
});
```

### Test Behavior, Not Implementation

```typescript
// ❌ BAD: Testing implementation details
it('calls internal helper method', () => {
  const service = new Service();
  const spy = vi.spyOn(service as any, '_internalHelper');
  service.process();
  expect(spy).toHaveBeenCalled();
});

// ✅ GOOD: Testing behavior
it('processes data correctly', () => {
  const service = new Service();
  const result = service.process(inputData);
  expect(result).toEqual(expectedOutput);
});
```

### Keep Tests Fast

- Use mocks for external dependencies (databases, APIs, file system)
- Avoid sleep/setTimeout in tests
- Run expensive setup once with beforeAll when safe

### Descriptive Test Names

```typescript
// ❌ BAD: Vague
it('works', () => { /* ... */ });

// ✅ GOOD: Descriptive
it('returns empty array when no users match filter criteria', () => {
  /* ... */
});
```

## Common TDD Workflow

### Starting a New Feature

1. Write a high-level test describing the feature:

```typescript
describe('User Registration', () => {
  it('creates new user account with valid email', async () => {
    const result = await registerUser({
      email: 'new@example.com',
      password: 'secure123',
    });
    
    expect(result.success).toBe(true);
    expect(result.user.email).toBe('new@example.com');
  });
});
```

2. Run test → See it fail (Red)
3. Implement minimal code → See it pass (Green)
4. Add edge case tests:

```typescript
it('rejects registration with existing email', async () => {
  await registerUser({ email: 'existing@example.com', password: 'pass' });
  
  const result = await registerUser({
    email: 'existing@example.com',
    password: 'pass2',
  });
  
  expect(result.success).toBe(false);
  expect(result.error).toContain('Email already registered');
});

it('rejects weak passwords', async () => {
  const result = await registerUser({
    email: 'new@example.com',
    password: '123',
  });
  
  expect(result.success).toBe(false);
  expect(result.error).toContain('Password too weak');
});
```

5. Refactor implementation while keeping tests green

### Debugging Failed Tests

When tests fail unexpectedly:

1. Check test isolation—are tests interfering with each other?
2. Verify mocks are properly reset between tests
3. Use `it.only()` to run single test
4. Add console.log or debugger statements
5. Check async timing issues

## Integration Testing with Vitest

### Testing Multiple Units Together

```typescript
describe('Order Processing Integration', () => {
  let database: TestDatabase;
  let paymentGateway: MockPaymentGateway;
  let orderService: OrderService;

  beforeEach(async () => {
    database = await TestDatabase.create();
    paymentGateway = new MockPaymentGateway();
    orderService = new OrderService(database, paymentGateway);
  });

  afterEach(async () => {
    await database.cleanup();
  });

  it('completes order flow from cart to confirmation', async () => {
    const user = await database.createUser();
    const cart = await orderService.createCart(user.id);
    await orderService.addItem(cart.id, { productId: 1, quantity: 2 });
    
    paymentGateway.simulateSuccess();
    const order = await orderService.checkout(cart.id);
    
    expect(order.status).toBe('confirmed');
    expect(order.items).toHaveLength(1);
  });
});
```

## Watch Mode

Vitest runs in watch mode by default during development:

```bash
vitest
```

This automatically re-runs tests when files change, enabling rapid TDD cycles.

## Quick Reference: Common Matchers

```typescript
// Equality
expect(value).toBe(5);                    // Strict equality (===)
expect(value).toEqual({ a: 1 });          // Deep equality

// Truthiness
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeNull();
expect(value).toBeUndefined();
expect(value).toBeDefined();

// Numbers
expect(value).toBeGreaterThan(3);
expect(value).toBeLessThan(10);
expect(value).toBeCloseTo(0.3);           // Floating point

// Strings
expect(string).toMatch(/pattern/);
expect(string).toContain('substring');

// Arrays
expect(array).toContain(item);
expect(array).toHaveLength(3);

// Objects
expect(object).toHaveProperty('key');
expect(object).toMatchObject({ a: 1 });   // Partial match

// Exceptions
expect(() => fn()).toThrow();
expect(() => fn()).toThrow('Error message');
expect(async () => fn()).rejects.toThrow();

// Functions
expect(fn).toHaveBeenCalled();
expect(fn).toHaveBeenCalledWith(arg1, arg2);
expect(fn).toHaveBeenCalledTimes(2);
```

## Tips for Effective TDD

1. **Start simple**: Begin with the simplest test case, not the most complex
2. **Take small steps**: Write one test, make it pass, refactor, repeat
3. **Trust the process**: Resist urge to write implementation before tests
4. **Refactor fearlessly**: With good test coverage, refactoring is safe
5. **Keep tests maintainable**: Tests are code too—keep them clean and DRY
6. **Run tests frequently**: Vitest's watch mode makes this effortless
7. **Write tests for bugs**: When you find a bug, write a test that exposes it first

## When to Use This Skill

Apply TDD when:
- Building new features from scratch
- Fixing bugs (write failing test first)
- Refactoring existing code
- Learning a new API or library
- Working on critical business logic

TDD is especially valuable for:
- Pure functions and algorithms
- Business logic and domain models
- Data transformations
- API endpoints and services

Related Skills

openapi-to-typescript

242
from aiskillstore/marketplace

Converts OpenAPI 3.0 JSON/YAML to TypeScript interfaces and type guards. This skill should be used when the user asks to generate types from OpenAPI, convert schema to TS, create API interfaces, or generate TypeScript types from an API specification.

typescript-pro

242
from aiskillstore/marketplace

Master TypeScript with advanced types, generics, and strict type safety. Handles complex type systems, decorators, and enterprise-grade patterns. Use PROACTIVELY for TypeScript architecture, type inference optimization, or advanced typing patterns.

typescript-expert

242
from aiskillstore/marketplace

TypeScript and JavaScript expert with deep knowledge of type-level programming, performance optimization, monorepo management, migration strategies, and modern tooling. Use PROACTIVELY for any TypeScript/JavaScript issues including complex type gymnastics, build performance, debugging, and architectural decisions. If a specialized expert is a better fit, I will recommend switching and stop.

typescript-advanced-types

242
from aiskillstore/marketplace

Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript projects.

javascript-typescript-typescript-scaffold

242
from aiskillstore/marketplace

You are a TypeScript project architecture expert specializing in scaffolding production-ready Node.js and frontend applications. Generate complete project structures with modern tooling (pnpm, Vite, N

dbos-typescript

242
from aiskillstore/marketplace

DBOS TypeScript SDK for building reliable, fault-tolerant applications with durable workflows. Use this skill when writing TypeScript code with DBOS, creating workflows and steps, using queues, using DBOSClient from external applications, or building applications that need to be resilient to failures.

typescript-write

242
from aiskillstore/marketplace

Write TypeScript and JavaScript code following Metabase coding standards and best practices. Use when developing or refactoring TypeScript/JavaScript code.

typescript-review

242
from aiskillstore/marketplace

Review TypeScript and JavaScript code changes for compliance with Metabase coding standards, style violations, and code quality issues. Use when reviewing pull requests or diffs containing TypeScript/JavaScript code.

typescript-node-expert

242
from aiskillstore/marketplace

Expert TypeScript/Node.js developer for building high-quality, performant, and maintainable CLI tools and libraries. Enforces best practices, strict typing, and modern patterns.

typescript-dev

242
from aiskillstore/marketplace

TypeScript development best practices, code quality tools, and documentation templates. Activated when working with .ts, .tsx files or TypeScript projects.

typescript-strict

242
from aiskillstore/marketplace

Strict TypeScript rules. Use when writing ANY TypeScript.

typescript-strict-guard

242
from aiskillstore/marketplace

Use when writing or reviewing TypeScript code. Enforces strict mode standards, explicit typing, and best practices. Prevents 'any' types, @ts-ignore comments, and non-null assertions. This is a COMPREHENSIVE skill - consult the detailed guides before writing any TypeScript code.