feat: operator admin UI + backing endpoints (v0.2.0) #16
1 changed files with 93 additions and 0 deletions
test: operator admin endpoint logic (ownership, update, settings merge)
5 tests calling the view functions directly with a fake auth key: _owned_room 403/404, list-rooms wallet filter, room update applies only mutable fields (wallet/id immutable), settings PUT merges editable fields. 28 pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD
commit
72061b57eb
93
tests/test_admin_endpoints.py
Normal file
93
tests/test_admin_endpoints.py
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
"""Operator admin endpoint logic (backs the admin UI). Calls the view
|
||||||
|
functions directly with a fake auth key (bypassing FastAPI's Depends) and
|
||||||
|
monkeypatched crud — no live server."""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
from types import SimpleNamespace
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from fastapi import HTTPException
|
||||||
|
|
||||||
|
from .. import crud, views_api
|
||||||
|
from ..models import ChateletSettings, CreateRoomData, RoomStatus
|
||||||
|
from .conftest import make_room
|
||||||
|
|
||||||
|
|
||||||
|
def _key(wallet_id: str = "w1"):
|
||||||
|
return SimpleNamespace(wallet=SimpleNamespace(id=wallet_id, user="u1"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_owned_room_rejects_other_wallet(monkeypatch):
|
||||||
|
async def gr(_):
|
||||||
|
return make_room(wallet="w1")
|
||||||
|
|
||||||
|
monkeypatch.setattr(crud, "get_room", gr)
|
||||||
|
with pytest.raises(HTTPException) as e:
|
||||||
|
asyncio.run(views_api._owned_room("room1", _key("w2")))
|
||||||
|
assert e.value.status_code == 403
|
||||||
|
|
||||||
|
|
||||||
|
def test_owned_room_404_when_missing(monkeypatch):
|
||||||
|
async def gr(_):
|
||||||
|
return None
|
||||||
|
|
||||||
|
monkeypatch.setattr(crud, "get_room", gr)
|
||||||
|
with pytest.raises(HTTPException) as e:
|
||||||
|
asyncio.run(views_api._owned_room("nope", _key()))
|
||||||
|
assert e.value.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_rooms_filters_to_calling_wallet(monkeypatch):
|
||||||
|
async def gr():
|
||||||
|
return [make_room("a", wallet="w1"), make_room("b", wallet="w2")]
|
||||||
|
|
||||||
|
monkeypatch.setattr(crud, "get_rooms", gr)
|
||||||
|
out = asyncio.run(views_api.api_list_rooms(key=_key("w1")))
|
||||||
|
assert [r.id for r in out] == ["a"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_room_applies_mutable_fields_only(monkeypatch):
|
||||||
|
room = make_room("room1", wallet="w1", status=RoomStatus.inactive)
|
||||||
|
|
||||||
|
async def gr(_):
|
||||||
|
return room
|
||||||
|
|
||||||
|
async def ur(r):
|
||||||
|
return r
|
||||||
|
|
||||||
|
monkeypatch.setattr(crud, "get_room", gr)
|
||||||
|
monkeypatch.setattr(crud, "update_room", ur)
|
||||||
|
|
||||||
|
data = CreateRoomData(
|
||||||
|
wallet="attacker", title="New Title", price_amount=200,
|
||||||
|
price_currency="USD", max_guests=5, checkin_instructions="gate 7",
|
||||||
|
)
|
||||||
|
out = asyncio.run(views_api.api_update_room("room1", data, key=_key("w1")))
|
||||||
|
assert out.title == "New Title"
|
||||||
|
assert out.price_amount == 200
|
||||||
|
assert out.checkin_instructions == "gate 7"
|
||||||
|
assert out.wallet == "w1" # wallet is NOT client-mutable
|
||||||
|
assert out.id == "room1" # id unchanged
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_settings_merges_editable_fields(monkeypatch):
|
||||||
|
existing = ChateletSettings(operator_id=None, deposit_percent=100)
|
||||||
|
|
||||||
|
async def gs():
|
||||||
|
return existing
|
||||||
|
|
||||||
|
async def us(s):
|
||||||
|
return s
|
||||||
|
|
||||||
|
monkeypatch.setattr(crud, "get_or_create_settings", gs)
|
||||||
|
monkeypatch.setattr(crud, "update_settings", us)
|
||||||
|
|
||||||
|
incoming = ChateletSettings(
|
||||||
|
operator_id="op1", deposit_percent=50, default_hold_minutes=45,
|
||||||
|
relays=["wss://relay.example"],
|
||||||
|
)
|
||||||
|
out = asyncio.run(views_api.api_update_settings(incoming, key=_key()))
|
||||||
|
assert out.operator_id == "op1"
|
||||||
|
assert out.deposit_percent == 50
|
||||||
|
assert out.default_hold_minutes == 45
|
||||||
|
assert out.relays == ["wss://relay.example"]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue