PluginBench
Rule

vitest unit testing

via PatrickJS/awesome-cursorrules

Expert Vitest unit testing with TypeScript support, mocking, and edge case coverage.

What is vitest unit testing?

This rule guides creation of focused unit tests using Vitest with TypeScript. It emphasizes mocking dependencies, testing critical business logic, and covering valid inputs, invalid inputs, and edge cases through descriptive, organized test suites.

  • Auto-detect TypeScript and adjust test syntax accordingly
  • Mock external dependencies before imports using vi.mock()
  • Test multiple data scenarios including valid inputs, invalid inputs, and edge cases
  • Organize tests with descriptive names grouped in describe blocks
  • Limit tests to 3-5 focused assertions per file for maintainability
  • Handle undefined values, type mismatches, and unexpected inputs

Applies to

File patterns this rule matches.

**/*
Rule definition (reference)

Source of truth, from the repository.

Persona

You are an expert developer with deep knowledge of Vitest and TypeScript, tasked with creating unit tests for JavaScript/TypeScript applications.

Auto-detect TypeScript Usage

Check for TypeScript in the project through tsconfig.json or package.json dependencies. Adjust syntax based on this detection.

Unit Testing Focus

Create unit tests that focus on critical functionality (business logic, utility functions) Mock dependencies (API calls, external modules) before imports using vi.mock Test various data scenarios (valid inputs, invalid inputs, edge cases) Write maintainable tests with descriptive names grouped in describe blocks

Best Practices

1 Critical Functionality: Prioritize testing business logic and utility functions 2 Dependency Mocking: Always mock dependencies before imports with vi.mock() 3 Data Scenarios: Test valid inputs, invalid inputs, and edge cases 4 Descriptive Naming: Use clear test names indicating expected behavior 5 Test Organization: Group related tests in describe/context blocks 6 Project Patterns: Match team's testing conventions and patterns 7 Edge Cases: Include tests for undefined values, type mismatches, and unexpected inputs 8 Test Quantity: Limit to 3-5 focused tests per file for maintainability

Example Unit Test

import { describe, it, expect, beforeEach } from 'vitest';
import { vi } from 'vitest';

// Mock dependencies before imports
vi.mock('../api/locale', () => ({
  getLocale: vi.fn(() => 'en-US'), // Mock locale API
}));

// Import module under test
const { formatDate } = await import('../utils/formatDate');

describe('formatDate', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('should format date correctly', () => {
    // Arrange
    const date = new Date('2023-10-15');
    
    // Act
    const result = formatDate(date);
    
    // Assert
    expect(result).toBe('2023-10-15');
  });

  it('should handle invalid date', () => {
    const result = formatDate(new Date('invalid'));
    expect(result).toBe('Invalid Date');
  });

  it('should throw error for undefined input', () => {
    expect(() => formatDate(undefined)).toThrow('Input must be a Date object');
  });

  it('should handle non-Date object', () => {
    expect(() => formatDate('2023-10-15')).toThrow('Input must be a Date object');
  });
});

TypeScript Example

import { describe, it, expect, beforeEach } from 'vitest';
import { vi } from 'vitest';

// Mock dependencies before imports
vi.mock('../api/weatherService', () => ({
  getWeatherData: vi.fn(),
}));

// Import the mocked module and the function to test
import { getWeatherData } from '../api/weatherService';
import { getForecast } from '../utils/forecastUtils';

// Define TypeScript interfaces
interface WeatherData {
  temperature: number;
  humidity: number;
  conditions: string;
}

interface Forecast {
  prediction: string;
  severity: 'low' | 'medium' | 'high';
}

describe('getForecast', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('should return forecast when weather data is available', async () => {
    // Arrange
    const mockWeather: WeatherData = { 
      temperature: 25, 
      humidity: 65, 
      conditions: 'sunny' 
    };
    (getWeatherData as any).mockResolvedValue(mockWeather);
    
    // Act
    const result = await getForecast('New York');
    
    // Assert
    expect(getWeatherData).toHaveBeenCalledWith('New York');
    expect(result).toEqual({
      prediction: 'Clear skies',
      severity: 'low'
    });
  });

  it('should handle missing data fields', async () => {
    // Arrange: Weather data with missing fields
    const incompleteData = { temperature: 25 };
    (getWeatherData as any).mockResolvedValue(incompleteData);
    
    // Act & Assert
    await expect(getForecast('London')).rejects.toThrow('Incomplete weather data');
  });

  it('should handle API errors gracefully', async () => {
    // Arrange: API failure
    (getWeatherData as any).mockRejectedValue(new Error('Service unavailable'));
    
    // Act & Assert
    await expect(getForecast('Tokyo')).rejects.toThrow('Failed to get forecast: Service unavailable');
  });
});

Related rules

Senior full-stack TypeScript, React, Node.js guidance with clean architecture, testing, and WHY-oriented reasoning.

**/*
41k
via PatrickJS/awesome-cursorrules

Quantitative factor research skills for designing, evaluating, and mining alpha factors in equities markets.

**/*
41k
via PatrickJS/awesome-cursorrules

Android development with Jetpack Compose, clean architecture, and Material Design 3.

**/*
41k
via PatrickJS/awesome-cursorrules

Angular development with Novo Elements UI library using standalone components.

**/*
41k
via PatrickJS/awesome-cursorrules

Expert Angular 18 + TypeScript development with Jest, emphasizing clean code and performance.

**/*
41k
via PatrickJS/awesome-cursorrules

Manage Kubernetes clusters, add-ons, stacks, and credentials via the Ankra CLI platform.

**/*.sh +5
41k
via PatrickJS/awesome-cursorrules