Move test/integration/production to test/production (#55981)
Moves `test/integration/production` to `test/production/pages-dir/production` to leverage test isolation, useful for when Turbopack runs for the test. <!-- 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 # -->
This commit is contained in:
parent
5f03a7129a
commit
73a6374de2
98 changed files with 1354 additions and 1378 deletions
4
.github/workflows/build_and_test.yml
vendored
4
.github/workflows/build_and_test.yml
vendored
|
@ -172,7 +172,7 @@ jobs:
|
|||
uses: ./.github/workflows/build_reusable.yml
|
||||
with:
|
||||
skipForDocsOnly: 'yes'
|
||||
afterBuild: rustup target add wasm32-unknown-unknown && curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh && node ./scripts/normalize-version-bump.js && turbo run build-wasm -- --target nodejs --features tracing/release_max_level_info && git checkout . && mv packages/next-swc/crates/wasm/pkg packages/next-swc/crates/wasm/pkg-nodejs && node ./scripts/setup-wasm.mjs && NEXT_TEST_MODE=start TEST_WASM=true node run-tests.js test/integration/production/test/index.test.js test/e2e/streaming-ssr/index.test.ts
|
||||
afterBuild: rustup target add wasm32-unknown-unknown && curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh && node ./scripts/normalize-version-bump.js && turbo run build-wasm -- --target nodejs --features tracing/release_max_level_info && git checkout . && mv packages/next-swc/crates/wasm/pkg packages/next-swc/crates/wasm/pkg-nodejs && node ./scripts/setup-wasm.mjs && NEXT_TEST_MODE=start TEST_WASM=true node run-tests.js test/production/pages-dir/production/test/index.test.ts test/e2e/streaming-ssr/index.test.ts
|
||||
secrets: inherit
|
||||
|
||||
test-unit:
|
||||
|
@ -238,7 +238,7 @@ jobs:
|
|||
uses: ./.github/workflows/build_reusable.yml
|
||||
with:
|
||||
skipForDocsOnly: 'yes'
|
||||
afterBuild: pnpm playwright install && BROWSER_NAME=firefox node run-tests.js test/integration/production/test/index.test.js && BROWSER_NAME=safari NEXT_TEST_MODE=start node run-tests.js -c 1 test/integration/production/test/index.test.js test/e2e/basepath.test.ts && BROWSER_NAME=safari DEVICE_NAME='iPhone XR' node run-tests.js -c 1 test/production/prerender-prefetch/index.test.ts
|
||||
afterBuild: pnpm playwright install && BROWSER_NAME=firefox node run-tests.js test/production/pages-dir/production/test/index.test.ts && BROWSER_NAME=safari NEXT_TEST_MODE=start node run-tests.js -c 1 test/production/pages-dir/production/test/index.test.ts test/e2e/basepath.test.ts && BROWSER_NAME=safari DEVICE_NAME='iPhone XR' node run-tests.js -c 1 test/production/prerender-prefetch/index.test.ts
|
||||
secrets: inherit
|
||||
|
||||
report-test-results:
|
||||
|
|
|
@ -70,7 +70,7 @@ stages:
|
|||
condition: eq(variables['isDocsOnly'], 'No')
|
||||
|
||||
- script: |
|
||||
node run-tests.js -c 1 test/integration/production/test/index.test.js test/integration/css-client-nav/test/index.test.js test/integration/rewrites-has-condition/test/index.test.js
|
||||
node run-tests.js -c 1 test/production/pages-dir/production/test/index.test.ts test/integration/css-client-nav/test/index.test.js test/integration/rewrites-has-condition/test/index.test.js
|
||||
condition: eq(variables['isDocsOnly'], 'No')
|
||||
displayName: 'Run tests'
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
Before Width: | Height: | Size: 887 B After Width: | Height: | Size: 887 B |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
@ -2,10 +2,11 @@
|
|||
import webdriver from 'next-webdriver'
|
||||
import cheerio from 'cheerio'
|
||||
import { check } from 'next-test-utils'
|
||||
import { NextInstance } from 'e2e-utils'
|
||||
|
||||
// These tests are similar to ../../basic/test/dynamic.js
|
||||
export default (context, render) => {
|
||||
async function get$(path, query) {
|
||||
export default (next: NextInstance, render) => {
|
||||
async function get$(path: string, query?: any) {
|
||||
const html = await render(path, query)
|
||||
return cheerio.load(html)
|
||||
}
|
||||
|
@ -43,12 +44,13 @@ export default (context, render) => {
|
|||
it('should not remove css styles for same css file between page transitions', async () => {
|
||||
let browser
|
||||
try {
|
||||
browser = await webdriver(context.appPort, '/dynamic/pagechange1')
|
||||
browser = await webdriver(next.appPort, '/dynamic/pagechange1')
|
||||
await check(() => browser.elementByCss('body').text(), /PageChange1/)
|
||||
const firstElement = await browser.elementById('with-css')
|
||||
const css1 = await firstElement.getComputedCss('display')
|
||||
expect(css1).toBe('flex')
|
||||
await browser.eval(function () {
|
||||
// @ts-expect-error window.next exists
|
||||
window.next.router.push('/dynamic/pagechange2')
|
||||
})
|
||||
await check(() => browser.elementByCss('body').text(), /PageChange2/)
|
||||
|
@ -78,7 +80,7 @@ export default (context, render) => {
|
|||
it('should render even there are no physical chunk exists', async () => {
|
||||
let browser
|
||||
try {
|
||||
browser = await webdriver(context.appPort, '/dynamic/no-chunk')
|
||||
browser = await webdriver(next.appPort, '/dynamic/no-chunk')
|
||||
await check(
|
||||
() => browser.elementByCss('body').text(),
|
||||
/Welcome, normal/
|
||||
|
@ -103,7 +105,7 @@ export default (context, render) => {
|
|||
it('should render the component on client side', async () => {
|
||||
let browser
|
||||
try {
|
||||
browser = await webdriver(context.appPort, '/dynamic/no-ssr')
|
||||
browser = await webdriver(next.appPort, '/dynamic/no-ssr')
|
||||
await check(
|
||||
() => browser.elementByCss('body').text(),
|
||||
/Hello World 1/
|
||||
|
@ -125,7 +127,7 @@ export default (context, render) => {
|
|||
it('should render the component on client side', async () => {
|
||||
let browser
|
||||
try {
|
||||
browser = await webdriver(context.appPort, '/dynamic/ssr-true')
|
||||
browser = await webdriver(next.appPort, '/dynamic/ssr-true')
|
||||
await check(
|
||||
() => browser.elementByCss('body').text(),
|
||||
/Hello World 1/
|
||||
|
@ -148,7 +150,7 @@ export default (context, render) => {
|
|||
let browser
|
||||
try {
|
||||
browser = await webdriver(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
'/dynamic/no-ssr-custom-loading'
|
||||
)
|
||||
await check(
|
1312
test/production/pages-dir/production/test/index.test.ts
Normal file
1312
test/production/pages-dir/production/test/index.test.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,17 +1,15 @@
|
|||
/* eslint-env jest */
|
||||
import webdriver from 'next-webdriver'
|
||||
import { join } from 'path'
|
||||
import {
|
||||
readNextBuildClientPageFile,
|
||||
readNextBuildServerPageFile,
|
||||
} from 'next-test-utils'
|
||||
import { NextInstance } from 'e2e-utils'
|
||||
|
||||
const appDir = join(__dirname, '..')
|
||||
|
||||
export default (context) => {
|
||||
export default (next: NextInstance) => {
|
||||
describe('process.env', () => {
|
||||
it('should set process.env.NODE_ENV in production', async () => {
|
||||
const browser = await webdriver(context.appPort, '/process-env')
|
||||
const browser = await webdriver(next.appPort, '/process-env')
|
||||
const nodeEnv = await browser.elementByCss('#node-env').text()
|
||||
expect(nodeEnv).toBe('production')
|
||||
await browser.close()
|
||||
|
@ -21,7 +19,7 @@ export default (context) => {
|
|||
describe('process.browser', () => {
|
||||
it('should eliminate server only code on the client', async () => {
|
||||
const clientCode = await readNextBuildClientPageFile(
|
||||
appDir,
|
||||
next.testDir,
|
||||
'/process-env'
|
||||
)
|
||||
expect(clientCode).toMatch(
|
||||
|
@ -34,7 +32,7 @@ export default (context) => {
|
|||
|
||||
it('should eliminate client only code on the server', async () => {
|
||||
const serverCode = await readNextBuildServerPageFile(
|
||||
appDir,
|
||||
next.testDir,
|
||||
'/process-env'
|
||||
)
|
||||
expect(serverCode).not.toMatch(
|
|
@ -1,5 +1,4 @@
|
|||
/* eslint-env jest */
|
||||
/* global browserName */
|
||||
import webdriver from 'next-webdriver'
|
||||
import { readFileSync } from 'fs'
|
||||
import http from 'http'
|
||||
|
@ -8,6 +7,7 @@ import { join } from 'path'
|
|||
import { getBrowserBodyText, waitFor, fetchViaHTTP } from 'next-test-utils'
|
||||
import { recursiveReadDir } from 'next/dist/lib/recursive-readdir'
|
||||
import { homedir } from 'os'
|
||||
import { NextInstance } from 'e2e-utils'
|
||||
|
||||
// Does the same evaluation checking for INJECTED for 5 seconds after hydration, triggering every 500ms
|
||||
async function checkInjected(browser) {
|
||||
|
@ -21,7 +21,7 @@ async function checkInjected(browser) {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = (context) => {
|
||||
export default (next: NextInstance) => {
|
||||
describe('With Security Related Issues', () => {
|
||||
it.skip('should handle invalid URL properly', async () => {
|
||||
async function invalidRequest() {
|
||||
|
@ -29,7 +29,7 @@ module.exports = (context) => {
|
|||
const request = http.request(
|
||||
{
|
||||
hostname: `localhost`,
|
||||
port: context.appPort,
|
||||
port: next.appPort,
|
||||
path: `*`,
|
||||
},
|
||||
(response) => {
|
||||
|
@ -50,7 +50,7 @@ module.exports = (context) => {
|
|||
})
|
||||
|
||||
it('should only access files inside .next directory', async () => {
|
||||
const buildId = readFileSync(join(__dirname, '../.next/BUILD_ID'), 'utf8')
|
||||
const buildId = next.buildId
|
||||
|
||||
const pathsToCheck = [
|
||||
`/_next/${buildId}/page/../../../info`,
|
||||
|
@ -68,7 +68,7 @@ module.exports = (context) => {
|
|||
]
|
||||
|
||||
for (const path of pathsToCheck) {
|
||||
const res = await fetchViaHTTP(context.appPort, path)
|
||||
const res = await fetchViaHTTP(next.appPort, path)
|
||||
const data = await res.text()
|
||||
expect(data.includes('cool-version')).toBeFalsy()
|
||||
expect([400, 404].includes(res.status)).toBeTruthy()
|
||||
|
@ -83,7 +83,7 @@ module.exports = (context) => {
|
|||
`/_next/static/../routes-manifest.json`,
|
||||
]
|
||||
for (const path of pathsToCheck) {
|
||||
const res = await fetchViaHTTP(context.appPort, path)
|
||||
const res = await fetchViaHTTP(next.appPort, path)
|
||||
const text = await res.text()
|
||||
try {
|
||||
expect(res.status).toBe(404)
|
||||
|
@ -95,9 +95,9 @@ module.exports = (context) => {
|
|||
})
|
||||
|
||||
it("should not leak the user's home directory into the build", async () => {
|
||||
const buildId = readFileSync(join(__dirname, '../.next/BUILD_ID'), 'utf8')
|
||||
const buildId = next.buildId
|
||||
|
||||
const readPath = join(__dirname, `../.next/static/${buildId}`)
|
||||
const readPath = join(next.testDir, `.next/static/${buildId}`)
|
||||
const buildFiles = await recursiveReadDir(readPath, {
|
||||
pathnameFilter: (f) => /\.js$/.test(f),
|
||||
})
|
||||
|
@ -131,7 +131,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should prevent URI based XSS attacks', async () => {
|
||||
const browser = await webdriver(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
'/\',document.body.innerHTML="INJECTED",\''
|
||||
)
|
||||
await checkInjected(browser)
|
||||
|
@ -140,7 +140,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should prevent URI based XSS attacks using single quotes', async () => {
|
||||
const browser = await webdriver(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
`/'-(document.body.innerHTML='INJECTED')-'`
|
||||
)
|
||||
await checkInjected(browser)
|
||||
|
@ -149,7 +149,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should prevent URI based XSS attacks using double quotes', async () => {
|
||||
const browser = await webdriver(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
`/"-(document.body.innerHTML='INJECTED')-"`
|
||||
)
|
||||
await checkInjected(browser)
|
||||
|
@ -159,7 +159,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should prevent URI based XSS attacks using semicolons and double quotes', async () => {
|
||||
const browser = await webdriver(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
`/;"-(document.body.innerHTML='INJECTED')-"`
|
||||
)
|
||||
await checkInjected(browser)
|
||||
|
@ -169,7 +169,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should prevent URI based XSS attacks using semicolons and single quotes', async () => {
|
||||
const browser = await webdriver(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
`/;'-(document.body.innerHTML='INJECTED')-'`
|
||||
)
|
||||
await checkInjected(browser)
|
||||
|
@ -179,7 +179,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should prevent URI based XSS attacks using src', async () => {
|
||||
const browser = await webdriver(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
`/javascript:(document.body.innerHTML='INJECTED')`
|
||||
)
|
||||
await checkInjected(browser)
|
||||
|
@ -189,7 +189,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should prevent URI based XSS attacks using querystring', async () => {
|
||||
const browser = await webdriver(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
`/?javascript=(document.body.innerHTML='INJECTED')`
|
||||
)
|
||||
await checkInjected(browser)
|
||||
|
@ -199,7 +199,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should prevent URI based XSS attacks using querystring and quotes', async () => {
|
||||
const browser = await webdriver(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
`/?javascript="(document.body.innerHTML='INJECTED')"`
|
||||
)
|
||||
await checkInjected(browser)
|
||||
|
@ -208,7 +208,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should handle encoded value in the pathname correctly \\', async () => {
|
||||
const res = await fetchViaHTTP(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
'/redirect/me/to-about/' + encodeURI('\\google.com'),
|
||||
undefined,
|
||||
{
|
||||
|
@ -226,7 +226,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should handle encoded value in the pathname correctly %', async () => {
|
||||
const res = await fetchViaHTTP(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
'/redirect/me/to-about/%25google.com',
|
||||
undefined,
|
||||
{
|
||||
|
@ -244,7 +244,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should handle encoded value in the query correctly', async () => {
|
||||
const res = await fetchViaHTTP(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
'/trailing-redirect/?url=https%3A%2F%2Fgoogle.com%2Fimage%3Fcrop%3Dfocalpoint%26w%3D24&w=1200&q=100',
|
||||
undefined,
|
||||
{
|
||||
|
@ -265,7 +265,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should handle encoded value in the pathname correctly /', async () => {
|
||||
const res = await fetchViaHTTP(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
'/redirect/me/to-about/%2fgoogle.com',
|
||||
undefined,
|
||||
{
|
||||
|
@ -283,7 +283,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should handle encoded value in the pathname to query correctly (/)', async () => {
|
||||
const res = await fetchViaHTTP(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
'/redirect-query-test/%2Fgoogle.com',
|
||||
undefined,
|
||||
{
|
||||
|
@ -303,7 +303,7 @@ module.exports = (context) => {
|
|||
|
||||
it('should handle encoded / value for trailing slash correctly', async () => {
|
||||
const res = await fetchViaHTTP(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
'/%2fexample.com/',
|
||||
undefined,
|
||||
{ redirect: 'manual' }
|
||||
|
@ -317,17 +317,17 @@ module.exports = (context) => {
|
|||
expect(hostname).not.toBe('example.com')
|
||||
})
|
||||
|
||||
if (browserName !== 'internet explorer') {
|
||||
if (global.browserName !== 'internet explorer') {
|
||||
it('should not execute script embedded inside svg image, even if dangerouslyAllowSVG=true', async () => {
|
||||
let browser
|
||||
try {
|
||||
browser = await webdriver(context.appPort, '/svg-image')
|
||||
browser = await webdriver(next.appPort, '/svg-image')
|
||||
await browser.eval(`document.getElementById("img").scrollIntoView()`)
|
||||
const src = await browser.elementById('img').getAttribute('src')
|
||||
expect(src).toMatch(/_next\/image\?.*xss\.svg/)
|
||||
expect(await browser.elementById('msg').text()).toBe('safe')
|
||||
browser = await webdriver(
|
||||
context.appPort,
|
||||
next.appPort,
|
||||
'/_next/image?url=%2Fxss.svg&w=256&q=75'
|
||||
)
|
||||
expect(await browser.elementById('msg').text()).toBe('safe')
|
Loading…
Reference in a new issue