Files
next.js/test/e2e/next-analyze/next-analyze.test.ts
Will Binns-SmithandGitHub 634cfd3312 bundle analyzer: remove custom output option (#87267)
This functionality was added late in #87258 but was broken as we needed
to pass this along to the Rust side. We'd also need to be able to write
to arbitrary absolute paths there, so let's punt on it.

Test Plan: e2e tests
2025-12-17 09:31:47 -08:00

139 lines
3.8 KiB
TypeScript

import { nextTestSetup } from 'e2e-utils'
import { runNextCommand, shouldUseTurbopack } from 'next-test-utils'
import path from 'node:path'
import { ChildProcess, spawn } from 'node:child_process'
import { existsSync, readFileSync } from 'node:fs'
describe('next experimental-analyze', () => {
if (!shouldUseTurbopack()) {
// Test suites require at least one test
it('skips in non-Turbopack tests', () => {})
return
}
const { next, skipped } = nextTestSetup({
files: __dirname,
skipStart: true,
skipDeployment: true,
})
if (skipped) {
// Test suites require at least one test
it('is skipped', () => {})
return
}
it('runs successfully without errors', async () => {
const nextDir = path.dirname(require.resolve('next/package'))
const nextBin = path.join(nextDir, 'dist/bin/next')
const serveProcess = spawn(
'node',
[nextBin, 'experimental-analyze', '--port', '0'],
{
cwd: next.testDir,
stdio: ['ignore', 'pipe', 'pipe'],
}
)
try {
const url = await waitForServer(serveProcess)
const response = await fetch(url)
expect(response.status).toBe(200)
expect(await response.text()).toContain(
'<title>Next.js Bundle Analyzer</title>'
)
} finally {
serveProcess.kill()
}
})
;['-o', '--output'].forEach((flag) => {
describe(`with ${flag} flag`, () => {
it('writes output to .next/diagnostics/analyze path', async () => {
const defaultOutputPath = path.join(
next.testDir,
'.next/diagnostics/analyze'
)
const { code, stderr, stdout } = await runNextCommand(
['experimental-analyze', flag],
{
cwd: next.testDir,
stderr: true,
stdout: true,
}
)
expect(code).toBe(0)
expect(stderr).not.toContain('Error')
expect(stdout).toContain('.next/diagnostics/analyze')
expect(existsSync(defaultOutputPath)).toBe(true)
for (const file of [
'index.html',
'data/routes.json',
'data/modules.data',
'data/analyze.data',
]) {
expect(existsSync(path.join(defaultOutputPath, file))).toBe(true)
}
const routesJson = readFileSync(
path.join(defaultOutputPath, 'data', 'routes.json'),
'utf-8'
)
const routes = JSON.parse(routesJson)
expect(routes).toEqual(['/', '/_not-found'])
})
})
})
})
function waitForServer(process: ChildProcess, timeoutMs: number = 30000) {
const serverUrlPromise = new Promise<string>((resolve, reject) => {
const timeout = setTimeout(() => {
process.stdout.off('data', onStdout)
process.off('error', onError)
process.off('exit', onExit)
reject(new Error('Server did not start within timeout'))
}, timeoutMs)
function onStdout(data: Buffer) {
const urlMatch = data.toString().match(/http:\/\/[^\s]+/)
if (urlMatch) {
clearTimeout(timeout)
process.stdout.off('data', onStdout)
process.off('error', onError)
process.off('exit', onExit)
resolve(urlMatch[0])
}
}
function onError(error: Error) {
clearTimeout(timeout)
process.stdout.off('data', onStdout)
process.off('error', onError)
process.off('exit', onExit)
reject(error)
}
function onExit(code: number) {
clearTimeout(timeout)
process.stdout.off('data', onStdout)
process.off('error', onError)
process.off('exit', onExit)
reject(
new Error(
`Server process exited with code ${code} before URL was emitted`
)
)
}
process.stdout.on('data', onStdout)
process.on('error', onError)
process.on('exit', onExit)
})
return serverUrlPromise
}