Replace createNextDescribe with nextTestSetup (#64817)

<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:

## For Contributors

### Improving Documentation

- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide

### Adding or Updating Examples

- The "examples guidelines" are followed from our contributing doc
https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See
https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md

### Fixing a bug

- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md

### Adding a feature

- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md


## For Maintainers

- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Closes NEXT-
Fixes #

-->

I took some time and [wrote a
codemod](https://gist.github.com/wyattjoh/0d4464427506cb02062a4729ca906b62)
that replaces the old usage of the `createNextDescribe` with the new
`nextTestSetup`. You'll likely have to turn on hiding of whitespace in
order to review, but this should primarily introduce no changes to the
test structure other than using the new mechanism now.

Closes NEXT-3178
This commit is contained in:
Wyatt Johnson 2024-04-25 12:06:12 -06:00 committed by GitHub
parent a6a6117197
commit c6320ed87a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
230 changed files with 27760 additions and 28255 deletions

View file

@ -1,6 +1,6 @@
import path from 'path' import path from 'path'
import { outdent } from 'outdent' import { outdent } from 'outdent'
import { FileRef, createNextDescribe } from 'e2e-utils' import { FileRef, nextTestSetup } from 'e2e-utils'
import { import {
check, check,
getRedboxDescription, getRedboxDescription,
@ -10,12 +10,11 @@ import {
retry, retry,
} from 'next-test-utils' } from 'next-test-utils'
createNextDescribe( describe('Error overlay - RSC runtime errors', () => {
'Error overlay - RSC runtime errors', const { next } = nextTestSetup({
{
files: new FileRef(path.join(__dirname, 'fixtures', 'rsc-runtime-errors')), files: new FileRef(path.join(__dirname, 'fixtures', 'rsc-runtime-errors')),
}, })
({ next }) => {
it('should show runtime errors if invalid client API from node_modules is executed', async () => { it('should show runtime errors if invalid client API from node_modules is executed', async () => {
await next.patchFile( await next.patchFile(
'app/server/page.js', 'app/server/page.js',
@ -148,5 +147,4 @@ createNextDescribe(
// Does not contain webpack traces in file path // Does not contain webpack traces in file path
expect(source).not.toMatch(/webpack(-internal:)?\/\//) expect(source).not.toMatch(/webpack(-internal:)?\/\//)
}) })
} })
)

View file

@ -1,14 +1,13 @@
/* eslint-env jest */ /* eslint-env jest */
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { getRedboxComponentStack, hasRedbox } from 'next-test-utils' import { getRedboxComponentStack, hasRedbox } from 'next-test-utils'
import path from 'path' import path from 'path'
createNextDescribe( describe('Component Stack in error overlay', () => {
'Component Stack in error overlay', const { next } = nextTestSetup({
{
files: path.join(__dirname, 'fixtures', 'component-stack'), files: path.join(__dirname, 'fixtures', 'component-stack'),
}, })
({ next }) => {
it('should show a component stack on hydration error', async () => { it('should show a component stack on hydration error', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
@ -38,5 +37,4 @@ createNextDescribe(
`) `)
} }
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('app-dir - app routes errors', () => {
'app-dir - app routes errors', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
describe('bad lowercase exports', () => { describe('bad lowercase exports', () => {
it.each([ it.each([
['get'], ['get'],
@ -36,5 +35,4 @@ createNextDescribe(
} }
) )
}) })
} })
)

View file

@ -1,4 +1,4 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { import {
getRedboxCallStack, getRedboxCallStack,
hasRedbox, hasRedbox,
@ -7,9 +7,8 @@ import {
getRedboxSource, getRedboxSource,
} from 'next-test-utils' } from 'next-test-utils'
createNextDescribe( describe('app dir - dynamic error trace', () => {
'app dir - dynamic error trace', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
dependencies: { dependencies: {
swr: 'latest', swr: 'latest',
@ -25,8 +24,9 @@ createNextDescribe(
startCommand: (global as any).isNextDev ? 'pnpm dev' : 'pnpm start', startCommand: (global as any).isNextDev ? 'pnpm dev' : 'pnpm start',
buildCommand: 'pnpm build', buildCommand: 'pnpm build',
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => { if (skipped) return
it('should show the error trace', async () => { it('should show the error trace', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
await hasRedbox(browser) await hasRedbox(browser)
@ -38,5 +38,4 @@ createNextDescribe(
const source = await getRedboxSource(browser) const source = await getRedboxSource(browser)
expect(source).toContain('app/lib.js') expect(source).toContain('app/lib.js')
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { hasRedbox } from 'next-test-utils' import { hasRedbox } from 'next-test-utils'
createNextDescribe( describe('develop - app-dir - edge errros hmr', () => {
'develop - app-dir - edge errros hmr', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should recover from build errors when server component error', async () => { it('should recover from build errors when server component error', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
const clientComponentSource = await next.readFile('app/comp.server.js') const clientComponentSource = await next.readFile('app/comp.server.js')
@ -36,5 +35,4 @@ createNextDescribe(
expect(await hasRedbox(browser)).toBe(false) expect(await hasRedbox(browser)).toBe(false)
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { hasRedbox } from 'next-test-utils' import { hasRedbox } from 'next-test-utils'
createNextDescribe( describe('HMR Move File', () => {
'HMR Move File', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should work when moving a component to another directory', async () => { it('should work when moving a component to another directory', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await browser.elementByCss('#hello-world-button').text()).toBe( expect(await browser.elementByCss('#hello-world-button').text()).toBe(
@ -24,5 +23,4 @@ createNextDescribe(
'hello world' 'hello world'
) )
}) })
} })
)

View file

@ -1,11 +1,10 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('multiple-compiles-single-route', () => {
'multiple-compiles-single-route', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
// Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API. // Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API.
it('should not compile additional matching paths', async () => { it('should not compile additional matching paths', async () => {
const logs: string[] = [] const logs: string[] = []
@ -16,5 +15,4 @@ createNextDescribe(
// Check if `/[slug]` is mentioned in the logs as being compiled // Check if `/[slug]` is mentioned in the logs as being compiled
expect(logs.some((log) => log.includes('/[slug]'))).toBe(false) expect(logs.some((log) => log.includes('/[slug]'))).toBe(false)
}) })
} })
)

View file

@ -1,13 +1,11 @@
import { type BrowserInterface } from 'next-webdriver' import { type BrowserInterface } from 'next-webdriver'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('Strict Mode enabled by default', () => {
'Strict Mode enabled by default', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
// experimental react is having issues with this use effect // experimental react is having issues with this use effect
// @acdlite will take a look // @acdlite will take a look
// TODO: remove this after react fixes the issue in experimental build. // TODO: remove this after react fixes the issue in experimental build.
@ -23,5 +21,4 @@ createNextDescribe(
return text === '2' ? 'success' : `failed: ${text}` return text === '2' ? 'success' : `failed: ${text}`
}, 'success') }, 'success')
}) })
} })
)

View file

@ -1,14 +1,13 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check, waitFor } from 'next-test-utils' import { check, waitFor } from 'next-test-utils'
const envFile = '.env.development.local' const envFile = '.env.development.local'
createNextDescribe( describe(`app-dir-hmr`, () => {
`app-dir-hmr`, const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
describe('filesystem changes', () => { describe('filesystem changes', () => {
it('should not continously poll when hitting a not found page', async () => { it('should not continously poll when hitting a not found page', async () => {
let requestCount = 0 let requestCount = 0
@ -92,5 +91,4 @@ createNextDescribe(
expect(next.cliOutput).not.toContain('Unexpected action') expect(next.cliOutput).not.toContain('Unexpected action')
}) })
}) })
} })
)

View file

@ -1,12 +1,10 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('app-render-error-log', () => {
'app-render-error-log', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should log the correct values on app-render error', async () => { it('should log the correct values on app-render error', async () => {
const outputIndex = next.cliOutput.length const outputIndex = next.cliOutput.length
await next.fetch('/') await next.fetch('/')
@ -38,5 +36,4 @@ createNextDescribe(
expect(cliOutput).not.toInclude('webpack-internal') expect(cliOutput).not.toInclude('webpack-internal')
}) })
} })
)

View file

@ -1,13 +1,12 @@
import { join } from 'path' import { join } from 'path'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('asset-prefix', () => {
'asset-prefix', const { next } = nextTestSetup({
{
files: join(__dirname, 'fixture'), files: join(__dirname, 'fixture'),
}, })
({ next }) => {
it('should load the app properly without reloading', async () => { it('should load the app properly without reloading', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
await browser.eval(`window.__v = 1`) await browser.eval(`window.__v = 1`)
@ -24,5 +23,4 @@ createNextDescribe(
expect(await browser.eval(`window.__v`)).toBe(1) expect(await browser.eval(`window.__v`)).toBe(1)
}) })
} })
)

View file

@ -1,13 +1,13 @@
import { join } from 'path' import { join } from 'path'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { hasRedbox } from 'next-test-utils' import { hasRedbox } from 'next-test-utils'
// Skipped in Turbopack, will be added later. // Skipped in Turbopack, will be added later.
;(process.env.TURBOPACK ? describe.skip : describe)( ;(process.env.TURBOPACK ? describe.skip : describe)(
'Skipped in Turbopack', 'Skipped in Turbopack',
() => { () => {
createNextDescribe( describe('optimizePackageImports - mui', () => {
'optimizePackageImports - mui', const { next } = nextTestSetup({
{
env: { env: {
NEXT_TEST_MODE: '1', NEXT_TEST_MODE: '1',
}, },
@ -18,8 +18,8 @@ import { hasRedbox } from 'next-test-utils'
'@emotion/react': '11.11.1', '@emotion/react': '11.11.1',
'@emotion/styled': '11.11.0', '@emotion/styled': '11.11.0',
}, },
}, })
({ next }) => {
it('should support MUI', async () => { it('should support MUI', async () => {
let logs = '' let logs = ''
next.on('stdout', (log) => { next.on('stdout', (log) => {
@ -42,7 +42,6 @@ import { hasRedbox } from 'next-test-utils'
expect(parseInt(moduleCount)).toBeLessThan(1500) expect(parseInt(moduleCount)).toBeLessThan(1500)
} }
}) })
} })
)
} }
) )

View file

@ -1,10 +1,9 @@
import { join } from 'path' import { join } from 'path'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { hasRedbox } from 'next-test-utils' import { hasRedbox } from 'next-test-utils'
createNextDescribe( describe('optimizePackageImports - mui', () => {
'optimizePackageImports - mui', const { next } = nextTestSetup({
{
env: { env: {
NEXT_TEST_MODE: '1', NEXT_TEST_MODE: '1',
}, },
@ -16,12 +15,11 @@ createNextDescribe(
'@remixicon/react': '^4.2.0', '@remixicon/react': '^4.2.0',
'@tremor/react': '^3.14.1', '@tremor/react': '^3.14.1',
}, },
}, })
({ next }) => {
it('should work', async () => { it('should work', async () => {
// Without barrel optimization, the reproduction breaks. // Without barrel optimization, the reproduction breaks.
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await hasRedbox(browser)).toBe(false) expect(await hasRedbox(browser)).toBe(false)
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { join } from 'path' import { join } from 'path'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
// Skipped in Turbopack, will be added later. // Skipped in Turbopack, will be added later.
;(process.env.TURBOPACK ? describe.skip : describe)( ;(process.env.TURBOPACK ? describe.skip : describe)(
'Skipped in Turbopack', 'Skipped in Turbopack',
() => { () => {
createNextDescribe( describe('optimizePackageImports - basic', () => {
'optimizePackageImports - basic', const { next } = nextTestSetup({
{
env: { env: {
NEXT_TEST_MODE: '1', NEXT_TEST_MODE: '1',
}, },
@ -18,8 +17,8 @@ import { createNextDescribe } from 'e2e-utils'
'@visx/visx': '3.3.0', '@visx/visx': '3.3.0',
'recursive-barrel': '1.0.0', 'recursive-barrel': '1.0.0',
}, },
}, })
({ next }) => {
it('app - should render the icons correctly without creating all the modules', async () => { it('app - should render the icons correctly without creating all the modules', async () => {
let logs = '' let logs = ''
next.on('stdout', (log) => { next.on('stdout', (log) => {
@ -125,7 +124,6 @@ import { createNextDescribe } from 'e2e-utils'
const html = await next.render('/client-boundary') const html = await next.render('/client-boundary')
expect(html).toContain('<button>0</button>') expect(html).toContain('<button>0</button>')
}) })
} })
)
} }
) )

View file

@ -1,11 +1,10 @@
import { join } from 'path' import { join } from 'path'
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('useDefineForClassFields SWC option', () => {
'useDefineForClassFields SWC option', const { next } = nextTestSetup({
{
files: join(__dirname, 'fixture'), files: join(__dirname, 'fixture'),
dependencies: { dependencies: {
mobx: '6.3.7', mobx: '6.3.7',
@ -14,8 +13,8 @@ createNextDescribe(
'@types/node': 'latest', '@types/node': 'latest',
'mobx-react': '7.2.1', 'mobx-react': '7.2.1',
}, },
}, })
({ next }) => {
it('tsx should compile with useDefineForClassFields enabled', async () => { it('tsx should compile with useDefineForClassFields enabled', async () => {
let browser let browser
try { try {
@ -76,5 +75,4 @@ createNextDescribe(
} }
} }
}) })
} })
)

View file

@ -1,17 +1,16 @@
import { join } from 'path' import { join } from 'path'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('emotion SWC option', () => {
'emotion SWC option', const { next } = nextTestSetup({
{
files: join(__dirname, 'fixture'), files: join(__dirname, 'fixture'),
dependencies: { dependencies: {
'@emotion/react': '11.10.4', '@emotion/react': '11.10.4',
'@emotion/styled': '11.10.4', '@emotion/styled': '11.10.4',
'@emotion/cache': '11.10.3', '@emotion/cache': '11.10.3',
}, },
}, })
({ next }) => {
it('should have styling from the css prop', async () => { it('should have styling from the css prop', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
@ -20,5 +19,4 @@ createNextDescribe(
.getComputedCss('background-color') .getComputedCss('background-color')
expect(color).toBe('rgb(255, 192, 203)') expect(color).toBe('rgb(255, 192, 203)')
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { join } from 'path' import { join } from 'path'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('node builtins', () => {
'node builtins', const { next } = nextTestSetup({
{
files: join(__dirname, 'node-builtins'), files: join(__dirname, 'node-builtins'),
}, })
({ next }) => {
it('should have polyfilled node.js builtins for the browser correctly', async () => { it('should have polyfilled node.js builtins for the browser correctly', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
@ -168,5 +167,4 @@ createNextDescribe(
expect(parsedData.sys).toBe(true) expect(parsedData.sys).toBe(true)
expect(parsedData.timers).toBe(true) expect(parsedData.timers).toBe(true)
}) })
} })
)

View file

@ -1,16 +1,14 @@
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { fetchViaHTTP, renderViaHTTP } from 'next-test-utils' import { fetchViaHTTP, renderViaHTTP } from 'next-test-utils'
createNextDescribe( describe('styled-components SWC transform', () => {
'styled-components SWC transform', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
dependencies: { dependencies: {
'styled-components': '5.3.3', 'styled-components': '5.3.3',
}, },
}, })
({ next }) => {
async function matchLogs$(browser) { async function matchLogs$(browser) {
let foundLog = false let foundLog = false
@ -84,5 +82,4 @@ createNextDescribe(
outputs.filter((output) => output.trim() === '__render__').length outputs.filter((output) => output.trim() === '__render__').length
).toBe(1) ).toBe(1)
}) })
} })
)

View file

@ -1,19 +1,17 @@
import { join } from 'path' import { join } from 'path'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('theme-ui SWC option', () => {
'theme-ui SWC option', const { next } = nextTestSetup({
{
files: join(__dirname, 'fixture'), files: join(__dirname, 'fixture'),
dependencies: { dependencies: {
'theme-ui': '0.12.0', 'theme-ui': '0.12.0',
}, },
}, })
({ next }) => {
it('should have theme provided styling', async () => { it('should have theme provided styling', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
const color = await browser.elementByCss('#hello').getComputedCss('color') const color = await browser.elementByCss('#hello').getComputedCss('color')
expect(color).toBe('rgb(51, 51, 238)') expect(color).toBe('rgb(51, 51, 238)')
}) })
} })
)

View file

@ -1,14 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('Handles Duplicate Pages', () => {
'Handles Duplicate Pages', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('Shows warning in development', async () => { it('Shows warning in development', async () => {
await next.render('/hello') await next.render('/hello')
expect(next.cliOutput).toMatch(/Duplicate page detected/) expect(next.cliOutput).toMatch(/Duplicate page detected/)
}) })
} })
)

View file

@ -1,17 +1,17 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import https from 'https' import https from 'https'
import { renderViaHTTP, shouldRunTurboDevTest } from 'next-test-utils' import { renderViaHTTP, shouldRunTurboDevTest } from 'next-test-utils'
createNextDescribe( describe('experimental-https-server (generated certificate)', () => {
'experimental-https-server (generated certificate)', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
startCommand: `pnpm next ${ startCommand: `pnpm next ${
shouldRunTurboDevTest() ? 'dev --turbo' : 'dev' shouldRunTurboDevTest() ? 'dev --turbo' : 'dev'
} --experimental-https`, } --experimental-https`,
skipStart: !process.env.CI, skipStart: !process.env.CI,
}, })
({ next }) => { if (skipped) return
if (!process.env.CI) { if (!process.env.CI) {
console.warn('only runs on CI as it requires administrator privileges') console.warn('only runs on CI as it requires administrator privileges')
it('only runs on CI as it requires administrator privileges', () => {}) it('only runs on CI as it requires administrator privileges', () => {})
@ -33,5 +33,4 @@ createNextDescribe(
const html = await renderViaHTTP(next.url, '/2', undefined, { agent }) const html = await renderViaHTTP(next.url, '/2', undefined, { agent })
expect(html).toContain('Hello from Pages') expect(html).toContain('Hello from Pages')
}) })
} })
)

View file

@ -1,16 +1,14 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import https from 'https' import https from 'https'
import { renderViaHTTP, shouldRunTurboDevTest } from 'next-test-utils' import { renderViaHTTP, shouldRunTurboDevTest } from 'next-test-utils'
createNextDescribe( describe('experimental-https-server (provided certificate)', () => {
'experimental-https-server (provided certificate)', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
startCommand: `pnpm next ${ startCommand: `pnpm next ${
shouldRunTurboDevTest() ? 'dev --turbo' : 'dev' shouldRunTurboDevTest() ? 'dev --turbo' : 'dev'
} --experimental-https --experimental-https-key ./certificates/localhost-key.pem --experimental-https-cert ./certificates/localhost.pem`, } --experimental-https --experimental-https-key ./certificates/localhost-key.pem --experimental-https-cert ./certificates/localhost.pem`,
}, })
({ next }) => {
const agent = new https.Agent({ const agent = new https.Agent({
rejectUnauthorized: false, rejectUnauthorized: false,
}) })
@ -26,5 +24,4 @@ createNextDescribe(
const html = await renderViaHTTP(next.url, '/2', undefined, { agent }) const html = await renderViaHTTP(next.url, '/2', undefined, { agent })
expect(html).toContain('Hello from Pages') expect(html).toContain('Hello from Pages')
}) })
} })
)

