vitest-testing
Skill2 starsChanged 40 days agoMITView on GitHub
Vitest testing patterns for production TypeScript projects. Use when writing tests, fixing test failures, configuring coverage, mocking modules, debugging flaky tests, or setting up Vitest in a monorepo. Covers Vitest 3+, vi.mock, vi.fn, React Testing Library, PGlite in-memory PostgreSQL, pool forks, maxWorkers, and hookTimeout.
We split this skill into the rules it gives an agent
16 rules. 0 are common, 4 are distinctive, and 12 are very specific to this project.
0
Common
Most of the 3 edited versions we read keep these.
4
Distinctive
This author's own choices. Worth a look.
12
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 17
Test directories: __tests__/ for grouped tests
- Very specific: line 19
Test utilities: shared test package or test/helpers.ts
- Very specific: line 58
Important: When using Biome, always mock classes with class syntax inside vi.mock() factories.
- Very specific: line 114
Use pool: 'forks' for process isolation (prevents shared state leaks)
- Very specific: line 141
Don't use jest.fn() — use vi.fn() (Vitest, not Jest)
- Distinctive: line 142
Don't mock everything — prefer real implementations, mock only external services
- Very specific: line 143
Don't use function() in vi.mock() factories — Biome converts to arrows, breaking new
- Very specific: line 144
Don't share state between tests — use beforeEach to reset
- Very specific: line 145
Don't use threads pool with native modules — use forks
- Very specific: line 146
Don't set hookTimeout too low when using PGlite
- Distinctive: line 150
Check for shared mutable state between tests
- Very specific: line 151
Check for timing issues (setTimeout, setInterval)
- Distinctive: line 152
Check for port conflicts (parallel workers binding same port)
- Distinctive: line 153
Check for PGlite startup timeout under load
- Very specific: line 154
Run with --reporter=verbose to see individual test timings
- Very specific: line 155
Run single test: vitest run src/path/to/file.test.ts
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Vitest Testing Patterns
Test File Conventions
- Unit/integration tests:
*.test.tsor*.test.tsx(co-located with source) - Test directories:
__tests__/for grouped tests - Fixtures:
__fixtures__/ortest/fixtures/ - Test utilities: shared test package or
test/helpers.ts
Writing Tests
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
describe('MyFunction', () => {
it('should handle the happy path', () => {
const result = myFunction('valid-input');
expect(result).toEqual({ status: 'ok' });
});
it('should throw on invalid input', () => {
expect(() => myFunction('')).toThrow('Input required');
});
});Mocking
// Mock a module
vi.mock('./database', () => ({
query: vi.fn().mockResolvedValue([{ id: 1 }]),
}));
// Mock a class (Biome-safe — use class syntax, not function)
vi.mock('./service', () => ({
MyService: class {
async getData() { return []; }
},
}));
// Spy on a method
const spy = vi.spyOn(object, 'method');
spy.mockReturnValue('mocked');Important: When using Biome, always mock classes with class syntax inside vi.mock() factories. Biome converts function() to arrow functions, which breaks new.
Async Testing
it('should fetch data', async () => {
const result = await fetchData();
expect(result).toHaveLength(3);
});
it('should reject on error', async () => {
await expect(fetchBadData()).rejects.toThrow('Not found');
});PGlite (In-Memory PostgreSQL)
import { PGlite } from '@electric-sql/pglite';
let db: PGlite;
beforeEach(async () => {
db = new PGlite(); // in-memory, fresh each test
await db.exec(schema);
});
afterEach(async () => {
await db.close();
});Config for PGlite: PGlite startup can take 3-5s under load. Set hookTimeout: 30000 in vitest.config.ts:
export default defineConfig({
test: {
hookTimeout: 30000,
},
});Monorepo Testing
// vitest.config.ts — per-package config
export default defineConfig({
test: {
pool: 'forks', // process isolation (not threads)
maxWorkers: 2, // prevent OOM in CI
hookTimeout: 30000, // PGlite startup time
include: ['src/**/*.test.{ts,tsx}'],
},
});- Use
pool: 'forks'for process isolation (prevents shared state leaks) - Cap
maxWorkersto prevent fork explosion (turbo concurrency x workers = total processes) - Disable test caching in turbo (
"cache": falsein turbo.json test task) to prevent stale results
Coverage
// vitest.config.ts
export default defineConfig({
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'lcov'],
exclude: ['**/*.test.ts', '**/__fixtures__/**'],
thresholds: {
statements: 80,
branches: 75,
functions: 80,
lines: 80,
},
},
},
});Common Mistakes to Avoid
- Don't use
jest.fn()— usevi.fn()(Vitest, not Jest) - Don't mock everything — prefer real implementations, mock only external services
- Don't use
function()invi.mock()factories — Biome converts to arrows, breakingnew - Don't share state between tests — use
beforeEachto reset - Don't use threads pool with native modules — use
forks - Don't set
hookTimeouttoo low when using PGlite
Debugging Flaky Tests
- Check for shared mutable state between tests
- Check for timing issues (
setTimeout,setInterval) - Check for port conflicts (parallel workers binding same port)
- Check for PGlite startup timeout under load
- Run with
--reporter=verboseto see individual test timings - Run single test:
vitest run src/path/to/file.test.ts
Skill by RevealUI Studio — the agentic business runtime.
Other versions4 projects use a version of this.
Word for word · 1
- RevealUIStudio/revskills★ 2100% same
Edited · 0
None found.
Wrote their own version · 3
- TangleML/tangle-ui★ 104same name
- axross/skills★ 1same name
- yutakobayashidev/skills★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository29 other files it gives its agents.
- skills/revealui-design/CLAUDE.mdCLAUDE.md
- drizzle-dbSkill
- electric-syncSkill
- exhaustive-auditSkill
- grok-bot-checkpointSkill
- knowledge-graphSkill
- mcp-serverSkill
- multi-agent-memorySkill
- next-best-practicesSkill
- redundancy-scanSkill
- revealui-checkpointSkill
- revealui-cleanupSkill
- coordinateSkill
- revealui-designSkill
- revealui-design-statusSkill
- revealui-doctorSkill
- revealui-opsSkill
- revealui-pickupSkill
- revealui-recoverSkill
- revealui-rollupSkill
- revealui-skills-testSkill
- revealui-snapshotSkill
- revealui-sync-ltsSkill
- revealui-sync-rulesSkill
- revealui-trackerSkill
- revvault-resolveSkill
- security-hardeningSkill
- tailwind-v4Skill
- yjs-collaborationSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

