Jest config with "next/jest" not picking up "babel-plugin-formatjs" on v. 12.1.6/12.1.7-canary.40
Verify canary release
- [X] I verified that the issue exists in Next.js canary release
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 21.5.0: Tue Apr 26 21:08:29 PDT 2022; root:xnu-8020.121.3~4/RELEASE_ARM64_T8101
Binaries:
Node: 16.14.2
npm: 8.5.0
Yarn: 1.22.11
pnpm: N/A
Relevant packages:
next: 12.1.7-canary.40
react: 18.2.0
react-dom: 18.2.0
What browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
Describe the Bug
Trying to add the babel-plugin-formatjs plugin to Jest testing environment. It automatically injects hash generated IDs for translations. This works on 12.1.0 but with newer releases I only get non-specific error message when I run yarn test:
FAIL test/index.test.tsx
✕ renders (41 ms)
● renders
[@formatjs/intl] An `id` must be provided to format a message. You can either:
1. Configure your build toolchain with [babel-plugin-formatjs](https://formatjs.io/docs/tooling/babel-plugin)
or [@formatjs/ts-transformer](https://formatjs.io/docs/tooling/ts-transformer) OR
2. Configure your `eslint` config to include [eslint-plugin-formatjs](https://formatjs.io/docs/tooling/linter#enforce-id)
to autofix this issue
11 | <div className={styles.container}>
12 | <Head>
> 13 | <title>{intl.formatMessage({ defaultMessage: 'Create Next App' })}</title>
My configuration:
.babelrc:
{
"presets": ["next/babel"],
"plugins": ["formatjs"]
}
jest.config.js:
const nextJest = require('next/jest');
const createJestConfig = nextJest({ dir: './' });
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
moduleNameMapper: {
'^@components/(.*)$': '<rootDir>/components/$1',
'^@containers/(.*)$': '<rootDir>/containers/$1',
'^@lib/(.*)$': '<rootDir>/lib/$1',
},
transform: {
//
// THIS WORKS ON NEXT 12.1.0:
//
// Use babel-jest to transpile tests with the next/babel preset (ELSE test will FAIL due to missing ID)
// https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
'^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }],
},
};
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);
jest.setup.js:
import '@testing-library/jest-dom/extend-expect';
Installed dependencies:
{
"dependencies": {
"next": "12.1.7-canary.40",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-intl": "^6.0.4"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@types/node": "18.0.0",
"@types/react": "18.0.13",
"@types/react-dom": "18.0.5",
"babel-jest": "^28.1.1",
"babel-plugin-formatjs": "^10.3.24",
"eslint": "8.17.0",
"eslint-config-next": "12.1.6",
"git18n": "^1.0.4",
"jest": "^28.1.1",
"jest-environment-jsdom": "^28.1.1",
"typescript": "4.7.3"
}
}
I am unsure which direction to look in. Has Next changed how it load Jest configuration/Babel plugins?
Expected Behavior
It should load the babel-plugin-formatjs as previously.
To Reproduce
Install the package and run yarn test:
{
"name": "next-hash-ids",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "yarn git18n && next build",
"start": "next start",
"lint": "next lint",
"translate": "git18n --files '(pages|components)/**/*.{js,jsx,ts,tsx}'",
"test": "jest",
"test:staged": "jest --bail --findRelatedTests",
"test-watch": "jest --watchAll",
"test-coverage": "jest --coverage"
},
"dependencies": {
"next": "12.1.7-canary.40",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-intl": "^6.0.4"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@types/node": "18.0.0",
"@types/react": "18.0.13",
"@types/react-dom": "18.0.5",
"babel-jest": "^28.1.1",
"babel-plugin-formatjs": "^10.3.24",
"eslint": "8.17.0",
"eslint-config-next": "12.1.6",
"git18n": "^1.0.4",
"jest": "^28.1.1",
"jest-environment-jsdom": "^28.1.1",
"typescript": "4.7.3"
}
}
I too noticed with latest versions from 12.1.5 to 12.2.5 that jest is not picking up babel config
It works without createJestConfig()
I can confirm the problem. Related to formatjs/formatjs#3789. I believe it's something related to how Jest transform is set up using the SWC compiler.
I created the following code sandbox: https://codesandbox.io/s/admiring-currying-0phokz
I am not using Next.js but encountered this problem. I wound up upgrading all @babel packages (including babel-jest & babel-plugin-formatjs), but only after I upgraded to jest 29 did the issue go away.
For the jest.config.js file in the original issue description:
I found that with Next.js 13.1.0, changing the "transform" line to
"^.+\\.(js|jsx|ts|tsx|mjs)$": ["babel-jest", { presets: ["next/babel"] }],
allowed Babel + plugins to work in my Jest tests. Note, specifically, that the key includes the "mjs" file suffix. This works because the key now matches the one provided by next/js and overrides it, switching the transformer from SWC to Babel.