游戏分发 web E2E 的冷启动假失败改为浏览器级预热
Project CI / AI game creator shell Rust crates (push) Successful in 1m31s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m56s
Project CI / Backend tests (push) Successful in 3m56s
Project CI / Frontend tests (push) Successful in 2m7s
Project CI / Native shell tests (push) Successful in 6m0s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 8m34s
Project CI / AI game creator shell web tests (push) Successful in 1m42s
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 9m40s
Project CI / Repository checks (push) Successful in 2m15s

- 现象:冷 Vite 下 check:game-distribution-web-e2e 先卡在目录卡片 20 秒等待,重跑又卡在游玩页「开始游戏」15 秒等待;同一时刻公开目录 API 已把该游戏排在第一
- 根因:原先的 fetch 预热只拿到 SPA 外壳(HTML 里没有路由模块),Vite 仍在断言阶段现编译这些模块图
- 修复:改成起浏览器后用一次性 context 真走 /games、/games/detail、/games/play(domcontentloaded + 2 秒 settle,120 秒上限,失败只告警),首个 goto 的 120 秒超时保留
- 复验:重启 dev 栈(冷缓存)→ 24/24 PASS;四条 web E2E(web / publish / publish-recovery / a11y)全部复跑通过
- 文档:里程碑补 2026-09-29 复跑记录,pitfalls 同日条目按实测证据补正
This commit is contained in:
kdletters
2026-09-29 06:54:47 +08:00
parent 198c208172
commit d8011a72fa
3 changed files with 49 additions and 24 deletions
@@ -277,4 +277,15 @@
- `check:game-distribution-web-publish-recovery-e2e` → 全部通过(中断恢复草稿、重登继续沿用原版本、恢复后清理草稿、换账号看不到他人草稿)。
- `check:game-distribution-web-a11y-e2e` → 全部通过(桌面/移动导航、键盘可达、全屏、安全区、移动发布面板无横向溢出)。
**顺带修掉一处取证噪声**:`check:game-distribution-web-e2e` 的首个 `goto` 用的是默认 30 秒超时,碰上 Vite dev 冷启动(实测 `/games` 首请求 20.2 秒、warm 后 14 毫秒)会以 `Timeout 30000ms exceeded` 假失败。现在脚本在导航前先 `fetch` 预热 `/games`、`/games/detail?id=…`、`/games/play?id=…` 三条路由并把首个 `goto` 超时提到 120 秒;冷启动重跑即 24/24 PASS(详见 pitfalls 同日条目)。
**顺带修掉一处取证噪声**:`check:game-distribution-web-e2e` 的首个 `goto` 用的是默认 30 秒超时,碰上 Vite dev 冷启动(实测 `/games` 首请求 20.2 秒、warm 后 14 毫秒)会以 `Timeout 30000ms exceeded` 假失败。当时只是在导航前 `fetch` 预热三条路由并把首个 `goto` 超时提到 120 秒——**这版预热不够**(`fetch` 拿到的 SPA 外壳里没有路由模块),2026-09-29 已改成浏览器级预热,见下。
## 2026-09-29 复跑(四条 E2E 全绿 + 冷启动噪声彻底修掉)
重新拉起 `npm run dev` 后把四条真实网页栈 E2E 全部重跑,**四条全绿**:`check:game-distribution-web-e2e` **24/24 PASS**、`check:game-distribution-web-publish-e2e` / `-web-publish-recovery-e2e` / `-web-a11y-e2e` 全部通过(列表、发布待审、中断恢复草稿、桌面与移动导航/键盘可达都在内)。
其中 `web-e2e` 的冷启动假失败这次才真正修干净:
- **现象**:冷缓存下重跑,先在 `button.game-card:visible` 的 **20 秒**等待超时;第二次(目录已热)推进到游玩页 `getByRole('button', { name: '开始游戏' })` 的 **15 秒**等待超时。两次都停在「该路由第一次被浏览器加载」的那一步,而同一时刻公开目录 API 已把该游戏排在第一(说明后端与数据都没问题)。
- **根因**:`fetch('/games')` 只取到 SPA 外壳,HTML 里没有路由模块,所以 Vite dev 仍是在断言阶段现编译这些模块图,超过单步等待就被判成"页面打不开"。
- **修复**:`scripts/check-game-distribution-web-e2e.mjs` 改成**浏览器级预热**——起浏览器后用一次性 context 真的访问 `/games`、`/games/detail?id=…`、`/games/play?id=…`(`domcontentloaded` + 2 秒 settle,120 秒上限,失败只告警),再做断言;首个 `goto` 的 120 秒超时保留。
- **复验**:重启 dev 栈(Vite 冷缓存)→ 修复版 **24/24 PASS**;同一冷启动条件下修复前版本会在上述两处各失败一次。判据已写入 pitfalls 同日条目。
@@ -6137,8 +6137,10 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/`
- **现象**:`npm run dev` 刚起(Vite 冷缓存)时跑 `check:game-distribution-web-e2e`,三轮 API 断言(管理员登录、作者注册、真实游戏发布上传→送审→审核)全过,但 `page.goto('http://127.0.0.1:3000/games', { waitUntil: 'domcontentloaded' })` 以 `Timeout 30000ms exceeded` 失败——看起来像"网页打不开"。
- **实测**:冷启动时 `Invoke-WebRequest /games` 花了 **20,171 ms**(`/` 约 2,146 ms),随后连续两次 4,208 ms / 10,119 ms,预热完成后 **14 ms**。原因是 Vite dev 按需编译该路由的模块图,首个请求最贵。
- **处理**:脚本在浏览器导航前先 `fetch` 预热本轮要用的 `/games`、`/games/detail?id=…`、`/games/play?id=…`(120s 上限,失败只告警),并把首个 `goto` 超时提到 120s;冷启动重跑 → **24/24 PASS**。另外三个 web 脚本原本就用 `waitUntil: 'commit', timeout: 120_000`,属同一类防护,别再去掉。
- **判据**:遇到"首个 goto 超时 + API 断言全过"的形态,先用 `curl`/`Invoke-WebRequest` 量一次同 URL 的耗时;20s 级冷启动说明是 Vite 编译,不是页面回归。
- **处理(2026-09-29 当天补正:`fetch` 预热不够)**:第一版只在导航前 `fetch` 预热 `/games`、`/games/detail?id=…`、`/games/play?id=…` 并把首个 `goto` 超时提到 120s。但 `fetch` 只拿到 SPA 外壳(HTML 里没有路由模块),**并没有真的让 Vite 编译那些模块**,所以冷启动下断言阶段照样假失败:实测第一次卡在 `button.game-card:visible` 的 20 秒等待,第二次(目录已热)又推进到游玩页 `getByRole('button', { name: '开始游戏' })` 的 15 秒等待——每次都停在「该路由第一次被**浏览器**加载」的那一步。
现在改为**浏览器级预热**:起浏览器后用一次性 context 真的把三条路由走一遍(`page.goto(url, { waitUntil: 'domcontentloaded', timeout: 120_000 })` + 2 秒 settle,失败只告警),让 Vite 先把模块编译落缓存,再建断言用的 context;首个 `goto` 的 120s 超时保留。另外三个 web 脚本原本就用 `waitUntil: 'commit', timeout: 120_000` + 60s 等待,属同一类防护,别再去掉。
- **复验**:重启 `npm run dev`(Vite 冷缓存)后跑修复版 → **24/24 PASS**;同一次冷启动下修复前的脚本会在上面两处各失败一次;四条 web E2E(`web` / `publish` / `publish-recovery` / `a11y`)本次全部复跑通过。
- **判据**:遇到"某一步等元素超时 + 前面的 API 断言全过",且这一步正好是该路由第一次在浏览器里加载,先怀疑 Vite 按需编译。`curl`/`Invoke-WebRequest` 量到的 20s 级冷启动只能解释导航慢;**纯 HTTP 预热不算预热**,要预热就得用浏览器真的走一遍。
## 2026-09-29 客户端"本地导出上限"不等于"平台发布上限"