fix(test): resolve CI failures from the overhaul

- fixture-integrity: probe media via media-engine probeMedia (resolves the
  bundled static ffmpeg) instead of bare system ffprobe, which is ENOENT in CI;
  gate on ffmpegAvailable() like the other media tests
- a11y: regenerate a11y-baseline.json to include the mobile device keys (the
  baseline only had desktop keys, so the mobile a11y scan saw them as new)
- device-visual: tag @visual and exclude it from the PR mobile-smoke gate
  (darwin-only screenshots cannot pass on linux; nightly + update-visual-baselines
  still run it to seed linux goldens)
This commit is contained in:
SnapOtter
2026-06-20 09:54:49 +08:00
parent ad215bd6ee
commit 34b006ded7
4 changed files with 158 additions and 31 deletions
@@ -1,9 +1,9 @@
import { execFileSync } from "node:child_process";
import { ffmpegAvailable, probeMedia } from "@snapotter/media-engine";
import sharp from "sharp";
import { describe, expect, it } from "vitest";
import { fixtures } from "../../fixtures/index.js";
const ffprobe = process.env.FFPROBE_PATH || "ffprobe";
const qpdf = process.env.QPDF_PATH || "qpdf";
describe("real fixtures decode through their real tools", () => {
@@ -21,33 +21,35 @@ describe("real fixtures decode through their real tools", () => {
expect((meta.width ?? 0) * (meta.height ?? 0)).toBeGreaterThan(64 * 64);
});
it.each([
fixtures.video.hero.mp4,
fixtures.video.hero.mov,
fixtures.video.hero.webm,
fixtures.video.hero.mkv,
fixtures.video.hero.avi,
fixtures.audio.speech.wav,
fixtures.audio.speech.flac,
fixtures.audio.speech.ogg,
fixtures.audio.speech.m4a,
fixtures.audio.speech.aac,
fixtures.audio.speech.opus,
fixtures.audio.tagged,
])("ffprobe reads a positive duration from %s", (path) => {
const out = execFileSync(
ffprobe,
["-v", "error", "-show_entries", "format=duration", "-of", "csv=p=0", path],
{ encoding: "utf8" },
);
expect(Number.parseFloat(out.trim())).toBeGreaterThan(0);
// Probe via media-engine, which resolves the bundled static ffmpeg/ffprobe.
// System ffprobe is NOT on PATH in CI (only the static binary is), so a bare
// `ffprobe` spawn would ENOENT. Gate on ffmpeg presence so a machine with no
// ffmpeg at all skips cleanly.
describe.skipIf(!ffmpegAvailable())("media probes", () => {
it.each([
fixtures.video.hero.mp4,
fixtures.video.hero.mov,
fixtures.video.hero.webm,
fixtures.video.hero.mkv,
fixtures.video.hero.avi,
fixtures.audio.speech.wav,
fixtures.audio.speech.flac,
fixtures.audio.speech.ogg,
fixtures.audio.speech.m4a,
fixtures.audio.speech.aac,
fixtures.audio.speech.opus,
fixtures.audio.tagged,
])("media probe reads a positive duration from %s", async (path) => {
const info = await probeMedia(path);
expect(info.durationS).toBeGreaterThan(0);
});
});
it.each([
fixtures.document.pdfMulti,
fixtures.document.pdfScanned,
])("qpdf reports pages for %s", (path) => {
const out = execFileSync(qpdf, ["--show-npages", path], { encoding: "utf8" });
expect(Number.parseInt(out.trim(), 10)).toBeGreaterThan(0);
});
it.each([fixtures.document.pdfMulti, fixtures.document.pdfScanned])(
"qpdf reports pages for %s",
(path) => {
const out = execFileSync(qpdf, ["--show-npages", path], { encoding: "utf8" });
expect(Number.parseInt(out.trim(), 10)).toBeGreaterThan(0);
},
);
});