From 78a4d2ea5ad40349193fdea85d4015f3e6ddf027 Mon Sep 17 00:00:00 2001 From: Christian Stewart Date: Sun, 2 Aug 2026 04:50:54 -0700 Subject: [PATCH] test(browser): stop gating chromium tests on a top-level-await export `bun test` fails the coding-agent native/unit job with ReferenceError: Cannot access 'CHROMIUM_AVAILABLE' before initialization in test/tools/browser-attach.test.ts and browser-tab-evaluate.test.ts, taking the job red on every pull request. chromium-probe.ts initializes its only export with top-level await. When a test file importing it is the first file the runner loads, the await settles before that file evaluates and the binding reads fine. When any other test file was loaded first, the importer's body runs while the binding is still in its temporal dead zone, and registration throws at the `skipIf` call. `bun test ` passes and `bun test --parallel=1 ` fails, which is why the job fails while a single-file run does not. Export the memoized probe as a function and let each test file await it during its own evaluation, which the runner sequences. The probe still runs once per process and resolves the executable exactly as before. Signed-off-by: Christian Stewart --- packages/coding-agent/CHANGELOG.md | 4 ++++ .../test/tools/browser-attach.test.ts | 4 +++- .../test/tools/browser-tab-evaluate.test.ts | 4 +++- .../coding-agent/test/tools/chromium-probe.ts | 22 +++++++++++++++++-- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 11d4830cc..e2451b8c3 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed Chromium-backed tests failing during suite registration when the shared availability probe was still initializing ([#7384](https://github.com/can1357/oh-my-pi/pull/7384) by [@paralin](https://github.com/paralin)). + ## [17.2.4] - 2026-08-01 ### Added diff --git a/packages/coding-agent/test/tools/browser-attach.test.ts b/packages/coding-agent/test/tools/browser-attach.test.ts index 905aa614b..ed9afd184 100644 --- a/packages/coding-agent/test/tools/browser-attach.test.ts +++ b/packages/coding-agent/test/tools/browser-attach.test.ts @@ -11,7 +11,9 @@ import { } from "@oh-my-pi/pi-coding-agent/tools/browser/registry"; import { acquireTab, releaseTab } from "@oh-my-pi/pi-coding-agent/tools/browser/tab-supervisor"; import type { Browser, Page, Target } from "puppeteer-core"; -import { CHROMIUM_AVAILABLE } from "./chromium-probe"; +import { chromiumAvailable } from "./chromium-probe"; + +const CHROMIUM_AVAILABLE = await chromiumAvailable(); interface FakePageOptions { url: string; diff --git a/packages/coding-agent/test/tools/browser-tab-evaluate.test.ts b/packages/coding-agent/test/tools/browser-tab-evaluate.test.ts index 5f87c97f2..5d6234d30 100644 --- a/packages/coding-agent/test/tools/browser-tab-evaluate.test.ts +++ b/packages/coding-agent/test/tools/browser-tab-evaluate.test.ts @@ -3,7 +3,9 @@ import { Settings } from "@oh-my-pi/pi-coding-agent/config/settings"; import type { ToolSession } from "@oh-my-pi/pi-coding-agent/sdk"; import { BrowserTool } from "@oh-my-pi/pi-coding-agent/tools/browser"; import { getTabsMapForTest } from "@oh-my-pi/pi-coding-agent/tools/browser/tab-supervisor"; -import { CHROMIUM_AVAILABLE } from "./chromium-probe"; +import { chromiumAvailable } from "./chromium-probe"; + +const CHROMIUM_AVAILABLE = await chromiumAvailable(); function makeSession(): ToolSession { return { diff --git a/packages/coding-agent/test/tools/chromium-probe.ts b/packages/coding-agent/test/tools/chromium-probe.ts index c7d5f1e19..c21456040 100644 --- a/packages/coding-agent/test/tools/chromium-probe.ts +++ b/packages/coding-agent/test/tools/chromium-probe.ts @@ -17,5 +17,23 @@ async function chromiumCanLaunch(): Promise { } } -/** Gate for tests that launch a real Chromium: `describe.skipIf(!CHROMIUM_AVAILABLE)`. */ -export const CHROMIUM_AVAILABLE = await chromiumCanLaunch(); +let probe: Promise | undefined; + +/** + * Gate for tests that launch a real Chromium: + * + * const CHROMIUM_AVAILABLE = await chromiumAvailable(); + * describe.skipIf(!CHROMIUM_AVAILABLE)(…); + * + * The result is a promise rather than an awaited `export const`. A module whose + * exports are initialized by top-level await hands the test runner a binding + * that is still in its temporal dead zone when a second test file in the same + * process imports it, and that file dies during registration with "Cannot + * access 'CHROMIUM_AVAILABLE' before initialization". Awaiting in the importer + * makes the wait part of that file's own evaluation, which the runner does + * sequence. The probe runs once per process. + */ +export function chromiumAvailable(): Promise { + probe ??= chromiumCanLaunch(); + return probe; +}