## 1. upgrade to jest 28

The main dependencies and versions of jest in package.json after the upgrade are as follows.

  1 2 3 4 5 6 7 8 9 10  { "devDependencies": { "@jest/types": "^28.1.1", "@types/jest": "^28.1.1", "jest": "^28.1.1", "jest-environment-jsdom": "^28.1.1", "jest-extended": "^2.0.0", "ts-jest": "^28.0.5", } } 

Compared to the dependencies associated with jest@27, you need to add the jest-environment-jsdom library dependency separately if you need a jsdom execution environment, in addition to the updated version.

## 2. jest 28 error problems and solution reference

### 2.1 SyntaxError: Unexpected token ’export'

The main error message reference is as follows.

 1 2 3 4 5 6  node_modules/uuid/dist/esm-browser/index.js:1 ({"Object.":function(module,exports,require,__dirname,__filename,jest){export { default as v1 } from './v1.js'; SyntaxError: Unexpected token 'export' > 1 | import { v4 } from "uuid"; 

chalk, uuid and other libraries that are adapted to the latest esm scheme basically report this error. The main reason is that jest uses jsdom to execute with the browser-esm version of the default export, and the default transform of jest 28 filters the contents of the node_modules directory.

The current workaround can be as follows.

Method 1: Specify the entry for the commonjs version of the corresponding package in the moduleNameMapper configuration. Example.

 1 2 3 4 5 6 7 8 9  /** @type {import('@jest/types').Config.InitialOptions } */ module.exports = { testEnvironment: 'jsdom', moduleNameMapper: { '^uuid$': require.resolve('uuid'), // 或直接指定入口 js 路径 // '^uuid$': '/node_modules/uuid/dist/index.js', } } 

Method 2: Modify the jest transform filtering rules to allow transformations to be performed for these unusual dependencies. example.

 1 2 3 4  module.exports = { testEnvironment: 'jsdom', transformIgnorePatterns: ['/node_modules/(?!(uuid|xxx)/)'], } 

Hint: Method 2 uses browser scheme, uuid library will also report an error because the current version of jsdom does not support crypto.getRandomValues.

Option 3: mock unimportant dependency libraries. If the dependency is not heavily used and has no impact on the test logic, you can just mock it. For example, mock for uuid.

 1 2 3 4 5  jest.mock('uuid', () => ({ v1: () => '110ec58a-a0f2-4ac4-8393-c866d813b8d1', v4: () => '110ec58a-a0f2-4ac4-8393-c866d813b8d1', v5: () => '110ec58a-a0f2-4ac4-8393-c866d813b8d1', }); 

### 2.2 setTimeout: Matcher error: received value must be a mock or spy function

  1 2 3 4 5 6 7 8 9 10 11 12  Received has value: [Function setTimeout] expect(received).toHaveBeenCalledTimes(expected) Matcher error: received value must be a mock or spy function Received has type: function Received has value: [Function setTimeout] 111 | jest.runAllTimers(); 112 | // Number of timer executions > 113 | expect(setTimeout).toHaveBeenCalledTimes(1); 

A look at the test code reveals a ts type exception. The original writeup was

 1  jest.useFakeTimers('legacy'); 

Just change the incoming parameters to the following.

 1  jest.useFakeTimers({ legacyFakeTimers: true });