78a4d2ea5a
`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 <one file>` passes and `bun test --parallel=1 <any earlier file> <that file>` 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 <christian@aperture.us>
40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
import { ensureChromiumExecutable } from "@oh-my-pi/pi-coding-agent/tools/browser/launch";
|
|
|
|
/**
|
|
* Whether the Chromium puppeteer resolves can actually execute on this host.
|
|
* CI runners without Chrome's system libraries (libnspr4 & co.) hold the
|
|
* downloaded binary but cannot exec it — probe with --version and skip
|
|
* instead of failing.
|
|
*/
|
|
async function chromiumCanLaunch(): Promise<boolean> {
|
|
try {
|
|
const executable = await ensureChromiumExecutable();
|
|
if (!executable) return false;
|
|
const probe = Bun.spawnSync([executable, "--version"], { stdout: "ignore", stderr: "ignore" });
|
|
return probe.exitCode === 0;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
let probe: Promise<boolean> | 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<boolean> {
|
|
probe ??= chromiumCanLaunch();
|
|
return probe;
|
|
}
|