Commit 37637356 by PLN (Algolia)

jest: own the transform pipeline — next/jest force-ignores /node_modules/ even…

jest: own the transform pipeline — next/jest force-ignores /node_modules/ even in PnP cache paths, so ESM deps shipped untransformed and the whole suite never ran
Co-Authored-By: 's avatarClaude Opus 5 <noreply@anthropic.com>
parent 9fbe130f
const nextJest = require('next/jest');
/** /**
* Jest config for the Next.js app (root: next/). * Jest config for the Next.js app.
* Uses next/jest SWC transformer and jsdom environment.
* Yarn PnP compatible via jest-pnp-resolver. * Yarn PnP compatible via jest-pnp-resolver.
*
* Why not next/jest: its config factory hard-prepends `/node_modules/` to
* transformIgnorePatterns ("custom config can append but not modify it").
* Under Yarn PnP every dependency resolves into a cache path shaped
* `…/<pkg>.zip/node_modules/<pkg>/…`, so the pattern matches ALL deps and the
* ESM-only unified markdown chain (unified, remark-*, shiki…) is shipped
* untransformed to the CJS runtime, which cannot parse `export`. We keep the
* same SWC transformer next/jest uses, plus the same CSS/image/font mocks,
* but own the ignore list: only CSS modules are excluded, so dependencies in
* the PnP cache get transformed like source files.
*/ */
const createJestConfig = nextJest({
dir: './', // Next's SWC transformer (the one next/jest wraps) and the mocks next/jest
}); // used to inject, resolved from the PnP cache.
const transformerPath = require.resolve('next/dist/build/swc/jest-transformer.js');
const objectProxy = require.resolve('next/dist/build/jest/object-proxy.js');
const styleMock = require.resolve('next/dist/build/jest/__mocks__/styleMock.js');
const fileMock = require.resolve('next/dist/build/jest/__mocks__/fileMock.js');
const nextFontMock = require.resolve('next/dist/build/jest/__mocks__/nextFontMock.js');
const emptyMock = require.resolve('next/dist/build/jest/__mocks__/empty.js');
/** @type {import('jest').Config} */ /** @type {import('jest').Config} */
const customJestConfig = { const customJestConfig = {
...@@ -16,24 +29,30 @@ const customJestConfig = { ...@@ -16,24 +29,30 @@ const customJestConfig = {
// Enable RTL matchers and router mocks // Enable RTL matchers and router mocks
setupFilesAfterEnv: ['<rootDir>/tests/jest.setup.js'], setupFilesAfterEnv: ['<rootDir>/tests/jest.setup.js'],
moduleNameMapper: { moduleNameMapper: {
// Support @/ alias → next/ path root // CSS modules → proxy returning class names; plain css/style/fonts → mocks
'^.+\\.module\\.(css|sass|scss)$': objectProxy,
'^.+\\.(css|sass|scss)$': styleMock,
'^.+\\.(png|jpg|jpeg|gif|webp|avif|ico|bmp|svg)$': fileMock,
'@next/font/(.*)': nextFontMock,
'next/font/(.*)': nextFontMock,
'^server-only$': emptyMock,
// Support @/ alias → repo root
'^@/(.*)$': '<rootDir>/$1', '^@/(.*)$': '<rootDir>/$1',
}, },
// Next's own SWC transformer (the one next/jest wraps), applied to source
// AND PnP-cached dependencies (see header note).
transform: {
'^.+\\.(js|jsx|ts|tsx|mjs)$': [transformerPath, {}],
},
transformIgnorePatterns: [
'^.+\\.module\\.(css|sass|scss)$',
],
testPathIgnorePatterns: [ testPathIgnorePatterns: [
'<rootDir>/.next/', '<rootDir>/.next/',
'<rootDir>/node_modules/',
'<rootDir>/tests/e2e/', '<rootDir>/tests/e2e/',
], ],
// Allow JSX in tests without explicit React import if using React 17+ JSX transform.
// Under Yarn PnP there are no real node_modules dirs — dependencies live in
// cache zips whose paths *contain* /node_modules/ segments, so excluding that
// pattern would skip transforming the ESM-only unified chain. Only the css
// module mocks (handled by next/jest) stay out of the transform.
transformIgnorePatterns: [
'^.+\\.module\\.(css|sass|scss)$',
],
// Make sure Jest can find our mocks // Make sure Jest can find our mocks
moduleDirectories: ['node_modules', '<rootDir>'], moduleDirectories: ['node_modules', '<rootDir>'],
}; };
module.exports = createJestConfig(customJestConfig); module.exports = customJestConfig;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment