90 lines
3.2 KiB
Python
90 lines
3.2 KiB
Python
"""Tests for common schemas — FailedUrl, PageImage, make_error_detail."""
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from web.schemas.common import FailedUrl, PageImage, make_error_detail
|
|
|
|
|
|
class TestFailedUrl:
|
|
"""Tests for FailedUrl schema."""
|
|
|
|
def test_round_trip(self) -> None:
|
|
"""Test serialization round-trip."""
|
|
obj = FailedUrl(url="https://example.com", error="Timeout")
|
|
data = obj.model_dump()
|
|
assert data == {"url": "https://example.com", "error": "Timeout"}
|
|
restored = FailedUrl.model_validate(data)
|
|
assert restored == obj
|
|
|
|
def test_extra_fields_rejected(self) -> None:
|
|
"""Test that extra fields are rejected."""
|
|
with pytest.raises(ValidationError):
|
|
FailedUrl(url="https://example.com", error="Timeout", extra="bad")
|
|
|
|
def test_json_round_trip(self) -> None:
|
|
"""Test JSON serialization round-trip."""
|
|
obj = FailedUrl(url="https://a.com", error="Connection refused")
|
|
json_str = obj.model_dump_json()
|
|
restored = FailedUrl.model_validate_json(json_str)
|
|
assert restored == obj
|
|
|
|
|
|
class TestPageImage:
|
|
"""Tests for PageImage schema."""
|
|
|
|
def test_round_trip(self) -> None:
|
|
"""Test serialization round-trip."""
|
|
obj = PageImage(url="https://img.example.com/1.jpg", alt="Photo")
|
|
data = obj.model_dump()
|
|
assert data == {"url": "https://img.example.com/1.jpg", "alt": "Photo"}
|
|
restored = PageImage.model_validate(data)
|
|
assert restored == obj
|
|
|
|
def test_alt_defaults_to_none(self) -> None:
|
|
"""Test that alt text defaults to None."""
|
|
obj = PageImage(url="https://img.example.com/1.jpg")
|
|
assert obj.alt is None
|
|
|
|
def test_extra_fields_rejected(self) -> None:
|
|
"""Test that extra fields are rejected."""
|
|
with pytest.raises(ValidationError):
|
|
PageImage(url="https://img.example.com/1.jpg", width=100)
|
|
|
|
|
|
class TestMakeErrorDetail:
|
|
"""Tests for make_error_detail helper."""
|
|
|
|
def test_basic(self) -> None:
|
|
"""Test basic error detail."""
|
|
result = make_error_detail("not_found", "Resource not found")
|
|
assert result == {"error": "not_found", "message": "Resource not found"}
|
|
|
|
def test_with_request_id(self) -> None:
|
|
"""Test error detail with request_id."""
|
|
result = make_error_detail("timeout", "Request timed out", request_id="abc-123")
|
|
assert result == {
|
|
"error": "timeout",
|
|
"message": "Request timed out",
|
|
"request_id": "abc-123",
|
|
}
|
|
|
|
def test_with_extra_fields(self) -> None:
|
|
"""Test error detail with extra fields."""
|
|
result = make_error_detail(
|
|
"rate_limit",
|
|
"Too many requests",
|
|
request_id="xyz",
|
|
retry_after=30.0,
|
|
)
|
|
assert result == {
|
|
"error": "rate_limit",
|
|
"message": "Too many requests",
|
|
"request_id": "xyz",
|
|
"retry_after": 30.0,
|
|
}
|
|
|
|
def test_no_request_id_when_none(self) -> None:
|
|
"""Test that request_id is omitted when None."""
|
|
result = make_error_detail("error", "msg", request_id=None)
|
|
assert "request_id" not in result
|