vitest
Installation
SKILL.md
Vitest
- Docs: if unsure about an API, fetch
https://vitest.dev/llms.txt. Do not guess. - Config file: use
vitest.config.{ts,mts,js,mjs}fortest/test.projects. Vitest-only-in-vite.configmerges badly with multiple projects and Storybook. - Gate: no
vitest.config.*butvite.confighastest:(or no Vitest file), ask before adding projects or Storybook whether to introducevitest.config.tsand movetestout of Vite. page.viewport(width, height): import fromvitest/browser.test.projectsfor mixed node/browser and Storybook. Eitherextends: true(inherit merged root: Storybook Vitest example withmergeConfig(viteConfig, …)) orextends: './vite.config.ts'per project; puttest+pluginson each project (svelte-5:storybook-vitest).- Browser concurrency:
vitest-browser-svelte/purewhen you need no auto-cleanup. vitest-browser-sveltev3:renderis async-only (await render(...)); usage insvelte-5:testing-svelte. v3 gives/purefull export parity with the main entry and exports theRenderResulttype.- Assertions: value, not presence. Presence-only assertions (
toBeInTheDocument,not.toBe(''),toHaveBeenCalled) ship regressions. Every interaction test must compute an expected value from the action and assert equality. See references/assertions.md for the pattern, callback-payload rules, and how to tell a harness failure from a behavior failure. - Locators: prefer accessible queries, avoid
data-testid.data-testidis an a11y smell (tkdodo, 2025), adding a testid means the element has no accessible name, role, or text for users of AT either. Fix the a11y hole, not the test. Usepage.getByRole(...),getByLabelText,getByText,getByPlaceholderText,getByTitle,getByAltTextfirst. They mirror how screen readers find elements and fail when a11y regresses. Reach fordata-testidonly as a last resort: charting canvases, truly decorative content, or legacy markup you cannot change, and when you do, leave a comment explaining why no accessible selector worked. - Upgrade: bump all
@vitest/*together. browser.provider:import { playwright } from '@vitest/browser-playwright'toprovider: playwright()(factory, not a string).- Use
import { page } from 'vitest/browser': not@vitest/browser/context. - In
test.projects,plugins/resolve/optimizeDepsbelong inside each project, not only at root: projects do not inherit root plugins by default (extends: trueinherits the merged root). optimizeDeps.exclude: Svelte 5 runes in.svelte.js(e.g. Melt UI) so vite-plugin-svelte handles them, not Vite's dependency pre-bundler (Rolldown since Vite 8, esbuild before).optimizeDeps.include: deps that trigger mid-test optimization (e.g.minisearch) to reduce flakes.- Storybook:
vitest.config.ts+storybookTest+ browserplaywright():svelte-5:storybook-vitest, manual setup.