Skip to content

Migrate test suite from Jest to Vitest#283

Open
TimothyJones wants to merge 14 commits intomasterfrom
claude/migrate-tests-vite-z8aAz
Open

Migrate test suite from Jest to Vitest#283
TimothyJones wants to merge 14 commits intomasterfrom
claude/migrate-tests-vite-z8aAz

Conversation

@TimothyJones
Copy link
Copy Markdown
Member

This PR migrates the entire test suite from Jest to Vitest, modernizing the testing infrastructure and enabling better support for ESM modules.

Summary

The test framework has been completely replaced with Vitest, which provides better ESM support, faster test execution, and improved developer experience. All test files have been updated to use Vitest's API while maintaining the same test coverage and functionality.

Key Changes

  • Test Framework Migration: Replaced Jest with Vitest across all test files

    • Updated jest.config.jsvitest.config.js with appropriate Vitest configuration
    • Configured Vitest with globals: true for Jest-compatible API
    • Set pool: 'forks' and concurrent: false for serial test execution
  • Mock System Refactoring: Redesigned the mock infrastructure to work with both CJS and ESM

    • Refactored test/mocks/jest-mocks.js to export a setup() function that returns mock objects
    • Implemented a Node.js Module._load hook to intercept CJS require() calls in the source code's dependency graph
    • This allows vi.mock() (ESM-level) to work alongside CJS source code that uses require()
    • Added support for mocking run-execFile and fs modules with proper spy integration
  • Test File Conversions: Converted all test files from CommonJS to ESM

    • Changed require() to import statements
    • Updated jest.spyOn()vi.spyOn()
    • Updated jest.mock()vi.mock() with proper module resolution
    • Used vi.hoisted() to set up mocks before module imports in integration tests
    • Added vi.resetModules() in integration tests to reload modules with fresh mocks
  • ESLint Configuration: Updated to use eslint-plugin-vitest instead of eslint-plugin-jest

    • Updated globals configuration to use Vitest's environment globals
    • Adjusted rule configurations for Vitest compatibility
  • Package.json Updates: Updated test scripts and dependencies

    • Changed test commands from jest to vitest run
    • Replaced Jest and jest-serial-runner with Vitest
    • Added eslint-plugin-vitest dependency

Notable Implementation Details

  • The mock setup uses a CJS require hook because the source code is written in CommonJS with require() statements, while tests are now ESM. This hybrid approach ensures mocks work correctly across both module systems.
  • Integration tests use vi.resetModules() before dynamic imports to ensure fresh module loads with current mock state
  • The fs module is mocked at both the CJS hook level (for source code) and ESM level (for test code) to ensure consistent spy behavior
  • Test timeout remains 30 seconds to maintain compatibility with existing test expectations

https://claude.ai/code/session_01JuGPaiD48RjuFRjujj7WU3

claude added 14 commits March 18, 2026 11:13
Documents the strategy for migrating all tests from Jest to Vitest,
including risk analysis, API translation table, and step-by-step plan.

https://claude.ai/code/session_01JuGPaiD48RjuFRjujj7WU3
- Replace jest/jest-serial-runner with vitest
- Replace eslint-plugin-jest with eslint-plugin-vitest
- Create vitest.config.js with forks pool and sequential execution
- Rewrite test/mocks/jest-mocks.js with Module._load hook for CJS interception
- Convert simple test files to ESM (stringify-package, utils, preset)
- Integration test and core.spec.js conversion in progress

https://claude.ai/code/session_01JuGPaiD48RjuFRjujj7WU3
- core.spec.js: Full ESM conversion with vi.mock('fs') factory for
  cross-module spy support, Module._load hook for CJS interception,
  and actualConventionalRecommendedBump re-loading. All 85 tests pass.
- All 7 integration tests: ESM imports, vi.hoisted() mock setup
- Integration tests still need investigation for preset config passing
  (conventional-changelog preset merging works differently in Vitest)

https://claude.ai/code/session_01JuGPaiD48RjuFRjujj7WU3
Key changes:
- Integration tests use dynamic import() for command.js and index.js
  because yargs.config() reads .versionrc at module load time, requiring
  CWD to be set to the temp directory first
- Module._load hook for run-execFile is opt-in (only core.spec.js uses it)
  so integration tests can run real git operations
- ESLint config includes jest-mocks.js in test files pattern for vi global

All 10 test files pass. All 138 tests pass. Repository integrity verified.

https://claude.ai/code/session_01JuGPaiD48RjuFRjujj7WU3
- Update engines field to >=20 (vitest deps require Node 20+)
- Remove Node 18 from CI matrix
- Add Node 24 to CI matrix

https://claude.ai/code/session_01JuGPaiD48RjuFRjujj7WU3
Replace @vitest/coverage-v8 with @vitest/coverage-istanbul since v8
coverage is incompatible with pool: 'forks' (no inspector session).
Narrow server.deps.inline to exclude vitest internals so coverage
instrumentation isn't broken by inlining.

https://claude.ai/code/session_01JuGPaiD48RjuFRjujj7WU3
In Vitest with pool:'forks', only files directly imported via ESM go
through Vite's transform pipeline (where Istanbul instruments them).
Files loaded via CJS require() inside source code bypass Vite and go
through Node's native Module._load, so they were never instrumented.

Add a pirates require hook (preloaded via execArgv --require) that
applies Istanbul instrumentation to project source files at the Node
level, writing to __VITEST_COVERAGE__ so the coverage provider
collects the data. This brings coverage from ~16% to ~92%.

Also clean up stale config: remove server.deps.inline and
ssr.noExternal which were debug attempts that aren't needed.

https://claude.ai/code/session_01JuGPaiD48RjuFRjujj7WU3
In Vitest, .mockImplementation() with no arguments passes through to
the original function (unlike Jest where it creates a noop). Change
all console spy setups to .mockImplementation(() => {}) to properly
suppress output. Also add console spies to 3 integration test files
that were missing them.

https://claude.ai/code/session_01JuGPaiD48RjuFRjujj7WU3
Add console.error spy to core.spec.js — the existing spies only
covered console.warn and console.info, leaving console.error calls
from print-error.js and child process errors visible in test output.

https://claude.ai/code/session_01JuGPaiD48RjuFRjujj7WU3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants