v0.4.0's merge of public_booking_dict landed inside AvailabilityQuery and left the two date fields orphaned after the helper's return, so POST /api/v1/availability raised AttributeError on q.check_in (500) on every install of that version. The RPC door reads the raw body and was unaffected, which is why nothing noticed. Put the helper next to public_room_dict and add a regression test that constructs the query model and drives the endpoint through the services layer. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
56 lines
2.1 KiB
Python
56 lines
2.1 KiB
Python
"""Guest availability endpoint. Regression guard for v0.4.0, where a bad merge
|
|
left AvailabilityQuery with only `room_id` and POST /availability 500'd on
|
|
`q.check_in` — the RPC door reads the raw body, so only HTTP was broken and no
|
|
test exercised it."""
|
|
|
|
import asyncio
|
|
|
|
import pytest
|
|
from fastapi import HTTPException
|
|
from pydantic import ValidationError
|
|
|
|
from .. import services, views_api
|
|
from ..models import AvailabilityQuery, AvailabilityResult
|
|
|
|
|
|
def test_availability_query_requires_both_dates():
|
|
q = AvailabilityQuery(room_id="r", check_in="2026-10-01", check_out="2026-10-03")
|
|
assert (q.room_id, q.check_in, q.check_out) == ("r", "2026-10-01", "2026-10-03")
|
|
assert set(AvailabilityQuery.__fields__) == {"room_id", "check_in", "check_out"}
|
|
with pytest.raises(ValidationError):
|
|
AvailabilityQuery(room_id="r") # type: ignore[call-arg]
|
|
|
|
|
|
def test_availability_endpoint_forwards_all_three_fields(monkeypatch):
|
|
seen: list[tuple] = []
|
|
|
|
async def fake(room_id, check_in, check_out):
|
|
seen.append((room_id, check_in, check_out))
|
|
return AvailabilityResult(
|
|
room_id=room_id,
|
|
check_in=check_in,
|
|
check_out=check_out,
|
|
available=True,
|
|
nights=2,
|
|
)
|
|
|
|
monkeypatch.setattr(services, "get_availability", fake)
|
|
q = AvailabilityQuery(room_id="r", check_in="2026-10-01", check_out="2026-10-03")
|
|
out = asyncio.run(views_api.api_check_availability(q))
|
|
assert seen == [("r", "2026-10-01", "2026-10-03")]
|
|
assert out.available and out.nights == 2
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("exc", "status"),
|
|
[(services.NotFound("Room not found"), 404), (ValueError("bad dates"), 400)],
|
|
)
|
|
def test_availability_endpoint_maps_service_errors(monkeypatch, exc, status):
|
|
async def fake(*_):
|
|
raise exc
|
|
|
|
monkeypatch.setattr(services, "get_availability", fake)
|
|
q = AvailabilityQuery(room_id="r", check_in="2026-10-03", check_out="2026-10-01")
|
|
with pytest.raises(HTTPException) as e:
|
|
asyncio.run(views_api.api_check_availability(q))
|
|
assert e.value.status_code == status
|