From 69bb6d9f42eb966cdcb79c34b7f9347817036377 Mon Sep 17 00:00:00 2001 From: Steven Enamakel <31011319+senamakel@users.noreply.github.com> Date: Sun, 5 Jul 2026 00:04:03 -0700 Subject: [PATCH] test(e2e): latch fast chat canaries (#4548) --- app/test/e2e/specs/chat-tool-call-flow.spec.ts | 4 +++- app/test/e2e/specs/user-journey-full-task.spec.ts | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/test/e2e/specs/chat-tool-call-flow.spec.ts b/app/test/e2e/specs/chat-tool-call-flow.spec.ts index 60005af08..288722442 100644 --- a/app/test/e2e/specs/chat-tool-call-flow.spec.ts +++ b/app/test/e2e/specs/chat-tool-call-flow.spec.ts @@ -136,6 +136,7 @@ describe('Chat tool-call lifecycle', () => { // Poll for a tool timeline entry while the LLM processes the tool_calls turn. let sawToolTimeline = false; + let sawFinalAnswer = false; const deadline = Date.now() + 45_000; while (Date.now() < deadline) { const snap = await snapshotRuntime(threadId); @@ -149,6 +150,7 @@ describe('Chat tool-call lifecycle', () => { // Also check if the final answer arrived (tool timeline may have already cleared // if the whole turn was faster than our polling interval). if (await textExists(CANARY_FINAL)) { + sawFinalAnswer = true; console.log(`${LOG_PREFIX} T1.1: final answer arrived before first timeline poll`); break; } @@ -157,7 +159,7 @@ describe('Chat tool-call lifecycle', () => { // The timeline entry is the primary signal, but if the full turn completed // before our first poll we still accept the final-answer path. - const finalArrived = await textExists(CANARY_FINAL); + const finalArrived = sawFinalAnswer || (await textExists(CANARY_FINAL)); expect(sawToolTimeline || finalArrived).toBe(true); console.log( `${LOG_PREFIX} T1.1: passed (sawTimeline=${sawToolTimeline}, finalArrived=${finalArrived})` diff --git a/app/test/e2e/specs/user-journey-full-task.spec.ts b/app/test/e2e/specs/user-journey-full-task.spec.ts index a5c5535c1..160b4e9b9 100644 --- a/app/test/e2e/specs/user-journey-full-task.spec.ts +++ b/app/test/e2e/specs/user-journey-full-task.spec.ts @@ -120,6 +120,7 @@ describe('User journey — full research task', () => { this.timeout(60_000); console.log(`${LOG_PREFIX} J1.2: watching for tool timeline entry`); let sawToolTimeline = false; + let sawFinalAnswer = false; const deadline = Date.now() + 45_000; while (Date.now() < deadline) { const snap = (await browser.execute((tid: string) => { @@ -137,15 +138,18 @@ describe('User journey — full research task', () => { break; } if (await textExists(CANARY_FINAL)) { + sawFinalAnswer = true; console.log(`${LOG_PREFIX} J1.2: canary arrived (turn may have completed before poll)`); break; } await browser.pause(200); } - const canaryVisible = await textExists(CANARY_FINAL); + const canaryVisible = sawFinalAnswer || (await textExists(CANARY_FINAL)); expect(sawToolTimeline || canaryVisible).toBe(true); - console.log(`${LOG_PREFIX} J1.2: passed`); + console.log( + `${LOG_PREFIX} J1.2: passed (sawTimeline=${sawToolTimeline}, canaryVisible=${canaryVisible})` + ); }); it('J1.3 — final answer with canary text renders', async function () {