rsnext/test/lib/next-modes/next-dev.ts
Jiachi Liu a8a199ec03
test: fix flaky tests and disabled constant failing ones (#65822)
In `test/production/graceful-shutdown/index.test.ts`, 2 tests cases are
always failing, disabled them for now to investigate later.

In
`test/e2e/app-dir/actions-allowed-origins/app-action-allowed-origins.test.ts`,
the hard-coded `port` was used sometimes already been used, so we change
that to a "random" port which can help find an available port instead of
`'0'`.

Co-authored-by: JJ Kasper <jj@jjsweb.site>
2024-05-16 15:05:28 +02:00

129 lines
3.6 KiB
TypeScript

import spawn from 'cross-spawn'
import { Span } from 'next/dist/trace'
import { NextInstance } from './base'
import { getTurbopackFlag } from '../turbo'
import stripAnsi from 'strip-ansi'
export class NextDevInstance extends NextInstance {
private _cliOutput: string = ''
public get buildId() {
return 'development'
}
public async setup(parentSpan: Span) {
super.setup(parentSpan)
await super.createTestDir({ parentSpan })
}
public get cliOutput() {
return this._cliOutput || ''
}
public async start(useDirArg: boolean = false) {
if (this.childProcess) {
throw new Error('next already started')
}
const useTurbo =
!process.env.TEST_WASM &&
((this as any).turbo || (this as any).experimentalTurbo)
let startArgs = [
'pnpm',
'next',
useTurbo ? getTurbopackFlag() : undefined,
useDirArg && this.testDir,
].filter(Boolean) as string[]
if (this.startCommand) {
startArgs = this.startCommand.split(' ')
}
if (process.env.NEXT_SKIP_ISOLATE) {
// without isolation yarn can't be used and pnpm must be used instead
if (startArgs[0] === 'yarn') {
startArgs[0] = 'pnpm'
}
}
console.log('running', startArgs.join(' '))
await new Promise<void>((resolve, reject) => {
try {
this.childProcess = spawn(startArgs[0], startArgs.slice(1), {
cwd: useDirArg ? process.cwd() : this.testDir,
stdio: ['ignore', 'pipe', 'pipe'],
shell: false,
env: {
...process.env,
...this.env,
NODE_ENV: this.env.NODE_ENV || ('' as any),
PORT: this.forcedPort || '0',
__NEXT_TEST_MODE: 'e2e',
__NEXT_TEST_WITH_DEVTOOL: '1',
},
})
this._cliOutput = ''
this.childProcess.stdout.on('data', (chunk) => {
const msg = chunk.toString()
if (!process.env.CI) process.stdout.write(chunk)
this._cliOutput += msg
this.emit('stdout', [msg])
})
this.childProcess.stderr.on('data', (chunk) => {
const msg = chunk.toString()
if (!process.env.CI) process.stderr.write(chunk)
this._cliOutput += msg
this.emit('stderr', [msg])
})
this.childProcess.on('close', (code, signal) => {
if (this.isStopping) return
if (code || signal) {
require('console').error(
`next dev exited unexpectedly with code/signal ${code || signal}`
)
}
})
const readyCb = (msg) => {
const resolveServer = () => {
try {
this._parsedUrl = new URL(this._url)
} catch (err) {
reject({
err,
msg,
})
}
// server might reload so we keep listening
resolve()
}
const colorStrippedMsg = stripAnsi(msg)
if (colorStrippedMsg.includes('- Local:')) {
this._url = msg
.split('\n')
.find((line) => line.includes('- Local:'))
.split(/\s*- Local:/)
.pop()
.trim()
resolveServer()
} else if (
msg.includes('started server on') &&
msg.includes('url:')
) {
this._url = msg.split('url: ').pop().split(/\s/, 1)[0].trim()
resolveServer()
}
}
this.on('stdout', readyCb)
} catch (err) {
require('console').error(`Failed to run ${startArgs.join(' ')}`, err)
setTimeout(() => process.exit(1), 0)
}
})
}
}