Playwright page
How many render ticks to drive; must be >= 1
Aggregate bound on this ONE call, defaulting to FLUSH_BUDGET_MS. Pass less where several flushes share one test budget: the bound is per call, so per-call bounds add up.
What the flush achieved; feed it to reportFlushVerdict.
Drive
ticksrender ticks, confirming each one against the renderer's own counter.WHAT A "TICK" IS: on WebGL
info.render.framecountsrenderer.render()calls, and Luxar's default pipeline issues two of them per animation frame (scene→HDR plus the fullscreen mega pass), more with bloom/FXAA on. So N ticks is roughly N/2 animation frames. (On WebGPU it is ~N animation frames and a weaker signal — see the module docblock.) The N values at the call sites are unchanged from thewaitForNextRender(page, N)calls they replace, which targeted the same counter — what is requested is the same; only the confirmation is new.WHY the caller confirms its own ticks instead of calling
waitForNextRender(page, N): that helper is documented as best-effort and its fallback is SILENT, so a detector that needs its draws to have happened cannot tell a confirmed flush from a fallback. A GL error that only appears on the Nth draw would then go unlogged and the detector would read stronger than it is.WHY this never throws for a short flush: a strict variant is reported in #1652 to turn the healthy case red — a tick can legitimately miss even a generous bound on a loaded box. One measured reason for a shortfall is that the OBSERVATION is starved rather than the rendering:
page.waitForFunctionpolls in-page and reports back over the same CDP channel a saturated rAF loop starves, so the counter can advance while no tick is ever confirmed (#1651). A shortfall is therefore reported (so a weak detector run is visible in the output) and the assertions that follow still operate on whatever landed; reportFlushVerdict decides what a ZERO-tick flush means, and it is called AFTER the detector's own reporting. This function throws only on a real contract break — aticksthat is not a positive integer (a caller bug: below 1 it would drive no iterations and then be reported as "none of the 0 requested ticks were confirmed" on a perfectly healthy page, and a fraction is not a tick count at all), the page ANSWERS but exposes no numeric frame counter so there is nothing to confirm against, or a non-timeout error out ofpage.waitForFunction, which is a crashed/closed page and must surface as itself. An UNANSWERED counter probe is the starvation case instead: it returns a report withstartFrame: null.Every wait here is bounded twice: individually by TICK_TIMEOUT_MS (
page.waitForFunctionhonours itstimeoutunlikepage.evaluate, whose evaluates go throughraceEvaluate), and in aggregate bybudgetMs.