Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions tests/integration/use-cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ describe.skipIf(!nextVersionSatisfies('>=15.3.0-canary.13'))('use cache', () =>
vi.stubEnv('NETLIFY_PURGE_API_TOKEN', 'fake-token')
await startMockBlobStore(ctx as FixtureTestContext)

// we use same fixture for all the tests, which normally cleans up after each test
// but here we want to control cleanup ourselves and only do that after all test suites did run
ctx.skipAutoCleanup = true

await createFixture('use-cache', ctx)
await runPlugin(ctx)
})
Expand Down
4 changes: 3 additions & 1 deletion tests/test-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@ export async function afterTestCleanup({ cleanup }: FixtureTestContext) {

// cleanup after each test as a fallback if someone forgot to call it
afterEach<FixtureTestContext>(async (ctx) => {
await afterTestCleanup(ctx)
if (ctx.skipAutoCleanup !== true) {
await afterTestCleanup(ctx)
}
})
1 change: 1 addition & 0 deletions tests/utils/contexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ export interface FixtureTestContext extends TestContext {
edgeFunctionPort: number
edgeFunctionOutput: WriteStream
cleanup?: (() => Promise<void>)[]
skipAutoCleanup?: boolean
}
41 changes: 41 additions & 0 deletions tests/utils/fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { execaCommand } from 'execa'
import getPort from 'get-port'
import { spawn } from 'node:child_process'
import { createWriteStream, existsSync } from 'node:fs'
import { createRequire } from 'node:module'
import { cp, mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { basename, dirname, join, parse, relative } from 'node:path'
Expand Down Expand Up @@ -37,6 +38,12 @@ const bootstrapURL = await getBootstrapURL()
const actualCwd = await vi.importActual<typeof import('process')>('process').then((p) => p.cwd())
const eszipHelper = join(actualCwd, 'tools/deno/eszip.ts')

const require = createRequire(import.meta.url)
const mod = require('module')

const originalRequire = mod.prototype.require
const originalResolveFilename = mod._resolveFilename

async function installDependencies(cwd: string) {
const NEXT_VERSION = process.env.NEXT_VERSION ?? 'latest'
await setNextVersionInFixture(cwd, NEXT_VERSION, { silent: true })
Expand Down Expand Up @@ -110,6 +117,30 @@ export const createFixture = async (fixture: string, ctx: FixtureTestContext) =>
// from any previous function invocations that might have run in the same process
delete globalThis[Symbol.for('next.server.manifests')]

// require hook leaves modified "require" and "require.resolve" modified - we restore here to original
// https://github.com/vercel/next.js/blob/812c26ab8741f68fbd6e2fe095510e0f03eac4c5/packages/next/src/server/require-hook.ts
mod.prototype.require = originalRequire
mod._resolveFilename = originalResolveFilename

// node environment baseline defines global WebSocket getter that requires compiled 'ws' package from first function modules
// we need to reset the getter to not have it attempt to import 'ws' package from unrelated functions that might have already been deleted
// https://github.com/vercel/next.js/blob/812c26ab8741f68fbd6e2fe095510e0f03eac4c5/packages/next/src/server/node-environment-baseline.ts#L11-L27
// note that some next versions didn't have setter, so we can't just do "globalThis.WebSocket = undefined" as that would throw
// "Cannot set property WebSocket of #<Object> which has only a getter" errors
Object.defineProperty(globalThis, 'WebSocket', {
get() {
return undefined
},
set(value) {
Object.defineProperty(globalThis, 'WebSocket', {
configurable: true,
writable: true,
value,
})
},
configurable: true,
})

ctx.cwd = await mkdtemp(join(tmpdir(), 'opennextjs-netlify-'))
vi.spyOn(process, 'cwd').mockReturnValue(ctx.cwd)

Expand Down Expand Up @@ -147,6 +178,16 @@ export const createFixture = async (fixture: string, ctx: FixtureTestContext) =>
} catch (error) {
console.log(`Fixture '${fixture}' has failed to cleanup at '${ctx.cwd}'`, error)
}
if (ctx.functionDist) {
try {
await rm(ctx.functionDist, { recursive: true, force: true })
} catch (error) {
console.log(
`Fixture's '${fixture}' bundled serverless function has failed to cleanup at '${ctx.cwd}'`,
error,
)
}
}
})
}

Expand Down
Loading