chatelet/tests/test_events.py
Padreug 1465a30a01 test: event-builder shape (30402/30078/31923/22001)
Pure tests (no signing/relays): listing tags (d/title/price/status/g/t),
reservation carries canonical amount_sat as plaintext JSON, calendar
start/end + no broken 'a' tag, availability response plaintext. 20 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019VUQCfdqiLSsFS2jcGnaFD
2026-07-19 18:09:35 +02:00

90 lines
3.1 KiB
Python

"""Nostr event builders — tag/kind/content shape (no signing, no relays)."""
import json
from ..models import AvailabilityResult, Booking, BookingStatus
from ..nostr import events
from ..nostr.kinds import (
KIND_AVAILABILITY_RESPONSE,
KIND_CALENDAR_EVENT,
KIND_LISTING,
KIND_RESERVATION,
)
from .conftest import make_room
def _tag(ev, name):
"""First tag value for `name`, or None."""
return next((t[1] for t in ev["tags"] if t[0] == name), None)
def _tags(ev, name):
return [t[1] for t in ev["tags"] if t[0] == name]
def test_listing_event_shape():
room = make_room(
currency="EUR", price=80.0,
)
room.amenities = ["wifi", "breakfast"]
room.location = "Château"
room.geohash = "u0j2"
room.images = ["https://img/1.jpg"]
ev = events.build_listing_event(room)
assert ev["kind"] == KIND_LISTING # 30402
assert _tag(ev, "d") == room.id # addressable: re-publish replaces
assert _tag(ev, "title") == "Tower Room"
price = next(t for t in ev["tags"] if t[0] == "price")
assert price == ["price", "80.0", "EUR", "night"]
assert _tag(ev, "status") == "active"
assert _tag(ev, "location") == "Château"
assert _tag(ev, "g") == "u0j2"
assert _tags(ev, "image") == ["https://img/1.jpg"]
assert set(_tags(ev, "t")) == {"wifi", "breakfast"}
def test_reservation_event_is_plaintext_json_no_scaffolding():
booking = Booking(
id="bk1", room_id="room1", guest_pubkey="npub_guest",
check_in="2026-08-01", check_out="2026-08-04", nights=3, num_guests=2,
currency="sat", price_fiat=300.0, amount_sat=300, deposit_sat=300,
status=BookingStatus.confirmed,
)
ev = events.build_reservation_event(booking, booking.guest_pubkey)
assert ev["kind"] == KIND_RESERVATION # 30078
assert _tag(ev, "d") == "bk1"
assert _tag(ev, "p") == "npub_guest"
assert "_plaintext" not in ev # scaffolding removed; service.py encrypts content
payload = json.loads(ev["content"])
assert payload["amount_sat"] == 300 # canonical, carried verbatim
assert payload["status"] == "confirmed"
def test_block_calendar_event_shape():
room = make_room()
ev = events.build_block_calendar_event(room, "2026-09-01", "2026-09-05", "blk1")
assert ev["kind"] == KIND_CALENDAR_EVENT # 31923
assert _tag(ev, "d") == "room1:blk1"
assert _tag(ev, "start") == "2026-09-01"
assert _tag(ev, "end") == "2026-09-05"
# the broken {operator_pubkey} 'a' tag was removed
assert not any(t[0] == "a" for t in ev["tags"])
def test_availability_response_is_plaintext():
result = AvailabilityResult(
room_id="room1", check_in="2026-08-01", check_out="2026-08-04",
available=True, nights=3, quote_sat=300, quote_fiat=3.0, currency="sat",
)
ev = events.build_availability_response(result, "npub_requester")
assert ev["kind"] == KIND_AVAILABILITY_RESPONSE # 22001
assert _tag(ev, "p") == "npub_requester"
assert "_plaintext" not in ev # public info: no encryption
payload = json.loads(ev["content"])
assert payload["available"] is True
assert payload["quote_sat"] == 300