Skip to content

Commit

Permalink
Fix Jest ESM compat with Babel
Browse files Browse the repository at this point in the history
  • Loading branch information
rekmarks committed Dec 6, 2023
1 parent 2d54a99 commit 7ac0338
Show file tree
Hide file tree
Showing 6 changed files with 1,603 additions and 89 deletions.
10 changes: 10 additions & 0 deletions babel.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// We use Babel to transpile down ESM dependencies to CommonJS for our tests
// using babel-jest.
module.exports = {
env: {
test: {
presets: ['@babel/preset-env', '@babel/preset-typescript'],
plugins: ['@babel/plugin-transform-modules-commonjs']
}
}
};
40 changes: 33 additions & 7 deletions jest.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,32 @@
* https://jestjs.io/docs/configuration
*/

/**
* Dependencies that are ESM-only, and need to be transpiled by Babel.
* This list is used in the `transformIgnorePatterns` option below.
*
* You probably need to add a dependency to this list if the tests fail with something like:
* - `SyntaxError: Cannot use import statement outside a module`
* - `SyntaxError: Unexpected token 'export'`
* If so, identify the dependency that's causing the error via the stack trace, and add it
* to this list.
*
* No, we do not live in the best of all possible worlds. Why do you ask?
*
* For details on Jest's currently experimental ESM support see: https://github.com/jestjs/jest/issues/9430
*/
const ESM_DEPENDENCIES = [
'execa',
'strip-final-newline',
'npm-run-path',
'path-key',
'onetime',
'mimic-fn',
'human-signals',
'is-stream',
'get-stream',
];

// This file needs to be .cjs for compatibility with jest-it-up.
module.exports = {
// All imported modules in your tests should be mocked automatically
Expand Down Expand Up @@ -103,8 +129,9 @@ module.exports = {
// An enum that specifies notification mode. Requires { notify: true }
// notifyMode: "failure-change",

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

// Run tests from one or more projects
// projects: undefined,
Expand Down Expand Up @@ -189,13 +216,12 @@ module.exports = {
// timers: "real",

// A map from regular expressions to paths to transformers
// transform: undefined,
transform: {
"\\.[jt]sx?$": "babel-jest"
},

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

// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
// unmockedModulePathPatterns: undefined,
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
"yargs": "^17.7.1"
},
"devDependencies": {
"@babel/core": "^7.23.5",
"@babel/plugin-transform-modules-commonjs": "^7.23.3",
"@babel/preset-env": "^7.23.5",
"@babel/preset-typescript": "^7.23.3",
"@lavamoat/allow-scripts": "^2.3.1",
"@metamask/auto-changelog": "^3.0.0",
"@metamask/eslint-config": "^10.0.0",
Expand All @@ -51,6 +55,7 @@
"@types/yargs": "^17.0.10",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"babel-jest": "^29.7.0",
"deepmerge": "^4.2.2",
"eslint": "^8.27.0",
"eslint-config-prettier": "^8.5.0",
Expand Down
8 changes: 4 additions & 4 deletions src/misc-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ describe('misc-utils', () => {
describe('runCommand', () => {
it('runs the command, discarding its output', async () => {
const execaSpy = jest
.spyOn(execaModule, 'default')
.spyOn(execaModule, 'execa')
// Typecast: It's difficult to provide a full return value for execa
.mockResolvedValue({ stdout: ' some output ' } as any);

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

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

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

it('does not strip leading and trailing whitespace from the output, but does remove empty lines', async () => {
const execaSpy = jest
.spyOn(execaModule, 'default')
.spyOn(execaModule, 'execa')
// Typecast: It's difficult to provide a full return value for execa
.mockResolvedValue({
stdout: ' line 1\nline 2\n\n line 3 \n',
Expand Down
1 change: 1 addition & 0 deletions src/repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ export async function hasChangesInDirectorySinceGitTag(
tagName,
);

/* istanbul ignore else */
if (!(tagName in CHANGED_FILE_PATHS_BY_TAG_NAME)) {
CHANGED_FILE_PATHS_BY_TAG_NAME[tagName] = changedFilePaths;
}
Expand Down
Loading

0 comments on commit 7ac0338

Please sign in to comment.