104 lines
4.6 KiB
Python
104 lines
4.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Focused tests for the reusable page restoration preflight."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
from PIL import Image
|
|
|
|
try:
|
|
from . import run_page_restore_preflight as preflight
|
|
except ImportError: # pragma: no cover - direct script execution
|
|
import run_page_restore_preflight as preflight
|
|
|
|
|
|
class PageRestorePreflightTests(unittest.TestCase):
|
|
def test_normalized_anchor_rejects_overflow(self) -> None:
|
|
self.assertTrue(preflight.normalized_anchor([0.1, 0.1, 0.4, 0.4]))
|
|
self.assertFalse(preflight.normalized_anchor([0.8, 0.1, 0.4, 0.4]))
|
|
|
|
def test_viewport_canvas_uses_contained_aspect(self) -> None:
|
|
self.assertEqual(preflight.viewport_canvas("760x360", 16 / 9), (640, 360))
|
|
self.assertEqual(preflight.viewport_canvas("1280x720", 16 / 9), (1280, 720))
|
|
|
|
def test_preflight_passes_structure_without_captures(self) -> None:
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
approved = root / "approved.png"
|
|
static = root / "static.png"
|
|
Image.new("RGB", (160, 90), "#456").save(approved)
|
|
Image.new("RGB", (160, 90), "#456").save(static)
|
|
files = {
|
|
"manifest.json": {"width": 160, "height": 90},
|
|
"fidelity.json": {"clean_static_master": {"sha256": preflight.sha256(static)}},
|
|
"layers.json": {"layers": [{"id": "world", "z": 0, "bounds": [0, 0, 1, 1]}]},
|
|
"text.json": {"slots": [{"id": "title", "owner": "engine", "anchor": [0, 0, 1, 0.1], "scale": [100, 130], "locales": ["zh_CN", "en"]}], "policy": "No visible copy is shipped from the generated PNG."},
|
|
"hit.json": {"minimum_target_px": 48, "areas": [{"id": "save", "anchor": [0.4, 0.8, 0.2, 0.2]}], "focus_order": ["save"]},
|
|
}
|
|
for name, value in files.items():
|
|
(root / name).write_text(json.dumps(value), encoding="utf-8")
|
|
config = {
|
|
"page_id": "TEST-001",
|
|
"design_size": [160, 90],
|
|
"design_aspect": 16 / 9,
|
|
"approved_master": "approved.png",
|
|
"clean_static_master": "static.png",
|
|
"visual_fidelity_contract": "fidelity.json",
|
|
"manifest": "manifest.json",
|
|
"layer_map": "layers.json",
|
|
"text_slots": "text.json",
|
|
"hit_areas": "hit.json",
|
|
"required_viewports": ["760x360"],
|
|
}
|
|
config_path = root / "config.json"
|
|
config_path.write_text(json.dumps(config), encoding="utf-8")
|
|
resolved = {}
|
|
checks: list[preflight.Check] = []
|
|
loaded, error = preflight.load_json(config_path)
|
|
self.assertIsNone(error)
|
|
self.assertIsInstance(loaded, dict)
|
|
resolved = preflight.check_required_files(config_path, loaded, checks)
|
|
preflight.check_images(config_path, loaded, resolved, checks)
|
|
preflight.check_text_slots(config_path, resolved["text_slots"], loaded, checks)
|
|
preflight.check_hit_areas(config_path, resolved["hit_areas"], loaded, checks)
|
|
preflight.check_layers(resolved["layer_map"], loaded, checks)
|
|
self.assertTrue(all(check.passed for check in checks), [check.as_dict() for check in checks])
|
|
|
|
def test_text_scale_requirement_can_be_normal_only(self) -> None:
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
slots_path = root / "text.json"
|
|
slots_path.write_text(
|
|
json.dumps(
|
|
{
|
|
"slots": [
|
|
{
|
|
"id": "title",
|
|
"owner": "engine",
|
|
"anchor": [0, 0, 1, 0.1],
|
|
"scale": [100],
|
|
"locales": ["zh_CN", "en"],
|
|
}
|
|
],
|
|
"policy": "Engine owns all visible copy; generated PNG has no text.",
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
checks: list[preflight.Check] = []
|
|
preflight.check_text_slots(
|
|
root / "config.json",
|
|
slots_path,
|
|
{"blocking_text_scales": [100]},
|
|
checks,
|
|
)
|
|
self.assertTrue(all(check.passed for check in checks), [check.as_dict() for check in checks])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|