test-generation

star 502

Generate comprehensive test cases for code

vinilana By vinilana schedule Updated 3/22/2026

type: skill name: Test Generation description: Generate comprehensive test cases for code skillSlug: test-generation phases: [E, V] generated: 2026-03-18 status: filled scaffoldVersion: "2.0.0"

Test Generation

Generate and maintain tests for the @dotcontext/cli project using Jest with ts-jest.

When to Use

  • Writing tests for new services, generators, or utilities
  • Adding test coverage for MCP gateway handlers
  • Creating integration tests for CLI commands
  • Validating bug fixes with regression tests
  • During Execution (E) and Validation (V) phases

Test Configuration

  • Framework: Jest with ts-jest preset
  • Config: jest.config.js at project root
  • Test location: Co-located with source files (*.test.ts) or in __tests__/ directories
  • Test match patterns: **/__tests__/**/*.ts, **/?(*.)+(spec|test).ts
  • Root: src/
# Run all tests
npm test

# Run specific test file
npx jest src/services/mcp/mcpServer.test.ts

# Run tests matching a pattern
npx jest --testPathPattern="mcp"

# Run with coverage
npx jest --coverage

Test Patterns by Layer

Service Tests

Services are the most common test target. Follow the pattern in current service and MCP tests:

import * as os from 'os';
import * as path from 'path';
import * as fs from 'fs-extra';
import { MyService } from './myService';
import type { CLIInterface } from '../../utils/cliUI';
import type { TranslateFn } from '../../utils/i18n';

// Create temp directory for isolation
let tempDir: string;

beforeEach(async () => {
  tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'test-'));
});

afterEach(async () => {
  await fs.remove(tempDir);
});

// Mock CLI interface
function createMockUI(): CLIInterface {
  return {
    displayWelcome: jest.fn(),
    displayProjectInfo: jest.fn(),
    displayStep: jest.fn(),
    displaySuccess: jest.fn(),
    displayWarning: jest.fn(),
    displayError: jest.fn(),
    // ... other CLIInterface methods
  };
}

// Mock translate function
const mockT: TranslateFn = ((key: string) => key) as TranslateFn;

Key patterns:

  • Temp directories: Always use fs.mkdtemp() and clean up in afterEach
  • Mock CLIInterface: Provide a mock with jest.fn() for each method
  • Mock TranslateFn: Simple passthrough (key) => key
  • Mock tool or gateway boundaries: Use jest.mock() at module level for filesystem, prompt loaders, or MCP helpers

MCP Gateway Handler Tests

Test handlers directly, not through MCP transport:

import { handleExplore, ExploreParams } from './gateway/explore';

describe('handleExplore', () => {
  let tempDir: string;

  beforeEach(async () => {
    tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'explore-'));
    await fs.writeFile(path.join(tempDir, 'test.ts'), 'export const x = 1;');
  });

  afterEach(async () => {
    await fs.remove(tempDir);
  });

  it('should read a file', async () => {
    const result = await handleExplore(
      { action: 'read', filePath: path.join(tempDir, 'test.ts') },
      { repoPath: tempDir }
    );

    const payload = JSON.parse(result.content[0].text);
    expect(payload.success).toBe(true);
    expect(payload.content).toContain('export const x');
  });

  it('should return error for missing file', async () => {
    const result = await handleExplore(
      { action: 'read', filePath: path.join(tempDir, 'missing.ts') },
      { repoPath: tempDir }
    );

    expect(result.isError).toBe(true);
  });
});

Generator Tests

Test that generators produce correct file structures:

import { SkillGenerator } from './skillGenerator';

describe('SkillGenerator', () => {
  let tempDir: string;

  beforeEach(async () => {
    tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'gen-'));
  });

  it('should generate skill directories', async () => {
    const generator = new SkillGenerator({ repoPath: tempDir });
    const result = await generator.generate({ skills: ['commit-message'] });

    expect(result.generatedSkills).toContain('commit-message');
    expect(fs.existsSync(path.join(tempDir, '.context/skills/commit-message/SKILL.md'))).toBe(true);
  });

  it('should skip existing skills when force is false', async () => {
    const generator = new SkillGenerator({ repoPath: tempDir });
    await generator.generate({ skills: ['commit-message'] });
    const result = await generator.generate({ skills: ['commit-message'], force: false });

    expect(result.skippedSkills).toContain('commit-message');
  });
});

Utility Tests

Test pure functions directly:

import { parseFrontMatter, isScaffoldFrontmatter } from './frontMatter';

describe('frontMatter', () => {
  it('should parse v2 scaffold frontmatter', () => {
    const content = `---
type: skill
name: Test
status: filled
scaffoldVersion: "2.0.0"
---
# Content`;

    const result = parseFrontMatter(content);
    expect(isScaffoldFrontmatter(result)).toBe(true);
    expect(result.status).toBe('filled');
  });
});

Workflow Tests

Test phase transitions and gate logic:

import { GateChecker } from './gateChecker';

describe('GateChecker', () => {
  it('should block P->R transition when plan required but missing', () => {
    const checker = new GateChecker({ require_plan: true });
    const result = checker.canAdvance('P', 'R', { hasPlan: false });

    expect(result.allowed).toBe(false);
    expect(result.reason).toContain('plan');
  });
});

What to Mock

Dependency Mock Strategy Example
MCP tools / gateway helpers jest.mock() at module level MCP service tests
File system (for isolation) Use fs.mkdtemp() temp dirs All service tests
Prompt loader jest.mock('../../utils/promptLoader') Return test prompt
CLI interface Manual mock object createMockUI() helper
Translate function Passthrough (key) => key All CLI-facing tests
tree-sitter (optional dep) Test with and without Semantic analysis tests

Test Checklist

  • Tests are co-located with source or in __tests__/
  • File name matches pattern: <name>.test.ts
  • External dependencies are mocked (AI, file system, network)
  • Temp directories created in beforeEach, removed in afterEach
  • Both success and error paths are tested
  • Edge cases covered: empty input, missing files, malformed frontmatter
  • Tests run independently (no shared mutable state between tests)
  • TypeScript types verified at compile time (npm run build)

Integration Tests

For end-to-end testing of current interfaces, see src/cli.test.ts and src/services/mcp/mcpServer.test.ts:

// Integration tests verify current CLI help surfaces and MCP tool registration

Integration tests are slower and may require:

  • Real .context/ directory structure
  • Actual file writes (in temp dirs)
  • Mocked AI responses (but real service orchestration)

Run integration tests separately if needed:

npx jest --testPathPattern="integration"
Install via CLI
npx skills add https://github.com/vinilana/dotcontext --skill test-generation
Repository Details
star Stars 502
call_split Forks 91
navigation Branch main
article Path SKILL.md
More from Creator