{"name":"write-unit-tests-with-vitest","description":"Writes fast JavaScript and TypeScript unit tests with Vitest - set it up, test pure functions and async code, mock modules and timers sparingly, and test React or Vue components with Testing Library. Use when the user wants JavaScript tests, to set up Vitest or migrate from Jest, or to test a component or function.","category":"debugging","tags":["testing","typescript","react"],"models":["any"],"proven":false,"passing_families":0,"model_testing":"Not yet model-tested; testing Jan 2027","url":"https://theskillvault.ai/skills/write-unit-tests-with-vitest","api_url":"https://theskillvault.ai/api/skills/write-unit-tests-with-vitest","raw_url":"https://theskillvault.ai/api/skills/write-unit-tests-with-vitest/raw","body":"# Write unit tests with Vitest\n\nVitest runs tests fast and reads your Vite config. Its API matches Jest, so most Jest knowledge carries over.\n\n## When to use\n- Your JavaScript or TypeScript code has no tests.\n- You want to test a React, Vue or Svelte component.\n- You are moving from Jest to something faster.\n\n## Steps\n1. Install: `npm i -D vitest` (add `@testing-library/react` and `jsdom` for components).\n2. Add `\"test\": \"vitest\"` to package.json scripts. For components, set `test.environment = \"jsdom\"` in `vitest.config.ts`.\n3. Put tests next to code as `thing.test.ts`.\n4. Start with pure functions: given an input, expect an output.\n5. For async code, `await` the call and use `expect(...).rejects` for errors.\n6. Mock only edges: `vi.mock(\"./api\")` for network modules, `vi.useFakeTimers()` for time.\n7. For components, render and act like a user: find by role or label, click, then assert what shows.\n8. Run `npx vitest run --coverage` to see gaps, then add tests for risky branches.\n9. Run `vitest run` in CI.\n\n```ts\nimport { describe, it, expect } from \"vitest\";\nimport { slugify } from \"./slugify\";\n\ndescribe(\"slugify\", () => {\n  it(\"lowercases and joins words\", () => expect(slugify(\"Hello World\")).toBe(\"hello-world\"));\n  it(\"drops symbols\", () => expect(slugify(\"Hi! There?\")).toBe(\"hi-there\"));\n});\n```\n\n## Gotchas\n- Testing implementation details (state names, private functions) breaks on every refactor. Test what users see.\n- Reset mocks between tests (`vi.restoreAllMocks()`) or one test leaks into the next.\n- Keep real API keys and tokens out of test files and snapshots. Use fake values.\n- Huge snapshots hide real changes. Prefer small, specific assertions.\n\n## Portability\nWorks with any Vite, Next.js, Nuxt or Node project. If you use Jest, the same tests run with small import changes; swap `vi` for `jest` instead.\n\n## Example prompt\n\"Set up Vitest in my React app and write tests for the cart total function and the Add to cart button.\"\n\n## Done when\n- `npm test` passes locally and in CI.\n- Key functions and components have tests for normal and error cases.\n- Mocks are reset between tests and no real secrets appear in tests.\n\n---\nAdapted from \"javascript-testing-patterns\" in wshobson/agents (MIT, Copyright (c) 2024 Seth Hobson). See LICENSE.txt.","files":["LICENSE.txt"],"license":"MIT","license_name":"MIT License","license_url":"https://opensource.org/license/mit","attribution":"Based on work by Seth Hobson (wshobson/agents, javascript-testing-patterns) (Copyright (c) 2024 Seth Hobson, MIT License), https://github.com/wshobson/agents/tree/7e2fb559cf4b824b27f1fec49fe88f7511066d26/plugins/javascript-typescript/skills/javascript-testing-patterns; adapted by TheSkillVault, https://theskillvault.ai","install":{"claude_code":"curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/write-unit-tests-with-vitest/raw' -o ~/'.claude/skills/write-unit-tests-with-vitest/SKILL.md' && curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/write-unit-tests-with-vitest/files/LICENSE.txt' -o ~/'.claude/skills/write-unit-tests-with-vitest/LICENSE.txt'","cursor":"curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/write-unit-tests-with-vitest/raw' -o '.cursor/skills/write-unit-tests-with-vitest/SKILL.md' && curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/write-unit-tests-with-vitest/files/LICENSE.txt' -o '.cursor/skills/write-unit-tests-with-vitest/LICENSE.txt'","agents":"curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/write-unit-tests-with-vitest/raw' -o '.agents/skills/write-unit-tests-with-vitest/SKILL.md' && curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/write-unit-tests-with-vitest/files/LICENSE.txt' -o '.agents/skills/write-unit-tests-with-vitest/LICENSE.txt'","mcp_url":"https://theskillvault.ai/mcp","cursor_mcp_deeplink":"cursor://anysphere.cursor-deeplink/mcp/install?name=theskillvault&config=eyJ1cmwiOiJodHRwczovL3RoZXNraWxsdmF1bHQuYWkvbWNwIn0%3D","mcp_config":{"mcpServers":{"theskillvault":{"url":"https://theskillvault.ai/mcp"}}}},"bundles":[],"tested_on":[{"family":"chatgpt","name":"ChatGPT","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"claude","name":"Claude","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"gemini","name":"Gemini","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"grok","name":"Grok","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"llama","name":"Llama","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"deepseek","name":"DeepSeek","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"mistral","name":"Mistral","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"qwen","name":"Qwen","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"kimi","name":"Kimi K","outcome":null,"date":null,"source":null,"counts":false,"stale":false}],"proven_rule":{"threshold":5,"window_days":365,"computed_at":"2026-11-02T03:20:33.817Z"}}