Skip to content

Commit 7ac0338

Browse files
committed
Fix Jest ESM compat with Babel
1 parent 2d54a99 commit 7ac0338

6 files changed

+1603
-89
lines changed

babel.config.cjs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// We use Babel to transpile down ESM dependencies to CommonJS for our tests
2+
// using babel-jest.
3+
module.exports = {
4+
env: {
5+
test: {
6+
presets: ['@babel/preset-env', '@babel/preset-typescript'],
7+
plugins: ['@babel/plugin-transform-modules-commonjs']
8+
}
9+
}
10+
};

jest.config.cjs

+33-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,32 @@
33
* https://jestjs.io/docs/configuration
44
*/
55

6+
/**
7+
* Dependencies that are ESM-only, and need to be transpiled by Babel.
8+
* This list is used in the `transformIgnorePatterns` option below.
9+
*
10+
* You probably need to add a dependency to this list if the tests fail with something like:
11+
* - `SyntaxError: Cannot use import statement outside a module`
12+
* - `SyntaxError: Unexpected token 'export'`
13+
* If so, identify the dependency that's causing the error via the stack trace, and add it
14+
* to this list.
15+
*
16+
* No, we do not live in the best of all possible worlds. Why do you ask?
17+
*
18+
* For details on Jest's currently experimental ESM support see: https://github.com/jestjs/jest/issues/9430
19+
*/
20+
const ESM_DEPENDENCIES = [
21+
'execa',
22+
'strip-final-newline',
23+
'npm-run-path',
24+
'path-key',
25+
'onetime',
26+
'mimic-fn',
27+
'human-signals',
28+
'is-stream',
29+
'get-stream',
30+
];
31+
632
// This file needs to be .cjs for compatibility with jest-it-up.
733
module.exports = {
834
// All imported modules in your tests should be mocked automatically
@@ -103,8 +129,9 @@ module.exports = {
103129
// An enum that specifies notification mode. Requires { notify: true }
104130
// notifyMode: "failure-change",
105131

106-
// A preset that is used as a base for Jest's configuration
107-
preset: 'ts-jest',
132+
// Disabled in favor of babel-jest, configured via "transform" below.
133+
// // A preset that is used as a base for Jest's configuration
134+
// preset: 'ts-jest',
108135

109136
// Run tests from one or more projects
110137
// projects: undefined,
@@ -189,13 +216,12 @@ module.exports = {
189216
// timers: "real",
190217

191218
// A map from regular expressions to paths to transformers
192-
// transform: undefined,
219+
transform: {
220+
"\\.[jt]sx?$": "babel-jest"
221+
},
193222

194223
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
195-
// transformIgnorePatterns: [
196-
// "/node_modules/",
197-
// "\\.pnp\\.[^\\/]+$"
198-
// ],
224+
transformIgnorePatterns: [`node_modules/(?!(${ESM_DEPENDENCIES.join('|')}))`],
199225

200226
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
201227
// unmockedModulePathPatterns: undefined,

package.json

+5
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
"yargs": "^17.7.1"
3737
},
3838
"devDependencies": {
39+
"@babel/core": "^7.23.5",
40+
"@babel/plugin-transform-modules-commonjs": "^7.23.3",
41+
"@babel/preset-env": "^7.23.5",
42+
"@babel/preset-typescript": "^7.23.3",
3943
"@lavamoat/allow-scripts": "^2.3.1",
4044
"@metamask/auto-changelog": "^3.0.0",
4145
"@metamask/eslint-config": "^10.0.0",
@@ -51,6 +55,7 @@
5155
"@types/yargs": "^17.0.10",
5256
"@typescript-eslint/eslint-plugin": "^5.62.0",
5357
"@typescript-eslint/parser": "^5.62.0",
58+
"babel-jest": "^29.7.0",
5459
"deepmerge": "^4.2.2",
5560
"eslint": "^8.27.0",
5661
"eslint-config-prettier": "^8.5.0",

src/misc-utils.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ describe('misc-utils', () => {
137137
describe('runCommand', () => {
138138
it('runs the command, discarding its output', async () => {
139139
const execaSpy = jest
140-
.spyOn(execaModule, 'default')
140+
.spyOn(execaModule, 'execa')
141141
// Typecast: It's difficult to provide a full return value for execa
142142
.mockResolvedValue({ stdout: ' some output ' } as any);
143143

@@ -155,7 +155,7 @@ describe('misc-utils', () => {
155155
describe('getStdoutFromCommand', () => {
156156
it('executes the given command and returns a version of the standard out from the command with whitespace trimmed', async () => {
157157
const execaSpy = jest
158-
.spyOn(execaModule, 'default')
158+
.spyOn(execaModule, 'execa')
159159
// Typecast: It's difficult to provide a full return value for execa
160160
.mockResolvedValue({ stdout: ' some output ' } as any);
161161

@@ -175,7 +175,7 @@ describe('misc-utils', () => {
175175
describe('getLinesFromCommand', () => {
176176
it('executes the given command and returns the standard out from the command split into lines', async () => {
177177
const execaSpy = jest
178-
.spyOn(execaModule, 'default')
178+
.spyOn(execaModule, 'execa')
179179
// Typecast: It's difficult to provide a full return value for execa
180180
.mockResolvedValue({ stdout: 'line 1\nline 2\nline 3' } as any);
181181

@@ -193,7 +193,7 @@ describe('misc-utils', () => {
193193

194194
it('does not strip leading and trailing whitespace from the output, but does remove empty lines', async () => {
195195
const execaSpy = jest
196-
.spyOn(execaModule, 'default')
196+
.spyOn(execaModule, 'execa')
197197
// Typecast: It's difficult to provide a full return value for execa
198198
.mockResolvedValue({
199199
stdout: ' line 1\nline 2\n\n line 3 \n',

src/repo.ts

+1
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ export async function hasChangesInDirectorySinceGitTag(
309309
tagName,
310310
);
311311

312+
/* istanbul ignore else */
312313
if (!(tagName in CHANGED_FILE_PATHS_BY_TAG_NAME)) {
313314
CHANGED_FILE_PATHS_BY_TAG_NAME[tagName] = changedFilePaths;
314315
}

0 commit comments

Comments
 (0)