diff --git a/docs/testing.md b/docs/testing.md index 7dca84b8879af9e..7414761d37c3b10 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -293,7 +293,7 @@ module.exports = createJestConfig(customJestConfig) Under the hood, `next/jest` is automatically configuring Jest for you, including: - Setting up `transform` using [SWC](https://nextjs.org/docs/advanced-features/compiler) -- Auto mocking stylesheets (`.css`, `.module.css`, and their scss variants) and image imports +- Auto mocking stylesheets (`.css`, `.module.css`, and their scss variants), image imports and [`@next/font`](https://nextjs.org/docs/basic-features/font-optimization) - Loading `.env` (and all variants) into `process.env` - Ignoring `node_modules` from test resolving and transforms - Ignoring `.next` from test resolving diff --git a/jest.config.js b/jest.config.js index a99f0afcea12b15..177949779f05069 100644 --- a/jest.config.js +++ b/jest.config.js @@ -14,6 +14,9 @@ const customJestConfig = { globals: { AbortSignal: global.AbortSignal, }, + moduleNameMapper: { + '@next/font/(.*)': '@next/font/$1', + }, } // createJestConfig is exported in this way to ensure that next/jest can load the Next.js config which is async diff --git a/packages/next/build/jest/__mocks__/nextFontMock.js b/packages/next/build/jest/__mocks__/nextFontMock.js new file mode 100644 index 000000000000000..f076797502d8e0b --- /dev/null +++ b/packages/next/build/jest/__mocks__/nextFontMock.js @@ -0,0 +1,12 @@ +module.exports = new Proxy( + {}, + { + get: function getter() { + return () => ({ + className: 'className', + variable: 'variable', + style: { fontFamily: 'fontFamily' }, + }) + }, + } +) diff --git a/packages/next/build/jest/jest.ts b/packages/next/build/jest/jest.ts index ef17dc10a189846..8b1e704bc1b0a9d 100644 --- a/packages/next/build/jest/jest.ts +++ b/packages/next/build/jest/jest.ts @@ -115,6 +115,9 @@ export default function nextJest(options: { dir?: string } = {}) { // Keep .svg to it's own rule to make overriding easy '^.+\\.(svg)$': require.resolve(`./__mocks__/fileMock.js`), + // Handle @next/font + '@next/font/(.*)': require.resolve('./__mocks__/nextFontMock.js'), + // custom config comes last to ensure the above rules are matched, // fixes the case where @pages/(.*) -> src/pages/$! doesn't break // CSS/image mocks diff --git a/packages/next/build/swc/options.js b/packages/next/build/swc/options.js index 6dfb154cd0e1faf..673d4a0dd279c5b 100644 --- a/packages/next/build/swc/options.js +++ b/packages/next/build/swc/options.js @@ -33,7 +33,6 @@ function getBaseSWCOptions({ jsConfig, swcCacheDir, isServerLayer, - relativeFilePathFromRoot, hasServerComponents, }) { const parserConfig = getParserOptions({ filename, jsConfig }) @@ -131,15 +130,6 @@ function getBaseSWCOptions({ isServer: !!isServerLayer, } : false, - fontLoaders: - nextConfig?.experimental?.fontLoaders && relativeFilePathFromRoot - ? { - fontLoaders: nextConfig.experimental.fontLoaders.map( - ({ loader }) => loader - ), - relativeFilePathFromRoot, - } - : null, } } @@ -255,6 +245,15 @@ export function getLoaderSWCOptions({ hasServerComponents, }) + if (nextConfig?.experimental?.fontLoaders && relativeFilePathFromRoot) { + baseOptions.fontLoaders = { + fontLoaders: nextConfig.experimental.fontLoaders.map( + ({ loader }) => loader + ), + relativeFilePathFromRoot, + } + } + const isNextDist = nextDistPath.test(filename) if (isServer) { diff --git a/test/production/jest/index.test.ts b/test/production/jest/index.test.ts index 5b831c90260970f..67db89fb5db3ce9 100644 --- a/test/production/jest/index.test.ts +++ b/test/production/jest/index.test.ts @@ -21,6 +21,11 @@ describe('next/jest', () => { import Image from "next/image"; import img from "../public/vercel.svg"; import styles from "../styles/index.module.css"; + import localFont from "@next/font/local"; + import { Inter } from "@next/font/google"; + + const inter = Inter(); + const myFont = localFont({ src: "./my-font.woff2" }); const Comp = dynamic(() => import("../components/comp"), { loading: () =>

Loading...

, @@ -32,6 +37,7 @@ describe('next/jest', () => { logo logo 2

hello world

+

hello world

} `, @@ -118,8 +124,10 @@ describe('next/jest', () => { expect(router.push._isMockFunction).toBeTruthy() }) `, + 'pages/my-font.woff2': 'fake font', }, dependencies: { + '@next/font': 'canary', jest: '27.4.7', '@testing-library/jest-dom': '5.16.1', '@testing-library/react': '12.1.2',