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 { outdent } from 'outdent'
import { FileRef, createNextDescribe } from 'e2e-utils'
import { FileRef, nextTestSetup } from 'e2e-utils'
import {
check,
getRedboxDescription,
@ -10,12 +10,11 @@ import {
retry,
} from 'next-test-utils'
createNextDescribe(
'Error overlay - RSC runtime errors',
{
describe('Error overlay - RSC runtime errors', () => {
const { next } = nextTestSetup({
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 () => {
await next.patchFile(
'app/server/page.js',
@ -148,5 +147,4 @@ createNextDescribe(
// Does not contain webpack traces in file path
expect(source).not.toMatch(/webpack(-internal:)?\/\//)
})
}
)
})

View file

@ -1,14 +1,13 @@
/* eslint-env jest */
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
import { getRedboxComponentStack, hasRedbox } from 'next-test-utils'
import path from 'path'
createNextDescribe(
'Component Stack in error overlay',
{
describe('Component Stack in error overlay', () => {
const { next } = nextTestSetup({
files: path.join(__dirname, 'fixtures', 'component-stack'),
},
({ next }) => {
})
it('should show a component stack on hydration error', async () => {
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'
createNextDescribe(
'app-dir - app routes errors',
{
describe('app-dir - app routes errors', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
describe('bad lowercase exports', () => {
it.each([
['get'],
@ -36,5 +35,4 @@ createNextDescribe(
}
)
})
}
)
})

View file

@ -1,4 +1,4 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
import {
getRedboxCallStack,
hasRedbox,
@ -7,9 +7,8 @@ import {
getRedboxSource,
} from 'next-test-utils'
createNextDescribe(
'app dir - dynamic error trace',
{
describe('app dir - dynamic error trace', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
dependencies: {
swr: 'latest',
@ -25,8 +24,9 @@ createNextDescribe(
startCommand: (global as any).isNextDev ? 'pnpm dev' : 'pnpm start',
buildCommand: 'pnpm build',
skipDeployment: true,
},
({ next }) => {
})
if (skipped) return
it('should show the error trace', async () => {
const browser = await next.browser('/')
await hasRedbox(browser)
@ -38,5 +38,4 @@ createNextDescribe(
const source = await getRedboxSource(browser)
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'
createNextDescribe(
'develop - app-dir - edge errros hmr',
{
describe('develop - app-dir - edge errros hmr', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('should recover from build errors when server component error', async () => {
const browser = await next.browser('/')
const clientComponentSource = await next.readFile('app/comp.server.js')
@ -36,5 +35,4 @@ createNextDescribe(
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'
createNextDescribe(
'HMR Move File',
{
describe('HMR Move File', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('should work when moving a component to another directory', async () => {
const browser = await next.browser('/')
expect(await browser.elementByCss('#hello-world-button').text()).toBe(
@ -24,5 +23,4 @@ createNextDescribe(
'hello world'
)
})
}
)
})

View file

@ -1,11 +1,10 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
createNextDescribe(
'multiple-compiles-single-route',
{
describe('multiple-compiles-single-route', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
// 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 () => {
const logs: string[] = []
@ -16,5 +15,4 @@ createNextDescribe(
// Check if `/[slug]` is mentioned in the logs as being compiled
expect(logs.some((log) => log.includes('/[slug]'))).toBe(false)
})
}
)
})

View file

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

View file

@ -1,14 +1,13 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
import { check, waitFor } from 'next-test-utils'
const envFile = '.env.development.local'
createNextDescribe(
`app-dir-hmr`,
{
describe(`app-dir-hmr`, () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
describe('filesystem changes', () => {
it('should not continously poll when hitting a not found page', async () => {
let requestCount = 0
@ -92,5 +91,4 @@ createNextDescribe(
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'
createNextDescribe(
'app-render-error-log',
{
describe('app-render-error-log', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('should log the correct values on app-render error', async () => {
const outputIndex = next.cliOutput.length
await next.fetch('/')
@ -38,5 +36,4 @@ createNextDescribe(
expect(cliOutput).not.toInclude('webpack-internal')
})
}
)
})

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,14 +1,11 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
createNextDescribe(
'Handles Duplicate Pages',
{
describe('Handles Duplicate Pages', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('Shows warning in development', async () => {
await next.render('/hello')
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 { renderViaHTTP, shouldRunTurboDevTest } from 'next-test-utils'
createNextDescribe(
'experimental-https-server (generated certificate)',
{
describe('experimental-https-server (generated certificate)', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
startCommand: `pnpm next ${
shouldRunTurboDevTest() ? 'dev --turbo' : 'dev'
} --experimental-https`,
skipStart: !process.env.CI,
},
({ next }) => {
})
if (skipped) return
if (!process.env.CI) {
console.warn('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 })
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 { renderViaHTTP, shouldRunTurboDevTest } from 'next-test-utils'
createNextDescribe(
'experimental-https-server (provided certificate)',
{
describe('experimental-https-server (provided certificate)', () => {
const { next } = nextTestSetup({
files: __dirname,
startCommand: `pnpm next ${
shouldRunTurboDevTest() ? 'dev --turbo' : 'dev'
} --experimental-https --experimental-https-key ./certificates/localhost-key.pem --experimental-https-cert ./certificates/localhost.pem`,
},
({ next }) => {
})
const agent = new https.Agent({
rejectUnauthorized: false,
})
@ -26,5 +24,4 @@ createNextDescribe(
const html = await renderViaHTTP(next.url, '/2', undefined, { agent })
expect(html).toContain('Hello from Pages')
})
}
)
})

View file

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

View file

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

View file

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

View file

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

View file

@ -1,14 +1,12 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
import fs from 'fs-extra'
import { hasRedbox } from 'next-test-utils'
import path from 'path'
createNextDescribe(
'repeated-dev-edits',
{
describe('repeated-dev-edits', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
// Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API.
it('should not break the hydration ', async () => {
const browser = await next.browser('/')
@ -44,5 +42,4 @@ createNextDescribe(
// Verify no hydration mismatch:
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 { join } from 'path'
createNextDescribe(
'watch-config-file',
{
describe('watch-config-file', () => {
const { next } = nextTestSetup({
files: join(__dirname, 'fixture'),
},
({ next }) => {
})
it('should output config file change', async () => {
await check(async () => next.cliOutput, /ready/i)
@ -34,5 +33,4 @@ createNextDescribe(
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(
'app-dir edge runtime config',
{
describe('app-dir edge runtime config', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: __dirname,
skipStart: true,
skipDeployment: true,
},
({ next, isNextDev }) => {
})
if (skipped) {
return
}
it('should warn the legacy object config export', async () => {
let error
await next.start().catch((err) => {
@ -30,5 +33,4 @@ createNextDescribe(
'- `export const preferredRegion = ["us-east-1"]`'
)
})
}
)
})

View file

@ -1,11 +1,9 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
createNextDescribe(
'_allow-underscored-root-directory',
{
describe('_allow-underscored-root-directory', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('should not serve app path with underscore', async () => {
const res = await next.fetch('/_handlers')
expect(res.status).toBe(404)
@ -20,5 +18,4 @@ createNextDescribe(
const res = await next.fetch('/_routable-folder')
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 { join } from 'path'
createNextDescribe(
'app-dir action allowed origins',
{
describe('app-dir action allowed origins', () => {
const { next, skipped } = nextTestSetup({
files: join(__dirname, 'safe-origins'),
skipDeployment: true,
dependencies: {
@ -14,8 +13,12 @@ createNextDescribe(
},
// An arbitrary & random port.
forcedPort: '41831',
},
({ next }) => {
})
if (skipped) {
return
}
it('should pass if localhost is set as a safe origin', async function () {
const browser = await next.browser('/')
@ -25,5 +28,4 @@ createNextDescribe(
return await browser.elementByCss('#res').text()
}, 'hi')
})
}
)
})

View file

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

View file

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

View file

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

View file

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

View file

@ -1,11 +1,10 @@
/* eslint-disable jest/no-standalone-expect */
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils'
import type { Response } from 'playwright'
createNextDescribe(
'app-dir action progressive enhancement',
{
describe('app-dir action progressive enhancement', () => {
const { next } = nextTestSetup({
files: __dirname,
dependencies: {
react: 'latest',
@ -13,8 +12,8 @@ createNextDescribe(
'react-dom': 'latest',
'server-only': 'latest',
},
},
({ next }) => {
})
it('should support formData and redirect without JS', async () => {
let responseCode
const browser = await next.browser('/server', {
@ -45,14 +44,11 @@ createNextDescribe(
disableJavaScript: true,
})
await browser.eval(
`document.getElementById('client-name').value = 'test'`
)
await browser.eval(`document.getElementById('client-name').value = 'test'`)
await browser.elementByCss('#there').click()
await check(() => {
return browser.eval('window.location.pathname + window.location.search')
}, '/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 { accountForOverhead } from './account-for-overhead'
const CONFIG_ERROR =
'Server Actions Size Limit must be a valid number or filesize format larger than 1MB'
createNextDescribe(
'app-dir action size limit invalid config',
{
describe('app-dir action size limit invalid config', () => {
const { next, isNextStart, isNextDeploy, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
skipStart: true,
@ -16,8 +15,9 @@ createNextDescribe(
'react-dom': 'latest',
'server-only': 'latest',
},
},
({ next, isNextStart, isNextDeploy }) => {
})
if (skipped) return
if (!isNextStart) {
it('skip test for development mode', () => {})
return
@ -154,5 +154,4 @@ createNextDescribe(
})
})
}
}
)
})

View file

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

View file

@ -1,15 +1,18 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils'
import type { BrowserInterface } from 'next-webdriver'
createNextDescribe(
'app a11y features',
{
describe('app a11y features', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
packageJson: {},
skipDeployment: true,
},
({ next }) => {
})
if (skipped) {
return
}
describe('route announcer', () => {
async function getAnnouncerContent(browser: BrowserInterface) {
return browser.eval(
@ -40,5 +43,4 @@ createNextDescribe(
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(
'app-dir alias',
{
describe('app-dir alias', () => {
const { next, isNextStart, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next, isNextStart }) => {
})
if (skipped) {
return
}
it('should handle typescript paths alias correctly', async () => {
const html = await next.render('/button')
expect(html).toContain('click</button>')
@ -42,5 +45,4 @@ createNextDescribe(
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 { join } from 'path'
createNextDescribe(
'custom-app-server-action-redirect',
{
describe('custom-app-server-action-redirect', () => {
const { next, skipped } = nextTestSetup({
files: join(__dirname, 'custom-server'),
skipDeployment: true,
startCommand: 'node server.js',
dependencies: {
'get-port': '5.1.1',
},
},
({ next }) => {
})
if (skipped) {
return
}
it('redirects with basepath properly when server action handler uses `redirect`', async () => {
const browser = await next.browser('/base')
const getCount = async () => browser.elementByCss('#current-count').text()
@ -56,5 +59,4 @@ createNextDescribe(
/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'
createNextDescribe(
'app dir - basepath',
{
describe('app dir - basepath', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
dependencies: {
sass: 'latest',
},
},
({ next }) => {
})
if (skipped) {
return
}
it('should successfully hard navigate from pages -> app', async () => {
const browser = await next.browser('/base/pages-path')
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 { BrowserInterface } from 'next-webdriver'
import {
@ -8,12 +8,11 @@ import {
getPathname,
} from './test-utils'
createNextDescribe(
'app dir client cache semantics',
{
describe('app dir client cache semantics', () => {
const { next, isNextDev } = nextTestSetup({
files: __dirname,
},
({ next, isNextDev }) => {
})
if (isNextDev) {
// 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 () => {
@ -425,9 +424,7 @@ createNextDescribe(
).toBeFalse()
// the root layout should still be visible
expect(
await browser.hasElementByCssSelector('#root-layout')
).toBeTrue()
expect(await browser.hasElementByCssSelector('#root-layout')).toBeTrue()
// the dynamic content should eventually appear
await browser.waitForElementByCss('#random-number')
@ -475,5 +472,4 @@ createNextDescribe(
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'
createNextDescribe(
'app dir',
{
describe('app dir', () => {
const { next, isNextDev, isNextStart } = nextTestSetup({
files: __dirname,
},
({ next, isNextDev: isDev, isNextStart }) => {
})
if (isNextStart) {
describe('Loading', () => {
it('should render loading.js in initial html for slow page', async () => {
@ -16,7 +15,7 @@ createNextDescribe(
})
}
if (isDev) {
if (isNextDev) {
describe('HMR', () => {
it('should not cause error when removing loading.js', async () => {
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(
'app dir - crossOrigin config',
{
describe('app dir - crossOrigin config', () => {
const { next, isNextStart, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next, isNextStart }) => {
})
if (skipped) {
return
}
if (isNextStart) {
it('skip in start mode', () => {})
return
@ -33,5 +36,4 @@ createNextDescribe(
expect(crossOrigin).toBeUndefined()
})
})
}
)
})

View file

@ -1,8 +1,7 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
createNextDescribe(
'app dir - css with pageextensions',
{
describe('app dir - css with pageextensions', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
dependencies: {
@ -11,8 +10,12 @@ createNextDescribe(
'react-dom': 'latest',
sass: 'latest',
},
},
({ next }) => {
})
if (skipped) {
return
}
describe('css support with pageextensions', () => {
describe('page in app directory with pageextention, css should work', () => {
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'
createNextDescribe(
'app dir - css',
{
describe('app dir - css', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
dependencies: {
@ -13,8 +12,12 @@ createNextDescribe(
sass: 'latest',
'@next/mdx': 'canary',
},
},
({ next, isNextDev: isDev }) => {
})
if (skipped) {
return
}
describe('css support', () => {
describe('server layouts', () => {
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 () => {
const filePath = 'app/ordering/page.js'
const origContent = await next.readFile(filePath)
@ -475,9 +478,7 @@ createNextDescribe(
} else {
// Even if it's deduped by Float, it should still only be included once in the payload.
const matches = initialHtml.match(
/\/_next\/static\/css\/.+?\.css/g
)
const matches = initialHtml.match(/\/_next\/static\/css\/.+?\.css/g)
const counts = new Map()
for (const match of matches) {
counts.set(match, (counts.get(match) || 0) + 1)
@ -657,7 +658,7 @@ createNextDescribe(
// Pages directory shouldn't be affected when `appDir` is enabled
describe('pages dir', () => {
if (!isDev) {
if (!isNextDev) {
it('should include css modules and global css after page transition', async () => {
const browser = await next.browser('/css-modules/page1')
await browser.elementByCss('a').click()
@ -678,7 +679,7 @@ createNextDescribe(
})
describe('HMR', () => {
if (isDev) {
if (isNextDev) {
it('should support HMR for CSS imports in server components', async () => {
const filePath = 'app/css/css-page/style.css'
const origContent = await next.readFile(filePath)
@ -741,10 +742,7 @@ createNextDescribe(
const browser = await next.browser('/hmr')
await browser.eval(`window.__v = 1`)
try {
await next.patchFile(
filePath,
origContent.replace('hello!', 'hmr!')
)
await next.patchFile(filePath, origContent.replace('hello!', 'hmr!'))
await check(() => browser.elementByCss('body').text(), 'hmr!')
// Make sure it doesn't reload the page
@ -846,7 +844,7 @@ createNextDescribe(
}
})
if (isDev) {
if (isNextDev) {
describe('Suspensey CSS', () => {
it('should suspend on CSS imports if its slow on client navigation', async () => {
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 fs from 'fs'
@ -27,37 +27,40 @@ function runTests(
})
}
createNextDescribe(
'app-dir - custom-cache-handler - cjs',
{
describe('app-dir - custom-cache-handler - cjs', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
env: {
CUSTOM_CACHE_HANDLER: 'cache-handler.js',
},
},
({ next, isNextDev }) => {
runTests('cjs module exports', { next, isNextDev })
}
)
})
createNextDescribe(
'app-dir - custom-cache-handler - cjs-default-export',
{
if (skipped) {
return
}
runTests('cjs module exports', { next, isNextDev })
})
describe('app-dir - custom-cache-handler - cjs-default-export', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
env: {
CUSTOM_CACHE_HANDLER: 'cache-handler-cjs-default-export.js',
},
},
({ next, isNextDev }) => {
runTests('cjs default export', { next, isNextDev })
}
)
})
createNextDescribe(
'app-dir - custom-cache-handler - esm',
{
if (skipped) {
return
}
runTests('cjs default export', { next, isNextDev })
})
describe('app-dir - custom-cache-handler - esm', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: {
app: new FileRef(__dirname + '/app'),
'cache-handler-esm.js': new FileRef(__dirname + '/cache-handler-esm.js'),
@ -73,8 +76,11 @@ createNextDescribe(
env: {
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(
'app-dir edge runtime root layout',
{
describe('app-dir edge runtime root layout', () => {
const { next, isNextStart, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next, isNextStart }) => {
})
if (skipped) {
return
}
it('should not emit metadata files into bad paths', async () => {
await next.fetch('/favicon.ico')
// issue: If metadata files are not filter out properly with image-loader,
@ -25,5 +28,4 @@ createNextDescribe(
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'
createNextDescribe(
'app-dir edge SSR',
{
describe('app-dir edge SSR', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next }) => {
})
if (skipped) {
return
}
it('should handle edge only routes', async () => {
const appHtml = await next.render('/edge/basic')
expect(appHtml).toContain('<p>Edge!</p>')
@ -56,9 +59,9 @@ createNextDescribe(
logs.push(log)
})
await next.render('/app-edge')
expect(
logs.some((log) => log.includes(`Attempted import error:`))
).toBe(false)
expect(logs.some((log) => log.includes(`Attempted import error:`))).toBe(
false
)
})
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(
'app-dir - esm js extension',
{
describe('app-dir - esm js extension', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('should be able to render nextjs api in app router', async () => {
const $ = await next.render$('/app')
@ -41,5 +40,4 @@ createNextDescribe(
expect(res.status).toBe(200)
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'
async function resolveStreamResponse(response: any, onData?: any) {
@ -15,9 +15,8 @@ async function resolveStreamResponse(response: any, onData?: any) {
return result
}
createNextDescribe(
'app dir - external dependency',
{
describe('app dir - external dependency', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
dependencies: {
swr: 'latest',
@ -34,8 +33,12 @@ createNextDescribe(
startCommand: (global as any).isNextDev ? 'pnpm dev' : 'pnpm start',
buildCommand: 'pnpm build',
skipDeployment: true,
},
({ next }) => {
})
if (skipped) {
return
}
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) => {
const result = await resolveStreamResponse(response)
@ -156,9 +159,7 @@ createNextDescribe(
async () => {
const browser = await next.browser('/browser')
// eslint-disable-next-line jest/no-standalone-expect
expect(await browser.elementByCss('#worker-state').text()).toBe(
'default'
)
expect(await browser.elementByCss('#worker-state').text()).toBe('default')
await browser.elementByCss('button').click()
@ -180,9 +181,7 @@ createNextDescribe(
expect(v1).toBe(v2)
// Should work with both esm and cjs imports
expect(html).toContain(
'CJS-ESM Compat package: cjs-esm-compat/index.mjs'
)
expect(html).toContain('CJS-ESM Compat package: cjs-esm-compat/index.mjs')
expect(html).toContain('CJS package: cjs-lib')
expect(html).toContain(
'Nested imports: nested-import:esm:cjs-esm-compat/index.mjs'
@ -197,9 +196,7 @@ createNextDescribe(
expect(v1).toBe(v2)
// Should work with both esm and cjs imports
expect(html).toContain(
'CJS-ESM Compat package: cjs-esm-compat/index.mjs'
)
expect(html).toContain('CJS-ESM Compat package: cjs-esm-compat/index.mjs')
expect(html).toContain('CJS package: cjs-lib')
})
@ -211,9 +208,7 @@ createNextDescribe(
expect(v1).toBe(v2)
// Should work with both esm and cjs imports
expect(html).toContain(
'CJS-ESM Compat package: cjs-esm-compat/index.mjs'
)
expect(html).toContain('CJS-ESM Compat package: cjs-esm-compat/index.mjs')
expect(html).toContain('CJS package: cjs-lib')
})
@ -317,5 +312,4 @@ createNextDescribe(
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'
createNextDescribe(
'app-invalid-revalidate',
{
describe('app-invalid-revalidate', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: __dirname,
skipStart: true,
skipDeployment: true,
},
({ next, isNextDev }) => {
})
if (skipped) {
return
}
it('should error properly for invalid revalidate at layout', async () => {
await next.stop().catch(() => {})
const origText = await next.readFile('app/layout.tsx')
@ -96,5 +99,4 @@ createNextDescribe(
await next.patchFile('app/page.tsx', origText)
}
})
}
)
})

View file

@ -2,16 +2,19 @@
import path from 'path'
import cheerio from 'cheerio'
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'
createNextDescribe(
'app-dir with middleware',
{
describe('app-dir with middleware', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next }) => {
})
if (skipped) {
return
}
it('should filter correctly after middleware rewrite', async () => {
const browser = await next.browser('/start')
@ -80,12 +83,8 @@ createNextDescribe(
expect(
res.headers.get('x-middleware-request-x-from-middleware')
).toBeNull()
expect(
res.headers.get('x-middleware-request-x-from-client1')
).toBeNull()
expect(
res.headers.get('x-middleware-request-x-from-client2')
).toBeNull()
expect(res.headers.get('x-middleware-request-x-from-client1')).toBeNull()
expect(res.headers.get('x-middleware-request-x-from-client2')).toBeNull()
})
it(`Updates headers`, async () => {
@ -114,15 +113,9 @@ createNextDescribe(
expect(
res.headers.get('x-middleware-request-x-from-middleware')
).toBeNull()
expect(
res.headers.get('x-middleware-request-x-from-client1')
).toBeNull()
expect(
res.headers.get('x-middleware-request-x-from-client2')
).toBeNull()
expect(
res.headers.get('x-middleware-request-x-from-client3')
).toBeNull()
expect(res.headers.get('x-middleware-request-x-from-client1')).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 () => {
@ -160,21 +153,17 @@ createNextDescribe(
await browser.elementByCss('[href="/rsc-cookies-delete"]').click()
await retry(async () => {
// only the first cookie should be deleted
expect(await browser.elementById('rsc-cookie-1').text()).toBe(
'Cookie 1:'
)
expect(await browser.elementById('rsc-cookie-1').text()).toBe('Cookie 1:')
expect(await browser.elementById('rsc-cookie-2').text()).toMatch(
/Cookie 2: \d+\.\d+/
)
})
})
}
)
})
createNextDescribe(
'app dir - middleware without pages dir',
{
describe('app dir - middleware without pages dir', () => {
const { next, skipped } = nextTestSetup({
files: {
app: new FileRef(path.join(__dirname, 'app')),
'next.config.js': new FileRef(path.join(__dirname, 'next.config.js')),
@ -191,20 +180,22 @@ createNextDescribe(
`,
},
skipDeployment: true,
},
({ next }) => {
})
if (skipped) {
return
}
// eslint-disable-next-line jest/no-identical-title
it('Updates headers', async () => {
const html = await next.render('/headers')
expect(html).toContain('redirected')
})
}
)
})
createNextDescribe(
'app dir - middleware with middleware in src dir',
{
describe('app dir - middleware with middleware in src dir', () => {
const { next, skipped } = nextTestSetup({
files: {
'src/app': new FileRef(path.join(__dirname, 'app')),
'next.config.js': new FileRef(path.join(__dirname, 'next.config.js')),
@ -219,8 +210,12 @@ createNextDescribe(
`,
},
skipDeployment: true,
},
({ next }) => {
})
if (skipped) {
return
}
it('works without crashing when using requestAsyncStorage', async () => {
const browser = await next.browser('/')
await browser.addCookie({
@ -233,5 +228,4 @@ createNextDescribe(
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'
createNextDescribe(
'app-prefetch-false-loading',
{
describe('app-prefetch-false-loading', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('should render loading for the initial render', async () => {
const $ = await next.render$('/en/testing')
@ -16,9 +15,7 @@ createNextDescribe(
const logStartIndex = next.cliOutput.length
const browser = await next.browser('/en/testing')
let initialRandomNumber = await browser
.elementById('random-number')
.text()
let initialRandomNumber = await browser.elementById('random-number').text()
await browser.elementByCss('[href="/en/testing/test"]').click()
expect(await browser.hasElementByCssSelector('#loading')).toBeFalsy()
@ -39,5 +36,4 @@ createNextDescribe(
return logOccurrences
}, 1)
})
}
)
})

View file

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

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
import { waitFor } from 'next-test-utils'
createNextDescribe(
'app-prefetch-static',
{
describe('app-prefetch-static', () => {
const { next, isNextDev } = nextTestSetup({
files: __dirname,
},
({ next, isNextDev }) => {
})
if (isNextDev) {
it('should skip next dev', () => {})
return
@ -35,5 +34,4 @@ createNextDescribe(
'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 { NEXT_RSC_UNION_QUERY } from 'next/dist/client/components/app-router-headers'
@ -27,13 +27,16 @@ const browserConfigWithFixedTime = {
},
}
createNextDescribe(
'app dir - prefetching',
{
describe('app dir - prefetching', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: __dirname,
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)
if (isNextDev) {
it('should skip next dev for now', () => {})
@ -214,8 +217,7 @@ createNextDescribe(
expect(
requests.filter(
(request) =>
request === '/static-page' ||
request.includes(NEXT_RSC_UNION_QUERY)
request === '/static-page' || request.includes(NEXT_RSC_UNION_QUERY)
).length
).toBe(0)
}
@ -359,9 +361,7 @@ createNextDescribe(
() => browser.elementById('search-params-data').text(),
/{"foo":"true"}/
)
await browser
.elementByCss(`[href="${basePath}/search-params"]`)
.click()
await browser.elementByCss(`[href="${basePath}/search-params"]`).click()
await check(
() => browser.elementById('search-params-data').text(),
/{}/
@ -385,9 +385,7 @@ createNextDescribe(
.click()
// navigating back to the route group page shouldn't trigger any data fetch
await browser
.elementByCss("[href='/prefetch-auto-route-groups']")
.click()
await browser.elementByCss("[href='/prefetch-auto-route-groups']").click()
// 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')
@ -398,9 +396,7 @@ createNextDescribe(
.click()
// finally, going back to the route group page shouldn't trigger any data fetch
await browser
.elementByCss("[href='/prefetch-auto-route-groups']")
.click()
await browser.elementByCss("[href='/prefetch-auto-route-groups']").click()
// 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')
@ -411,5 +407,4 @@ createNextDescribe(
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 cheerio from 'cheerio'
createNextDescribe(
'app dir rendering',
{
describe('app dir rendering', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next, isNextDev: isDev }) => {
})
if (skipped) {
return
}
it('should serve app/page.server.js at /', async () => {
const html = await next.render('/')
expect(html).toContain('app/page.server.js')
@ -42,7 +45,7 @@ createNextDescribe(
})
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 () => {
// const startTime = Date.now()
const $ = await next.render$('/static-only/slow')
@ -125,5 +128,4 @@ createNextDescribe(
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 ?? ''
createNextDescribe(
'app-routes-subrequests',
{
describe('app-routes-subrequests', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next }) => {
})
if (skipped) {
return
}
it('shortcuts after 5 subrequests', async () => {
expect(JSON.parse(await next.render(bathPath + '/'))).toEqual({
count: 5,
})
})
}
)
})

View file

@ -1,11 +1,10 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
createNextDescribe(
'app-routes-trailing-slash',
{
describe('app-routes-trailing-slash', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it.each(['edge', 'node'])(
'should handle trailing slash for %s 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 { Readable } from 'stream'
@ -10,12 +10,11 @@ import {
const basePath = process.env.BASE_PATH ?? ''
createNextDescribe(
'app-custom-routes',
{
describe('app-custom-routes', () => {
const { next, isNextDeploy, isNextDev, isNextStart } = nextTestSetup({
files: __dirname,
},
({ next, isNextDeploy, isNextDev, isNextStart }) => {
})
describe('works with api prefix correctly', () => {
it('statically generates correctly with no dynamic usage', async () => {
if (isNextStart) {
@ -46,9 +45,7 @@ createNextDescribe(
.catch(() => '')
).toBeFalsy()
}
expect(
JSON.parse(await next.render(basePath + '/api/dynamic'))
).toEqual({
expect(JSON.parse(await next.render(basePath + '/api/dynamic'))).toEqual({
pathname: '/api/dynamic',
query: {},
})
@ -90,9 +87,7 @@ createNextDescribe(
})
await check(async () => {
expect(data).not.toEqual(
JSON.parse(await next.render(basePath + path))
)
expect(data).not.toEqual(JSON.parse(await next.render(basePath + path)))
return 'success'
}, 'success')
@ -269,13 +264,10 @@ createNextDescribe(
},
})
const res = await next.fetch(
basePath + '/edge/advanced/body/streaming',
{
const res = await next.fetch(basePath + '/edge/advanced/body/streaming', {
method: 'POST',
body: stream,
}
)
})
expect(res.status).toEqual(200)
expect(await res.text()).toEqual(body.join('\n') + '\n')
@ -706,5 +698,4 @@ createNextDescribe(
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 ?? ''
createNextDescribe(
'app-simple-routes',
{
describe('app-simple-routes', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
describe('works with simple routes', () => {
it('renders a node route', async () => {
expect(
@ -24,5 +23,4 @@ createNextDescribe(
})
})
})
}
)
})

View file

@ -2,7 +2,7 @@ import globOrig from 'glob'
import cheerio from 'cheerio'
import { promisify } from 'util'
import { join } from 'path'
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
import {
check,
fetchViaHTTP,
@ -14,9 +14,8 @@ import stripAnsi from 'strip-ansi'
const glob = promisify(globOrig)
createNextDescribe(
'app-dir static/dynamic handling',
{
describe('app-dir static/dynamic handling', () => {
const { next, isNextDev, isNextStart, isNextDeploy } = nextTestSetup({
files: __dirname,
env: {
NEXT_DEBUG_BUILD: '1',
@ -26,8 +25,8 @@ createNextDescribe(
}
: {}),
},
},
({ next, isNextDev: isDev, isNextStart, isNextDeploy }) => {
})
let prerenderManifest
let buildCliOutputIndex = 0
@ -115,15 +114,11 @@ createNextDescribe(
'.next/server/app/variable-revalidate/revalidate-360-isr.meta'
)
)
expect(meta.headers['x-next-cache-tags']).toContain(
'unstable_cache_tag1'
)
expect(meta.headers['x-next-cache-tags']).toContain('unstable_cache_tag1')
})
it('should infer a fetchCache of force-no-store when force-dynamic is used', async () => {
const $ = await next.render$(
'/force-dynamic-fetch-cache/no-fetch-cache'
)
const $ = await next.render$('/force-dynamic-fetch-cache/no-fetch-cache')
const initData = $('#data').text()
await retry(async () => {
const $2 = await next.render$(
@ -262,7 +257,7 @@ createNextDescribe(
}
})
if (isDev) {
if (isNextDev) {
it('should error correctly for invalid params from generateStaticParams', async () => {
await next.patchFile(
'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 () => {
// wait for the revalidation period
let res = await next.fetch('/route-handler/no-store-force-static')
@ -352,9 +347,7 @@ createNextDescribe(
])(
'it should revalidate tag correctly with $type',
async ({ revalidateApi }) => {
const initRes = await next.fetch(
'/variable-revalidate/revalidate-360'
)
const initRes = await next.fetch('/variable-revalidate/revalidate-360')
const html = await initRes.text()
const $ = cheerio.load(html)
const initLayoutData = $('#layout-data').text()
@ -380,9 +373,7 @@ createNextDescribe(
)
expect((await revalidateRes.json()).revalidated).toBe(true)
const newRes = await next.fetch(
'/variable-revalidate/revalidate-360'
)
const newRes = await next.fetch('/variable-revalidate/revalidate-360')
const cacheHeader = newRes.headers.get('x-nextjs-cache')
if ((global as any).isNextStart && cacheHeader) {
@ -563,9 +554,7 @@ createNextDescribe(
// wait for a fresh revalidation
await check(async () => {
const $ = await next.render$(
'/variable-config-revalidate/revalidate-3'
)
const $ = await next.render$('/variable-config-revalidate/revalidate-3')
prevInitialDate = $('#date').text()
prevInitialRandomData = $('#random-data').text()
@ -577,9 +566,7 @@ createNextDescribe(
// the date should revalidate first after 3 seconds
// while the fetch data stays in place for 9 seconds
await check(async () => {
const $ = await next.render$(
'/variable-config-revalidate/revalidate-3'
)
const $ = await next.render$('/variable-config-revalidate/revalidate-3')
const curDate = $('#date').text()
const curRandomData = $('#random-data').text()
@ -2054,9 +2041,7 @@ createNextDescribe(
const curHtml = await curRes.text()
const cur$ = cheerio.load(curHtml)
expect(cur$('#data-no-cache').text()).toBe(
prev$('#data-no-cache').text()
)
expect(cur$('#data-no-cache').text()).toBe(prev$('#data-no-cache').text())
expect(cur$('#data-force-cache').text()).toBe(
prev$('#data-force-cache').text()
)
@ -2118,7 +2103,7 @@ createNextDescribe(
}, 'success')
})
if (isDev) {
if (isNextDev) {
it('should bypass fetch cache with cache-control: no-cache', async () => {
const res = await fetchViaHTTP(
next.url,
@ -2332,7 +2317,7 @@ createNextDescribe(
let langFetchSlug
let slugFetchSlug
if (isDev) {
if (isNextDev) {
await check(() => {
const matches = stripAnsi(next.cliOutput).match(
/partial-gen-params fetch ([\d]{1,})/
@ -2635,10 +2620,7 @@ createNextDescribe(
it('should cache correctly with utf8 encoding', async () => {
await check(async () => {
const res = await fetchViaHTTP(
next.url,
'/variable-revalidate/encoding'
)
const res = await fetchViaHTTP(next.url, '/variable-revalidate/encoding')
expect(res.status).toBe(200)
const html = await res.text()
const $ = cheerio.load(html)
@ -2650,10 +2632,7 @@ createNextDescribe(
'超鬼畜激辛ボム兵スピンジャンプ Bomb Spin Jump'
)
const res2 = await fetchViaHTTP(
next.url,
'/variable-revalidate/encoding'
)
const res2 = await fetchViaHTTP(next.url, '/variable-revalidate/encoding')
expect(res2.status).toBe(200)
const html2 = await res2.text()
const $2 = cheerio.load(html2)
@ -2697,10 +2676,7 @@ createNextDescribe(
it('should cache correctly handle JSON body', async () => {
await check(async () => {
const res = await fetchViaHTTP(
next.url,
'/variable-revalidate-edge/body'
)
const res = await fetchViaHTTP(next.url, '/variable-revalidate-edge/body')
expect(res.status).toBe(200)
const html = await res.text()
const $ = cheerio.load(html)
@ -2727,9 +2703,7 @@ createNextDescribe(
it('should not throw Dynamic Server Usage error when using generateStaticParams with draftMode', async () => {
const browserOnIndexPage = await next.browser('/ssg-draft-mode')
const content = await browserOnIndexPage
.elementByCss('#draft-mode')
.text()
const content = await browserOnIndexPage.elementByCss('#draft-mode').text()
expect(content).toBe('{"isEnabled":false}')
})
@ -2979,9 +2953,7 @@ createNextDescribe(
await browser.elementByCss('#author-2').click()
await check(async () => {
const params = JSON.parse(
await browser.elementByCss('#params').text()
)
const params = JSON.parse(await browser.elementByCss('#params').text())
return params.author === 'seb' ? 'found' : params
}, 'found')
@ -2989,9 +2961,7 @@ createNextDescribe(
await browser.elementByCss('#author-1-post-1').click()
await check(async () => {
const params = JSON.parse(
await browser.elementByCss('#params').text()
)
const params = JSON.parse(await browser.elementByCss('#params').text())
return params.author === 'tim' && params.slug === 'first-post'
? 'found'
: params
@ -3001,9 +2971,7 @@ createNextDescribe(
await browser.back()
await check(async () => {
const params = JSON.parse(
await browser.elementByCss('#params').text()
)
const params = JSON.parse(await browser.elementByCss('#params').text())
return params.author === 'seb' ? 'found' : params
}, 'found')
@ -3115,9 +3083,7 @@ createNextDescribe(
'/hooks/use-search-params/with-suspense?first=value&second=other&third'
const browser = await next.browser(url)
expect(await browser.elementByCss('#params-first').text()).toBe(
'value'
)
expect(await browser.elementByCss('#params-first').text()).toBe('value')
expect(await browser.elementByCss('#params-second').text()).toBe(
'other'
)
@ -3138,9 +3104,7 @@ createNextDescribe(
)
expect(await browser.elementByCss('#params-first').text()).toBe('N/A')
expect(await browser.elementByCss('#params-second').text()).toBe(
'N/A'
)
expect(await browser.elementByCss('#params-second').text()).toBe('N/A')
expect(await browser.elementByCss('#params-third').text()).toBe('N/A')
expect(await browser.elementByCss('#params-not-real').text()).toBe(
'N/A'
@ -3166,9 +3130,7 @@ createNextDescribe(
)
expect(await browser.elementByCss('#params-first').text()).toBe('a')
expect(await browser.elementByCss('#params-second').text()).toBe(
'b'
)
expect(await browser.elementByCss('#params-second').text()).toBe('b')
expect(await browser.elementByCss('#params-third').text()).toBe('c')
expect(await browser.elementByCss('#params-not-real').text()).toBe(
'N/A'
@ -3177,12 +3139,10 @@ createNextDescribe(
}
})
// Don't run these tests in development mode since they won't be statically generated
if (!isDev) {
if (!isNextDev) {
describe('server response', () => {
it('should bailout to client rendering - with suspense boundary', async () => {
const res = await next.fetch(
'/hooks/use-search-params/with-suspense'
)
const res = await next.fetch('/hooks/use-search-params/with-suspense')
const html = await res.text()
expect(html).toInclude('<p>search params suspense</p>')
})
@ -3355,7 +3315,7 @@ createNextDescribe(
).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 () => {
const cliOutputStart = next.cliOutput.length
const resp1 = await next.fetch('/force-cache/large-data')
@ -3373,8 +3333,7 @@ createNextDescribe(
await check(async () => {
expect(
next.cliOutput.substring(cliOutputStart).match(/Load data/g)
.length
next.cliOutput.substring(cliOutputStart).match(/Load data/g).length
).toBe(2)
expect(next.cliOutput.substring(cliOutputStart)).toContain(
'Error: Failed to set Next.js data cache, items over 2MB can not be cached'
@ -3383,7 +3342,7 @@ createNextDescribe(
}, '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 () => {
const cliOutputStart = next.cliOutput.length
const resp1 = await next.fetch('/force-cache/large-data')
@ -3401,8 +3360,7 @@ createNextDescribe(
await check(async () => {
expect(
next.cliOutput.substring(cliOutputStart).match(/Load data/g)
.length
next.cliOutput.substring(cliOutputStart).match(/Load data/g).length
).toBe(1)
return 'success'
}, 'success')
@ -3418,5 +3376,4 @@ createNextDescribe(
const browser = await next.browser('/dynamic-param-edge/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(
'app dir - validation',
{
describe('app dir - validation', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next }) => {
})
if (skipped) {
return
}
it('should error when passing invalid router state tree', async () => {
const res = await next.fetch('/', {
headers: {
@ -24,5 +27,4 @@ createNextDescribe(
})
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 cheerio from 'cheerio'
import stripAnsi from 'strip-ansi'
@ -8,9 +8,14 @@ import stripAnsi from 'strip-ansi'
// gates like this one into a single module.
const isPPREnabledByDefault = process.env.__NEXT_EXPERIMENTAL_PPR === 'true'
createNextDescribe(
'app dir - basic',
{
describe('app dir - basic', () => {
const {
next,
isNextDev: isDev,
isNextStart,
isNextDeploy,
isTurbopack,
} = nextTestSetup({
files: __dirname,
buildCommand: process.env.NEXT_EXPERIMENTAL_COMPILE
? `pnpm next build --experimental-build-mode=compile`
@ -18,8 +23,8 @@ createNextDescribe(
dependencies: {
nanoid: '4.0.1',
},
},
({ next, isNextDev: isDev, isNextStart, isNextDeploy, isTurbopack }) => {
})
if (isDev && isPPREnabledByDefault) {
it('should allow returning just skeleton in dev with query', async () => {
const res = await next.fetch('/skeleton?__nextppronly=1')
@ -52,9 +57,9 @@ createNextDescribe(
})
it('should not have entire prerender-manifest for edge', async () => {
expect(
await next.readFile('.next/prerender-manifest.js')
).not.toContain('initialRevalidate')
expect(await next.readFile('.next/prerender-manifest.js')).not.toContain(
'initialRevalidate'
)
})
if (!process.env.NEXT_EXPERIMENTAL_COMPILE) {
@ -70,19 +75,18 @@ createNextDescribe(
await next.readFile('.next/server/middleware-manifest.json')
)
expect(
middlewareManifest.functions['/(rootonly)/dashboard/hello/page']
.regions
middlewareManifest.functions['/(rootonly)/dashboard/hello/page'].regions
).toEqual(['iad1', 'sfo1'])
expect(middlewareManifest.functions['/dashboard/page'].regions).toEqual(
['iad1']
)
expect(middlewareManifest.functions['/dashboard/page'].regions).toEqual([
'iad1',
])
expect(
middlewareManifest.functions['/slow-page-no-loading/page'].regions
).toEqual(['global'])
expect(middlewareManifest.functions['/test-page/page'].regions).toEqual(
['home']
)
expect(middlewareManifest.functions['/test-page/page'].regions).toEqual([
'home',
])
// Inherits from the root layout.
expect(
@ -164,9 +168,7 @@ createNextDescribe(
requests.push(req.url())
})
await browser.eval(
'window.location.href = "/dynamic-client/first/second"'
)
await browser.eval('window.location.href = "/dynamic-client/first/second"')
await check(async () => {
return requests.some(
@ -281,9 +283,7 @@ createNextDescribe(
'.next/server/app/dashboard/deployments/[id]/page.js.nft.json'
)
) as { files: string[] }
expect(trace.files.some((file) => file.endsWith('data.json'))).toBe(
true
)
expect(trace.files.some((file) => file.endsWith('data.json'))).toBe(true)
})
}
@ -810,9 +810,7 @@ createNextDescribe(
expect(
await browser.waitForElementByCss('#app-text', 5000).text()
).toBe(
'hello from app/dynamic-pages-route-app-overlap/app-dir/page'
)
).toBe('hello from app/dynamic-pages-route-app-overlap/app-dir/page')
// When refreshing the browser, the app page should be rendered
await browser.refresh()
@ -893,9 +891,7 @@ createNextDescribe(
const $ = await next.render$('/dynamic/books/hello-world')
expect($('#dynamic-layout-params').text()).toBe('{}')
expect($('#category-layout-params').text()).toBe(
'{"category":"books"}'
)
expect($('#category-layout-params').text()).toBe('{"category":"books"}')
expect($('#id-layout-params').text()).toBe(
'{"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
// expect(await browser.elementByCss('#loading').text()).toBe('Loading...')
expect(
await browser.elementByCss('#slow-layout-message').text()
).toBe('hello from slow layout')
expect(await browser.elementByCss('#slow-layout-message').text()).toBe(
'hello from slow layout'
)
expect(await browser.elementByCss('#page-message').text()).toBe(
'Hello World'
@ -1044,9 +1040,7 @@ createNextDescribe(
})
it('should render loading.js in initial html for slow layout and page', async () => {
const $ = await next.render$(
'/slow-layout-and-page-with-loading/slow'
)
const $ = await next.render$('/slow-layout-and-page-with-loading/slow')
expect($('#loading-layout').text()).toBe('Loading layout...')
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-page').text()).toBe('Loading...')
expect(
await browser.elementByCss('#slow-layout-message').text()
).toBe('hello from slow layout')
expect(await browser.elementByCss('#slow-layout-message').text()).toBe(
'hello from slow layout'
)
expect(await browser.elementByCss('#slow-page-message').text()).toBe(
'hello from slow page'
@ -1178,9 +1172,7 @@ createNextDescribe(
const ssrInitial = await next.render('/client-component-route')
expect(ssrInitial).toContain(
'hello from app/client-component-route'
)
expect(ssrInitial).toContain('hello from app/client-component-route')
expect(await browser.elementByCss('p').text()).toContain(
'hello from app/client-component-route'
@ -1378,9 +1370,7 @@ createNextDescribe(
async () => {
const browser = await next.browser('/template/servercomponent')
// eslint-disable-next-line jest/no-standalone-expect
expect(await browser.elementByCss('h1').text()).toStartWith(
'Template'
)
expect(await browser.elementByCss('h1').text()).toStartWith('Template')
const currentTime = await browser
.elementByCss('#performance-now')
@ -1390,9 +1380,7 @@ createNextDescribe(
await browser.waitForElementByCss('#other-page')
// eslint-disable-next-line jest/no-standalone-expect
expect(await browser.elementByCss('h1').text()).toStartWith(
'Template'
)
expect(await browser.elementByCss('h1').text()).toStartWith('Template')
// template should rerender on navigation even when it's a server component
// eslint-disable-next-line jest/no-standalone-expect
@ -1703,9 +1691,7 @@ createNextDescribe(
await retry(async () => {
await browser.elementByCss('#get-order').click()
const order = JSON.parse(
await browser.elementByCss('#order').text()
)
const order = JSON.parse(await browser.elementByCss('#order').text())
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 os from 'os'
import path from 'path'
@ -12,16 +12,19 @@ import {
if (!(globalThis as any).isNextStart) {
it('should skip for non-next start', () => {})
} else {
createNextDescribe(
'output: standalone with getStaticProps',
{
describe('output: standalone with getStaticProps', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
skipStart: true,
dependencies: {
swr: 'latest',
},
},
({ next }) => {
})
if (skipped) {
return
}
beforeAll(async () => {
await next.patchFile(
'next.config.js',
@ -53,10 +56,7 @@ if (!(globalThis as any).isNextStart) {
})
it('should work correctly with output standalone', async () => {
const tmpFolder = path.join(
os.tmpdir(),
'next-standalone-' + Date.now()
)
const tmpFolder = path.join(os.tmpdir(), 'next-standalone-' + Date.now())
await fs.move(path.join(next.testDir, '.next/standalone'), tmpFolder)
let server: any
@ -83,6 +83,5 @@ if (!(globalThis as any).isNextStart) {
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 os from 'os'
import path from 'path'
@ -12,13 +12,16 @@ import {
if (!(globalThis as any).isNextStart) {
it('should skip for non-next start', () => {})
} else {
createNextDescribe(
'output: standalone with app dir',
{
describe('output: standalone with app dir', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
skipStart: true,
},
({ next }) => {
})
if (skipped) {
return
}
beforeAll(async () => {
await next.patchFile(
'next.config.js',
@ -55,10 +58,7 @@ if (!(globalThis as any).isNextStart) {
})
it('should work correctly with output standalone', async () => {
const tmpFolder = path.join(
os.tmpdir(),
'next-standalone-' + Date.now()
)
const tmpFolder = path.join(os.tmpdir(), 'next-standalone-' + Date.now())
await fs.move(path.join(next.testDir, '.next/standalone'), tmpFolder)
let server: any
@ -99,6 +99,5 @@ if (!(globalThis as any).isNextStart) {
await fs.remove(tmpFolder)
}
})
}
)
})
}

View file

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

View file

@ -1,12 +1,11 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils'
createNextDescribe(
'router autoscrolling on navigation with css modules',
{
describe('router autoscrolling on navigation with css modules', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
type BrowserInterface = Awaited<ReturnType<(typeof next)['browser']>>
const getTopScroll = async (browser: BrowserInterface) =>
@ -56,5 +55,4 @@ createNextDescribe(
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
describe.skip('app-dir back button download bug', () => {
createNextDescribe(
'app-dir back button download bug',
{
describe('app-dir back button download bug', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next }) => {
})
if (skipped) {
return
}
it('should redirect route when clicking link', async () => {
const browser = await next.browser('/')
const text = await browser
@ -24,6 +27,5 @@ describe.skip('app-dir back button download bug', () => {
'Home!'
)
})
}
)
})
})

View file

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

View file

@ -1,15 +1,18 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils'
createNextDescribe(
'conflicting-page-segments',
{
describe('conflicting-page-segments', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: __dirname,
// 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
skipStart: true,
},
({ next, isNextDev }) => {
})
if (skipped) {
return
}
it('should throw an error when a route groups causes a conflict with a parallel segment', async () => {
if (isNextDev) {
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(
'Web Crypto API is available globally',
{
describe('Web Crypto API is available globally', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
// Recommended for tests that need a full browser
it('should be available in Server Components', async () => {
const browser = await next.browser('/')
@ -18,5 +17,4 @@ createNextDescribe(
const html = await res.text()
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'
createNextDescribe(
'app dir - draft mode',
{
describe('app dir - draft mode', () => {
const { next, isNextDev } = nextTestSetup({
files: __dirname,
},
({ next, isNextDev }) => {
})
async function runTests({ basePath = '/' }: { basePath: string }) {
let origRandHome = 'unintialized'
let origRandWithCookies = 'unintialized'
@ -116,5 +115,4 @@ createNextDescribe(
describe('in edge runtime', () => {
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'
createNextDescribe(
'app dir - dynamic css',
{
describe('app dir - dynamic css', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next }) => {
})
if (skipped) {
return
}
it('should preload css of dynamic component during SSR', async () => {
const $ = await next.render$('/ssr')
const cssLinks = $('link[rel="stylesheet"]')
@ -69,5 +72,4 @@ createNextDescribe(
const output = next.cliOutput
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'
process.env.__TEST_SENTINEL = 'build'
createNextDescribe(
'dynamic-data',
{
describe('dynamic-data', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: __dirname + '/fixtures/main',
skipStart: true,
skipDeployment: true,
},
({ next, isNextDev }) => {
})
if (skipped) {
return
}
beforeAll(async () => {
await next.start()
// This will update the __TEST_SENTINEL value to "run"
@ -170,16 +173,18 @@ createNextDescribe(
)
})
}
}
)
})
createNextDescribe(
'dynamic-data with dynamic = "error"',
{
describe('dynamic-data with dynamic = "error"', () => {
const { next, isNextDev, isNextDeploy, skipped } = nextTestSetup({
files: __dirname + '/fixtures/require-static',
skipStart: true,
},
({ next, isNextDev, isNextDeploy }) => {
})
if (skipped) {
return
}
if (isNextDeploy) {
it.skip('should not run in next deploy.', () => {})
return
@ -246,16 +251,18 @@ createNextDescribe(
)
})
}
}
)
})
createNextDescribe(
'dynamic-data inside cache scope',
{
describe('dynamic-data inside cache scope', () => {
const { next, isNextDev, isNextDeploy, skipped } = nextTestSetup({
files: __dirname + '/fixtures/cache-scoped',
skipStart: true,
},
({ next, isNextDev, isNextDeploy }) => {
})
if (skipped) {
return
}
if (isNextDeploy) {
it.skip('should not run in next deploy..', () => {})
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'
createNextDescribe(
'dynamic-href',
{
describe('dynamic-href', () => {
const {
isNextDev: isDev,
next,
skipped,
} = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ isNextDev: isDev, next }) => {
})
if (skipped) {
return
}
if (isDev) {
it('should error when using dynamic href.pathname in app dir', async () => {
const browser = await next.browser('/object')
@ -27,9 +34,7 @@ createNextDescribe(
"pathname: '/object/slug'"
)
)
expect(await browser.waitForElementByCss('#link').text()).toBe(
'to slug'
)
expect(await browser.waitForElementByCss('#link').text()).toBe('to slug')
// Navigate to new page
await browser.elementByCss('#link').click()
@ -58,5 +63,4 @@ createNextDescribe(
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) {
const content = await (await next.fetch(pathname)).text()
return content.match(/<lastmod>([^<]+)<\/lastmod>/)[1]
}
createNextDescribe(
'app-dir - dynamic in generate params',
{
describe('app-dir - dynamic in generate params', () => {
const { next, isNextDev } = nextTestSetup({
files: __dirname,
},
({ next, isNextDev }) => {
})
it('should render sitemap with generateSitemaps in force-dynamic config dynamically', async () => {
const firstTime = await getLastModifiedTime(
next,
@ -26,12 +25,10 @@ createNextDescribe(
it('should be able to call while generating multiple dynamic sitemaps', async () => {
expect(
(await next.fetch(isNextDev ? 'sitemap.xml/0' : '/sitemap/0.xml'))
.status
(await next.fetch(isNextDev ? 'sitemap.xml/0' : '/sitemap/0.xml')).status
).toBe(200)
expect(
(await next.fetch(isNextDev ? 'sitemap.xml/1' : '/sitemap/1.xml'))
.status
(await next.fetch(isNextDev ? 'sitemap.xml/1' : '/sitemap/1.xml')).status
).toBe(200)
})
@ -39,5 +36,4 @@ createNextDescribe(
expect((await next.fetch('/dynamic/0')).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(
'app dir - next/dynamic',
{
describe('app dir - next/dynamic', () => {
const { next, isNextStart, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next, isNextStart }) => {
})
if (skipped) {
return
}
it('should handle ssr: false in pages when appDir is enabled', async () => {
const $ = await next.render$('/legacy/no-ssr')
expect($.html()).not.toContain('navigator')
const browser = await next.browser('/legacy/no-ssr')
expect(
await browser.waitForElementByCss('#pure-client').text()
).toContain('navigator')
expect(await browser.waitForElementByCss('#pure-client').text()).toContain(
'navigator'
)
})
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 client')
expect(serverContent).toContain('next-dynamic server import client')
expect(serverContent).not.toContain(
'next-dynamic dynamic no ssr on client'
)
expect(serverContent).not.toContain('next-dynamic dynamic no ssr on client')
expect(serverContent).not.toContain(
'next-dynamic dynamic no ssr on server'
)
expect(serverContent).not.toContain('next-dynamic dynamic no ssr on server')
// 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')
@ -69,9 +68,7 @@ createNextDescribe(
'ssr-false-client-module-text'
)
// noSSR should not show up in browser
const browser = await next.browser(
'/dynamic-mixed-ssr-false/client-edge'
)
const browser = await next.browser('/dynamic-mixed-ssr-false/client-edge')
expect(
await browser.elementByCss('#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')
})
})
}
)
})

View file

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

View file

@ -1,11 +1,10 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
createNextDescribe(
'edge-route-rewrite',
{
describe('edge-route-rewrite', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('it should support a rewrite to an edge route', async () => {
const result = await next.render('/one/example')
expect(result).toContain('Hello from /app/two/example/route.ts')
@ -17,5 +16,4 @@ createNextDescribe(
'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(
'edge runtime node compatibility',
{
describe('edge runtime node compatibility', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('[app] supports node:buffer', async () => {
const res = await next.fetch('/buffer', {
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'
createNextDescribe(
'app dir - emotion-js',
{
describe('app dir - emotion-js', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
dependencies: {
'@emotion/react': 'latest',
'@emotion/cache': 'latest',
},
},
({ next }) => {
})
if (skipped) {
return
}
it('should render emotion-js css with compiler.emotion option correctly', async () => {
const browser = await next.browser('/')
const el = browser.elementByCss('h1')
@ -24,5 +27,4 @@ createNextDescribe(
'rgb(0, 0, 255)'
)
})
}
)
})

View file

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

View file

@ -1,13 +1,11 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
import { runTest } from './index.test'
createNextDescribe(
'app dir - not found navigation - with overridden node env',
{
describe('app dir - not found navigation - with overridden node env', () => {
const { next } = nextTestSetup({
files: __dirname,
env: { NODE_ENV: 'test' },
},
({ 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'
createNextDescribe(
'app-dir - errors',
{
describe('app-dir - errors', () => {
const { next, isNextDev, isNextStart, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next, isNextDev, isNextStart }) => {
})
if (skipped) {
return
}
describe('error component', () => {
it('should trigger error component when an error happens during rendering', async () => {
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(
'app dir - front redirect issue',
{
describe('app dir - front redirect issue', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('should redirect', async () => {
const browser = await next.browser('/vercel-user')
expect(
await browser
.waitForElementByCss('#home-page')
.elementByCss('h1')
.text()
await browser.waitForElementByCss('#home-page').elementByCss('h1').text()
).toBe('Hello!')
expect(await browser.url()).toBe(`${next.url}/vercel-user`)
})
}
)
})

View file

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

View file

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

View file

@ -1,18 +1,21 @@
import { getRedboxHeader, hasRedbox } from 'next-test-utils'
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
async function testDev(browser, errorRegex) {
expect(await hasRedbox(browser)).toBe(true)
expect(await getRedboxHeader(browser)).toMatch(errorRegex)
}
createNextDescribe(
'app dir - global error - layout error',
{
describe('app dir - global error - layout error', () => {
const { next, isNextDev, skipped } = nextTestSetup({
files: __dirname,
skipDeployment: true,
},
({ next, isNextDev }) => {
})
if (skipped) {
return
}
it('should render global error for error in server components', async () => {
const browser = await next.browser('/')
@ -26,5 +29,4 @@ createNextDescribe(
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'
createNextDescribe(
'headers-static-bailout',
{
describe('headers-static-bailout', () => {
const { next, isNextStart } = nextTestSetup({
files: __dirname,
dependencies: {
nanoid: '4.0.1',
},
},
({ next, isNextStart }) => {
})
if (!isNextStart) {
it('should skip', () => {})
return
@ -67,5 +66,4 @@ createNextDescribe(
'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(
'hello-world',
{
describe('hello-world', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
// Recommended for tests that check HTML. Cheerio is a HTML parser that has a jQuery like API.
it('should work using cheerio', async () => {
const $ = await next.render$('/')
@ -30,5 +29,4 @@ createNextDescribe(
const html = await res.text()
expect(html).toContain('hello world')
})
}
)
})

View file

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

View file

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

View file

@ -1,16 +1,14 @@
import { createNextDescribe } from 'e2e-utils'
import { nextTestSetup } from 'e2e-utils'
createNextDescribe(
'app dir - imports',
{
describe('app dir - imports', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
;['js', 'jsx', 'ts', 'tsx'].forEach((ext) => {
it(`we can import all components from .${ext}`, async () => {
const $ = await next.render$(`/${ext}`)
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'
createNextDescribe(
'interception-dynamic-segment-middleware',
{
describe('interception-dynamic-segment-middleware', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('should work when interception route is paired with a dynamic segment & middleware', async () => {
const browser = await next.browser('/')
@ -14,10 +13,6 @@ createNextDescribe(
await check(() => browser.elementById('modal').text(), /intercepted/)
await browser.refresh()
await check(() => browser.elementById('modal').text(), '')
await check(
() => browser.elementById('children').text(),
/not intercepted/
)
await check(() => 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'
createNextDescribe(
'interception-dynamic-segment',
{
describe('interception-dynamic-segment', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('should work when interception route is paired with a dynamic segment', async () => {
const browser = await next.browser('/')
@ -14,10 +13,6 @@ createNextDescribe(
await check(() => browser.elementById('modal').text(), /intercepted/)
await browser.refresh()
await check(() => browser.elementById('modal').text(), '')
await check(
() => browser.elementById('children').text(),
/not intercepted/
)
await check(() => 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'
createNextDescribe(
'interception-middleware-rewrite',
{
describe('interception-middleware-rewrite', () => {
const { next, skipped } = nextTestSetup({
files: __dirname,
// TODO: remove after deployment handling is updated
skipDeployment: true,
},
({ next }) => {
})
if (skipped) {
return
}
it('should support intercepting routes with a middleware rewrite', async () => {
const browser = await next.browser('/')
@ -86,5 +89,4 @@ createNextDescribe(
// page content should not have changed
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'
createNextDescribe(
'interception-routes-root-catchall',
{
describe('interception-routes-root-catchall', () => {
const { next } = nextTestSetup({
files: __dirname,
},
({ next }) => {
})
it('should support having a root catch-all and a catch-all in a parallel route group', async () => {
const browser = await next.browser('/')
await browser.elementByCss('[href="/items/1"]').click()
@ -37,5 +36,4 @@ createNextDescribe(
/Root Catch-All Page/
)
})
}
)
})

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