75 lines
3.3 KiB
Python
75 lines
3.3 KiB
Python
from pathlib import Path
|
|||
|
|
import json
|
||
|
|
import subprocess
|
||
|
|
import sys
|
||
|
|
import tempfile
|
||
|
|
import unittest
|
||
|
|
|
||
|
|
from PIL import Image
|
||
|
|
|
||
|
|
SCRIPT = Path(__file__).resolve().parents[1] / "scripts" / "assemble_page.py"
|
||
|
|
|
||
|
|
|
||
|
|
class AssemblePageTests(unittest.TestCase):
|
||
|
|
def setUp(self):
|
||
|
|
self.temp = tempfile.TemporaryDirectory()
|
||
|
|
self.addCleanup(self.temp.cleanup)
|
||
|
|
self.root = Path(self.temp.name)
|
||
|
|
Image.new("RGBA", (8, 5), (255, 0, 0, 255)).save(self.root / "a.png")
|
||
|
|
Image.new("RGBA", (8, 3), (0, 0, 255, 128)).save(self.root / "b.png")
|
||
|
|
self.data = {"expected_sections": ["a", "b"], "sections": [{"id": "a", "image": "a.png"}, {"id": "b", "image": "b.png"}]}
|
||
|
|
self.output = self.root / "page.png"
|
||
|
|
|
||
|
|
def run_cli(self, *extra):
|
||
|
|
manifest = self.root / "page.json"
|
||
|
|
manifest.write_text(json.dumps(self.data))
|
||
|
|
return subprocess.run([sys.executable, str(SCRIPT), "--manifest", str(manifest), "--output", str(self.output), *extra], capture_output=True, text=True, cwd=self.root.parent)
|
||
|
|
|
||
|
|
def test_cli_preserves_order_dimensions_pixels_and_relative_paths(self):
|
||
|
|
result = self.run_cli()
|
||
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
||
|
|
with Image.open(self.output) as im:
|
||
|
|
self.assertEqual(im.size, (8, 8))
|
||
|
|
self.assertEqual(im.getpixel((0, 4)), (255, 0, 0, 255))
|
||
|
|
self.assertEqual(im.getpixel((0, 5)), (0, 0, 255, 128))
|
||
|
|
|
||
|
|
def test_rejects_wrong_width_without_writing_output(self):
|
||
|
|
Image.new("RGB", (7, 3)).save(self.root / "b.png")
|
||
|
|
self.assertNotEqual(self.run_cli().returncode, 0)
|
||
|
|
self.assertFalse(self.output.exists())
|
||
|
|
|
||
|
|
def test_rejects_missing_reordered_and_duplicate_sections(self):
|
||
|
|
for sections in ([self.data["sections"][0]], list(reversed(self.data["sections"])), [self.data["sections"][0]] * 2):
|
||
|
|
with self.subTest(sections=sections):
|
||
|
|
original = self.data["sections"]
|
||
|
|
self.data["sections"] = sections
|
||
|
|
self.assertNotEqual(self.run_cli().returncode, 0)
|
||
|
|
self.assertFalse(self.output.exists())
|
||
|
|
self.data["sections"] = original
|
||
|
|
|
||
|
|
def test_rejects_corrupt_source_and_preserves_existing_output(self):
|
||
|
|
self.output.write_bytes(b"existing")
|
||
|
|
self.assertNotEqual(self.run_cli().returncode, 0)
|
||
|
|
self.assertEqual(self.output.read_bytes(), b"existing")
|
||
|
|
(self.root / "b.png").write_bytes(b"broken")
|
||
|
|
self.assertNotEqual(self.run_cli("--force").returncode, 0)
|
||
|
|
self.assertEqual(self.output.read_bytes(), b"existing")
|
||
|
|
|
||
|
|
def test_force_replaces_output_after_validation(self):
|
||
|
|
self.output.write_bytes(b"existing")
|
||
|
|
self.assertEqual(self.run_cli("--force").returncode, 0)
|
||
|
|
with Image.open(self.output) as im:
|
||
|
|
self.assertEqual(im.size, (8, 8))
|
||
|
|
|
||
|
|
def test_rejects_duplicate_image_and_overwriting_source(self):
|
||
|
|
self.data["sections"][1]["image"] = "a.png"
|
||
|
|
self.assertNotEqual(self.run_cli().returncode, 0)
|
||
|
|
self.data["sections"][1]["image"] = "b.png"
|
||
|
|
self.output = self.root / "a.png"
|
||
|
|
before = self.output.read_bytes()
|
||
|
|
self.assertNotEqual(self.run_cli("--force").returncode, 0)
|
||
|
|
self.assertEqual(self.output.read_bytes(), before)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
unittest.main()
|