字彈 Zidan · 驗證測試報告

日期 2026-09-07 | commit e8c23b6 | P1 離線 PWA + P2 雲端同步 + P3 1v1 對戰
驗證範圍:單元/引擎冒煙、雙端 TypeScript、生產 build、全 API route 實機煙測、12 頁面 UI 實機截圖

總覽

45 / 45
引擎冒煙(含 6 分數回歸)
0 / 0
client + server tsc 錯誤
83
build 模組 / 233ms
18 / 18
全 API route 煙測通過
66 字
內建題庫結構/簡體/重複
88 音節
可打(含輕聲/多音字)

1. 自動化測試

項目結果
npm test — 引擎冒煙(輸入/退格/輕聲 ˙ 與 ˉ 雙軌/canon 比對/score 唯一寫入者)45 通過 / 0 失敗
內建題庫 validate-wordbook(66 字結構、無簡體、無重複)全過
88 音節可打驗證(含 ˙ 輕聲)88/88

2. 型別 & 建置

項目結果
client tsc --noEmit(React + Vite + TS)0 錯
server tsc --noEmit(Fastify + TS,拆分後 13 檔案)0 錯
npm run build(vite prod,PWA 含 workbox)83 modules,233ms,產出 dist/

3. 全 API route 實機煙測

server/smoke-split.py — 對真實 server(內嵌 PostgreSQL + JWT)打全部端點, 確認 e8c23b6 拆分(1,131 行 → 182 行 composition root + 6 plugins)後 端點 shape 零改動、行為等價
Plugin端點斷言結果
authPOST /api/debug/login200 + token 簽發PASS
GET /api/auth/me(JWT / 無 token)200 回 name / 401PASS
GET /api/health · GET /api/site-features200 pg 連線 / 開關清單PASS
sync(SRS)GET /api/srs/due200 到期清單PASS
GET /api/sync/learning200 學習紀錄PASS
POST /api/srs/reviews(raw array)200 批量複習PASS
POST /api/sync/ratings(raw array)200 學習寫入PASS
adminGET /api/admin/stats(player token)403 拒絕非 adminPASS
wordsGET /api/words/1200 單字(數字 id)PASS
GET /api/words/不存在的id400(zod coerce 失敗,與原始一致)PASS
POST /api/words/upload(token)201 + created=1PASS
POST /api/words/upload(無 token)401PASS
oauthGET /api/auth/oauth/unknown400 unknown_providerPASS
GET /api/auth/oauth/google(未設 env)503 provider_disabledPASS
dailyPOST /api/daily/submit(未登入)401PASS
GET /api/daily/board200 榜單PASS
組裝根GET /some/route200 SPA fallback(index.html)PASS
GET /api/nope404 JSONPASS
另驗 socket.io(P3):polling handshake 回 sid → WebSocket 路徑在拆分後正常。

4. UI 實機截圖(12 畫面)

Playwright + Chromium 跑真實 build(VITE_ZIDAN_DEBUG=1 版),admin 真實 token (經 /api/debug/login),後台/榜單/統計皆為真實資料(235 用戶 / 10,751 有效字 / 6 待審上傳 / 全球榜 13 人 / 本機 5 次練習)。無 page error。

5. 本次 commit 鏈(2026-09-07)

hash訊息
e8c23b6refactor(server): server.ts 1131 行上帝模組拆成 Fastify plugins
32ba83cdocs: README 對齊實作(4 模式/整句/45 測試/公開上傳)+ OAuth 簽名限制標註
88f6f80refactor(client): 清死碼/去 as any/設定單一所有權 + 接上公開題庫上傳
bde41a2refactor(server): 清死碼 + CORS 白名單統一 + 繁中註解 + admin 安全閥
85fae0efix(battle): 對戰結算分數歸零 — 引擎累計 g.score 為唯一事實來源

6. 結論