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
This commit is contained in:
parent
e6973fa192
commit
72061b57eb
1 changed files with 93 additions and 0 deletions
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