View file

@ -1,14 +1,12 @@
import { check, getRedboxSource, hasRedbox } from 'next-test-utils' import { check, getRedboxSource, hasRedbox } from 'next-test-utils'
import stripAnsi from 'strip-ansi' import stripAnsi from 'strip-ansi'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('middleware - development errors', () => {
'middleware - development errors', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
env: { __NEXT_TEST_WITH_DEVTOOL: '1' }, env: { __NEXT_TEST_WITH_DEVTOOL: '1' },
}, })
({ next }) => {
beforeEach(async () => { beforeEach(async () => {
await next.stop() await next.stop()
}) })
@ -290,9 +288,7 @@ createNextDescribe(
await check(() => { await check(() => {
expect(next.cliOutput).toContain(`Expected '{', got '}'`) expect(next.cliOutput).toContain(`Expected '{', got '}'`)
expect(next.cliOutput.split(`Expected '{', got '}'`).length).toEqual( expect(next.cliOutput.split(`Expected '{', got '}'`).length).toEqual(2)
2
)
return 'success' return 'success'
}, 'success') }, 'success')
}) })
@ -307,5 +303,4 @@ createNextDescribe(
expect(await browser.elementByCss('#page-title')).toBeTruthy() expect(await browser.elementByCss('#page-title')).toBeTruthy()
}) })
}) })
} })
)

View file

@ -1,10 +1,9 @@
/* eslint-env jest */ /* eslint-env jest */
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('Deprecated @next/font warning', () => {
'Deprecated @next/font warning', const { next, skipped } = nextTestSetup({
{
files: { files: {
'pages/index.js': '', 'pages/index.js': '',
}, },
@ -14,8 +13,9 @@ createNextDescribe(
'@next/font': 'canary', '@next/font': 'canary',
}, },
skipStart: true, skipStart: true,
}, })
({ next }) => { if (skipped) return
it('should warn if @next/font is in deps', async () => { it('should warn if @next/font is in deps', async () => {
await next.start() await next.start()
await check(() => next.cliOutput, /ready/i) await check(() => next.cliOutput, /ready/i)
@ -43,5 +43,4 @@ createNextDescribe(
await next.stop() await next.stop()
await next.clean() await next.clean()
}) })
} })
)

View file

@ -12,14 +12,13 @@ import {
import webdriver from 'next-webdriver' import webdriver from 'next-webdriver'
import path from 'path' import path from 'path'
import renderingSuite from './rendering' import renderingSuite from './rendering'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('Client Navigation', () => {
'Client Navigation', const { next } = nextTestSetup({
{
files: path.join(__dirname, 'fixture'), files: path.join(__dirname, 'fixture'),
}, })
({ next }) => {
it('should not reload when visiting /_error directly', async () => { it('should not reload when visiting /_error directly', async () => {
const { status } = await fetchViaHTTP(next.appPort, '/_error') const { status } = await fetchViaHTTP(next.appPort, '/_error')
const browser = await webdriver(next.appPort, '/_error') const browser = await webdriver(next.appPort, '/_error')
@ -172,9 +171,7 @@ createNextDescribe(
) )
// @ts-expect-error _didNotNavigate is set intentionally // @ts-expect-error _didNotNavigate is set intentionally
await browser.eval(() => (window._didNotNavigate = true)) await browser.eval(() => (window._didNotNavigate = true))
await browser await browser.waitForElementByCss('#absolute-local-dynamic-link').click()
.waitForElementByCss('#absolute-local-dynamic-link')
.click()
expect(await browser.waitForElementByCss('#dynamic-page').text()).toBe( expect(await browser.waitForElementByCss('#dynamic-page').text()).toBe(
'hello' 'hello'
) )
@ -471,10 +468,7 @@ createNextDescribe(
it('should reset scroll before the new page runs its lifecycles (<Link />)', async () => { it('should reset scroll before the new page runs its lifecycles (<Link />)', async () => {
let browser let browser
try { try {
browser = await webdriver( browser = await webdriver(next.appPort, '/nav/long-page-to-snap-scroll')
next.appPort,
'/nav/long-page-to-snap-scroll'
)
// Scrolls to item 400 on the page // Scrolls to item 400 on the page
await browser await browser
@ -505,10 +499,7 @@ createNextDescribe(
it('should reset scroll before the new page runs its lifecycles (Router#push)', async () => { it('should reset scroll before the new page runs its lifecycles (Router#push)', async () => {
let browser let browser
try { try {
browser = await webdriver( browser = await webdriver(next.appPort, '/nav/long-page-to-snap-scroll')
next.appPort,
'/nav/long-page-to-snap-scroll'
)
// Scrolls to item 400 on the page // Scrolls to item 400 on the page
await browser await browser
@ -539,10 +530,7 @@ createNextDescribe(
it('should intentionally not reset scroll before the new page runs its lifecycles (Router#push)', async () => { it('should intentionally not reset scroll before the new page runs its lifecycles (Router#push)', async () => {
let browser let browser
try { try {
browser = await webdriver( browser = await webdriver(next.appPort, '/nav/long-page-to-snap-scroll')
next.appPort,
'/nav/long-page-to-snap-scroll'
)
// Scrolls to item 400 on the page // Scrolls to item 400 on the page
await browser await browser
@ -647,9 +635,7 @@ createNextDescribe(
// Scrolls to cjk anchor on the page // Scrolls to cjk anchor on the page
await browser.elementByCss('#scroll-to-cjk-anchor').click() await browser.elementByCss('#scroll-to-cjk-anchor').click()
const scrollPositionCJKHash = await browser.eval( const scrollPositionCJKHash = await browser.eval('window.pageYOffset')
'window.pageYOffset'
)
expect(scrollPositionCJKHash).toBe(17436) expect(scrollPositionCJKHash).toBe(17436)
} finally { } finally {
@ -664,9 +650,7 @@ createNextDescribe(
const curScroll = await browser.eval( const curScroll = await browser.eval(
'document.documentElement.scrollTop' 'document.documentElement.scrollTop'
) )
await browser await browser.elementByCss('#scroll-to-name-item-400-no-scroll').click()
.elementByCss('#scroll-to-name-item-400-no-scroll')
.click()
expect(curScroll).toBe( expect(curScroll).toBe(
await browser.eval('document.documentElement.scrollTop') await browser.eval('document.documentElement.scrollTop')
) )
@ -1400,9 +1384,7 @@ createNextDescribe(
expect(await hasRedbox(browser)).toBe(true) expect(await hasRedbox(browser)).toBe(true)
const text = await getRedboxSource(browser) const text = await getRedboxSource(browser)
expect(text).toMatch(/An Expected error occurred/) expect(text).toMatch(/An Expected error occurred/)
expect(text).toMatch( expect(text).toMatch(/pages[\\/]error-inside-browser-page\.js \(5:13\)/)
/pages[\\/]error-inside-browser-page\.js \(5:13\)/
)
} finally { } finally {
if (browser) { if (browser) {
await browser.close() await browser.close()
@ -1808,12 +1790,12 @@ createNextDescribe(
await browser.waitForElementByCss('h1') await browser.waitForElementByCss('h1')
await waitFor(2000) await waitFor(2000)
expect( expect(Number(await browser.eval('window.__test_async_executions'))).toBe(
Number(await browser.eval('window.__test_async_executions')) 1
).toBe(1) )
expect( expect(Number(await browser.eval('window.__test_defer_executions'))).toBe(
Number(await browser.eval('window.__test_defer_executions')) 1
).toBe(1) )
} finally { } finally {
if (browser) { if (browser) {
await browser.close() await browser.close()
@ -1870,5 +1852,4 @@ createNextDescribe(
(p, q) => fetchViaHTTP(next.appPort, p, q), (p, q) => fetchViaHTTP(next.appPort, p, q),
next next
) )
} })
)

View file

@ -1,12 +1,10 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('custom-app-hmr', () => {
'custom-app-hmr', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should not do full reload when simply editing _app.js', async () => { it('should not do full reload when simply editing _app.js', async () => {
const customAppFilePath = 'pages/_app.js' const customAppFilePath = 'pages/_app.js'
const browser = await next.browser('/') const browser = await next.browser('/')
@ -42,5 +40,4 @@ createNextDescribe(
return 'success' return 'success'
}, 'success') }, 'success')
}) })
} })
)

View file

@ -1,14 +1,12 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import fs from 'fs-extra' import fs from 'fs-extra'
import { hasRedbox } from 'next-test-utils' import { hasRedbox } from 'next-test-utils'
import path from 'path' import path from 'path'
createNextDescribe( describe('repeated-dev-edits', () => {
'repeated-dev-edits', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
// Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API. // Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API.
it('should not break the hydration ', async () => { it('should not break the hydration ', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
@ -44,5 +42,4 @@ createNextDescribe(
// Verify no hydration mismatch: // Verify no hydration mismatch:
expect(await hasRedbox(browser)).toBeFalse() expect(await hasRedbox(browser)).toBeFalse()
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
import { join } from 'path' import { join } from 'path'
createNextDescribe(
'watch-config-file', describe('watch-config-file', () => {
{ const { next } = nextTestSetup({
files: join(__dirname, 'fixture'), files: join(__dirname, 'fixture'),
}, })
({ next }) => {
it('should output config file change', async () => { it('should output config file change', async () => {
await check(async () => next.cliOutput, /ready/i) await check(async () => next.cliOutput, /ready/i)
@ -34,5 +33,4 @@ createNextDescribe(
await check(() => next.fetch('/about').then((res) => res.status), 200) await check(() => next.fetch('/about').then((res) => res.status), 200)
}) })
} })
)

View file

@ -1,13 +1,16 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app-dir edge runtime config', () => {
'app-dir edge runtime config', const { next, isNextDev, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipStart: true, skipStart: true,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextDev }) => {
if (skipped) {
return
}
it('should warn the legacy object config export', async () => { it('should warn the legacy object config export', async () => {
let error let error
await next.start().catch((err) => { await next.start().catch((err) => {
@ -30,5 +33,4 @@ createNextDescribe(
'- `export const preferredRegion = ["us-east-1"]`' '- `export const preferredRegion = ["us-east-1"]`'
) )
}) })
} })
)

View file

@ -1,11 +1,9 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('_allow-underscored-root-directory', () => {
'_allow-underscored-root-directory', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should not serve app path with underscore', async () => { it('should not serve app path with underscore', async () => {
const res = await next.fetch('/_handlers') const res = await next.fetch('/_handlers')
expect(res.status).toBe(404) expect(res.status).toBe(404)
@ -20,5 +18,4 @@ createNextDescribe(
const res = await next.fetch('/_routable-folder') const res = await next.fetch('/_routable-folder')
await expect(res.text()).resolves.toBe('Hello, world!') await expect(res.text()).resolves.toBe('Hello, world!')
}) })
} })
)

View file

@ -1,10 +1,9 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
import { join } from 'path' import { join } from 'path'
createNextDescribe( describe('app-dir action allowed origins', () => {
'app-dir action allowed origins', const { next, skipped } = nextTestSetup({
{
files: join(__dirname, 'safe-origins'), files: join(__dirname, 'safe-origins'),
skipDeployment: true, skipDeployment: true,
dependencies: { dependencies: {
@ -14,8 +13,12 @@ createNextDescribe(
}, },
// An arbitrary & random port. // An arbitrary & random port.
forcedPort: '41831', forcedPort: '41831',
}, })
({ next }) => {
if (skipped) {
return
}
it('should pass if localhost is set as a safe origin', async function () { it('should pass if localhost is set as a safe origin', async function () {
const browser = await next.browser('/') const browser = await next.browser('/')
@ -25,5 +28,4 @@ createNextDescribe(
return await browser.elementByCss('#res').text() return await browser.elementByCss('#res').text()
}, 'hi') }, 'hi')
}) })
} })
)

View file

@ -1,10 +1,9 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
import { join } from 'path' import { join } from 'path'
createNextDescribe( describe('app-dir action disallowed origins', () => {
'app-dir action disallowed origins', const { next, skipped } = nextTestSetup({
{
files: join(__dirname, 'unsafe-origins'), files: join(__dirname, 'unsafe-origins'),
skipDeployment: true, skipDeployment: true,
dependencies: { dependencies: {
@ -12,8 +11,12 @@ createNextDescribe(
'react-dom': 'latest', 'react-dom': 'latest',
'server-only': 'latest', 'server-only': 'latest',
}, },
}, })
({ next }) => {
if (skipped) {
return
}
// Origin should be localhost // Origin should be localhost
it('should error if x-forwarded-host does not match the origin', async function () { it('should error if x-forwarded-host does not match the origin', async function () {
const browser = await next.browser('/') const browser = await next.browser('/')
@ -29,5 +32,4 @@ createNextDescribe(
: 'no' : 'no'
}, 'yes') }, 'yes')
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check, waitFor } from 'next-test-utils' import { check, waitFor } from 'next-test-utils'
createNextDescribe( describe('app-dir action handling', () => {
'app-dir action handling', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should handle actions correctly after navigation / redirection events', async () => { it('should handle actions correctly after navigation / redirection events', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
@ -45,5 +44,4 @@ createNextDescribe(
return (next.cliOutput.match(/addToCart/g) || []).length return (next.cliOutput.match(/addToCart/g) || []).length
}, 1) }, 1)
}) })
} })
)

View file

@ -1,8 +1,7 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app-dir action handling - next export', () => {
'app-dir action handling - next export', const { next, isNextStart, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipStart: true, skipStart: true,
skipDeployment: true, skipDeployment: true,
@ -11,8 +10,9 @@ createNextDescribe(
'react-dom': 'latest', 'react-dom': 'latest',
'server-only': 'latest', 'server-only': 'latest',
}, },
}, })
({ next, isNextStart }) => { if (skipped) return
if (!isNextStart) { if (!isNextStart) {
it('skip test for development mode', () => {}) it('skip test for development mode', () => {})
return return
@ -38,5 +38,4 @@ createNextDescribe(
`Server Actions are not supported with static export.` `Server Actions are not supported with static export.`
) )
}) })
} })
)

View file

@ -1,17 +1,15 @@
/* eslint-disable jest/no-standalone-expect */ /* eslint-disable jest/no-standalone-expect */
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('app-dir action useFormState', () => {
'app-dir action useFormState', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
dependencies: { dependencies: {
react: 'latest', react: 'latest',
'react-dom': 'latest', 'react-dom': 'latest',
}, },
}, })
({ next }) => {
it('should support submitting form state with JS', async () => { it('should support submitting form state with JS', async () => {
const browser = await next.browser('/client/form-state') const browser = await next.browser('/client/form-state')
@ -69,5 +67,4 @@ createNextDescribe(
return browser.elementByCss('#form-state').text() return browser.elementByCss('#form-state').text()
}, 'initial-state:test-permalink') }, 'initial-state:test-permalink')
}) })
} })
)

View file

@ -1,11 +1,10 @@
/* eslint-disable jest/no-standalone-expect */ /* eslint-disable jest/no-standalone-expect */
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
import type { Response } from 'playwright' import type { Response } from 'playwright'
createNextDescribe( describe('app-dir action progressive enhancement', () => {
'app-dir action progressive enhancement', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
dependencies: { dependencies: {
react: 'latest', react: 'latest',
@ -13,8 +12,8 @@ createNextDescribe(
'react-dom': 'latest', 'react-dom': 'latest',
'server-only': 'latest', 'server-only': 'latest',
}, },
}, })
({ next }) => {
it('should support formData and redirect without JS', async () => { it('should support formData and redirect without JS', async () => {
let responseCode let responseCode
const browser = await next.browser('/server', { const browser = await next.browser('/server', {
@ -45,14 +44,11 @@ createNextDescribe(
disableJavaScript: true, disableJavaScript: true,
}) })
await browser.eval( await browser.eval(`document.getElementById('client-name').value = 'test'`)
`document.getElementById('client-name').value = 'test'`
)
await browser.elementByCss('#there').click() await browser.elementByCss('#there').click()
await check(() => { await check(() => {
return browser.eval('window.location.pathname + window.location.search') return browser.eval('window.location.pathname + window.location.search')
}, '/header?name=test&hidden-info=hi') }, '/header?name=test&hidden-info=hi')
}) })
} })
)

View file

@ -1,13 +1,12 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { retry } from 'next-test-utils' import { retry } from 'next-test-utils'
import { accountForOverhead } from './account-for-overhead' import { accountForOverhead } from './account-for-overhead'
const CONFIG_ERROR = const CONFIG_ERROR =
'Server Actions Size Limit must be a valid number or filesize format larger than 1MB' 'Server Actions Size Limit must be a valid number or filesize format larger than 1MB'
createNextDescribe( describe('app-dir action size limit invalid config', () => {
'app-dir action size limit invalid config', const { next, isNextStart, isNextDeploy, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
skipStart: true, skipStart: true,
@ -16,8 +15,9 @@ createNextDescribe(
'react-dom': 'latest', 'react-dom': 'latest',
'server-only': 'latest', 'server-only': 'latest',
}, },
}, })
({ next, isNextStart, isNextDeploy }) => { if (skipped) return
if (!isNextStart) { if (!isNextStart) {
it('skip test for development mode', () => {}) it('skip test for development mode', () => {})
return return
@ -154,5 +154,4 @@ createNextDescribe(
}) })
}) })
} }
} })
)

