Day 20 結尾我留了一句:
Day 21 如果還要加 browser test,我會先把今天的 browser harness 抽乾淨,再補 case。
今天就是在兌現這句。
Day 20 終於補了 browser test。
不是很大的 end-to-end,只是針對 Day 19 的 draft import confirmation,也就是「選了檔案,要先確認才會取代目前 draft」這條規則,補了三條使用者真的看得到的路徑:
這三條測試會真的打開 index.html、載入 src/main.js、用 headless Chrome 跑,也會處理 native window.confirm()。
我其實很想直接補下一條。
例如從 Idea Entry 一路走到 Prompt Preview。
但先停一下。
Day 20 留下來的問題不是 coverage 還不夠,而是 browser test harness 已經開始長出重量了。
這裡的 harness,指的是讓 browser test 能跑起來的那包工具:local server、Chrome 啟動、Chrome DevTools Protocol(CDP)連線、page helper、file input helper。
Day 20 的 test/browserFlow.test.js 有 522 行。裡面大約 240 行是這些工具,三個情境本身大約 90 行。
下一條測試如果繼續放同一個檔案,它會繼續長。
如果新開一個 browser test 檔案,就不能直接去 import browserFlow.test.js 裡的 helper。
因為測試檔 import 測試檔,會連對方的測試也一起載入。
最後只能把那約 240 行複製一份。
所以 Day 21 的主論點很簡單:
先降低下一次補 browser test 的摩擦。
今天不重寫測試策略、不導入 Playwright,也不改產品行為。
只是把 Day 20 那包「為了讓 browser test 跑起來」的工具,從情境測試裡抽出來。
Day 20 的 test/browserFlow.test.js 裡有兩種東西。
第一種是產品情境。
例如:
browser import rejects invalid draft without confirmation and preserves current output
這種內容在講 ClarifyBuild 的產品規則:
這些要留在測試檔裡。
第二種是測試工具。
這類東西不是 ClarifyBuild 的產品規則。
它們只是為了讓 browser test 能跑。
所以 Day 21 新增了 test/helpers/browserHarness.js。
搬走的是:
goto()、click()、text()、value()、waitForText()
DOM.setFileInputFiles 選 JSON 檔留下的是:
抽完之後,browserFlow.test.js 讀起來比較接近使用者流程:
載入目前 draft
產生目前輸出
選擇 imported draft file
處理 confirm / cancel
檢查畫面
但還沒有完全乾淨。
confirm 的處理仍然是原始 CDP。三條測試都直接用 Page.javascriptDialogOpening 和 Page.handleJavaScriptDialog:第二、三條幾乎一樣,第一條是另一種寫法,用來確認壞檔根本沒跳確認。
形狀還沒收斂,所以我先不抽。
這個切法不是最終答案,只是先把最明顯的工具和情境拆開。
npm test 也需要收窄抽出 helper 後,出現一個小問題。
不帶參數的 node --test,會把名叫 test 的資料夾底下所有 .js 都當成測試檔。
所以新增 test/helpers/browserHarness.js 之後,npm test 會多跑一個 helper 檔。
它沒有測試,所以不會失敗。
但輸出會多一行:
✔ test/helpers/browserHarness.js
測試數也會從 27 變成 28。
這不是功能錯誤,但會讓人誤以為 helper 本身是一個測試案例。
所以 Day 21 把 script 從 node --test 改成:
node --test test/*.test.js
這樣 top-level 的 *.test.js 照跑,test/helpers/ 裡的 helper 照樣可以被 import,但不會被當成獨立測試檔。
代價是,之後新的測試檔如果放進子資料夾,例如 test/browser/import.test.js,npm test 不會跑它。
也就是說,接下來的測試檔要先放在 test/ 第一層,檔名以 .test.js 結尾。
這個限制目前可以接受。
如果之後真的需要整理測試資料夾結構,再一起調整 test script。
現在 browserFlow.test.js 裡還有一個 ClarifyBuild 專用的測試用假資料,也就是 completeMvpState()。
這個東西其實 test/appFlow.test.js 也有一份。
所以如果只看「有沒有重複」,重複已經出現了。
但我今天沒有把它抽成共用 fixture。
原因不是「完全沒有重複」。
真正原因是兩份形狀已經不一樣。
兩邊其實都要分「目前的 draft」和「匯入的 draft」。
appFlow.test.js 是叫完 completeMvpState() 再改 draft.idea。
browserFlow.test.js 則把 idea、featureName、flowLabel、behaviorTrigger 都做成參數,資料也是手寫的物件,沒有走 createFeature()、normalizeFlowRows() 這些正式程式裡的 helper。
而且這四個參數裡,目前真的被測試檢查的只有 idea 和 featureName。
所以它現在不是單純重複。
它是兩種還沒決定誰當標準的寫法。現在硬抽,只是把還沒想清楚的形狀固定下來。
這裡我比較想遵守的節奏是:
先等重複的形狀穩下來,再抽象。
Day 21 先抽 browser harness,不急著抽 ClarifyBuild fixture。
今天沒有改 src/main.js。
沒有改 src/ui/render.js。
沒有改 src/state/appFlow.js。
也沒有碰 Day 10 到 Day 13 定下來的產品邏輯。
三條測試驗的東西沒變。
改的是測試怎麼被組織。
這件事對產品沒有直接可見的差異。
但它會影響後面幾天寫測試的成本。
如果明天要補一條從 Idea Entry 到 Prompt Preview 的 browser happy path,現在不用重新處理 Chrome 啟動和 CDP connection。
多半可以把注意力放在流程本身,頂多再補一兩個像 fill() 或 select() 的小 helper。
Day 21 focused browser test:
node --test test/browserFlow.test.js
結果:
tests 3
pass 3
fail 0
完整測試:
npm test
結果:
tests 27
pass 27
fail 0
跟 Day 20 一樣,我跑測試的環境會限制本機網路權限。第一次跑時,本地 server 不能 bind 到 127.0.0.1;放寬權限後重跑,測試通過。
Playwright 本來就是做 browser test 的工具。
之後換,我不意外。
Day 20 我先不用,今天整理完又看了一次:browserHarness.js 有 282 行。
其中約 240 行是 server、Chrome 和 CDP 本體,其餘是 import、常數,以及 withBrowserApp()、chooseDraftFile()、writeDraftFile() 三個入口 helper。
未來如果換 Playwright,會被它取代的主要是 Chrome 啟動、CDP 連線和那些 wait helper。
但今天卡住的不是「這些該不該自己寫」。
而是它們不該跟情境混在同一個檔案。
就算之後要換,也得先有一條邊界。
另外有兩題,換不換 Playwright 都得回答。
第一,Chrome 裝在哪裡。
我現在把 Mac 上的路徑寫死:
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome
第二,CI 要怎麼拿到瀏覽器。
目前這個專案目錄裡還沒有 CI 設定,所以今天先不處理。
所以我先把「什麼時候換」寫下來。
如果出現下面幾種情況,就該重新評估 Playwright:
fill()、select()、keyboard helper到那時候再換,要動的主要會是 browserHarness.js,加上測試裡目前還沒抽掉的 confirm 處理。
這樣換工具比較像替換一層 harness,而不是到處拆測試。
現在測試分工變成這樣:
test/browserFlow.test.js
放 browser-level 使用者情境
test/helpers/browserHarness.js
放 browser test harness
這個分工只是讓下一次補 browser test 時,不用再面對同一包 Chrome / CDP / local server 工具。
Day 22 如果繼續往 browser test 走,我會補一條更完整的 happy path:進度列上的 Idea、Clarify、Scope、Specify、Spec、Prompt 六站都走過一次,中間實際流程可能還會經過 Optional Details。
不先整理的話,明天的文章很可能就會變成:
我複製了昨天那坨 CDP 工具,然後又多寫一條測試
那不是我想要的方向。
先等重複的形狀穩下來,再抽象;但當工具和情境已經混在一起時,就先拆開。
Day 21 完成。
明天見。