Skip to content

Commit

Permalink
Enable jest hoist transform when using next/jest (#33731)
Browse files Browse the repository at this point in the history
Fixes #32539

Implements what was shared at #32539 (comment).



## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have 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 helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `yarn lint`
  • Loading branch information
timneutkens committed Jan 31, 2022
1 parent 5b31c18 commit 3bac02e
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 5 deletions.
8 changes: 8 additions & 0 deletions packages/next/build/swc/options.js
Expand Up @@ -38,6 +38,14 @@ export function getBaseSWCOptions({
},

transform: {
// Enables https://github.com/swc-project/swc/blob/0359deb4841be743d73db4536d4a22ac797d7f65/crates/swc_ecma_ext_transforms/src/jest.rs
...(jest
? {
hidden: {
jest: true,
},
}
: {}),
legacyDecorator: enableDecorators,
react: {
importSource: jsConfig?.compilerOptions?.jsxImportSource || 'react',
Expand Down
7 changes: 6 additions & 1 deletion test/lib/create-next-install.js
Expand Up @@ -6,7 +6,11 @@ const childProcess = require('child_process')
const { linkPackages } =
require('../../.github/actions/next-stats-action/src/prepare/repo-setup')()

async function createNextInstall(dependencies, installCommand) {
async function createNextInstall(
dependencies,
installCommand,
packageJson = {}
) {
const tmpDir = await fs.realpath(process.env.NEXT_TEST_DIR || os.tmpdir())
const origRepoDir = path.join(__dirname, '../../')
const installDir = path.join(tmpDir, `next-install-${Date.now()}`)
Expand Down Expand Up @@ -56,6 +60,7 @@ async function createNextInstall(dependencies, installCommand) {
path.join(installDir, 'package.json'),
JSON.stringify(
{
...packageJson,
dependencies: combinedDependencies,
private: true,
},
Expand Down
3 changes: 2 additions & 1 deletion test/lib/e2e-utils.ts
@@ -1,7 +1,7 @@
import path from 'path'
import assert from 'assert'
import { NextConfig } from 'next'
import { InstallCommand, NextInstance } from './next-modes/base'
import { InstallCommand, NextInstance, PackageJson } from './next-modes/base'
import { NextDevInstance } from './next-modes/next-dev'
import { NextStartInstance } from './next-modes/next-start'

Expand Down Expand Up @@ -113,6 +113,7 @@ export async function createNext(opts: {
skipStart?: boolean
installCommand?: InstallCommand
buildCommand?: string
packageJson?: PackageJson
startCommand?: string
}): Promise<NextInstance> {
try {
Expand Down
11 changes: 10 additions & 1 deletion test/lib/next-modes/base.ts
Expand Up @@ -12,6 +12,9 @@ export type InstallCommand =
| string
| ((ctx: { dependencies: { [key: string]: string } }) => string)

export type PackageJson = {
[key: string]: unknown
}
export class NextInstance {
protected files: {
[filename: string]: string | FileRef
Expand All @@ -28,6 +31,7 @@ export class NextInstance {
protected childProcess: ChildProcess
protected _url: string
protected _parsedUrl: URL
protected packageJson: PackageJson

constructor({
files,
Expand All @@ -36,13 +40,15 @@ export class NextInstance {
installCommand,
buildCommand,
startCommand,
packageJson = {},
}: {
files: {
[filename: string]: string | FileRef
}
dependencies?: {
[name: string]: string
}
packageJson?: PackageJson
nextConfig?: NextConfig
installCommand?: InstallCommand
buildCommand?: string
Expand All @@ -54,6 +60,7 @@ export class NextInstance {
this.installCommand = installCommand
this.buildCommand = buildCommand
this.startCommand = startCommand
this.packageJson = packageJson
this.events = {}
this.isDestroyed = false
this.isStopping = false
Expand Down Expand Up @@ -86,8 +93,10 @@ export class NextInstance {
react: 'latest',
'react-dom': 'latest',
...this.dependencies,
...((this.packageJson.dependencies as object | undefined) || {}),
},
this.installCommand
this.installCommand,
this.packageJson
)
}
console.log('created next.js install, writing test files')
Expand Down
74 changes: 74 additions & 0 deletions test/production/next/jest/index.test.ts
@@ -0,0 +1,74 @@
import { createNext } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'
import { renderViaHTTP } from 'next-test-utils'

describe('next/jest', () => {
let next: NextInstance

beforeAll(async () => {
next = await createNext({
files: {
'pages/index.js': `
export default function Page() {
return <p>hello world</p>
}
`,
'jest.config.js': `
// jest.config.js
const nextJest = require('next/jest')
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
})
// Add any custom config to be passed to Jest
const customJestConfig = {
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig)
`,
'test/mock.test.js': `
import router from 'next/router'
jest.mock('next/router', () => ({
push: jest.fn(),
back: jest.fn(),
events: {
on: jest.fn(),
off: jest.fn(),
},
asPath: jest.fn().mockReturnThis(),
beforePopState: jest.fn(() => null),
useRouter: () => ({
push: jest.fn(),
}),
}))
it('call mocked', async () => {
expect(router.push._isMockFunction).toBeTruthy()
})
`,
},
dependencies: {
jest: '27.4.7',
},
packageJson: {
scripts: {
build: 'next build && yarn jest test/mock.test.js',
},
},
buildCommand: `yarn build`,
})
})
afterAll(() => next.destroy())

it('should work', async () => {
const html = await renderViaHTTP(next.url, '/')
expect(html).toContain('hello world')
})
})
3 changes: 1 addition & 2 deletions yarn.lock
Expand Up @@ -20572,8 +20572,7 @@ webpack-bundle-analyzer@4.3.0:
source-list-map "^2.0.0"
source-map "~0.6.1"

"webpack-sources3@npm:webpack-sources@3.2.3", webpack-sources@^3.2.3:
name webpack-sources3
"webpack-sources3@npm:webpack-sources@3.2.3", webpack-sources@^3.2.2, webpack-sources@^3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
Expand Down

0 comments on commit 3bac02e

Please sign in to comment.