View file

@ -1,5 +1,5 @@
/* eslint-disable jest/no-standalone-expect */ /* eslint-disable jest/no-standalone-expect */
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { import {
check, check,
retry, retry,
@ -14,9 +14,9 @@ import { join } from 'path'
const GENERIC_RSC_ERROR = const GENERIC_RSC_ERROR =
'Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.' 'Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.'
createNextDescribe( describe('app-dir action handling', () => {
'app-dir action handling', const { next, isNextDev, isNextStart, isNextDeploy, isTurbopack } =
{ nextTestSetup({
files: __dirname, files: __dirname,
dependencies: { dependencies: {
react: 'latest', react: 'latest',
@ -24,8 +24,8 @@ createNextDescribe(
'react-dom': 'latest', 'react-dom': 'latest',
'server-only': 'latest', 'server-only': 'latest',
}, },
}, })
({ next, isNextDev, isNextStart, isNextDeploy, isTurbopack }) => {
it('should handle basic actions correctly', async () => { it('should handle basic actions correctly', async () => {
const browser = await next.browser('/server') const browser = await next.browser('/server')
@ -83,9 +83,7 @@ createNextDescribe(
await check(async () => { await check(async () => {
const res = (await browser.elementByCss('h1').text()) || '' const res = (await browser.elementByCss('h1').text()) || ''
const id = res.split(':', 3) const id = res.split(':', 3)
return id[0] === id[1] && id[0] === id[2] && id[0] return id[0] === id[1] && id[0] === id[2] && id[0] ? 'same' : 'different'
? 'same'
: 'different'
}, 'same') }, 'same')
}) })
@ -101,9 +99,7 @@ createNextDescribe(
await browser.back() await browser.back()
await check(async () => { await check(async () => {
return ( return (await browser.elementByCss('#setCookieAndRedirect').text()) || ''
(await browser.elementByCss('#setCookieAndRedirect').text()) || ''
)
}, 'setCookieAndRedirect') }, 'setCookieAndRedirect')
}) })
@ -254,9 +250,7 @@ createNextDescribe(
// we don't have access to runtime logs on deploy // we don't have access to runtime logs on deploy
if (!isNextDeploy) { if (!isNextDeploy) {
await check(() => { await check(() => {
return logs.some((log) => return logs.some((log) => log.includes('File name: hello.txt size: 5'))
log.includes('File name: hello.txt size: 5')
)
? 'yes' ? 'yes'
: '' : ''
}, 'yes') }, 'yes')
@ -470,9 +464,7 @@ createNextDescribe(
}, },
}) })
expect(await browser.elementByCss('h1').text()).toBe( expect(await browser.elementByCss('h1').text()).toBe('Transition is: idle')
'Transition is: idle'
)
const button = await browser.elementById('action-button') const button = await browser.elementById('action-button')
// fire off 6 successive requests by clicking the button 6 times // fire off 6 successive requests by clicking the button 6 times
@ -490,10 +482,7 @@ createNextDescribe(
await check(() => requestCount, 6) await check(() => requestCount, 6)
await check( await check(() => browser.elementByCss('h1').text(), 'Transition is: idle')
() => browser.elementByCss('h1').text(),
'Transition is: idle'
)
}) })
it('should 404 when POSTing an invalid server action', async () => { it('should 404 when POSTing an invalid server action', async () => {
@ -548,9 +537,7 @@ createNextDescribe(
await browser.elementById('good-action').click() await browser.elementById('good-action').click()
// verify that the app didn't crash after the error was thrown // verify that the app didn't crash after the error was thrown
expect(await browser.elementById('submitted-msg').text()).toBe( expect(await browser.elementById('submitted-msg').text()).toBe('Submitted!')
'Submitted!'
)
// Verify that the catch log was printed // Verify that the catch log was printed
const logs = await browser.log() const logs = await browser.log()
@ -565,9 +552,7 @@ createNextDescribe(
await browser.elementById('bad-action').click() await browser.elementById('bad-action').click()
// verify that the app didn't crash after the error was thrown // verify that the app didn't crash after the error was thrown
expect(await browser.elementById('submitted-msg').text()).toBe( expect(await browser.elementById('submitted-msg').text()).toBe('Submitted!')
'Submitted!'
)
// Verify that the catch log was printed // Verify that the catch log was printed
const logs = await browser.log() const logs = await browser.log()
@ -583,9 +568,7 @@ createNextDescribe(
const browser = await next.browser(`/delayed-action/${runtime}`) const browser = await next.browser(`/delayed-action/${runtime}`)
// confirm there's no data yet // confirm there's no data yet
expect(await browser.elementById('delayed-action-result').text()).toBe( expect(await browser.elementById('delayed-action-result').text()).toBe('')
''
)
// Trigger the delayed action. This will sleep for a few seconds before dispatching the server action handler // Trigger the delayed action. This will sleep for a few seconds before dispatching the server action handler
await browser.elementById('run-action').click() await browser.elementById('run-action').click()
@ -710,9 +693,7 @@ createNextDescribe(
expect(await Promise.all(reads)).toContain(true) expect(await Promise.all(reads)).toContain(true)
} else { } else {
expect(pageBundle.toString()).toContain( expect(pageBundle.toString()).toContain('node_modules/nanoid/index.js')
'node_modules/nanoid/index.js'
)
} }
}) })
} }
@ -1077,9 +1058,7 @@ createNextDescribe(
revalidatedRandomCookie = JSON.parse( revalidatedRandomCookie = JSON.parse(
await browser.elementByCss('#random-cookie').text() await browser.elementByCss('#random-cookie').text()
).value ).value
return randomCookie !== revalidatedRandomCookie return randomCookie !== revalidatedRandomCookie ? 'success' : 'failure'
? 'success'
: 'failure'
}, 'success') }, 'success')
await browser.elementByCss('#another').click() await browser.elementByCss('#another').click()
@ -1101,9 +1080,7 @@ createNextDescribe(
const browser = await next.browser('/revalidate') const browser = await next.browser('/revalidate')
await browser.refresh() await browser.refresh()
const thankYouNext = await browser const thankYouNext = await browser.elementByCss('#thankyounext').text()
.elementByCss('#thankyounext')
.text()
await browser.elementByCss('#another').click() await browser.elementByCss('#another').click()
await check(async () => { await check(async () => {
@ -1159,10 +1136,7 @@ createNextDescribe(
it('should work with interception routes', async () => { it('should work with interception routes', async () => {
const browser = await next.browser('/interception-routes') const browser = await next.browser('/interception-routes')
await check( await check(() => browser.elementById('children-data').text(), /Open modal/)
() => browser.elementById('children-data').text(),
/Open modal/
)
await browser.elementByCss("[href='/interception-routes/test']").click() await browser.elementByCss("[href='/interception-routes/test']").click()
@ -1184,10 +1158,7 @@ createNextDescribe(
expect(await browser.hasElementByCssSelector('#modal-data')).toBeFalsy() expect(await browser.hasElementByCssSelector('#modal-data')).toBeFalsy()
// The page text should show // The page text should show
await check( await check(() => browser.elementById('children-data').text(), /in "page"/)
() => browser.elementById('children-data').text(),
/in "page"/
)
// Submit the action // Submit the action
await browser.elementById('submit-page-action').click() await browser.elementById('submit-page-action').click()
@ -1451,5 +1422,4 @@ createNextDescribe(
}, 'success') }, 'success')
}) })
}) })
} })
)

View file

@ -1,15 +1,18 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
import type { BrowserInterface } from 'next-webdriver' import type { BrowserInterface } from 'next-webdriver'
createNextDescribe( describe('app a11y features', () => {
'app a11y features', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
packageJson: {}, packageJson: {},
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => {
if (skipped) {
return
}
describe('route announcer', () => { describe('route announcer', () => {
async function getAnnouncerContent(browser: BrowserInterface) { async function getAnnouncerContent(browser: BrowserInterface) {
return browser.eval( return browser.eval(
@ -40,5 +43,4 @@ createNextDescribe(
await check(() => getAnnouncerContent(browser), 'noop-layout/page-2') await check(() => getAnnouncerContent(browser), 'noop-layout/page-2')
}) })
}) })
} })
)

View file

@ -1,12 +1,15 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app-dir alias', () => {
'app-dir alias', const { next, isNextStart, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextStart }) => {
if (skipped) {
return
}
it('should handle typescript paths alias correctly', async () => { it('should handle typescript paths alias correctly', async () => {
const html = await next.render('/button') const html = await next.render('/button')
expect(html).toContain('click</button>') expect(html).toContain('click</button>')
@ -42,5 +45,4 @@ createNextDescribe(
expect(manifest.pages).not.toBeEmptyObject() expect(manifest.pages).not.toBeEmptyObject()
}) })
} }
} })
)

View file

@ -1,18 +1,21 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check, retry } from 'next-test-utils' import { check, retry } from 'next-test-utils'
import { join } from 'path' import { join } from 'path'
createNextDescribe( describe('custom-app-server-action-redirect', () => {
'custom-app-server-action-redirect', const { next, skipped } = nextTestSetup({
{
files: join(__dirname, 'custom-server'), files: join(__dirname, 'custom-server'),
skipDeployment: true, skipDeployment: true,
startCommand: 'node server.js', startCommand: 'node server.js',
dependencies: { dependencies: {
'get-port': '5.1.1', 'get-port': '5.1.1',
}, },
}, })
({ next }) => {
if (skipped) {
return
}
it('redirects with basepath properly when server action handler uses `redirect`', async () => { it('redirects with basepath properly when server action handler uses `redirect`', async () => {
const browser = await next.browser('/base') const browser = await next.browser('/base')
const getCount = async () => browser.elementByCss('#current-count').text() const getCount = async () => browser.elementByCss('#current-count').text()
@ -56,5 +59,4 @@ createNextDescribe(
/custom-server-action-test-cookie/ /custom-server-action-test-cookie/
) )
}) })
} })
)

View file

@ -1,16 +1,19 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { retry } from 'next-test-utils' import { retry } from 'next-test-utils'
createNextDescribe( describe('app dir - basepath', () => {
'app dir - basepath', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
dependencies: { dependencies: {
sass: 'latest', sass: 'latest',
}, },
}, })
({ next }) => {
if (skipped) {
return
}
it('should successfully hard navigate from pages -> app', async () => { it('should successfully hard navigate from pages -> app', async () => {
const browser = await next.browser('/base/pages-path') const browser = await next.browser('/base/pages-path')
await browser.elementByCss('#to-another').click() await browser.elementByCss('#to-another').click()
@ -91,5 +94,4 @@ createNextDescribe(
}) })
} }
) )
} })
)

View file

@ -1,4 +1,4 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
import { BrowserInterface } from 'next-webdriver' import { BrowserInterface } from 'next-webdriver'
import { import {
@ -8,12 +8,11 @@ import {
getPathname, getPathname,
} from './test-utils' } from './test-utils'
createNextDescribe( describe('app dir client cache semantics', () => {
'app dir client cache semantics', const { next, isNextDev } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next, isNextDev }) => {
if (isNextDev) { if (isNextDev) {
// dev doesn't support prefetch={true}, so this just performs a basic test to make sure data is reused for 30s // dev doesn't support prefetch={true}, so this just performs a basic test to make sure data is reused for 30s
it('should renew the 30s cache once the data is revalidated', async () => { it('should renew the 30s cache once the data is revalidated', async () => {
@ -425,9 +424,7 @@ createNextDescribe(
).toBeFalse() ).toBeFalse()
// the root layout should still be visible // the root layout should still be visible
expect( expect(await browser.hasElementByCssSelector('#root-layout')).toBeTrue()
await browser.hasElementByCssSelector('#root-layout')
).toBeTrue()
// the dynamic content should eventually appear // the dynamic content should eventually appear
await browser.waitForElementByCss('#random-number') await browser.waitForElementByCss('#random-number')
@ -475,5 +472,4 @@ createNextDescribe(
expect(newNumber).not.toBe(initialNumber) expect(newNumber).not.toBe(initialNumber)
}) })
} }
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check, hasRedbox, waitFor } from 'next-test-utils' import { check, hasRedbox, waitFor } from 'next-test-utils'
createNextDescribe( describe('app dir', () => {
'app dir', const { next, isNextDev, isNextStart } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next, isNextDev: isDev, isNextStart }) => {
if (isNextStart) { if (isNextStart) {
describe('Loading', () => { describe('Loading', () => {
it('should render loading.js in initial html for slow page', async () => { it('should render loading.js in initial html for slow page', async () => {
@ -16,7 +15,7 @@ createNextDescribe(
}) })
} }
if (isDev) { if (isNextDev) {
describe('HMR', () => { describe('HMR', () => {
it('should not cause error when removing loading.js', async () => { it('should not cause error when removing loading.js', async () => {
const browser = await next.browser('/page-with-loading') const browser = await next.browser('/page-with-loading')
@ -48,5 +47,4 @@ createNextDescribe(
}) })
}) })
} }
} })
)

View file

@ -1,12 +1,15 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app dir - crossOrigin config', () => {
'app dir - crossOrigin config', const { next, isNextStart, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextStart }) => {
if (skipped) {
return
}
if (isNextStart) { if (isNextStart) {
it('skip in start mode', () => {}) it('skip in start mode', () => {})
return return
@ -33,5 +36,4 @@ createNextDescribe(
expect(crossOrigin).toBeUndefined() expect(crossOrigin).toBeUndefined()
}) })
}) })
} })
)

View file

