92 lines
3.5 KiB
Python
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()
|