Skip to content

Commit 7d79370

Browse files
committed
test(engine): probe ffmpeg and Chrome instead of assuming them
Two failures on #3021's Test job, both about the environment rather than the code under test. **Bare `ffmpeg` is not on PATH in CI.** The 16-bit fixture shelled out to `execFileSync("ffmpeg", ...)` and died with ENOENT. The job does provide ffmpeg, through `prepare-ffmpeg-bin`, which is what `getFfmpegBinary()` resolves — every other ffmpeg-dependent suite in this package already goes through it. Now this one does too, and the case is `skipIf(!HAS_FFMPEG)` so a contributor without ffmpeg skips rather than fails. **The browser guard trusted the wrong thing.** It asked `resolveHeadlessShellPath()` and treated a returned path as "a browser is here". CI's cache holds a chrome-headless-shell that resolves and then fails to spawn — a partial download is indistinguishable from a working one by `existsSync`, which is all that resolver checks. So the three browser cases ran anyway and failed on the launch. It now runs `--version` and requires exit 0, which is the same probe the ffmpeg suites use: ask the binary, do not infer from the filesystem. Checked both directions rather than just the green one. With a working browser all 11 cases run and pass; with `HYPERFRAMES_BROWSER_PATH` pointed at a binary that exits non-zero — CI's exact situation — exactly 3 skip and the other 8 still run. A guard that quietly skipped everything would have looked identical on the CI summary.
1 parent 7fdf4db commit 7d79370

1 file changed

Lines changed: 18 additions & 4 deletions

File tree

packages/engine/src/services/audioFxRender.test.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { execFileSync } from "node:child_process";
1+
import { execFileSync, spawnSync } from "node:child_process";
22
import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
33
import { tmpdir } from "node:os";
44
import { join } from "node:path";
@@ -7,6 +7,10 @@ import { applyVolumeEnvelopeToWav } from "./audioVolumeEnvelope.js";
77
import { defaultAudioFxParams, type HfAudioFxChain } from "@hyperframes/core/audio-fx";
88
import { applyAudioFxChain, AudioFxRenderError, readWav, writeWav } from "./audioFxRender.js";
99
import { resolveHeadlessShellPath } from "./browserManager.js";
10+
import { getFfmpegBinary } from "../utils/ffmpegBinaries.js";
11+
12+
/** Same probe the ffmpeg-dependent suites use: ask the binary, don't assume it. */
13+
const HAS_FFMPEG = spawnSync(getFfmpegBinary(), ["-version"], { encoding: "utf-8" }).status === 0;
1014

1115
/**
1216
* Whether a Chrome is actually on this machine, asked the same way the render
@@ -24,7 +28,14 @@ import { resolveHeadlessShellPath } from "./browserManager.js";
2428
*/
2529
const HAS_BROWSER = ((): boolean => {
2630
try {
27-
return Boolean(resolveHeadlessShellPath());
31+
const path = resolveHeadlessShellPath();
32+
if (!path) return false;
33+
// ASK the binary rather than trusting that the file is there. CI carries a
34+
// chrome-headless-shell in its cache that resolves and then fails to spawn
35+
// — a partial download is indistinguishable from a working one by
36+
// existsSync, and the first version of this guard was fooled by exactly
37+
// that. Same probe the ffmpeg suites use.
38+
return spawnSync(path, ["--version"], { encoding: "utf-8" }).status === 0;
2839
} catch {
2940
// An explicitly-configured path that does not exist throws. That is a
3041
// broken environment rather than an absent browser, but either way these
@@ -116,9 +127,12 @@ describe("readWav / writeWav", () => {
116127
expect(back.samples[1]).toBeCloseTo(-1, 3);
117128
});
118129

119-
it("reads 16-bit PCM, which the trim step can emit", () => {
130+
// Needs a real ffmpeg to author the 16-bit fixture. The Test job installs one,
131+
// but a bare "ffmpeg" is not on PATH there — hence getFfmpegBinary above — and
132+
// a contributor without it should skip rather than fail.
133+
it.skipIf(!HAS_FFMPEG)("reads 16-bit PCM, which the trim step can emit", () => {
120134
const p = join(dir, "pcm16.wav");
121-
execFileSync("ffmpeg", [
135+
execFileSync(getFfmpegBinary(), [
122136
"-hide_banner",
123137
"-loglevel",
124138
"error",

0 commit comments

Comments
 (0)