Loading...
No commits yet
Not committed History
Blame
test_tile_panels.py • 6.2 KB
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Test file for: tile_panels.py

import os
import sys
from pathlib import Path

import pytest

# Add scripts/python to path for imports
ROOT_DIR = Path(__file__).resolve().parent.parent.parent
sys.path.insert(0, str(ROOT_DIR / "scripts" / "python"))

pytest.importorskip("PIL")

# calculate_layout is pure logic - no dependencies needed
from tile_panels import calculate_layout, detect_panels  # noqa: E402

# Check for PIL dependency
try:
    from PIL import Image
    from tile_panels import tile_images

    HAS_PIL = True
except ImportError:
    HAS_PIL = False


# Tests for calculate_layout (pure logic - always testable)
def test_calculate_layout_1_panel():
    """Test layout for 1 panel."""
    assert calculate_layout(1) == (1, 1)


def test_calculate_layout_2_panels():
    """Test layout for 2 panels."""
    assert calculate_layout(2) == (1, 2)


def test_calculate_layout_3_panels():
    """Test layout for 3 panels."""
    assert calculate_layout(3) == (1, 3)


def test_calculate_layout_4_panels():
    """Test layout for 4 panels."""
    assert calculate_layout(4) == (2, 2)


def test_calculate_layout_5_panels():
    """Test layout for 5 panels."""
    assert calculate_layout(5) == (2, 3)


def test_calculate_layout_6_panels():
    """Test layout for 6 panels."""
    assert calculate_layout(6) == (2, 3)


def test_calculate_layout_7_panels():
    """Test layout for 7 panels."""
    assert calculate_layout(7) == (3, 3)


def test_calculate_layout_9_panels():
    """Test layout for 9 panels."""
    assert calculate_layout(9) == (3, 3)


def test_calculate_layout_10_panels():
    """Test layout for 10 panels."""
    rows, cols = calculate_layout(10)
    assert rows * cols >= 10
    assert isinstance(rows, int)
    assert isinstance(cols, int)


# Tests for detect_panels (file system only)
def test_detect_panels_finds_files(tmp_path):
    """Test that detect_panels finds panel files."""
    # Create test panel files following naming convention
    (tmp_path / "01a_figure.jpg").touch()
    (tmp_path / "01b_figure.jpg").touch()
    (tmp_path / "01c_figure.jpg").touch()

    panels = detect_panels("01_demographic_data", str(tmp_path))

    assert len(panels) == 3
    assert "A" in panels
    assert "B" in panels
    assert "C" in panels


def test_detect_panels_empty_dir(tmp_path):
    """Test that empty directory returns empty dict."""
    panels = detect_panels("01_figure", str(tmp_path))
    assert panels == {}


def test_detect_panels_wrong_prefix(tmp_path):
    """Test that panels with wrong prefix are not detected."""
    (tmp_path / "02a_figure.jpg").touch()
    (tmp_path / "02b_figure.jpg").touch()

    panels = detect_panels("01_figure", str(tmp_path))
    assert panels == {}


def test_detect_panels_sorted_order(tmp_path):
    """Test that panels are returned in sorted order."""
    (tmp_path / "01c_figure.jpg").touch()
    (tmp_path / "01a_figure.jpg").touch()
    (tmp_path / "01b_figure.jpg").touch()

    panels = detect_panels("01_figure", str(tmp_path))

    keys = list(panels.keys())
    assert keys == ["A", "B", "C"]


def test_detect_panels_mixed_case(tmp_path):
    """Test that lowercase panel letters are uppercase in output."""
    (tmp_path / "01a_figure.jpg").touch()

    panels = detect_panels("01_figure", str(tmp_path))

    assert "A" in panels
    assert "a" not in panels


# Tests for tile_images (requires PIL)
@pytest.mark.skipif(not HAS_PIL, reason="PIL (Pillow) not available")
def test_tile_images_empty_panels():
    """Test that tile_images returns False for empty panels."""
    result = tile_images({}, "output.jpg")
    assert result is False


@pytest.mark.skipif(not HAS_PIL, reason="PIL (Pillow) not available")
def test_tile_images_creates_output(tmp_path):
    """Test that tile_images creates output file."""
    # Create small test images
    img_a = Image.new("RGB", (100, 100), color="red")
    img_b = Image.new("RGB", (100, 100), color="blue")

    img_a_path = tmp_path / "01a_test.jpg"
    img_b_path = tmp_path / "01b_test.jpg"
    img_a.save(str(img_a_path))
    img_b.save(str(img_b_path))

    panels = {"A": str(img_a_path), "B": str(img_b_path)}
    output_path = tmp_path / "tiled.jpg"

    result = tile_images(panels, str(output_path), spacing=10, dpi=100)

    assert result is True
    assert output_path.exists()


@pytest.mark.skipif(not HAS_PIL, reason="PIL (Pillow) not available")
def test_tile_images_correct_dimensions(tmp_path):
    """Test that tiled image has correct dimensions."""
    # Create test images
    img_a = Image.new("RGB", (200, 150), color="red")
    img_b = Image.new("RGB", (200, 150), color="blue")

    img_a_path = tmp_path / "01a_test.jpg"
    img_b_path = tmp_path / "01b_test.jpg"
    img_a.save(str(img_a_path))
    img_b.save(str(img_b_path))

    panels = {"A": str(img_a_path), "B": str(img_b_path)}
    output_path = tmp_path / "tiled.jpg"

    spacing = 20
    tile_images(panels, str(output_path), spacing=spacing)

    # Open result and check dimensions
    result_img = Image.open(str(output_path))
    # 2 panels in 1 row, 2 cols layout
    expected_width = 2 * 200 + (2 - 1) * spacing
    assert result_img.width == expected_width


@pytest.mark.skipif(not HAS_PIL, reason="PIL (Pillow) not available")
def test_tile_images_invalid_path_returns_false(tmp_path):
    """Test that tile_images returns False for invalid image path."""
    panels = {"A": "/nonexistent/image.jpg"}
    output_path = tmp_path / "output.jpg"

    result = tile_images(panels, str(output_path))

    assert result is False


@pytest.mark.skipif(not HAS_PIL, reason="PIL (Pillow) not available")
def test_tile_images_4_panels_layout(tmp_path):
    """Test that 4 panels use 2x2 layout."""
    # Create 4 test images
    panels = {}
    for letter in ["A", "B", "C", "D"]:
        img = Image.new("RGB", (100, 100), color="white")
        img_path = tmp_path / f"01{letter.lower()}_test.jpg"
        img.save(str(img_path))
        panels[letter] = str(img_path)

    output_path = tmp_path / "tiled.jpg"
    tile_images(panels, str(output_path), spacing=0)

    result_img = Image.open(str(output_path))
    # 2x2 layout
    assert result_img.width == 200  # 2 * 100
    assert result_img.height == 200  # 2 * 100


if __name__ == "__main__":
    import pytest

    pytest.main([os.path.abspath(__file__), "-v"])