693 lines
26 KiB
Python
693 lines
26 KiB
Python
"""
|
|
Unit tests for pyPhotoAlbum template management system
|
|
"""
|
|
|
|
import pytest
|
|
import tempfile
|
|
import json
|
|
from pathlib import Path
|
|
from pyPhotoAlbum.template_manager import Template, TemplateManager
|
|
from pyPhotoAlbum.models import ImageData, PlaceholderData, TextBoxData
|
|
from pyPhotoAlbum.page_layout import PageLayout
|
|
from pyPhotoAlbum.project import Page
|
|
|
|
|
|
class TestTemplate:
|
|
"""Tests for Template class"""
|
|
|
|
def test_initialization_default(self):
|
|
"""Test Template initialization with default values"""
|
|
template = Template()
|
|
assert template.name == "Untitled Template"
|
|
assert template.description == ""
|
|
assert template.page_size_mm == (210, 297)
|
|
assert len(template.elements) == 0
|
|
|
|
def test_initialization_with_parameters(self):
|
|
"""Test Template initialization with custom parameters"""
|
|
template = Template(
|
|
name="My Template",
|
|
description="Test template",
|
|
page_size_mm=(200, 280)
|
|
)
|
|
assert template.name == "My Template"
|
|
assert template.description == "Test template"
|
|
assert template.page_size_mm == (200, 280)
|
|
|
|
def test_add_element(self):
|
|
"""Test adding elements to template"""
|
|
template = Template()
|
|
placeholder = PlaceholderData(x=10, y=20, width=100, height=50)
|
|
|
|
template.add_element(placeholder)
|
|
assert len(template.elements) == 1
|
|
assert template.elements[0] == placeholder
|
|
|
|
def test_add_multiple_elements(self):
|
|
"""Test adding multiple elements"""
|
|
template = Template()
|
|
elem1 = PlaceholderData(x=10, y=20, width=100, height=50)
|
|
elem2 = TextBoxData(text_content="Test", x=30, y=40, width=150, height=60)
|
|
|
|
template.add_element(elem1)
|
|
template.add_element(elem2)
|
|
|
|
assert len(template.elements) == 2
|
|
assert elem1 in template.elements
|
|
assert elem2 in template.elements
|
|
|
|
def test_to_dict(self):
|
|
"""Test serialization to dictionary"""
|
|
template = Template(name="Test", description="Desc", page_size_mm=(200, 280))
|
|
placeholder = PlaceholderData(x=10, y=20, width=100, height=50)
|
|
template.add_element(placeholder)
|
|
|
|
data = template.to_dict()
|
|
|
|
assert data["name"] == "Test"
|
|
assert data["description"] == "Desc"
|
|
assert data["page_size_mm"] == (200, 280)
|
|
assert len(data["elements"]) == 1
|
|
assert data["elements"][0]["type"] == "placeholder"
|
|
|
|
def test_from_dict(self):
|
|
"""Test deserialization from dictionary"""
|
|
data = {
|
|
"name": "Loaded Template",
|
|
"description": "Test description",
|
|
"page_size_mm": [220, 300],
|
|
"elements": [
|
|
{
|
|
"type": "placeholder",
|
|
"position": (50, 60),
|
|
"size": (120, 80),
|
|
"placeholder_type": "image"
|
|
},
|
|
{
|
|
"type": "textbox",
|
|
"position": (70, 90),
|
|
"size": (140, 100),
|
|
"text_content": "Test text"
|
|
}
|
|
]
|
|
}
|
|
|
|
template = Template.from_dict(data)
|
|
|
|
assert template.name == "Loaded Template"
|
|
assert template.description == "Test description"
|
|
assert template.page_size_mm == (220, 300)
|
|
assert len(template.elements) == 2
|
|
assert isinstance(template.elements[0], PlaceholderData)
|
|
assert isinstance(template.elements[1], TextBoxData)
|
|
|
|
def test_from_dict_skips_image_elements(self):
|
|
"""Test that from_dict skips image elements"""
|
|
data = {
|
|
"name": "Test",
|
|
"elements": [
|
|
{"type": "image", "position": (10, 20), "size": (100, 50)},
|
|
{"type": "placeholder", "position": (30, 40), "size": (120, 60)}
|
|
]
|
|
}
|
|
|
|
template = Template.from_dict(data)
|
|
|
|
# Should only have the placeholder, not the image
|
|
assert len(template.elements) == 1
|
|
assert isinstance(template.elements[0], PlaceholderData)
|
|
|
|
def test_save_to_file(self, temp_dir):
|
|
"""Test saving template to file"""
|
|
template = Template(name="Save Test", description="Test save")
|
|
placeholder = PlaceholderData(x=10, y=20, width=100, height=50)
|
|
template.add_element(placeholder)
|
|
|
|
file_path = Path(temp_dir) / "test_template.json"
|
|
template.save_to_file(str(file_path))
|
|
|
|
# Verify file was created
|
|
assert file_path.exists()
|
|
|
|
# Verify content
|
|
with open(file_path, 'r') as f:
|
|
data = json.load(f)
|
|
assert data["name"] == "Save Test"
|
|
assert data["description"] == "Test save"
|
|
|
|
def test_load_from_file(self, temp_dir):
|
|
"""Test loading template from file"""
|
|
# Create a test file
|
|
data = {
|
|
"name": "Load Test",
|
|
"description": "Test load",
|
|
"page_size_mm": [210, 297],
|
|
"elements": [
|
|
{
|
|
"type": "placeholder",
|
|
"position": (10, 20),
|
|
"size": (100, 50),
|
|
"placeholder_type": "image"
|
|
}
|
|
]
|
|
}
|
|
|
|
file_path = Path(temp_dir) / "load_test.json"
|
|
with open(file_path, 'w') as f:
|
|
json.dump(data, f)
|
|
|
|
# Load template
|
|
template = Template.load_from_file(str(file_path))
|
|
|
|
assert template.name == "Load Test"
|
|
assert template.description == "Test load"
|
|
assert len(template.elements) == 1
|
|
|
|
|
|
class TestTemplateManager:
|
|
"""Tests for TemplateManager class"""
|
|
|
|
def test_initialization(self):
|
|
"""Test TemplateManager initialization"""
|
|
manager = TemplateManager()
|
|
assert manager.templates_dir is not None
|
|
assert isinstance(manager.templates_dir, Path)
|
|
|
|
def test_get_templates_directory(self):
|
|
"""Test getting templates directory"""
|
|
manager = TemplateManager()
|
|
templates_dir = manager._get_templates_directory()
|
|
|
|
assert templates_dir.name == "templates"
|
|
assert ".pyphotoalbum" in str(templates_dir)
|
|
|
|
def test_get_builtin_templates_directory(self):
|
|
"""Test getting built-in templates directory"""
|
|
manager = TemplateManager()
|
|
builtin_dir = manager._get_builtin_templates_directory()
|
|
|
|
assert builtin_dir.name == "templates"
|
|
assert "pyPhotoAlbum" in str(builtin_dir)
|
|
|
|
def test_list_templates_empty(self, tmp_path, monkeypatch):
|
|
"""Test listing templates when directory is empty"""
|
|
# Create temporary directories
|
|
user_dir = tmp_path / "user_templates"
|
|
builtin_dir = tmp_path / "builtin_templates"
|
|
user_dir.mkdir()
|
|
builtin_dir.mkdir()
|
|
|
|
manager = TemplateManager()
|
|
monkeypatch.setattr(manager, 'templates_dir', user_dir)
|
|
monkeypatch.setattr(manager, '_get_builtin_templates_directory', lambda: builtin_dir)
|
|
|
|
templates = manager.list_templates()
|
|
assert templates == []
|
|
|
|
def test_list_templates_with_files(self, tmp_path, monkeypatch):
|
|
"""Test listing templates with template files"""
|
|
user_dir = tmp_path / "user_templates"
|
|
builtin_dir = tmp_path / "builtin_templates"
|
|
user_dir.mkdir()
|
|
builtin_dir.mkdir()
|
|
|
|
# Create user template
|
|
user_template = user_dir / "My_Template.json"
|
|
user_template.write_text('{"name": "My Template"}')
|
|
|
|
# Create built-in template
|
|
builtin_template = builtin_dir / "Grid_2x2.json"
|
|
builtin_template.write_text('{"name": "Grid 2x2"}')
|
|
|
|
manager = TemplateManager()
|
|
monkeypatch.setattr(manager, 'templates_dir', user_dir)
|
|
monkeypatch.setattr(manager, '_get_builtin_templates_directory', lambda: builtin_dir)
|
|
|
|
templates = manager.list_templates()
|
|
|
|
assert "[Built-in] Grid_2x2" in templates
|
|
assert "My_Template" in templates
|
|
assert len(templates) == 2
|
|
|
|
def test_save_template(self, tmp_path, monkeypatch):
|
|
"""Test saving a template"""
|
|
user_dir = tmp_path / "user_templates"
|
|
user_dir.mkdir()
|
|
|
|
manager = TemplateManager()
|
|
monkeypatch.setattr(manager, 'templates_dir', user_dir)
|
|
|
|
template = Template(name="Test Template")
|
|
manager.save_template(template)
|
|
|
|
# Verify file was created
|
|
template_file = user_dir / "Test Template.json"
|
|
assert template_file.exists()
|
|
|
|
def test_load_template_user(self, tmp_path, monkeypatch):
|
|
"""Test loading a user template"""
|
|
user_dir = tmp_path / "user_templates"
|
|
user_dir.mkdir()
|
|
|
|
# Create template file
|
|
data = {"name": "User Template", "description": "Test", "page_size_mm": [210, 297], "elements": []}
|
|
template_file = user_dir / "User Template.json"
|
|
with open(template_file, 'w') as f:
|
|
json.dump(data, f)
|
|
|
|
manager = TemplateManager()
|
|
monkeypatch.setattr(manager, 'templates_dir', user_dir)
|
|
|
|
template = manager.load_template("User Template")
|
|
assert template.name == "User Template"
|
|
|
|
def test_load_template_builtin(self, tmp_path, monkeypatch):
|
|
"""Test loading a built-in template"""
|
|
builtin_dir = tmp_path / "builtin_templates"
|
|
builtin_dir.mkdir()
|
|
|
|
# Create built-in template file
|
|
data = {"name": "Grid 2x2", "description": "Built-in grid", "page_size_mm": [210, 297], "elements": []}
|
|
template_file = builtin_dir / "Grid 2x2.json"
|
|
with open(template_file, 'w') as f:
|
|
json.dump(data, f)
|
|
|
|
manager = TemplateManager()
|
|
monkeypatch.setattr(manager, '_get_builtin_templates_directory', lambda: builtin_dir)
|
|
|
|
template = manager.load_template("[Built-in] Grid 2x2")
|
|
assert template.name == "Grid 2x2"
|
|
|
|
def test_load_template_not_found(self, tmp_path, monkeypatch):
|
|
"""Test loading non-existent template raises error"""
|
|
user_dir = tmp_path / "user_templates"
|
|
user_dir.mkdir()
|
|
|
|
manager = TemplateManager()
|
|
monkeypatch.setattr(manager, 'templates_dir', user_dir)
|
|
|
|
with pytest.raises(FileNotFoundError):
|
|
manager.load_template("NonExistent")
|
|
|
|
def test_delete_template(self, tmp_path, monkeypatch):
|
|
"""Test deleting a user template"""
|
|
user_dir = tmp_path / "user_templates"
|
|
user_dir.mkdir()
|
|
|
|
# Create template file
|
|
template_file = user_dir / "DeleteMe.json"
|
|
template_file.write_text('{"name": "DeleteMe"}')
|
|
|
|
manager = TemplateManager()
|
|
monkeypatch.setattr(manager, 'templates_dir', user_dir)
|
|
|
|
manager.delete_template("DeleteMe")
|
|
assert not template_file.exists()
|
|
|
|
def test_delete_builtin_template_raises_error(self):
|
|
"""Test deleting built-in template raises error"""
|
|
manager = TemplateManager()
|
|
|
|
with pytest.raises(PermissionError):
|
|
manager.delete_template("[Built-in] Grid_2x2")
|
|
|
|
def test_create_template_from_page(self):
|
|
"""Test creating template from a page"""
|
|
# Create a page with various elements
|
|
layout = PageLayout(width=210, height=297)
|
|
img = ImageData(image_path="test.jpg", x=10, y=20, width=100, height=50)
|
|
text = TextBoxData(text_content="Test", x=30, y=40, width=150, height=60)
|
|
placeholder = PlaceholderData(x=50, y=60, width=120, height=70)
|
|
|
|
layout.add_element(img)
|
|
layout.add_element(text)
|
|
layout.add_element(placeholder)
|
|
|
|
page = Page(layout=layout, page_number=1)
|
|
|
|
# Create template
|
|
manager = TemplateManager()
|
|
template = manager.create_template_from_page(
|
|
page,
|
|
name="Test Template",
|
|
description="Created from page"
|
|
)
|
|
|
|
assert template.name == "Test Template"
|
|
assert template.description == "Created from page"
|
|
assert len(template.elements) == 3
|
|
|
|
# Image should be converted to placeholder
|
|
assert isinstance(template.elements[0], PlaceholderData)
|
|
assert isinstance(template.elements[1], TextBoxData)
|
|
assert isinstance(template.elements[2], PlaceholderData)
|
|
|
|
def test_scale_template_elements_proportional(self):
|
|
"""Test scaling template elements proportionally"""
|
|
manager = TemplateManager()
|
|
|
|
# Create elements at 200x200 size
|
|
elem = PlaceholderData(x=50, y=50, width=100, height=100)
|
|
elements = [elem]
|
|
|
|
# Scale to 400x400 (2x scale)
|
|
scaled = manager.scale_template_elements(
|
|
elements,
|
|
from_size=(200, 200),
|
|
to_size=(400, 400),
|
|
scale_mode="proportional"
|
|
)
|
|
|
|
assert len(scaled) == 1
|
|
# With proportional scaling and centering
|
|
# scale = min(400/200, 400/200) = 2.0
|
|
# offset = (400 - 200*2) / 2 = 0
|
|
assert scaled[0].position == (100, 100) # 50 * 2 + 0
|
|
assert scaled[0].size == (200, 200) # 100 * 2
|
|
|
|
def test_scale_template_elements_stretch(self):
|
|
"""Test scaling template elements with stretch mode"""
|
|
manager = TemplateManager()
|
|
|
|
elem = PlaceholderData(x=50, y=50, width=100, height=100)
|
|
elements = [elem]
|
|
|
|
# Scale to 400x200 (2x width, 1x height)
|
|
scaled = manager.scale_template_elements(
|
|
elements,
|
|
from_size=(200, 200),
|
|
to_size=(400, 200),
|
|
scale_mode="stretch"
|
|
)
|
|
|
|
assert len(scaled) == 1
|
|
assert scaled[0].position == (100, 50) # 50 * 2, 50 * 1
|
|
assert scaled[0].size == (200, 100) # 100 * 2, 100 * 1
|
|
|
|
def test_scale_template_elements_center(self):
|
|
"""Test scaling template elements with center mode"""
|
|
manager = TemplateManager()
|
|
|
|
elem = PlaceholderData(x=50, y=50, width=100, height=100)
|
|
elements = [elem]
|
|
|
|
# Center in larger space without scaling
|
|
scaled = manager.scale_template_elements(
|
|
elements,
|
|
from_size=(200, 200),
|
|
to_size=(400, 400),
|
|
scale_mode="center"
|
|
)
|
|
|
|
assert len(scaled) == 1
|
|
# offset = (400 - 200) / 2 = 100
|
|
assert scaled[0].position == (150, 150) # 50 + 100
|
|
assert scaled[0].size == (100, 100) # No scaling
|
|
|
|
def test_scale_template_preserves_properties(self):
|
|
"""Test that scaling preserves element properties"""
|
|
manager = TemplateManager()
|
|
|
|
elem = PlaceholderData(x=50, y=50, width=100, height=100)
|
|
elem.rotation = 45
|
|
elem.z_index = 5
|
|
elem.placeholder_type = "image"
|
|
|
|
scaled = manager.scale_template_elements(
|
|
[elem],
|
|
from_size=(200, 200),
|
|
to_size=(400, 400),
|
|
scale_mode="proportional"
|
|
)
|
|
|
|
assert scaled[0].rotation == 45
|
|
assert scaled[0].z_index == 5
|
|
assert scaled[0].placeholder_type == "image"
|
|
|
|
def test_apply_template_to_page_replace(self):
|
|
"""Test applying template with replace mode"""
|
|
manager = TemplateManager()
|
|
|
|
# Create template
|
|
template = Template(page_size_mm=(200, 200))
|
|
template.add_element(PlaceholderData(x=10, y=20, width=80, height=60))
|
|
|
|
# Create page with existing content
|
|
layout = PageLayout(width=200, height=200)
|
|
layout.add_element(ImageData(x=100, y=100, width=50, height=50))
|
|
page = Page(layout=layout, page_number=1)
|
|
|
|
# Apply template
|
|
manager.apply_template_to_page(template, page, mode="replace")
|
|
|
|
# Page should have only template elements
|
|
assert len(page.layout.elements) == 1
|
|
assert isinstance(page.layout.elements[0], PlaceholderData)
|
|
|
|
def test_apply_template_to_page_reflow(self):
|
|
"""Test applying template with reflow mode"""
|
|
manager = TemplateManager()
|
|
|
|
# Create template with 2 placeholders
|
|
template = Template(page_size_mm=(200, 200))
|
|
template.add_element(PlaceholderData(x=10, y=20, width=80, height=60))
|
|
template.add_element(PlaceholderData(x=100, y=100, width=80, height=60))
|
|
|
|
# Create page with 1 image
|
|
layout = PageLayout(width=200, height=200)
|
|
img = ImageData(image_path="test.jpg", x=50, y=50, width=50, height=50)
|
|
layout.add_element(img)
|
|
page = Page(layout=layout, page_number=1)
|
|
|
|
# Apply template with reflow
|
|
manager.apply_template_to_page(template, page, mode="reflow")
|
|
|
|
# Should have 1 image (reflowed) + 1 placeholder
|
|
assert len(page.layout.elements) == 2
|
|
# First should be the reflowed image
|
|
assert isinstance(page.layout.elements[0], ImageData)
|
|
# Second should be placeholder (no image to fill it)
|
|
assert isinstance(page.layout.elements[1], PlaceholderData)
|
|
|
|
def test_create_page_from_template_default_size(self):
|
|
"""Test creating page from template with default size"""
|
|
manager = TemplateManager()
|
|
|
|
# Create template
|
|
template = Template(page_size_mm=(210, 297))
|
|
template.add_element(PlaceholderData(x=10, y=20, width=100, height=50))
|
|
|
|
# Create page
|
|
page = manager.create_page_from_template(template, page_number=5)
|
|
|
|
assert page.page_number == 5
|
|
assert page.layout.size == (210, 297)
|
|
assert len(page.layout.elements) == 1
|
|
assert isinstance(page.layout.elements[0], PlaceholderData)
|
|
|
|
def test_create_page_from_template_custom_size(self):
|
|
"""Test creating page from template with custom size"""
|
|
manager = TemplateManager()
|
|
|
|
# Create template at 200x200
|
|
template = Template(page_size_mm=(200, 200))
|
|
template.add_element(PlaceholderData(x=50, y=50, width=100, height=100))
|
|
|
|
# Create page at 400x400
|
|
page = manager.create_page_from_template(
|
|
template,
|
|
page_number=1,
|
|
target_size_mm=(400, 400),
|
|
scale_mode="proportional"
|
|
)
|
|
|
|
assert page.layout.size == (400, 400)
|
|
assert len(page.layout.elements) == 1
|
|
# Element should be scaled
|
|
assert page.layout.elements[0].size == (200, 200) # 100 * 2
|
|
|
|
def test_scale_with_textbox_preserves_font_settings(self):
|
|
"""Test that scaling preserves text box font settings"""
|
|
manager = TemplateManager()
|
|
|
|
font_settings = {"family": "Arial", "size": 12, "color": (0, 0, 0)}
|
|
text = TextBoxData(
|
|
text_content="Test",
|
|
font_settings=font_settings,
|
|
x=50,
|
|
y=50,
|
|
width=100,
|
|
height=50
|
|
)
|
|
|
|
scaled = manager.scale_template_elements(
|
|
[text],
|
|
from_size=(200, 200),
|
|
to_size=(400, 400),
|
|
scale_mode="proportional"
|
|
)
|
|
|
|
assert scaled[0].text_content == "Test"
|
|
assert scaled[0].font_settings == font_settings
|
|
assert scaled[0].alignment == text.alignment
|
|
|
|
def test_grid_2x2_stretch_to_square_page(self):
|
|
"""Test Grid_2x2 template applied to square page with stretch mode"""
|
|
manager = TemplateManager()
|
|
|
|
# Create a 2x2 grid template at 210x210mm (margin-less, fills entire space)
|
|
template = Template(name="Grid_2x2", page_size_mm=(210, 210))
|
|
# 4 cells: each 105 x 105mm (half of 210mm)
|
|
template.add_element(PlaceholderData(x=0, y=0, width=105, height=105))
|
|
template.add_element(PlaceholderData(x=105, y=0, width=105, height=105))
|
|
template.add_element(PlaceholderData(x=0, y=105, width=105, height=105))
|
|
template.add_element(PlaceholderData(x=105, y=105, width=105, height=105))
|
|
|
|
# Apply to same size page with stretch mode and 2.5% margin
|
|
layout = PageLayout(width=210, height=210)
|
|
page = Page(layout=layout, page_number=1)
|
|
|
|
manager.apply_template_to_page(
|
|
template, page,
|
|
mode="replace",
|
|
scale_mode="stretch",
|
|
margin_percent=2.5
|
|
)
|
|
|
|
# With 2.5% margin on 210mm page: margin = 5.25mm, content area = 199.5mm
|
|
# Template is 210mm, so scale = 199.5 / 210 = 0.95
|
|
# Each element should scale by 0.95 and be offset by margin
|
|
assert len(page.layout.elements) == 4
|
|
|
|
# Check first element (top-left)
|
|
elem = page.layout.elements[0]
|
|
scale = 199.5 / 210.0 # 0.95
|
|
expected_x = 0 * scale + 5.25 # 0 + 5.25 = 5.25
|
|
expected_y = 0 * scale + 5.25 # 0 + 5.25 = 5.25
|
|
expected_width = 105 * scale # 99.75
|
|
expected_height = 105 * scale # 99.75
|
|
|
|
assert abs(elem.position[0] - expected_x) < 0.1
|
|
assert abs(elem.position[1] - expected_y) < 0.1
|
|
assert abs(elem.size[0] - expected_width) < 0.1
|
|
assert abs(elem.size[1] - expected_height) < 0.1
|
|
|
|
def test_grid_2x2_stretch_to_a4_page(self):
|
|
"""Test Grid_2x2 template applied to A4 page with stretch mode"""
|
|
manager = TemplateManager()
|
|
|
|
# Create Grid_2x2 template (210x210mm, margin-less)
|
|
template = Template(name="Grid_2x2", page_size_mm=(210, 210))
|
|
template.add_element(PlaceholderData(x=0, y=0, width=105, height=105))
|
|
template.add_element(PlaceholderData(x=105, y=0, width=105, height=105))
|
|
template.add_element(PlaceholderData(x=0, y=105, width=105, height=105))
|
|
template.add_element(PlaceholderData(x=105, y=105, width=105, height=105))
|
|
|
|
# Apply to A4 page (210x297mm) with stretch mode and 2.5% margin
|
|
layout = PageLayout(width=210, height=297)
|
|
page = Page(layout=layout, page_number=1)
|
|
|
|
manager.apply_template_to_page(
|
|
template, page,
|
|
mode="replace",
|
|
scale_mode="stretch",
|
|
margin_percent=2.5
|
|
)
|
|
|
|
# With 2.5% margin: x_margin = 5.25mm, y_margin = 7.425mm
|
|
# Content area: 199.5 x 282.15mm
|
|
# Scale: x = 199.5/210 = 0.95, y = 282.15/210 = 1.3436
|
|
assert len(page.layout.elements) == 4
|
|
|
|
# First element should stretch
|
|
elem = page.layout.elements[0]
|
|
scale_x = 199.5 / 210.0
|
|
scale_y = 282.15 / 210.0
|
|
|
|
expected_x = 0 * scale_x + 5.25 # 5.25
|
|
expected_y = 0 * scale_y + 7.425 # 7.425
|
|
expected_width = 105 * scale_x # 99.75
|
|
expected_height = 105 * scale_y # 141.075
|
|
|
|
assert abs(elem.position[0] - expected_x) < 0.1
|
|
assert abs(elem.position[1] - expected_y) < 0.1
|
|
assert abs(elem.size[0] - expected_width) < 0.1
|
|
assert abs(elem.size[1] - expected_height) < 0.1
|
|
|
|
def test_grid_2x2_with_different_margins(self):
|
|
"""Test Grid_2x2 template with different margin percentages"""
|
|
manager = TemplateManager()
|
|
|
|
template = Template(name="Grid_2x2", page_size_mm=(210, 210))
|
|
template.add_element(PlaceholderData(x=0, y=0, width=105, height=105))
|
|
|
|
# Test with 0% margin
|
|
layout = PageLayout(width=210, height=210)
|
|
page = Page(layout=layout, page_number=1)
|
|
|
|
manager.apply_template_to_page(
|
|
template, page,
|
|
mode="replace",
|
|
scale_mode="stretch",
|
|
margin_percent=0.0
|
|
)
|
|
|
|
# With 0% margin, template fills entire page (scale = 1.0, offset = 0)
|
|
elem = page.layout.elements[0]
|
|
assert abs(elem.position[0] - 0.0) < 0.1
|
|
assert abs(elem.position[1] - 0.0) < 0.1
|
|
assert abs(elem.size[0] - 105.0) < 0.1
|
|
|
|
# Test with 5% margin
|
|
layout2 = PageLayout(width=210, height=210)
|
|
page2 = Page(layout=layout2, page_number=1)
|
|
|
|
manager.apply_template_to_page(
|
|
template, page2,
|
|
mode="replace",
|
|
scale_mode="stretch",
|
|
margin_percent=5.0
|
|
)
|
|
|
|
# With 5% margin: margin = 10.5mm, content = 189mm, scale = 189/210 = 0.9
|
|
elem2 = page2.layout.elements[0]
|
|
assert abs(elem2.position[0] - 10.5) < 0.1
|
|
assert abs(elem2.position[1] - 10.5) < 0.1
|
|
assert abs(elem2.size[0] - (105 * 0.9)) < 0.1
|
|
|
|
def test_grid_2x2_proportional_mode(self):
|
|
"""Test Grid_2x2 template with proportional scaling"""
|
|
manager = TemplateManager()
|
|
|
|
template = Template(name="Grid_2x2", page_size_mm=(210, 210))
|
|
template.add_element(PlaceholderData(x=0, y=0, width=105, height=105))
|
|
|
|
# Apply to rectangular page with proportional mode
|
|
layout = PageLayout(width=210, height=297)
|
|
page = Page(layout=layout, page_number=1)
|
|
|
|
manager.apply_template_to_page(
|
|
template, page,
|
|
mode="replace",
|
|
scale_mode="proportional",
|
|
margin_percent=2.5
|
|
)
|
|
|
|
# With proportional mode on 210x297 page:
|
|
# Content area: 199.5 x 282.15mm
|
|
# Template: 210 x 210mm
|
|
# Scale = min(199.5/210, 282.15/210) = 0.95 (uniform)
|
|
# Content is centered on page
|
|
|
|
elem = page.layout.elements[0]
|
|
scale = 199.5 / 210.0
|
|
|
|
# Should be scaled uniformly
|
|
expected_width = 105 * scale # 99.75
|
|
expected_height = 105 * scale # 99.75
|
|
|
|
assert abs(elem.size[0] - expected_width) < 0.1
|
|
assert abs(elem.size[1] - expected_height) < 0.1
|
|
# Width should equal height (uniform scaling)
|
|
assert abs(elem.size[0] - elem.size[1]) < 0.1
|