Replace 13 content fixtures with deterministic, reproducible outputs from gen-synthetic-content.mjs: - QR codes (PNG/SVG/AVIF): qrcode lib encoding https://snapotter.com - Barcodes (PNG/AVIF): Code 128B encoder for SNAPOTTER-TEST-123 - OCR text (English/Japanese PNG): Sharp SVG text rendering - PDFs (2-page/6-page): minimal PDF byte generator - Audio (MP3 with ID3 tags, 30s WAV): ffmpeg 440Hz sine wave - Video (1s metadata, 30s hero): ffmpeg testsrc2 + sine tone All outputs are CC0 with no third-party IP. The generator script is idempotent and can be re-run to reproduce identical fixtures.
Test Fixtures
Shared test fixtures for the SnapOtter test suite. Organized in two tiers:
Two-Tier Structure
Tier 1: Tiny Synthetics (matrices/format coverage)
Small, project-generated files for format-compatibility matrices and fast unit tests.
Located in media/, documents/, data/, formats/, and root-level test-* files.
Tier 2: Real Heroes (depth/fidelity testing)
Larger, content-representative files for integration and fidelity tests.
Located in content/. Each must be tracked in manifest.json with sha256 + provenance.
Layout (Modality-First, Phase 6 Target)
tests/fixtures/
index.ts # Typed registry (import paths from here, not raw strings)
manifest.json # sha256 + bytes + provenance for content/ heroes
gen-manifest.mjs # Script to re-stamp manifest hashes
LICENSES.md # Provenance audit trail
content/ # Tier-2 real heroes
formats/ # Tier-1 format samples (35 formats incl. RAW)
media/ # Tier-1 tiny audio/video samples
documents/ # Tier-1 tiny document samples
data/ # Tier-1 tiny data samples (csv, json, xml, etc.)
hostile/ # Malformed/bomb/polyglot files for rejection tests
security/ # XXE, SSRF test vectors
image/ # (Phase 6) modality-first target dir
video/ # (Phase 6) modality-first target dir
audio/ # (Phase 6) modality-first target dir
document/ # (Phase 6) modality-first target dir
data/ # (Phase 6) modality-first target dir
Using the Registry
Always import paths from tests/fixtures/index.ts rather than hard-coding paths:
import { fixtures, readFixture } from "../../fixtures/index.js";
// Direct path access
const pngPath = fixtures.image.base.png200;
// Read bytes
const buffer = readFixture(fixtures.image.base.png200);
// Format accessor (for matrix iteration)
const arwPath = fixtures.image.formats("arw");
const mp4Path = fixtures.video.tiny("mp4");
Adding a Fixture
- Add the file to the appropriate directory
- Add a key in
tests/fixtures/index.tspointing to it - Run
node tests/fixtures/gen-manifest.mjsif the file is incontent/ - Fill in
sourceUrlandlicenseinmanifest.json(required for Phase 2+) - Update
LICENSES.mdwith the provenance record - Run the guards:
pnpm vitest run tests/unit/fixtures/ tests/integration/fixtures/
Licensing Gate
Phase 1 allows UNVERIFIED provenance. Phase 2 enforces that every content/ hero
has a verified license (CC0, CC-BY, CC-BY-SA, or public-domain). See LICENSES.md
for the current audit status.
Guard Tests
Four guard tests protect fixture integrity:
- fixture-resolve (unit): every registry path exists and is non-empty
- fixture-budget (unit): per-extension size caps prevent bloat
- fixture-manifest (unit): sha256/bytes in manifest.json match disk
- fixture-integrity (integration): real heroes decode through Sharp/ffprobe/qpdf