| name | build-update-tests |
| version | 1.0.0 |
| description | Evaluate test coverage and create appropriate tests based on risk assessment. Use when user says "build tests", "update tests", "add test coverage", "write tests for this", or "improve test coverage". |
| allowed-tools | Read, Write, Edit, Bash, Grep, Glob, Task |
| context | fork |
Build/Update Tests
Evaluate test coverage and create appropriate tests based on risk assessment.
<when_to_use>
When to Use
Invoke when user says:
- "build tests"
- "update tests"
- "add test coverage"
- "write tests for this"
- "improve test coverage"
- "what tests do we need"
- "test this feature"
</when_to_use>
Workflow
| Phase | Action | Gate |
|---|
| 1 | Identify changed/new code | - |
| 2 | Assess risk level | - |
| 3 | Check existing coverage | - |
| 4 | Determine test types needed | User approval |
| 5 | Generate tests | - |
| 6 | Verify tests pass | Tests must pass |
<risk_matrix>
Risk Matrix
| Risk Level | Code Type | Required Tests |
|---|
| Critical | Auth, security, RLS policies | Unit + API contract + RLS tests |
| High | Mutations, data modifications | Unit + API contract tests |
| Medium | Queries, data fetching | Unit tests + edge cases |
| Low | Utils, formatters, pure functions | Unit tests |
Critical Code Patterns (Recept)
login(), signup(), password handling
- RLS policies in migrations
- JWT claim extraction
insert_recipe(), update_recipe() atomic operations
High Risk Patterns
- Any INSERT, UPDATE, DELETE operations
- State mutations
- Form submissions
- API route handlers
</risk_matrix>
<test_types>
Test Types
Unit Tests (vitest)
Location: Same directory as source, *.test.ts
Use for: Pure functions, utilities, components, hooks
import { describe, it, expect } from 'vitest'
import { formatRecipeTime } from './utils'
describe('formatRecipeTime', () => {
it('formats minutes correctly', () => {
expect(formatRecipeTime(90)).toBe('1h 30min')
})
it('handles zero', () => {
expect(formatRecipeTime(0)).toBe('0min')
})
})
API Contract Tests
Location: tests/api/*.test.ts
Use for: PostgREST endpoints, RLS verification
import { describe, it, expect, beforeAll } from 'vitest'
import { createTestClient } from '../helpers'
describe('GET /recipes', () => {
it('returns public recipes without auth', async () => {
const client = createTestClient()
const response = await client.get('/recipes')
expect(response.status).toBe(200)
expect(Array.isArray(response.data)).toBe(true)
})
})
RLS Tests
Location: tests/api/rls/*.test.ts
Use for: Row-level security policy verification
describe('recipes RLS', () => {
it('prevents users from modifying others recipes', async () => {
const userA = createTestClient({ email: 'a@test.com' })
const userB = createTestClient({ email: 'b@test.com' })
const recipe = await userA.post('/recipes', { title: 'Test' })
const response = await userB.delete(`/recipes?id=eq.${recipe.id}`)
expect(response.status).toBe(404)
})
})
Behavior Tests
Location: Component test files
Use for: User interactions, form submissions
import { render, screen, fireEvent } from '@testing-library/react'
import { RecipeForm } from './recipe-form'
describe('RecipeForm', () => {
it('validates required fields', async () => {
render(<RecipeForm />)
fireEvent.click(screen.getByText('Save'))
expect(await screen.findByText('Title is required')).toBeInTheDocument()
})
})
</test_types>
Phase 1: Identify Changed Code
git diff --name-only HEAD
git diff --name-only --diff-filter=A HEAD~5
git diff --name-only HEAD | grep -E '\.(ts|tsx)$' | grep -v '\.test\.'
Phase 2: Assess Risk Level
For each changed file:
- Read the file content
- Identify code patterns (see Risk Matrix)
- Assign risk level
Phase 3: Check Existing Coverage
ls -la [source-path].test.ts 2>/dev/null || echo "No test file"
grep -r "[function-or-endpoint-name]" tests/api/
Phase 4: Determine Test Types Needed
Based on risk and existing coverage:
| Scenario | Action |
|---|
| Critical code, no tests | Create all required test types |
| High risk, partial coverage | Add missing test types |
| Medium risk, no unit tests | Add unit tests |
| Low risk, no tests | Add basic unit tests |
| Existing tests, code changed | Update tests to match new behavior |
Present plan to user for approval.
Phase 5: Generate Tests
Follow project patterns:
- Use vitest (
describe, it, expect)
- Use existing test helpers from
tests/helpers/
- Match file naming:
[source].test.ts
- Co-locate unit tests with source
Phase 6: Verify Tests Pass
pnpm test --run [test-file-path]
pnpm check:test
<recept_patterns>
Recept Testing Patterns
Test Environment Setup
docker-compose -f docker-compose.test.yml up -d
pnpm check:api
Common Test Helpers
createTestClient(jwt?) — HTTP client for API tests
seedTestData() — Insert test fixtures
cleanupTestData() — Remove test data after run
Mocking
- Mock
fetch for external API calls
- Mock
cookies() for auth in server components
- Use MSW for complex API mocking if needed
Assertions
- PostgREST returns arrays by default
- Check
Content-Range header for pagination
- RLS may return 404 instead of 403
</recept_patterns>
<quick_reference>
Quick Reference
pnpm check:test
pnpm test --run [test-file-path]
docker-compose -f docker-compose.test.yml up -d
pnpm check:api
ls -la **/*.test.ts tests/api/
</quick_reference>
<approval_gates>
Approval Gates
| Gate | Phase | Question |
|---|
| Test plan | 4 | "Create these tests? [list test types per file]" |
| Test pass | 6 | "All tests pass. Commit with changes?" |
</approval_gates>