centralised image loading logic
Python CI / test (push) Successful in 1m17s
Lint / lint (push) Successful in 1m32s
Tests / test (3.10) (push) Successful in 1m9s
Tests / test (3.11) (push) Successful in 1m8s
Tests / test (3.9) (push) Successful in 1m7s

This commit is contained in:
2025-11-27 21:33:53 +01:00
parent 45268cdfe4
commit d7786ede80
5 changed files with 91 additions and 78 deletions
+25 -33
View File
@@ -10,8 +10,6 @@ from pyPhotoAlbum.models import ImageData, TextBoxData, PlaceholderData
from pyPhotoAlbum.project import Project, Page
from pyPhotoAlbum.page_layout import PageLayout
from pyPhotoAlbum.commands import CommandHistory
from PIL import Image
import io
# Create test window with ElementOperationsMixin
@@ -69,8 +67,8 @@ class TestAddImage:
"""Test add_image method"""
@patch('pyPhotoAlbum.mixins.operations.element_ops.QFileDialog.getOpenFileName')
@patch('pyPhotoAlbum.mixins.operations.element_ops.Image.open')
def test_add_image_success(self, mock_image_open, mock_file_dialog, qtbot):
@patch('pyPhotoAlbum.mixins.operations.element_ops.get_image_dimensions')
def test_add_image_success(self, mock_get_dims, mock_file_dialog, qtbot):
"""Test successfully adding an image"""
window = TestElementWindow()
qtbot.addWidget(window)
@@ -85,10 +83,8 @@ class TestAddImage:
# Mock file dialog
mock_file_dialog.return_value = ("/path/to/image.jpg", "Image Files (*.jpg)")
# Mock PIL Image
mock_img = Mock()
mock_img.size = (800, 600)
mock_image_open.return_value = mock_img
# Mock get_image_dimensions (returns scaled dimensions)
mock_get_dims.return_value = (300, 225) # 800x600 scaled to max 300
# Mock asset manager
window.project.asset_manager.import_asset.return_value = "assets/image.jpg"
@@ -139,8 +135,8 @@ class TestAddImage:
assert not window._update_view_called
@patch('pyPhotoAlbum.mixins.operations.element_ops.QFileDialog.getOpenFileName')
@patch('pyPhotoAlbum.mixins.operations.element_ops.Image.open')
def test_add_image_scales_large_image(self, mock_image_open, mock_file_dialog, qtbot):
@patch('pyPhotoAlbum.mixins.operations.element_ops.get_image_dimensions')
def test_add_image_scales_large_image(self, mock_get_dims, mock_file_dialog, qtbot):
"""Test that large images are scaled down"""
window = TestElementWindow()
qtbot.addWidget(window)
@@ -153,22 +149,20 @@ class TestAddImage:
mock_file_dialog.return_value = ("/path/to/large.jpg", "Image Files (*.jpg)")
# Mock very large image
mock_img = Mock()
mock_img.size = (3000, 2000) # Much larger than max_size=300
mock_image_open.return_value = mock_img
# Mock get_image_dimensions returning scaled dimensions (3000x2000 -> 300x200)
mock_get_dims.return_value = (300, 200)
window.project.asset_manager.import_asset.return_value = "assets/large.jpg"
window.add_image()
# Image should be added (scaled down internally)
# Image should be added (scaled down by get_image_dimensions)
assert window._update_view_called
@patch('pyPhotoAlbum.mixins.operations.element_ops.QFileDialog.getOpenFileName')
@patch('pyPhotoAlbum.mixins.operations.element_ops.Image.open')
def test_add_image_error_handling(self, mock_image_open, mock_file_dialog, qtbot):
"""Test error handling when adding image fails"""
@patch('pyPhotoAlbum.mixins.operations.element_ops.get_image_dimensions')
def test_add_image_fallback_dimensions(self, mock_get_dims, mock_file_dialog, qtbot):
"""Test fallback dimensions when get_image_dimensions returns None"""
window = TestElementWindow()
qtbot.addWidget(window)
@@ -180,14 +174,16 @@ class TestAddImage:
mock_file_dialog.return_value = ("/path/to/broken.jpg", "Image Files (*.jpg)")
# Mock error
mock_image_open.side_effect = Exception("Cannot open image")
# Mock get_image_dimensions returning None (image unreadable)
mock_get_dims.return_value = None
window.project.asset_manager.import_asset.return_value = "assets/broken.jpg"
window.add_image()
# Should show error
assert window._error_message is not None
assert "failed to add image" in window._error_message.lower()
# Should still add image with fallback dimensions (200x150)
assert window._update_view_called
assert window.project.history.can_undo()
class TestAddText:
@@ -294,8 +290,8 @@ class TestElementOperationsIntegration:
"""Test integration between element operations"""
@patch('pyPhotoAlbum.mixins.operations.element_ops.QFileDialog.getOpenFileName')
@patch('pyPhotoAlbum.mixins.operations.element_ops.Image.open')
def test_add_multiple_elements(self, mock_image_open, mock_file_dialog, qtbot):
@patch('pyPhotoAlbum.mixins.operations.element_ops.get_image_dimensions')
def test_add_multiple_elements(self, mock_get_dims, mock_file_dialog, qtbot):
"""Test adding multiple different element types"""
window = TestElementWindow()
qtbot.addWidget(window)
@@ -317,9 +313,7 @@ class TestElementOperationsIntegration:
# Add image
mock_file_dialog.return_value = ("/test.jpg", "Image Files")
mock_img = Mock()
mock_img.size = (100, 100)
mock_image_open.return_value = mock_img
mock_get_dims.return_value = (100, 100)
window.project.asset_manager.import_asset.return_value = "assets/test.jpg"
window.add_image()
@@ -328,8 +322,8 @@ class TestElementOperationsIntegration:
assert window._update_view_called
@patch('pyPhotoAlbum.mixins.operations.element_ops.QFileDialog.getOpenFileName')
@patch('pyPhotoAlbum.mixins.operations.element_ops.Image.open')
def test_add_image_with_undo(self, mock_image_open, mock_file_dialog, qtbot):
@patch('pyPhotoAlbum.mixins.operations.element_ops.get_image_dimensions')
def test_add_image_with_undo(self, mock_get_dims, mock_file_dialog, qtbot):
"""Test that adding image can be undone"""
window = TestElementWindow()
qtbot.addWidget(window)
@@ -341,9 +335,7 @@ class TestElementOperationsIntegration:
window._current_page = page
mock_file_dialog.return_value = ("/test.jpg", "Image Files")
mock_img = Mock()
mock_img.size = (200, 150)
mock_image_open.return_value = mock_img
mock_get_dims.return_value = (200, 150)
window.project.asset_manager.import_asset.return_value = "assets/test.jpg"
# Should have no commands initially