rsnext/test/lib/next-test-utils.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1415 lines
37 KiB
TypeScript
Raw Permalink Normal View History

2017-05-10 01:24:34 +02:00
import express from 'express'
import {
existsSync,
readFileSync,
unlinkSync,
writeFileSync,
createReadStream,
} from 'fs'
import { promisify } from 'util'
import http from 'http'
import path from 'path'
import cheerio from 'cheerio'
import spawn from 'cross-spawn'
import { writeFile } from 'fs-extra'
import getPort from 'get-port'
import { getRandomPort } from 'get-port-please'
import fetch from 'node-fetch'
import qs from 'querystring'
import treeKill from 'tree-kill'
graceful shutdown (#60059) - Both the standalone server and the `startServer` function it calls attempt to stop the server on `SIGINT` and `SIGTERM` in different ways. This lets `server.js` yield to `startServer` - The cleanup function in `startServer` was not waiting for the server to close before calling `process.exit`. This lets it wait for any in-flight requests to finish processing before exiting the process - Sends `SIGKILL` to the child process in `next dev`, which should have the same effect of immediately shutting down the server on `SIGTERM` or `SIGINT` fixes: #53661 refs: #59551 ------ Previously #59551 attempted to fix #53661, but had broken some tests in the process. It looks like the final commit was also missing an intended change to `utils.ts`. This should fix those issues as well as introduce a new set of tests for the graceful shutdown feature. In the last PR I was squashing and force-pushing updates along the way but it made it difficult to track the changes. This time I'm pushing quite a few commits to make it easier to track the changes and refactors I've made, with the idea that this should be squashed before being merged. <!-- 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 # -->
2024-01-16 18:25:49 +01:00
import { once } from 'events'
New test setup (#640) * Use jest-cli instead of gulp plugin. * Use jest-cli instead of gulp plugin. * Move fixtures into the examples dir. * Move test code of example app to the basic example. * Add isolated tests for server/resolve * Allow tests to use cheerio. * Use portfinder to get a unique port. * Move back integration tests into the example dir. * Introduce next-test-utils. * Remove gulp-jest * Add coveralls support. * Use transpiled version of code in dist. This is to make sure same file gets covered by both unit/isolated tests and integration tests. * Add support for source maps. * Use code from dist always. * Use nyc to stop instrument. * Add integration test suite for production usage. * Use jest-cli. * Add support for running e2e tests. * Check gzipPath with fs.stat before serving Otherwise, serve package might throw issues other than ENOENT * Install chromedriver with npm install. * Install chrome on travis-ci. * Add --forceExit to Jest. * Run tests only on Node v6. That's because selenium-webdriver only supports Node 6 LTS. * Use chromedriver NPM module to install chromedriver. * Use wd as the webdriver client. * Run chromedriver before tests. * Run travis for both node 4 and 6 * Remove unwanted npm install script. * Move some common text utilities to next-test-utils * Add lint checks and testing in npm prepublish hook. * Use npm on travis-ci. We are having some caching issues with yarn and chromedriver. * Make tests work on windows.\n But chromedriver doesn't work. * Clean up dependencies. * Run chromedriver in background without any tools. * Fix a typo in the code. * Use ES6 features used in node4 inside the gulpfile. * Add some comments. * Add support for running in windows. * Stop chromedriver properly on windows. * Fix typos.
2017-01-12 05:14:49 +01:00
import server from 'next/dist/server/next'
import _pkg from 'next/package.json'
import type { SpawnOptions, ChildProcess } from 'child_process'
import type { RequestInit, Response } from 'node-fetch'
import type { NextServer } from 'next/dist/server/next'
import type { BrowserInterface } from './browsers/base'
import { getTurbopackFlag, shouldRunTurboDevTest } from './turbo'
Redesign nextjs logging (#54713) The current logging styles has been existed for a while, this PR gives a fresh impression for the logging output from Next.js. We want to achieve few new goals that makes the output clean, modernized, sweet 🍫 . Few goals are addressed with this redesign: ## Refresh Impression & Simplification The new design of logging is much more information centralized and streamlined. * Given a `ready` message at the begining when compilers are bootstrapped. * Only show `compiled` event with green check mark indicating succesful compilation, this will merge the unclear `compiling` event which shows `(client and server)` before, now tell you the route compilation info in one line. hello world app ### `next dev` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/9649b340-8241-4756-a2b3-a989f0b74003" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/ee181263-3dd4-40d0-9ffc-819a56b45900" height="120"> ### `next build` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/5db9829a-9ffc-49f0-b030-93ee92f5c248" width="360"> <img src="https://github.com/vercel/next.js/assets/4800338/b9527b83-27c8-4426-9c0d-c0d4072b7d58" width="360"> ### error status #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/00455226-ace7-468b-8d90-0d36bf038489" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/1be8c451-d3f0-465c-9ef7-6b0dde7cff85" height="120"> ## Streamlization If you have customized envs and experiments Next.js will give the brief in the early summary about your network information, env vars, and enabled experimental features <img src="https://github.com/vercel/next.js/assets/4800338/ca1a7409-1532-46cb-850f-687e61e587b2" width="400"> ## Polish ### fetching logging structure #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/97526397-dffe-4736-88ed-e5cbe5e945bd" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/ab77c907-5ab5-48bb-8347-6146d2e60932" width="400"> ### Dedupe Duplicates The logging is moved from `@next/env` to `next` itself, `@next/env` will only notify the invoker that the env is reloaded. Then the duplicated logs for the env reloading cases can be avoid. #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/04799295-e739-4035-87aa-61cec962fc39" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/e29020c9-0031-4bf3-a21b-8b64633f43a2" width="400"> ### Different indicators Use unicode text icons for different situation: * passed -> check mark * warning -> warning * error -> red cross * loading -> circle <img src="https://github.com/vercel/next.js/assets/4800338/715c34bd-298f-4990-a5d7-e12e455ead44" width="400"> Co-authored-by: Tim Neutkens <6324199+timneutkens@users.noreply.github.com>
2023-09-05 13:40:00 +02:00
import stripAnsi from 'strip-ansi'
export { shouldRunTurboDevTest }
New test setup (#640) * Use jest-cli instead of gulp plugin. * Use jest-cli instead of gulp plugin. * Move fixtures into the examples dir. * Move test code of example app to the basic example. * Add isolated tests for server/resolve * Allow tests to use cheerio. * Use portfinder to get a unique port. * Move back integration tests into the example dir. * Introduce next-test-utils. * Remove gulp-jest * Add coveralls support. * Use transpiled version of code in dist. This is to make sure same file gets covered by both unit/isolated tests and integration tests. * Add support for source maps. * Use code from dist always. * Use nyc to stop instrument. * Add integration test suite for production usage. * Use jest-cli. * Add support for running e2e tests. * Check gzipPath with fs.stat before serving Otherwise, serve package might throw issues other than ENOENT * Install chromedriver with npm install. * Install chrome on travis-ci. * Add --forceExit to Jest. * Run tests only on Node v6. That's because selenium-webdriver only supports Node 6 LTS. * Use chromedriver NPM module to install chromedriver. * Use wd as the webdriver client. * Run chromedriver before tests. * Run travis for both node 4 and 6 * Remove unwanted npm install script. * Move some common text utilities to next-test-utils * Add lint checks and testing in npm prepublish hook. * Use npm on travis-ci. We are having some caching issues with yarn and chromedriver. * Make tests work on windows.\n But chromedriver doesn't work. * Clean up dependencies. * Run chromedriver in background without any tools. * Fix a typo in the code. * Use ES6 features used in node4 inside the gulpfile. * Add some comments. * Add support for running in windows. * Stop chromedriver properly on windows. * Fix typos.
2017-01-12 05:14:49 +01:00
export const nextServer = server
export const pkg = _pkg
export function initNextServerScript(
scriptPath: string,
successRegexp: RegExp,
env: NodeJS.ProcessEnv,
failRegexp?: RegExp,
opts?: {
cwd?: string
nodeArgs?: string[]
onStdout?: (data: any) => void
onStderr?: (data: any) => void
}
): Promise<ChildProcess> {
return new Promise((resolve, reject) => {
const instance = spawn(
'node',
[...((opts && opts.nodeArgs) || []), '--no-deprecation', scriptPath],
{
env: { HOSTNAME: '::', ...env },
cwd: opts && opts.cwd,
}
)
function handleStdout(data) {
const message = data.toString()
if (successRegexp.test(message)) {
resolve(instance)
}
process.stdout.write(message)
if (opts && opts.onStdout) {
opts.onStdout(message.toString())
}
}
function handleStderr(data) {
const message = data.toString()
if (failRegexp && failRegexp.test(message)) {
instance.kill()
return reject(new Error('received failRegexp'))
}
process.stderr.write(message)
if (opts && opts.onStderr) {
opts.onStderr(message.toString())
}
}
instance.stdout.on('data', handleStdout)
instance.stderr.on('data', handleStderr)
instance.on('close', () => {
instance.stdout.removeListener('data', handleStdout)
instance.stderr.removeListener('data', handleStderr)
})
2020-05-18 21:24:37 +02:00
instance.on('error', (err) => {
reject(err)
})
})
}
export function getFullUrl(
appPortOrUrl: string | number,
url?: string,
hostname?: string
) {
let fullUrl =
typeof appPortOrUrl === 'string' && appPortOrUrl.startsWith('http')
? appPortOrUrl
: `http://${hostname ? hostname : 'localhost'}:${appPortOrUrl}${url}`
if (typeof appPortOrUrl === 'string' && url) {
const parsedUrl = new URL(fullUrl)
const parsedPathQuery = new URL(url, fullUrl)
parsedUrl.hash = parsedPathQuery.hash
parsedUrl.search = parsedPathQuery.search
parsedUrl.pathname = parsedPathQuery.pathname
if (hostname && parsedUrl.hostname === 'localhost') {
parsedUrl.hostname = hostname
}
fullUrl = parsedUrl.toString()
}
return fullUrl
}
/**
* Appends the querystring to the url
*
* @param pathname the pathname
* @param query the query object to add to the pathname
* @returns the pathname with the query
*/
export function withQuery(
pathname: string,
query: Record<string, any> | string
) {
const querystring = typeof query === 'string' ? query : qs.stringify(query)
if (querystring.length === 0) {
return pathname
}
// If there's a `?` between the pathname and the querystring already, then
// don't add another one.
if (querystring.startsWith('?') || pathname.endsWith('?')) {
return `${pathname}${querystring}`
}
return `${pathname}?${querystring}`
}
export function fetchViaHTTP(
appPort: string | number,
pathname: string,
query?: Record<string, any> | string | null | undefined,
opts?: RequestInit
): Promise<Response> {
const url = query ? withQuery(pathname, query) : pathname
Better IPv6 support for `next-server` (#53131) ### What? This PR makes it easier to use Next.js with IPv6 hostnames such as `::1` and `::`. ### How? It does so by removing rewrites from `localhost` to `127.0.0.1` introduced in #52492. It also fixes the issue where Next.js tries to fetch something like `http://::1:3000` when `--hostname` is `::1` as it is not a valid URL (browsers' `URL` class throws an error when constructed with such hosts). It also fixes `NextURL` so that it doesn't accept `http://::1:3000` but refuse `http://[::1]:3000`. It also changes `next/src/server/lib/setup-server-worker.ts` so that it uses the server's `address` method to retrieve the host instead of our provided `opts.hostname`, ensuring that no matter what `opts.hostname` is we will always get the correct one. ### Note I've verified that `next dev`, `next start` and `node .next/standalone/server.js` work with IPv6 hostnames (such as `::` and `::1`), IPv4 hostnames (such as `127.0.0.1`, `0.0.0.0`) and `localhost` - and with any of these hostnames fetching to `localhost` also works. Server Actions and middleware have no problems as well. This also removes `.next/standalone/server.js`'s logging as we now use `start-server`'s logging to avoid duplicates. `start-server`'s logging has also been updated to report the actual hostname. ![image](https://github.com/vercel/next.js/assets/75556609/cefa5f23-ff09-4cef-a055-13eea7c11d89) ![image](https://github.com/vercel/next.js/assets/75556609/619e82ce-45d9-47b7-8644-f4ad083429db) The above pictures also demonstrate using Server Actions with Next.js after this PR. ![image](https://github.com/vercel/next.js/assets/75556609/3d4166e9-f950-4390-bde9-af2547658148) Fixes #53171 Fixes #49578 Closes NEXT-1510 Co-authored-by: Tim Neutkens <6324199+timneutkens@users.noreply.github.com> Co-authored-by: Zack Tanner <1939140+ztanner@users.noreply.github.com>
2023-08-14 09:23:24 +02:00
return fetch(getFullUrl(appPort, url), opts)
New test setup (#640) * Use jest-cli instead of gulp plugin. * Use jest-cli instead of gulp plugin. * Move fixtures into the examples dir. * Move test code of example app to the basic example. * Add isolated tests for server/resolve * Allow tests to use cheerio. * Use portfinder to get a unique port. * Move back integration tests into the example dir. * Introduce next-test-utils. * Remove gulp-jest * Add coveralls support. * Use transpiled version of code in dist. This is to make sure same file gets covered by both unit/isolated tests and integration tests. * Add support for source maps. * Use code from dist always. * Use nyc to stop instrument. * Add integration test suite for production usage. * Use jest-cli. * Add support for running e2e tests. * Check gzipPath with fs.stat before serving Otherwise, serve package might throw issues other than ENOENT * Install chromedriver with npm install. * Install chrome on travis-ci. * Add --forceExit to Jest. * Run tests only on Node v6. That's because selenium-webdriver only supports Node 6 LTS. * Use chromedriver NPM module to install chromedriver. * Use wd as the webdriver client. * Run chromedriver before tests. * Run travis for both node 4 and 6 * Remove unwanted npm install script. * Move some common text utilities to next-test-utils * Add lint checks and testing in npm prepublish hook. * Use npm on travis-ci. We are having some caching issues with yarn and chromedriver. * Make tests work on windows.\n But chromedriver doesn't work. * Clean up dependencies. * Run chromedriver in background without any tools. * Fix a typo in the code. * Use ES6 features used in node4 inside the gulpfile. * Add some comments. * Add support for running in windows. * Stop chromedriver properly on windows. * Fix typos.
2017-01-12 05:14:49 +01:00
}
export function renderViaHTTP(
appPort: string | number,
pathname: string,
query?: Record<string, any> | string | undefined,
opts?: RequestInit
) {
return fetchViaHTTP(appPort, pathname, query, opts).then((res) => res.text())
}
export function findPort() {
// [NOTE] What are we doing here?
// There are some flaky tests failures caused by `No available ports found` from 'get-port'.
// This may be related / fixed by upstream https://github.com/sindresorhus/get-port/pull/56,
// however it happened after get-port switched to pure esm which is not easy to adapt by bump.
// get-port-please seems to offer the feature parity so we'll try to use it, and leave get-port as fallback
// for a while until we are certain to switch to get-port-please entirely.
try {
return getRandomPort()
} catch (e) {
require('console').warn('get-port-please failed, falling back to get-port')
return getPort()
}
}
export interface NextOptions {
cwd?: string
env?: NodeJS.Dict<string>
nodeArgs?: string[]
spawnOptions?: SpawnOptions
instance?: (instance: ChildProcess) => void
stderr?: true | 'log'
stdout?: true | 'log'
ignoreFail?: boolean
/**
* If true, this enables the linting step in the build process. If false or
* undefined, it adds a `--no-lint` flag to the build command.
*/
lint?: boolean
onStdout?: (data: any) => void
onStderr?: (data: any) => void
}
export function runNextCommand(
argv: string[],
options: NextOptions = {}
): Promise<{
code: number
signal: NodeJS.Signals
stdout: string
stderr: string
}> {
const nextDir = path.dirname(require.resolve('next/package'))
const nextBin = path.join(nextDir, 'dist/bin/next')
const cwd = options.cwd || nextDir
// Let Next.js decide the environment
const env = {
...process.env,
NODE_ENV: undefined,
__NEXT_TEST_MODE: 'true',
...options.env,
}
return new Promise((resolve, reject) => {
console.log(`Running command "next ${argv.join(' ')}"`)
const instance = spawn(
'node',
[...(options.nodeArgs || []), '--no-deprecation', nextBin, ...argv],
{
...options.spawnOptions,
cwd,
env,
stdio: ['ignore', 'pipe', 'pipe'],
}
)
if (typeof options.instance === 'function') {
options.instance(instance)
}
let mergedStdio = ''
let stderrOutput = ''
if (options.stderr || options.onStderr) {
2020-05-18 21:24:37 +02:00
instance.stderr.on('data', function (chunk) {
mergedStdio += chunk
stderrOutput += chunk
if (options.stderr === 'log') {
console.log(chunk.toString())
}
if (typeof options.onStderr === 'function') {
options.onStderr(chunk.toString())
}
})
} else {
instance.stderr.on('data', function (chunk) {
mergedStdio += chunk
})
}
let stdoutOutput = ''
if (options.stdout || options.onStdout) {
2020-05-18 21:24:37 +02:00
instance.stdout.on('data', function (chunk) {
mergedStdio += chunk
stdoutOutput += chunk
if (options.stdout === 'log') {
console.log(chunk.toString())
}
if (typeof options.onStdout === 'function') {
options.onStdout(chunk.toString())
}
})
} else {
instance.stdout.on('data', function (chunk) {
mergedStdio += chunk
})
}
instance.on('close', (code, signal) => {
if (
!options.stderr &&
!options.stdout &&
!options.ignoreFail &&
(code !== 0 || signal)
) {
return reject(
new Error(
`command failed with code ${code} signal ${signal}\n${mergedStdio}`
)
)
}
if (code || signal) {
console.error(`process exited with code ${code} and signal ${signal}`)
}
resolve({
code,
signal,
stdout: stdoutOutput,
stderr: stderrOutput,
})
})
2020-05-18 21:24:37 +02:00
instance.on('error', (err) => {
err['stdout'] = stdoutOutput
err['stderr'] = stderrOutput
reject(err)
})
})
}
export interface NextDevOptions {
cwd?: string
env?: NodeJS.Dict<string>
nodeArgs?: string[]
nextBin?: string
bootupMarker?: RegExp
nextStart?: boolean
turbo?: boolean
stderr?: false
stdout?: false
onStdout?: (data: any) => void
onStderr?: (data: any) => void
}
export function runNextCommandDev(
argv: string[],
stdOut?: boolean,
opts: NextDevOptions = {}
): Promise<(typeof stdOut extends true ? string : ChildProcess) | undefined> {
const nextDir = path.dirname(require.resolve('next/package'))
const nextBin = opts.nextBin || path.join(nextDir, 'dist/bin/next')
const cwd = opts.cwd || nextDir
const env = {
...process.env,
NODE_ENV: undefined,
__NEXT_TEST_MODE: 'true',
...opts.env,
}
const nodeArgs = opts.nodeArgs || []
return new Promise((resolve, reject) => {
const instance = spawn(
'node',
[...nodeArgs, '--no-deprecation', nextBin, ...argv],
{
cwd,
env,
}
)
let didResolve = false
Redesign nextjs logging (#54713) The current logging styles has been existed for a while, this PR gives a fresh impression for the logging output from Next.js. We want to achieve few new goals that makes the output clean, modernized, sweet 🍫 . Few goals are addressed with this redesign: ## Refresh Impression & Simplification The new design of logging is much more information centralized and streamlined. * Given a `ready` message at the begining when compilers are bootstrapped. * Only show `compiled` event with green check mark indicating succesful compilation, this will merge the unclear `compiling` event which shows `(client and server)` before, now tell you the route compilation info in one line. hello world app ### `next dev` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/9649b340-8241-4756-a2b3-a989f0b74003" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/ee181263-3dd4-40d0-9ffc-819a56b45900" height="120"> ### `next build` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/5db9829a-9ffc-49f0-b030-93ee92f5c248" width="360"> <img src="https://github.com/vercel/next.js/assets/4800338/b9527b83-27c8-4426-9c0d-c0d4072b7d58" width="360"> ### error status #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/00455226-ace7-468b-8d90-0d36bf038489" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/1be8c451-d3f0-465c-9ef7-6b0dde7cff85" height="120"> ## Streamlization If you have customized envs and experiments Next.js will give the brief in the early summary about your network information, env vars, and enabled experimental features <img src="https://github.com/vercel/next.js/assets/4800338/ca1a7409-1532-46cb-850f-687e61e587b2" width="400"> ## Polish ### fetching logging structure #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/97526397-dffe-4736-88ed-e5cbe5e945bd" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/ab77c907-5ab5-48bb-8347-6146d2e60932" width="400"> ### Dedupe Duplicates The logging is moved from `@next/env` to `next` itself, `@next/env` will only notify the invoker that the env is reloaded. Then the duplicated logs for the env reloading cases can be avoid. #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/04799295-e739-4035-87aa-61cec962fc39" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/e29020c9-0031-4bf3-a21b-8b64633f43a2" width="400"> ### Different indicators Use unicode text icons for different situation: * passed -> check mark * warning -> warning * error -> red cross * loading -> circle <img src="https://github.com/vercel/next.js/assets/4800338/715c34bd-298f-4990-a5d7-e12e455ead44" width="400"> Co-authored-by: Tim Neutkens <6324199+timneutkens@users.noreply.github.com>
2023-09-05 13:40:00 +02:00
const bootType =
opts.nextStart || stdOut ? 'start' : opts?.turbo ? 'turbo' : 'dev'
Redesign nextjs logging (#54713) The current logging styles has been existed for a while, this PR gives a fresh impression for the logging output from Next.js. We want to achieve few new goals that makes the output clean, modernized, sweet 🍫 . Few goals are addressed with this redesign: ## Refresh Impression & Simplification The new design of logging is much more information centralized and streamlined. * Given a `ready` message at the begining when compilers are bootstrapped. * Only show `compiled` event with green check mark indicating succesful compilation, this will merge the unclear `compiling` event which shows `(client and server)` before, now tell you the route compilation info in one line. hello world app ### `next dev` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/9649b340-8241-4756-a2b3-a989f0b74003" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/ee181263-3dd4-40d0-9ffc-819a56b45900" height="120"> ### `next build` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/5db9829a-9ffc-49f0-b030-93ee92f5c248" width="360"> <img src="https://github.com/vercel/next.js/assets/4800338/b9527b83-27c8-4426-9c0d-c0d4072b7d58" width="360"> ### error status #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/00455226-ace7-468b-8d90-0d36bf038489" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/1be8c451-d3f0-465c-9ef7-6b0dde7cff85" height="120"> ## Streamlization If you have customized envs and experiments Next.js will give the brief in the early summary about your network information, env vars, and enabled experimental features <img src="https://github.com/vercel/next.js/assets/4800338/ca1a7409-1532-46cb-850f-687e61e587b2" width="400"> ## Polish ### fetching logging structure #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/97526397-dffe-4736-88ed-e5cbe5e945bd" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/ab77c907-5ab5-48bb-8347-6146d2e60932" width="400"> ### Dedupe Duplicates The logging is moved from `@next/env` to `next` itself, `@next/env` will only notify the invoker that the env is reloaded. Then the duplicated logs for the env reloading cases can be avoid. #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/04799295-e739-4035-87aa-61cec962fc39" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/e29020c9-0031-4bf3-a21b-8b64633f43a2" width="400"> ### Different indicators Use unicode text icons for different situation: * passed -> check mark * warning -> warning * error -> red cross * loading -> circle <img src="https://github.com/vercel/next.js/assets/4800338/715c34bd-298f-4990-a5d7-e12e455ead44" width="400"> Co-authored-by: Tim Neutkens <6324199+timneutkens@users.noreply.github.com>
2023-09-05 13:40:00 +02:00
function handleStdout(data) {
const message = data.toString()
const bootupMarkers = {
Redesign nextjs logging (#54713) The current logging styles has been existed for a while, this PR gives a fresh impression for the logging output from Next.js. We want to achieve few new goals that makes the output clean, modernized, sweet 🍫 . Few goals are addressed with this redesign: ## Refresh Impression & Simplification The new design of logging is much more information centralized and streamlined. * Given a `ready` message at the begining when compilers are bootstrapped. * Only show `compiled` event with green check mark indicating succesful compilation, this will merge the unclear `compiling` event which shows `(client and server)` before, now tell you the route compilation info in one line. hello world app ### `next dev` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/9649b340-8241-4756-a2b3-a989f0b74003" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/ee181263-3dd4-40d0-9ffc-819a56b45900" height="120"> ### `next build` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/5db9829a-9ffc-49f0-b030-93ee92f5c248" width="360"> <img src="https://github.com/vercel/next.js/assets/4800338/b9527b83-27c8-4426-9c0d-c0d4072b7d58" width="360"> ### error status #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/00455226-ace7-468b-8d90-0d36bf038489" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/1be8c451-d3f0-465c-9ef7-6b0dde7cff85" height="120"> ## Streamlization If you have customized envs and experiments Next.js will give the brief in the early summary about your network information, env vars, and enabled experimental features <img src="https://github.com/vercel/next.js/assets/4800338/ca1a7409-1532-46cb-850f-687e61e587b2" width="400"> ## Polish ### fetching logging structure #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/97526397-dffe-4736-88ed-e5cbe5e945bd" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/ab77c907-5ab5-48bb-8347-6146d2e60932" width="400"> ### Dedupe Duplicates The logging is moved from `@next/env` to `next` itself, `@next/env` will only notify the invoker that the env is reloaded. Then the duplicated logs for the env reloading cases can be avoid. #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/04799295-e739-4035-87aa-61cec962fc39" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/e29020c9-0031-4bf3-a21b-8b64633f43a2" width="400"> ### Different indicators Use unicode text icons for different situation: * passed -> check mark * warning -> warning * error -> red cross * loading -> circle <img src="https://github.com/vercel/next.js/assets/4800338/715c34bd-298f-4990-a5d7-e12e455ead44" width="400"> Co-authored-by: Tim Neutkens <6324199+timneutkens@users.noreply.github.com>
2023-09-05 13:40:00 +02:00
dev: /✓ ready/i,
turbo: /✓ ready/i,
start: /✓ ready/i,
}
Redesign nextjs logging (#54713) The current logging styles has been existed for a while, this PR gives a fresh impression for the logging output from Next.js. We want to achieve few new goals that makes the output clean, modernized, sweet 🍫 . Few goals are addressed with this redesign: ## Refresh Impression & Simplification The new design of logging is much more information centralized and streamlined. * Given a `ready` message at the begining when compilers are bootstrapped. * Only show `compiled` event with green check mark indicating succesful compilation, this will merge the unclear `compiling` event which shows `(client and server)` before, now tell you the route compilation info in one line. hello world app ### `next dev` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/9649b340-8241-4756-a2b3-a989f0b74003" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/ee181263-3dd4-40d0-9ffc-819a56b45900" height="120"> ### `next build` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/5db9829a-9ffc-49f0-b030-93ee92f5c248" width="360"> <img src="https://github.com/vercel/next.js/assets/4800338/b9527b83-27c8-4426-9c0d-c0d4072b7d58" width="360"> ### error status #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/00455226-ace7-468b-8d90-0d36bf038489" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/1be8c451-d3f0-465c-9ef7-6b0dde7cff85" height="120"> ## Streamlization If you have customized envs and experiments Next.js will give the brief in the early summary about your network information, env vars, and enabled experimental features <img src="https://github.com/vercel/next.js/assets/4800338/ca1a7409-1532-46cb-850f-687e61e587b2" width="400"> ## Polish ### fetching logging structure #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/97526397-dffe-4736-88ed-e5cbe5e945bd" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/ab77c907-5ab5-48bb-8347-6146d2e60932" width="400"> ### Dedupe Duplicates The logging is moved from `@next/env` to `next` itself, `@next/env` will only notify the invoker that the env is reloaded. Then the duplicated logs for the env reloading cases can be avoid. #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/04799295-e739-4035-87aa-61cec962fc39" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/e29020c9-0031-4bf3-a21b-8b64633f43a2" width="400"> ### Different indicators Use unicode text icons for different situation: * passed -> check mark * warning -> warning * error -> red cross * loading -> circle <img src="https://github.com/vercel/next.js/assets/4800338/715c34bd-298f-4990-a5d7-e12e455ead44" width="400"> Co-authored-by: Tim Neutkens <6324199+timneutkens@users.noreply.github.com>
2023-09-05 13:40:00 +02:00
const strippedMessage = stripAnsi(message) as any
if (
Redesign nextjs logging (#54713) The current logging styles has been existed for a while, this PR gives a fresh impression for the logging output from Next.js. We want to achieve few new goals that makes the output clean, modernized, sweet 🍫 . Few goals are addressed with this redesign: ## Refresh Impression & Simplification The new design of logging is much more information centralized and streamlined. * Given a `ready` message at the begining when compilers are bootstrapped. * Only show `compiled` event with green check mark indicating succesful compilation, this will merge the unclear `compiling` event which shows `(client and server)` before, now tell you the route compilation info in one line. hello world app ### `next dev` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/9649b340-8241-4756-a2b3-a989f0b74003" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/ee181263-3dd4-40d0-9ffc-819a56b45900" height="120"> ### `next build` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/5db9829a-9ffc-49f0-b030-93ee92f5c248" width="360"> <img src="https://github.com/vercel/next.js/assets/4800338/b9527b83-27c8-4426-9c0d-c0d4072b7d58" width="360"> ### error status #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/00455226-ace7-468b-8d90-0d36bf038489" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/1be8c451-d3f0-465c-9ef7-6b0dde7cff85" height="120"> ## Streamlization If you have customized envs and experiments Next.js will give the brief in the early summary about your network information, env vars, and enabled experimental features <img src="https://github.com/vercel/next.js/assets/4800338/ca1a7409-1532-46cb-850f-687e61e587b2" width="400"> ## Polish ### fetching logging structure #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/97526397-dffe-4736-88ed-e5cbe5e945bd" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/ab77c907-5ab5-48bb-8347-6146d2e60932" width="400"> ### Dedupe Duplicates The logging is moved from `@next/env` to `next` itself, `@next/env` will only notify the invoker that the env is reloaded. Then the duplicated logs for the env reloading cases can be avoid. #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/04799295-e739-4035-87aa-61cec962fc39" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/e29020c9-0031-4bf3-a21b-8b64633f43a2" width="400"> ### Different indicators Use unicode text icons for different situation: * passed -> check mark * warning -> warning * error -> red cross * loading -> circle <img src="https://github.com/vercel/next.js/assets/4800338/715c34bd-298f-4990-a5d7-e12e455ead44" width="400"> Co-authored-by: Tim Neutkens <6324199+timneutkens@users.noreply.github.com>
2023-09-05 13:40:00 +02:00
(opts.bootupMarker && opts.bootupMarker.test(strippedMessage)) ||
bootupMarkers[bootType].test(strippedMessage)
) {
if (!didResolve) {
didResolve = true
Redesign nextjs logging (#54713) The current logging styles has been existed for a while, this PR gives a fresh impression for the logging output from Next.js. We want to achieve few new goals that makes the output clean, modernized, sweet 🍫 . Few goals are addressed with this redesign: ## Refresh Impression & Simplification The new design of logging is much more information centralized and streamlined. * Given a `ready` message at the begining when compilers are bootstrapped. * Only show `compiled` event with green check mark indicating succesful compilation, this will merge the unclear `compiling` event which shows `(client and server)` before, now tell you the route compilation info in one line. hello world app ### `next dev` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/9649b340-8241-4756-a2b3-a989f0b74003" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/ee181263-3dd4-40d0-9ffc-819a56b45900" height="120"> ### `next build` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/5db9829a-9ffc-49f0-b030-93ee92f5c248" width="360"> <img src="https://github.com/vercel/next.js/assets/4800338/b9527b83-27c8-4426-9c0d-c0d4072b7d58" width="360"> ### error status #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/00455226-ace7-468b-8d90-0d36bf038489" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/1be8c451-d3f0-465c-9ef7-6b0dde7cff85" height="120"> ## Streamlization If you have customized envs and experiments Next.js will give the brief in the early summary about your network information, env vars, and enabled experimental features <img src="https://github.com/vercel/next.js/assets/4800338/ca1a7409-1532-46cb-850f-687e61e587b2" width="400"> ## Polish ### fetching logging structure #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/97526397-dffe-4736-88ed-e5cbe5e945bd" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/ab77c907-5ab5-48bb-8347-6146d2e60932" width="400"> ### Dedupe Duplicates The logging is moved from `@next/env` to `next` itself, `@next/env` will only notify the invoker that the env is reloaded. Then the duplicated logs for the env reloading cases can be avoid. #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/04799295-e739-4035-87aa-61cec962fc39" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/e29020c9-0031-4bf3-a21b-8b64633f43a2" width="400"> ### Different indicators Use unicode text icons for different situation: * passed -> check mark * warning -> warning * error -> red cross * loading -> circle <img src="https://github.com/vercel/next.js/assets/4800338/715c34bd-298f-4990-a5d7-e12e455ead44" width="400"> Co-authored-by: Tim Neutkens <6324199+timneutkens@users.noreply.github.com>
2023-09-05 13:40:00 +02:00
// Pass down the original message
resolve(stdOut ? message : instance)
}
}
if (typeof opts.onStdout === 'function') {
opts.onStdout(message)
}
if (opts.stdout !== false) {
process.stdout.write(message)
}
}
function handleStderr(data) {
const message = data.toString()
if (typeof opts.onStderr === 'function') {
opts.onStderr(message)
}
if (opts.stderr !== false) {
process.stderr.write(message)
}
}
instance.stderr.on('data', handleStderr)
Redesign nextjs logging (#54713) The current logging styles has been existed for a while, this PR gives a fresh impression for the logging output from Next.js. We want to achieve few new goals that makes the output clean, modernized, sweet 🍫 . Few goals are addressed with this redesign: ## Refresh Impression & Simplification The new design of logging is much more information centralized and streamlined. * Given a `ready` message at the begining when compilers are bootstrapped. * Only show `compiled` event with green check mark indicating succesful compilation, this will merge the unclear `compiling` event which shows `(client and server)` before, now tell you the route compilation info in one line. hello world app ### `next dev` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/9649b340-8241-4756-a2b3-a989f0b74003" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/ee181263-3dd4-40d0-9ffc-819a56b45900" height="120"> ### `next build` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/5db9829a-9ffc-49f0-b030-93ee92f5c248" width="360"> <img src="https://github.com/vercel/next.js/assets/4800338/b9527b83-27c8-4426-9c0d-c0d4072b7d58" width="360"> ### error status #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/00455226-ace7-468b-8d90-0d36bf038489" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/1be8c451-d3f0-465c-9ef7-6b0dde7cff85" height="120"> ## Streamlization If you have customized envs and experiments Next.js will give the brief in the early summary about your network information, env vars, and enabled experimental features <img src="https://github.com/vercel/next.js/assets/4800338/ca1a7409-1532-46cb-850f-687e61e587b2" width="400"> ## Polish ### fetching logging structure #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/97526397-dffe-4736-88ed-e5cbe5e945bd" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/ab77c907-5ab5-48bb-8347-6146d2e60932" width="400"> ### Dedupe Duplicates The logging is moved from `@next/env` to `next` itself, `@next/env` will only notify the invoker that the env is reloaded. Then the duplicated logs for the env reloading cases can be avoid. #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/04799295-e739-4035-87aa-61cec962fc39" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/e29020c9-0031-4bf3-a21b-8b64633f43a2" width="400"> ### Different indicators Use unicode text icons for different situation: * passed -> check mark * warning -> warning * error -> red cross * loading -> circle <img src="https://github.com/vercel/next.js/assets/4800338/715c34bd-298f-4990-a5d7-e12e455ead44" width="400"> Co-authored-by: Tim Neutkens <6324199+timneutkens@users.noreply.github.com>
2023-09-05 13:40:00 +02:00
instance.stdout.on('data', handleStdout)
instance.on('close', () => {
instance.stderr.removeListener('data', handleStderr)
Redesign nextjs logging (#54713) The current logging styles has been existed for a while, this PR gives a fresh impression for the logging output from Next.js. We want to achieve few new goals that makes the output clean, modernized, sweet 🍫 . Few goals are addressed with this redesign: ## Refresh Impression & Simplification The new design of logging is much more information centralized and streamlined. * Given a `ready` message at the begining when compilers are bootstrapped. * Only show `compiled` event with green check mark indicating succesful compilation, this will merge the unclear `compiling` event which shows `(client and server)` before, now tell you the route compilation info in one line. hello world app ### `next dev` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/9649b340-8241-4756-a2b3-a989f0b74003" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/ee181263-3dd4-40d0-9ffc-819a56b45900" height="120"> ### `next build` #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/5db9829a-9ffc-49f0-b030-93ee92f5c248" width="360"> <img src="https://github.com/vercel/next.js/assets/4800338/b9527b83-27c8-4426-9c0d-c0d4072b7d58" width="360"> ### error status #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/00455226-ace7-468b-8d90-0d36bf038489" height="120"> <img src="https://github.com/vercel/next.js/assets/4800338/1be8c451-d3f0-465c-9ef7-6b0dde7cff85" height="120"> ## Streamlization If you have customized envs and experiments Next.js will give the brief in the early summary about your network information, env vars, and enabled experimental features <img src="https://github.com/vercel/next.js/assets/4800338/ca1a7409-1532-46cb-850f-687e61e587b2" width="400"> ## Polish ### fetching logging structure #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/97526397-dffe-4736-88ed-e5cbe5e945bd" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/ab77c907-5ab5-48bb-8347-6146d2e60932" width="400"> ### Dedupe Duplicates The logging is moved from `@next/env` to `next` itself, `@next/env` will only notify the invoker that the env is reloaded. Then the duplicated logs for the env reloading cases can be avoid. #### After vs Before <img src="https://github.com/vercel/next.js/assets/4800338/04799295-e739-4035-87aa-61cec962fc39" width="400"> <img src="https://github.com/vercel/next.js/assets/4800338/e29020c9-0031-4bf3-a21b-8b64633f43a2" width="400"> ### Different indicators Use unicode text icons for different situation: * passed -> check mark * warning -> warning * error -> red cross * loading -> circle <img src="https://github.com/vercel/next.js/assets/4800338/715c34bd-298f-4990-a5d7-e12e455ead44" width="400"> Co-authored-by: Tim Neutkens <6324199+timneutkens@users.noreply.github.com>
2023-09-05 13:40:00 +02:00
instance.stdout.removeListener('data', handleStdout)
if (!didResolve) {
didResolve = true
resolve(undefined)
}
})
2020-05-18 21:24:37 +02:00
instance.on('error', (err) => {
reject(err)
})
})
}
Rename process.env.TURBOPACK -> process.env.TURBOPACK_DEV in test skips (#63665) ## What? Follow-up to #63653. <!-- 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 # --> Closes NEXT-2911
2024-03-25 14:17:56 +01:00
// Launch the app in development mode.
export function launchApp(
dir: string,
port: string | number,
opts?: NextDevOptions
) {
test(integration): allow to run `--turbo` dev server tests dynamically (#42967) This PR is companion to https://github.com/vercel/next.js/pull/42656. Previous PR https://github.com/vercel/next.js/pull/41908 allowed to set up integration / e2e tests spawn `next dev` with `--turbo` as needed. This PR leverages those, change all the tests suites to run with `--turbo`. One additional change is it can be configured dynamically via env variable. Setting env `__INTERNAL_NEXT_DEV_TEST_TURBO_GLOB_MATCH` to glob pattern will selectively enables tests to run with --turbo, normally it'll skip and only current devserver will be used. These changes allow gradual integration between https://github.com/vercel/turbo to next.js. Plan is to run these tests with latest turbopack dev branch. Each time turbopack fixes / implements changes to enable certain set of tests, its CI will change its env variable without manually patching next.js's test cases. Once those change goes to upstream `next-swc` those tests can be permanantly enabled. For those reasons, PR have somewhat verbose changes to touch individual test cases runs devserver. Changed file counts are lot, but mostly identical changes. ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2022-11-24 00:00:49 +01:00
const options = opts ?? {}
const useTurbo = shouldRunTurboDevTest()
return runNextCommandDev(
[
useTurbo ? getTurbopackFlag() : undefined,
dir,
'-p',
port as string,
'--hostname',
'::',
].filter(Boolean),
undefined,
{ ...options, turbo: useTurbo }
)
}
export function nextBuild(
dir: string,
args: string[] = [],
opts: NextOptions = {}
) {
// If the build hasn't requested it to be linted explicitly, disable linting
// if it's not already disabled.
if (!opts.lint && !args.includes('--no-lint')) {
args.push('--no-lint')
}
return runNextCommand(['build', dir, ...args], opts)
}
export function nextLint(
dir: string,
args: string[] = [],
opts: NextOptions = {}
) {
return runNextCommand(['lint', dir, ...args], opts)
}
export function nextTest(
dir: string,
args: string[] = [],
opts: NextOptions = {}
) {
return runNextCommand(['experimental-test', dir, ...args], {
...opts,
env: {
JEST_WORKER_ID: undefined, // Playwright complains about being executed by Jest
...opts.env,
},
})
}
export function nextStart(
dir: string,
port: string | number,
opts: NextDevOptions = {}
) {
return runNextCommandDev(
['start', '-p', port as string, '--hostname', '::', dir],
undefined,
{ ...opts, nextStart: true }
)
}
export function buildTS(
args: string[] = [],
cwd?: string,
env?: any
): Promise<void> {
cwd = cwd || path.dirname(require.resolve('next/package'))
env = { ...process.env, NODE_ENV: undefined, ...env }
return new Promise((resolve, reject) => {
const instance = spawn(
'node',
['--no-deprecation', require.resolve('typescript/lib/tsc'), ...args],
{ cwd, env }
)
let output = ''
2020-05-18 21:24:37 +02:00
const handleData = (chunk) => {
output += chunk.toString()
}
instance.stdout.on('data', handleData)
instance.stderr.on('data', handleData)
2020-05-18 21:24:37 +02:00
instance.on('exit', (code) => {
if (code) {
return reject(new Error('exited with code: ' + code + '\n' + output))
}
resolve()
})
})
}
export async function killProcess(
pid: number,
graceful shutdown (#60059) - Both the standalone server and the `startServer` function it calls attempt to stop the server on `SIGINT` and `SIGTERM` in different ways. This lets `server.js` yield to `startServer` - The cleanup function in `startServer` was not waiting for the server to close before calling `process.exit`. This lets it wait for any in-flight requests to finish processing before exiting the process - Sends `SIGKILL` to the child process in `next dev`, which should have the same effect of immediately shutting down the server on `SIGTERM` or `SIGINT` fixes: #53661 refs: #59551 ------ Previously #59551 attempted to fix #53661, but had broken some tests in the process. It looks like the final commit was also missing an intended change to `utils.ts`. This should fix those issues as well as introduce a new set of tests for the graceful shutdown feature. In the last PR I was squashing and force-pushing updates along the way but it made it difficult to track the changes. This time I'm pushing quite a few commits to make it easier to track the changes and refactors I've made, with the idea that this should be squashed before being merged. <!-- 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 # -->
2024-01-16 18:25:49 +01:00
signal: NodeJS.Signals | number = 'SIGTERM'
): Promise<void> {
return await new Promise((resolve, reject) => {
treeKill(pid, signal, (err) => {
if (err) {
if (
process.platform === 'win32' &&
typeof err.message === 'string' &&
(err.message.includes(`no running instance of the task`) ||
err.message.includes(`not found`))
) {
// Windows throws an error if the process is already dead
//
// Command failed: taskkill /pid 6924 /T /F
// ERROR: The process with PID 6924 (child process of PID 6736) could not be terminated.
// Reason: There is no running instance of the task.
return resolve()
}
return reject(err)
}
resolve()
})
})
}
// Kill a launched app
graceful shutdown (#60059) - Both the standalone server and the `startServer` function it calls attempt to stop the server on `SIGINT` and `SIGTERM` in different ways. This lets `server.js` yield to `startServer` - The cleanup function in `startServer` was not waiting for the server to close before calling `process.exit`. This lets it wait for any in-flight requests to finish processing before exiting the process - Sends `SIGKILL` to the child process in `next dev`, which should have the same effect of immediately shutting down the server on `SIGTERM` or `SIGINT` fixes: #53661 refs: #59551 ------ Previously #59551 attempted to fix #53661, but had broken some tests in the process. It looks like the final commit was also missing an intended change to `utils.ts`. This should fix those issues as well as introduce a new set of tests for the graceful shutdown feature. In the last PR I was squashing and force-pushing updates along the way but it made it difficult to track the changes. This time I'm pushing quite a few commits to make it easier to track the changes and refactors I've made, with the idea that this should be squashed before being merged. <!-- 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 # -->
2024-01-16 18:25:49 +01:00
export async function killApp(
instance?: ChildProcess,
signal: NodeJS.Signals | number = 'SIGKILL'
) {
Improve handling of failed `nextBuild()` calls in test suite (#63717) ## What? Currently `next build` with Turbopack fails to run in certain tests (as expected), the problem with that is that the `afterAll()` calls assume the server was started, which doesn't happen when the build fails, and then causes a timeout that can't be reported if an error happens. This change ensures the error around `server['__app']` doesn't happen. <!-- 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 # --> Closes NEXT-2933
2024-03-27 19:29:16 +01:00
if (!instance) {
return
}
graceful shutdown (#60059) - Both the standalone server and the `startServer` function it calls attempt to stop the server on `SIGINT` and `SIGTERM` in different ways. This lets `server.js` yield to `startServer` - The cleanup function in `startServer` was not waiting for the server to close before calling `process.exit`. This lets it wait for any in-flight requests to finish processing before exiting the process - Sends `SIGKILL` to the child process in `next dev`, which should have the same effect of immediately shutting down the server on `SIGTERM` or `SIGINT` fixes: #53661 refs: #59551 ------ Previously #59551 attempted to fix #53661, but had broken some tests in the process. It looks like the final commit was also missing an intended change to `utils.ts`. This should fix those issues as well as introduce a new set of tests for the graceful shutdown feature. In the last PR I was squashing and force-pushing updates along the way but it made it difficult to track the changes. This time I'm pushing quite a few commits to make it easier to track the changes and refactors I've made, with the idea that this should be squashed before being merged. <!-- 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 # -->
2024-01-16 18:25:49 +01:00
if (
instance?.pid &&
instance.exitCode === null &&
instance.signalCode === null
) {
const exitPromise = once(instance, 'exit')
await killProcess(instance.pid, signal)
await exitPromise
}
}
async function startListen(server: http.Server, port?: number) {
const listenerPromise = new Promise((resolve) => {
server['__socketSet'] = new Set()
const listener = server.listen(port, () => {
resolve(null)
})
listener.on('connection', function (socket) {
server['__socketSet'].add(socket)
socket.on('close', () => {
server['__socketSet'].delete(socket)
})
})
})
await listenerPromise
}
export async function startApp(app: NextServer) {
// force require usage instead of dynamic import in jest
// x-ref: https://github.com/nodejs/node/issues/35889
process.env.__NEXT_TEST_MODE = 'jest'
// TODO: tests that use this should be migrated to use
// the nextStart test function instead as it tests outside
// of jest's context
await app.prepare()
const handler = app.getRequestHandler()
const server = http.createServer(handler)
server['__app'] = app
await startListen(server)
return server
}
Improve handling of failed `nextBuild()` calls in test suite (#63717) ## What? Currently `next build` with Turbopack fails to run in certain tests (as expected), the problem with that is that the `afterAll()` calls assume the server was started, which doesn't happen when the build fails, and then causes a timeout that can't be reported if an error happens. This change ensures the error around `server['__app']` doesn't happen. <!-- 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 # --> Closes NEXT-2933
2024-03-27 19:29:16 +01:00
export async function stopApp(server: http.Server | undefined) {
if (!server) {
return
}
if (server['__app']) {
await server['__app'].close()
2017-05-10 01:24:34 +02:00
}
// Node.js's http::close() prevents new connections from being accepted,
// but doesn't close existing connections and if there are any leftover
// whole process teardown will wait until it's being closed.
// Instead, force close connections since this is teardown fn that we expect
// any connections to be closed already.
server['__socketSet']?.forEach(function (socket) {
if (!socket.closed && !socket.destroyed) {
socket.destroy()
}
})
await promisify(server.close).apply(server)
}
export function waitFor(millis: number) {
2020-05-18 21:24:37 +02:00
return new Promise((resolve) => setTimeout(resolve, millis))
}
2017-05-10 01:24:34 +02:00
export async function startStaticServer(
dir: string,
notFoundFile?: string,
fixedPort?: number
) {
2017-05-10 01:24:34 +02:00
const app = express()
const server = http.createServer(app)
app.use(express.static(dir))
if (notFoundFile) {
app.use((req, res) => {
createReadStream(notFoundFile).pipe(res)
})
}
await startListen(server, fixedPort)
2017-05-10 01:24:34 +02:00
return server
}
export async function startCleanStaticServer(dir: string) {
const app = express()
const server = http.createServer(app)
app.use(express.static(dir, { extensions: ['html'] }))
await startListen(server)
return server
}
/**
* Check for content in 1 second intervals timing out after 30 seconds.
*
* @param {() => Promise<unknown> | unknown} contentFn
* @param {RegExp | string | number} regex
* @param {boolean} hardError
* @param {number} maxRetries
* @returns {Promise<boolean>}
*/
Add support for scrolling to hash fragment (#46995) Adds support for scrolling based on the [hash fragment](https://en.wikipedia.org/wiki/URI_fragment) in client-side navigations for the App Router, mirroring browser behavior. - `#main-content` → scrolls to `id="main-content"` or `name="main-content"` property - `#top` → scrolls to the top of the page, this is a special case in browsers. - no hash → default scroll behavior, layout that changed Fixes NEXT-658 <!-- 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 or adding/fixing 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 # --> fixes #44295 --------- Co-authored-by: JJ Kasper <jj@jjsweb.site>
2023-03-14 13:17:10 +01:00
export async function check(
contentFn: () => any | Promise<any>,
regex: any,
Add support for scrolling to hash fragment (#46995) Adds support for scrolling based on the [hash fragment](https://en.wikipedia.org/wiki/URI_fragment) in client-side navigations for the App Router, mirroring browser behavior. - `#main-content` → scrolls to `id="main-content"` or `name="main-content"` property - `#top` → scrolls to the top of the page, this is a special case in browsers. - no hash → default scroll behavior, layout that changed Fixes NEXT-658 <!-- 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 or adding/fixing 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 # --> fixes #44295 --------- Co-authored-by: JJ Kasper <jj@jjsweb.site>
2023-03-14 13:17:10 +01:00
hardError = true,
maxRetries = 30
) {
let content
2020-05-10 11:36:07 +02:00
let lastErr
Add support for scrolling to hash fragment (#46995) Adds support for scrolling based on the [hash fragment](https://en.wikipedia.org/wiki/URI_fragment) in client-side navigations for the App Router, mirroring browser behavior. - `#main-content` → scrolls to `id="main-content"` or `name="main-content"` property - `#top` → scrolls to the top of the page, this is a special case in browsers. - no hash → default scroll behavior, layout that changed Fixes NEXT-658 <!-- 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 or adding/fixing 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 # --> fixes #44295 --------- Co-authored-by: JJ Kasper <jj@jjsweb.site>
2023-03-14 13:17:10 +01:00
for (let tries = 0; tries < maxRetries; tries++) {
try {
content = await contentFn()
if (typeof regex !== typeof /regex/) {
if (regex === content) {
return true
}
} else if (regex.test(content)) {
// found the content
return true
}
await waitFor(1000)
} catch (err) {
2020-05-10 11:36:07 +02:00
await waitFor(1000)
lastErr = err
}
}
2020-05-10 11:36:07 +02:00
console.error('TIMED OUT CHECK: ', { regex, content, lastErr })
if (hardError) {
Fix CSS not being bundled in app dir (#45787) Currently all import CSS resources, including CSS modules, are imported lazily. This means that they can't be chunked as by definition of "lazy" they can be loaded separately. This PR changes it to always use "eager" so if they're in the same entry, these CSS resources can be chunked together and reduce the total amount of requests. However the downside will be tree shaking, as not all modules in a chunk are used by one entry. Two entries can only share a part of it. Since CSS modules won't have side effects this should be a good trade off. ## Bug - [ ] Related issues linked using `fixes #number` - [x] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <22380829+ijjk@users.noreply.github.com>
2023-03-17 18:38:19 +01:00
throw new Error('TIMED OUT: ' + regex + '\n\n' + content + '\n\n' + lastErr)
}
return false
}
export class File {
path: string
originalContent: string
constructor(path: string) {
this.path = path
this.originalContent = existsSync(this.path)
? readFileSync(this.path, 'utf8')
: null
}
write(content: string) {
if (!this.originalContent) {
this.originalContent = content
}
writeFileSync(this.path, content, 'utf8')
}
replace(pattern: RegExp | string, newValue: string) {
const currentContent = readFileSync(this.path, 'utf8')
if (pattern instanceof RegExp) {
if (!pattern.test(currentContent)) {
throw new Error(
`Failed to replace content.\n\nPattern: ${pattern.toString()}\n\nContent: ${currentContent}`
)
}
} else if (typeof pattern === 'string') {
if (!currentContent.includes(pattern)) {
throw new Error(
`Failed to replace content.\n\nPattern: ${pattern}\n\nContent: ${currentContent}`
)
}
} else {
throw new Error(`Unknown replacement attempt type: ${pattern}`)
}
const newContent = currentContent.replace(pattern, newValue)
this.write(newContent)
}
prepend(str: string) {
const content = readFileSync(this.path, 'utf8')
this.write(str + content)
}
delete() {
unlinkSync(this.path)
}
restore() {
this.write(this.originalContent)
}
}
export async function evaluate(
browser: BrowserInterface,
input: string | Function
) {
if (typeof input === 'function') {
const result = await browser.eval(input)
2020-05-18 21:24:37 +02:00
await new Promise((resolve) => setTimeout(resolve, 30))
return result
} else {
throw new Error(`You must pass a function to be evaluated in the browser.`)
}
}
export async function retry<T>(
fn: () => T | Promise<T>,
duration: number = 3000,
interval: number = 500,
description?: string
): Promise<T> {
if (duration % interval !== 0) {
throw new Error(
`invalid duration ${duration} and interval ${interval} mix, duration must be evenly divisible by interval`
)
}
for (let i = duration; i >= 0; i -= interval) {
try {
return await fn()
} catch (err) {
if (i === 0) {
console.error(
`Failed to retry${
description ? ` ${description}` : ''
} within ${duration}ms`
)
throw err
}
console.warn(
`Retrying${description ? ` ${description}` : ''} in ${interval}ms`
)
await waitFor(interval)
}
}
}
export async function assertHasRedbox(browser: BrowserInterface) {
try {
await retry(
async () => {
const hasRedbox = await evaluate(browser, () => {
return Boolean(
[].slice
.call(document.querySelectorAll('nextjs-portal'))
.find((p) =>
p.shadowRoot.querySelector(
'#nextjs__container_errors_label, #nextjs__container_errors_label'
)
)
)
})
expect(hasRedbox).toBe(true)
},
5000,
200
)
} catch (errorCause) {
const error = new Error('Expected Redbox but found none')
Error.captureStackTrace(error, assertHasRedbox)
throw error
}
}
export async function assertNoRedbox(browser: BrowserInterface) {
Add hasRedbox fix (#60522) ## What? As @leerob and I found in-person when opening #57230 the `hasRedBox()` helper was incorrectly passing when it shouldn't pass in both the true and false case. This PR uses a different approach by waiting 7 seconds before checking, this leaves enough room for HMR / reloads to apply, it doesn't meaningfully slow down the test suite and increases reliability of the check as you can see below in the tests that were previously passing that are no longer passing. I've moved these to skipped tests for landing this PR as I want to avoid further issues being introduced while we fix them. @huozhi will investigate these next week 👍 Failing tests that are temporarily skipped: - https://github.com/vercel/next.js/pull/60522/files#diff-513b477050bf1a620697b4d16bc1e6850282cb54e0609bdc5fd34307bfa9e471R9 - https://github.com/vercel/next.js/pull/60522/files#diff-fa7d7c8c40914005c138d852eaf6a69ac0df51ec77bec548cbc5f0bfbdc8ebc5R25 - https://github.com/vercel/next.js/pull/60522/files#diff-6f9f7dc131416cb17938311939a56d8c0e685a8fe6e8fc0cf5cd04939c74f388R41 - https://github.com/vercel/next.js/pull/60522/files#diff-439830e340a320c56645e9d00aaf0fd0b492ddb90b6d7f9db89458ccc5158eb7R8 - https://github.com/vercel/next.js/pull/60522/files#diff-62938bf5cd4d84f96dde8b6bcb2c8e18099e6dfca269c4302229b79175c0250cR18 - https://github.com/vercel/next.js/pull/60522/files#diff-513b477050bf1a620697b4d16bc1e6850282cb54e0609bdc5fd34307bfa9e471R9 <!-- 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 # --> Closes NEXT-2059
2024-01-15 09:36:44 +01:00
await waitFor(5000)
const hasRedbox = await evaluate(browser, () => {
Add hasRedbox fix (#60522) ## What? As @leerob and I found in-person when opening #57230 the `hasRedBox()` helper was incorrectly passing when it shouldn't pass in both the true and false case. This PR uses a different approach by waiting 7 seconds before checking, this leaves enough room for HMR / reloads to apply, it doesn't meaningfully slow down the test suite and increases reliability of the check as you can see below in the tests that were previously passing that are no longer passing. I've moved these to skipped tests for landing this PR as I want to avoid further issues being introduced while we fix them. @huozhi will investigate these next week 👍 Failing tests that are temporarily skipped: - https://github.com/vercel/next.js/pull/60522/files#diff-513b477050bf1a620697b4d16bc1e6850282cb54e0609bdc5fd34307bfa9e471R9 - https://github.com/vercel/next.js/pull/60522/files#diff-fa7d7c8c40914005c138d852eaf6a69ac0df51ec77bec548cbc5f0bfbdc8ebc5R25 - https://github.com/vercel/next.js/pull/60522/files#diff-6f9f7dc131416cb17938311939a56d8c0e685a8fe6e8fc0cf5cd04939c74f388R41 - https://github.com/vercel/next.js/pull/60522/files#diff-439830e340a320c56645e9d00aaf0fd0b492ddb90b6d7f9db89458ccc5158eb7R8 - https://github.com/vercel/next.js/pull/60522/files#diff-62938bf5cd4d84f96dde8b6bcb2c8e18099e6dfca269c4302229b79175c0250cR18 - https://github.com/vercel/next.js/pull/60522/files#diff-513b477050bf1a620697b4d16bc1e6850282cb54e0609bdc5fd34307bfa9e471R9 <!-- 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 # --> Closes NEXT-2059
2024-01-15 09:36:44 +01:00
return Boolean(
[].slice
.call(document.querySelectorAll('nextjs-portal'))
.find((p) =>
p.shadowRoot.querySelector(
'#nextjs__container_errors_label, #nextjs__container_errors_label'
)
Add hasRedbox fix (#60522) ## What? As @leerob and I found in-person when opening #57230 the `hasRedBox()` helper was incorrectly passing when it shouldn't pass in both the true and false case. This PR uses a different approach by waiting 7 seconds before checking, this leaves enough room for HMR / reloads to apply, it doesn't meaningfully slow down the test suite and increases reliability of the check as you can see below in the tests that were previously passing that are no longer passing. I've moved these to skipped tests for landing this PR as I want to avoid further issues being introduced while we fix them. @huozhi will investigate these next week 👍 Failing tests that are temporarily skipped: - https://github.com/vercel/next.js/pull/60522/files#diff-513b477050bf1a620697b4d16bc1e6850282cb54e0609bdc5fd34307bfa9e471R9 - https://github.com/vercel/next.js/pull/60522/files#diff-fa7d7c8c40914005c138d852eaf6a69ac0df51ec77bec548cbc5f0bfbdc8ebc5R25 - https://github.com/vercel/next.js/pull/60522/files#diff-6f9f7dc131416cb17938311939a56d8c0e685a8fe6e8fc0cf5cd04939c74f388R41 - https://github.com/vercel/next.js/pull/60522/files#diff-439830e340a320c56645e9d00aaf0fd0b492ddb90b6d7f9db89458ccc5158eb7R8 - https://github.com/vercel/next.js/pull/60522/files#diff-62938bf5cd4d84f96dde8b6bcb2c8e18099e6dfca269c4302229b79175c0250cR18 - https://github.com/vercel/next.js/pull/60522/files#diff-513b477050bf1a620697b4d16bc1e6850282cb54e0609bdc5fd34307bfa9e471R9 <!-- 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 # --> Closes NEXT-2059
2024-01-15 09:36:44 +01:00
)
)
})
if (hasRedbox) {
const error = new Error('Expected no Redbox but found one')
Error.captureStackTrace(error, assertHasRedbox)
throw error
}
}
export async function hasErrorToast(
browser: BrowserInterface
): Promise<boolean> {
return browser.eval(() => {
return Boolean(
Array.from(document.querySelectorAll('nextjs-portal')).find((p) =>
p.shadowRoot.querySelector('[data-nextjs-toast]')
)
)
})
}
export async function waitForAndOpenRuntimeError(browser: BrowserInterface) {
return browser.waitForElementByCss('[data-nextjs-toast]').click()
}
export async function getRedboxHeader(browser: BrowserInterface) {
return retry(
() => {
return evaluate(browser, () => {
const portal = [].slice
.call(document.querySelectorAll('nextjs-portal'))
.find((p) =>
p.shadowRoot.querySelector('[data-nextjs-dialog-header]')
)
const root = portal?.shadowRoot
return root?.querySelector('[data-nextjs-dialog-header]')?.innerText
})
},
10000,
500,
'getRedboxHeader'
)
}
export async function getRedboxTotalErrorCount(browser: BrowserInterface) {
return parseInt(
(await getRedboxHeader(browser)).match(/\d+ of (\d+) error/)?.[1],
10
)
}
export async function getRedboxSource(browser: BrowserInterface) {
return retry(
() =>
evaluate(browser, () => {
const portal = [].slice
.call(document.querySelectorAll('nextjs-portal'))
.find((p) =>
p.shadowRoot.querySelector(
'#nextjs__container_errors_label, #nextjs__container_errors_label'
)
)
const root = portal.shadowRoot
return root.querySelector(
'[data-nextjs-codeframe], [data-nextjs-terminal]'
).innerText
}),
10000,
500,
'getRedboxSource'
)
}
export async function getRedboxDescription(browser: BrowserInterface) {
return retry(
() =>
evaluate(browser, () => {
const portal = [].slice
.call(document.querySelectorAll('nextjs-portal'))
.find((p) =>
p.shadowRoot.querySelector('[data-nextjs-dialog-header]')
)
const root = portal.shadowRoot
const text = root.querySelector(
'#nextjs__container_errors_desc'
).innerText
if (text === null) throw new Error('No redbox description found')
return text
}),
3000,
500,
'getRedboxDescription'
)
}
DX: display highlited pesudo html when bad nesting html error occurred (#62590) ### What When you have bad nesting html in your React code, React wil raise hydration error since the browser html parser might parse it to sth else different comparing to server html on client. Previously we're display only the warning in the error description in dev overlay. Now we introduced another format of displaying pesudo html that representing your code, with highlighting the html tag that causes the error. Since React might gives you the whole component stack of React tree, so we also introduced a way that can collapse the error. #### Example https://github.com/vercel/next.js/assets/4800338/622122d6-4d2e-4c8e-95e8-4864343e478b ### Why The reason we added this is that even we show the html diff, it could super large due to React ordering the html on client, so the mismatch might be a lot. The idea here is similar to what you saw when you passed down a bad event handler into server component, we displayed a pesudo html as it could hit your mind faster than just seeing the warning. The best way is to display the source code, but before we can show the source, getting component stack display as pseudo html instead of here could be more helpful. ### After vs Before <img width="400" src="https://github.com/vercel/next.js/assets/4800338/714119ad-ff23-46a9-bc5a-5601eb390e71"> <img width="400" src="https://github.com/vercel/next.js/assets/4800338/575f95fa-889e-4cee-ad19-9c2fea06519a"> Closes NEXT-2621
2024-02-28 16:14:48 +01:00
export async function getRedboxDescriptionWarning(browser: BrowserInterface) {
return retry(
() =>
evaluate(browser, () => {
const portal = [].slice
.call(document.querySelectorAll('nextjs-portal'))
.find((p) =>
p.shadowRoot.querySelector('[data-nextjs-dialog-header]')
)
const root = portal.shadowRoot
const text = root.querySelector(
'#nextjs__container_errors__notes'
DX: display highlited pesudo html when bad nesting html error occurred (#62590) ### What When you have bad nesting html in your React code, React wil raise hydration error since the browser html parser might parse it to sth else different comparing to server html on client. Previously we're display only the warning in the error description in dev overlay. Now we introduced another format of displaying pesudo html that representing your code, with highlighting the html tag that causes the error. Since React might gives you the whole component stack of React tree, so we also introduced a way that can collapse the error. #### Example https://github.com/vercel/next.js/assets/4800338/622122d6-4d2e-4c8e-95e8-4864343e478b ### Why The reason we added this is that even we show the html diff, it could super large due to React ordering the html on client, so the mismatch might be a lot. The idea here is similar to what you saw when you passed down a bad event handler into server component, we displayed a pesudo html as it could hit your mind faster than just seeing the warning. The best way is to display the source code, but before we can show the source, getting component stack display as pseudo html instead of here could be more helpful. ### After vs Before <img width="400" src="https://github.com/vercel/next.js/assets/4800338/714119ad-ff23-46a9-bc5a-5601eb390e71"> <img width="400" src="https://github.com/vercel/next.js/assets/4800338/575f95fa-889e-4cee-ad19-9c2fea06519a"> Closes NEXT-2621
2024-02-28 16:14:48 +01:00
)?.innerText
return text
}),
3000,
500,
'getRedboxDescriptionWarning'
)
}
export function getBrowserBodyText(browser: BrowserInterface) {
return browser.eval('document.getElementsByTagName("body")[0].innerText')
}
export function normalizeRegEx(src: string) {
return new RegExp(src).source.replace(/\^\//g, '^\\/')
}
function readJson(path: string) {
return JSON.parse(readFileSync(path, 'utf-8'))
}
export function getBuildManifest(dir: string) {
return readJson(path.join(dir, '.next/build-manifest.json'))
}
export function getPageFileFromBuildManifest(dir: string, page: string) {
const buildManifest = getBuildManifest(dir)
const pageFiles = buildManifest.pages[page]
if (!pageFiles) {
throw new Error(`No files for page ${page}`)
}
const pageFile = pageFiles[pageFiles.length - 1]
expect(pageFile).toEndWith('.js')
if (!process.env.TURBOPACK) {
expect(pageFile).toInclude(`pages${page === '' ? '/index' : page}`)
}
if (!pageFile) {
throw new Error(`No page file for page ${page}`)
}
return pageFile
}
export function readNextBuildClientPageFile(appDir: string, page: string) {
const pageFile = getPageFileFromBuildManifest(appDir, page)
return readFileSync(path.join(appDir, '.next', pageFile), 'utf8')
}
export function getPagesManifest(dir: string) {
const serverFile = path.join(dir, '.next/server/pages-manifest.json')
return readJson(serverFile)
}
export function updatePagesManifest(dir: string, content: any) {
const serverFile = path.join(dir, '.next/server/pages-manifest.json')
return writeFile(serverFile, content)
}
export function getPageFileFromPagesManifest(dir: string, page: string) {
const pagesManifest = getPagesManifest(dir)
const pageFile = pagesManifest[page]
if (!pageFile) {
throw new Error(`No file for page ${page}`)
}
return pageFile
}
export function readNextBuildServerPageFile(appDir: string, page: string) {
const pageFile = getPageFileFromPagesManifest(appDir, page)
return readFileSync(path.join(appDir, '.next', 'server', pageFile), 'utf8')
}
function runSuite(
suiteName: string,
context: { env: 'prod' | 'dev'; appDir: string } & Partial<{
stderr: string
stdout: string
appPort: number
code: number
server: ChildProcess
}>,
options: {
beforeAll?: Function
afterAll?: Function
runTests: Function
} & NextDevOptions
) {
const { appDir, env } = context
describe(`${suiteName} ${env}`, () => {
beforeAll(async () => {
options.beforeAll?.(env)
context.stderr = ''
const onStderr = (msg) => {
context.stderr += msg
}
context.stdout = ''
const onStdout = (msg) => {
context.stdout += msg
}
if (env === 'prod') {
context.appPort = await findPort()
const { stdout, stderr, code } = await nextBuild(appDir, [], {
stderr: true,
stdout: true,
env: options.env || {},
nodeArgs: options.nodeArgs,
})
context.stdout = stdout
context.stderr = stderr
context.code = code
context.server = await nextStart(context.appDir, context.appPort, {
onStderr,
onStdout,
env: options.env || {},
nodeArgs: options.nodeArgs,
})
} else if (env === 'dev') {
context.appPort = await findPort()
context.server = await launchApp(context.appDir, context.appPort, {
onStderr,
onStdout,
env: options.env || {},
nodeArgs: options.nodeArgs,
})
}
})
afterAll(async () => {
options.afterAll?.(env)
if (context.server) {
await killApp(context.server)
}
})
options.runTests(context, env)
})
}
export function runDevSuite(
suiteName: string,
appDir: string,
options: {
beforeAll?: Function
afterAll?: Function
runTests: Function
env?: NodeJS.ProcessEnv
}
) {
return runSuite(suiteName, { appDir, env: 'dev' }, options)
}
export function runProdSuite(
suiteName: string,
appDir: string,
options: {
beforeAll?: Function
afterAll?: Function
runTests: Function
env?: NodeJS.ProcessEnv
}
) {
Rename process.env.TURBOPACK -> process.env.TURBOPACK_DEV in test skips (#63665) ## What? Follow-up to #63653. <!-- 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 # --> Closes NEXT-2911
2024-03-25 14:17:56 +01:00
;(process.env.TURBOPACK_DEV ? describe.skip : describe)(
'production mode',
() => {
runSuite(suiteName, { appDir, env: 'prod' }, options)
}
)
}
/**
* Parse the output and return all entries that match the provided `eventName`
* @param {string} output output of the console
* @param {string} eventName
* @returns {Array<{}>}
*/
export function findAllTelemetryEvents(output: string, eventName: string) {
const regex = /\[telemetry\] ({.+?^})/gms
// Pop the last element of each entry to retrieve contents of the capturing group
const events = [...output.matchAll(regex)].map((entry) =>
JSON.parse(entry.pop())
)
return events.filter((e) => e.eventName === eventName).map((e) => e.payload)
}
test(integration): allow to run `--turbo` dev server tests dynamically (#42967) This PR is companion to https://github.com/vercel/next.js/pull/42656. Previous PR https://github.com/vercel/next.js/pull/41908 allowed to set up integration / e2e tests spawn `next dev` with `--turbo` as needed. This PR leverages those, change all the tests suites to run with `--turbo`. One additional change is it can be configured dynamically via env variable. Setting env `__INTERNAL_NEXT_DEV_TEST_TURBO_GLOB_MATCH` to glob pattern will selectively enables tests to run with --turbo, normally it'll skip and only current devserver will be used. These changes allow gradual integration between https://github.com/vercel/turbo to next.js. Plan is to run these tests with latest turbopack dev branch. Each time turbopack fixes / implements changes to enable certain set of tests, its CI will change its env variable without manually patching next.js's test cases. Once those change goes to upstream `next-swc` those tests can be permanantly enabled. For those reasons, PR have somewhat verbose changes to touch individual test cases runs devserver. Changed file counts are lot, but mostly identical changes. ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
2022-11-24 00:00:49 +01:00
type TestVariants = 'default' | 'turbo'
// WEB-168: There are some differences / incompletes in turbopack implementation enforces jest requires to update
// test snapshot when run against turbo. This fn returns describe, or describe.skip dependes on the running context
// to avoid force-snapshot update per each runs until turbopack update includes all the changes.
export function getSnapshotTestDescribe(variant: TestVariants) {
const runningEnv = variant ?? 'default'
if (runningEnv !== 'default' && runningEnv !== 'turbo') {
throw new Error(
`An invalid test env was passed: ${variant} (only "default" and "turbo" are valid options)`
)
}
const shouldRunTurboDev = shouldRunTurboDevTest()
const shouldSkip =
(runningEnv === 'turbo' && !shouldRunTurboDev) ||
(runningEnv === 'default' && shouldRunTurboDev)
return shouldSkip ? describe.skip : describe
}
export async function getRedboxComponentStack(
browser: BrowserInterface
): Promise<string> {
await browser.waitForElementByCss(
feat: display text diff for text mismatch hydration errors (#62684) ### What Keep improving the hydration erros. Currently we divide the hydration mismatch types into two categories, html tag mismatch and text mismatch. We're displaying the mismatched text content between server and client here since we have it in the component stack and warnings. We've already made some improvements in #62590 , here we carry on improving the highlited text into red and bold that is much easier for you to spot on. This updated a few long snapshots that we could collapse and show only the text content difference instead of all the component stack. ### Screenshots (Dark and light modes) #### Mismatch html tags <img width="360" src="https://github.com/vercel/next.js/assets/4800338/f721b374-69cc-4600-a09d-bef87e885fab"><img width="360" src="https://github.com/vercel/next.js/assets/4800338/1abf2572-2be8-4359-a652-8ba39aaccfd3"> #### Mismatch text content <img width="360" src="https://github.com/vercel/next.js/assets/4800338/7f0d2215-8bc0-4fba-9c92-6c44efa29531"><img width="360" src="https://github.com/vercel/next.js/assets/4800338/656d1e1a-3157-4bcf-a239-74bb81fcb4c4"> #### Large content mismatch ### Why I was intended to bring a html diff between server and client html content but turns out the diff result could be giant and not ideal due to few reasons. So we switched to the path of leveraging component stack and mismatch contents. React reordering the tags after hydration. For instance the `script` or `link` tags could be hoist by React Float, so the lines of html is are to preserved. so the diff is hard to be super accurate unless your mismatch is small. If you're mismatch a component with rich html content, it could be a pretty large diff. Another case is if you have a bad nesting html like `<p> ...<span>... <p>my text</p> ...</span>... <p>` where there're many span in between, the final different could also be hudge as browser will close the first `<p>` tag and the rest content will go into the diff. Hence we're going with the component and text content diff. Closes NEXT-2645
2024-02-29 23:36:38 +01:00
'[data-nextjs-container-errors-pseudo-html] code',
30000
)
// TODO: the type for elementsByCss is incorrect
const componentStackFrameElements: any = await browser.elementsByCss(
feat: display text diff for text mismatch hydration errors (#62684) ### What Keep improving the hydration erros. Currently we divide the hydration mismatch types into two categories, html tag mismatch and text mismatch. We're displaying the mismatched text content between server and client here since we have it in the component stack and warnings. We've already made some improvements in #62590 , here we carry on improving the highlited text into red and bold that is much easier for you to spot on. This updated a few long snapshots that we could collapse and show only the text content difference instead of all the component stack. ### Screenshots (Dark and light modes) #### Mismatch html tags <img width="360" src="https://github.com/vercel/next.js/assets/4800338/f721b374-69cc-4600-a09d-bef87e885fab"><img width="360" src="https://github.com/vercel/next.js/assets/4800338/1abf2572-2be8-4359-a652-8ba39aaccfd3"> #### Mismatch text content <img width="360" src="https://github.com/vercel/next.js/assets/4800338/7f0d2215-8bc0-4fba-9c92-6c44efa29531"><img width="360" src="https://github.com/vercel/next.js/assets/4800338/656d1e1a-3157-4bcf-a239-74bb81fcb4c4"> #### Large content mismatch ### Why I was intended to bring a html diff between server and client html content but turns out the diff result could be giant and not ideal due to few reasons. So we switched to the path of leveraging component stack and mismatch contents. React reordering the tags after hydration. For instance the `script` or `link` tags could be hoist by React Float, so the lines of html is are to preserved. so the diff is hard to be super accurate unless your mismatch is small. If you're mismatch a component with rich html content, it could be a pretty large diff. Another case is if you have a bad nesting html like `<p> ...<span>... <p>my text</p> ...</span>... <p>` where there're many span in between, the final different could also be hudge as browser will close the first `<p>` tag and the rest content will go into the diff. Hence we're going with the component and text content diff. Closes NEXT-2645
2024-02-29 23:36:38 +01:00
'[data-nextjs-container-errors-pseudo-html] code'
)
const componentStackFrameTexts = await Promise.all(
componentStackFrameElements.map((f) => f.innerText())
)
Use snapshots for component-stack tests (#60768) ### What? Follow-up to #60579 and #60750. Checking `startsWith` is not enough because it hides the rest of the stack. Changed the test to check the snapshot for Turbopack and webpack. Fixes a bug where the stack lines showed `http (NaN:NaN)` as the source lines. Added support for source lines that don't have a open in editor. <!-- 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 # --> Closes NEXT-2128
2024-01-18 13:44:03 +01:00
return componentStackFrameTexts.join('\n').trim()
}
export async function toggleCollapseComponentStack(
DX: display highlited pesudo html when bad nesting html error occurred (#62590) ### What When you have bad nesting html in your React code, React wil raise hydration error since the browser html parser might parse it to sth else different comparing to server html on client. Previously we're display only the warning in the error description in dev overlay. Now we introduced another format of displaying pesudo html that representing your code, with highlighting the html tag that causes the error. Since React might gives you the whole component stack of React tree, so we also introduced a way that can collapse the error. #### Example https://github.com/vercel/next.js/assets/4800338/622122d6-4d2e-4c8e-95e8-4864343e478b ### Why The reason we added this is that even we show the html diff, it could super large due to React ordering the html on client, so the mismatch might be a lot. The idea here is similar to what you saw when you passed down a bad event handler into server component, we displayed a pesudo html as it could hit your mind faster than just seeing the warning. The best way is to display the source code, but before we can show the source, getting component stack display as pseudo html instead of here could be more helpful. ### After vs Before <img width="400" src="https://github.com/vercel/next.js/assets/4800338/714119ad-ff23-46a9-bc5a-5601eb390e71"> <img width="400" src="https://github.com/vercel/next.js/assets/4800338/575f95fa-889e-4cee-ad19-9c2fea06519a"> Closes NEXT-2621
2024-02-28 16:14:48 +01:00
browser: BrowserInterface
): Promise<void> {
await browser
.elementByCss('[data-nextjs-container-errors-pseudo-html-collapse]')
.click()
}
export async function expandCallStack(
browser: BrowserInterface
): Promise<void> {
// Open full Call Stack
await browser
.elementByCss('[data-nextjs-data-runtime-error-collapsed-action]')
.click()
}
export async function getRedboxCallStack(
browser: BrowserInterface
): Promise<string> {
await browser.waitForElementByCss('[data-nextjs-call-stack-frame]', 30000)
const callStackFrameElements: any = await browser.elementsByCss(
'[data-nextjs-call-stack-frame]'
)
const callStackFrameTexts = await Promise.all(
callStackFrameElements.map((f) => f.innerText())
)
return callStackFrameTexts.join('\n').trim()
}
export async function getVersionCheckerText(
browser: BrowserInterface
): Promise<string> {
await browser.waitForElementByCss('[data-nextjs-version-checker]', 30000)
const versionCheckerElement = await browser.elementByCss(
'[data-nextjs-version-checker]'
)
const versionCheckerText = await versionCheckerElement.innerText()
return versionCheckerText.trim()
}
export function colorToRgb(color) {
switch (color) {
case 'blue':
return 'rgb(0, 0, 255)'
case 'red':
return 'rgb(255, 0, 0)'
case 'green':
return 'rgb(0, 128, 0)'
case 'yellow':
return 'rgb(255, 255, 0)'
case 'purple':
return 'rgb(128, 0, 128)'
case 'black':
return 'rgb(0, 0, 0)'
default:
throw new Error('Unknown color')
}
}
export function getUrlFromBackgroundImage(backgroundImage: string) {
const matches = backgroundImage.match(/url\("[^)]+"\)/g).map((match) => {
// Extract the URL part from each match. The match includes 'url("' and '"")', so we remove those.
return match.slice(5, -2)
})
return matches
}
/**
* For better editor support, pass in the variants this should run on (`default` and/or `turbo`) as cases.
*
* This is necessary if separate snapshots are needed for next.js with webpack vs turbopack.
*/
export const describeVariants = {
each(variants: TestVariants[]) {
return (name: string, fn: (variants: TestVariants) => any) => {
if (
!Array.isArray(variants) ||
!variants.every((val) => typeof val === 'string')
) {
throw new Error('variants need to be an array of strings')
}
for (const variant of variants) {
getSnapshotTestDescribe(variant).each([variant])(name, fn)
}
}
},
}
export const getTitle = (browser: BrowserInterface) =>
browser.elementByCss('title').text()
async function checkMeta(
browser: BrowserInterface,
queryValue: string,
expected: RegExp | string | string[] | undefined | null,
queryKey: string = 'property',
tag: string = 'meta',
domAttributeField: string = 'content'
) {
const values = await browser.eval(
`[...document.querySelectorAll('${tag}[${queryKey}="${queryValue}"]')].map((el) => el.getAttribute("${domAttributeField}"))`
)
if (expected instanceof RegExp) {
expect(values[0]).toMatch(expected)
} else {
if (Array.isArray(expected)) {
expect(values).toEqual(expected)
} else {
// If expected is undefined, then it should not exist.
// Otherwise, it should exist in the matched values.
if (expected === undefined) {
expect(values).not.toContain(undefined)
} else {
expect(values).toContain(expected)
}
}
}
}
export function createDomMatcher(browser: BrowserInterface) {
/**
* @param tag - tag name, e.g. 'meta'
* @param query - query string, e.g. 'name="description"'
* @param expectedObject - expected object, e.g. { content: 'my description' }
* @returns {Promise<void>} - promise that resolves when the check is done
*
* @example
* const matchDom = createDomMatcher(browser)
* await matchDom('meta', 'name="description"', { content: 'description' })
*/
return async (
tag: string,
query: string,
expectedObject: Record<string, string | null | undefined>
) => {
const props = await browser.eval(`
const el = document.querySelector('${tag}[${query}]');
const res = {}
const keys = ${JSON.stringify(Object.keys(expectedObject))}
for (const k of keys) {
res[k] = el?.getAttribute(k)
}
res
`)
expect(props).toEqual(expectedObject)
}
}
export function createMultiHtmlMatcher($: ReturnType<typeof cheerio.load>) {
/**
* @param tag - tag name, e.g. 'meta'
* @param queryKey - query key, e.g. 'property'
* @param domAttributeField - dom attribute field, e.g. 'content'
* @param expected - expected object, e.g. { description: 'my description' }
* @returns {void} - void when the check is done
*
* @example
*
* const $ = await next.render$('html')
* const matchHtml = createMultiHtmlMatcher($)
* matchHtml('meta', 'name', 'property', {
* description: 'description',
* og: 'og:description'
* })
*
*/
return (
tag: string,
queryKey: string,
domAttributeField: string,
expected: Record<string, string | string[] | undefined>
) => {
const res = {}
for (const key of Object.keys(expected)) {
const el = $(`${tag}[${queryKey}="${key}"]`)
if (el.length > 1) {
res[key] = el.toArray().map((el) => el.attribs[domAttributeField])
} else {
res[key] = el.attr(domAttributeField)
}
}
expect(res).toEqual(expected)
}
}
export function createMultiDomMatcher(browser: BrowserInterface) {
/**
* @param tag - tag name, e.g. 'meta'
* @param queryKey - query key, e.g. 'property'
* @param domAttributeField - dom attribute field, e.g. 'content'
* @param expected - expected object, e.g. { description: 'my description' }
* @returns {Promise<void>} - promise that resolves when the check is done
*
* @example
* const matchMultiDom = createMultiDomMatcher(browser)
* await matchMultiDom('meta', 'property', 'content', {
* description: 'description',
* 'og:title': 'title',
* 'twitter:title': 'title'
* })
*
*/
return async (
tag: string,
queryKey: string,
domAttributeField: string,
expected: Record<string, string | string[] | undefined | null>
) => {
await Promise.all(
Object.keys(expected).map(async (key) => {
return checkMeta(
browser,
key,
expected[key],
queryKey,
tag,
domAttributeField
)
})
)
}
}
export const checkMetaNameContentPair = (
browser: BrowserInterface,
name: string,
content: string | string[]
) => checkMeta(browser, name, content, 'name')
export const checkLink = (
browser: BrowserInterface,
rel: string,
content: string | string[]
) => checkMeta(browser, rel, content, 'rel', 'link', 'href')