(page: Page)
| 93 | * 2. the parsed message count has grown beyond the pre-click baseline. |
| 94 | */ |
| 95 | export async function runTest(page: Page): Promise<void> { |
| 96 | const readMessageCount = () => |
| 97 | page.evaluate(() => { |
| 98 | const text = |
| 99 | document.getElementById('messages-json-content')?.textContent || '[]' |
| 100 | try { |
| 101 | const parsed = JSON.parse(text) |
| 102 | return Array.isArray(parsed) ? parsed.length : 0 |
| 103 | } catch { |
| 104 | return 0 |
| 105 | } |
| 106 | }) |
| 107 | |
| 108 | for (let attempt = 0; attempt < 5; attempt++) { |
| 109 | const baselineMessageCount = await readMessageCount() |
| 110 | await page.click('#run-test-button') |
| 111 | |
| 112 | // A run "starts" only when real stream activity appears — not when the |
| 113 | // optimistic user message lands. Clicking adds one user message |
| 114 | // synchronously (baseline + 1); that alone must NOT count as started, or a |
| 115 | // stalled run (the click registered but the stream produced nothing) would |
| 116 | // be reported as started and the test would later time out waiting for an |
| 117 | // approval / completion that never comes. Real activity is: loading turned |
| 118 | // on, a tool call appeared, the test completed, or a *second* message (the |
| 119 | // assistant response) was added beyond the optimistic user message. Poll |
| 120 | // briefly so a slow-but-real run under CI load isn't mistaken for a stall. |
| 121 | const started = await page |
| 122 | .waitForFunction( |
| 123 | (baseline) => { |
| 124 | const metadata = document.getElementById('test-metadata') |
| 125 | if (metadata?.getAttribute('data-is-loading') === 'true') return true |
| 126 | if ( |
| 127 | parseInt( |
| 128 | metadata?.getAttribute('data-tool-call-count') || '0', |
| 129 | 10, |
| 130 | ) > 0 |
| 131 | ) |
| 132 | return true |
| 133 | if (metadata?.getAttribute('data-test-complete') === 'true') |
| 134 | return true |
| 135 | const text = |
| 136 | document.getElementById('messages-json-content')?.textContent || |
| 137 | '[]' |
| 138 | try { |
| 139 | const parsed = JSON.parse(text) |
| 140 | // > baseline + 1: the assistant message arrived (a real response), |
| 141 | // not just the optimistic user message. |
| 142 | return Array.isArray(parsed) && parsed.length > baseline + 1 |
| 143 | } catch { |
| 144 | return false |
| 145 | } |
| 146 | }, |
| 147 | baselineMessageCount, |
| 148 | { timeout: 2000 }, |
| 149 | ) |
| 150 | .then(() => true) |
| 151 | .catch(() => false) |
| 152 |
no test coverage detected