Mock @next/font when using next/jest (#42413)

Mock `@next/font` when using `next/jest`.

fixes #42379

## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the
feature request has been accepted for implementation before opening a
PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm build && pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
This commit is contained in:
Hannes Bornö 2022-11-03 19:12:46 +01:00 committed by GitHub
parent 73c5b77a84
commit 539769dddc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 11 deletions

View file

@ -293,7 +293,7 @@ module.exports = createJestConfig(customJestConfig)
Under the hood, `next/jest` is automatically configuring Jest for you, including: Under the hood, `next/jest` is automatically configuring Jest for you, including:
- Setting up `transform` using [SWC](https://nextjs.org/docs/advanced-features/compiler) - 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` - Loading `.env` (and all variants) into `process.env`
- Ignoring `node_modules` from test resolving and transforms - Ignoring `node_modules` from test resolving and transforms
- Ignoring `.next` from test resolving - Ignoring `.next` from test resolving

View file

@ -14,6 +14,9 @@ const customJestConfig = {
globals: { globals: {
AbortSignal: global.AbortSignal, 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 // createJestConfig is exported in this way to ensure that next/jest can load the Next.js config which is async

View file

@ -0,0 +1,12 @@
module.exports = new Proxy(
{},
{
get: function getter() {
return () => ({
className: 'className',
variable: 'variable',
style: { fontFamily: 'fontFamily' },
})
},
}
)

View file

@ -115,6 +115,9 @@ export default function nextJest(options: { dir?: string } = {}) {
// Keep .svg to it's own rule to make overriding easy // Keep .svg to it's own rule to make overriding easy
'^.+\\.(svg)$': require.resolve(`./__mocks__/fileMock.js`), '^.+\\.(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, // custom config comes last to ensure the above rules are matched,
// fixes the case where @pages/(.*) -> src/pages/$! doesn't break // fixes the case where @pages/(.*) -> src/pages/$! doesn't break
// CSS/image mocks // CSS/image mocks

View file

@ -33,7 +33,6 @@ function getBaseSWCOptions({
jsConfig, jsConfig,
swcCacheDir, swcCacheDir,
isServerLayer, isServerLayer,
relativeFilePathFromRoot,
hasServerComponents, hasServerComponents,
}) { }) {
const parserConfig = getParserOptions({ filename, jsConfig }) const parserConfig = getParserOptions({ filename, jsConfig })
@ -131,15 +130,6 @@ function getBaseSWCOptions({
isServer: !!isServerLayer, isServer: !!isServerLayer,
} }
: false, : false,
fontLoaders:
nextConfig?.experimental?.fontLoaders && relativeFilePathFromRoot
? {
fontLoaders: nextConfig.experimental.fontLoaders.map(
({ loader }) => loader
),
relativeFilePathFromRoot,
}
: null,
} }
} }
@ -255,6 +245,15 @@ export function getLoaderSWCOptions({
hasServerComponents, hasServerComponents,
}) })
if (nextConfig?.experimental?.fontLoaders && relativeFilePathFromRoot) {
baseOptions.fontLoaders = {
fontLoaders: nextConfig.experimental.fontLoaders.map(
({ loader }) => loader
),
relativeFilePathFromRoot,
}
}
const isNextDist = nextDistPath.test(filename) const isNextDist = nextDistPath.test(filename)
if (isServer) { if (isServer) {

View file

@ -21,6 +21,11 @@ describe('next/jest', () => {
import Image from "next/image"; import Image from "next/image";
import img from "../public/vercel.svg"; import img from "../public/vercel.svg";
import styles from "../styles/index.module.css"; 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"), { const Comp = dynamic(() => import("../components/comp"), {
loading: () => <h1>Loading...</h1>, loading: () => <h1>Loading...</h1>,
@ -32,6 +37,7 @@ describe('next/jest', () => {
<Image src={img} alt="logo" placeholder="blur"/> <Image src={img} alt="logo" placeholder="blur"/>
<Image src={img} alt="logo 2"/> <Image src={img} alt="logo 2"/>
<p className={styles.home}>hello world</p> <p className={styles.home}>hello world</p>
<p style={{ fontFamily: inter.style.fontFamily }} className={myFont.className}>hello world</p>
</> </>
} }
`, `,
@ -118,8 +124,10 @@ describe('next/jest', () => {
expect(router.push._isMockFunction).toBeTruthy() expect(router.push._isMockFunction).toBeTruthy()
}) })
`, `,
'pages/my-font.woff2': 'fake font',
}, },
dependencies: { dependencies: {
'@next/font': 'canary',
jest: '27.4.7', jest: '27.4.7',
'@testing-library/jest-dom': '5.16.1', '@testing-library/jest-dom': '5.16.1',
'@testing-library/react': '12.1.2', '@testing-library/react': '12.1.2',