metropolis-chess / tests /test_phase_4_2_5_zero_button.py
Forkei's picture
Fix 4: implicitly unmute ambient audio on first user gesture
cf83640
"""Phase 4.2.5 — zero-button pass: auto-start PvP when both seated + clock control."""
from __future__ import annotations
import pytest
from app.db import SessionLocal
from app.lobbies.service import (
ControlsPatch,
CreateLobbyIn,
LobbyInvalidControl,
TIME_CONTROL_PRESETS,
create_lobby,
join_lobby,
update_controls,
)
from app.models.lobby import Lobby
from app.models.match import Player
def _mk_player(s, username: str) -> Player:
p = Player(username=username, display_name=username, elo=1200)
s.add(p); s.commit(); s.refresh(p)
return p
# --- tabletop clock control ----------------------------------------------
def test_clock_defaults_to_untimed():
with SessionLocal() as s:
host = _mk_player(s, "clk_1")
lob = create_lobby(s, host, CreateLobbyIn())
assert lob.time_control == "untimed"
def test_clock_cycle_accepts_known_presets():
with SessionLocal() as s:
host = _mk_player(s, "clk_2")
lob = create_lobby(s, host, CreateLobbyIn())
for preset in TIME_CONTROL_PRESETS:
update_controls(s, lob, by=host, patch=ControlsPatch(time_control=preset))
s.refresh(lob)
assert lob.time_control == preset
def test_clock_rejects_unknown_preset():
with SessionLocal() as s:
host = _mk_player(s, "clk_3")
lob = create_lobby(s, host, CreateLobbyIn())
with pytest.raises(LobbyInvalidControl):
update_controls(s, lob, by=host, patch=ControlsPatch(time_control="3+7"))
# --- auto-start on second seat -------------------------------------------
def test_lobby_state_endpoint_exposes_time_control(tmp_path, monkeypatch):
from fastapi.testclient import TestClient
from app.main import create_app
from tests.conftest import signup_and_login
c = TestClient(create_app(), follow_redirects=False)
signup_and_login(c, "state_user")
r = c.post("/lobby/new", data={
"music_volume": 0.5, "lights_brightness": 0.7, "lights_hue": "#C9A66B",
})
lobby_id = r.headers["location"].rsplit("/", 1)[-1]
r = c.get(f"/lobby/{lobby_id}/state")
assert r.status_code == 200
assert r.json()["time_control"] == "untimed"
r = c.post(f"/lobby/{lobby_id}/controls", data={"time_control": "10+0"})
assert r.status_code == 200
assert r.json()["time_control"] == "10+0"
def test_lobby_ambient_script_unmutes_on_first_gesture():
"""Fix 4 (demo-rescue): lobby_ambient.js must implicitly unmute on
the first user gesture when no explicit preference is stored. The
coffee_shop.ogg bed otherwise plays at volume 0 and looks broken.
Lock in the implementation so a future refactor doesn't silently
revert to opt-in audio."""
from pathlib import Path
src = Path("app/web/static/js/lobby_ambient.js").read_text(encoding="utf-8")
# The unmute-on-first-gesture branch must call setItem("mp_ambient_muted", "false").
assert "MUTED_KEY" in src
assert 'setItem(MUTED_KEY, "false")' in src
assert "onFirstGesture" in src