From a898303ccf670bfcd2bab7aede42bfe59b9f77fd Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 29 Aug 2026 00:39:27 +0000 Subject: [PATCH] Wait for the demo's panels, not for the names above them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit main went red on the merge of #28: the demo step reported "demo is missing 'Overall alignment'" while the page dump printed directly beneath it contained "Overall alignment · 63% · from 22 shared answers". The assertion was right about what it wanted and wrong about when to look. The step waited for the creature names, which render as soon as the model resolves, and then snapshotted document.body. Every compare panel is a lazily loaded component that arrives after that, so the snapshot caught a page still filling in. It has been a race since the demo step was written and only lost it on a slower runner — three CI runs and every local run happened to win. It now waits for the panels it actually asserts on before reading the body. Same lesson as the networkidle fix a commit ago: wait for the thing you are asserting, not for a proxy that usually arrives first. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01UaDanzXTm6kVSgbNh1eNrs --- e2e/run-e2e.mjs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/e2e/run-e2e.mjs b/e2e/run-e2e.mjs index 4e8832c..c31e2e4 100644 --- a/e2e/run-e2e.mjs +++ b/e2e/run-e2e.mjs @@ -264,11 +264,14 @@ try { // newcomer is shown before they commit to anything, and it never fetches. step = 'demo-unconfigured'; await page.click('text=See a comparison first'); - await page.waitForSelector('text=brave-azure-otter', { timeout: 30000 }); - const demoBody = await page.textContent('body'); - for (const expected of ['Overall alignment', 'Mutual desires', 'Fit, each way']) { - if (!demoBody.includes(expected)) fail(`demo is missing "${expected}" with no server`); + // Wait for the panels, not for the creature names. The names render as soon + // as the model resolves, but every panel is a lazily loaded component that + // arrives afterwards — snapshotting the body in between reads a page that is + // still filling in, which is a race that only shows up on a slow runner. + for (const expected of ['Overall alignment', 'Mutual desires', 'Fit, each way', 'In words']) { + await page.waitForSelector(`text=${expected}`, { timeout: 30000 }); } + const demoBody = await page.textContent('body'); // The dealbreaker alert and the mutual reveal are the two moments the demo // exists to show; a demo that quietly lost them would still look fine. if (!demoBody.includes('Alcohol')) fail('demo does not name the violated dealbreaker');