diff --git a/automation/js-render/render.mjs b/automation/js-render/render.mjs index 2ad25ab4c5b..213aed41d53 100644 --- a/automation/js-render/render.mjs +++ b/automation/js-render/render.mjs @@ -362,14 +362,27 @@ async function main() { // fall back to fonts-ready + a double rAF, which is sufficient for the // animation:false static renders the library prompts mandate. This is the // page.waitForFunction(...) signal the design calls for — never a time.sleep. - try { - await page.waitForFunction(() => window.__anyplotReady === true, { timeout: 2500 }); - } catch { - // No explicit signal — settle deterministically instead. - await page.evaluate(async () => { + // The signal can only arrive from a snippet whose source names it or from + // the React entry (which sets it after fonts + three rAFs), so every other + // snippet settles directly instead of idling through the timeout. + // Playwright's signature is (pageFunction, arg, options): the options object + // must sit in the third slot, or it becomes the page function's argument + // and the wait runs to the 30 s default timeout. + const settle = () => + page.evaluate(async () => { await (document.fonts ? document.fonts.ready : Promise.resolve()); await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r))); }); + const expectsReadySignal = bundleInfo.framework === "react" || snippetSource.includes("__anyplotReady"); + if (expectsReadySignal) { + try { + await page.waitForFunction(() => window.__anyplotReady === true, null, { timeout: 2500 }); + } catch { + // The signal never came (a guarded `finished` handler, say) — settle instead. + await settle(); + } + } else { + await settle(); } // Surface snippet failures loudly — a blank/half-drawn PNG must fail the diff --git a/changelog.d/js-render-ready-timeout.md b/changelog.d/js-render-ready-timeout.md new file mode 100644 index 00000000000..cf156ac6ca1 --- /dev/null +++ b/changelog.d/js-render-ready-timeout.md @@ -0,0 +1,9 @@ +### Fixed + +- **JavaScript render harness waits 2.5 s, not 30 s, for the ready signal.** + `automation/js-render/render.mjs` passed the `{ timeout: 2500 }` options to + `page.waitForFunction` in the argument slot, so every snippet without + `window.__anyplotReady` sat through Playwright's 30 s default before the + fonts-ready fallback ran. The options now sit in the third slot, which + shortens every such render by about 27 s across all JavaScript libraries. + (#12248)