Bug 1037643 - img src/srcset mutation tests r=bz
authorJohn Schoenick <jschoenick@mozilla.com>
Tue, 30 Sep 2014 18:54:13 -0700
changeset 228524 f81dc8f11838719ce4353a4ead078a4481668fbe
parent 228523 7e0376b11638ab7b75669de970233c97b9a1bb59
child 228525 56cee6c6cd5c74862e95480ea0248310e76aaf6a
push id7326
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:58:42 +0000
treeherdermozilla-aurora@d3a3b2a0f2f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1037643
milestone36.0a1
Bug 1037643 - img src/srcset mutation tests r=bz
dom/tests/mochitest/general/image_100.png
dom/tests/mochitest/general/image_200.png
dom/tests/mochitest/general/image_50.png
dom/tests/mochitest/general/mochitest.ini
dom/tests/mochitest/general/test_img_mutations.html
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..df421453c25631353cfe86bde5973fdca15b1ea9
GIT binary patch
literal 91
zc%17D@N?(olHy`uVBq!ia0vp^DIm<q3?#jD*u{YqbAV5XtC5k>QX|f*K(4T-i(`m{
lWU>V7;slYNra*^q1_ss&2F5$COwvGU22WQ%mvv4FO#rqO5n=!U
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6f76d4438724111983a11860f13568361b52d9bc
GIT binary patch
literal 100
zc%17D@N?(olHy`uVBq!ia0vp^CqS5y8Awi_W^)%vF$egBxTd6}EPfSw1jv=~ba4!k
rkbHZv5y)XUyx@1R|3ikWAU1;^qeuV)<1IPC3=q%L)z4*}Q$iB}r??p{
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..144a2f0b93c5913872f30056999da000ae6049cd
GIT binary patch
literal 85
zc%17D@N?(olHy`uVBq!ia0vp^Mj*_{3?x-PN__%S%mF?ju9A|H-p`i&1*>y$43Usb
dmSAlLYGa(hz<BW6Dm$PAgQu&X%Q~loCIF<=5=;O9
--- a/dom/tests/mochitest/general/mochitest.ini
+++ b/dom/tests/mochitest/general/mochitest.ini
@@ -6,16 +6,19 @@ support-files =
   file_clonewrapper.html
   file_domWindowUtils_scrollbarSize.html
   file_frameElementWrapping.html
   file_interfaces.xml
   file_moving_nodeList.html
   file_moving_xhr.html
   file_showModalDialog.html
   historyframes.html
+  image_50.png
+  image_100.png
+  image_200.png
   resource_timing_iframe.html
   resource_timing_main_test.html
   resource_timing_cross_origin.html
   res0.resource
   res1.resource
   res1.resource^headers^
   res2.resource
   res2.resource^headers^
@@ -56,16 +59,17 @@ skip-if = buildapp == 'mulet'
 [test_focus_legend_noparent.html]
 [test_focusrings.xul]
 skip-if = e10s || buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
 [test_for_of.html]
 [test_frameElementWrapping.html]
 [test_framedhistoryframes.html]
 [test_idleapi_permissions.html]
 skip-if = e10s || buildapp == 'b2g' || buildapp == 'mulet'
+[test_img_mutations.html]
 [test_interfaces.html]
 skip-if = ((buildapp == 'mulet' || buildapp == 'b2g') && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 # [test_network_events.html]
 # Disable this test until bug 795711 is fixed.
 [test_offsets.html]
 [test_offsets.js]
 [test_outerHTML.html]
 [test_outerHTML.xhtml]
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/test_img_mutations.html
@@ -0,0 +1,227 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Image srcset mutations</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+  <script type="application/javascript">
+    "use strict";
+
+    // Tests the relevant mutations part of the spec for img src and srcset
+    // and that img.src still behaves by the older spec. (Bug 1076583)
+    // https://html.spec.whatwg.org/#relevant-mutations
+    SimpleTest.waitForExplicitFinish();
+
+    // 50x50 png
+    var testPNG50 = new URL("image_50.png", location).href;
+    // 100x100 png
+    var testPNG100 = new URL("image_100.png", location).href;
+    // 200x200 png
+    var testPNG200 = new URL("image_200.png", location).href;
+
+    var tests = [];
+    var img;
+    var expectingErrors = 0;
+    var expectingLoads = 0;
+    var afterExpectCallback;
+
+    function onImgLoad() {
+      ok(expectingLoads > 0, "expected load");
+      if (expectingLoads > 0) {
+        expectingLoads--;
+      }
+      if (!expectingLoads && !expectingErrors) {
+        setTimeout(afterExpectCallback, 0);
+      }
+    }
+    function onImgError() {
+      ok(expectingErrors > 0, "expected error");
+      if (expectingErrors > 0) {
+        expectingErrors--;
+      }
+      if (!expectingLoads && !expectingErrors) {
+        setTimeout(afterExpectCallback, 0);
+      }
+    }
+    function expectEvents(loads, errors, callback) {
+      if (!loads && !errors) {
+        setTimeout(callback, 0);
+      } else {
+        expectingLoads += loads;
+        expectingErrors += errors;
+        info("Waiting for " + expectingLoads + " load and " + expectingErrors + " error events");
+        afterExpectCallback = callback;
+      }
+    }
+
+    //
+    // Test that img.src still does some work synchronously per the older spec (bug 1076583)
+    //
+    tests.push(function test1() {
+      info("test 1");
+      img.src = testPNG50;
+      is(img.currentSrc, testPNG50, "Should have synchronously selected source");
+
+      img.src = "non_existent_image.404";
+      ok(img.currentSrc.endsWith("non_existent_image.404"), "Should have synchronously selected source");
+
+      img.removeAttribute("src");
+      is(img.currentSrc, null, "Should have dropped currentSrc");
+
+      // Load another image while previous load is still pending
+      img.src = testPNG200;
+      is(img.currentSrc, testPNG200, "Should have synchronously selected source");
+
+      // No events should have fired synchronously, now we should get just one load (and no 404 error)
+      expectEvents(1, 0, nextTest);
+    });
+
+
+    // Setting srcset should be async
+    tests.push(function () {
+      info("test 2");
+      img.srcset = testPNG100;
+      is(img.currentSrc, testPNG200, "Should still have testPNG200 as current request");
+
+      expectEvents(1, 0, function() {
+        is(img.currentSrc, testPNG100, "Should now have testPNG100 as current request");
+        nextTest();
+      });
+    });
+
+    // Setting srcset, even to no ultimate effect, should trigger a reload
+    tests.push(function () {
+      info("test 3");
+      img.srcset = testPNG100 + " 1x, " + testPNG200 + " 2x";
+      is(img.currentSrc, testPNG100, "Should still have testPNG100 as current request");
+
+      expectEvents(1, 0, function() {
+        is(img.currentSrc, testPNG100, "Should still have testPNG100 as current request");
+        nextTest();
+      });
+    });
+
+    // Should switch to src as 1x source
+    tests.push(function () {
+      info("test 4");
+      img.srcset = testPNG50 + " 2x";
+      is(img.currentSrc, testPNG100, "Should still have testPNG100 as current request");
+
+      expectEvents(1, 0, function() {
+        is(img.currentSrc, testPNG200, "Should now have testPNG200 as current request");
+        nextTest();
+      });
+    });
+
+    // Changing src while we have responsive attributes should not be sync
+    tests.push(function () {
+      info("test 5");
+      img.src = testPNG100;
+      is(img.currentSrc, testPNG200, "Should still have testPNG200 as current request");
+
+      expectEvents(1, 0, function() {
+        is(img.currentSrc, testPNG100, "Should now have testPNG100 as current request");
+
+        // Switch to using srcset again for next test
+        img.srcset = testPNG100;
+        expectEvents(1, 0, nextTest);
+      });
+    });
+
+    // img.src = img.src should trigger an async event even in responsive mode
+    tests.push(function () {
+      info("test 6");
+      is(img.currentSrc, testPNG100, "Should now have testPNG100 as current request");
+      img.src = img.src;
+      is(img.currentSrc, testPNG100, "Should still have testPNG100 as current request");
+
+      expectEvents(1, 0, nextTest);
+    });
+
+    // img.srcset = img.srcset should be a no-op
+    tests.push(function () {
+      info("test 7");
+      img.srcset = img.srcset;
+      is(img.currentSrc, testPNG100, "Should still have testPNG100 as current request");
+
+      expectEvents(0, 0, nextTest);
+    });
+
+    // Re-binding image to document should be a no-op
+    tests.push(function () {
+      info("test 8");
+      document.body.appendChild(img);
+      is(img.currentSrc, testPNG100, "Should still have testPNG100 as current request");
+
+      expectEvents(0, 0, nextTest);
+    });
+
+    // We should re-run our selection algorithm when any load event occurs
+    tests.push(function () {
+      info("test 9");
+      img.srcset = testPNG50 + " 1x, " + testPNG200 + " 2x";
+      is(img.currentSrc, testPNG100, "Should still have testPNG100 as current request");
+
+      expectEvents(1, 0, function() {
+        is(img.currentSrc, testPNG50, "Should now have testPNG50 as current request");
+        SpecialPowers.pushPrefEnv({'set': [ ["layout.css.devPixelsPerPx", "2.0"] ] },
+                                  function() {
+          // We don't currently dynamically switch, but doing so is
+          // up to the UA so we may in the future. In which case
+          // this test needs to be changed.
+          is(img.currentSrc, testPNG50, "Should now have testPNG50 as current request");
+          img.src = img.src;
+          is(img.currentSrc, testPNG50, "Should still have testPNG50 as current request");
+          expectEvents(1, 0, function() {
+            is(img.currentSrc, testPNG200, "Should now have testPNG200 as current request");
+            nextTest();
+          });
+        });
+      });
+    });
+
+    // Removing srcset attr should async switch back to src
+    tests.push(function () {
+      info("test 10");
+      is(img.currentSrc, testPNG200, "Should have testPNG200 as current request");
+
+      img.removeAttribute("srcset");
+      is(img.currentSrc, testPNG200, "Should still have testPNG200 as current request");
+
+      expectEvents(1, 0, function() {
+        is(img.currentSrc, testPNG100, "Should now have testPNG100 as current request");
+
+        expectEvents(0, 0, nextTest);
+      });
+    });
+
+    function nextTest() {
+      if (tests.length) {
+        // Spin event loop to make sure no unexpected image events are
+        // pending (unexpected events will assert in the handlers)
+        setTimeout(function() {
+          (tests.shift())();
+        }, 0);
+      } else {
+        SimpleTest.finish();
+      }
+    }
+
+    addEventListener("load", function() {
+      SpecialPowers.pushPrefEnv({'set': [ ["layout.css.devPixelsPerPx", "1.0"],
+                                          [ "dom.image.srcset.enabled", true ]] },
+                                function() {
+        // Create this after the pref is set, as it is guarding webIDL attributes
+        img = document.createElement("img");
+        img.addEventListener("load", onImgLoad);
+        img.addEventListener("error", onImgError);
+        document.body.appendChild(img);
+        setTimeout(nextTest, 0);
+      });
+    });
+  </script>
+</body>
+</html>