Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/nene2/http/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,19 @@ def parse(
Raises ValidationException (→ 422) when values are out of range.
"""
params = request.query_params
limit = int(params.get("limit", default_limit))
offset = int(params.get("offset", 0))

errors: list[ValidationError] = []
try:
limit = int(params.get("limit", default_limit))
except ValueError:
errors.append(ValidationError("limit", "limit must be an integer.", "invalid"))
limit = default_limit
try:
offset = int(params.get("offset", 0))
except ValueError:
errors.append(ValidationError("offset", "offset must be an integer.", "invalid"))
offset = 0

if limit < 1 or limit > max_limit:
errors.append(
ValidationError(
Expand Down
28 changes: 28 additions & 0 deletions tests/nene2/http/test_pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,34 @@ def test_limit_out_of_range_raises() -> None:
assert exc_info.value.errors[0].field == "limit"


def test_non_integer_limit_raises_validation_exception() -> None:
mock_request = MagicMock(spec=Request)
mock_request.query_params = {"limit": "abc"}
with pytest.raises(ValidationException) as exc_info:
PaginationQueryParser.parse(mock_request)
assert exc_info.value.errors[0].field == "limit"
assert exc_info.value.errors[0].code == "invalid"


def test_non_integer_offset_raises_validation_exception() -> None:
mock_request = MagicMock(spec=Request)
mock_request.query_params = {"offset": "xyz"}
with pytest.raises(ValidationException) as exc_info:
PaginationQueryParser.parse(mock_request)
assert exc_info.value.errors[0].field == "offset"
assert exc_info.value.errors[0].code == "invalid"


def test_both_invalid_collects_all_errors() -> None:
mock_request = MagicMock(spec=Request)
mock_request.query_params = {"limit": "abc", "offset": "xyz"}
with pytest.raises(ValidationException) as exc_info:
PaginationQueryParser.parse(mock_request)
fields = [e.field for e in exc_info.value.errors]
assert "limit" in fields
assert "offset" in fields


def test_pagination_response_without_total() -> None:
r = PaginationResponse(items=[{"id": 1}], limit=20, offset=0)
d = r.to_dict()
Expand Down
Loading