de201436ea
CI/CD Pipeline / Check if frontend-only change (push) Has been cancelled
CI/CD Pipeline / Validate - Code Quality (push) Has been cancelled
CI/CD Pipeline / Validate - Type Check (mypy) (push) Has been cancelled
CI/CD Pipeline / Validate - Migration (alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / PR Build Web Image (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Build Staging API Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
180 lines
6.4 KiB
Python
Executable File
180 lines
6.4 KiB
Python
Executable File
"""pagination 单元测试."""
|
|
|
|
import pytest
|
|
|
|
from packages.application.common.pagination import (
|
|
PaginatedResponse,
|
|
PaginationMeta,
|
|
PaginationParams,
|
|
paginate,
|
|
)
|
|
|
|
# ── PaginationParams ────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPaginationParams:
|
|
def test_default_values(self):
|
|
params = PaginationParams()
|
|
assert params.page == 1
|
|
assert params.page_size == 20
|
|
|
|
def test_custom_values(self):
|
|
params = PaginationParams(page=3, page_size=50)
|
|
assert params.page == 3
|
|
assert params.page_size == 50
|
|
|
|
def test_offset_calculation(self):
|
|
params = PaginationParams(page=1, page_size=20)
|
|
assert params.offset == 0
|
|
|
|
params = PaginationParams(page=3, page_size=20)
|
|
assert params.offset == 40
|
|
|
|
params = PaginationParams(page=10, page_size=50)
|
|
assert params.offset == 450
|
|
|
|
def test_limit_equals_page_size(self):
|
|
params = PaginationParams(page_size=30)
|
|
assert params.limit == 30
|
|
|
|
def test_page_must_be_at_least_1(self):
|
|
with pytest.raises(ValueError):
|
|
PaginationParams(page=0)
|
|
|
|
def test_page_size_must_be_at_least_1(self):
|
|
with pytest.raises(ValueError):
|
|
PaginationParams(page_size=0)
|
|
|
|
def test_page_size_max_100(self):
|
|
with pytest.raises(ValueError):
|
|
PaginationParams(page_size=101)
|
|
|
|
|
|
# ── PaginationMeta ──────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPaginationMeta:
|
|
def test_from_params_first_page(self):
|
|
params = PaginationParams(page=1, page_size=10)
|
|
meta = PaginationMeta.from_params(params, total=25)
|
|
assert meta.page == 1
|
|
assert meta.page_size == 10
|
|
assert meta.total == 25
|
|
assert meta.total_pages == 3 # ceil(25/10)
|
|
assert meta.has_next is True
|
|
assert meta.has_prev is False
|
|
|
|
def test_from_params_last_page(self):
|
|
params = PaginationParams(page=3, page_size=10)
|
|
meta = PaginationMeta.from_params(params, total=25)
|
|
assert meta.page == 3
|
|
assert meta.total_pages == 3
|
|
assert meta.has_next is False
|
|
assert meta.has_prev is True
|
|
|
|
def test_from_params_middle_page(self):
|
|
params = PaginationParams(page=2, page_size=10)
|
|
meta = PaginationMeta.from_params(params, total=25)
|
|
assert meta.has_next is True
|
|
assert meta.has_prev is True
|
|
|
|
def test_from_params_single_page(self):
|
|
params = PaginationParams(page=1, page_size=20)
|
|
meta = PaginationMeta.from_params(params, total=5)
|
|
assert meta.total_pages == 1
|
|
assert meta.has_next is False
|
|
assert meta.has_prev is False
|
|
|
|
def test_from_params_zero_total(self):
|
|
params = PaginationParams(page=1, page_size=20)
|
|
meta = PaginationMeta.from_params(params, total=0)
|
|
assert meta.total == 0
|
|
assert meta.total_pages == 0
|
|
assert meta.has_next is False
|
|
assert meta.has_prev is False
|
|
|
|
def test_from_params_exact_page_size(self):
|
|
params = PaginationParams(page=1, page_size=10)
|
|
meta = PaginationMeta.from_params(params, total=10)
|
|
assert meta.total_pages == 1
|
|
|
|
def test_from_params_one_extra(self):
|
|
params = PaginationParams(page=1, page_size=10)
|
|
meta = PaginationMeta.from_params(params, total=11)
|
|
assert meta.total_pages == 2
|
|
|
|
|
|
# ── PaginatedResponse ───────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPaginatedResponse:
|
|
def test_create_response(self):
|
|
params = PaginationParams(page=1, page_size=5)
|
|
data = [1, 2, 3, 4, 5]
|
|
response = PaginatedResponse.create(data, params, total=15)
|
|
assert response.data == data
|
|
assert response.pagination.page == 1
|
|
assert response.pagination.total == 15
|
|
assert response.pagination.total_pages == 3
|
|
|
|
|
|
# ── paginate function ───────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPaginate:
|
|
def test_first_page(self):
|
|
items = list(range(30))
|
|
params = PaginationParams(page=1, page_size=10)
|
|
result = paginate(items, params)
|
|
assert result.data == list(range(10))
|
|
assert result.pagination.total == 30
|
|
assert result.pagination.total_pages == 3
|
|
assert result.pagination.has_next is True
|
|
assert result.pagination.has_prev is False
|
|
|
|
def test_last_page(self):
|
|
items = list(range(25))
|
|
params = PaginationParams(page=3, page_size=10)
|
|
result = paginate(items, params)
|
|
assert result.data == list(range(20, 25))
|
|
assert len(result.data) == 5
|
|
assert result.pagination.has_next is False
|
|
assert result.pagination.has_prev is True
|
|
|
|
def test_single_page(self):
|
|
items = list(range(5))
|
|
params = PaginationParams(page=1, page_size=10)
|
|
result = paginate(items, params)
|
|
assert result.data == items
|
|
assert result.pagination.total_pages == 1
|
|
|
|
def test_empty_list(self):
|
|
items = []
|
|
params = PaginationParams(page=1, page_size=10)
|
|
result = paginate(items, params)
|
|
assert result.data == []
|
|
assert result.pagination.total == 0
|
|
assert result.pagination.total_pages == 0
|
|
|
|
def test_page_beyond_end(self):
|
|
items = list(range(5))
|
|
params = PaginationParams(page=10, page_size=10)
|
|
result = paginate(items, params)
|
|
assert result.data == []
|
|
assert result.pagination.total == 5
|
|
|
|
def test_page_size_larger_than_items(self):
|
|
items = list(range(5))
|
|
params = PaginationParams(page=1, page_size=100)
|
|
result = paginate(items, params)
|
|
assert result.data == items
|
|
assert result.pagination.total_pages == 1
|
|
|
|
def test_middle_page(self):
|
|
items = list(range(100))
|
|
params = PaginationParams(page=5, page_size=10)
|
|
result = paginate(items, params)
|
|
assert result.data == list(range(40, 50))
|
|
assert result.pagination.has_next is True
|
|
assert result.pagination.has_prev is True
|