From 2fee2b16fb11a67adf07fc84214ee3b8648ca70f Mon Sep 17 00:00:00 2001 From: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> Date: Fri, 28 Aug 2026 02:36:45 +0530 Subject: [PATCH] test: bind fixture servers to os-assigned ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- __tests__/base/relative-file.test.ts | 4 +++- __tests__/base/vitestGlobalSetup.ts | 27 ++++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/__tests__/base/relative-file.test.ts b/__tests__/base/relative-file.test.ts index 1480a1ac..e2115802 100644 --- a/__tests__/base/relative-file.test.ts +++ b/__tests__/base/relative-file.test.ts @@ -31,7 +31,9 @@ describe('relative base opened over file://', () => { ) expect(fontFamily).toContain('Inter') const logoLoaded = await t.page.evaluate( - () => document.querySelector('img[alt="logo again"]')!.naturalWidth + () => + document.querySelector('img[alt="logo again"]')! + .naturalWidth ) expect(logoLoaded).toBe(1) }) diff --git a/__tests__/base/vitestGlobalSetup.ts b/__tests__/base/vitestGlobalSetup.ts index 5674df2b..fa13458d 100644 --- a/__tests__/base/vitestGlobalSetup.ts +++ b/__tests__/base/vitestGlobalSetup.ts @@ -1,10 +1,10 @@ import { spawnSync } from 'node:child_process' import { readFile } from 'node:fs/promises' import { createServer, type Server } from 'node:http' +import type { AddressInfo } from 'node:net' import { extname, join, resolve } from 'node:path' import { fileURLToPath } from 'node:url' -import getPort from 'get-port' import { chromium, type BrowserServer } from 'playwright-chromium' import { ALT_PREFIX, SUB_PREFIX } from './constants' @@ -23,8 +23,9 @@ const types: Record = { '.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( - port: number, mounts: [prefix: string, root: string][], cors: boolean ): Promise { @@ -48,18 +49,19 @@ function serveStatic( res.writeHead(404) 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 servers: Server[] = [] export async function setup() { - const [subPort, pagesPort, cdnPort] = await Promise.all([ - getPort(), - getPort(), - getPort() - ]) + // the cdn server starts before its dist exists (requests just 404 until + // the build lands) so the real port can be baked into assetsBase + const cdnServer = await serveStatic([['/', dist('cdn')]], true) + const cdnPort = portOf(cdnServer) // each flavor builds in its own process: the markdown renderer is a // process-wide singleton, so sequential in-process builds would leak the @@ -82,15 +84,14 @@ export async function setup() { servers = [ // one relative-base build mounted at two unrelated prefixes await serveStatic( - subPort, [ [SUB_PREFIX, dist('relative')], [ALT_PREFIX, dist('relative')] ], false ), - await serveStatic(pagesPort, [['/', dist('cdn')]], false), - await serveStatic(cdnPort, [['/', dist('cdn')]], true) + await serveStatic([['/', dist('cdn')]], false), + cdnServer ] browserServer = await chromium.launchServer({ @@ -101,8 +102,8 @@ export async function setup() { }) process.env['WS_ENDPOINT'] = browserServer.wsEndpoint() - process.env['SUB_PORT'] = String(subPort) - process.env['PAGES_PORT'] = String(pagesPort) + process.env['SUB_PORT'] = String(portOf(servers[0]!)) + process.env['PAGES_PORT'] = String(portOf(servers[1]!)) process.env['VP_CDN_PORT'] = String(cdnPort) }