From 408b0e1d088d82671264f9f611b87f046ec7f826 Mon Sep 17 00:00:00 2001 From: Padreug Date: Mon, 20 Jul 2026 01:39:39 +0200 Subject: [PATCH] test: public endpoints + private-field strip Asserts public_room_dict drops wallet + checkin_instructions, public list shows active-only + stripped, and public get 404s on inactive. 32 pass. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD --- tests/test_public_endpoints.py | 60 ++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 tests/test_public_endpoints.py diff --git a/tests/test_public_endpoints.py b/tests/test_public_endpoints.py new file mode 100644 index 0000000..363ae7c --- /dev/null +++ b/tests/test_public_endpoints.py @@ -0,0 +1,60 @@ +"""Public guest discovery endpoints + the operator-private field strip +(privacy: check-in instructions must never reach a guest).""" + +import asyncio + +import pytest +from fastapi import HTTPException + +from .. import crud, views_api +from ..models import RoomStatus, public_room_dict +from .conftest import make_room + + +def test_public_room_dict_strips_private_fields(): + room = make_room(wallet="w1") + room.checkin_instructions = "gate code 4213, door on the left" + d = public_room_dict(room) + assert "wallet" not in d # operator-internal + assert "checkin_instructions" not in d # private, DM-only + assert d["title"] == "Tower Room" # public fields survive + assert d["price_amount"] == 100 + + +def test_public_rooms_lists_active_only_and_stripped(monkeypatch): + active = make_room("a", status=RoomStatus.active) + active.checkin_instructions = "secret" + inactive = make_room("b", status=RoomStatus.inactive) + + async def gr(): + return [active, inactive] + + monkeypatch.setattr(crud, "get_rooms", gr) + out = asyncio.run(views_api.api_public_rooms()) + assert [r["id"] for r in out] == ["a"] # inactive hidden from guests + assert "checkin_instructions" not in out[0] + assert "wallet" not in out[0] + + +def test_public_room_404_when_inactive(monkeypatch): + async def gr(_): + return make_room(status=RoomStatus.inactive) + + monkeypatch.setattr(crud, "get_room", gr) + with pytest.raises(HTTPException) as e: + asyncio.run(views_api.api_public_room("x")) + assert e.value.status_code == 404 + + +def test_public_room_returns_stripped_when_active(monkeypatch): + room = make_room("a", status=RoomStatus.active) + room.checkin_instructions = "gate" + + async def gr(_): + return room + + monkeypatch.setattr(crud, "get_room", gr) + out = asyncio.run(views_api.api_public_room("a")) + assert out["id"] == "a" + assert "checkin_instructions" not in out + assert "wallet" not in out