Files
OBS-Overlays/blackout-bingo/tests/test_server.py
T

92 lines
3.5 KiB
Python

import json
import os
import subprocess
import sys
import tempfile
import time
import urllib.request
from pathlib import Path
def start_server(tmp_path):
src = Path(__file__).resolve().parents[1]
work = tmp_path / "app"
work.mkdir()
for name in ["server.py", "overlay.html", "editor.html"]:
(work / name).write_text((src / name).read_text(), encoding="utf-8")
(work / "bingo.json").write_text((src / "defaults" / "bingo.json").read_text(), encoding="utf-8")
proc = subprocess.Popen(
[sys.executable, "server.py", "8780"],
cwd=work,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
)
deadline = time.time() + 5
while time.time() < deadline:
try:
urllib.request.urlopen("http://127.0.0.1:8780/api/bingo", timeout=0.25).read()
return proc, work
except Exception:
time.sleep(0.1)
output = proc.stdout.read() if proc.stdout else ""
proc.kill()
raise AssertionError(f"server did not start: {output}")
def request_json(url, method="GET", payload=None):
data = None
headers = {}
if payload is not None:
data = json.dumps(payload).encode("utf-8")
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=2) as resp:
return json.loads(resp.read().decode("utf-8"))
def test_save_rejects_more_than_100_tasks(tmp_path):
proc, work = start_server(tmp_path)
try:
payload = {"tasks": [f"Task {i}" for i in range(101)], "board": [], "players": ["P1", "P2"]}
try:
request_json("http://127.0.0.1:8780/api/bingo", "POST", payload)
except urllib.error.HTTPError as exc:
assert exc.code == 400
else:
raise AssertionError("expected 400 for too many tasks")
finally:
proc.kill()
def test_save_and_generate_25_unique_board_cells(tmp_path):
proc, work = start_server(tmp_path)
try:
tasks = [f"Challenge {i:02d}" for i in range(30)]
saved = request_json("http://127.0.0.1:8780/api/bingo", "POST", {"tasks": tasks, "board": [], "players": ["Ash", "Misty"]})
assert saved["ok"] is True
generated = request_json("http://127.0.0.1:8780/api/generate", "POST", {"seed": "demo"})
board = generated["data"]["board"]
assert len(board) == 25
assert len({cell["task"] for cell in board}) == 25
assert all(cell["completedBy"] == [] for cell in board)
assert (work / "bingo.json").exists()
finally:
proc.kill()
def test_mark_cell_toggles_two_players_independently(tmp_path):
proc, work = start_server(tmp_path)
try:
tasks = [f"Task {i}" for i in range(25)]
request_json("http://127.0.0.1:8780/api/bingo", "POST", {"tasks": tasks, "board": [], "players": ["Blue", "Red"]})
request_json("http://127.0.0.1:8780/api/generate", "POST", {"seed": "fixed"})
one = request_json("http://127.0.0.1:8780/api/mark", "POST", {"cellId": 0, "player": "Blue"})
assert one["data"]["board"][0]["completedBy"] == ["Blue"]
two = request_json("http://127.0.0.1:8780/api/mark", "POST", {"cellId": 0, "player": "Red"})
assert set(two["data"]["board"][0]["completedBy"]) == {"Blue", "Red"}
off = request_json("http://127.0.0.1:8780/api/mark", "POST", {"cellId": 0, "player": "Blue"})
assert off["data"]["board"][0]["completedBy"] == ["Red"]
finally:
proc.kill()