test(website): wait for the copy button label before reading the clipboard (#1624)

The home-sections browser test clicked `.copy-btn` and immediately asserted
`textContent() === 'Copied'`. The button flips its label only after the
asynchronous `navigator.clipboard.writeText` promise resolves, which is after
Playwright's `click()` has already returned, so a loaded CI runner sometimes
still read "Copy" (PR #1619, run 35369544094).

Poll for the label with Playwright's `expect(locator).toHaveText` (bounded
5 s) before reading the clipboard. The import is dynamic and sits after
`launchBrowser()`, so the local no-Chromium skip path is unchanged.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Fable 5.1 authored and GitHub committed 2026-09-19 09:23:12 +02:00
1 parent 6f987d79d8
commit 5273e5fb55
1 file changed
+9 -2
+9 -2
View File
@@ -143,14 +143,21 @@ test('browser: the download CTA and the Detected row follow the visitor OS, phon
await page.close();
}
// Copy buttons write the command and confirm briefly.
// Copy buttons write the command and confirm briefly. The label flips
// only after the asynchronous `navigator.clipboard.writeText` resolves,
// which is after `click()` has already returned, so the check has to wait
// for the change instead of reading the label synchronously (a loaded CI
// runner otherwise still sees "Copy"). `launchBrowser()` succeeding proves
// `@playwright/test` is importable, so this import cannot break the local
// no-Chromium skip above.
const { expect } = await import('@playwright/test');
const context = await browser.newContext({ permissions: ['clipboard-read', 'clipboard-write'] });
const page = await context.newPage();
await page.goto(`${origin}${BASE}/`, { waitUntil: 'networkidle' });
const button = page.locator('.copy-btn').first();
await button.scrollIntoViewIfNeeded();
await button.click();
assert.equal(await button.textContent(), 'Copied');
await expect(button).toHaveText('Copied', { timeout: 5000 });
assert.equal(await page.evaluate(() => navigator.clipboard.readText()), 'brew install --cask iptvnator');
await context.close();
} finally {