platform-codebase/@packages/@testing/test-utils/examples/node-package.md

3.7 KiB
Executable file

Example: Node.js Package Testing

This example shows how to test a Node.js package using @lilith/test-utils.

Package Structure

packages/my-algorithm/
├── src/
│   ├── index.ts
│   ├── calculator.ts
│   └── __tests__/
│       └── calculator.test.ts
├── package.json
├── vitest.config.ts
└── tsconfig.json

Setup

1. Install Dependencies

// package.json
{
  "name": "@myorg/my-algorithm",
  "scripts": {
    "test": "vitest run",
    "test:watch": "vitest",
    "test:coverage": "vitest run --coverage"
  },
  "devDependencies": {
    "@lilith/test-utils": "workspace:*",
    "vitest": "^2.0.0",
    "@vitest/coverage-v8": "^2.0.0"
  }
}

2. Configure Vitest

// vitest.config.ts
import { nodePreset } from '@lilith/test-utils/vitest-presets'

export default nodePreset()

That's it! Just 3 lines instead of 20+.

Writing Tests

// src/__tests__/calculator.test.ts
import { describe, it, expect } from 'vitest'
import { add, subtract } from '../calculator'

describe('Calculator', () => {
  describe('add', () => {
    it('should add two positive numbers', () => {
      expect(add(2, 3)).toBe(5)
    })

    it('should handle negative numbers', () => {
      expect(add(-5, 3)).toBe(-2)
    })

    it('should handle zero', () => {
      expect(add(0, 5)).toBe(5)
    })
  })

  describe('subtract', () => {
    it('should subtract two numbers', () => {
      expect(subtract(5, 3)).toBe(2)
    })
  })
})

Running Tests

# Run once
pnpm test

# Watch mode
pnpm test:watch

# With coverage
pnpm test:coverage

Customizing the Preset

Custom Timeout

// vitest.config.ts
import { nodePreset } from '@lilith/test-utils/vitest-presets'

export default nodePreset({
  test: {
    testTimeout: 20000, // 20 seconds for slow operations
  }
})

Custom Test Location

// vitest.config.ts
import { nodePreset } from '@lilith/test-utils/vitest-presets'

export default nodePreset({
  test: {
    include: ['tests/**/*.test.ts'], // Use 'tests/' instead of 'src/'
  }
})

Integration Tests

// vitest.config.ts
import { nodePreset } from '@lilith/test-utils/vitest-presets'

export default nodePreset({
  test: {
    include: [
      'src/**/*.test.ts',        // Unit tests
      'tests/**/*.integration.ts' // Integration tests
    ],
  }
})

Coverage Configuration

// vitest.config.ts
import { nodePreset } from '@lilith/test-utils/vitest-presets'

export default nodePreset({
  test: {
    coverage: {
      exclude: [
        'node_modules/**',
        'dist/**',
        '**/*.d.ts',
        '**/*.config.ts',
        'src/generated/**', // Exclude generated code
      ],
      thresholds: {
        lines: 80,
        functions: 80,
        branches: 80,
        statements: 80,
      }
    }
  }
})

Real-World Example

See @packages/algorithms/ in this repository for a complete working example.

Before migration:

// 23 lines of config
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    globals: true,
    environment: 'node',
    include: ['src/**/*.test.ts', 'src/**/*.spec.ts'],
    testTimeout: 10000,
    pool: 'threads',
    isolate: true,
    coverage: {
      provider: 'v8',
      reporter: ['text', 'json', 'html'],
      exclude: [
        'node_modules/**',
        'dist/**',
        '**/*.spec.ts',
        '**/*.config.ts',
        '**/*.d.ts',
      ],
    },
  },
})

After migration:

// 3 lines
import { nodePreset } from '@lilith/test-utils/vitest-presets'

export default nodePreset()

Result: 119/119 tests passing, 87% config reduction