@ -1,8 +1,7 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app dir - css with pageextensions', () => {
'app dir - css with pageextensions', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
dependencies: { dependencies: {
@ -11,8 +10,12 @@ createNextDescribe(
'react-dom': 'latest', 'react-dom': 'latest',
sass: 'latest', sass: 'latest',
}, },
}, })
({ next }) => {
if (skipped) {
return
}
describe('css support with pageextensions', () => { describe('css support with pageextensions', () => {
describe('page in app directory with pageextention, css should work', () => { describe('page in app directory with pageextention, css should work', () => {
it('should support global css inside layout', async () => { it('should support global css inside layout', async () => {
@ -25,5 +28,4 @@ createNextDescribe(
}) })
}) })
}) })
} })
)

View file

@ -1,9 +1,8 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('app dir - css', () => {
'app dir - css', const { next, isNextDev, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
dependencies: { dependencies: {
@ -13,8 +12,12 @@ createNextDescribe(
sass: 'latest', sass: 'latest',
'@next/mdx': 'canary', '@next/mdx': 'canary',
}, },
}, })
({ next, isNextDev: isDev }) => {
if (skipped) {
return
}
describe('css support', () => { describe('css support', () => {
describe('server layouts', () => { describe('server layouts', () => {
it.skip('should support global css inside server layouts', async () => { it.skip('should support global css inside server layouts', async () => {
@ -315,7 +318,7 @@ createNextDescribe(
}) })
}) })
if (isDev) { if (isNextDev) {
it('should not affect css orders during HMR', async () => { it('should not affect css orders during HMR', async () => {
const filePath = 'app/ordering/page.js' const filePath = 'app/ordering/page.js'
const origContent = await next.readFile(filePath) const origContent = await next.readFile(filePath)
@ -475,9 +478,7 @@ createNextDescribe(
} else { } else {
// Even if it's deduped by Float, it should still only be included once in the payload. // Even if it's deduped by Float, it should still only be included once in the payload.
const matches = initialHtml.match( const matches = initialHtml.match(/\/_next\/static\/css\/.+?\.css/g)
/\/_next\/static\/css\/.+?\.css/g
)
const counts = new Map() const counts = new Map()
for (const match of matches) { for (const match of matches) {
counts.set(match, (counts.get(match) || 0) + 1) counts.set(match, (counts.get(match) || 0) + 1)
@ -657,7 +658,7 @@ createNextDescribe(
// Pages directory shouldn't be affected when `appDir` is enabled // Pages directory shouldn't be affected when `appDir` is enabled
describe('pages dir', () => { describe('pages dir', () => {
if (!isDev) { if (!isNextDev) {
it('should include css modules and global css after page transition', async () => { it('should include css modules and global css after page transition', async () => {
const browser = await next.browser('/css-modules/page1') const browser = await next.browser('/css-modules/page1')
await browser.elementByCss('a').click() await browser.elementByCss('a').click()
@ -678,7 +679,7 @@ createNextDescribe(
}) })
describe('HMR', () => { describe('HMR', () => {
if (isDev) { if (isNextDev) {
it('should support HMR for CSS imports in server components', async () => { it('should support HMR for CSS imports in server components', async () => {
const filePath = 'app/css/css-page/style.css' const filePath = 'app/css/css-page/style.css'
const origContent = await next.readFile(filePath) const origContent = await next.readFile(filePath)
@ -741,10 +742,7 @@ createNextDescribe(
const browser = await next.browser('/hmr') const browser = await next.browser('/hmr')
await browser.eval(`window.__v = 1`) await browser.eval(`window.__v = 1`)
try { try {
await next.patchFile( await next.patchFile(filePath, origContent.replace('hello!', 'hmr!'))
filePath,
origContent.replace('hello!', 'hmr!')
)
await check(() => browser.elementByCss('body').text(), 'hmr!') await check(() => browser.elementByCss('body').text(), 'hmr!')
// Make sure it doesn't reload the page // Make sure it doesn't reload the page
@ -846,7 +844,7 @@ createNextDescribe(
} }
}) })
if (isDev) { if (isNextDev) {
describe('Suspensey CSS', () => { describe('Suspensey CSS', () => {
it('should suspend on CSS imports if its slow on client navigation', async () => { it('should suspend on CSS imports if its slow on client navigation', async () => {
const browser = await next.browser('/suspensey-css') const browser = await next.browser('/suspensey-css')
@ -858,5 +856,4 @@ createNextDescribe(
}) })
}) })
} }
} })
)

View file

@ -1,4 +1,4 @@
import { type NextInstance, createNextDescribe, FileRef } from 'e2e-utils' import { type NextInstance, nextTestSetup, FileRef } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
import fs from 'fs' import fs from 'fs'
@ -27,37 +27,40 @@ function runTests(
}) })
} }
createNextDescribe( describe('app-dir - custom-cache-handler - cjs', () => {
'app-dir - custom-cache-handler - cjs', const { next, isNextDev, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
env: { env: {
CUSTOM_CACHE_HANDLER: 'cache-handler.js', CUSTOM_CACHE_HANDLER: 'cache-handler.js',
}, },
}, })
({ next, isNextDev }) => {
runTests('cjs module exports', { next, isNextDev })
}
)
createNextDescribe( if (skipped) {
'app-dir - custom-cache-handler - cjs-default-export', return
{ }
runTests('cjs module exports', { next, isNextDev })
})
describe('app-dir - custom-cache-handler - cjs-default-export', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
env: { env: {
CUSTOM_CACHE_HANDLER: 'cache-handler-cjs-default-export.js', CUSTOM_CACHE_HANDLER: 'cache-handler-cjs-default-export.js',
}, },
}, })
({ next, isNextDev }) => {
runTests('cjs default export', { next, isNextDev })
}
)
createNextDescribe( if (skipped) {
'app-dir - custom-cache-handler - esm', return
{ }
runTests('cjs default export', { next, isNextDev })
})
describe('app-dir - custom-cache-handler - esm', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: { files: {
app: new FileRef(__dirname + '/app'), app: new FileRef(__dirname + '/app'),
'cache-handler-esm.js': new FileRef(__dirname + '/cache-handler-esm.js'), 'cache-handler-esm.js': new FileRef(__dirname + '/cache-handler-esm.js'),
@ -73,8 +76,11 @@ createNextDescribe(
env: { env: {
CUSTOM_CACHE_HANDLER: 'cache-handler-esm.js', CUSTOM_CACHE_HANDLER: 'cache-handler-esm.js',
}, },
}, })
({ next, isNextDev }) => {
runTests('esm default export', { next, isNextDev }) if (skipped) {
return
} }
)
runTests('esm default export', { next, isNextDev })
})

View file

@ -1,12 +1,15 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app-dir edge runtime root layout', () => {
'app-dir edge runtime root layout', const { next, isNextStart, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextStart }) => {
if (skipped) {
return
}
it('should not emit metadata files into bad paths', async () => { it('should not emit metadata files into bad paths', async () => {
await next.fetch('/favicon.ico') await next.fetch('/favicon.ico')
// issue: If metadata files are not filter out properly with image-loader, // issue: If metadata files are not filter out properly with image-loader,
@ -25,5 +28,4 @@ createNextDescribe(
expect(middlewareManifest).not.toContain('favicon') expect(middlewareManifest).not.toContain('favicon')
}) })
} }
} })
)

View file

@ -1,13 +1,16 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('app-dir edge SSR', () => {
'app-dir edge SSR', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => {
if (skipped) {
return
}
it('should handle edge only routes', async () => { it('should handle edge only routes', async () => {
const appHtml = await next.render('/edge/basic') const appHtml = await next.render('/edge/basic')
expect(appHtml).toContain('<p>Edge!</p>') expect(appHtml).toContain('<p>Edge!</p>')
@ -56,9 +59,9 @@ createNextDescribe(
logs.push(log) logs.push(log)
}) })
await next.render('/app-edge') await next.render('/app-edge')
expect( expect(logs.some((log) => log.includes(`Attempted import error:`))).toBe(
logs.some((log) => log.includes(`Attempted import error:`)) false
).toBe(false) )
}) })
it('should resolve client component without error', async () => { it('should resolve client component without error', async () => {
@ -104,5 +107,4 @@ createNextDescribe(
]) ])
}) })
} }
} })
)

View file

@ -1,11 +1,10 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app-dir - esm js extension', () => {
'app-dir - esm js extension', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should be able to render nextjs api in app router', async () => { it('should be able to render nextjs api in app router', async () => {
const $ = await next.render$('/app') const $ = await next.render$('/app')
@ -41,5 +40,4 @@ createNextDescribe(
expect(res.status).toBe(200) expect(res.status).toBe(200)
expect(res.headers.get('content-type')).toBe('image/png') expect(res.headers.get('content-type')).toBe('image/png')
}) })
} })
)

View file

