Skip to content

chore: migrate test suite from Mocha/Chai to Vitest#1257

Merged
MarshallOfSound merged 1 commit intomainfrom
claude/port-mocha-to-vitest-XGpun
Apr 7, 2026
Merged

chore: migrate test suite from Mocha/Chai to Vitest#1257
MarshallOfSound merged 1 commit intomainfrom
claude/port-mocha-to-vitest-XGpun

Conversation

@MarshallOfSound
Copy link
Copy Markdown
Member

This PR migrates the entire test suite from Mocha and Chai to Vitest, a modern and faster test framework.

Summary

The test infrastructure has been completely refactored to use Vitest instead of Mocha/Chai. This includes updating test syntax, assertion methods, and configuration files to align with Vitest's API and conventions.

Key Changes

  • Test Framework Migration: Replaced Mocha with Vitest as the primary test runner
  • Assertion Library: Migrated from Chai assertions (e.g., expect().to.equal()) to Vitest assertions (e.g., expect().toBe())
  • Test Hooks: Updated lifecycle hooks from Mocha style (before, after) to Vitest style (beforeAll, afterAll, beforeEach, afterEach)
  • Test Syntax: Converted function-based test definitions to arrow functions and removed this.timeout() calls
  • Configuration:
    • Added vitest.config.ts with test configuration including timeout settings, coverage configuration, and file parallelism settings
    • Removed .mocharc.jsonc (Mocha configuration)
    • Updated package.json scripts to use vitest run instead of mocha
  • Coverage: Replaced nyc with Vitest's built-in v8 coverage provider
  • Dependencies:
    • Removed: mocha, chai, chai-as-promised, nyc, @types/mocha, @types/chai, @types/chai-as-promised, eslint-plugin-mocha
    • Added: vitest, @vitest/coverage-v8
  • Test Utilities: Updated helper functions to remove Mocha-specific code (e.g., execArgv filtering for tsx)
  • ESLint: Removed Mocha plugin and related rules from .eslintrc.js
  • TypeScript Config: Updated tsconfig.json to remove Mocha types

Notable Implementation Details

  • Test timeout is configured globally in vitest.config.ts (10 minutes) rather than per-test
  • File parallelism is disabled (fileParallelism: false) since test files share a single TEST_MODULE_PATH fixture on disk
  • Coverage configuration uses Vitest's v8 provider with lcov reporter for CI integration
  • All assertion syntax has been updated to use Vitest's chainable API (e.g., .toBe(), .toContain(), .toEqual(), .toHaveLength(), .rejects.toThrow())

https://preview.claude.ai/code/session_01QHrqXbnQUtPxuynmvQsJrz

@MarshallOfSound MarshallOfSound requested a review from a team as a code owner April 4, 2026 09:35
@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 4, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedtar@​7.5.1099859993100
Addedvitest@​4.1.2961007998100
Added@​vitest/​coverage-v8@​4.1.2991007998100
Updatednode-pre-gyp-test@​5.1.6 ⏵ 0.0.0-use.local100100100100100

View full report

@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 4, 2026

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
High CVE: Picomatch has a ReDoS vulnerability via extglob quantifiers

CVE: GHSA-c2c7-rcm5-vvqj Picomatch has a ReDoS vulnerability via extglob quantifiers (HIGH)

Affected versions: >= 4.0.0 < 4.0.4; >= 3.0.0 < 3.0.2; < 2.3.2

Patched version: 4.0.4

From: ?npm/vitest@4.1.2npm/node-gyp@11.2.0npm/picomatch@4.0.2

ℹ Read more on: This package | This alert | What is a CVE?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Remove or replace dependencies that include known high severity CVEs. Consumers can use dependency overrides or npm audit fix --force to remove vulnerable dependencies.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/picomatch@4.0.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
High CVE: node-npm tar Symlink Path Traversal via Drive-Relative Linkpath

CVE: GHSA-9ppj-qmqm-q256 node-tar Symlink Path Traversal via Drive-Relative Linkpath (HIGH)

Affected versions: < 7.5.11

Patched version: 7.5.11

From: package.jsonnpm/tar@7.5.10

ℹ Read more on: This package | This alert | What is a CVE?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Remove or replace dependencies that include known high severity CVEs. Consumers can use dependency overrides or npm audit fix --force to remove vulnerable dependencies.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/tar@7.5.10. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
High CVE: Vite Vulnerable to Arbitrary File Read via Vite Dev Server WebSocket

CVE: GHSA-p9ff-h696-f583 Vite Vulnerable to Arbitrary File Read via Vite Dev Server WebSocket (HIGH)

Affected versions: >= 8.0.0 < 8.0.5; >= 7.0.0 < 7.3.2; >= 6.0.0 < 6.4.2

Patched version: 8.0.5

From: ?npm/vitest@4.1.2npm/vite@8.0.3

