"""Tests for PPT_longPic function.""" from pathlib import Path from unittest.mock import MagicMock, patch import pytest from pptopic.lib import PPT_longPic def _make_img_mocks(tmp_path, num_images=1): """Build reusable mock objects for PPT_longPic tests. Returns (img_paths, mock_img, mock_canvas): - img_paths: real Path objects so ``sorted()`` works - mock_img: PIL Image mock with .size, .width, .height, .resize - mock_canvas: PIL Image.new mock """ img_paths = [tmp_path / f"slide{i}.jpg" for i in range(1, num_images + 1)] mock_img = MagicMock() mock_img.mode = "RGB" mock_img.size = (100, 100) mock_img.width = 100 mock_img.height = 100 mock_img.resize.return_value = mock_img mock_canvas = MagicMock() return img_paths, mock_img, mock_canvas class TestPPTLongPic: """Test PPT_longPic function.""" # -- width variations -------------------------------------------------- @pytest.mark.parametrize( "width,expected_size", [ (None, (100, 100)), # no scaling → uses img.size (50, (50, 50)), # pixel width → (w, h*w//W) ("50%", (50, 50)), # percentage → half ], ids=["none", "pixel", "percentage"], ) @patch("pptopic.lib.convertPPT") def test_width_variations(self, mock_convert_ppt, width, expected_size, tmp_path): """PPT_longPic handles None / pixel / percentage width correctly.""" img_paths, mock_img, mock_canvas = _make_img_mocks(tmp_path) mock_convert_ppt.return_value.__enter__.return_value = MagicMock() with patch("pptopic.lib.Path.glob", return_value=img_paths): with patch("pptopic.lib.Image.open") as mock_open: mock_open.return_value.__enter__.return_value = mock_img with patch("pptopic.lib.Image.new", return_value=mock_canvas): PPT_longPic(tmp_path / "test.pptx", width=width, saveto=tmp_path) mock_canvas.save.assert_called_once() # -- saveName / saveto variations ------------------------------------- @pytest.mark.parametrize( "save_name,saveto", [ (None, None), # defaults: JPG, ppt parent dir ("output.jpg", None), # named, ppt parent dir (None, "."), # default name, custom dir ], ids=["defaults", "named", "custom_dir"], ) @patch("pptopic.lib.convertPPT") def test_save_params(self, mock_convert_ppt, save_name, saveto, tmp_path): """PPT_longPic handles saveName / saveto combinations.""" img_paths, mock_img, mock_canvas = _make_img_mocks(tmp_path) mock_convert_ppt.return_value.__enter__.return_value = MagicMock() with patch("pptopic.lib.Path.glob", return_value=img_paths): with patch("pptopic.lib.Image.open") as mock_open: mock_open.return_value.__enter__.return_value = mock_img with patch("pptopic.lib.Image.new", return_value=mock_canvas): PPT_longPic( tmp_path / "test.pptx", saveName=save_name, saveto=saveto if saveto else tmp_path, ) mock_canvas.save.assert_called_once() # -- error paths ------------------------------------------------------- def test_invalid_image_type(self, tmp_path): ppt_file = tmp_path / "test.pptx" ppt_file.touch() with pytest.raises(ValueError, match="Unable to save this type"): PPT_longPic(ppt_file, saveName="output.bmp") @patch("pptopic.lib.convertPPT") def test_no_images_generated(self, mock_convert_ppt, tmp_path): ppt_file = tmp_path / "test.pptx" ppt_file.touch() mock_convert_ppt.return_value.__enter__.return_value = MagicMock() with patch("pptopic.lib.Path.glob", return_value=[]): with pytest.raises(ValueError, match="No images generated"): PPT_longPic(ppt_file) # -- multiple images --------------------------------------------------- @patch("pptopic.lib.convertPPT") def test_multiple_images(self, mock_convert_ppt, tmp_path): """PPT_longPic pastes every slide into the canvas.""" img_paths, mock_img, mock_canvas = _make_img_mocks(tmp_path, num_images=3) mock_convert_ppt.return_value.__enter__.return_value = MagicMock() with patch("pptopic.lib.Path.glob", return_value=img_paths): with patch("pptopic.lib.Image.open") as mock_open: mock_open.return_value.__enter__.return_value = mock_img with patch("pptopic.lib.Image.new", return_value=mock_canvas): PPT_longPic(tmp_path / "test.pptx", saveto=tmp_path) assert mock_canvas.paste.call_count == 3 mock_canvas.save.assert_called_once()