test: bind fixture servers to os-assigned ports

The test:* scripts run in parallel on CI, so a pre-picked free port could
be claimed by another suite before the bind (EADDRINUSE). The cdn server
now starts first on port 0 — 404ing until its dist exists — so its real
port can be baked into assetsBase. Also type the file:// image probe.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pull/5406/head
Divyansh Singh 2 weeks ago
parent bcb3172c29
commit 2fee2b16fb

@ -31,7 +31,9 @@ describe('relative base opened over file://', () => {
) )
expect(fontFamily).toContain('Inter') expect(fontFamily).toContain('Inter')
const logoLoaded = await t.page.evaluate( const logoLoaded = await t.page.evaluate(
() => document.querySelector('img[alt="logo again"]')!.naturalWidth () =>
document.querySelector<HTMLImageElement>('img[alt="logo again"]')!
.naturalWidth
) )
expect(logoLoaded).toBe(1) expect(logoLoaded).toBe(1)
}) })

@ -1,10 +1,10 @@
import { spawnSync } from 'node:child_process' import { spawnSync } from 'node:child_process'
import { readFile } from 'node:fs/promises' import { readFile } from 'node:fs/promises'
import { createServer, type Server } from 'node:http' import { createServer, type Server } from 'node:http'
import type { AddressInfo } from 'node:net'
import { extname, join, resolve } from 'node:path' import { extname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url' import { fileURLToPath } from 'node:url'
import getPort from 'get-port'
import { chromium, type BrowserServer } from 'playwright-chromium' import { chromium, type BrowserServer } from 'playwright-chromium'
import { ALT_PREFIX, SUB_PREFIX } from './constants' import { ALT_PREFIX, SUB_PREFIX } from './constants'
@ -23,8 +23,9 @@ const types: Record<string, string> = {
'.zip': 'application/zip' '.zip': 'application/zip'
} }
// listens on an os-assigned port (the other suites run in parallel on CI,
// so a pre-picked "free" port can be taken before we bind it)
function serveStatic( function serveStatic(
port: number,
mounts: [prefix: string, root: string][], mounts: [prefix: string, root: string][],
cors: boolean cors: boolean
): Promise<Server> { ): Promise<Server> {
@ -48,18 +49,19 @@ function serveStatic(
res.writeHead(404) res.writeHead(404)
res.end('not found') res.end('not found')
}) })
return new Promise((r) => server.listen(port, () => r(server))) return new Promise((r) => server.listen(0, () => r(server)))
} }
const portOf = (server: Server) => (server.address() as AddressInfo).port
let browserServer: BrowserServer let browserServer: BrowserServer
let servers: Server[] = [] let servers: Server[] = []
export async function setup() { export async function setup() {
const [subPort, pagesPort, cdnPort] = await Promise.all([ // the cdn server starts before its dist exists (requests just 404 until
getPort(), // the build lands) so the real port can be baked into assetsBase
getPort(), const cdnServer = await serveStatic([['/', dist('cdn')]], true)
getPort() const cdnPort = portOf(cdnServer)
])
// each flavor builds in its own process: the markdown renderer is a // each flavor builds in its own process: the markdown renderer is a
// process-wide singleton, so sequential in-process builds would leak the // process-wide singleton, so sequential in-process builds would leak the
@ -82,15 +84,14 @@ export async function setup() {
servers = [ servers = [
// one relative-base build mounted at two unrelated prefixes // one relative-base build mounted at two unrelated prefixes
await serveStatic( await serveStatic(
subPort,
[ [
[SUB_PREFIX, dist('relative')], [SUB_PREFIX, dist('relative')],
[ALT_PREFIX, dist('relative')] [ALT_PREFIX, dist('relative')]
], ],
false false
), ),
await serveStatic(pagesPort, [['/', dist('cdn')]], false), await serveStatic([['/', dist('cdn')]], false),
await serveStatic(cdnPort, [['/', dist('cdn')]], true) cdnServer
] ]
browserServer = await chromium.launchServer({ browserServer = await chromium.launchServer({
@ -101,8 +102,8 @@ export async function setup() {
}) })
process.env['WS_ENDPOINT'] = browserServer.wsEndpoint() process.env['WS_ENDPOINT'] = browserServer.wsEndpoint()
process.env['SUB_PORT'] = String(subPort) process.env['SUB_PORT'] = String(portOf(servers[0]!))
process.env['PAGES_PORT'] = String(pagesPort) process.env['PAGES_PORT'] = String(portOf(servers[1]!))
process.env['VP_CDN_PORT'] = String(cdnPort) process.env['VP_CDN_PORT'] = String(cdnPort)
} }

Loading…
Cancel
Save