test(engine): skip the browser FX render cases when there is no browser

CI's `Test` job was red on this PR with four failures, all the same cause:

  Failed to launch the browser process: spawn
  /home/runner/.cache/hyperframes/chrome/chrome-headless-shell

The job installs ffmpeg and no browser, deliberately — every other suite
that needs an external binary already guards on it
(`describe.skipIf(!HAS_FFMPEG)`). These cases were the only ones assuming
a Chrome, so they failed on an absent dependency rather than on anything
about the code.

Guards on `resolveHeadlessShellPath()` — the same resolver
`acquireBrowser` launches through, so the check cannot drift from the
thing it guards the way a hard-coded cache path would. A configured path
that does not exist throws; that is caught and read as "cannot run here".

Checked both directions rather than just the green one: with a browser all
11 cases run and pass, and with `HYPERFRAMES_BROWSER_PATH` pointed at a
missing binary exactly 3 skip and the other 8 still run. A guard that
silently skipped everything would have looked identical in CI.

They keep their value where it exists — every developer machine, and any
job that has run `hyperframes browser ensure`.

Not touched: the CodeQL failure on this PR is a run from 2026-08-07, five
days and several force-pushes stale. None of the 17 open repo alerts are
in files this PR changes; it re-runs on this push.
This commit is contained in:
Vance Ingalls
2026-08-12 02:35:09 -07:00
parent f75e5a814d
commit 384fdc443f
@@ -6,6 +6,32 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { applyVolumeEnvelopeToWav } from "./audioVolumeEnvelope.js";
import { defaultAudioFxParams, type HfAudioFxChain } from "@hyperframes/core/audio-fx";
import { applyAudioFxChain, AudioFxRenderError, readWav, writeWav } from "./audioFxRender.js";
import { resolveHeadlessShellPath } from "./browserManager.js";
/**
* Whether a Chrome is actually on this machine, asked the same way the render
* asks — `resolveHeadlessShellPath` is what `acquireBrowser` resolves through,
* so this cannot drift from the thing it is guarding the way a hard-coded cache
* path would.
*
* The repo's `Test` job installs ffmpeg and no browser, on purpose. Without
* this guard the four browser cases below fail there with a spawn error that
* says nothing about the code under test, and the same pattern already covers
* the ffmpeg-dependent suites (`describe.skipIf(!HAS_FFMPEG)`).
*
* They still run wherever a browser exists — every developer machine, and any
* job that has run `hyperframes browser ensure`.
*/
const HAS_BROWSER = ((): boolean => {
try {
return Boolean(resolveHeadlessShellPath());
} catch {
// An explicitly-configured path that does not exist throws. That is a
// broken environment rather than an absent browser, but either way these
// cases cannot run.
return false;
}
})();
const SR = 48000;
@@ -150,7 +176,7 @@ describe("applyAudioFxChain", () => {
* are the only place that proves the injected runtime loads and processes
* audio, so they are worth the seconds they cost.
*/
describe("browser render", () => {
describe.skipIf(!HAS_BROWSER)("browser render", () => {
it("notches out the tone it is tuned to", async () => {
const input = join(dir, "in.wav");
tone(input);