Files
weirsoe-party-protocol/party/tests/test_ws.py
T
agw 16054a9b67
CI / test (push) Successful in 28s
Skærmen følger speakeren, opsummering, musik, lydeffekter og drillerier
Faseskift venter, til speakeren er færdig med den aktuelle skærm, og
replikker til en skærm, der er væk, afspilles ikke. Ny kategori-intro med
en lyd pr. kategori, musik pr. fase med bløde overgange og lydeffekter til
alt, der flyver over skærmen. Efter afsløringen eksploderer løgne, ingen
valgte, og pointene tæller op. Hjerter gives kun under afsløringen og ses
live på storskærmen. Lyv for mig giver halve point. Narrede spilleres
telefon kan blive drillet med et fjollet billede og et buh. Alle lyd- og
billedfiler serveres med versionerede navne og caches af browseren.

Claude-Session: https://claude.ai/code/session_01JmhJG6JnhXfzNiKv8f2vHu
2026-10-01 21:59:40 +02:00

130 lines
5.4 KiB
Python

from channels.testing.websocket import WebsocketCommunicator
from django.test import TransactionTestCase, override_settings
from fupogfakta.models import Category, Question
from partyhub.asgi import application
from party import rooms
def make_bank():
for c in range(1, 6):
cat = Category.objects.create(name=f"Kat {c}")
for i in range(3):
Question.objects.create(category=cat, prompt=f"Spørgsmål {c}-{i} _____.", answer=f"sandt{c}{i}",
decoys=["x", "y", "z"])
async def recv_until(comm, type_, phase=None, limit=20):
for _ in range(limit):
msg = await comm.receive_json_from(timeout=3)
if msg["type"] == type_ and (phase is None or msg["state"]["phase"] == phase):
return msg
raise AssertionError(f"fik aldrig {type_} {phase}")
HOST_HEADERS = [(b"x-authentik-username", b"agw"), (b"x-authentik-groups", b"Familie")]
@override_settings(TRUSTED_PROXIES=["127.0.0.1"], DEV_HOST_USER=None)
class WebSocketGameTests(TransactionTestCase):
def setUp(self):
rooms.all_rooms().clear()
make_bank()
from fupogfakta import engine as _engine
self._intro, _engine.INTRO_SECONDS = _engine.INTRO_SECONDS, 0.2
self.addCleanup(setattr, _engine, "INTRO_SECONDS", self._intro)
def _room(self):
from fupogfakta.models import load_game_questions
return rooms.create_room(load_game_questions(), "agw", "http://testserver")
async def _host(self, code, headers=HOST_HEADERS):
comm = WebsocketCommunicator(application, f"/ws/host/{code}/", headers=headers)
comm.scope["client"] = ("127.0.0.1", 5000)
return comm
async def test_host_requires_authentik_header(self):
room = await self._sync(self._room)
comm = await self._host(room.code, headers=[])
connected, code = await comm.connect()
self.assertFalse(connected)
async def test_header_from_untrusted_ip_is_ignored(self):
room = await self._sync(self._room)
comm = WebsocketCommunicator(application, f"/ws/host/{room.code}/", headers=HOST_HEADERS)
comm.scope["client"] = ("203.0.113.9", 5000)
connected, _ = await comm.connect()
self.assertFalse(connected)
async def test_unknown_room(self):
comm = WebsocketCommunicator(application, "/ws/play/ZZZZ/")
connected, _ = await comm.connect()
self.assertTrue(connected)
msg = await comm.receive_json_from()
self.assertEqual(msg["code"], "unknown_room")
await comm.disconnect()
async def test_join_play_a_question_and_resume(self):
room = await self._sync(self._room)
host = await self._host(room.code)
self.assertTrue((await host.connect())[0])
await recv_until(host, "state", "lobby")
phones = []
for name in ["Asger", "Sus", "Jørn"]:
c = WebsocketCommunicator(application, f"/ws/play/{room.code}/")
await c.connect()
await c.send_json_to({"action": "join", "name": name})
joined = await recv_until(c, "joined")
phones.append((c, joined))
await phones[0][0].send_json_to({"action": "start"})
st = (await recv_until(host, "state", "category"))["state"]
chooser = next(c for c, j in phones if j["player_id"] == st["category"]["chooser_id"])
await chooser.send_json_to({"action": "choose_category", "category_id": st["category"]["options"][0]["id"]})
await recv_until(host, "state", "lie")
for i, (c, _) in enumerate(phones):
await c.send_json_to({"action": "submit_lie", "text": f"løgn {i}"})
st = (await recv_until(host, "state", "guess"))["state"]
self.assertGreaterEqual(len(st["answers"]), 4)
for c, j in phones:
mine = (await recv_until(c, "state", "guess"))["state"]
await c.send_json_to({"action": "guess", "answer_id": mine["answers"][0]["id"]})
st = (await recv_until(host, "state", "reveal"))["state"]
self.assertTrue(st["reveal"]["steps"][-1]["is_truth"])
# Telefonen mister forbindelsen og kommer tilbage med sit token.
c0, j0 = phones[0]
await c0.disconnect()
again = WebsocketCommunicator(application, f"/ws/play/{room.code}/")
await again.connect()
await again.send_json_to({"action": "resume", "token": j0["token"]})
self.assertEqual((await recv_until(again, "joined"))["player_id"], j0["player_id"])
st = (await recv_until(again, "state"))["state"]
self.assertEqual(st["me"]["id"], j0["player_id"])
for c, _ in phones[1:]:
await c.disconnect()
await again.disconnect()
await host.disconnect()
async def test_errors_are_reported_not_raised(self):
room = await self._sync(self._room)
c = WebsocketCommunicator(application, f"/ws/play/{room.code}/")
await c.connect()
await c.send_json_to({"action": "start"})
self.assertEqual((await c.receive_json_from())["code"], "unknown_token")
await c.send_json_to({"action": "join", "name": "A"})
await recv_until(c, "joined")
await c.send_json_to({"action": "guess"})
msg = await recv_until(c, "error")
self.assertIn(msg["code"], ("wrong_phase", "bad_request"))
await c.disconnect()
@staticmethod
async def _sync(fn):
from asgiref.sync import sync_to_async
return await sync_to_async(fn)()