From 5273e5fb5533e58577b41e1b940934bb260bd724 Mon Sep 17 00:00:00 2001 From: 4gray <4gray@users.noreply.github.com> Date: Sat, 19 Sep 2026 09:23:12 +0200 Subject: [PATCH] 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 --- tools/testing/website-home-sections.test.mjs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/testing/website-home-sections.test.mjs b/tools/testing/website-home-sections.test.mjs index 85c95e5a4..002a80e7e 100644 --- a/tools/testing/website-home-sections.test.mjs +++ b/tools/testing/website-home-sections.test.mjs @@ -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 {