fix tests
All checks were successful
Python CI / test (push) Successful in 1m24s
Lint / lint (push) Successful in 1m13s
Tests / test (3.11) (push) Successful in 1m37s
Tests / test (3.12) (push) Successful in 1m41s
Tests / test (3.13) (push) Successful in 1m34s
Tests / test (3.14) (push) Successful in 1m12s
All checks were successful
Python CI / test (push) Successful in 1m24s
Lint / lint (push) Successful in 1m13s
Tests / test (3.11) (push) Successful in 1m37s
Tests / test (3.12) (push) Successful in 1m41s
Tests / test (3.13) (push) Successful in 1m34s
Tests / test (3.14) (push) Successful in 1m12s
This commit is contained in:
parent
c1ee894e7b
commit
254a95d83c
@ -257,25 +257,50 @@ class TestLoadCallbacks:
|
||||
class TestSaveProject:
|
||||
"""Test save_project method"""
|
||||
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.save_to_zip")
|
||||
def test_save_project_with_existing_path(self, mock_save, qtbot):
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.save_to_zip_async")
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.LoadingWidget")
|
||||
def test_save_project_with_existing_path(self, mock_loading_widget, mock_save_async, qtbot):
|
||||
"""Test saves to existing file path"""
|
||||
window = TestFileOpsWindow()
|
||||
qtbot.addWidget(window)
|
||||
|
||||
window.project.file_path = "/path/to/existing.ppz"
|
||||
mock_save.return_value = (True, None)
|
||||
|
||||
# Mock loading widget
|
||||
mock_loading_instance = Mock()
|
||||
mock_loading_widget.return_value = mock_loading_instance
|
||||
|
||||
# Capture status messages
|
||||
status_messages = []
|
||||
original_show_status = window.show_status
|
||||
def capture_status(msg, timeout=0):
|
||||
status_messages.append(msg)
|
||||
original_show_status(msg, timeout)
|
||||
window.show_status = capture_status
|
||||
|
||||
# Mock save_to_zip_async to call on_complete immediately with success
|
||||
def mock_save_call(project, path, on_complete=None, on_progress=None):
|
||||
if on_complete:
|
||||
on_complete(True, None)
|
||||
return Mock() # Return mock thread
|
||||
|
||||
mock_save_async.side_effect = mock_save_call
|
||||
|
||||
window.save_project()
|
||||
|
||||
# Verify save was called with existing path
|
||||
mock_save.assert_called_once_with(window.project, "/path/to/existing.ppz")
|
||||
assert "Project saved" in window._status_message
|
||||
assert mock_save_async.call_count == 1
|
||||
call_args = mock_save_async.call_args
|
||||
assert call_args[0][0] == window.project
|
||||
assert call_args[0][1] == "/path/to/existing.ppz"
|
||||
# Check that "Project saved" was shown at some point
|
||||
assert any("Project saved" in msg for msg in status_messages)
|
||||
assert not window.project.is_dirty() # is_dirty() is a method
|
||||
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.save_to_zip")
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.save_to_zip_async")
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.LoadingWidget")
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.QFileDialog.getSaveFileName")
|
||||
def test_save_project_prompts_for_path(self, mock_file_dialog, mock_save, qtbot):
|
||||
def test_save_project_prompts_for_path(self, mock_file_dialog, mock_loading_widget, mock_save_async, qtbot):
|
||||
"""Test prompts for path when none exists"""
|
||||
window = TestFileOpsWindow()
|
||||
qtbot.addWidget(window)
|
||||
@ -285,18 +310,33 @@ class TestSaveProject:
|
||||
|
||||
# Mock dialog to return path
|
||||
mock_file_dialog.return_value = ("/path/to/new.ppz", "")
|
||||
mock_save.return_value = (True, None)
|
||||
|
||||
# Mock loading widget
|
||||
mock_loading_instance = Mock()
|
||||
mock_loading_widget.return_value = mock_loading_instance
|
||||
|
||||
# Mock save_to_zip_async to call on_complete immediately with success
|
||||
def mock_save_call(project, path, on_complete=None, on_progress=None):
|
||||
if on_complete:
|
||||
on_complete(True, None)
|
||||
return Mock() # Return mock thread
|
||||
|
||||
mock_save_async.side_effect = mock_save_call
|
||||
|
||||
window.save_project()
|
||||
|
||||
# Verify dialog was shown and save was called
|
||||
mock_file_dialog.assert_called_once()
|
||||
mock_save.assert_called_once_with(window.project, "/path/to/new.ppz")
|
||||
assert mock_save_async.call_count == 1
|
||||
call_args = mock_save_async.call_args
|
||||
assert call_args[0][0] == window.project
|
||||
assert call_args[0][1] == "/path/to/new.ppz"
|
||||
assert window.project.file_path == "/path/to/new.ppz"
|
||||
assert not window.project.is_dirty()
|
||||
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.save_to_zip")
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.save_to_zip_async")
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.QFileDialog.getSaveFileName")
|
||||
def test_save_project_user_cancels(self, mock_file_dialog, mock_save, qtbot):
|
||||
def test_save_project_user_cancels(self, mock_file_dialog, mock_save_async, qtbot):
|
||||
"""Test returns when user cancels file dialog"""
|
||||
window = TestFileOpsWindow()
|
||||
qtbot.addWidget(window)
|
||||
@ -307,22 +347,34 @@ class TestSaveProject:
|
||||
window.save_project()
|
||||
|
||||
# Should not call save
|
||||
mock_save.assert_not_called()
|
||||
mock_save_async.assert_not_called()
|
||||
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.save_to_zip")
|
||||
def test_save_project_handles_error(self, mock_save, qtbot):
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.save_to_zip_async")
|
||||
@patch("pyPhotoAlbum.mixins.operations.file_ops.LoadingWidget")
|
||||
def test_save_project_handles_error(self, mock_loading_widget, mock_save_async, qtbot):
|
||||
"""Test handles save errors"""
|
||||
window = TestFileOpsWindow()
|
||||
qtbot.addWidget(window)
|
||||
|
||||
window.project.file_path = "/path/to/project.ppz"
|
||||
mock_save.return_value = (False, "Disk full")
|
||||
|
||||
# Mock loading widget
|
||||
mock_loading_instance = Mock()
|
||||
mock_loading_widget.return_value = mock_loading_instance
|
||||
|
||||
# Mock save_to_zip_async to call on_complete with error
|
||||
def mock_save_call(project, path, on_complete=None, on_progress=None):
|
||||
if on_complete:
|
||||
on_complete(False, "Disk full")
|
||||
return Mock() # Return mock thread
|
||||
|
||||
mock_save_async.side_effect = mock_save_call
|
||||
|
||||
window.save_project()
|
||||
|
||||
# Verify error was shown
|
||||
assert "Failed to save project" in window._status_message
|
||||
assert "Disk full" in window._status_message
|
||||
assert "Failed to save project" in window._error_message
|
||||
assert "Disk full" in window._error_message
|
||||
|
||||
|
||||
class TestHealAssets:
|
||||
|
||||
@ -1099,8 +1099,7 @@ class TestTextBoxData:
|
||||
@patch("pyPhotoAlbum.models.glTranslatef")
|
||||
@patch("pyPhotoAlbum.models.glDisable")
|
||||
@patch("pyPhotoAlbum.models.glEnable")
|
||||
@patch("pyPhotoAlbum.models.glBlendFunc")
|
||||
@patch("pyPhotoAlbum.models.glColor4f")
|
||||
@patch("pyPhotoAlbum.models.glLineStipple")
|
||||
@patch("pyPhotoAlbum.models.glColor3f")
|
||||
@patch("pyPhotoAlbum.models.glVertex2f")
|
||||
@patch("pyPhotoAlbum.models.glBegin")
|
||||
@ -1111,8 +1110,7 @@ class TestTextBoxData:
|
||||
mock_glBegin,
|
||||
mock_glVertex2f,
|
||||
mock_glColor3f,
|
||||
mock_glColor4f,
|
||||
mock_glBlendFunc,
|
||||
mock_glLineStipple,
|
||||
mock_glEnable,
|
||||
mock_glDisable,
|
||||
mock_glTranslatef,
|
||||
@ -1125,18 +1123,15 @@ class TestTextBoxData:
|
||||
|
||||
textbox.render()
|
||||
|
||||
# Should enable and disable blending
|
||||
from pyPhotoAlbum.models import GL_BLEND, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
|
||||
# Should enable and disable line stipple for dashed border
|
||||
from pyPhotoAlbum.models import GL_LINE_STIPPLE
|
||||
|
||||
mock_glEnable.assert_called_with(GL_BLEND)
|
||||
mock_glBlendFunc.assert_called_once_with(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||
mock_glDisable.assert_called_with(GL_BLEND)
|
||||
mock_glEnable.assert_called_with(GL_LINE_STIPPLE)
|
||||
mock_glLineStipple.assert_called_once_with(2, 0xAAAA)
|
||||
mock_glDisable.assert_called_with(GL_LINE_STIPPLE)
|
||||
|
||||
# Should draw semi-transparent yellow background
|
||||
mock_glColor4f.assert_called_with(1.0, 1.0, 0.7, 0.3)
|
||||
|
||||
# Should draw black border
|
||||
mock_glColor3f.assert_called_with(0.0, 0.0, 0.0)
|
||||
# Should draw light gray dashed border
|
||||
mock_glColor3f.assert_called_with(0.7, 0.7, 0.7)
|
||||
|
||||
# Should NOT push/pop matrix when rotation is 0
|
||||
mock_glPushMatrix.assert_not_called()
|
||||
|
||||
@ -313,9 +313,10 @@ class TestPageLayoutSnapLines:
|
||||
|
||||
layout.render(dpi=300, project=mock_project)
|
||||
|
||||
# Cyan color should be used for guides (0.0, 0.7, 0.9, 0.8)
|
||||
# Cyan color should be used for guides (0.0, 0.7, 0.9)
|
||||
# Check if cyan color was set (at least once)
|
||||
assert mock_color4f.call_count > 0
|
||||
cyan_calls = [call for call in mock_color3f.call_args_list if call[0] == (0.0, 0.7, 0.9)]
|
||||
assert len(cyan_calls) > 0, "Cyan color for guides should be set"
|
||||
|
||||
|
||||
class TestPageLayoutEdgeCases:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user