@ -1,4 +1,4 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check, hasRedbox, retry, shouldRunTurboDevTest } from 'next-test-utils' import { check, hasRedbox, retry, shouldRunTurboDevTest } from 'next-test-utils'
async function resolveStreamResponse(response: any, onData?: any) { async function resolveStreamResponse(response: any, onData?: any) {
@ -15,9 +15,8 @@ async function resolveStreamResponse(response: any, onData?: any) {
return result return result
} }
createNextDescribe( describe('app dir - external dependency', () => {
'app dir - external dependency', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
dependencies: { dependencies: {
swr: 'latest', swr: 'latest',
@ -34,8 +33,12 @@ createNextDescribe(
startCommand: (global as any).isNextDev ? 'pnpm dev' : 'pnpm start', startCommand: (global as any).isNextDev ? 'pnpm dev' : 'pnpm start',
buildCommand: 'pnpm build', buildCommand: 'pnpm build',
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => {
if (skipped) {
return
}
it('should be able to opt-out 3rd party packages being bundled in server components', async () => { it('should be able to opt-out 3rd party packages being bundled in server components', async () => {
await next.fetch('/react-server/optout').then(async (response) => { await next.fetch('/react-server/optout').then(async (response) => {
const result = await resolveStreamResponse(response) const result = await resolveStreamResponse(response)
@ -156,9 +159,7 @@ createNextDescribe(
async () => { async () => {
const browser = await next.browser('/browser') const browser = await next.browser('/browser')
// eslint-disable-next-line jest/no-standalone-expect // eslint-disable-next-line jest/no-standalone-expect
expect(await browser.elementByCss('#worker-state').text()).toBe( expect(await browser.elementByCss('#worker-state').text()).toBe('default')
'default'
)
await browser.elementByCss('button').click() await browser.elementByCss('button').click()
@ -180,9 +181,7 @@ createNextDescribe(
expect(v1).toBe(v2) expect(v1).toBe(v2)
// Should work with both esm and cjs imports // Should work with both esm and cjs imports
expect(html).toContain( expect(html).toContain('CJS-ESM Compat package: cjs-esm-compat/index.mjs')
'CJS-ESM Compat package: cjs-esm-compat/index.mjs'
)
expect(html).toContain('CJS package: cjs-lib') expect(html).toContain('CJS package: cjs-lib')
expect(html).toContain( expect(html).toContain(
'Nested imports: nested-import:esm:cjs-esm-compat/index.mjs' 'Nested imports: nested-import:esm:cjs-esm-compat/index.mjs'
@ -197,9 +196,7 @@ createNextDescribe(
expect(v1).toBe(v2) expect(v1).toBe(v2)
// Should work with both esm and cjs imports // Should work with both esm and cjs imports
expect(html).toContain( expect(html).toContain('CJS-ESM Compat package: cjs-esm-compat/index.mjs')
'CJS-ESM Compat package: cjs-esm-compat/index.mjs'
)
expect(html).toContain('CJS package: cjs-lib') expect(html).toContain('CJS package: cjs-lib')
}) })
@ -211,9 +208,7 @@ createNextDescribe(
expect(v1).toBe(v2) expect(v1).toBe(v2)
// Should work with both esm and cjs imports // Should work with both esm and cjs imports
expect(html).toContain( expect(html).toContain('CJS-ESM Compat package: cjs-esm-compat/index.mjs')
'CJS-ESM Compat package: cjs-esm-compat/index.mjs'
)
expect(html).toContain('CJS package: cjs-lib') expect(html).toContain('CJS package: cjs-lib')
}) })
@ -317,5 +312,4 @@ createNextDescribe(
expect(text).toBe('get route') expect(text).toBe('get route')
}) })
}) })
} })
)

View file

@ -1,14 +1,17 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('app-invalid-revalidate', () => {
'app-invalid-revalidate', const { next, isNextDev, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipStart: true, skipStart: true,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextDev }) => {
if (skipped) {
return
}
it('should error properly for invalid revalidate at layout', async () => { it('should error properly for invalid revalidate at layout', async () => {
await next.stop().catch(() => {}) await next.stop().catch(() => {})
const origText = await next.readFile('app/layout.tsx') const origText = await next.readFile('app/layout.tsx')
@ -96,5 +99,4 @@ createNextDescribe(
await next.patchFile('app/page.tsx', origText) await next.patchFile('app/page.tsx', origText)
} }
}) })
} })
)

View file

@ -2,16 +2,19 @@
import path from 'path' import path from 'path'
import cheerio from 'cheerio' import cheerio from 'cheerio'
import { check, retry, withQuery } from 'next-test-utils' import { check, retry, withQuery } from 'next-test-utils'
import { createNextDescribe, FileRef } from 'e2e-utils' import { nextTestSetup, FileRef } from 'e2e-utils'
import type { Response } from 'node-fetch' import type { Response } from 'node-fetch'
createNextDescribe( describe('app-dir with middleware', () => {
'app-dir with middleware', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => {
if (skipped) {
return
}
it('should filter correctly after middleware rewrite', async () => { it('should filter correctly after middleware rewrite', async () => {
const browser = await next.browser('/start') const browser = await next.browser('/start')
@ -80,12 +83,8 @@ createNextDescribe(
expect( expect(
res.headers.get('x-middleware-request-x-from-middleware') res.headers.get('x-middleware-request-x-from-middleware')
).toBeNull() ).toBeNull()
expect( expect(res.headers.get('x-middleware-request-x-from-client1')).toBeNull()
res.headers.get('x-middleware-request-x-from-client1') expect(res.headers.get('x-middleware-request-x-from-client2')).toBeNull()
).toBeNull()
expect(
res.headers.get('x-middleware-request-x-from-client2')
).toBeNull()
}) })
it(`Updates headers`, async () => { it(`Updates headers`, async () => {
@ -114,15 +113,9 @@ createNextDescribe(
expect( expect(
res.headers.get('x-middleware-request-x-from-middleware') res.headers.get('x-middleware-request-x-from-middleware')
).toBeNull() ).toBeNull()
expect( expect(res.headers.get('x-middleware-request-x-from-client1')).toBeNull()
res.headers.get('x-middleware-request-x-from-client1') expect(res.headers.get('x-middleware-request-x-from-client2')).toBeNull()
).toBeNull() expect(res.headers.get('x-middleware-request-x-from-client3')).toBeNull()
expect(
res.headers.get('x-middleware-request-x-from-client2')
).toBeNull()
expect(
res.headers.get('x-middleware-request-x-from-client3')
).toBeNull()
}) })
it(`Supports draft mode`, async () => { it(`Supports draft mode`, async () => {
@ -160,21 +153,17 @@ createNextDescribe(
await browser.elementByCss('[href="/rsc-cookies-delete"]').click() await browser.elementByCss('[href="/rsc-cookies-delete"]').click()
await retry(async () => { await retry(async () => {
// only the first cookie should be deleted // only the first cookie should be deleted
expect(await browser.elementById('rsc-cookie-1').text()).toBe( expect(await browser.elementById('rsc-cookie-1').text()).toBe('Cookie 1:')
'Cookie 1:'
)
expect(await browser.elementById('rsc-cookie-2').text()).toMatch( expect(await browser.elementById('rsc-cookie-2').text()).toMatch(
/Cookie 2: \d+\.\d+/ /Cookie 2: \d+\.\d+/
) )
}) })
}) })
} })
)
createNextDescribe( describe('app dir - middleware without pages dir', () => {
'app dir - middleware without pages dir', const { next, skipped } = nextTestSetup({
{
files: { files: {
app: new FileRef(path.join(__dirname, 'app')), app: new FileRef(path.join(__dirname, 'app')),
'next.config.js': new FileRef(path.join(__dirname, 'next.config.js')), 'next.config.js': new FileRef(path.join(__dirname, 'next.config.js')),
@ -191,20 +180,22 @@ createNextDescribe(
`, `,
}, },
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => {
if (skipped) {
return
}
// eslint-disable-next-line jest/no-identical-title // eslint-disable-next-line jest/no-identical-title
it('Updates headers', async () => { it('Updates headers', async () => {
const html = await next.render('/headers') const html = await next.render('/headers')
expect(html).toContain('redirected') expect(html).toContain('redirected')
}) })
} })
)
createNextDescribe( describe('app dir - middleware with middleware in src dir', () => {
'app dir - middleware with middleware in src dir', const { next, skipped } = nextTestSetup({
{
files: { files: {
'src/app': new FileRef(path.join(__dirname, 'app')), 'src/app': new FileRef(path.join(__dirname, 'app')),
'next.config.js': new FileRef(path.join(__dirname, 'next.config.js')), 'next.config.js': new FileRef(path.join(__dirname, 'next.config.js')),
@ -219,8 +210,12 @@ createNextDescribe(
`, `,
}, },
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => {
if (skipped) {
return
}
it('works without crashing when using requestAsyncStorage', async () => { it('works without crashing when using requestAsyncStorage', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
await browser.addCookie({ await browser.addCookie({
@ -233,5 +228,4 @@ createNextDescribe(
expect(html).toContain('test-cookie-response') expect(html).toContain('test-cookie-response')
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('app-prefetch-false-loading', () => {
'app-prefetch-false-loading', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should render loading for the initial render', async () => { it('should render loading for the initial render', async () => {
const $ = await next.render$('/en/testing') const $ = await next.render$('/en/testing')
@ -16,9 +15,7 @@ createNextDescribe(
const logStartIndex = next.cliOutput.length const logStartIndex = next.cliOutput.length
const browser = await next.browser('/en/testing') const browser = await next.browser('/en/testing')
let initialRandomNumber = await browser let initialRandomNumber = await browser.elementById('random-number').text()
.elementById('random-number')
.text()
await browser.elementByCss('[href="/en/testing/test"]').click() await browser.elementByCss('[href="/en/testing/test"]').click()
expect(await browser.hasElementByCssSelector('#loading')).toBeFalsy() expect(await browser.hasElementByCssSelector('#loading')).toBeFalsy()
@ -39,5 +36,4 @@ createNextDescribe(
return logOccurrences return logOccurrences
}, 1) }, 1)
}) })
} })
)

View file

@ -1,6 +1,6 @@
import type { Request } from 'playwright' import type { Request } from 'playwright'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import type { BrowserInterface } from '../../../lib/browsers/base' import type { BrowserInterface } from '../../../lib/browsers/base'
const getPathname = (url: string) => { const getPathname = (url: string) => {
@ -28,12 +28,11 @@ const createRequestsListener = async (browser: BrowserInterface) => {
} }
} }
createNextDescribe( describe('app-prefetch-false', () => {
'app-prefetch-false', const { next, isNextDev } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next, isNextDev }) => {
if (isNextDev) { if (isNextDev) {
it.skip('should skip test in development mode', () => {}) it.skip('should skip test in development mode', () => {})
} else { } else {
@ -45,10 +44,8 @@ createNextDescribe(
await browser.elementByCss('[href="/foo/bar"]').click() await browser.elementByCss('[href="/foo/bar"]').click()
console.log('getRequests()', getRequests()) console.log('getRequests()', getRequests())
expect( expect(
getRequests().filter(([req]) => getPathname(req) === '/foo/bar') getRequests().filter(([req]) => getPathname(req) === '/foo/bar').length
.length
).toBe(1) ).toBe(1)
}) })
} }
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { waitFor } from 'next-test-utils' import { waitFor } from 'next-test-utils'
createNextDescribe( describe('app-prefetch-static', () => {
'app-prefetch-static', const { next, isNextDev } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next, isNextDev }) => {
if (isNextDev) { if (isNextDev) {
it('should skip next dev', () => {}) it('should skip next dev', () => {})
return return
@ -35,5 +34,4 @@ createNextDescribe(
'Hello from Static Prefetch Page' 'Hello from Static Prefetch Page'
) )
}) })
} })
)

View file

@ -1,4 +1,4 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check, waitFor } from 'next-test-utils' import { check, waitFor } from 'next-test-utils'
import { NEXT_RSC_UNION_QUERY } from 'next/dist/client/components/app-router-headers' import { NEXT_RSC_UNION_QUERY } from 'next/dist/client/components/app-router-headers'
@ -27,13 +27,16 @@ const browserConfigWithFixedTime = {
}, },
} }
createNextDescribe( describe('app dir - prefetching', () => {
'app dir - prefetching', const { next, isNextDev, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextDev }) => {
if (skipped) {
return
}
// TODO: re-enable for dev after https://vercel.slack.com/archives/C035J346QQL/p1663822388387959 is resolved (Sep 22nd 2022) // TODO: re-enable for dev after https://vercel.slack.com/archives/C035J346QQL/p1663822388387959 is resolved (Sep 22nd 2022)
if (isNextDev) { if (isNextDev) {
it('should skip next dev for now', () => {}) it('should skip next dev for now', () => {})
@ -214,8 +217,7 @@ createNextDescribe(
expect( expect(
requests.filter( requests.filter(
(request) => (request) =>
request === '/static-page' || request === '/static-page' || request.includes(NEXT_RSC_UNION_QUERY)
request.includes(NEXT_RSC_UNION_QUERY)
).length ).length
).toBe(0) ).toBe(0)
} }
@ -359,9 +361,7 @@ createNextDescribe(
() => browser.elementById('search-params-data').text(), () => browser.elementById('search-params-data').text(),
/{"foo":"true"}/ /{"foo":"true"}/
) )
await browser await browser.elementByCss(`[href="${basePath}/search-params"]`).click()
.elementByCss(`[href="${basePath}/search-params"]`)
.click()
await check( await check(
() => browser.elementById('search-params-data').text(), () => browser.elementById('search-params-data').text(),
/{}/ /{}/
@ -385,9 +385,7 @@ createNextDescribe(
.click() .click()
// navigating back to the route group page shouldn't trigger any data fetch // navigating back to the route group page shouldn't trigger any data fetch
await browser await browser.elementByCss("[href='/prefetch-auto-route-groups']").click()
.elementByCss("[href='/prefetch-auto-route-groups']")
.click()
// confirm that the dashboard page is still rendering the stale fetch count, as it should be cached // confirm that the dashboard page is still rendering the stale fetch count, as it should be cached
expect(await browser.elementById('count').text()).toBe('1') expect(await browser.elementById('count').text()).toBe('1')
@ -398,9 +396,7 @@ createNextDescribe(
.click() .click()
// finally, going back to the route group page shouldn't trigger any data fetch // finally, going back to the route group page shouldn't trigger any data fetch
await browser await browser.elementByCss("[href='/prefetch-auto-route-groups']").click()
.elementByCss("[href='/prefetch-auto-route-groups']")
.click()
// confirm that the dashboard page is still rendering the stale fetch count, as it should be cached // confirm that the dashboard page is still rendering the stale fetch count, as it should be cached
expect(await browser.elementById('count').text()).toBe('1') expect(await browser.elementById('count').text()).toBe('1')
@ -411,5 +407,4 @@ createNextDescribe(
expect(await browser.elementById('count').text()).toBe('4') expect(await browser.elementById('count').text()).toBe('4')
}) })
}) })
} })
)

View file

@ -1,14 +1,17 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { waitFor } from 'next-test-utils' import { waitFor } from 'next-test-utils'
import cheerio from 'cheerio' import cheerio from 'cheerio'
createNextDescribe( describe('app dir rendering', () => {
'app dir rendering', const { next, isNextDev, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextDev: isDev }) => {
if (skipped) {
return
}
it('should serve app/page.server.js at /', async () => { it('should serve app/page.server.js at /', async () => {
const html = await next.render('/') const html = await next.render('/')
expect(html).toContain('app/page.server.js') expect(html).toContain('app/page.server.js')
@ -42,7 +45,7 @@ createNextDescribe(
}) })
it(`should run data in parallel ${ it(`should run data in parallel ${
isDev ? 'during development' : 'and use cached version for production' isNextDev ? 'during development' : 'and use cached version for production'
}`, async () => { }`, async () => {
// const startTime = Date.now() // const startTime = Date.now()
const $ = await next.render$('/static-only/slow') const $ = await next.render$('/static-only/slow')
@ -125,5 +128,4 @@ createNextDescribe(
expect(pageNow).toBe(pageNowSecond) expect(pageNow).toBe(pageNowSecond)
}) })
}) })
} })
)

View file

@ -1,18 +1,20 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
const bathPath = process.env.BASE_PATH ?? '' const bathPath = process.env.BASE_PATH ?? ''
createNextDescribe( describe('app-routes-subrequests', () => {
'app-routes-subrequests', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => {
if (skipped) {
return
}
it('shortcuts after 5 subrequests', async () => { it('shortcuts after 5 subrequests', async () => {
expect(JSON.parse(await next.render(bathPath + '/'))).toEqual({ expect(JSON.parse(await next.render(bathPath + '/'))).toEqual({
count: 5, count: 5,
}) })
}) })
} })
)

View file

@ -1,11 +1,10 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app-routes-trailing-slash', () => {
'app-routes-trailing-slash', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it.each(['edge', 'node'])( it.each(['edge', 'node'])(
'should handle trailing slash for %s runtime', 'should handle trailing slash for %s runtime',
async (runtime) => { async (runtime) => {
@ -27,5 +26,4 @@ createNextDescribe(
}) })
} }
) )
} })
)

View file

@ -1,4 +1,4 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check, waitFor } from 'next-test-utils' import { check, waitFor } from 'next-test-utils'
import { Readable } from 'stream' import { Readable } from 'stream'
@ -10,12 +10,11 @@ import {
const basePath = process.env.BASE_PATH ?? '' const basePath = process.env.BASE_PATH ?? ''
createNextDescribe( describe('app-custom-routes', () => {
'app-custom-routes', const { next, isNextDeploy, isNextDev, isNextStart } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next, isNextDeploy, isNextDev, isNextStart }) => {
describe('works with api prefix correctly', () => { describe('works with api prefix correctly', () => {
it('statically generates correctly with no dynamic usage', async () => { it('statically generates correctly with no dynamic usage', async () => {
if (isNextStart) { if (isNextStart) {
@ -46,9 +45,7 @@ createNextDescribe(
.catch(() => '') .catch(() => '')
).toBeFalsy() ).toBeFalsy()
} }
expect( expect(JSON.parse(await next.render(basePath + '/api/dynamic'))).toEqual({
JSON.parse(await next.render(basePath + '/api/dynamic'))
).toEqual({
pathname: '/api/dynamic', pathname: '/api/dynamic',
query: {}, query: {},
}) })
@ -90,9 +87,7 @@ createNextDescribe(
}) })
await check(async () => { await check(async () => {
expect(data).not.toEqual( expect(data).not.toEqual(JSON.parse(await next.render(basePath + path)))
JSON.parse(await next.render(basePath + path))
)
return 'success' return 'success'
}, 'success') }, 'success')
@ -269,13 +264,10 @@ createNextDescribe(
}, },
}) })
const res = await next.fetch( const res = await next.fetch(basePath + '/edge/advanced/body/streaming', {
basePath + '/edge/advanced/body/streaming',
{
method: 'POST', method: 'POST',
body: stream, body: stream,
} })
)
expect(res.status).toEqual(200) expect(res.status).toEqual(200)
expect(await res.text()).toEqual(body.join('\n') + '\n') expect(await res.text()).toEqual(body.join('\n') + '\n')
@ -706,5 +698,4 @@ createNextDescribe(
expect(cliOutput).not.toContain('Attempted import error') expect(cliOutput).not.toContain('Attempted import error')
}) })
}) })
} })
)

View file

@ -1,13 +1,12 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
const bathPath = process.env.BASE_PATH ?? '' const bathPath = process.env.BASE_PATH ?? ''
createNextDescribe( describe('app-simple-routes', () => {
'app-simple-routes', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
describe('works with simple routes', () => { describe('works with simple routes', () => {
it('renders a node route', async () => { it('renders a node route', async () => {
expect( expect(
@ -24,5 +23,4 @@ createNextDescribe(
}) })
}) })
}) })
} })
)

View file

