function waitForAnimationFrames(count) { return new Promise(resolve => { if (count-- <= 0) { resolve(); } else { requestAnimationFrame(() => { waitForAnimationFrames(count).then(resolve); }); } }); } // Asserts that there is currently no FCP reported. Pass t to add some wait, in case CSS is loaded // and FCP is incorrectly fired afterwards. async function assertNoFirstContentfulPaint(t) { await waitForAnimationFrames(3); assert_equals(performance.getEntriesByName('first-contentful-paint').length, 0, 'First contentful paint marked too early. '); } // Function that is resolved once FCP is reported, using PerformanceObserver. It rejects after a long // wait time so that failing tests don't timeout. async function assertFirstContentfulPaint(t) { return new Promise(resolve => { function checkFCP() { if (performance.getEntriesByName('first-contentful-paint').length === 1) { resolve(); } else { t.step_timeout(checkFCP, 0); } } t.step(checkFCP); }); } async function test_fcp(label, before_assert_fcp_func) { setup({"hide_test_state": true}); const style = document.createElement('style'); document.head.appendChild(style); await promise_test(async t => { assert_implements(window.PerformancePaintTiming, "Paint Timing isn't supported."); const main = document.getElementById('main'); await new Promise(r => window.addEventListener('load', r)); await assertNoFirstContentfulPaint(t); main.className = 'preFCP'; await assertNoFirstContentfulPaint(t); if (before_assert_fcp_func) { await before_assert_fcp_func(); } main.className = 'contentful'; await assertFirstContentfulPaint(t); }, label); }