# 本地实时 1v1 与联机码约战测试 本指南用于在一台电脑上使用两个浏览器会话验证完整联机流程。 ## 1. 准备数据 ```bash make install make migrate make seed ``` 种子数据会创建三个赛道的实时 1v1 比赛。本地邀请码为: ```text HULU2026 ``` ## 2. 使用 ASGI 启动 实时比赛依赖 WebSocket。不要使用普通 WSGI 服务测试联机。 ```bash make run-asgi ``` 访问: ```text http://127.0.0.1:8000/ ``` 本地没有配置 `REDIS_URL` 时会使用进程内 Channel Layer,适合单进程开发测试。生产环境必须使用 Redis。 ### 一键端到端验证 保持 `make run-asgi` 运行,另开终端执行: ```bash .venv/bin/python scripts/test_realtime_local.py ``` 脚本会临时创建两个本地账号,通过真实 HTTP Session 和两个真实 WebSocket 完成: ```text 创建联机码 → 第二位玩家加入 → matched 状态推送 → 答题进度同步 → 第一位提交且不泄露答案 → 第二位提交 → completed 推送 → 胜负、Rating 和解析检查 ``` 结束后脚本自动清理临时用户和比赛记录。 ## 3. 准备两个独立登录会话 使用下列任一组合: - Chrome 普通窗口 + 无痕窗口 - Chrome + Safari - 两个不同浏览器 Profile 两个窗口分别使用邀请码 `HULU2026` 注册不同账号。不要在同一浏览器 Profile 的两个普通标签页登录不同账号,因为它们会共享 Session Cookie。 ## 4. 联机码约战 玩家 A: 1. 打开“比赛”。 2. 选择双方约定的赛道。 3. 点击“创建当前赛道约战”。 4. 复制 6 位联机码。 玩家 B: 1. 打开“比赛”。 2. 输入联机码。 3. 点击“加入约战”。 预期结果: - 玩家 A 无需再次点击,自动进入答题。 - 双方显示相同题目和同一个倒计时。 - 任一方填写答案时,另一方看到答题数量变化。 - 第一位提交者只看到“答案已锁定”,看不到正确答案。 - 双方提交或倒计时结束后,同时展示胜负、双方分数、Rating 变化和题目解析。 ## 5. 随机匹配 双方选择同一赛道并点击“开始匹配”。 预期结果: - 第一位玩家进入等待状态。 - 第二位玩家加入后,第一位玩家自动进入答题。 - 私人联机码房间不会被随机匹配玩家加入。 ## 6. 断线与超时 验证以下场景: 1. 答题时短暂关闭网络,再恢复。 2. WebSocket 断开后页面仍每 2 秒轮询比赛状态。 3. 关闭其中一个窗口,另一方等待倒计时结束。 4. 服务端到时后将未提交 Attempt 标记为过期并完成结算。 5. 等待中的联机码 10 分钟后失效。 ## 7. 排查 浏览器开发者工具应看到: ```text WS /ws/v1/contest/matches// GET /api/v1/contests/matches// ``` 检查 Redis: ```bash redis-cli ping ``` 检查 ASGI: ```bash curl http://127.0.0.1:8000/health/ ``` 生产 Nginx 必须为 `/ws/` 设置 `Upgrade` 和 `Connection` 请求头。详见 `docs/DEPLOYMENT.md`。