@ -2,7 +2,7 @@ import globOrig from 'glob'
import cheerio from 'cheerio' import cheerio from 'cheerio'
import { promisify } from 'util' import { promisify } from 'util'
import { join } from 'path' import { join } from 'path'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { import {
check, check,
fetchViaHTTP, fetchViaHTTP,
@ -14,9 +14,8 @@ import stripAnsi from 'strip-ansi'
const glob = promisify(globOrig) const glob = promisify(globOrig)
createNextDescribe( describe('app-dir static/dynamic handling', () => {
'app-dir static/dynamic handling', const { next, isNextDev, isNextStart, isNextDeploy } = nextTestSetup({
{
files: __dirname, files: __dirname,
env: { env: {
NEXT_DEBUG_BUILD: '1', NEXT_DEBUG_BUILD: '1',
@ -26,8 +25,8 @@ createNextDescribe(
} }
: {}), : {}),
}, },
}, })
({ next, isNextDev: isDev, isNextStart, isNextDeploy }) => {
let prerenderManifest let prerenderManifest
let buildCliOutputIndex = 0 let buildCliOutputIndex = 0
@ -115,15 +114,11 @@ createNextDescribe(
'.next/server/app/variable-revalidate/revalidate-360-isr.meta' '.next/server/app/variable-revalidate/revalidate-360-isr.meta'
) )
) )
expect(meta.headers['x-next-cache-tags']).toContain( expect(meta.headers['x-next-cache-tags']).toContain('unstable_cache_tag1')
'unstable_cache_tag1'
)
}) })
it('should infer a fetchCache of force-no-store when force-dynamic is used', async () => { it('should infer a fetchCache of force-no-store when force-dynamic is used', async () => {
const $ = await next.render$( const $ = await next.render$('/force-dynamic-fetch-cache/no-fetch-cache')
'/force-dynamic-fetch-cache/no-fetch-cache'
)
const initData = $('#data').text() const initData = $('#data').text()
await retry(async () => { await retry(async () => {
const $2 = await next.render$( const $2 = await next.render$(
@ -262,7 +257,7 @@ createNextDescribe(
} }
}) })
if (isDev) { if (isNextDev) {
it('should error correctly for invalid params from generateStaticParams', async () => { it('should error correctly for invalid params from generateStaticParams', async () => {
await next.patchFile( await next.patchFile(
'app/invalid/[slug]/page.js', 'app/invalid/[slug]/page.js',
@ -312,7 +307,7 @@ createNextDescribe(
} }
}) })
if (!isDev && !process.env.CUSTOM_CACHE_HANDLER) { if (!isNextDev && !process.env.CUSTOM_CACHE_HANDLER) {
it('should properly revalidate a route handler that triggers dynamic usage with force-static', async () => { it('should properly revalidate a route handler that triggers dynamic usage with force-static', async () => {
// wait for the revalidation period // wait for the revalidation period
let res = await next.fetch('/route-handler/no-store-force-static') let res = await next.fetch('/route-handler/no-store-force-static')
@ -352,9 +347,7 @@ createNextDescribe(
])( ])(
'it should revalidate tag correctly with $type', 'it should revalidate tag correctly with $type',
async ({ revalidateApi }) => { async ({ revalidateApi }) => {
const initRes = await next.fetch( const initRes = await next.fetch('/variable-revalidate/revalidate-360')
'/variable-revalidate/revalidate-360'
)
const html = await initRes.text() const html = await initRes.text()
const $ = cheerio.load(html) const $ = cheerio.load(html)
const initLayoutData = $('#layout-data').text() const initLayoutData = $('#layout-data').text()
@ -380,9 +373,7 @@ createNextDescribe(
) )
expect((await revalidateRes.json()).revalidated).toBe(true) expect((await revalidateRes.json()).revalidated).toBe(true)
const newRes = await next.fetch( const newRes = await next.fetch('/variable-revalidate/revalidate-360')
'/variable-revalidate/revalidate-360'
)
const cacheHeader = newRes.headers.get('x-nextjs-cache') const cacheHeader = newRes.headers.get('x-nextjs-cache')
if ((global as any).isNextStart && cacheHeader) { if ((global as any).isNextStart && cacheHeader) {
@ -563,9 +554,7 @@ createNextDescribe(
// wait for a fresh revalidation // wait for a fresh revalidation
await check(async () => { await check(async () => {
const $ = await next.render$( const $ = await next.render$('/variable-config-revalidate/revalidate-3')
'/variable-config-revalidate/revalidate-3'
)
prevInitialDate = $('#date').text() prevInitialDate = $('#date').text()
prevInitialRandomData = $('#random-data').text() prevInitialRandomData = $('#random-data').text()
@ -577,9 +566,7 @@ createNextDescribe(
// the date should revalidate first after 3 seconds // the date should revalidate first after 3 seconds
// while the fetch data stays in place for 9 seconds // while the fetch data stays in place for 9 seconds
await check(async () => { await check(async () => {
const $ = await next.render$( const $ = await next.render$('/variable-config-revalidate/revalidate-3')
'/variable-config-revalidate/revalidate-3'
)
const curDate = $('#date').text() const curDate = $('#date').text()
const curRandomData = $('#random-data').text() const curRandomData = $('#random-data').text()
@ -2054,9 +2041,7 @@ createNextDescribe(
const curHtml = await curRes.text() const curHtml = await curRes.text()
const cur$ = cheerio.load(curHtml) const cur$ = cheerio.load(curHtml)
expect(cur$('#data-no-cache').text()).toBe( expect(cur$('#data-no-cache').text()).toBe(prev$('#data-no-cache').text())
prev$('#data-no-cache').text()
)
expect(cur$('#data-force-cache').text()).toBe( expect(cur$('#data-force-cache').text()).toBe(
prev$('#data-force-cache').text() prev$('#data-force-cache').text()
) )
@ -2118,7 +2103,7 @@ createNextDescribe(
}, 'success') }, 'success')
}) })
if (isDev) { if (isNextDev) {
it('should bypass fetch cache with cache-control: no-cache', async () => { it('should bypass fetch cache with cache-control: no-cache', async () => {
const res = await fetchViaHTTP( const res = await fetchViaHTTP(
next.url, next.url,
@ -2332,7 +2317,7 @@ createNextDescribe(
let langFetchSlug let langFetchSlug
let slugFetchSlug let slugFetchSlug
if (isDev) { if (isNextDev) {
await check(() => { await check(() => {
const matches = stripAnsi(next.cliOutput).match( const matches = stripAnsi(next.cliOutput).match(
/partial-gen-params fetch ([\d]{1,})/ /partial-gen-params fetch ([\d]{1,})/
@ -2635,10 +2620,7 @@ createNextDescribe(
it('should cache correctly with utf8 encoding', async () => { it('should cache correctly with utf8 encoding', async () => {
await check(async () => { await check(async () => {
const res = await fetchViaHTTP( const res = await fetchViaHTTP(next.url, '/variable-revalidate/encoding')
next.url,
'/variable-revalidate/encoding'
)
expect(res.status).toBe(200) expect(res.status).toBe(200)
const html = await res.text() const html = await res.text()
const $ = cheerio.load(html) const $ = cheerio.load(html)
@ -2650,10 +2632,7 @@ createNextDescribe(
'超鬼畜激辛ボム兵スピンジャンプ Bomb Spin Jump' '超鬼畜激辛ボム兵スピンジャンプ Bomb Spin Jump'
) )
const res2 = await fetchViaHTTP( const res2 = await fetchViaHTTP(next.url, '/variable-revalidate/encoding')
next.url,
'/variable-revalidate/encoding'
)
expect(res2.status).toBe(200) expect(res2.status).toBe(200)
const html2 = await res2.text() const html2 = await res2.text()
const $2 = cheerio.load(html2) const $2 = cheerio.load(html2)
@ -2697,10 +2676,7 @@ createNextDescribe(
it('should cache correctly handle JSON body', async () => { it('should cache correctly handle JSON body', async () => {
await check(async () => { await check(async () => {
const res = await fetchViaHTTP( const res = await fetchViaHTTP(next.url, '/variable-revalidate-edge/body')
next.url,
'/variable-revalidate-edge/body'
)
expect(res.status).toBe(200) expect(res.status).toBe(200)
const html = await res.text() const html = await res.text()
const $ = cheerio.load(html) const $ = cheerio.load(html)
@ -2727,9 +2703,7 @@ createNextDescribe(
it('should not throw Dynamic Server Usage error when using generateStaticParams with draftMode', async () => { it('should not throw Dynamic Server Usage error when using generateStaticParams with draftMode', async () => {
const browserOnIndexPage = await next.browser('/ssg-draft-mode') const browserOnIndexPage = await next.browser('/ssg-draft-mode')
const content = await browserOnIndexPage const content = await browserOnIndexPage.elementByCss('#draft-mode').text()
.elementByCss('#draft-mode')
.text()
expect(content).toBe('{"isEnabled":false}') expect(content).toBe('{"isEnabled":false}')
}) })
@ -2979,9 +2953,7 @@ createNextDescribe(
await browser.elementByCss('#author-2').click() await browser.elementByCss('#author-2').click()
await check(async () => { await check(async () => {
const params = JSON.parse( const params = JSON.parse(await browser.elementByCss('#params').text())
await browser.elementByCss('#params').text()
)
return params.author === 'seb' ? 'found' : params return params.author === 'seb' ? 'found' : params
}, 'found') }, 'found')
@ -2989,9 +2961,7 @@ createNextDescribe(
await browser.elementByCss('#author-1-post-1').click() await browser.elementByCss('#author-1-post-1').click()
await check(async () => { await check(async () => {
const params = JSON.parse( const params = JSON.parse(await browser.elementByCss('#params').text())
await browser.elementByCss('#params').text()
)
return params.author === 'tim' && params.slug === 'first-post' return params.author === 'tim' && params.slug === 'first-post'
? 'found' ? 'found'
: params : params
@ -3001,9 +2971,7 @@ createNextDescribe(
await browser.back() await browser.back()
await check(async () => { await check(async () => {
const params = JSON.parse( const params = JSON.parse(await browser.elementByCss('#params').text())
await browser.elementByCss('#params').text()
)
return params.author === 'seb' ? 'found' : params return params.author === 'seb' ? 'found' : params
}, 'found') }, 'found')
@ -3115,9 +3083,7 @@ createNextDescribe(
'/hooks/use-search-params/with-suspense?first=value&second=other&third' '/hooks/use-search-params/with-suspense?first=value&second=other&third'
const browser = await next.browser(url) const browser = await next.browser(url)
expect(await browser.elementByCss('#params-first').text()).toBe( expect(await browser.elementByCss('#params-first').text()).toBe('value')
'value'
)
expect(await browser.elementByCss('#params-second').text()).toBe( expect(await browser.elementByCss('#params-second').text()).toBe(
'other' 'other'
) )
@ -3138,9 +3104,7 @@ createNextDescribe(
) )
expect(await browser.elementByCss('#params-first').text()).toBe('N/A') expect(await browser.elementByCss('#params-first').text()).toBe('N/A')
expect(await browser.elementByCss('#params-second').text()).toBe( expect(await browser.elementByCss('#params-second').text()).toBe('N/A')
'N/A'
)
expect(await browser.elementByCss('#params-third').text()).toBe('N/A') expect(await browser.elementByCss('#params-third').text()).toBe('N/A')
expect(await browser.elementByCss('#params-not-real').text()).toBe( expect(await browser.elementByCss('#params-not-real').text()).toBe(
'N/A' 'N/A'
@ -3166,9 +3130,7 @@ createNextDescribe(
) )
expect(await browser.elementByCss('#params-first').text()).toBe('a') expect(await browser.elementByCss('#params-first').text()).toBe('a')
expect(await browser.elementByCss('#params-second').text()).toBe( expect(await browser.elementByCss('#params-second').text()).toBe('b')
'b'
)
expect(await browser.elementByCss('#params-third').text()).toBe('c') expect(await browser.elementByCss('#params-third').text()).toBe('c')
expect(await browser.elementByCss('#params-not-real').text()).toBe( expect(await browser.elementByCss('#params-not-real').text()).toBe(
'N/A' 'N/A'
@ -3177,12 +3139,10 @@ createNextDescribe(
} }
}) })
// Don't run these tests in development mode since they won't be statically generated // Don't run these tests in development mode since they won't be statically generated
if (!isDev) { if (!isNextDev) {
describe('server response', () => { describe('server response', () => {
it('should bailout to client rendering - with suspense boundary', async () => { it('should bailout to client rendering - with suspense boundary', async () => {
const res = await next.fetch( const res = await next.fetch('/hooks/use-search-params/with-suspense')
'/hooks/use-search-params/with-suspense'
)
const html = await res.text() const html = await res.text()
expect(html).toInclude('<p>search params suspense</p>') expect(html).toInclude('<p>search params suspense</p>')
}) })
@ -3355,7 +3315,7 @@ createNextDescribe(
).toBeNull() ).toBeNull()
}) })
} }
if (!process.env.CUSTOM_CACHE_HANDLER && isDev) { if (!process.env.CUSTOM_CACHE_HANDLER && isNextDev) {
it('should not cache request if response data size is greater than 2MB and FetchCache is possible in development mode', async () => { it('should not cache request if response data size is greater than 2MB and FetchCache is possible in development mode', async () => {
const cliOutputStart = next.cliOutput.length const cliOutputStart = next.cliOutput.length
const resp1 = await next.fetch('/force-cache/large-data') const resp1 = await next.fetch('/force-cache/large-data')
@ -3373,8 +3333,7 @@ createNextDescribe(
await check(async () => { await check(async () => {
expect( expect(
next.cliOutput.substring(cliOutputStart).match(/Load data/g) next.cliOutput.substring(cliOutputStart).match(/Load data/g).length
.length
).toBe(2) ).toBe(2)
expect(next.cliOutput.substring(cliOutputStart)).toContain( expect(next.cliOutput.substring(cliOutputStart)).toContain(
'Error: Failed to set Next.js data cache, items over 2MB can not be cached' 'Error: Failed to set Next.js data cache, items over 2MB can not be cached'
@ -3383,7 +3342,7 @@ createNextDescribe(
}, 'success') }, 'success')
}) })
} }
if (process.env.CUSTOM_CACHE_HANDLER && isDev) { if (process.env.CUSTOM_CACHE_HANDLER && isNextDev) {
it('should cache request if response data size is greater than 2MB in development mode', async () => { it('should cache request if response data size is greater than 2MB in development mode', async () => {
const cliOutputStart = next.cliOutput.length const cliOutputStart = next.cliOutput.length
const resp1 = await next.fetch('/force-cache/large-data') const resp1 = await next.fetch('/force-cache/large-data')
@ -3401,8 +3360,7 @@ createNextDescribe(
await check(async () => { await check(async () => {
expect( expect(
next.cliOutput.substring(cliOutputStart).match(/Load data/g) next.cliOutput.substring(cliOutputStart).match(/Load data/g).length
.length
).toBe(1) ).toBe(1)
return 'success' return 'success'
}, 'success') }, 'success')
@ -3418,5 +3376,4 @@ createNextDescribe(
const browser = await next.browser('/dynamic-param-edge/hello') const browser = await next.browser('/dynamic-param-edge/hello')
expect(await browser.elementByCss('#slug').text()).toBe('hello') expect(await browser.elementByCss('#slug').text()).toBe('hello')
}) })
} })
)

View file

@ -1,12 +1,15 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app dir - validation', () => {
'app dir - validation', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => {
if (skipped) {
return
}
it('should error when passing invalid router state tree', async () => { it('should error when passing invalid router state tree', async () => {
const res = await next.fetch('/', { const res = await next.fetch('/', {
headers: { headers: {
@ -24,5 +27,4 @@ createNextDescribe(
}) })
expect(res2.status).toBe(200) expect(res2.status).toBe(200)
}) })
} })
)

View file

@ -1,4 +1,4 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check, retry, waitFor } from 'next-test-utils' import { check, retry, waitFor } from 'next-test-utils'
import cheerio from 'cheerio' import cheerio from 'cheerio'
import stripAnsi from 'strip-ansi' import stripAnsi from 'strip-ansi'
@ -8,9 +8,14 @@ import stripAnsi from 'strip-ansi'
// gates like this one into a single module. // gates like this one into a single module.
const isPPREnabledByDefault = process.env.__NEXT_EXPERIMENTAL_PPR === 'true' const isPPREnabledByDefault = process.env.__NEXT_EXPERIMENTAL_PPR === 'true'
createNextDescribe( describe('app dir - basic', () => {
'app dir - basic', const {
{ next,
isNextDev: isDev,
isNextStart,
isNextDeploy,
isTurbopack,
} = nextTestSetup({
files: __dirname, files: __dirname,
buildCommand: process.env.NEXT_EXPERIMENTAL_COMPILE buildCommand: process.env.NEXT_EXPERIMENTAL_COMPILE
? `pnpm next build --experimental-build-mode=compile` ? `pnpm next build --experimental-build-mode=compile`
@ -18,8 +23,8 @@ createNextDescribe(
dependencies: { dependencies: {
nanoid: '4.0.1', nanoid: '4.0.1',
}, },
}, })
({ next, isNextDev: isDev, isNextStart, isNextDeploy, isTurbopack }) => {
if (isDev && isPPREnabledByDefault) { if (isDev && isPPREnabledByDefault) {
it('should allow returning just skeleton in dev with query', async () => { it('should allow returning just skeleton in dev with query', async () => {
const res = await next.fetch('/skeleton?__nextppronly=1') const res = await next.fetch('/skeleton?__nextppronly=1')
@ -52,9 +57,9 @@ createNextDescribe(
}) })
it('should not have entire prerender-manifest for edge', async () => { it('should not have entire prerender-manifest for edge', async () => {
expect( expect(await next.readFile('.next/prerender-manifest.js')).not.toContain(
await next.readFile('.next/prerender-manifest.js') 'initialRevalidate'
).not.toContain('initialRevalidate') )
}) })
if (!process.env.NEXT_EXPERIMENTAL_COMPILE) { if (!process.env.NEXT_EXPERIMENTAL_COMPILE) {
@ -70,19 +75,18 @@ createNextDescribe(
await next.readFile('.next/server/middleware-manifest.json') await next.readFile('.next/server/middleware-manifest.json')
) )
expect( expect(
middlewareManifest.functions['/(rootonly)/dashboard/hello/page'] middlewareManifest.functions['/(rootonly)/dashboard/hello/page'].regions
.regions
).toEqual(['iad1', 'sfo1']) ).toEqual(['iad1', 'sfo1'])
expect(middlewareManifest.functions['/dashboard/page'].regions).toEqual( expect(middlewareManifest.functions['/dashboard/page'].regions).toEqual([
['iad1'] 'iad1',
) ])
expect( expect(
middlewareManifest.functions['/slow-page-no-loading/page'].regions middlewareManifest.functions['/slow-page-no-loading/page'].regions
).toEqual(['global']) ).toEqual(['global'])
expect(middlewareManifest.functions['/test-page/page'].regions).toEqual( expect(middlewareManifest.functions['/test-page/page'].regions).toEqual([
['home'] 'home',
) ])
// Inherits from the root layout. // Inherits from the root layout.
expect( expect(
@ -164,9 +168,7 @@ createNextDescribe(
requests.push(req.url()) requests.push(req.url())
}) })
await browser.eval( await browser.eval('window.location.href = "/dynamic-client/first/second"')
'window.location.href = "/dynamic-client/first/second"'
)
await check(async () => { await check(async () => {
return requests.some( return requests.some(
@ -281,9 +283,7 @@ createNextDescribe(
'.next/server/app/dashboard/deployments/[id]/page.js.nft.json' '.next/server/app/dashboard/deployments/[id]/page.js.nft.json'
) )
) as { files: string[] } ) as { files: string[] }
expect(trace.files.some((file) => file.endsWith('data.json'))).toBe( expect(trace.files.some((file) => file.endsWith('data.json'))).toBe(true)
true
)
}) })
} }
@ -810,9 +810,7 @@ createNextDescribe(
expect( expect(
await browser.waitForElementByCss('#app-text', 5000).text() await browser.waitForElementByCss('#app-text', 5000).text()
).toBe( ).toBe('hello from app/dynamic-pages-route-app-overlap/app-dir/page')
'hello from app/dynamic-pages-route-app-overlap/app-dir/page'
)
// When refreshing the browser, the app page should be rendered // When refreshing the browser, the app page should be rendered
await browser.refresh() await browser.refresh()
@ -893,9 +891,7 @@ createNextDescribe(
const $ = await next.render$('/dynamic/books/hello-world') const $ = await next.render$('/dynamic/books/hello-world')
expect($('#dynamic-layout-params').text()).toBe('{}') expect($('#dynamic-layout-params').text()).toBe('{}')
expect($('#category-layout-params').text()).toBe( expect($('#category-layout-params').text()).toBe('{"category":"books"}')
'{"category":"books"}'
)
expect($('#id-layout-params').text()).toBe( expect($('#id-layout-params').text()).toBe(
'{"category":"books","id":"hello-world"}' '{"category":"books","id":"hello-world"}'
) )
@ -1034,9 +1030,9 @@ createNextDescribe(
// TODO-APP: `await next.browser()` causes waiting for the full page to complete streaming. At that point "Loading..." is replaced by the actual content // TODO-APP: `await next.browser()` causes waiting for the full page to complete streaming. At that point "Loading..." is replaced by the actual content
// expect(await browser.elementByCss('#loading').text()).toBe('Loading...') // expect(await browser.elementByCss('#loading').text()).toBe('Loading...')
expect( expect(await browser.elementByCss('#slow-layout-message').text()).toBe(
await browser.elementByCss('#slow-layout-message').text() 'hello from slow layout'
).toBe('hello from slow layout') )
expect(await browser.elementByCss('#page-message').text()).toBe( expect(await browser.elementByCss('#page-message').text()).toBe(
'Hello World' 'Hello World'
@ -1044,9 +1040,7 @@ createNextDescribe(
}) })
it('should render loading.js in initial html for slow layout and page', async () => { it('should render loading.js in initial html for slow layout and page', async () => {
const $ = await next.render$( const $ = await next.render$('/slow-layout-and-page-with-loading/slow')
'/slow-layout-and-page-with-loading/slow'
)
expect($('#loading-layout').text()).toBe('Loading layout...') expect($('#loading-layout').text()).toBe('Loading layout...')
expect($('#loading-page').text()).toBe('Loading page...') expect($('#loading-page').text()).toBe('Loading page...')
@ -1063,9 +1057,9 @@ createNextDescribe(
// expect(await browser.elementByCss('#loading-layout').text()).toBe('Loading...') // expect(await browser.elementByCss('#loading-layout').text()).toBe('Loading...')
// expect(await browser.elementByCss('#loading-page').text()).toBe('Loading...') // expect(await browser.elementByCss('#loading-page').text()).toBe('Loading...')
expect( expect(await browser.elementByCss('#slow-layout-message').text()).toBe(
await browser.elementByCss('#slow-layout-message').text() 'hello from slow layout'
).toBe('hello from slow layout') )
expect(await browser.elementByCss('#slow-page-message').text()).toBe( expect(await browser.elementByCss('#slow-page-message').text()).toBe(
'hello from slow page' 'hello from slow page'
@ -1178,9 +1172,7 @@ createNextDescribe(
const ssrInitial = await next.render('/client-component-route') const ssrInitial = await next.render('/client-component-route')
expect(ssrInitial).toContain( expect(ssrInitial).toContain('hello from app/client-component-route')
'hello from app/client-component-route'
)
expect(await browser.elementByCss('p').text()).toContain( expect(await browser.elementByCss('p').text()).toContain(
'hello from app/client-component-route' 'hello from app/client-component-route'
@ -1378,9 +1370,7 @@ createNextDescribe(
async () => { async () => {
const browser = await next.browser('/template/servercomponent') const browser = await next.browser('/template/servercomponent')
// eslint-disable-next-line jest/no-standalone-expect // eslint-disable-next-line jest/no-standalone-expect
expect(await browser.elementByCss('h1').text()).toStartWith( expect(await browser.elementByCss('h1').text()).toStartWith('Template')
'Template'
)
const currentTime = await browser const currentTime = await browser
.elementByCss('#performance-now') .elementByCss('#performance-now')
@ -1390,9 +1380,7 @@ createNextDescribe(
await browser.waitForElementByCss('#other-page') await browser.waitForElementByCss('#other-page')
// eslint-disable-next-line jest/no-standalone-expect // eslint-disable-next-line jest/no-standalone-expect
expect(await browser.elementByCss('h1').text()).toStartWith( expect(await browser.elementByCss('h1').text()).toStartWith('Template')
'Template'
)
// template should rerender on navigation even when it's a server component // template should rerender on navigation even when it's a server component
// eslint-disable-next-line jest/no-standalone-expect // eslint-disable-next-line jest/no-standalone-expect
@ -1703,9 +1691,7 @@ createNextDescribe(
await retry(async () => { await retry(async () => {
await browser.elementByCss('#get-order').click() await browser.elementByCss('#get-order').click()
const order = JSON.parse( const order = JSON.parse(await browser.elementByCss('#order').text())
await browser.elementByCss('#order').text()
)
expect(order?.length).toBe(2) expect(order?.length).toBe(2)
}) })
} }
@ -1767,5 +1753,4 @@ createNextDescribe(
}) })
} }
}) })
} })
)

View file

@ -1,4 +1,4 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import fs from 'fs-extra' import fs from 'fs-extra'
import os from 'os' import os from 'os'
import path from 'path' import path from 'path'
@ -12,16 +12,19 @@ import {
if (!(globalThis as any).isNextStart) { if (!(globalThis as any).isNextStart) {
it('should skip for non-next start', () => {}) it('should skip for non-next start', () => {})
} else { } else {
createNextDescribe( describe('output: standalone with getStaticProps', () => {
'output: standalone with getStaticProps', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipStart: true, skipStart: true,
dependencies: { dependencies: {
swr: 'latest', swr: 'latest',
}, },
}, })
({ next }) => {
if (skipped) {
return
}
beforeAll(async () => { beforeAll(async () => {
await next.patchFile( await next.patchFile(
'next.config.js', 'next.config.js',
@ -53,10 +56,7 @@ if (!(globalThis as any).isNextStart) {
}) })
it('should work correctly with output standalone', async () => { it('should work correctly with output standalone', async () => {
const tmpFolder = path.join( const tmpFolder = path.join(os.tmpdir(), 'next-standalone-' + Date.now())
os.tmpdir(),
'next-standalone-' + Date.now()
)
await fs.move(path.join(next.testDir, '.next/standalone'), tmpFolder) await fs.move(path.join(next.testDir, '.next/standalone'), tmpFolder)
let server: any let server: any
@ -83,6 +83,5 @@ if (!(globalThis as any).isNextStart) {
await fs.remove(tmpFolder) await fs.remove(tmpFolder)
} }
}) })
} })
)
} }

View file

@ -1,4 +1,4 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import fs from 'fs-extra' import fs from 'fs-extra'
import os from 'os' import os from 'os'
import path from 'path' import path from 'path'
@ -12,13 +12,16 @@ import {
if (!(globalThis as any).isNextStart) { if (!(globalThis as any).isNextStart) {
it('should skip for non-next start', () => {}) it('should skip for non-next start', () => {})
} else { } else {
createNextDescribe( describe('output: standalone with app dir', () => {
'output: standalone with app dir', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipStart: true, skipStart: true,
}, })
({ next }) => {
if (skipped) {
return
}
beforeAll(async () => { beforeAll(async () => {
await next.patchFile( await next.patchFile(
'next.config.js', 'next.config.js',
@ -55,10 +58,7 @@ if (!(globalThis as any).isNextStart) {
}) })
it('should work correctly with output standalone', async () => { it('should work correctly with output standalone', async () => {
const tmpFolder = path.join( const tmpFolder = path.join(os.tmpdir(), 'next-standalone-' + Date.now())
os.tmpdir(),
'next-standalone-' + Date.now()
)
await fs.move(path.join(next.testDir, '.next/standalone'), tmpFolder) await fs.move(path.join(next.testDir, '.next/standalone'), tmpFolder)
let server: any let server: any
@ -99,6 +99,5 @@ if (!(globalThis as any).isNextStart) {
await fs.remove(tmpFolder) await fs.remove(tmpFolder)
} }
}) })
} })
)
} }

View file

@ -1,17 +1,17 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('async-component-preload', () => {
'async-component-preload', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => {
if (skipped) {
return
}
it('should handle redirect in an async page', async () => { it('should handle redirect in an async page', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
expect(await browser.waitForElementByCss('#success').text()).toBe( expect(await browser.waitForElementByCss('#success').text()).toBe('Success')
'Success'
)
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('router autoscrolling on navigation with css modules', () => {
'router autoscrolling on navigation with css modules', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
type BrowserInterface = Awaited<ReturnType<(typeof next)['browser']>> type BrowserInterface = Awaited<ReturnType<(typeof next)['browser']>>
const getTopScroll = async (browser: BrowserInterface) => const getTopScroll = async (browser: BrowserInterface) =>
@ -56,5 +55,4 @@ createNextDescribe(
await waitForScrollToComplete(browser, { x: 0, y: 0 }) await waitForScrollToComplete(browser, { x: 0, y: 0 })
}) })
}) })
} })
)

View file

@ -1,14 +1,17 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
// TODO-APP: fix test as it's failing randomly // TODO-APP: fix test as it's failing randomly
describe.skip('app-dir back button download bug', () => { describe.skip('app-dir back button download bug', () => {
createNextDescribe( describe('app-dir back button download bug', () => {
'app-dir back button download bug', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => {
if (skipped) {
return
}
it('should redirect route when clicking link', async () => { it('should redirect route when clicking link', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
const text = await browser const text = await browser
@ -24,6 +27,5 @@ describe.skip('app-dir back button download bug', () => {
'Home!' 'Home!'
) )
}) })
} })
)
}) })

View file

@ -1,12 +1,15 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app-dir build size', () => {
'app-dir build size', const { next, isNextStart, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextStart }) => {
if (skipped) {
return
}
if (isNextStart) { if (isNextStart) {
it('should have correct size in build output', async () => { it('should have correct size in build output', async () => {
const regex = /(\S+)\s+([\d.]+\s\w+)\s+([\d.]+\s\w+)/g const regex = /(\S+)\s+([\d.]+\s\w+)\s+([\d.]+\s\w+)/g
@ -45,5 +48,4 @@ createNextDescribe(
it('should skip next dev for now', () => {}) it('should skip next dev for now', () => {})
return return
} }
} })
)

View file

@ -1,15 +1,18 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('conflicting-page-segments', () => {
'conflicting-page-segments', const { next, isNextDev, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
// we skip start because the build will fail and we won't be able to catch it // we skip start because the build will fail and we won't be able to catch it
// start is re-triggered but caught in the assertions below // start is re-triggered but caught in the assertions below
skipStart: true, skipStart: true,
}, })
({ next, isNextDev }) => {
if (skipped) {
return
}
it('should throw an error when a route groups causes a conflict with a parallel segment', async () => { it('should throw an error when a route groups causes a conflict with a parallel segment', async () => {
if (isNextDev) { if (isNextDev) {
await next.start() await next.start()
@ -27,5 +30,4 @@ createNextDescribe(
) )
} }
}) })
} })
)

View file

@ -1,11 +1,10 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('Web Crypto API is available globally', () => {
'Web Crypto API is available globally', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
// Recommended for tests that need a full browser // Recommended for tests that need a full browser
it('should be available in Server Components', async () => { it('should be available in Server Components', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
@ -18,5 +17,4 @@ createNextDescribe(
const html = await res.text() const html = await res.text()
expect(html).toContain('crypto is available') expect(html).toContain('crypto is available')
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { waitFor } from 'next-test-utils' import { waitFor } from 'next-test-utils'
createNextDescribe( describe('app dir - draft mode', () => {
'app dir - draft mode', const { next, isNextDev } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next, isNextDev }) => {
async function runTests({ basePath = '/' }: { basePath: string }) { async function runTests({ basePath = '/' }: { basePath: string }) {
let origRandHome = 'unintialized' let origRandHome = 'unintialized'
let origRandWithCookies = 'unintialized' let origRandWithCookies = 'unintialized'
@ -116,5 +115,4 @@ createNextDescribe(
describe('in edge runtime', () => { describe('in edge runtime', () => {
runTests({ basePath: '/with-edge/' }) runTests({ basePath: '/with-edge/' })
}) })
} })
)

View file

@ -1,13 +1,16 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { retry } from 'next-test-utils' import { retry } from 'next-test-utils'
createNextDescribe( describe('app dir - dynamic css', () => {
'app dir - dynamic css', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => {
if (skipped) {
return
}
it('should preload css of dynamic component during SSR', async () => { it('should preload css of dynamic component during SSR', async () => {
const $ = await next.render$('/ssr') const $ = await next.render$('/ssr')
const cssLinks = $('link[rel="stylesheet"]') const cssLinks = $('link[rel="stylesheet"]')
@ -69,5 +72,4 @@ createNextDescribe(
const output = next.cliOutput const output = next.cliOutput
expect(output).not.toContain('was called outside a request scope') expect(output).not.toContain('was called outside a request scope')
}) })
} })
)

View file

@ -1,16 +1,19 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { getRedboxHeader, hasRedbox } from 'next-test-utils' import { getRedboxHeader, hasRedbox } from 'next-test-utils'
process.env.__TEST_SENTINEL = 'build' process.env.__TEST_SENTINEL = 'build'
createNextDescribe( describe('dynamic-data', () => {
'dynamic-data', const { next, isNextDev, skipped } = nextTestSetup({
{
files: __dirname + '/fixtures/main', files: __dirname + '/fixtures/main',
skipStart: true, skipStart: true,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextDev }) => {
if (skipped) {
return
}
beforeAll(async () => { beforeAll(async () => {
await next.start() await next.start()
// This will update the __TEST_SENTINEL value to "run" // This will update the __TEST_SENTINEL value to "run"
@ -170,16 +173,18 @@ createNextDescribe(
) )
}) })
} }
} })
)
createNextDescribe( describe('dynamic-data with dynamic = "error"', () => {
'dynamic-data with dynamic = "error"', const { next, isNextDev, isNextDeploy, skipped } = nextTestSetup({
{
files: __dirname + '/fixtures/require-static', files: __dirname + '/fixtures/require-static',
skipStart: true, skipStart: true,
}, })
({ next, isNextDev, isNextDeploy }) => {
if (skipped) {
return
}
if (isNextDeploy) { if (isNextDeploy) {
it.skip('should not run in next deploy.', () => {}) it.skip('should not run in next deploy.', () => {})
return return
@ -246,16 +251,18 @@ createNextDescribe(
) )
}) })
} }
} })
)
createNextDescribe( describe('dynamic-data inside cache scope', () => {
'dynamic-data inside cache scope', const { next, isNextDev, isNextDeploy, skipped } = nextTestSetup({
{
files: __dirname + '/fixtures/cache-scoped', files: __dirname + '/fixtures/cache-scoped',
skipStart: true, skipStart: true,
}, })
({ next, isNextDev, isNextDeploy }) => {
if (skipped) {
return
}
if (isNextDeploy) { if (isNextDeploy) {
it.skip('should not run in next deploy..', () => {}) it.skip('should not run in next deploy..', () => {})
return return
@ -302,5 +309,4 @@ createNextDescribe(
) )
}) })
} }
} })
)

View file

@ -1,13 +1,20 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { getRedboxDescription, hasRedbox } from 'next-test-utils' import { getRedboxDescription, hasRedbox } from 'next-test-utils'
createNextDescribe( describe('dynamic-href', () => {
'dynamic-href', const {
{ isNextDev: isDev,
next,
skipped,
} = nextTestSetup({
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ isNextDev: isDev, next }) => {
if (skipped) {
return
}
if (isDev) { if (isDev) {
it('should error when using dynamic href.pathname in app dir', async () => { it('should error when using dynamic href.pathname in app dir', async () => {
const browser = await next.browser('/object') const browser = await next.browser('/object')
@ -27,9 +34,7 @@ createNextDescribe(
"pathname: '/object/slug'" "pathname: '/object/slug'"
) )
) )
expect(await browser.waitForElementByCss('#link').text()).toBe( expect(await browser.waitForElementByCss('#link').text()).toBe('to slug')
'to slug'
)
// Navigate to new page // Navigate to new page
await browser.elementByCss('#link').click() await browser.elementByCss('#link').click()
@ -58,5 +63,4 @@ createNextDescribe(
expect(await browser.elementByCss('#link').text()).toBe('to slug') expect(await browser.elementByCss('#link').text()).toBe('to slug')
}) })
} }
} })
)

View file

@ -1,16 +1,15 @@
import { type NextInstance, createNextDescribe } from 'e2e-utils' import { type NextInstance, nextTestSetup } from 'e2e-utils'
async function getLastModifiedTime(next: NextInstance, pathname: string) { async function getLastModifiedTime(next: NextInstance, pathname: string) {
const content = await (await next.fetch(pathname)).text() const content = await (await next.fetch(pathname)).text()
return content.match(/<lastmod>([^<]+)<\/lastmod>/)[1] return content.match(/<lastmod>([^<]+)<\/lastmod>/)[1]
} }
createNextDescribe( describe('app-dir - dynamic in generate params', () => {
'app-dir - dynamic in generate params', const { next, isNextDev } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next, isNextDev }) => {
it('should render sitemap with generateSitemaps in force-dynamic config dynamically', async () => { it('should render sitemap with generateSitemaps in force-dynamic config dynamically', async () => {
const firstTime = await getLastModifiedTime( const firstTime = await getLastModifiedTime(
next, next,
@ -26,12 +25,10 @@ createNextDescribe(
it('should be able to call while generating multiple dynamic sitemaps', async () => { it('should be able to call while generating multiple dynamic sitemaps', async () => {
expect( expect(
(await next.fetch(isNextDev ? 'sitemap.xml/0' : '/sitemap/0.xml')) (await next.fetch(isNextDev ? 'sitemap.xml/0' : '/sitemap/0.xml')).status
.status
).toBe(200) ).toBe(200)
expect( expect(
(await next.fetch(isNextDev ? 'sitemap.xml/1' : '/sitemap/1.xml')) (await next.fetch(isNextDev ? 'sitemap.xml/1' : '/sitemap/1.xml')).status
.status
).toBe(200) ).toBe(200)
}) })
@ -39,5 +36,4 @@ createNextDescribe(
expect((await next.fetch('/dynamic/0')).status).toBe(200) expect((await next.fetch('/dynamic/0')).status).toBe(200)
expect((await next.fetch('/dynamic/1')).status).toBe(200) expect((await next.fetch('/dynamic/1')).status).toBe(200)
}) })
} })
)

View file

@ -1,20 +1,23 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app dir - next/dynamic', () => {
'app dir - next/dynamic', const { next, isNextStart, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextStart }) => {
if (skipped) {
return
}
it('should handle ssr: false in pages when appDir is enabled', async () => { it('should handle ssr: false in pages when appDir is enabled', async () => {
const $ = await next.render$('/legacy/no-ssr') const $ = await next.render$('/legacy/no-ssr')
expect($.html()).not.toContain('navigator') expect($.html()).not.toContain('navigator')
const browser = await next.browser('/legacy/no-ssr') const browser = await next.browser('/legacy/no-ssr')
expect( expect(await browser.waitForElementByCss('#pure-client').text()).toContain(
await browser.waitForElementByCss('#pure-client').text() 'navigator'
).toContain('navigator') )
}) })
it('should handle next/dynamic in SSR correctly', async () => { it('should handle next/dynamic in SSR correctly', async () => {
@ -28,13 +31,9 @@ createNextDescribe(
expect(serverContent).toContain('next-dynamic dynamic on server') expect(serverContent).toContain('next-dynamic dynamic on server')
expect(serverContent).toContain('next-dynamic dynamic on client') expect(serverContent).toContain('next-dynamic dynamic on client')
expect(serverContent).toContain('next-dynamic server import client') expect(serverContent).toContain('next-dynamic server import client')
expect(serverContent).not.toContain( expect(serverContent).not.toContain('next-dynamic dynamic no ssr on client')
'next-dynamic dynamic no ssr on client'
)
expect(serverContent).not.toContain( expect(serverContent).not.toContain('next-dynamic dynamic no ssr on server')
'next-dynamic dynamic no ssr on server'
)
// client component under server component with ssr: false will not be rendered either in flight or SSR // client component under server component with ssr: false will not be rendered either in flight or SSR
expect($.html()).not.toContain('client component under sever no ssr') expect($.html()).not.toContain('client component under sever no ssr')
@ -69,9 +68,7 @@ createNextDescribe(
'ssr-false-client-module-text' 'ssr-false-client-module-text'
) )
// noSSR should not show up in browser // noSSR should not show up in browser
const browser = await next.browser( const browser = await next.browser('/dynamic-mixed-ssr-false/client-edge')
'/dynamic-mixed-ssr-false/client-edge'
)
expect( expect(
await browser.elementByCss('#ssr-false-server-module').text() await browser.elementByCss('#ssr-false-server-module').text()
).toBe('ssr-false-server-module-text') ).toBe('ssr-false-server-module-text')
@ -122,5 +119,4 @@ createNextDescribe(
expect($('#client-button').text()).toBe('this is a client button') expect($('#client-button').text()).toBe('this is a client button')
}) })
}) })
} })
)

View file

@ -1,11 +1,10 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('edge-route-catchall', () => {
'edge-route-catchall', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should correctly normalize edge route catch-all with a single param', async () => { it('should correctly normalize edge route catch-all with a single param', async () => {
const result = await next.fetch('/edge/one') const result = await next.fetch('/edge/one')
@ -19,5 +18,4 @@ createNextDescribe(
JSON.stringify({ slug: ['one', 'two', 'three'] }) JSON.stringify({ slug: ['one', 'two', 'three'] })
) )
}) })
} })
)

View file

@ -1,11 +1,10 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('edge-route-rewrite', () => {
'edge-route-rewrite', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('it should support a rewrite to an edge route', async () => { it('it should support a rewrite to an edge route', async () => {
const result = await next.render('/one/example') const result = await next.render('/one/example')
expect(result).toContain('Hello from /app/two/example/route.ts') expect(result).toContain('Hello from /app/two/example/route.ts')
@ -17,5 +16,4 @@ createNextDescribe(
'Hello from /app/dynamic/[slug]/route.ts. Slug: foo' 'Hello from /app/dynamic/[slug]/route.ts. Slug: foo'
) )
}) })
} })
)

View file

@ -1,11 +1,10 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('edge runtime node compatibility', () => {
'edge runtime node compatibility', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('[app] supports node:buffer', async () => { it('[app] supports node:buffer', async () => {
const res = await next.fetch('/buffer', { const res = await next.fetch('/buffer', {
method: 'POST', method: 'POST',
@ -47,5 +46,4 @@ createNextDescribe(
]), ]),
}) })
}) })
} })
)

View file

@ -1,17 +1,20 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('app dir - emotion-js', () => {
'app dir - emotion-js', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
dependencies: { dependencies: {
'@emotion/react': 'latest', '@emotion/react': 'latest',
'@emotion/cache': 'latest', '@emotion/cache': 'latest',
}, },
}, })
({ next }) => {
if (skipped) {
return
}
it('should render emotion-js css with compiler.emotion option correctly', async () => { it('should render emotion-js css with compiler.emotion option correctly', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
const el = browser.elementByCss('h1') const el = browser.elementByCss('h1')
@ -24,5 +27,4 @@ createNextDescribe(
'rgb(0, 0, 255)' 'rgb(0, 0, 255)'
) )
}) })
} })
)

View file

@ -1,4 +1,4 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
export function runTest({ next }) { export function runTest({ next }) {
it('should allow navigation on not-found', async () => { it('should allow navigation on not-found', async () => {
@ -125,12 +125,10 @@ export function runTest({ next }) {
}) })
} }
createNextDescribe( describe('app dir - not found navigation', () => {
'app dir - not found navigation', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
runTest({ next }) runTest({ next })
} })
)

View file

@ -1,13 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { runTest } from './index.test' import { runTest } from './index.test'
createNextDescribe( describe('app dir - not found navigation - with overridden node env', () => {
'app dir - not found navigation - with overridden node env', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
env: { NODE_ENV: 'test' }, env: { NODE_ENV: 'test' },
}, })
({ next }) => {
runTest({ next }) runTest({ next })
} })
)

View file

@ -1,13 +1,16 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { getRedboxHeader, hasRedbox, retry } from 'next-test-utils' import { getRedboxHeader, hasRedbox, retry } from 'next-test-utils'
createNextDescribe( describe('app-dir - errors', () => {
'app-dir - errors', const { next, isNextDev, isNextStart, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextDev, isNextStart }) => {
if (skipped) {
return
}
describe('error component', () => { describe('error component', () => {
it('should trigger error component when an error happens during rendering', async () => { it('should trigger error component when an error happens during rendering', async () => {
const browser = await next.browser('/client-component') const browser = await next.browser('/client-component')
@ -172,5 +175,4 @@ createNextDescribe(
}) })
} }
}) })
} })
)

View file

@ -1,20 +1,15 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app dir - front redirect issue', () => {
'app dir - front redirect issue', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should redirect', async () => { it('should redirect', async () => {
const browser = await next.browser('/vercel-user') const browser = await next.browser('/vercel-user')
expect( expect(
await browser await browser.waitForElementByCss('#home-page').elementByCss('h1').text()
.waitForElementByCss('#home-page')
.elementByCss('h1')
.text()
).toBe('Hello!') ).toBe('Hello!')
expect(await browser.url()).toBe(`${next.url}/vercel-user`) expect(await browser.url()).toBe(`${next.url}/vercel-user`)
}) })
} })
)

View file

@ -1,17 +1,16 @@
import { getRedboxHeader, hasRedbox } from 'next-test-utils' import { getRedboxHeader, hasRedbox } from 'next-test-utils'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
async function testDev(browser, errorRegex) { async function testDev(browser, errorRegex) {
expect(await hasRedbox(browser)).toBe(true) expect(await hasRedbox(browser)).toBe(true)
expect(await getRedboxHeader(browser)).toMatch(errorRegex) expect(await getRedboxHeader(browser)).toMatch(errorRegex)
} }
createNextDescribe( describe('app dir - global error', () => {
'app dir - global error', const { next, isNextDev } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next, isNextDev }) => {
it('should trigger error component when an error happens during rendering', async () => { it('should trigger error component when an error happens during rendering', async () => {
const browser = await next.browser('/client') const browser = await next.browser('/client')
await browser await browser
@ -91,5 +90,4 @@ createNextDescribe(
) )
} }
}) })
} })
)

View file

@ -1,20 +1,21 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app dir - global error - with catch-all route', () => {
'app dir - global error - with catch-all route', const { next, isNextStart, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextStart }) => {
if (skipped) {
return
}
it('should render catch-all route correctly', async () => { it('should render catch-all route correctly', async () => {
expect(await next.render('/en/foo')).toContain('catch-all page') expect(await next.render('/en/foo')).toContain('catch-all page')
}) })
it('should render 404 page correctly', async () => { it('should render 404 page correctly', async () => {
expect(await next.render('/en')).toContain( expect(await next.render('/en')).toContain('This page could not be found.')
'This page could not be found.'
)
}) })
if (isNextStart) { if (isNextStart) {
@ -25,5 +26,4 @@ createNextDescribe(
expect(text).toBe('global-error') expect(text).toBe('global-error')
}) })
} }
} })
)

View file

@ -1,18 +1,21 @@
import { getRedboxHeader, hasRedbox } from 'next-test-utils' import { getRedboxHeader, hasRedbox } from 'next-test-utils'
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
async function testDev(browser, errorRegex) { async function testDev(browser, errorRegex) {
expect(await hasRedbox(browser)).toBe(true) expect(await hasRedbox(browser)).toBe(true)
expect(await getRedboxHeader(browser)).toMatch(errorRegex) expect(await getRedboxHeader(browser)).toMatch(errorRegex)
} }
createNextDescribe( describe('app dir - global error - layout error', () => {
'app dir - global error - layout error', const { next, isNextDev, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
skipDeployment: true, skipDeployment: true,
}, })
({ next, isNextDev }) => {
if (skipped) {
return
}
it('should render global error for error in server components', async () => { it('should render global error for error in server components', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
@ -26,5 +29,4 @@ createNextDescribe(
expect(await browser.elementByCss('#digest').text()).toMatch(/\w+/) expect(await browser.elementByCss('#digest').text()).toMatch(/\w+/)
} }
}) })
} })
)

View file

@ -1,15 +1,14 @@
import { createNextDescribe } from '../../../lib/e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { outdent } from 'outdent' import { outdent } from 'outdent'
createNextDescribe( describe('headers-static-bailout', () => {
'headers-static-bailout', const { next, isNextStart } = nextTestSetup({
{
files: __dirname, files: __dirname,
dependencies: { dependencies: {
nanoid: '4.0.1', nanoid: '4.0.1',
}, },
}, })
({ next, isNextStart }) => {
if (!isNextStart) { if (!isNextStart) {
it('should skip', () => {}) it('should skip', () => {})
return return
@ -67,5 +66,4 @@ createNextDescribe(
'https://nextjs.org/docs/messages/dynamic-server-error' 'https://nextjs.org/docs/messages/dynamic-server-error'
) )
}) })
} })
)

