From 9695dd9ab10212428d8a2f3c7138cb950c0e407f Mon Sep 17 00:00:00 2001 From: ChengLong GU <88359731+gcl-coder@users.noreply.github.com> Date: Thu, 5 Nov 2026 22:35:14 +0800 Subject: [PATCH] fix(browser): wait for DOM content when reopening recovered history `openWorkspacePage` defaults to `waitUntil: "networkidle"`, so the required browser lane dies on Playwright's 30 second navigation timeout whenever the page keeps a request in flight. The conversation-history-recovery scenario does exactly that on purpose: it interrupts the second history page and asserts that a partial read cannot masquerade as complete history. Four call sites in that file still took the default while the fifth and five other scenarios already ask for `domcontentloaded`. The helper's own `personal-goal-home` visibility wait then decides readiness, so the navigation no longer has to wait for traffic the fixture holds open. Signed-off-by: ChengLong GU <88359731+gcl-coder@users.noreply.github.com> --- .../conversation-history-recovery.mjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/personal-workspace-browser/conversation-history-recovery.mjs b/examples/personal-workspace-browser/conversation-history-recovery.mjs index 67ad3bc8d4..1f7a77a3e2 100644 --- a/examples/personal-workspace-browser/conversation-history-recovery.mjs +++ b/examples/personal-workspace-browser/conversation-history-recovery.mjs @@ -12,6 +12,7 @@ async function pagedHistoryRecovery(browser, url) { role: index % 2 ? "agent" : "user", text: index === 201 ? "原始长文。".repeat(2400) : `原始历史第 ${index} 条。`, created_at: "2026-08-13T01:00:00Z"})); const context = await openWorkspacePage(browser, url, { + gotoWaitUntil: "domcontentloaded", async beforeGoto(_api, page) { const runtime = page.__loopxRuntime; runtime.sessions.clear(); @@ -131,6 +132,7 @@ async function retiredHistoryRead(browser, url) { const readWait = new Promise(resolve => { releaseRead = resolve; }); const readStarted = new Promise(resolve => { markReadStarted = resolve; }); const context = await openWorkspacePage(browser, url, { + gotoWaitUntil: "domcontentloaded", async beforeGoto(api, page) { const runtime = page.__loopxRuntime; runtime.sessions.set(sessionId, { @@ -198,6 +200,7 @@ async function recoveryObserverHandover(browser, url) { const newTurnWait = new Promise(resolve => { releaseNewTurn = resolve; }); const previewStarted = new Promise(resolve => { markPreviewStarted = resolve; }); const context = await openWorkspacePage(browser, url, { + gotoWaitUntil: "domcontentloaded", async beforeGoto(api, page) { const runtime = page.__loopxRuntime; runtime.sessions.set(sessionId, { @@ -277,6 +280,7 @@ export const conversationHistoryRecoveryScenario = { let unavailable = oldId; let failedReads = 0; const context = await openWorkspacePage(browser, url, { + gotoWaitUntil: "domcontentloaded", collectCoverage, beforeGoto(_api, page) { for (const [id, agentId, date, text] of [