home / skills / physics91 / claude-vibe / test-generator

test-generator skill

/skills/test-generator

This skill automatically generates tests by detecting the project framework and applying appropriate Jest, Vitest, RTL, or Playwright templates.

npx playbooks add skill physics91/claude-vibe --skill test-generator

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
5.7 KB
---
name: test-generator
description: |
  WHEN: Test code generation, unit/integration/E2E test writing, component/hook/utility tests
  WHAT: Framework detection + Jest/Vitest/RTL/Playwright templates + Happy Path/Edge/Error case tests
  WHEN NOT: Coverage analysis → coverage-analyzer, Test quality review → code-reviewer
---

# Test Generator Skill

## Purpose
Automatically generates tests by detecting project test framework and applying appropriate patterns.

## When to Use
- Test generation requests
- New component/function needs tests
- Unit, E2E, integration test mentions
- Coverage improvement needed

## Framework Detection

### Test Runners
| Framework | Detection | package.json |
|-----------|-----------|--------------|
| Jest | `jest.config.*` | `jest` |
| Vitest | `vitest.config.*` | `vitest` |
| Playwright | `playwright.config.*` | `@playwright/test` |
| Cypress | `cypress.config.*` | `cypress` |

### Test Libraries
| Library | Purpose | package.json |
|---------|---------|--------------|
| RTL | React components | `@testing-library/react` |
| Vue Test Utils | Vue components | `@vue/test-utils` |

## Workflow

### Step 1: Detect Environment
```
**Runner**: Jest
**Library**: React Testing Library
**Config**: jest.config.js
**Test Dir**: __tests__/, *.test.tsx
```

### Step 2: Select Target
**AskUserQuestion:**
```
"Which code to test?"
Options:
- Specific file/component
- Auto-detect untested files
- Recently changed files
- Entire directory
```

### Step 3: Select Test Type
**AskUserQuestion:**
```
"What type of tests?"
Options:
- Unit Test
- Integration Test
- Component Test
- E2E Test (Playwright/Cypress)
```

### Step 4: Coverage Goal
**AskUserQuestion:**
```
"Coverage goal?"
Options:
- Happy Path only
- Happy Path + Edge Cases
- Full (including errors)
- Specify scenarios
```

## Test Templates

### React Component (Jest + RTL)
```typescript
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { Component } from './Component'

describe('Component', () => {
  const defaultProps = { /* ... */ }
  const renderComponent = (props = {}) =>
    render(<Component {...defaultProps} {...props} />)

  describe('Rendering', () => {
    it('renders with default state', () => {
      renderComponent()
      expect(screen.getByRole('button')).toBeInTheDocument()
    })
  })

  describe('Interactions', () => {
    it('calls callback on click', async () => {
      const onClick = jest.fn()
      renderComponent({ onClick })
      await userEvent.click(screen.getByRole('button'))
      expect(onClick).toHaveBeenCalledTimes(1)
    })
  })

  describe('Edge Cases', () => {
    it('handles empty data', () => {
      renderComponent({ data: [] })
      expect(screen.getByText('No data')).toBeInTheDocument()
    })
  })
})
```

### React Hook
```typescript
import { renderHook, act, waitFor } from '@testing-library/react'
import { useCustomHook } from './useCustomHook'

describe('useCustomHook', () => {
  it('returns initial state', () => {
    const { result } = renderHook(() => useCustomHook())
    expect(result.current.value).toBe(initialValue)
  })

  it('updates state', () => {
    const { result } = renderHook(() => useCustomHook())
    act(() => { result.current.setValue('new') })
    expect(result.current.value).toBe('new')
  })
})
```

### Utility Function
```typescript
import { utilityFunction } from './utils'

describe('utilityFunction', () => {
  it('processes valid input', () => {
    expect(utilityFunction('valid')).toBe('expected')
  })

  describe('Edge Cases', () => {
    it('handles empty string', () => {
      expect(utilityFunction('')).toBe('')
    })

    it('handles null', () => {
      expect(utilityFunction(null)).toBeNull()
    })
  })

  describe('Errors', () => {
    it('throws on invalid input', () => {
      expect(() => utilityFunction(undefined)).toThrow()
    })
  })
})
```

