mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
The test was calling `createNext` inside each `it.each` test body, which meant deployment setup time counted against the 60-second per-test timeout introduced in #89929. In deploy mode, `createNext` deploys to Vercel which can exceed 60 seconds. When the test timed out, the `next` local variable was never assigned (the `await createNext(...)` hadn't resolved), so the `afterEach` hook would throw a `TypeError` on `next.destroy()`. This left the module-level `nextInstance` variable pointing at the stale, half-initialized deploy instance. When the next test case started, `createNext` saw the leftover `nextInstance` and threw `"createNext called without destroying previous instance"`. The test now uses `nextTestSetup`, which runs `createNext` in `beforeAll` where it has the longer 120-second `setupTimeout`. Both API route variants (`/api/single` and `/api/multiple`) are real fixture files served from a single instance, so deployment only happens once.
72 lines
2.0 KiB
TypeScript
72 lines
2.0 KiB
TypeScript
import { nextTestSetup } from 'e2e-utils'
|
|
import { fetchViaHTTP } from 'next-test-utils'
|
|
|
|
describe('edge api can use async local storage', () => {
|
|
const { next } = nextTestSetup({
|
|
files: __dirname,
|
|
})
|
|
|
|
const cases = [
|
|
{
|
|
title: 'a single instance',
|
|
route: '/api/single',
|
|
expectResponse: (response: any, id: string) =>
|
|
expect(response).toMatchObject({ status: 200, json: { id } }),
|
|
},
|
|
{
|
|
title: 'multiple instances',
|
|
route: '/api/multiple',
|
|
expectResponse: (response: any, id: string) =>
|
|
expect(response).toMatchObject({
|
|
status: 200,
|
|
json: { id: id, nestedId: `nested-${id}` },
|
|
}),
|
|
},
|
|
]
|
|
|
|
it.each(cases)(
|
|
'can use $title per request',
|
|
async ({ route, expectResponse }) => {
|
|
const ids = Array.from({ length: 100 }, (_, i) => `req-${i}`)
|
|
|
|
const responses = await Promise.all(
|
|
ids.map((id) =>
|
|
fetchViaHTTP(next.url, route, {}, { headers: { 'req-id': id } }).then(
|
|
(response) =>
|
|
response.headers
|
|
.get('content-type')
|
|
?.startsWith('application/json')
|
|
? response.json().then((json) => ({
|
|
status: response.status,
|
|
json,
|
|
text: null,
|
|
}))
|
|
: response.text().then((text) => ({
|
|
status: response.status,
|
|
json: null,
|
|
text,
|
|
}))
|
|
)
|
|
)
|
|
)
|
|
const rankById = new Map(ids.map((id, rank) => [id, rank]))
|
|
|
|
const errors: Error[] = []
|
|
for (const [rank, response] of responses.entries()) {
|
|
try {
|
|
expectResponse(response, ids[rank])
|
|
} catch (error) {
|
|
const received = response.json?.id
|
|
console.log(
|
|
`response #${rank} has id from request #${rankById.get(received)}`
|
|
)
|
|
errors.push(error as Error)
|
|
}
|
|
}
|
|
if (errors.length) {
|
|
throw errors[0]
|
|
}
|
|
}
|
|
)
|
|
})
|