scripts/generate_frame_previews.py iterates figma_to_html_agent/blocks/{frame_id}/index.html,
renders preview.png via Selenium headless (capture_slide_screenshot pattern reuse), and writes
_preview_manifest.json (schema v1) with idempotent stale-detect (mtime+sha256). Build-time only
— no runtime pipeline integration, no AI calls, no MDX/Jinja regen. Stage 2 baseline (commit
56619a0): total=33, renderable=20, missing_index_html=13, orphan=1 (1171281192).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
51 lines
2.7 KiB
Python
51 lines
2.7 KiB
Python
"""IMP-13 u7 smoke — discovery, source invariants, dry-run, idempotency, manifest schema."""
|
|
from __future__ import annotations
|
|
import json, os, re, sys
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
SCRIPT_PATH = REPO_ROOT / "scripts" / "generate_frame_previews.py"
|
|
sys.path.insert(0, str(SCRIPT_PATH.parent))
|
|
import generate_frame_previews as gfp # noqa: E402
|
|
|
|
def _fixture(root: Path) -> Path:
|
|
blocks = root / "blocks"
|
|
(blocks / "FRAME_A").mkdir(parents=True)
|
|
(blocks / "FRAME_A" / "index.html").write_text("<html><body class=slide></body></html>", encoding="utf-8")
|
|
(blocks / "FRAME_A" / "preview.png").write_bytes(b"\x89PNG\r\n\x1a\n")
|
|
(blocks / "FRAME_B").mkdir()
|
|
(blocks / "ORPHAN").mkdir()
|
|
(blocks / "ORPHAN" / "preview.png").write_bytes(b"x")
|
|
return blocks
|
|
|
|
def test_discover_counts(tmp_path: Path) -> None:
|
|
rows = gfp.discover(_fixture(tmp_path))
|
|
assert [r.frame_id for r in rows] == ["FRAME_A", "FRAME_B", "ORPHAN"]
|
|
assert sum(r.has_index for r in rows) == 1 and sum(r.has_preview for r in rows) == 2
|
|
|
|
def test_source_invariants() -> None:
|
|
src = SCRIPT_PATH.read_text(encoding="utf-8")
|
|
for t in ("anthropic", "openai", "jinja", "phase_z2", "slide_measurer"): assert t not in src, t
|
|
for lit in ("1280", "720", "1400", "900"): assert not re.search(rf"(?<!\d){lit}(?!\d)", src), lit
|
|
|
|
def test_dry_run_prints_counts(tmp_path: Path, capsys) -> None:
|
|
rc = gfp.main(["--blocks-dir", str(_fixture(tmp_path)), "--manifest", str(tmp_path / "m.json"), "--dry-run"])
|
|
assert rc == 0 and "discovered: total=3 with_index_html=1 with_preview_png=2" in capsys.readouterr().out
|
|
|
|
def test_idempotency_unchanged(tmp_path: Path) -> None:
|
|
row = gfp.discover(_fixture(tmp_path))[0]
|
|
mt = row.index_html_path.stat().st_mtime
|
|
os.utime(row.preview_png_path, (mt + 1, mt + 1))
|
|
sha = gfp._sha256_file(row.index_html_path)
|
|
assert gfp.is_unchanged(row, {"index_sha256": sha}) is True
|
|
assert gfp.is_unchanged(row, {"index_sha256": "x"}) is False
|
|
assert gfp.is_unchanged(row, None) is False
|
|
|
|
def test_manifest_schema(tmp_path: Path) -> None:
|
|
blocks = tmp_path / "blocks"; (blocks / "F").mkdir(parents=True); (blocks / "F" / "preview.png").write_bytes(b"x")
|
|
mf = tmp_path / "m.json"
|
|
assert gfp.main(["--blocks-dir", str(blocks), "--manifest", str(mf)]) == 0
|
|
data = json.loads(mf.read_text(encoding="utf-8"))
|
|
assert set(data) >= {"schema", "generated_at", "blocks_dir", "summary", "frames"} and data["schema"] == 1
|
|
assert set(data["summary"]) >= {"total", "renderable", "missing_index_html", "orphan", "rendered", "skipped_unchanged", "error"} and data["summary"]["orphan"] == 1 and data["frames"]["F"]["status"] == "orphan"
|