All checks were successful
Python CI / test (push) Successful in 1m20s
Lint / lint (push) Successful in 1m4s
Tests / test (3.11) (push) Successful in 1m27s
Tests / test (3.12) (push) Successful in 2m25s
Tests / test (3.13) (push) Successful in 2m52s
Tests / test (3.14) (push) Successful in 1m9s
734 lines
27 KiB
Python
734 lines
27 KiB
Python
"""
|
|
Tests for PageSetupDialog
|
|
"""
|
|
|
|
import pytest
|
|
from unittest.mock import Mock, MagicMock, patch
|
|
from PyQt6.QtWidgets import QDialog
|
|
from pyPhotoAlbum.dialogs.page_setup_dialog import PageSetupDialog
|
|
from pyPhotoAlbum.project import Project, Page
|
|
from pyPhotoAlbum.page_layout import PageLayout
|
|
|
|
|
|
class TestPageSetupDialog:
|
|
"""Test PageSetupDialog UI component"""
|
|
|
|
def test_dialog_initialization(self, qtbot):
|
|
"""Test dialog initializes with project data"""
|
|
project = Project(name="Test")
|
|
project.paper_thickness_mm = 0.1
|
|
project.cover_bleed_mm = 3.0
|
|
project.working_dpi = 96
|
|
project.export_dpi = 300
|
|
project.page_size_mm = (210, 297)
|
|
|
|
page = Page(layout=PageLayout(width=210, height=297), page_number=1)
|
|
project.pages = [page]
|
|
|
|
dialog = PageSetupDialog(None, project, initial_page_index=0)
|
|
qtbot.addWidget(dialog)
|
|
|
|
# Check dialog is created
|
|
assert dialog.windowTitle() == "Page Setup"
|
|
assert dialog.minimumWidth() == 450
|
|
|
|
# Check DPI values initialized correctly
|
|
assert dialog.working_dpi_spinbox.value() == 96
|
|
assert dialog.export_dpi_spinbox.value() == 300
|
|
|
|
# Check cover settings initialized correctly
|
|
assert dialog.thickness_spinbox.value() == 0.1
|
|
assert dialog.bleed_spinbox.value() == 3.0
|
|
|
|
def test_dialog_page_selection(self, qtbot):
|
|
"""Test page selection combo box populated correctly"""
|
|
project = Project(name="Test")
|
|
project.page_size_mm = (210, 297)
|
|
|
|
page1 = Page(layout=PageLayout(width=210, height=297), page_number=1)
|
|
page2 = Page(layout=PageLayout(width=210, height=297), page_number=2)
|
|
page2.manually_sized = True
|
|
page3 = Page(layout=PageLayout(width=420, height=297), page_number=3)
|
|
page3.is_double_spread = True
|
|
|
|
project.pages = [page1, page2, page3]
|
|
|
|
dialog = PageSetupDialog(None, project, initial_page_index=0)
|
|
qtbot.addWidget(dialog)
|
|
|
|
# Check combo box has all pages
|
|
assert dialog.page_combo.count() == 3
|
|
|
|
# Check page labels
|
|
assert "Page 1" in dialog.page_combo.itemText(0)
|
|
assert "Page 2" in dialog.page_combo.itemText(1)
|
|
assert "*" in dialog.page_combo.itemText(1) # Manually sized marker
|
|
# Page 3 is a double spread, so it shows as "Pages 3-4"
|
|
assert "Pages 3-4" in dialog.page_combo.itemText(2) or "Page 3" in dialog.page_combo.itemText(2)
|
|
assert "Double Spread" in dialog.page_combo.itemText(2)
|
|
|
|
def test_dialog_cover_settings_visibility(self, qtbot):
|
|
"""Test cover settings visibility toggled based on page selection"""
|
|
project = Project(name="Test")
|
|
project.page_size_mm = (210, 297)
|
|
|
|
page1 = Page(layout=PageLayout(width=210, height=297), page_number=1)
|
|
page2 = Page(layout=PageLayout(width=210, height=297), page_number=2)
|
|
project.pages = [page1, page2]
|
|
|
|
dialog = PageSetupDialog(None, project, initial_page_index=0)
|
|
qtbot.addWidget(dialog)
|
|
|
|
# Test the _on_page_changed method directly (testing business logic)
|
|
# When showing first page (index 0), cover group should be made visible
|
|
dialog._on_page_changed(0)
|
|
# We can't reliably test isVisible() in headless Qt, but we can verify
|
|
# the method was called and completed without error
|
|
|
|
# When showing second page (index 1), cover group should be hidden
|
|
dialog._on_page_changed(1)
|
|
|
|
# Test that invalid indices are handled gracefully
|
|
dialog._on_page_changed(-1) # Should return early
|
|
dialog._on_page_changed(999) # Should return early
|
|
|
|
# Verify page combo was populated correctly
|
|
assert dialog.page_combo.count() == 2
|
|
|
|
def test_dialog_cover_disables_size_editing(self, qtbot):
|
|
"""Test cover pages disable size editing"""
|
|
project = Project(name="Test")
|
|
project.page_size_mm = (210, 297)
|
|
|
|
page1 = Page(layout=PageLayout(width=500, height=297), page_number=1)
|
|
page1.is_cover = True
|
|
project.pages = [page1]
|
|
|
|
dialog = PageSetupDialog(None, project, initial_page_index=0)
|
|
qtbot.addWidget(dialog)
|
|
|
|
# Size editing should be disabled for covers
|
|
assert not dialog.width_spinbox.isEnabled()
|
|
assert not dialog.height_spinbox.isEnabled()
|
|
assert not dialog.set_default_checkbox.isEnabled()
|
|
|
|
def test_dialog_double_spread_width_calculation(self, qtbot):
|
|
"""Test double spread shows per-page width, not total width"""
|
|
project = Project(name="Test")
|
|
project.page_size_mm = (210, 297)
|
|
|
|
page = Page(layout=PageLayout(width=420, height=297), page_number=1)
|
|
page.is_double_spread = True
|
|
page.layout.base_width = 210
|
|
project.pages = [page]
|
|
|
|
dialog = PageSetupDialog(None, project, initial_page_index=0)
|
|
qtbot.addWidget(dialog)
|
|
|
|
# Should show base width (per-page width), not total width
|
|
assert dialog.width_spinbox.value() == 210
|
|
assert dialog.height_spinbox.value() == 297
|
|
|
|
def test_dialog_spine_info_calculation(self, qtbot):
|
|
"""Test spine info is calculated correctly"""
|
|
project = Project(name="Test")
|
|
project.page_size_mm = (210, 297)
|
|
project.paper_thickness_mm = 0.1
|
|
project.cover_bleed_mm = 3.0
|
|
|
|
page1 = Page(layout=PageLayout(width=210, height=297), page_number=1)
|
|
page1.is_cover = False
|
|
page2 = Page(layout=PageLayout(width=210, height=297), page_number=2)
|
|
page3 = Page(layout=PageLayout(width=210, height=297), page_number=3)
|
|
project.pages = [page1, page2, page3]
|
|
|
|
dialog = PageSetupDialog(None, project, initial_page_index=0)
|
|
qtbot.addWidget(dialog)
|
|
|
|
# Enable cover checkbox
|
|
dialog.cover_checkbox.setChecked(True)
|
|
|
|
# Check spine info label has content
|
|
spine_text = dialog.spine_info_label.text()
|
|
assert "Cover Layout" in spine_text
|
|
assert "Front" in spine_text
|
|
assert "Spine" in spine_text
|
|
assert "Back" in spine_text
|
|
assert "Bleed" in spine_text
|
|
|
|
# Disable cover checkbox
|
|
dialog.cover_checkbox.setChecked(False)
|
|
|
|
# Spine info should be empty
|
|
assert dialog.spine_info_label.text() == ""
|
|
|
|
def test_get_values_returns_correct_data(self, qtbot):
|
|
"""Test get_values returns all dialog values"""
|
|
project = Project(name="Test")
|
|
project.page_size_mm = (210, 297)
|
|
project.paper_thickness_mm = 0.1
|
|
project.cover_bleed_mm = 3.0
|
|
project.working_dpi = 96
|
|
project.export_dpi = 300
|
|
|
|
page = Page(layout=PageLayout(width=210, height=297), page_number=1)
|
|
project.pages = [page]
|
|
|
|
dialog = PageSetupDialog(None, project, initial_page_index=0)
|
|
qtbot.addWidget(dialog)
|
|
|
|
# Modify some values
|
|
dialog.width_spinbox.setValue(200)
|
|
dialog.height_spinbox.setValue(280)
|
|
dialog.working_dpi_spinbox.setValue(150)
|
|
dialog.export_dpi_spinbox.setValue(600)
|
|
dialog.set_default_checkbox.setChecked(True)
|
|
dialog.cover_checkbox.setChecked(True)
|
|
dialog.thickness_spinbox.setValue(0.15)
|
|
dialog.bleed_spinbox.setValue(5.0)
|
|
|
|
values = dialog.get_values()
|
|
|
|
# Check all values returned
|
|
assert values["selected_index"] == 0
|
|
assert values["selected_page"] == page
|
|
assert values["is_cover"] is True
|
|
assert values["paper_thickness_mm"] == 0.15
|
|
assert values["cover_bleed_mm"] == 5.0
|
|
assert values["width_mm"] == 200
|
|
assert values["height_mm"] == 280
|
|
assert values["working_dpi"] == 150
|
|
assert values["export_dpi"] == 600
|
|
assert values["set_as_default"] is True
|
|
|
|
def test_dialog_page_change_updates_values(self, qtbot):
|
|
"""Test changing selected page updates displayed values"""
|
|
project = Project(name="Test")
|
|
project.page_size_mm = (210, 297)
|
|
|
|
page1 = Page(layout=PageLayout(width=210, height=297), page_number=1)
|
|
page2 = Page(layout=PageLayout(width=180, height=250), page_number=2)
|
|
project.pages = [page1, page2]
|
|
|
|
dialog = PageSetupDialog(None, project, initial_page_index=0)
|
|
qtbot.addWidget(dialog)
|
|
|
|
# Initially showing page 1 values
|
|
assert dialog.width_spinbox.value() == 210
|
|
assert dialog.height_spinbox.value() == 297
|
|
|
|
# Change to page 2
|
|
dialog.page_combo.setCurrentIndex(1)
|
|
|
|
# Should now show page 2 values
|
|
assert dialog.width_spinbox.value() == 180
|
|
assert dialog.height_spinbox.value() == 250
|
|
|
|
|
|
class TestDialogMixin:
|
|
"""Test DialogMixin functionality"""
|
|
|
|
def test_dialog_mixin_create_dialog_accepted(self, qtbot):
|
|
"""Test create_dialog returns values when accepted"""
|
|
from pyPhotoAlbum.mixins.dialog_mixin import DialogMixin
|
|
|
|
class TestWindow(DialogMixin):
|
|
pass
|
|
|
|
window = TestWindow()
|
|
|
|
# Create mock dialog with get_values as a proper method
|
|
mock_dialog = MagicMock(spec=QDialog)
|
|
mock_dialog.exec = Mock(return_value=QDialog.DialogCode.Accepted)
|
|
mock_dialog.get_values = Mock(return_value={"test": "value"})
|
|
|
|
# Mock dialog class
|
|
mock_dialog_class = Mock(return_value=mock_dialog)
|
|
|
|
result = window.create_dialog(mock_dialog_class)
|
|
|
|
assert result == {"test": "value"}
|
|
mock_dialog.exec.assert_called_once()
|
|
|
|
def test_dialog_mixin_create_dialog_rejected(self, qtbot):
|
|
"""Test create_dialog returns None when rejected"""
|
|
from pyPhotoAlbum.mixins.dialog_mixin import DialogMixin
|
|
|
|
class TestWindow(DialogMixin):
|
|
pass
|
|
|
|
window = TestWindow()
|
|
|
|
# Create mock dialog
|
|
mock_dialog = Mock(spec=QDialog)
|
|
mock_dialog.exec.return_value = QDialog.DialogCode.Rejected
|
|
|
|
# Mock dialog class
|
|
mock_dialog_class = Mock(return_value=mock_dialog)
|
|
|
|
result = window.create_dialog(mock_dialog_class)
|
|
|
|
assert result is None
|
|
mock_dialog.exec.assert_called_once()
|
|
|
|
def test_dialog_mixin_show_dialog_with_callback(self, qtbot):
|
|
"""Test show_dialog executes callback on acceptance"""
|
|
from pyPhotoAlbum.mixins.dialog_mixin import DialogMixin
|
|
|
|
class TestWindow(DialogMixin):
|
|
pass
|
|
|
|
window = TestWindow()
|
|
|
|
# Create mock dialog with get_values as a proper method
|
|
mock_dialog = MagicMock(spec=QDialog)
|
|
mock_dialog.exec = Mock(return_value=QDialog.DialogCode.Accepted)
|
|
mock_dialog.get_values = Mock(return_value={"test": "value"})
|
|
|
|
# Mock dialog class
|
|
mock_dialog_class = Mock(return_value=mock_dialog)
|
|
|
|
# Mock callback
|
|
callback = Mock()
|
|
|
|
result = window.show_dialog(mock_dialog_class, on_accept=callback)
|
|
|
|
assert result is True
|
|
callback.assert_called_once_with({"test": "value"})
|
|
|
|
|
|
class TestDialogActionDecorator:
|
|
"""Test the @dialog_action decorator functionality"""
|
|
|
|
def test_decorator_with_title_override(self, qtbot):
|
|
"""Test decorator can set custom dialog title"""
|
|
from pyPhotoAlbum.decorators import dialog_action
|
|
|
|
# We'll test that the decorator can pass through kwargs
|
|
# This is more of a structural test
|
|
decorator = dialog_action(dialog_class=PageSetupDialog, requires_pages=True)
|
|
assert decorator.dialog_class == PageSetupDialog
|
|
assert decorator.requires_pages is True
|
|
|
|
def test_decorator_without_pages_requirement(self, qtbot):
|
|
"""Test decorator can disable page requirement"""
|
|
from pyPhotoAlbum.decorators import dialog_action
|
|
|
|
decorator = dialog_action(dialog_class=PageSetupDialog, requires_pages=False)
|
|
assert decorator.requires_pages is False
|
|
|
|
def test_dialog_action_class_decorator(self, qtbot):
|
|
"""Test DialogAction class directly"""
|
|
from pyPhotoAlbum.decorators import DialogAction
|
|
|
|
decorator = DialogAction(dialog_class=PageSetupDialog, requires_pages=True)
|
|
assert decorator.dialog_class == PageSetupDialog
|
|
assert decorator.requires_pages is True
|
|
|
|
|
|
class TestDialogMixinEdgeCases:
|
|
"""Test edge cases for DialogMixin"""
|
|
|
|
def test_create_dialog_without_get_values(self, qtbot):
|
|
"""Test create_dialog when dialog has no get_values method"""
|
|
from pyPhotoAlbum.mixins.dialog_mixin import DialogMixin
|
|
|
|
class TestWindow(DialogMixin):
|
|
pass
|
|
|
|
window = TestWindow()
|
|
|
|
# Create mock dialog WITHOUT get_values
|
|
mock_dialog = MagicMock(spec=QDialog)
|
|
mock_dialog.exec = Mock(return_value=QDialog.DialogCode.Accepted)
|
|
# Explicitly make get_values unavailable
|
|
del mock_dialog.get_values
|
|
|
|
mock_dialog_class = Mock(return_value=mock_dialog)
|
|
|
|
result = window.create_dialog(mock_dialog_class)
|
|
|
|
# Should return True when accepted even without get_values
|
|
assert result is True
|
|
|
|
def test_create_dialog_with_title(self, qtbot):
|
|
"""Test create_dialog with custom title"""
|
|
from pyPhotoAlbum.mixins.dialog_mixin import DialogMixin
|
|
|
|
class TestWindow(DialogMixin):
|
|
pass
|
|
|
|
window = TestWindow()
|
|
|
|
mock_dialog = MagicMock(spec=QDialog)
|
|
mock_dialog.exec = Mock(return_value=QDialog.DialogCode.Accepted)
|
|
mock_dialog.get_values = Mock(return_value={"data": "test"})
|
|
|
|
mock_dialog_class = Mock(return_value=mock_dialog)
|
|
|
|
result = window.create_dialog(mock_dialog_class, title="Custom Title")
|
|
|
|
# Verify setWindowTitle was called
|
|
mock_dialog.setWindowTitle.assert_called_once_with("Custom Title")
|
|
assert result == {"data": "test"}
|
|
|
|
def test_show_dialog_rejected(self, qtbot):
|
|
"""Test show_dialog when user rejects dialog"""
|
|
from pyPhotoAlbum.mixins.dialog_mixin import DialogMixin
|
|
|
|
class TestWindow(DialogMixin):
|
|
pass
|
|
|
|
window = TestWindow()
|
|
|
|
mock_dialog = MagicMock(spec=QDialog)
|
|
mock_dialog.exec = Mock(return_value=QDialog.DialogCode.Rejected)
|
|
|
|
mock_dialog_class = Mock(return_value=mock_dialog)
|
|
callback = Mock()
|
|
|
|
result = window.show_dialog(mock_dialog_class, on_accept=callback)
|
|
|
|
# Callback should not be called
|
|
callback.assert_not_called()
|
|
assert result is False
|
|
|
|
|
|
class TestPageSetupDialogEdgeCases:
|
|
"""Test edge cases in PageSetupDialog"""
|
|
|
|
def test_dialog_with_cover_page(self, qtbot):
|
|
"""Test dialog correctly handles cover pages"""
|
|
project = Project(name="Test")
|
|
project.page_size_mm = (210, 297)
|
|
project.paper_thickness_mm = 0.1
|
|
project.cover_bleed_mm = 3.0
|
|
|
|
page1 = Page(layout=PageLayout(width=500, height=297), page_number=1)
|
|
page1.is_cover = True
|
|
project.pages = [page1]
|
|
|
|
dialog = PageSetupDialog(None, project, initial_page_index=0)
|
|
qtbot.addWidget(dialog)
|
|
|
|
# Cover checkbox should be checked
|
|
assert dialog.cover_checkbox.isChecked()
|
|
|
|
# Width spinbox should show full cover width
|
|
assert dialog.width_spinbox.value() == 500
|
|
|
|
def test_dialog_invalid_initial_page_index(self, qtbot):
|
|
"""Test dialog handles invalid initial page index gracefully"""
|
|
project = Project(name="Test")
|
|
project.page_size_mm = (210, 297)
|
|
|
|
page = Page(layout=PageLayout(width=210, height=297), page_number=1)
|
|
project.pages = [page]
|
|
|
|
# Invalid initial index (out of bounds)
|
|
dialog = PageSetupDialog(None, project, initial_page_index=999)
|
|
qtbot.addWidget(dialog)
|
|
|
|
# Should still work, defaulting to first available page or handling gracefully
|
|
assert dialog.page_combo.count() == 1
|
|
|
|
def test_on_page_changed_invalid_index(self, qtbot):
|
|
"""Test _on_page_changed handles invalid indices"""
|
|
project = Project(name="Test")
|
|
project.page_size_mm = (210, 297)
|
|
|
|
page = Page(layout=PageLayout(width=210, height=297), page_number=1)
|
|
project.pages = [page]
|
|
|
|
dialog = PageSetupDialog(None, project, initial_page_index=0)
|
|
qtbot.addWidget(dialog)
|
|
|
|
# Call with negative index - should return early
|
|
dialog._on_page_changed(-1)
|
|
|
|
# Call with out of bounds index - should return early
|
|
dialog._on_page_changed(999)
|
|
|
|
# Dialog should still be functional
|
|
assert dialog.page_combo.count() == 1
|
|
|
|
def test_update_spine_info_when_not_cover(self, qtbot):
|
|
"""Test spine info is empty when cover checkbox is unchecked"""
|
|
project = Project(name="Test")
|
|
project.page_size_mm = (210, 297)
|
|
|
|
page = Page(layout=PageLayout(width=210, height=297), page_number=1)
|
|
project.pages = [page]
|
|
|
|
dialog = PageSetupDialog(None, project, initial_page_index=0)
|
|
qtbot.addWidget(dialog)
|
|
|
|
# Uncheck cover
|
|
dialog.cover_checkbox.setChecked(False)
|
|
|
|
# Spine info should be empty
|
|
assert dialog.spine_info_label.text() == ""
|
|
|
|
|
|
class TestPageSetupIntegration:
|
|
"""Integration tests for page_setup with decorator"""
|
|
|
|
def test_page_setup_decorator_requires_pages(self, qtbot):
|
|
"""Test page_setup decorator returns early when no pages"""
|
|
from PyQt6.QtWidgets import QMainWindow
|
|
from pyPhotoAlbum.mixins.base import ApplicationStateMixin
|
|
from pyPhotoAlbum.mixins.operations.page_ops import PageOperationsMixin
|
|
|
|
class TestWindow(PageOperationsMixin, ApplicationStateMixin, QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._project = Project(name="Test")
|
|
self._project.pages = [] # No pages
|
|
self._gl_widget = Mock()
|
|
self._status_bar = Mock()
|
|
self._update_view_called = False
|
|
|
|
def update_view(self):
|
|
self._update_view_called = True
|
|
|
|
def show_status(self, message, timeout=0):
|
|
pass
|
|
|
|
window = TestWindow()
|
|
qtbot.addWidget(window)
|
|
|
|
# Should return early without showing dialog
|
|
result = window.page_setup()
|
|
|
|
# No update should occur
|
|
assert not window._update_view_called
|
|
assert result is None
|
|
|
|
def test_page_setup_applies_values(self, qtbot):
|
|
"""Test page_setup applies dialog values to project"""
|
|
from PyQt6.QtWidgets import QMainWindow
|
|
from pyPhotoAlbum.mixins.base import ApplicationStateMixin
|
|
from pyPhotoAlbum.mixins.operations.page_ops import PageOperationsMixin
|
|
|
|
class TestWindow(PageOperationsMixin, ApplicationStateMixin, QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._project = Project(name="Test")
|
|
self._project.page_size_mm = (210, 297)
|
|
self._project.working_dpi = 96
|
|
self._project.export_dpi = 300
|
|
self._project.paper_thickness_mm = 0.1
|
|
self._project.cover_bleed_mm = 3.0
|
|
|
|
page = Page(layout=PageLayout(width=210, height=297), page_number=1)
|
|
self._project.pages = [page]
|
|
|
|
self._gl_widget = Mock()
|
|
self._gl_widget._page_renderers = []
|
|
self._status_bar = Mock()
|
|
self._update_view_called = False
|
|
self._status_message = None
|
|
|
|
def _get_most_visible_page_index(self):
|
|
return 0
|
|
|
|
def update_view(self):
|
|
self._update_view_called = True
|
|
|
|
def show_status(self, message, timeout=0):
|
|
self._status_message = message
|
|
|
|
window = TestWindow()
|
|
qtbot.addWidget(window)
|
|
|
|
# Create mock values that would come from dialog
|
|
values = {
|
|
"selected_index": 0,
|
|
"selected_page": window.project.pages[0],
|
|
"is_cover": False,
|
|
"paper_thickness_mm": 0.15,
|
|
"cover_bleed_mm": 5.0,
|
|
"width_mm": 200,
|
|
"height_mm": 280,
|
|
"working_dpi": 150,
|
|
"export_dpi": 600,
|
|
"set_as_default": True,
|
|
}
|
|
|
|
# Access the unwrapped function to test business logic directly
|
|
# The decorator wraps the function, so we need to get the original
|
|
# or call it through the wrapper with the right setup
|
|
import inspect
|
|
|
|
# Get the original function before decorators
|
|
original_func = window.page_setup
|
|
# Decorators return wrappers, but we can call them with values directly
|
|
# by accessing the innermost wrapped function
|
|
while hasattr(original_func, "__wrapped__"):
|
|
original_func = original_func.__wrapped__
|
|
|
|
# If no __wrapped__, the decorator system is different
|
|
# Let's just call the business logic method manually
|
|
# First, let's extract and call just the business logic
|
|
from pyPhotoAlbum.mixins.operations import page_ops
|
|
|
|
# Get the undecorated method from the class
|
|
undecorated_page_setup = page_ops.PageOperationsMixin.page_setup
|
|
# Find the innermost function
|
|
while hasattr(undecorated_page_setup, "__wrapped__"):
|
|
undecorated_page_setup = undecorated_page_setup.__wrapped__
|
|
|
|
# Call the business logic directly
|
|
undecorated_page_setup(window, values)
|
|
|
|
# Check values applied to project
|
|
assert window.project.paper_thickness_mm == 0.15
|
|
assert window.project.cover_bleed_mm == 5.0
|
|
assert window.project.working_dpi == 150
|
|
assert window.project.export_dpi == 600
|
|
assert window.project.page_size_mm == (200, 280) # set_as_default=True
|
|
|
|
# Check page size updated
|
|
assert window.project.pages[0].layout.size == (200, 280)
|
|
assert window.project.pages[0].manually_sized is True
|
|
|
|
# Check view updated
|
|
assert window._update_view_called
|
|
assert window._status_message is not None
|
|
|
|
def test_page_setup_cover_designation(self, qtbot):
|
|
"""Test page_setup correctly designates and un-designates covers"""
|
|
from PyQt6.QtWidgets import QMainWindow
|
|
from pyPhotoAlbum.mixins.base import ApplicationStateMixin
|
|
from pyPhotoAlbum.mixins.operations.page_ops import PageOperationsMixin
|
|
|
|
class TestWindow(PageOperationsMixin, ApplicationStateMixin, QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._project = Project(name="Test")
|
|
self._project.page_size_mm = (210, 297)
|
|
self._project.working_dpi = 96
|
|
self._project.export_dpi = 300
|
|
self._project.paper_thickness_mm = 0.1
|
|
self._project.cover_bleed_mm = 3.0
|
|
|
|
page = Page(layout=PageLayout(width=210, height=297), page_number=1)
|
|
page.is_cover = False
|
|
self._project.pages = [page]
|
|
|
|
self._gl_widget = Mock()
|
|
self._gl_widget._page_renderers = []
|
|
self._status_bar = Mock()
|
|
self._update_view_called = False
|
|
|
|
def _get_most_visible_page_index(self):
|
|
return 0
|
|
|
|
def update_view(self):
|
|
self._update_view_called = True
|
|
|
|
def show_status(self, message, timeout=0):
|
|
pass
|
|
|
|
window = TestWindow()
|
|
qtbot.addWidget(window)
|
|
|
|
# Test designating first page as cover
|
|
values = {
|
|
"selected_index": 0,
|
|
"selected_page": window.project.pages[0],
|
|
"is_cover": True, # Designate as cover
|
|
"paper_thickness_mm": 0.1,
|
|
"cover_bleed_mm": 3.0,
|
|
"width_mm": 210,
|
|
"height_mm": 297,
|
|
"working_dpi": 96,
|
|
"export_dpi": 300,
|
|
"set_as_default": False,
|
|
}
|
|
|
|
# Get the undecorated method
|
|
from pyPhotoAlbum.mixins.operations import page_ops
|
|
|
|
undecorated_page_setup = page_ops.PageOperationsMixin.page_setup
|
|
while hasattr(undecorated_page_setup, "__wrapped__"):
|
|
undecorated_page_setup = undecorated_page_setup.__wrapped__
|
|
|
|
# Mock update_cover_dimensions
|
|
window.project.update_cover_dimensions = Mock()
|
|
|
|
# Call with cover designation
|
|
undecorated_page_setup(window, values)
|
|
|
|
# Check cover was designated
|
|
assert window.project.pages[0].is_cover is True
|
|
assert window.project.has_cover is True
|
|
window.project.update_cover_dimensions.assert_called_once()
|
|
|
|
def test_page_setup_double_spread_sizing(self, qtbot):
|
|
"""Test page_setup correctly handles double spread page sizing"""
|
|
from PyQt6.QtWidgets import QMainWindow
|
|
from pyPhotoAlbum.mixins.base import ApplicationStateMixin
|
|
from pyPhotoAlbum.mixins.operations.page_ops import PageOperationsMixin
|
|
|
|
class TestWindow(PageOperationsMixin, ApplicationStateMixin, QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._project = Project(name="Test")
|
|
self._project.page_size_mm = (210, 297)
|
|
self._project.working_dpi = 96
|
|
self._project.export_dpi = 300
|
|
self._project.paper_thickness_mm = 0.1
|
|
self._project.cover_bleed_mm = 3.0
|
|
|
|
# Create double spread page
|
|
page = Page(layout=PageLayout(width=420, height=297), page_number=1)
|
|
page.is_double_spread = True
|
|
page.layout.base_width = 210
|
|
page.layout.is_facing_page = True
|
|
self._project.pages = [page]
|
|
|
|
self._gl_widget = Mock()
|
|
self._gl_widget._page_renderers = []
|
|
self._status_bar = Mock()
|
|
self._update_view_called = False
|
|
|
|
def _get_most_visible_page_index(self):
|
|
return 0
|
|
|
|
def update_view(self):
|
|
self._update_view_called = True
|
|
|
|
def show_status(self, message, timeout=0):
|
|
pass
|
|
|
|
window = TestWindow()
|
|
qtbot.addWidget(window)
|
|
|
|
# Test changing double spread page size
|
|
values = {
|
|
"selected_index": 0,
|
|
"selected_page": window.project.pages[0],
|
|
"is_cover": False,
|
|
"paper_thickness_mm": 0.1,
|
|
"cover_bleed_mm": 3.0,
|
|
"width_mm": 200, # New base width
|
|
"height_mm": 280, # New height
|
|
"working_dpi": 96,
|
|
"export_dpi": 300,
|
|
"set_as_default": False,
|
|
}
|
|
|
|
from pyPhotoAlbum.mixins.operations import page_ops
|
|
|
|
undecorated_page_setup = page_ops.PageOperationsMixin.page_setup
|
|
while hasattr(undecorated_page_setup, "__wrapped__"):
|
|
undecorated_page_setup = undecorated_page_setup.__wrapped__
|
|
|
|
undecorated_page_setup(window, values)
|
|
|
|
# Check double spread sizing
|
|
assert window.project.pages[0].layout.base_width == 200
|
|
assert window.project.pages[0].layout.size == (400, 280) # Double width
|
|
assert window.project.pages[0].manually_sized is True
|