Motivation
The project runs two separate Jest setups and the ESM story is painful. Migrating to Vitest gives us native ESM/TS support (no ts-jest, no --experimental-vm-modules), faster runs, a Jest-compatible API (low-friction migration), and unified web + node configs via a single vitest.workspace.
This ticket blocks #33 — CI should run the Vitest suites, not Jest, so this migration should land first.
Current state
- Web suite (
jest.config.js): next/jest, jsdom, @testing-library/react, setup in _jest.setup.web.ts (mocks next/server, polyfills URLPattern). Ignores src/cli/ and src/lib/. - CLI suite (
jest.config.cli.js): ts-jest, node env, maxWorkers: 4, coverage, matches src/cli/**/*.test.ts and src/lib/**/*.test.ts. - Setup:
_jest.setup.web.ts, _jest.setup.cli.ts (global.jest = jest). - ~95 test files. Heaviest areas:
src/point-functions/__tests__ (24), src/lib/__tests__ (14), src/cli/services/__tests__ (13). - Deps:
jest, @jest/globals, @types/jest, jest-environment-jsdom, ts-jest. - Scripts:
test:web, test:cli, update-snapshots; test runs both.
Scope / plan
- Add
vitest, @vitest/coverage-v8, jsdom, @testing-library/jest-dom (or vitest-compatible matchers); remove jest, ts-jest, @jest/globals, @types/jest, jest-environment-jsdom. - Create a
vitest.workspace.ts with two projects:
- web:
environment: 'jsdom', setup file port of _jest.setup.web.ts, @/ alias → src/, includes the current web globs. - cli/node:
environment: 'node', includes src/cli/** and src/lib/**, coverage (v8) → coverage/cli.
- Alias
^@/(.*)$ → src/$1 (via vite-tsconfig-paths or resolve.alias). - Port setup files: replace
jest.mock('next/server', …) with vi.mock; keep the URLPattern polyfill; drop the global.jest = jest shim. - Codemod test files:
jest.fn/mock/spyOn → vi.*, @jest/globals imports → vitest. Enable globals: true to minimize churn, or add explicit imports. - Verify snapshots migrate (Vitest uses a compatible format; regenerate with
--update where needed). - Confirm
aws-sdk-client-mock/sinon and next/server mocking still work under Vitest. - Update
package.json scripts: test:web → vitest run --project web, test:cli → vitest run --project cli, test → vitest run, update-snapshots → vitest run --update; drop the --experimental-vm-modules flag. - Update
CONTRIBUTING.md/docs test commands and remove Jest config files.
Acceptance criteria
Notes
Keep the two-project split (web jsdom vs. node) — the CLI/lib tests should not load the jsdom/Next setup. next/jest's SWC transform is replaced by Vitest's esbuild/SWC; watch for any Next-specific transform behavior (e.g. CSS module or next/font imports) in component tests.
Motivation
The project runs two separate Jest setups and the ESM story is painful. Migrating to Vitest gives us native ESM/TS support (no
ts-jest, no--experimental-vm-modules), faster runs, a Jest-compatible API (low-friction migration), and unified web + node configs via a singlevitest.workspace.This ticket blocks #33 — CI should run the Vitest suites, not Jest, so this migration should land first.
Current state
jest.config.js):next/jest,jsdom,@testing-library/react, setup in_jest.setup.web.ts(mocksnext/server, polyfillsURLPattern). Ignoressrc/cli/andsrc/lib/.jest.config.cli.js):ts-jest, node env,maxWorkers: 4, coverage, matchessrc/cli/**/*.test.tsandsrc/lib/**/*.test.ts._jest.setup.web.ts,_jest.setup.cli.ts(global.jest = jest).src/point-functions/__tests__(24),src/lib/__tests__(14),src/cli/services/__tests__(13).jest,@jest/globals,@types/jest,jest-environment-jsdom,ts-jest.test:web,test:cli,update-snapshots;testruns both.Scope / plan
vitest,@vitest/coverage-v8,jsdom,@testing-library/jest-dom(orvitest-compatible matchers); removejest,ts-jest,@jest/globals,@types/jest,jest-environment-jsdom.vitest.workspace.tswith two projects:environment: 'jsdom', setup file port of_jest.setup.web.ts,@/alias →src/, includes the current web globs.environment: 'node', includessrc/cli/**andsrc/lib/**, coverage (v8) →coverage/cli.^@/(.*)$→src/$1(viavite-tsconfig-pathsorresolve.alias).jest.mock('next/server', …)withvi.mock; keep theURLPatternpolyfill; drop theglobal.jest = jestshim.jest.fn/mock/spyOn→vi.*,@jest/globalsimports →vitest. Enableglobals: trueto minimize churn, or add explicit imports.--updatewhere needed).aws-sdk-client-mock/sinonandnext/servermocking still work under Vitest.package.jsonscripts:test:web→vitest run --project web,test:cli→vitest run --project cli,test→vitest run,update-snapshots→vitest run --update; drop the--experimental-vm-modulesflag.CONTRIBUTING.md/docs test commands and remove Jest config files.Acceptance criteria
pnpm test,pnpm test:web,pnpm test:clirun via Vitest; no--experimental-vm-modulests-jestremoved frompackage.jsonand lockfileNotes
Keep the two-project split (web jsdom vs. node) — the CLI/lib tests should not load the jsdom/Next setup.
next/jest's SWC transform is replaced by Vitest's esbuild/SWC; watch for any Next-specific transform behavior (e.g. CSS module ornext/fontimports) in component tests.