Testing vitest
Skill Syo-M/codex-frontend-skills/plugins/codex-frontend-skills/skills/testing-vitest
Codex-native frontend skills, custom agents, profiles, and an evidence-backed evaluation harness for React, Next.js, Vite, and Astro.
npx -y skills add Syo-M/codex-frontend-skills --skill testing-vitestAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 24 days oldThe repository was created 24 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Vitest tests for pure logic and headless hooks/providers, plus config, MSW, mocks, and timers. Not for Storybook-owned visible behavior or Playwright journeys. 日本語の依頼例:「ユニットテスト」「Vitest」「モック」「ロジックのテスト」。
SKILL.md
4.0 KB, as published. Nobody here has run it
Vitest
What to test, where
- Pure logic (utils, reducers, schema transforms) → plain unit tests. Fast, no DOM.
- Component behavior → Storybook play functions are the primary component-test layer (see
storybookskill); write direct Testing Library tests only for headless hooks/providers with no visual states, or when exhaustively covering a pure prop/branch matrix (roughly ≥ 6 combinations) where one story per case would bloat the catalog — the meaningful visual states still get stories. - Full user flows → Playwright (see
testing-playwright). Don't simulate routing/auth flows in jsdom.
Worked examples (the layer decision people get wrong most):
- "Test that the Button shows a spinner while submitting" → Storybook play function — a visible state + interaction the catalog should own; not a Vitest component test.
- "Test that
formatCurrencyrounds half-up and handles -0" → Vitest unit test — pure logic, no DOM, no story. - "Test the
useDebouncehook's timing" → Vitest unit test with fake timers — headless hook, no visual state. - "Test the checkout form across 8 field-validation combinations" → Vitest for the exhaustive matrix, plus one story per meaningful visual state (empty / error / submitting) — don't make 8 stories.
- Test behavior users observe, not implementation: no asserting on state internals, no
container.querySelector('.styles_button_x'), no spying on internal functions of the unit under test.
Structure
- Colocate:
format.ts+format.test.ts. Name tests as behavior sentences:it('disables submit while the request is in flight'). - Arrange–Act–Assert, one behavior per test. Shared setup in a plain
setup()factory function returning what tests need — avoid sprawlingbeforeEachmutation. - No logic in tests (if/loops computing expectations). Expected values are literals.
Testing Library rules
- Query priority (same list as
testing-playwright):getByRole(withname) >getByLabelText>getByText>getByTestId(last resort, added deliberately). Never query by placeholder — a placeholder is not a label (seea11y); needing it means the input lacks one. - All interactions via
userEvent(const user = userEvent.setup()), neverfireEvent— userEvent fires the full real event sequence. - Async UI:
await screen.findByRole(...)/waitForfor assertions only — neverwaitForcontaining a user action, never arbitrarysetTimeoutsleeps. - Wrap components needing providers with a shared
renderWithProviderstest util — one definition, not per-file copies.
Mocking policy — mock at the boundary, not the module graph
- Network: MSW handlers, not
vi.mock-ing your own fetch wrapper. Tests then survive refactors of the data layer. vi.mockonly for true externals (analytics SDK, payment widget) and module-level non-determinism. If you're mocking your own module to make a test pass, the design or the test level is wrong.- Non-determinism:
vi.useFakeTimers()+vi.setSystemTime()for time; alwaysvi.useRealTimers()inafterEach. With fake timers + userEvent, configureadvanceTimers: vi.advanceTimersByTime. vi.restoreAllMocks()inafterEach(orrestoreMocks: truein config) — leaked mocks cause order-dependent flake.
Config
- Single source: define
testinvite.config.ts(or merge it) so aliases/plugins match the app.environment: 'jsdom'only for DOM test projects; pure-logic tests run innode(faster) — use Vitest projects to split. - Coverage is a signal, not a goal: review uncovered branches, don't chase a number with assertion-free tests.
- A test that fails intermittently is a bug to fix now (usually unawaited async or shared state) — never retry-loop or skip it.