ci: fix the frontend coverage timeout and the WebKit Load more race (#262)

* ci: give the frontend coverage job a 40-minute limit with measured headroom

The job runs every page workflow twice (chromium, then touch) on one
worker with V8 coverage, so it takes about twice a single-browser job.
Recent runs took 18m26s-24m57s and PR head 6359999 was cancelled at the
25-minute limit while still passing. Coverage, floors and commands are
unchanged.

* test(images): dispatch the production Load more press so the observer cannot pre-empt it

A pointer click scrolls the continuation row into view, which lets the
page's own infinite-scroll observer append the final batch and hide the
button before the click lands (WebKit, run 39512528039). Dispatch the
press as the concept side already does, after asserting the button is
visible and enabled; the count, card, toast and loading-row assertions
are unchanged.
This commit is contained in:
Vito
2026-10-20 19:47:37 -07:00
committed by GitHub
parent 5ded3cfd39
commit 728db36ac3
2 changed files with 12 additions and 2 deletions
+6 -1
View File
@@ -26,7 +26,12 @@ jobs:
container:
image: mcr.microsoft.com/playwright:v1.64.1-noble
options: --user 1001
timeout-minutes: 25
# This job runs every page workflow twice (chromium, then touch) on one worker with V8 coverage on, so it
# takes about twice a single-browser job. Measured 2026-10-20: whole job 18m26s-24m57s (main 5ded3cf
# 22m15s; PR head 6359999 was cancelled at the old 25-minute limit while still passing), coverage step
# alone 20m55s-22m17s+, against ~12-15 minutes for the firefox/webkit jobs. 40 minutes leaves headroom
# for suite growth while still stopping a hung run; re-measure if a run passes 30 minutes.
timeout-minutes: 40
steps:
- uses: actions/checkout@v7
# The image's own Python 3.12 and Node 24: setup-python/setup-node install the runner's toolcache
+6 -1
View File
@@ -410,7 +410,12 @@ for(const [width,height] of SIZES)for(const theme of THEMES)test(`images page ge
await openProductionLoaded(page,theme,motion,total);
const before=await page.locator(CARDS).count();
const loadingRow=(await inventoryOf(page,'#workspace-main')).continuation,loadingCount=await countText(page);
await page.getByRole('button',{name:'Load more images',exact:true}).click();
// A dispatched press, as on the concept side: a pointer click scrolls the row into view first, and the page's
// own observer (rootMargin 250px) can append the final batch and hide the button before the click lands
// (WebKit, run 39512528039). The button must still be the enabled one the user would press.
const more=page.getByRole('button',{name:'Load more images',exact:true});
await expect(more).toBeVisible();await expect(more).toHaveAttribute('aria-disabled','false');
await more.dispatchEvent('click');
await expect(page.locator('#result-count')).toHaveText(new RegExp(`^${total} of ${total} images`));
result[motion].productionLoad={before,after:await page.locator(CARDS).count(),toast:await toastText(page),count:await countText(page)};
result[motion].loadingDiff=compareLoadingRow(result[motion].conceptLoad.loadingRow,loadingRow,loadingCount);