plugins/bun/skills/bun-jest-migration/SKILL.md
Use when migrating from Jest to Bun's test runner, import compatibility, mocks, and config.
npx skillsauth add secondsky/claude-skills bun-jest-migrationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Bun's test runner is Jest-compatible. Most Jest tests run without changes.
# 1. Remove Jest dependencies
bun remove jest ts-jest @types/jest babel-jest
# 2. Update test script
# package.json: "test": "bun test"
# 3. Run tests
bun test
// Before (Jest)
import { describe, it, expect, jest } from '@jest/globals';
// After (Bun) - No import needed, or explicit:
import { describe, test, expect, mock, spyOn } from "bun:test";
| Jest | Bun | Notes |
|------|-----|-------|
| describe() | describe() | Identical |
| it() / test() | test() | Use test() |
| expect() | expect() | Same matchers |
| beforeAll/Each | beforeAll/Each | Identical |
| afterAll/Each | afterAll/Each | Identical |
| jest.fn() | mock() | Use mock() |
| jest.spyOn() | spyOn() | Identical |
| Jest | Bun Equivalent |
|------|----------------|
| jest.mock('module') | mock.module('module', () => {...}) |
| jest.useFakeTimers() | import { setSystemTime } from "bun:test" |
| jest.setTimeout() | Third argument to test() |
| jest.clearAllMocks() | Call .mockClear() on each mock |
// Jest
const fn = jest.fn().mockReturnValue('value');
// Bun
const fn = mock(() => 'value');
// Or for compatibility:
import { jest } from "bun:test";
const fn = jest.fn(() => 'value');
// Jest (top-level hoisting)
jest.mock('./utils', () => ({
helper: jest.fn(() => 'mocked')
}));
// Bun (inline, no hoisting)
import { mock } from "bun:test";
mock.module('./utils', () => ({
helper: mock(() => 'mocked')
}));
// Jest
jest.spyOn(console, 'log').mockImplementation(() => {});
// Bun (identical)
spyOn(console, 'log').mockImplementation(() => {});
// Jest
jest.useFakeTimers();
jest.setSystemTime(new Date('2024-01-01'));
jest.advanceTimersByTime(1000);
// Bun - supports Jest-compatible timer APIs
import { setSystemTime } from "bun:test";
import { jest } from "bun:test";
jest.useFakeTimers();
jest.setSystemTime(new Date('2024-01-01'));
jest.advanceTimersByTime(1000); // Now supported
// Jest
expect(component).toMatchSnapshot();
expect(data).toMatchInlineSnapshot(`"expected"`);
// Bun (identical)
expect(component).toMatchSnapshot();
expect(data).toMatchInlineSnapshot(`"expected"`);
Update snapshots:
bun test --update-snapshots
// jest.config.js (before)
module.exports = {
testMatch: ['**/*.test.ts'],
testTimeout: 10000,
setupFilesAfterEnv: ['./jest.setup.ts'],
collectCoverage: true,
coverageThreshold: { global: { lines: 80 } }
};
# bunfig.toml (after)
[test]
root = "./"
preload = ["./jest.setup.ts"]
timeout = 10000
coverage = true
coverageThreshold = 0.8
jest.mock Not Working// Jest mock hoisting doesn't exist in Bun
// Move mock.module before imports or use dynamic imports
// Solution 1: Use mock.module at top
mock.module('./api', () => ({ fetch: mock() }));
import { fetch } from './api';
// Solution 2: Dynamic import
const mockFetch = mock();
mock.module('./api', () => ({ fetch: mockFetch }));
const { fetch } = await import('./api');
// Bun timer support is limited
// Use setSystemTime for date mocking
import { setSystemTime } from "bun:test";
beforeEach(() => {
setSystemTime(new Date('2024-01-01'));
});
afterEach(() => {
setSystemTime(); // Reset to real time
});
// Jest
expect.extend({ toBeWithinRange(received, floor, ceiling) {...} });
// Bun (same API)
import { expect } from "bun:test";
expect.extend({
toBeWithinRange(received, floor, ceiling) {
const pass = received >= floor && received <= ceiling;
return {
pass,
message: () => `expected ${received} to be within ${floor}-${ceiling}`
};
}
});
Remove Jest packages
bun remove jest ts-jest @types/jest babel-jest jest-environment-jsdom
Update package.json
{
"scripts": {
"test": "bun test",
"test:watch": "bun test --watch",
"test:coverage": "bun test --coverage"
}
}
Convert jest.config.js to bunfig.toml
Update imports in test files
@jest/globals → bun:testjest.fn() → mock()jest.mock() → mock.module()Run and fix
bun test 2>&1 | head -50 # Check first errors
| Error | Cause | Fix |
|-------|-------|-----|
| Cannot find module '@jest/globals' | Old import | Use bun:test |
| jest is not defined | Global jest | Import from bun:test |
| mock.module is not a function | Wrong import | import { mock } from "bun:test" |
| Snapshot mismatch | Different serialization | Update with --update-snapshots |
Load references/compatibility-matrix.md when:
devops
Cloudflare Workers AI for serverless GPU inference. Use for LLMs, text/image generation, embeddings, or encountering AI_ERROR, rate limits, token exceeded errors.
devops
Cloudflare Vectorize vector database for semantic search and RAG. Use for vector indexes, embeddings, similarity search, or encountering dimension mismatches, filter errors.
development
This skill should be used when the user asks to "add turnstile", "implement bot protection", "validate turnstile token", "fix turnstile error", "setup captcha alternative", or encounters error codes 100*/300*/600*, CSP errors, or token validation failures. Provides CAPTCHA-alternative protection for Cloudflare Workers, React, Next.js, and Hono.
development
Cloudflare Sandboxes SDK for secure code execution in Linux containers at edge. Use for untrusted code, Python/Node.js scripts, AI code interpreters, git operations.