layout/style/test/test_media_query_list.html

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 <!DOCTYPE HTML>
michael@0 2 <html>
michael@0 3 <!--
michael@0 4 https://bugzilla.mozilla.org/show_bug.cgi?id=542058
michael@0 5 -->
michael@0 6 <head>
michael@0 7 <title>Test for MediaQueryList (Bug 542058)</title>
michael@0 8 <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
michael@0 9 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
michael@0 10 </head>
michael@0 11 <body onload="run()">
michael@0 12 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=542058">Mozilla Bug 542058</a>
michael@0 13 <iframe id="subdoc" src="about:blank"></iframe>
michael@0 14 <div id="content" style="display:none"></div>
michael@0 15 <pre id="test">
michael@0 16 <script type="application/javascript">
michael@0 17
michael@0 18 /** Test for MediaQueryList (Bug 542058) **/
michael@0 19
michael@0 20 SimpleTest.waitForExplicitFinish();
michael@0 21
michael@0 22 function run() {
michael@0 23 var iframe = document.getElementById("subdoc");
michael@0 24 var subdoc = iframe.contentDocument;
michael@0 25 var subwin = iframe.contentWindow;
michael@0 26 var subroot = subdoc.documentElement;
michael@0 27
michael@0 28 var content_div = document.getElementById("content");
michael@0 29 content_div.style.font = "initial";
michael@0 30 var em_size =
michael@0 31 getComputedStyle(content_div, "").fontSize.match(/^(\d+)px$/)[1];
michael@0 32
michael@0 33 var w = Math.floor(em_size * 9.3);
michael@0 34 var h = Math.floor(em_size * 4.2);
michael@0 35 iframe.style.width = w + "px";
michael@0 36 iframe.style.height = h + "px";
michael@0 37 subroot.offsetWidth; // flush layout
michael@0 38
michael@0 39 function setup_mql(str) {
michael@0 40 var obj = {
michael@0 41 str: str,
michael@0 42 mql: subwin.matchMedia(str),
michael@0 43 notifyCount: 0,
michael@0 44 listener: function(mql) {
michael@0 45 is(mql, obj.mql,
michael@0 46 "correct argument to listener: " + obj.str);
michael@0 47 ++obj.notifyCount;
michael@0 48 // Test the last match result only on odd
michael@0 49 // notifications.
michael@0 50 if (obj.notifyCount & 1) {
michael@0 51 obj.lastOddMatchResult = mql.matches;
michael@0 52 }
michael@0 53 }
michael@0 54 }
michael@0 55 obj.mql.addListener(obj.listener);
michael@0 56 return obj;
michael@0 57 }
michael@0 58
michael@0 59 function finish_mql(obj) {
michael@0 60 obj.mql.removeListener(obj.listener);
michael@0 61 }
michael@0 62
michael@0 63 var w_exact_w = setup_mql("(width: " + w + "px)");
michael@0 64 var w_min_9em = setup_mql("(min-width : 9em)");
michael@0 65 var w_min_10em = setup_mql("( min-width: 10em ) ");
michael@0 66 var w_max_9em = setup_mql("(max-width: 9em)");
michael@0 67 var w_max_10em = setup_mql("(max-width: 10em)");
michael@0 68
michael@0 69 is(w_exact_w.mql.media, "(width: " + w + "px)", "serialization");
michael@0 70 is(w_min_9em.mql.media, "(min-width: 9em)", "serialization");
michael@0 71 is(w_min_10em.mql.media, "(min-width: 10em)", "serialization");
michael@0 72 is(w_max_9em.mql.media, "(max-width: 9em)", "serialization");
michael@0 73 is(w_max_10em.mql.media, "(max-width: 10em)", "serialization");
michael@0 74
michael@0 75 function check_match(obj, expected, desc) {
michael@0 76 is(obj.mql.matches, expected,
michael@0 77 obj.str + " media query list .matches " + desc);
michael@0 78 if (obj.notifyCount & 1) { // odd notifications only
michael@0 79 is(obj.lastOddMatchResult, expected,
michael@0 80 obj.str + " media query list last notify result " + desc);
michael@0 81 }
michael@0 82 }
michael@0 83 function check_notify(obj, expected, desc) {
michael@0 84 is(obj.notifyCount, expected,
michael@0 85 obj.str + " media query list .notify count " + desc);
michael@0 86 }
michael@0 87 check_match(w_exact_w, true, "initially");
michael@0 88 check_notify(w_exact_w, 0, "initially");
michael@0 89 check_match(w_min_9em, true, "initially");
michael@0 90 check_notify(w_min_9em, 0, "initially");
michael@0 91 check_match(w_min_10em, false, "initially");
michael@0 92 check_notify(w_min_10em, 0, "initially");
michael@0 93 check_match(w_max_9em, false, "initially");
michael@0 94 check_notify(w_max_9em, 0, "initially");
michael@0 95 check_match(w_max_10em, true, "initially");
michael@0 96 check_notify(w_max_10em, 0, "initially");
michael@0 97
michael@0 98 var w2 = Math.floor(em_size * 10.3);
michael@0 99 iframe.style.width = w2 + "px";
michael@0 100 subroot.offsetWidth; // flush layout
michael@0 101
michael@0 102 check_match(w_exact_w, false, "after width increase to around 10.3em");
michael@0 103 check_notify(w_exact_w, 1, "after width increase to around 10.3em");
michael@0 104 check_match(w_min_9em, true, "after width increase to around 10.3em");
michael@0 105 check_notify(w_min_9em, 0, "after width increase to around 10.3em");
michael@0 106 check_match(w_min_10em, true, "after width increase to around 10.3em");
michael@0 107 check_notify(w_min_10em, 1, "after width increase to around 10.3em");
michael@0 108 check_match(w_max_9em, false, "after width increase to around 10.3em");
michael@0 109 check_notify(w_max_9em, 0, "after width increase to around 10.3em");
michael@0 110 check_match(w_max_10em, false, "after width increase to around 10.3em");
michael@0 111 check_notify(w_max_10em, 1, "after width increase to around 10.3em");
michael@0 112
michael@0 113 var w3 = w * 2;
michael@0 114 iframe.style.width = w3 + "px";
michael@0 115 subroot.offsetWidth; // flush layout
michael@0 116
michael@0 117 check_match(w_exact_w, false, "after width double from original");
michael@0 118 check_notify(w_exact_w, 1, "after width double from original");
michael@0 119 check_match(w_min_9em, true, "after width double from original");
michael@0 120 check_notify(w_min_9em, 0, "after width double from original");
michael@0 121 check_match(w_min_10em, true, "after width double from original");
michael@0 122 check_notify(w_min_10em, 1, "after width double from original");
michael@0 123 check_match(w_max_9em, false, "after width double from original");
michael@0 124 check_notify(w_max_9em, 0, "after width double from original");
michael@0 125 check_match(w_max_10em, false, "after width double from original");
michael@0 126 check_notify(w_max_10em, 1, "after width double from original");
michael@0 127
michael@0 128 SpecialPowers.setFullZoom(subwin, 2.0);
michael@0 129 subroot.offsetWidth; // flush layout
michael@0 130
michael@0 131 check_match(w_exact_w, true, "after zoom");
michael@0 132 check_notify(w_exact_w, 2, "after zoom");
michael@0 133 check_match(w_min_9em, true, "after zoom");
michael@0 134 check_notify(w_min_9em, 0, "after zoom");
michael@0 135 check_match(w_min_10em, false, "after zoom");
michael@0 136 check_notify(w_min_10em, 2, "after zoom");
michael@0 137 check_match(w_max_9em, false, "after zoom");
michael@0 138 check_notify(w_max_9em, 0, "after zoom");
michael@0 139 check_match(w_max_10em, true, "after zoom");
michael@0 140 check_notify(w_max_10em, 2, "after zoom");
michael@0 141
michael@0 142 SpecialPowers.setFullZoom(subwin, 1.0);
michael@0 143
michael@0 144 finish_mql(w_exact_w);
michael@0 145 finish_mql(w_min_9em);
michael@0 146 finish_mql(w_min_10em);
michael@0 147 finish_mql(w_max_9em);
michael@0 148 finish_mql(w_max_10em);
michael@0 149
michael@0 150 // Additional tests of listener mutation.
michael@0 151 (function() {
michael@0 152 var received = [];
michael@0 153 var received_mql = [];
michael@0 154 function listener1(mql) {
michael@0 155 received.push(1);
michael@0 156 received_mql.push(mql);
michael@0 157 }
michael@0 158 function listener2(mql) {
michael@0 159 received.push(2);
michael@0 160 received_mql.push(mql);
michael@0 161 }
michael@0 162
michael@0 163 iframe.style.width = "200px";
michael@0 164 subroot.offsetWidth; // flush layout
michael@0 165
michael@0 166 var mql = subwin.matchMedia("(min-width: 150px)");
michael@0 167 mql.addListener(listener1);
michael@0 168 mql.addListener(listener1);
michael@0 169 mql.addListener(listener2);
michael@0 170 is(JSON.stringify(received), "[]", "listeners before notification");
michael@0 171
michael@0 172 iframe.style.width = "100px";
michael@0 173 subroot.offsetWidth; // flush layout
michael@0 174
michael@0 175 is(JSON.stringify(received), "[1,2]", "duplicate listeners removed");
michael@0 176 received = [];
michael@0 177 mql.removeListener(listener1);
michael@0 178
michael@0 179 iframe.style.width = "200px";
michael@0 180 subroot.offsetWidth; // flush layout
michael@0 181
michael@0 182 is(JSON.stringify(received), "[2]", "listener removal");
michael@0 183 received = [];
michael@0 184 mql.addListener(listener1);
michael@0 185
michael@0 186 iframe.style.width = "100px";
michael@0 187 subroot.offsetWidth; // flush layout
michael@0 188
michael@0 189 is(JSON.stringify(received), "[2,1]", "listeners notified in order");
michael@0 190 received = [];
michael@0 191 mql.addListener(listener2);
michael@0 192
michael@0 193 iframe.style.width = "200px";
michael@0 194 subroot.offsetWidth; // flush layout
michael@0 195
michael@0 196 is(JSON.stringify(received), "[2,1]", "add of existing listener is no-op");
michael@0 197 received = [];
michael@0 198 mql.addListener(listener1);
michael@0 199
michael@0 200 iframe.style.width = "100px";
michael@0 201 subroot.offsetWidth; // flush layout
michael@0 202
michael@0 203 is(JSON.stringify(received), "[2,1]", "add of existing listener is no-op");
michael@0 204 mql.removeListener(listener2);
michael@0 205 received = [];
michael@0 206 received_mql = [];
michael@0 207
michael@0 208 var mql2 = subwin.matchMedia("(min-width: 160px)");
michael@0 209 mql2.addListener(listener1);
michael@0 210 mql.addListener(listener2);
michael@0 211
michael@0 212 iframe.style.width = "200px";
michael@0 213 subroot.offsetWidth; // flush layout
michael@0 214
michael@0 215 // mql (1, 2), mql2 (1)
michael@0 216 is(JSON.stringify(received), "[1,2,1]",
michael@0 217 "notification of lists in order created");
michael@0 218 is(received_mql[0], mql,
michael@0 219 "notification of lists in order created");
michael@0 220 is(received_mql[1], mql,
michael@0 221 "notification of lists in order created");
michael@0 222 is(received_mql[2], mql2,
michael@0 223 "notification of lists in order created");
michael@0 224 received = [];
michael@0 225 received_mql = [];
michael@0 226
michael@0 227 function removing_listener(mql) {
michael@0 228 received.push(3);
michael@0 229 received_mql.push(mql);
michael@0 230 mql.removeListener(listener2);
michael@0 231 mql2.removeListener(listener1);
michael@0 232 }
michael@0 233
michael@0 234 mql.addListener(removing_listener);
michael@0 235 mql.removeListener(listener2);
michael@0 236 mql.addListener(listener2); // after removing_listener (3)
michael@0 237
michael@0 238 iframe.style.width = "100px";
michael@0 239 subroot.offsetWidth; // flush layout
michael@0 240
michael@0 241 // mql(1, 3, 2) mql2(1)
michael@0 242 is(JSON.stringify(received), "[1,3,2,1]",
michael@0 243 "listeners still notified after removed if change was before");
michael@0 244 is(received_mql[0], mql,
michael@0 245 "notification order (removal tests)");
michael@0 246 is(received_mql[1], mql,
michael@0 247 "notification order (removal tests)");
michael@0 248 is(received_mql[2], mql,
michael@0 249 "notification order (removal tests)");
michael@0 250 is(received_mql[3], mql2,
michael@0 251 "notification order (removal tests)");
michael@0 252 received = [];
michael@0 253 received_mql = [];
michael@0 254
michael@0 255 iframe.style.width = "200px";
michael@0 256 subroot.offsetWidth; // flush layout
michael@0 257
michael@0 258 // mql(1, 3)
michael@0 259 is(JSON.stringify(received), "[1,3]",
michael@0 260 "listeners not notified for changes after their removal");
michael@0 261 is(received_mql[0], mql,
michael@0 262 "notification order (removal tests)");
michael@0 263 is(received_mql[1], mql,
michael@0 264 "notification order (removal tests)");
michael@0 265 })();
michael@0 266
michael@0 267 /* Bug 716751: null-dereference crash */
michael@0 268 (function() {
michael@0 269 iframe.style.width = "200px";
michael@0 270 subroot.offsetWidth; // flush layout
michael@0 271
michael@0 272 var mql = subwin.matchMedia("(min-width: 150px)");
michael@0 273 SimpleTest.doesThrow(function() {
michael@0 274 mql.addListener(null);
michael@0 275 }, "expected an exception");
michael@0 276
michael@0 277 iframe.style.width = "100px";
michael@0 278 subroot.offsetWidth; // flush layout
michael@0 279 // With the bug, we crash here. No need for test assertions.
michael@0 280
michael@0 281 SimpleTest.doesThrow(function() {
michael@0 282 mql.removeListener(null);
michael@0 283 }, "expected an exception");
michael@0 284 SimpleTest.doesThrow(function() {
michael@0 285 mql.removeListener(null);
michael@0 286 }, "expected an exception");
michael@0 287 })();
michael@0 288
michael@0 289 /* Bug 753777: test that things work in a freshly-created iframe */
michael@0 290 (function() {
michael@0 291 var iframe = document.createElement("iframe");
michael@0 292 document.body.appendChild(iframe);
michael@0 293
michael@0 294 is(iframe.contentWindow.matchMedia("(min-width: 1px)").matches, true,
michael@0 295 "(min-width: 1px) should match in newly-created iframe");
michael@0 296 is(iframe.contentWindow.matchMedia("(max-width: 1px)").matches, false,
michael@0 297 "(max-width: 1px) should not match in newly-created iframe");
michael@0 298
michael@0 299 document.body.removeChild(iframe);
michael@0 300 })();
michael@0 301
michael@0 302 /* Bug 716751: listeners lost due to GC */
michael@0 303 var gc_received = [];
michael@0 304 (function() {
michael@0 305 var received = [];
michael@0 306 var listener1 = function(mql) {
michael@0 307 gc_received.push(1);
michael@0 308 }
michael@0 309
michael@0 310 iframe.style.width = "200px";
michael@0 311 subroot.offsetWidth; // flush layout
michael@0 312
michael@0 313 var mql = subwin.matchMedia("(min-width: 150px)");
michael@0 314 mql.addListener(listener1);
michael@0 315 is(JSON.stringify(gc_received), "[]", "GC test: before notification");
michael@0 316
michael@0 317 iframe.style.width = "100px";
michael@0 318 subroot.offsetWidth; // flush layout
michael@0 319
michael@0 320 is(JSON.stringify(gc_received), "[1]", "GC test: after notification 1");
michael@0 321
michael@0 322 // Because of conservative GC, we need to go back to the event loop
michael@0 323 // to GC properly.
michael@0 324 setTimeout(step2, 0);
michael@0 325 })();
michael@0 326
michael@0 327 function step2() {
michael@0 328 SpecialPowers.DOMWindowUtils.garbageCollect();
michael@0 329
michael@0 330 iframe.style.width = "200px";
michael@0 331 subroot.offsetWidth; // flush layout
michael@0 332
michael@0 333 is(JSON.stringify(gc_received), "[1,1]", "GC test: after notification 2");
michael@0 334
michael@0 335 SimpleTest.finish();
michael@0 336 }
michael@0 337 }
michael@0 338
michael@0 339 </script>
michael@0 340 </pre>
michael@0 341 </body>
michael@0 342 </html>

mercurial