ℹ Read more on: This package | This alert | What is a CVE?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Remove or replace dependencies that include known high severity CVEs. Consumers can use dependency overrides or npm audit fix --force to remove vulnerable dependencies.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/vite@8.0.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
High CVE: Vite: server.fs.deny bypassed with queries

CVE: GHSA-v2wj-q39q-566r Vite: server.fs.deny bypassed with queries (HIGH)

Affected versions: >= 8.0.0 < 8.0.5; >= 7.1.0 < 7.3.2

Patched version: 8.0.5

From: ?npm/vitest@4.1.2npm/vite@8.0.3

ℹ Read more on: This package | This alert | What is a CVE?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Remove or replace dependencies that include known high severity CVEs. Consumers can use dependency overrides or npm audit fix --force to remove vulnerable dependencies.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/vite@8.0.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@MarshallOfSound MarshallOfSound changed the title Migrate test suite from Mocha/Chai to Vitest chore: migrate test suite from Mocha/Chai to Vitest Apr 4, 2026
@MarshallOfSound
Copy link
Copy Markdown
Member Author

@SocketSecurity ignore npm/vite@5.4.21

@MarshallOfSound MarshallOfSound force-pushed the claude/port-mocha-to-vitest-XGpun branch 25 times, most recently from c262511 to c2f1139 Compare April 6, 2026 16:33
@MarshallOfSound MarshallOfSound force-pushed the claude/port-mocha-to-vitest-XGpun branch 7 times, most recently from 23745e1 to f7574b7 Compare April 6, 2026 17:19
Copy link
Copy Markdown
Member

@dsanders11 dsanders11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial review has a couple of small comments, will come back to this later today.

Comment on lines +9 to +11
// Test files share a single TEST_MODULE_PATH on disk, so they cannot run
// in parallel without clobbering each other's fixtures.
fileParallelism: false,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up for a different PR, but this would probably be easy enough to change if it gave us a speed up on how long CI takes, since it's 5-10 mins.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, follow-up. The blocker is TEST_MODULE_PATH being a single shared path on disk (os.tmpdir()/electron-rebuild-test), so any two test files that share it would clobber each other's fixtures if they ran concurrently. Making it per-file (e.g., os.tmpdir()/electron-rebuild-test-${path.basename(import.meta.filename)}) would unlock parallelism.


Generated by Claude Code

vitest.config.ts Outdated
test: {
include: ['test/*.ts'],
reporters: process.env.GITHUB_ACTIONS ? ['default', 'github-actions'] : 'default',
testTimeout: 10 * 60 * 1000,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had more fine-grained timeouts before, now everything is 10 minutes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restored. The describe-level { timeout: ... } option in vitest only applies to tests, not to beforeAll/afterAll, so the per-suite timeouts are now passed directly on each describe and the global hookTimeout is set to TIMEOUT_IN_MILLISECONDS (mirroring what mocha's this.timeout() did at the suite level for hooks). The two macOS/Windows-specific 5-minute test overrides also got restored as a third arg on the relevant it() calls, and the 10-minute debug/clang suites are explicit again.


Generated by Claude Code

Comment on lines +28 to +35
process.execArgv = process.execArgv.filter((arg, i, all) => {
if (arg === '--experimental-import-meta-resolve') return false;
if (arg === '--require' && all[i + 1]?.includes('vitest')) return false;
if (i > 0 && all[i - 1] === '--require' && arg.includes('vitest')) return false;
if (arg === '--conditions' && all[i + 1] === 'development') return false;
if (i > 0 && all[i - 1] === '--conditions' && arg === 'development') return false;
return true;
});
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might prove to be fragile over time. 🤔

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Simplified to just process.execArgv = [] with a comment explaining the forked node-gyp worker doesn't need any of vitest's worker flags. That's much less coupled to vitest's internal flag list than the earlier per-flag filter.


Generated by Claude Code

Replace mocha + chai + chai-as-promised + nyc with vitest +
@vitest/coverage-v8.

- Replace describe/it/before/after assertions with vitest equivalents
- Replace chai matchers (to.equal, to.deep.equal, to.be.true, etc.) with
  vitest matchers (toBe, toEqual, etc.)
- Replace 'context' aliases with 'describe'
- Replace per-test/suite this.timeout() calls with a global testTimeout
  in vitest.config.ts
- Externalize lib/ in vitest's SSR transformer so import.meta.resolve
  in lib/electron-locator.js works correctly
- Disable file parallelism since test files share TEST_MODULE_PATH
- Drop the now-obsolete tsx execArgv filter from module-setup.ts
@MarshallOfSound MarshallOfSound force-pushed the claude/port-mocha-to-vitest-XGpun branch from f7574b7 to 822fb79 Compare April 6, 2026 19:53
@MarshallOfSound MarshallOfSound merged commit 2ed0cf7 into main Apr 7, 2026
6 checks passed
@MarshallOfSound MarshallOfSound deleted the claude/port-mocha-to-vitest-XGpun branch April 7, 2026 02:27
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.

4 participants