"""Tests for pagination utilities. Validates the pagination helper functions used across all paginated endpoints. """ import pytest from app.utils.pagination import get_offset, compute_total_pages, PAGINATION_DEFAULTS class TestPaginationDefaults: """Test pagination default constants.""" def test_pagination_defaults_structure(self) -> None: """PAGINATION_DEFAULTS contains required keys.""" required_keys = {"page", "page_size", "max_page_size"} assert required_keys.issubset(PAGINATION_DEFAULTS.keys()) def test_pagination_defaults_values(self) -> None: """PAGINATION_DEFAULTS have expected values.""" assert PAGINATION_DEFAULTS["page"] == 1 assert PAGINATION_DEFAULTS["page_size"] == 100 assert PAGINATION_DEFAULTS["max_page_size"] == 500 class TestGetOffset: """Test get_offset calculation.""" def test_first_page(self) -> None: """First page (page=1) produces offset=0.""" assert get_offset(1, 10) == 0 def test_second_page(self) -> None: """Second page (page=2) produces offset=page_size.""" assert get_offset(2, 10) == 10 def test_arbitrary_page(self) -> None: """Arbitrary pages produce correct offsets.""" assert get_offset(3, 50) == 100 assert get_offset(5, 25) == 100 assert get_offset(10, 100) == 900 def test_page_size_variations(self) -> None: """Offsets scale correctly with page_size.""" assert get_offset(2, 1) == 1 assert get_offset(2, 10) == 10 assert get_offset(2, 100) == 100 assert get_offset(2, 500) == 500 def test_invalid_page_raises(self) -> None: """Invalid page numbers raise ValueError.""" with pytest.raises(ValueError, match="page must be >= 1"): get_offset(0, 10) with pytest.raises(ValueError, match="page must be >= 1"): get_offset(-1, 10) def test_invalid_page_size_raises(self) -> None: """Invalid page sizes raise ValueError.""" with pytest.raises(ValueError, match="page_size must be >= 1"): get_offset(1, 0) with pytest.raises(ValueError, match="page_size must be >= 1"): get_offset(1, -1) class TestComputeTotalPages: """Test compute_total_pages calculation.""" def test_empty_collection(self) -> None: """Empty collection (total=0) produces at least 1 page.""" assert compute_total_pages(0, 10) == 1 def test_exact_page_fit(self) -> None: """Totals that fit exactly produce expected page count.""" assert compute_total_pages(10, 10) == 1 assert compute_total_pages(20, 10) == 2 assert compute_total_pages(50, 10) == 5 def test_partial_page(self) -> None: """Totals that overflow a page produce ceil(total / page_size).""" assert compute_total_pages(11, 10) == 2 assert compute_total_pages(25, 5) == 5 assert compute_total_pages(101, 10) == 11 def test_single_item(self) -> None: """Single item produces 1 page regardless of page_size.""" assert compute_total_pages(1, 1) == 1 assert compute_total_pages(1, 10) == 1 assert compute_total_pages(1, 500) == 1 def test_large_page_size(self) -> None: """Large page sizes still compute correctly.""" assert compute_total_pages(1, 500) == 1 assert compute_total_pages(501, 500) == 2 assert compute_total_pages(1000, 500) == 2 def test_invalid_page_size_raises(self) -> None: """Invalid page sizes raise ValueError.""" with pytest.raises(ValueError, match="page_size must be >= 1"): compute_total_pages(100, 0) with pytest.raises(ValueError, match="page_size must be >= 1"): compute_total_pages(100, -1)