Files
C.E.L_Slide_test2/tests/test_generate_frame_previews.py
kyeongmin 7d5639ad72 feat(IMP-13): A-3 — build-time frame preview generator (capture_slide_screenshot salvage)
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>
2026-05-18 06:25:05 +09:00

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"