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

Enable jest hoist transform when using next/jest #33731

Merged
merged 5 commits into from Jan 31, 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
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