agentsclimarketplace

Testing vitest

Skill Syo-M/fable-frontend-skills/plugin/skills/testing-vitest

Vitest unit and component testing conventions — Testing Library, mocking policy, MSW, timers. Use when writing or fixing unit/component tests or vitest config. 日本語の依頼例:「ユニットテスト書いて」「Vitest」「テスト追加して」「モック」「ロジックのテスト」。From its SKILL.md

Install
npx -y skills add Syo-M/fable-frontend-skills --skill testing-vitest

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 3 stars3 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.

SKILL.md

4.0 KB, 882 tokens by cl100k_base, 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 storybook skill); 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 formatCurrency rounds half-up and handles -0" → Vitest unit test — pure logic, no DOM, no story.
  • "Test the useDebounce hook'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 sprawling beforeEach mutation.
  • No logic in tests (if/loops computing expectations). Expected values are literals.

Testing Library rules

  • Query priority (same list as testing-playwright): getByRole (with name) > getByLabelText > getByText > getByTestId (last resort, added deliberately). Never query by placeholder — a placeholder is not a label (see a11y); needing it means the input lacks one.
  • All interactions via userEvent (const user = userEvent.setup()), never fireEvent — userEvent fires the full real event sequence.
  • Async UI: await screen.findByRole(...) / waitFor for assertions only — never waitFor containing a user action, never arbitrary setTimeout sleeps.
  • Wrap components needing providers with a shared renderWithProviders test 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.mock only 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; always vi.useRealTimers() in afterEach. With fake timers + userEvent, configure advanceTimers: vi.advanceTimersByTime.
  • vi.restoreAllMocks() in afterEach (or restoreMocks: true in config) — leaked mocks cause order-dependent flake.

Config

  • Single source: define test in vite.config.ts (or merge it) so aliases/plugins match the app. environment: 'jsdom' only for DOM test projects; pure-logic tests run in node (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.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Gives 3 of the 12 instructions most unit integration skills give in 882 tokens

Counted across 149 of the 202 authors here whose files we hold, read 2026-09-06

  • Structure tests as arrange, act, assertin 17 of 149
  • Test behavior, not implementationhere, and in 16 of 149
  • Mock all external dependenciesin 14 of 149
  • Keep tests independentin 9 of 149
  • Implement minimal code to passin 7 of 149
  • Write a failing test firstin 7 of 149
  • Fix or delete flaky tests immediatelyhere, and in 7 of 149
  • Verify one behaviour per test functionhere, and in 7 of 149
  • Name tests MethodName_StateUnderTest_ExpectedBehaviorin 6 of 149
  • Separate arrange, act, and assert with blank linesin 6 of 149
  • Target at least 80 percent core logic coveragein 6 of 149
  • Create factory fixtures for test datain 6 of 149

Said here and by no other author read

  • Prefer getByRole queries, test-id last
  • Await findBy or waitFor for async assertions
  • Wrap provider components in shared renderWithProviders
  • Mock network with MSW handlers
  • Restrict vi.mock to true externals

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.