View file

@ -1,11 +1,10 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('hello-world', () => {
'hello-world', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
// Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API. // Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API.
it('should work using cheerio', async () => { it('should work using cheerio', async () => {
const $ = await next.render$('/') const $ = await next.render$('/')
@ -30,5 +29,4 @@ createNextDescribe(
const html = await res.text() const html = await res.text()
expect(html).toContain('hello world') expect(html).toContain('hello world')
}) })
} })
)

View file

@ -1,11 +1,10 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app dir - hooks', () => {
'app dir - hooks', const { next, isNextDeploy } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next, isNextDeploy }) => {
describe('from pages', () => { describe('from pages', () => {
it.each([ it.each([
{ pathname: '/adapter-hooks/static' }, { pathname: '/adapter-hooks/static' },
@ -182,5 +181,4 @@ createNextDescribe(
expect(JSON.parse($('#page-layout-segment').text())).toEqual(null) expect(JSON.parse($('#page-layout-segment').text())).toEqual(null)
}) })
}) })
} })
)

View file

@ -1,7 +1,7 @@
// @ts-check // @ts-check
// @ts-ignore // @ts-ignore
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import cheerio from 'cheerio' import cheerio from 'cheerio'
const { i18n } = require('./next.config') const { i18n } = require('./next.config')
@ -47,12 +47,11 @@ const urls = [
})), })),
] ]
createNextDescribe( describe('i18n-hybrid', () => {
'i18n-hybrid', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it.each(urls.filter((url) => !url.expected))( it.each(urls.filter((url) => !url.expected))(
'does not resolve $pathname', 'does not resolve $pathname',
async (url) => { async (url) => {
@ -78,5 +77,4 @@ createNextDescribe(
expect(debug).toEqual(url.expected) expect(debug).toEqual(url.expected)
} }
) )
} })
)