### E2E (Playwright)
```typescript
import { test, expect } from '@playwright/test'

test.describe('User Flow: Login', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/login')
  })

  test('logs in successfully', async ({ page }) => {
    await page.getByLabel('Email').fill('[email protected]')
    await page.getByLabel('Password').fill('password123')
    await page.getByRole('button', { name: 'Login' }).click()
    await expect(page).toHaveURL('/dashboard')
  })

  test('shows error on invalid credentials', async ({ page }) => {
    await page.getByLabel('Email').fill('[email protected]')
    await page.getByLabel('Password').fill('wrong')
    await page.getByRole('button', { name: 'Login' }).click()
    await expect(page.getByRole('alert')).toContainText('Login failed')
  })
})
```

## Response Template
```
## Tests Generated

**Target**: src/components/Button.tsx
**Output**: src/components/__tests__/Button.test.tsx
**Runner**: Jest + RTL

### Test Cases
| Category | Test | Description |
|----------|------|-------------|
| Rendering | Default render | Renders correctly |
| Interaction | Click event | onClick callback |
| Edge Case | Long text | Overflow handling |

### Run
\`\`\`bash
npm test -- Button.test.tsx
npm test -- --coverage Button.test.tsx
\`\`\`

### Expected Coverage
- Lines: ~90%
- Branches: ~85%
- Functions: ~100%
```

## Best Practices
1. **AAA Pattern**: Arrange-Act-Assert
2. **Clear Names**: Expected behavior in test name
3. **Independence**: Each test runs independently
4. **Minimal Mocking**: Mock only when necessary
5. **Real User Behavior**: Prefer user-event

## Integration
- `/generate-tests` command
- `coverage-analyzer` skill
- `code-reviewer` skill

## Notes
- Follows existing test patterns if present
- Test file location matches project structure
- Mocking based on actual implementation analysis

Overview

This skill generates tests automatically by detecting the project's test runner and libraries, then applying matching templates and patterns. It produces unit, integration, component, hook, utility, and E2E tests with happy-path, edge-case, and error-case variants. It targets practical, runnable test files placed to match your project structure.

How this skill works

The skill scans the repository for test runner configs and package.json entries to detect Jest, Vitest, Playwright, or Cypress, and for libraries like React Testing Library or Vue Test Utils. It asks which files or targets to test and what test types and coverage goals you want, then selects templates and fills them to produce ready-to-run test files. Generated tests follow project conventions, include mocks only when needed, and place files in the appropriate test directories.

When to use it

  • You need tests for a new component, hook, or utility.
  • You want unit, integration, or E2E tests generated quickly.
  • You want consistent test patterns across the codebase.
  • You need happy-path plus edge or error case coverage.
  • You want to bootstrap tests for recently changed or untested files.

Best practices

  • Follow AAA pattern: Arrange, Act, Assert in each test.
  • Name tests to describe expected behavior, not implementation.
  • Keep tests independent; avoid cross-test state and global leaks.
  • Mock minimally; prefer real user interactions via user-event or Playwright actions.
  • Match test file location and naming to existing project conventions.

Example use cases

  • Generate Jest + RTL tests for a React Button component with render, interaction, and edge cases.
  • Create renderHook tests for a custom React hook using renderHook and act.
  • Produce utility function tests covering valid inputs, edge cases, and thrown errors.
  • Create Playwright E2E tests for a login flow including success and invalid credential scenarios.
  • Auto-detect recently changed files and scaffold unit tests for uncovered logic.

FAQ

Which frameworks and libraries can it detect?

It detects Jest, Vitest, Playwright, and Cypress based on config files and package.json entries, and recognizes RTL and Vue Test Utils for component testing.

Can I control test scope and coverage level?

Yes. The skill prompts for target files or directories and lets you choose Happy Path, Edge Cases, Full (including errors), or custom scenarios before generating tests.