esmaill1
feat: implement image processing core, FastAPI backend, and full-stack integration tests
f19ba0f | import sys | |
| import os | |
| import unittest | |
| from pathlib import Path | |
| from PIL import Image, ImageFont | |
| # Add root and core directories to python path | |
| ROOT_DIR = Path(__file__).resolve().parent.parent | |
| sys.path.insert(0, str(ROOT_DIR)) | |
| sys.path.insert(0, str(ROOT_DIR / "core")) | |
| import layout_engine | |
| class TestLayoutEngine(unittest.TestCase): | |
| def test_load_settings(self): | |
| settings = layout_engine.load_settings() | |
| self.assertIsInstance(settings, dict) | |
| self.assertIn("layout", settings) | |
| self.assertIn("overlays", settings) | |
| self.assertIn("colors", settings) | |
| # Check defaults are populated | |
| self.assertIn("dpi", settings["layout"]) | |
| self.assertIn("grid_rows", settings["layout"]) | |
| self.assertIn("grid_cols", settings["layout"]) | |
| def test_to_arabic_digits(self): | |
| translated = layout_engine._to_arabic_digits("1234567890") | |
| self.assertEqual(translated, "١٢٣٤٥٦٧٨٩٠") | |
| def test_reshape_arabic(self): | |
| # Even if raqm or bidi is present/absent, it should return reshaped text or original | |
| text = "مرحبا" | |
| reshaped = layout_engine._reshape_arabic(text) | |
| self.assertIsNotNone(reshaped) | |
| self.assertNotEqual(reshaped, "") | |
| def test_resize_to_fit(self): | |
| # Create an image of 1000x2000 (aspect ratio 1:2) | |
| img = Image.new("RGB", (1000, 2000)) | |
| # Resize to fit in max 100x100 | |
| resized = layout_engine._resize_to_fit(img, 100, 100) | |
| self.assertEqual(resized.size[0], 50) | |
| self.assertEqual(resized.size[1], 100) | |
| # Resize to fit in max 300x100 | |
| resized2 = layout_engine._resize_to_fit(img, 300, 100) | |
| self.assertEqual(resized2.size[0], 50) | |
| self.assertEqual(resized2.size[1], 100) | |
| def test_add_inner_stroke(self): | |
| img = Image.new("RGB", (100, 100), (255, 255, 255)) | |
| stroked = layout_engine._add_inner_stroke(img, color=(0, 0, 0), width=2) | |
| self.assertEqual(stroked.size, (100, 100)) | |
| # Top-left pixel should be stroke color (0, 0, 0) | |
| self.assertEqual(stroked.getpixel((0, 0)), (0, 0, 0)) | |
| # Center pixel should still be white (255, 255, 255) | |
| self.assertEqual(stroked.getpixel((50, 50)), (255, 255, 255)) | |
| def test_generate_layout(self): | |
| # Create a dummy portrait image | |
| img = Image.new("RGB", (300, 420), (200, 200, 200)) | |
| # Call generate_layout with various options | |
| canvas = layout_engine.generate_layout( | |
| img, | |
| person_name="Test User", | |
| id_number="12345", | |
| add_studio_name=True, | |
| add_logo=False, # Avoid logo file requirements | |
| add_date=True, | |
| frame_color=(50, 50, 50) | |
| ) | |
| # Verify result is a PIL Image with output dimensions | |
| self.assertIsInstance(canvas, Image.Image) | |
| expected_w = round(layout_engine.S["layout"]["output_w_cm"] / 2.54 * layout_engine.DPI) | |
| expected_h = round(layout_engine.S["layout"]["output_h_cm"] / 2.54 * layout_engine.DPI) | |
| self.assertEqual(canvas.size[0], expected_w) | |
| self.assertEqual(canvas.size[1], expected_h) | |
| self.assertIn("dpi", canvas.info) | |
| if __name__ == "__main__": | |
| unittest.main() | |