Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 5 commits into from Nov 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/testing.md
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions jest.config.js
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions 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' },
})
},
}
)
3 changes: 3 additions & 0 deletions packages/next/build/jest/jest.ts
Expand Up @@ -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
Expand Down
19 changes: 9 additions & 10 deletions packages/next/build/swc/options.js
Expand Up @@ -33,7 +33,6 @@ function getBaseSWCOptions({
jsConfig,
swcCacheDir,
isServerLayer,
relativeFilePathFromRoot,
hasServerComponents,
}) {
const parserConfig = getParserOptions({ filename, jsConfig })
Expand Down Expand Up @@ -131,15 +130,6 @@ function getBaseSWCOptions({
isServer: !!isServerLayer,
}
: false,
fontLoaders:
nextConfig?.experimental?.fontLoaders && relativeFilePathFromRoot
? {
fontLoaders: nextConfig.experimental.fontLoaders.map(
({ loader }) => loader
),
relativeFilePathFromRoot,
}
: null,
}
}

Expand Down Expand Up @@ -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) {
Expand Down
8 changes: 8 additions & 0 deletions test/production/jest/index.test.ts
Expand Up @@ -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: () => <h1>Loading...</h1>,
Expand All @@ -32,6 +37,7 @@ describe('next/jest', () => {
<Image src={img} alt="logo" placeholder="blur"/>
<Image src={img} alt="logo 2"/>
<p className={styles.home}>hello world</p>
<p style={{ fontFamily: inter.style.fontFamily }} className={myFont.className}>hello world</p>
</>
}
`,
Expand Down Expand Up @@ -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',
Expand Down