diff options
Diffstat (limited to 'image/test/mochitest/test_animated_css_image.html')
-rw-r--r-- | image/test/mochitest/test_animated_css_image.html | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/image/test/mochitest/test_animated_css_image.html b/image/test/mochitest/test_animated_css_image.html new file mode 100644 index 0000000000..ca4a47915f --- /dev/null +++ b/image/test/mochitest/test_animated_css_image.html @@ -0,0 +1,223 @@ +<!doctype html> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script src="/tests/SimpleTest/WindowSnapshot.js"></script> +<!-- + scrolling=no is just paranoia to ensure that we don't get invalidations + due to scrollbars +--> +<iframe scrolling="no" id="iframe"></iframe> +<script> +SimpleTest.waitForExplicitFinish(); + +// We hit an optimized path in WebRender that doesn't cause a repaint on the +// main thread: +// +// https://searchfox.org/mozilla-central/rev/b7f3977978922d44c7d92ae01c0d4cc2baca7bc2/layout/style/ImageLoader.cpp#553 +// +// So our assertions and polling need to be a bit weaker on WR. +const kUsingWebRender = SpecialPowers.DOMWindowUtils.layerManagerType.startsWith("WebRender"); + +let iframe = document.getElementById("iframe"); +let blankSnapshot; + +async function assertAnimates(html, getExpectedRepaintedElement) { + const kExpectEqual = true; + const kNumRetries = kUsingWebRender ? 600 : 30; + + info("testing: " + html); + + { + let load = new Promise(resolve => { + iframe.addEventListener("load", resolve, { once: true }); + }); + iframe.srcdoc = html; + await load; + } + + // This ensures the MozAfterPaint events come through as expected. + await SimpleTest.promiseFocus(iframe.contentWindow); + + let initial = await snapshotWindow(iframe.contentWindow); + + let repaintedElement = getExpectedRepaintedElement(iframe.contentDocument); + if (!kUsingWebRender) { + // Ensure the painted state is clear before we start polling. + SpecialPowers.DOMWindowUtils.checkAndClearPaintedState(repaintedElement); + } + + { + let [equal, s1 /* , s2, differentPixels, maxDiff */] = compareSnapshots(initial, blankSnapshot, kExpectEqual); + ok(!equal, "Initial snapshot shouldn't be blank"); + info(s1); + } + + let foundDifferent = false; + let foundInitialAgain = false; + for (let i = 0; i < kNumRetries; ++i) { + let current = await snapshotWindow(iframe.contentWindow); + let [equal, /* s1 */, s2 /* , differentPixels, maxDiff */ ] = compareSnapshots(initial, current, kExpectEqual); + if (!foundDifferent && !equal) { + ok(true, `Found different image after ${i} retries`); + ok(kUsingWebRender || SpecialPowers.DOMWindowUtils.checkAndClearPaintedState(repaintedElement), "Should've repainted the expected element"); + info(s2); + foundDifferent = true; + } + + // Ensure that we go back to the initial state (animated1.gif) is an + // infinite gif. + if (foundDifferent && equal) { + ok(true, `Found same image again after ${i} retries`); + ok(kUsingWebRender || SpecialPowers.DOMWindowUtils.checkAndClearPaintedState(repaintedElement), "Should've repainted the expected element"); + foundInitialAgain = true; + break; + } + + await new Promise(resolve => { + if (kUsingWebRender) { + requestAnimationFrame(() => { + requestAnimationFrame(resolve); + }); + } else { + iframe.contentWindow.addEventListener("MozAfterPaint", resolve, { once: true }); + } + }); + } + + ok(foundDifferent && foundInitialAgain, `Should've found a different snapshot and then an equal one, after ${kNumRetries} retries`); +} + +const kTests = [ + // Sanity test: background-image on a regular element. + { + html: ` + <!doctype html> + <style> + div { + width: 100px; + height: 100px; + background-image: url(animated1.gif); + } + </style> + <div></div> + `, + element(doc) { + return doc.querySelector("div"); + }, + }, + + // bug 1627585: content: url() + { + html: ` + <!doctype html> + <style> + div::before { + content: url(animated1.gif); + } + </style> + <div></div> + `, + element(doc) { + return doc.querySelector("div"); + }, + }, + + // bug 1627585: content: url() (on an element directly) + { + html: ` + <!doctype html> + <style> + div { + content: url(animated1.gif); + } + </style> + <div></div> + `, + element(doc) { + return doc.querySelector("div"); + }, + }, + + // bug 1625571: background propagated to canvas. + { + html: ` + <!doctype html> + <style> + body { + background-image: url(animated1.gif); + } + </style> + `, + element(doc) { + return doc.documentElement; + }, + }, + + // bug 1719375: CSS animation in SVG image. + { + html: ` + <!doctype html> + <style> + div { + width: 100px; + height: 100px; + background-image: url(animated1.svg); + } + </style> + <div></div> + `, + element(doc) { + return doc.querySelector("div"); + }, + }, + + // bug 1730834: stopped window. + { + html: ` + <!doctype html> + <style> + div { + width: 100px; + height: 100px; + } + </style> + <body onload="window.stop(); document.querySelector('div').style.backgroundImage = 'url(animated1.gif)';"> + <div></div> + </body> + `, + element(doc) { + return doc.querySelector("div"); + }, + }, + + // bug 1731138: Animated mask + { + html: ` + <!doctype html> + <style> + div { + width: 100px; + height: 100px; + background-color: lime; + mask-clip: border-box; + mask-size: 100% 100%; + mask-image: url(animatedMask.gif); + } + </style> + <div></div> + `, + element(doc) { + return doc.querySelector("div"); + }, + }, +]; + +onload = async function() { + // First snapshot the blank window. + blankSnapshot = await snapshotWindow(iframe.contentWindow); + + for (let { html, element } of kTests) + await assertAnimates(html, element); + + SimpleTest.finish(); +} +</script> |