View file

@ -1,16 +1,14 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
createNextDescribe( describe('app dir - imports', () => {
'app dir - imports', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
;['js', 'jsx', 'ts', 'tsx'].forEach((ext) => { ;['js', 'jsx', 'ts', 'tsx'].forEach((ext) => {
it(`we can import all components from .${ext}`, async () => { it(`we can import all components from .${ext}`, async () => {
const $ = await next.render$(`/${ext}`) const $ = await next.render$(`/${ext}`)
expect($('#js').text()).toBe('CompJs') expect($('#js').text()).toBe('CompJs')
}) })
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('interception-dynamic-segment-middleware', () => {
'interception-dynamic-segment-middleware', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should work when interception route is paired with a dynamic segment & middleware', async () => { it('should work when interception route is paired with a dynamic segment & middleware', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
@ -14,10 +13,6 @@ createNextDescribe(
await check(() => browser.elementById('modal').text(), /intercepted/) await check(() => browser.elementById('modal').text(), /intercepted/)
await browser.refresh() await browser.refresh()
await check(() => browser.elementById('modal').text(), '') await check(() => browser.elementById('modal').text(), '')
await check( await check(() => browser.elementById('children').text(), /not intercepted/)
() => browser.elementById('children').text(),
/not intercepted/
)
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('interception-dynamic-segment', () => {
'interception-dynamic-segment', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should work when interception route is paired with a dynamic segment', async () => { it('should work when interception route is paired with a dynamic segment', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
@ -14,10 +13,6 @@ createNextDescribe(
await check(() => browser.elementById('modal').text(), /intercepted/) await check(() => browser.elementById('modal').text(), /intercepted/)
await browser.refresh() await browser.refresh()
await check(() => browser.elementById('modal').text(), '') await check(() => browser.elementById('modal').text(), '')
await check( await check(() => browser.elementById('children').text(), /not intercepted/)
() => browser.elementById('children').text(),
/not intercepted/
)
}) })
} })
)

View file

@ -1,14 +1,17 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('interception-middleware-rewrite', () => {
'interception-middleware-rewrite', const { next, skipped } = nextTestSetup({
{
files: __dirname, files: __dirname,
// TODO: remove after deployment handling is updated // TODO: remove after deployment handling is updated
skipDeployment: true, skipDeployment: true,
}, })
({ next }) => {
if (skipped) {
return
}
it('should support intercepting routes with a middleware rewrite', async () => { it('should support intercepting routes with a middleware rewrite', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
@ -86,5 +89,4 @@ createNextDescribe(
// page content should not have changed // page content should not have changed
await check(() => browser.elementById('children').text(), 'root') await check(() => browser.elementById('children').text(), 'root')
}) })
} })
)

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils' import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils' import { check } from 'next-test-utils'
createNextDescribe( describe('interception-routes-root-catchall', () => {
'interception-routes-root-catchall', const { next } = nextTestSetup({
{
files: __dirname, files: __dirname,
}, })
({ next }) => {
it('should support having a root catch-all and a catch-all in a parallel route group', async () => { it('should support having a root catch-all and a catch-all in a parallel route group', async () => {
const browser = await next.browser('/') const browser = await next.browser('/')
await browser.elementByCss('[href="/items/1"]').click() await browser.elementByCss('[href="/items/1"]').click()
@ -37,5 +36,4 @@ createNextDescribe(
/Root Catch-All Page/ /Root Catch-All Page/
) )
}) })
} })
)

Some files were not shown because too many files have changed in this diff Show more