1---2name: mocha-to-jest-migrator3description: Specialized guidance for migrating Node.js packages from the legacy Mocha, Sinon, and Istanbul/c8 ecosystem to Jest. It focuses on surgical test transformation, type safety, and resolving ESM/CommonJS interoperability issues.4---561. Infrastructure Migration7 * Dependency Swap: Remove mocha, @types/mocha, sinon, @types/sinon, c8, codecov, proxyquire, and @types/proxyquire. Install8 jest, ts-jest, and @types/jest.9 * Script Alignment: Update package.json to use jest for the test and system-test commands. Avoid NODE_OPTIONS or10 experimental flags if possible by using mocking.11 * Config Generation: Create a jest.config.js using the modern transform block for ts-jest:12 ```javascript13 transform: { '^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.json' }] },14 clearMocks: true15 ```16 * In the config file, include this license header:17 ```javascript18 // Copyright 2026 Google LLC19 //20 // Licensed under the Apache License, Version 2.0 (the "License");21 // you may not use this file except in compliance with the License.22 // You may obtain a copy of the License at23 //24 // https://www.apache.org/licenses/LICENSE-2.025 //26 // Unless required by applicable law or agreed to in writing, software27 // distributed under the License is distributed on an "AS IS" BASIS,28 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.29 // See the License for the specific language governing permissions and30 // limitations under the License.31 ```322. Syntax Transformation (Cheat Sheet)33 * Structure: Jest supports describe, it, beforeEach, etc., natively. No changes are needed to the block structure.34 * Assertions: 35 * assert.strictEqual(a, b) → expect(a).toBe(b)36 * assert.deepStrictEqual(a, b) → expect(a).toEqual(b)37 * assert.ifError(err) → expect(err).toBeNull()38 * somePromise.then(result => assert.deepStrictEqual(result, expected)) → expect(somePromise).resolves.toEqual(expected)39 * Mocking:40 * sinon.stub(obj, 'meth') → jest.spyOn(obj, 'meth').mockImplementation(...)41 * sinon.fn() → jest.fn()42 * proxyquire(path, { 'dep': mock }) → jest.mock('dep', () => mock)433. Advanced Patterns44 * Strong Typing: If possible without adding to much complexity, remove the use of `any` from the tests as you go. 45 * Top-Level Mocking: If a dependency uses ESM dynamic imports (like import('node-fetch')) that trigger TypeError in Jest,46 mock that dependency at the top level of the test file using jest.mock(). This bypasses the need for the47 --experimental-vm-modules flag.48 * Async Robustness: For tests using done(), always wrap expectations in try-catch blocks and pass the error to done(e) to49 prevent tests from hanging on failure.504. Cleanup Workflow51 * Config Deletion: Remove .mocharc.js, .nycrc, and old .coverage or .nyc_output directories.52 * Git: Update .gitignore to ignore `coverage/`.