# Conflicts:
# oxlint-suppressions.json
# packages/accounts-controller/package.json
# packages/approval-controller/package.json
# packages/base-controller/package.json
# packages/controller-utils/package.json
# packages/keyring-controller/package.json
# packages/phishing-controller/package.json
# packages/polling-controller/package.json
# packages/sample-controllers/package.json
# packages/subscription-controller/package.json
# packages/subscription-controller/src/subscription-delegation/SubscriptionDelegationService.test.ts
# packages/user-operation-controller/package.json
# yarn.lock
Explanation
Every package in the monorepo runs its tests on Jest via ts-jest, which compiles the ESM sources to CommonJS just for tests. We want to be on Vitest, like
metamask-module-templatealready is, but moving 97 packages and 848 test files in one PR is not reviewable.So this sets up both runners side by side and moves the first ten packages. A package runs on Vitest once it has a
vitest.config.mts, otherwise it keeps itsjest.config.cjs. Script names are identical on both sides, soyarn testandyarn workspaces foreach run testdo not care which runner a package uses.yarn.config.cjsandoxlint.config.tsboth work the split out from disk, so there is no list to keep in sync by hand.Migrated here:
accounts-controller,approval-controller,base-controller,controller-utils,keyring-controller,phishing-controller,polling-controller,sample-controllers,subscription-controller,user-operation-controller. That is 2,066 tests, with each package's coverage thresholds still enforced.Changes whose purpose is not obvious
tests/setup.tshad to be rewritten for Vitest. It deletesglobalThis.fetchand then importsisomorphic-fetchto put it back, which only works because ts-jest emits therequirein source order. Under real ESM the import evaluates first, so you end up with nofetchat all and every nock test fails.tests/vitest/setup.tsassigns thenode-fetchglobals directly instead.Test helpers shared between packages cannot cross the runner boundary. A Jest package importing a Vitest package's helper fails at require time, and the reverse fails on
@jest/globals. Both cases already existed (assets-controllersreaching intoaccounts-controller,sample-controllersintonetwork-controller), so the shared helpers are now split to keep the common parts free of runner imports. Worth knowing for later batches: a package cannot always be migrated independently of its consumers.Custom matcher types moved to
types/vitest.d.ts, which needs itsexport {}. In a global script TypeScript readsdeclare module 'vitest'as declaring the module rather than augmenting it, which silently drops every other export includingvi.Three coverage thresholds moved by about 1.5 points (
controller-utils,keyring-controller,user-operation-controller) because istanbul on esbuild output counts statements a little differently from babel on ts-jest output. Nothing was loosened beyond that measurement difference.Smaller ones:
toThrownow compares thrown values strictly, which showedapproval-controllerwas never actually asserting the error codes it looked like it was; roottest:packagesskips coverage through aCOLLECT_COVERAGEenv var that both shared configs read, rather than the Jest CLI flags it used to forward to every package;.gitignorecoverstests/**/*.d.ts, whichtsc --buildemits beside the shared helpers.Why the dependency versions
Vitest 5, not the 4 that
metamask-module-templatepins. Starting a migration this size on a superseded major seemed worse than briefly leading the template, but it does mean the template wants a follow up bump.viteis a direct devDependency because the shared config imports itsPlugintype, andjsdombecausecontroller-utilsneeds that environment.Verification
yarn lint,yarn constraints,yarn changelog:validateandyarn test:scriptspass. Beyond the ten migrated packages, I ran the 19 Jest packages that consume the shared helpers or custom matchers, pluswalletandreact-data-query, since those are what the shared changes could break.yarn lint:tscis not green onmain(1619 errors, and it is excluded fromyarn lint). This branch sits at 1621: it fixes 3 and adds 2 of the same kindmainalready reports 8 times.network-controlleris deliberately left out. 17 of its 4,181 tests fail under Vitest on timing and event ordering, which is real work rather than a codemod gap, and belongs with the other timer heavy packages in its own PR.References
metamask-module-templatemetamask-module-templateto Vitest 5 so the two stop driftingnetwork-controller,transaction-controller,transaction-pay-controller,assets-controllersandbridge-status-controller, whose tests lean heavily on timersChecklist
dist/changes, so this PR carries theno-changeloglabel.