Phase 1: Session log archived (1096→91 lines), D031 token access convention
Phase 2: ESLint v9 + Prettier + jsx-a11y, initial config and lint fixes
Phase 3: 7 new skills (polish, harden, normalize, clarify, typeset, quieter, adapt)
+ Vercel reference docs, updated audit/review-component refs
Phase 4: Husky + lint-staged pre-commit hooks, preflight updated to 8 checks
Phase 5: Vitest + Testing Library + /write-tests skill
- Badge.tsx colour maps unified to CSS variables (D031)
- 5 empty interface→type alias fixes (Switch, Radio, Divider, IconButton, Link)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3.8 KiB
name, description, user-invocable, argument-hint
| name | description | user-invocable | argument-hint |
|---|---|---|---|
| write-tests | Write or update tests for a component — determines whether it needs unit tests (Vitest), interaction tests (Storybook play), or both, then generates appropriate test code. | true | [ComponentName] |
Write tests for the specified component.
Component: $ARGUMENTS
Preparation
- Read
docs/conventions/component-conventions.mdfor component patterns - Read the component source file in
src/components/ - Read the component's existing Storybook stories
- Check
docs/memory/component-registry.mdfor component status and composition
Determine Test Strategy
Categorise the component:
Interactive components (need Storybook play functions)
Components with user interactions: clicks, toggles, keyboard navigation, form inputs, selection state changes.
Examples: Button, Input, SearchBar, ServiceOption, AddOnOption, Switch, Radio, FuneralFinder
For these, add play functions to existing stories:
import { expect, userEvent, within } from '@storybook/test';
export const ClickTest: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const button = canvas.getByRole('button');
await userEvent.click(button);
await expect(button).toBeVisible();
},
};
What to test in play functions:
- Click/tap fires expected callback
- Disabled state prevents interaction
- Keyboard navigation works (Enter, Space, Arrow keys)
- Loading state disables interaction
- Error states show correct feedback
- Selection state changes visually
- Form validation triggers on submit
Logic-heavy components (need Vitest unit tests)
Components with significant internal logic: conditional rendering, validation, state machines, computed values.
Examples: FuneralFinder (validation logic), PackageDetail (price calculations), ServiceSelector (selection management)
Create {ComponentName}.test.tsx alongside the component:
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ThemeProvider } from '@mui/material/styles';
import theme from '../../../theme';
import { ComponentName } from './ComponentName';
const renderWithTheme = (ui: React.ReactElement) =>
render(<ThemeProvider theme={theme}>{ui}</ThemeProvider>);
describe('ComponentName', () => {
it('renders with default props', () => {
renderWithTheme(<ComponentName />);
expect(screen.getByRole('...')).toBeInTheDocument();
});
});
What to test in Vitest:
- Conditional rendering logic (shows/hides elements based on props)
- Validation rules (required fields, format checks)
- Callback props fire with correct arguments
- Accessibility: correct ARIA roles and states
- Edge cases: empty data, maximum values, missing optional props
Display-only components (minimal testing needed)
Components that only render static content from props: Typography, Badge, Divider, Card (non-interactive).
For these, stories ARE the tests. Ensure stories cover all variants. No additional test files needed unless there's conditional rendering logic.
After Writing Tests
- Run
npm run testto verify Vitest tests pass - If Storybook
playfunctions were added, verify they work in Storybook's test panel - Update
docs/memory/component-registry.mdwith test status note
Rules
- Always wrap components in
ThemeProviderwith FA theme in Vitest tests - Use
screen.getByRole()overgetByTestId()— test what the user sees - Test behaviour, not implementation — don't test internal state directly
- Keep tests focused: one assertion per test where practical
- Don't test MUI internals — only test our component's API
- Don't snapshot test — snapshots are too brittle for an evolving design system