test_media_queries.html (36564B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=156716 5 --> 6 <head> 7 <title>Test for Bug 156716</title> 8 <script src="/tests/SimpleTest/SimpleTest.js"></script> 9 <script src="chrome/chrome-only-media-queries.js"></script> 10 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 11 </head> 12 <body onload="run()"> 13 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=156716">Mozilla Bug 156716</a> 14 <iframe id="subdoc" src="media_queries_iframe.html"></iframe> 15 <div id="content" style="display: none"> 16 17 </div> 18 <pre id="test"> 19 <script class="testbody" type="application/javascript"> 20 21 /** Test for Bug 156716 */ 22 23 // Note that many other tests are in test_acid3_test46.html . 24 25 SimpleTest.waitForExplicitFinish(); 26 SimpleTest.requestLongerTimeout(2); 27 28 var iframe; 29 30 function getScreenPixelsPerCSSPixel() { 31 return window.devicePixelRatio; 32 } 33 34 function run() { 35 iframe = document.getElementById("subdoc"); 36 var subdoc = iframe.contentDocument; 37 var subwin = iframe.contentWindow; 38 var style = subdoc.getElementById("style"); 39 var iframe_style = iframe.style; 40 var body_cs = subdoc.defaultView.getComputedStyle(subdoc.body); 41 42 function query_applies(q) { 43 style.setAttribute("media", q); 44 return body_cs.getPropertyValue("text-decoration-line") == "underline"; 45 } 46 47 function should_apply(q) { 48 ok(query_applies(q), q + " should apply"); 49 test_serialization(q, true, true); 50 } 51 52 function should_not_apply(q) { 53 ok(!query_applies(q), q + " should not apply"); 54 test_serialization(q, true, false); 55 } 56 57 /* for queries that are parseable standalone but not within CSS */ 58 function should_apply_unbalanced(q) { 59 ok(query_applies(q), q + " should apply"); 60 } 61 62 /* for queries that are parseable standalone but not within CSS */ 63 function should_not_apply_unbalanced(q) { 64 ok(!query_applies(q), q + " should not apply"); 65 } 66 67 /* 68 * Functions to test whether a query is parseable at all. (Should not 69 * be used for parse errors within expressions.) 70 */ 71 var parse_test_style_element = document.createElement("style"); 72 parse_test_style_element.type = "text/css"; 73 parse_test_style_element.disabled = true; // for performance, hopefully 74 var parse_test_style_text = document.createTextNode(""); 75 parse_test_style_element.appendChild(parse_test_style_text); 76 document.getElementsByTagName("head")[0] 77 .appendChild(parse_test_style_element); 78 79 function query_is_parseable(q) { 80 parse_test_style_text.data = "@media screen, " + q + " {}"; 81 var sheet = parse_test_style_element.sheet; // XXX yikes, not live! 82 if (sheet.cssRules.length == 1 && 83 sheet.cssRules[0].type == CSSRule.MEDIA_RULE) 84 return sheet.cssRules[0].media.mediaText != "screen, not all"; 85 ok(false, "unexpected result testing whether query " + q + 86 " is parseable"); 87 return true; // doesn't matter, we already failed 88 } 89 90 function query_should_be_parseable(q) { 91 ok(query_is_parseable(q), "query " + q + " should be parseable"); 92 test_serialization(q, false, false); 93 } 94 95 function query_should_not_be_parseable(q) { 96 ok(!query_is_parseable(q), "query " + q + " should not be parseable"); 97 } 98 99 function expression_should_be_known(e) { 100 should_apply(`(${e}) or (not (${e}))`); 101 } 102 103 function expression_should_not_be_known(e) { 104 should_not_apply(`(${e}) or (not (${e}))`); 105 } 106 107 // Helper to share code between -moz & -webkit device-pixel-ratio versions: 108 function test_device_pixel_ratio(equal_name, min_name, max_name) { 109 var real_dpr = 1.0 * getScreenPixelsPerCSSPixel(); 110 var high_dpr = 1.1 * getScreenPixelsPerCSSPixel(); 111 var low_dpr = 0.9 * getScreenPixelsPerCSSPixel(); 112 should_apply("all and (" + max_name + ": " + real_dpr + ")"); 113 should_apply("all and (" + min_name + ": " + real_dpr + ")"); 114 should_not_apply("not all and (" + max_name + ": " + real_dpr + ")"); 115 should_not_apply("not all and (" + min_name + ": " + real_dpr + ")"); 116 should_apply("all and (" + min_name + ": " + low_dpr + ")"); 117 should_apply("all and (" + max_name + ": " + high_dpr + ")"); 118 should_not_apply("all and (" + max_name + ": " + low_dpr + ")"); 119 should_not_apply("all and (" + min_name + ": " + high_dpr + ")"); 120 should_apply("not all and (" + max_name + ": " + low_dpr + ")"); 121 should_apply("not all and (" + min_name + ": " + high_dpr + ")"); 122 should_apply("(" + equal_name + ": " + real_dpr + ")"); 123 should_not_apply("(" + equal_name + ": " + high_dpr + ")"); 124 should_not_apply("(" + equal_name + ": " + low_dpr + ")"); 125 should_apply("(" + equal_name + ")"); 126 expression_should_not_be_known(min_name); 127 expression_should_not_be_known(max_name); 128 } 129 130 function test_serialization(q, test_application, expected_to_apply) { 131 style.setAttribute("media", q); 132 var ser1 = style.sheet.media.mediaText; 133 isnot(ser1, "", "serialization of '" + q + "' should not be empty"); 134 style.setAttribute("media", ser1); 135 var ser2 = style.sheet.media.mediaText; 136 is(ser2, ser1, "parse+serialize of '" + q + "' should be idempotent"); 137 if (test_application) { 138 let applies = body_cs.getPropertyValue("text-decoration-line") == 139 "underline"; 140 is(applies, expected_to_apply, 141 "Media query '" + q + "' should " + (expected_to_apply ? "" : "NOT ") + 142 "apply after serialize + reparse"); 143 } 144 145 // Test cloning 146 var sheet = "@media " + q + " { body { text-decoration: underline } }" 147 var sheeturl = "data:text/css," + escape(sheet); 148 var link = "<link rel='stylesheet' href='" + sheeturl + "'>"; 149 var htmldoc = "<!DOCTYPE HTML>" + link + link + "<body>"; 150 post_clone_test(htmldoc, function() { 151 var clonedoc = iframe.contentDocument; 152 var clonewin = iframe.contentWindow; 153 var links = clonedoc.getElementsByTagName("link"); 154 // cause a clone 155 var clonedsheet = links[1].sheet; 156 clonedsheet.insertRule("#nonexistent { color: purple}", 1); 157 // remove the uncloned sheet 158 links[0].remove(); 159 160 var ser3 = clonedsheet.cssRules[0].media.mediaText; 161 is(ser3, ser1, "cloning query '" + q + "' should not change " + 162 "serialization"); 163 if (test_application) { 164 let applies = clonewin.getComputedStyle(clonedoc.body). 165 textDecorationLine == "underline"; 166 is(applies, expected_to_apply, 167 "Media query '" + q + "' should " + (expected_to_apply ? "" : "NOT ") + 168 "apply after cloning"); 169 } 170 }); 171 } 172 173 // The no-type syntax doesn't mix with the not and only keywords. 174 expression_should_be_known("(orientation)"); 175 expression_should_be_known("not (orientation)"); 176 query_should_not_be_parseable("only (orientation)"); 177 query_should_be_parseable("all and (orientation)"); 178 query_should_be_parseable("not all and (orientation)"); 179 query_should_be_parseable("only all and (orientation)"); 180 181 query_should_not_be_parseable("not not (orientation)"); 182 expression_should_be_known("(orientation) and (orientation)"); 183 expression_should_be_known("(orientation) or (orientation)"); 184 expression_should_be_known("(orientation) or ((orientation) and ((orientation) or (orientation) or (not (orientation))))"); 185 186 query_should_not_be_parseable("all and (orientation) or (orientation)"); 187 query_should_be_parseable("all and (orientation) and (orientation)"); 188 189 query_should_not_be_parseable("(orientation) and (orientation) or (orientation)"); 190 query_should_not_be_parseable("(orientation) and not (orientation)"); 191 192 query_should_be_parseable("(-moz-device-orientation)"); 193 query_should_be_parseable("not (-moz-device-orientation)"); 194 query_should_not_be_parseable("only (-moz-device-orientation)"); 195 query_should_be_parseable("all and (-moz-device-orientation)"); 196 query_should_be_parseable("not all and (-moz-device-orientation)"); 197 query_should_be_parseable("only all and (-moz-device-orientation)"); 198 199 // Test that the 'not', 'only', 'and', and 'or' keywords are not 200 // allowed as media types. 201 query_should_not_be_parseable("not"); 202 query_should_not_be_parseable("and"); 203 query_should_not_be_parseable("or"); 204 query_should_not_be_parseable("only"); 205 query_should_be_parseable("unknowntype"); 206 query_should_not_be_parseable("not not"); 207 query_should_not_be_parseable("not and"); 208 query_should_not_be_parseable("not or"); 209 query_should_not_be_parseable("not only"); 210 query_should_be_parseable("not unknowntype"); 211 query_should_not_be_parseable("only not"); 212 query_should_not_be_parseable("only and"); 213 query_should_not_be_parseable("only or"); 214 query_should_not_be_parseable("only only"); 215 query_should_be_parseable("only unknowntype"); 216 query_should_not_be_parseable("not and (width)"); 217 query_should_not_be_parseable("and and (width)"); 218 query_should_not_be_parseable("or and (width)"); 219 query_should_not_be_parseable("only and (width)"); 220 query_should_be_parseable("unknowntype and (width)"); 221 query_should_not_be_parseable("not not and (width)"); 222 query_should_not_be_parseable("not and and (width)"); 223 query_should_not_be_parseable("not or and (width)"); 224 query_should_not_be_parseable("not only and (width)"); 225 query_should_be_parseable("not unknowntype and (width)"); 226 query_should_not_be_parseable("only not and (width)"); 227 query_should_not_be_parseable("only and and (width)"); 228 query_should_not_be_parseable("only or and (width)"); 229 query_should_not_be_parseable("only only and (width)"); 230 query_should_be_parseable("only unknowntype and (width)"); 231 232 var features = [ "width", "height", "device-width", "device-height" ]; 233 var separators = [ ":", ">", ">=", "=", "<=", "<" ]; 234 235 var feature; 236 var i; 237 for (i in features) { 238 feature = features[i]; 239 expression_should_be_known(feature); 240 expression_should_not_be_known("min-" + feature); 241 expression_should_not_be_known("max-" + feature); 242 for (let separator of separators) { 243 expression_should_be_known(feature + " " + separator + " 0"); 244 expression_should_be_known(feature + " " + separator + " 0px"); 245 expression_should_be_known(feature + " " + separator + " 0em"); 246 expression_should_be_known(feature + " " + separator + " -0"); 247 expression_should_be_known(feature + " " + separator + " -0cm"); 248 expression_should_be_known(feature + " " + separator + " 1px"); 249 expression_should_be_known(feature + " " + separator + " 0.001mm"); 250 expression_should_be_known(feature + " " + separator + " 100000px"); 251 expression_should_be_known(feature + " " + separator + " -1px"); 252 if (separator == ":") { 253 expression_should_be_known("min-" + feature + " " + separator + " -0"); 254 expression_should_be_known("max-" + feature + " " + separator + " -0"); 255 expression_should_be_known("min-" + feature + " " + separator + " -1px"); 256 expression_should_be_known("max-" + feature + " " + separator + " -1px"); 257 expression_should_be_known(feature + " " + separator + " -0.00001mm"); 258 expression_should_be_known(feature + " " + separator + " -100000em"); 259 } else { 260 expression_should_not_be_known("min-" + feature + " " + separator + " -0"); 261 expression_should_not_be_known("max-" + feature + " " + separator + " -0"); 262 expression_should_not_be_known("min-" + feature + " " + separator + " -1px"); 263 expression_should_not_be_known("max-" + feature + " " + separator + " -1px"); 264 let multi_range = "0px " + separator + " " + feature + " " + separator + " 100000px" 265 if (separator == "=") { 266 expression_should_not_be_known(multi_range); 267 } else { 268 expression_should_be_known(multi_range); 269 } 270 } 271 if (separator == ">=") { 272 expression_should_not_be_known(feature + " > = 0px"); 273 } else if (separator == "<=") { 274 expression_should_not_be_known(feature + " < = 0px"); 275 } 276 } 277 } 278 279 var mediatypes = ["browser", "minimal-ui", "standalone", "fullscreen"]; 280 281 mediatypes.forEach(function(type) { 282 expression_should_be_known("display-mode: " + type); 283 }); 284 285 if (SpecialPowers.getBoolPref("dom.documentpip.enabled")) { 286 expression_should_be_known("display-mode: picture-in-picture"); 287 } else { 288 expression_should_not_be_known("display-mode: picture-in-picture"); 289 } 290 291 expression_should_not_be_known("display-mode: invalid") 292 293 var content_div = document.getElementById("content"); 294 content_div.style.font = "initial"; 295 var em_size = 296 getComputedStyle(content_div, "").fontSize.match(/^(\d+)px$/)[1]; 297 298 // in this test, assume the common underlying implementation is correct 299 var width_val = 117; // pick two not-too-round numbers 300 var height_val = 76; 301 change_state(function() { 302 iframe_style.width = width_val + "px"; 303 iframe_style.height = height_val + "px"; 304 }); 305 var device_width = window.screen.width; 306 var device_height = window.screen.height; 307 features = { 308 "width": width_val, 309 "height": height_val, 310 "device-width": device_width, 311 "device-height": device_height 312 }; 313 for (feature in features) { 314 var value = features[feature]; 315 should_apply("all and (" + feature + ": " + value + "px)"); 316 should_apply("all and (" + feature + " = " + value + "px)"); 317 should_not_apply("all and (" + feature + ": " + (value + 1) + "px)"); 318 should_not_apply("all and (" + feature + ": " + (value - 1) + "px)"); 319 should_not_apply("all and (" + feature + " = " + (value + 1) + "px)"); 320 should_not_apply("all and (" + feature + " = " + (value - 1) + "px)"); 321 322 should_apply("all and (min-" + feature + ": " + value + "px)"); 323 should_not_apply("all and (min-" + feature + ": " + (value + 1) + "px)"); 324 should_apply("all and (min-" + feature + ": " + (value - 1) + "px)"); 325 should_apply("all and (max-" + feature + ": " + value + "px)"); 326 should_apply("all and (max-" + feature + ": " + (value + 1) + "px)"); 327 should_not_apply("all and (max-" + feature + ": " + (value - 1) + "px)"); 328 should_not_apply("all and (min-" + feature + ": " + 329 (Math.ceil(value/em_size) + 1) + "em)"); 330 should_apply("all and (min-" + feature + ": " + 331 (Math.floor(value/em_size) - 1) + "em)"); 332 should_apply("all and (max-" + feature + ": " + 333 (Math.ceil(value/em_size) + 1) + "em)"); 334 should_not_apply("all and (max-" + feature + ": " + 335 (Math.floor(value/em_size) - 1) + "em)"); 336 should_not_apply("all and (min-" + feature + ": " + 337 (Math.ceil(value/em_size) + 1) + "rem)"); 338 should_apply("all and (min-" + feature + ": " + 339 (Math.floor(value/em_size) - 1) + "rem)"); 340 should_apply("all and (max-" + feature + ": " + 341 (Math.ceil(value/em_size) + 1) + "rem)"); 342 should_not_apply("all and (max-" + feature + ": " + 343 (Math.floor(value/em_size) - 1) + "rem)"); 344 345 should_apply("(" + feature + " <= " + value + "px)"); 346 should_apply("(" + feature + " >= " + value + "px)"); 347 348 should_apply("(0px < " + feature + " <= " + value + "px)"); 349 should_apply("(" + value + "px >= " + feature + " > 0px)"); 350 351 should_not_apply("(0px < " + feature + " < " + value + "px)"); 352 should_not_apply("(" + value + "px > " + feature + " > 0px)"); 353 354 should_not_apply("(" + feature + " < " + value + "px)"); 355 should_not_apply("(" + feature + " > " + value + "px)"); 356 357 should_apply("(" + feature + " < " + (value + 1) + "px)"); 358 should_apply("(" + feature + " <= " + (value + 1) + "px)"); 359 should_not_apply("(" + feature + " > " + (value + 1) + "px)"); 360 should_not_apply("(" + feature + " >= " + (value + 1) + "px)"); 361 362 should_apply("(" + feature + " > " + (value - 1) + "px)"); 363 should_apply("(" + feature + " >= " + (value - 1) + "px)"); 364 should_not_apply("(" + feature + " < " + (value - 1) + "px)"); 365 should_not_apply("(" + feature + " <= " + (value - 1) + "px)"); 366 } 367 368 change_state(function() { 369 iframe_style.width = "0"; 370 }); 371 should_apply("all and (height)"); 372 should_not_apply("all and (width)"); 373 change_state(function() { 374 iframe_style.height = "0"; 375 }); 376 should_not_apply("all and (height)"); 377 should_not_apply("all and (width)"); 378 should_apply("all and (device-height)"); 379 should_apply("all and (device-width)"); 380 change_state(function() { 381 iframe_style.width = width_val + "px"; 382 }); 383 should_not_apply("all and (height)"); 384 should_apply("all and (width)"); 385 change_state(function() { 386 iframe_style.height = height_val + "px"; 387 }); 388 should_apply("all and (height)"); 389 should_apply("all and (width)"); 390 391 // ratio that reduces to 59/40 392 change_state(function() { 393 iframe_style.width = "236px"; 394 iframe_style.height = "160px"; 395 }); 396 expression_should_be_known("orientation"); 397 expression_should_be_known("orientation: portrait"); 398 expression_should_be_known("orientation: landscape"); 399 expression_should_not_be_known("min-orientation"); 400 expression_should_not_be_known("min-orientation: portrait"); 401 expression_should_not_be_known("min-orientation: landscape"); 402 expression_should_not_be_known("max-orientation"); 403 expression_should_not_be_known("max-orientation: portrait"); 404 expression_should_not_be_known("max-orientation: landscape"); 405 should_apply("(orientation)"); 406 should_apply("(orientation: landscape)"); 407 should_not_apply("(orientation: portrait)"); 408 should_apply("not all and (orientation: portrait)"); 409 // ratio that reduces to 59/80 410 change_state(function() { 411 iframe_style.height = "320px"; 412 }); 413 should_apply("(orientation)"); 414 should_not_apply("(orientation: landscape)"); 415 should_apply("not all and (orientation: landscape)"); 416 should_apply("(orientation: portrait)"); 417 418 expression_should_be_known("-moz-device-orientation"); 419 expression_should_be_known("-moz-device-orientation: portrait"); 420 expression_should_be_known("-moz-device-orientation: landscape"); 421 expression_should_not_be_known("min--moz-device-orientation"); 422 expression_should_not_be_known("min--moz-device-orientation: portrait"); 423 expression_should_not_be_known("min--moz-device-orientation: landscape"); 424 expression_should_not_be_known("max--moz-device-orientation"); 425 expression_should_not_be_known("max--moz-device-orientation: portrait"); 426 expression_should_not_be_known("max--moz-device-orientation: landscape"); 427 428 // determine the actual configuration of the screen and test against it 429 var device_orientation = (device_width > device_height) ? "landscape" : "portrait"; 430 var not_device_orientation = (device_orientation == "landscape") ? "portrait" : "landscape"; 431 should_apply("(-moz-device-orientation)"); 432 should_apply("(-moz-device-orientation: " + device_orientation + ")"); 433 should_not_apply("(-moz-device-orientation: " + not_device_orientation + ")"); 434 should_apply("not all and (-moz-device-orientation: " + not_device_orientation + ")"); 435 436 should_apply("(aspect-ratio: 59/80)"); 437 should_not_apply("(aspect-ratio: 58/80)"); 438 should_not_apply("(aspect-ratio: 59/81)"); 439 should_not_apply("(aspect-ratio: 60/80)"); 440 should_not_apply("(aspect-ratio: 59/79)"); 441 should_apply("(aspect-ratio: 177/240)"); 442 should_apply("(aspect-ratio: 413/560)"); 443 should_apply("(aspect-ratio: 5900/8000)"); 444 should_not_apply("(aspect-ratio: 5901/8000)"); 445 should_not_apply("(aspect-ratio: 5899/8000)"); 446 should_not_apply("(aspect-ratio: 5900/8001)"); 447 should_not_apply("(aspect-ratio: 5900/7999)"); 448 should_apply("(aspect-ratio)"); 449 450 // Test "unreasonable", but still valid aspect ratios, such as aspect ratios with negative numbers, 451 // and zeros, and with numbers near 2^32 and 2^64 (to check overflow). 452 should_not_apply("(aspect-ratio: 0/1)"); 453 should_not_apply("(aspect-ratio: 1/0)"); 454 should_not_apply("(aspect-ratio: -1/1)"); 455 should_not_apply("(aspect-ratio: 1/-1)"); 456 should_not_apply("(aspect-ratio: -1/-1)"); 457 should_not_apply("(aspect-ratio: -59/-80)"); 458 should_not_apply("(aspect-ratio: 4294967295/4294967295)"); 459 should_not_apply("(aspect-ratio: 4294967297/4294967297)"); 460 should_not_apply("(aspect-ratio: 18446744073709560000/18446744073709560000)"); 461 462 // Test min and max aspect ratios. 463 should_apply("(min-aspect-ratio: 59/80)"); 464 should_apply("(min-aspect-ratio: 58/80)"); 465 should_apply("(min-aspect-ratio: 59/81)"); 466 should_not_apply("(min-aspect-ratio: 60/80)"); 467 should_not_apply("(min-aspect-ratio: 59/79)"); 468 expression_should_not_be_known("min-aspect-ratio"); 469 470 should_apply("(max-aspect-ratio: 59/80)"); 471 should_not_apply("(max-aspect-ratio: 58/80)"); 472 should_not_apply("(max-aspect-ratio: 59/81)"); 473 should_apply("(max-aspect-ratio: 60/80)"); 474 should_apply("(max-aspect-ratio: 59/79)"); 475 expression_should_not_be_known("max-aspect-ratio"); 476 477 var real_dar = device_width + "/" + device_height; 478 var high_dar_1 = (device_width + 1) + "/" + device_height; 479 var high_dar_2 = device_width + "/" + (device_height - 1); 480 var low_dar_1 = (device_width - 1) + "/" + device_height; 481 var low_dar_2 = device_width + "/" + (device_height + 1); 482 should_apply("(device-aspect-ratio: " + real_dar + ")"); 483 should_apply("not all and (device-aspect-ratio: " + high_dar_1 + ")"); 484 should_not_apply("all and (device-aspect-ratio: " + high_dar_2 + ")"); 485 should_not_apply("all and (device-aspect-ratio: " + low_dar_1 + ")"); 486 should_apply("not all and (device-aspect-ratio: " + low_dar_2 + ")"); 487 should_apply("(device-aspect-ratio)"); 488 489 should_apply("(min-device-aspect-ratio: " + real_dar + ")"); 490 should_not_apply("all and (min-device-aspect-ratio: " + high_dar_1 + ")"); 491 should_apply("not all and (min-device-aspect-ratio: " + high_dar_2 + ")"); 492 should_not_apply("not all and (min-device-aspect-ratio: " + low_dar_1 + ")"); 493 should_apply("all and (min-device-aspect-ratio: " + low_dar_2 + ")"); 494 expression_should_not_be_known("min-device-aspect-ratio"); 495 496 should_apply("all and (max-device-aspect-ratio: " + real_dar + ")"); 497 should_apply("(max-device-aspect-ratio: " + high_dar_1 + ")"); 498 should_apply("(max-device-aspect-ratio: " + high_dar_2 + ")"); 499 should_not_apply("all and (max-device-aspect-ratio: " + low_dar_1 + ")"); 500 should_apply("not all and (max-device-aspect-ratio: " + low_dar_2 + ")"); 501 expression_should_not_be_known("max-device-aspect-ratio"); 502 503 // Tests for -moz- & -webkit versions of "device-pixel-ratio" 504 // (Note that the vendor prefixes go in different places.) 505 test_device_pixel_ratio("-moz-device-pixel-ratio", 506 "min--moz-device-pixel-ratio", 507 "max--moz-device-pixel-ratio"); 508 test_device_pixel_ratio("-webkit-device-pixel-ratio", 509 "-webkit-min-device-pixel-ratio", 510 "-webkit-max-device-pixel-ratio"); 511 512 // Make sure that we don't accidentally start accepting *unprefixed* 513 // "device-pixel-ratio" expressions: 514 expression_should_be_known("-webkit-device-pixel-ratio: 1.0"); 515 expression_should_not_be_known("device-pixel-ratio: 1.0"); 516 expression_should_be_known("-webkit-min-device-pixel-ratio: 1.0"); 517 expression_should_not_be_known("min-device-pixel-ratio: 1.0"); 518 expression_should_be_known("-webkit-max-device-pixel-ratio: 1.0"); 519 expression_should_not_be_known("max-device-pixel-ratio: 1.0"); 520 521 should_apply("(-webkit-transform-3d)"); 522 523 features = [ "max-aspect-ratio", "device-aspect-ratio" ]; 524 for (i in features) { 525 feature = features[i]; 526 expression_should_be_known(feature + ": 1/1"); 527 expression_should_be_known(feature + ": 1 /1"); 528 expression_should_be_known(feature + ": 1 / \t\n1"); 529 expression_should_be_known(feature + ": 1/\r1"); 530 expression_should_be_known(feature + ": 1"); 531 expression_should_be_known(feature + ": 0.5"); 532 expression_should_be_known(feature + ": 1.0/1"); 533 expression_should_be_known(feature + ": 1/1.0"); 534 expression_should_be_known(feature + ": 1.0/1.0"); 535 expression_should_be_known(feature + ": 1.5/1.2"); 536 expression_should_be_known(feature + ": 1.5"); 537 expression_should_be_known(feature + ": calc(1.2 * 1.3)"); 538 expression_should_be_known(feature + ": 1.1/calc(2.2 * 2.3)"); 539 expression_should_be_known(feature + ": calc(1.2 * 1.3)/2.2"); 540 expression_should_be_known(feature + ": calc(1.2 * 1.3)/calc(2.2 * 2.3)"); 541 expression_should_be_known(feature + ": 0/1"); 542 expression_should_be_known(feature + ": 1/0"); 543 expression_should_be_known(feature + ": 0/0"); 544 expression_should_not_be_known(feature + ": -1/1"); 545 expression_should_not_be_known(feature + ": 1/-1"); 546 expression_should_not_be_known(feature + ": -1/-1"); 547 expression_should_not_be_known(feature + ": -1/-1"); 548 expression_should_not_be_known(feature + ": -1/-1"); 549 expression_should_not_be_known(feature + ": invalid"); 550 expression_should_not_be_known(feature + ": 1 / invalid"); 551 expression_should_not_be_known(feature + ": 1 invalid"); 552 } 553 554 var is_monochrome = query_applies("all and (min-monochrome: 1)"); 555 test_serialization("all and (min-monochrome: 1)", true, is_monochrome); 556 var is_color = query_applies("all and (min-color: 1)"); 557 test_serialization("all and (min-color: 1)", true, is_color); 558 isnot(is_monochrome, is_color, "should be either monochrome or color"); 559 560 function depth_query(prefix, depth) { 561 return "all and (" + prefix + (is_color ? "color" : "monochrome") + 562 ":" + depth + ")"; 563 } 564 565 var depth = 0; 566 do { 567 if (depth > 50) { 568 ok(false, "breaking from loop, depth > 50"); 569 break; 570 } 571 } while (query_applies(depth_query("min-", ++depth))); 572 --depth; 573 574 should_apply(depth_query("", depth)); 575 should_not_apply(depth_query("", depth - 1)); 576 should_not_apply(depth_query("", depth + 1)); 577 should_apply(depth_query("max-", depth)); 578 should_not_apply(depth_query("max-", depth - 1)); 579 should_apply(depth_query("max-", depth + 1)); 580 581 (is_color ? should_apply : should_not_apply)("all and (color)"); 582 expression_should_not_be_known("max-color"); 583 expression_should_not_be_known("min-color"); 584 (is_color ? should_not_apply : should_apply)("all and (monochrome)"); 585 expression_should_not_be_known("max-monochrome"); 586 expression_should_not_be_known("min-monochrome"); 587 (is_color ? should_apply : should_not_apply)("not all and (monochrome)"); 588 (is_color ? should_not_apply : should_apply)("not all and (color)"); 589 (is_color ? should_apply : should_not_apply)("only all and (color)"); 590 (is_color ? should_not_apply : should_apply)("only all and (monochrome)"); 591 592 features = [ "color", "min-monochrome", "max-color-index" ]; 593 for (i in features) { 594 feature = features[i]; 595 expression_should_be_known(feature + ": 1"); 596 expression_should_be_known(feature + ": 327"); 597 expression_should_be_known(feature + ": 0"); 598 expression_should_be_known(feature + ": -1"); 599 expression_should_not_be_known(feature + ": 1.0"); 600 expression_should_not_be_known(feature + ": 1/1"); 601 } 602 603 // Presume that we never support indexed color (at least not usefully 604 // enough to call it indexed color). 605 should_apply("(color-index: 0)"); 606 should_not_apply("(color-index: 1)"); 607 should_apply("(min-color-index: 0)"); 608 should_not_apply("(min-color-index: 1)"); 609 should_apply("(max-color-index: 0)"); 610 should_apply("(max-color-index: 1)"); 611 should_apply("(max-color-index: 157)"); 612 613 features = [ "resolution", "min-resolution", "max-resolution" ]; 614 for (i in features) { 615 feature = features[i]; 616 expression_should_be_known(feature + ": 3dpi"); 617 expression_should_be_known(feature + ":3dpi"); 618 expression_should_be_known(feature + ": 3.0dpi"); 619 expression_should_be_known(feature + ": 3.4dpi"); 620 expression_should_be_known(feature + "\t: 120dpcm"); 621 expression_should_be_known(feature + ": 1dppx"); 622 expression_should_be_known(feature + ": 1x"); 623 expression_should_be_known(feature + ": 1.5dppx"); 624 expression_should_be_known(feature + ": 1.5x"); 625 expression_should_be_known(feature + ": 2.0dppx"); 626 expression_should_be_known(feature + ": 0dpi"); 627 expression_should_be_known(feature + ": 0dppx"); 628 expression_should_be_known(feature + ": 0x"); 629 expression_should_not_be_known(feature + ": -3dpi"); 630 } 631 632 // Find the resolution using max-resolution 633 var resolution = 0; 634 do { 635 ++resolution; 636 if (resolution > 10000) { 637 ok(false, "resolution greater than 10000dpi???"); 638 break; 639 } 640 } while (!query_applies("(max-resolution: " + resolution + "dpi)")); 641 642 // resolution should now be Math.ceil() of the actual resolution. 643 var dpi_high; 644 var dpi_low = resolution - 1; 645 if (query_applies("(min-resolution: " + resolution + "dpi)")) { 646 // It's exact! 647 should_apply("(resolution: " + resolution + "dpi)"); 648 should_apply("(resolution: " + Math.floor(resolution/96) + "dppx)"); 649 should_apply("(resolution: " + Math.floor(resolution/96) + "x)"); 650 should_not_apply("(resolution: " + (resolution + 1) + "dpi)"); 651 should_not_apply("(resolution: " + (resolution - 1) + "dpi)"); 652 dpi_high = resolution + 1; 653 } else { 654 // We have no way to test resolution applying since it need not be 655 // an integer. 656 should_not_apply("(resolution: " + resolution + "dpi)"); 657 should_not_apply("(resolution: " + (resolution - 1) + "dpi)"); 658 dpi_high = resolution; 659 } 660 661 should_apply("(min-resolution: " + dpi_low + "dpi)"); 662 should_not_apply("not all and (min-resolution: " + dpi_low + "dpi)"); 663 should_apply("not all and (min-resolution: " + dpi_high + "dpi)"); 664 should_not_apply("all and (min-resolution: " + dpi_high + "dpi)"); 665 666 // Test dpcm units based on what we computed in dpi. 667 var dpcm_high = Math.ceil(dpi_high / 2.54); 668 var dpcm_low = Math.floor(dpi_low / 2.54); 669 should_apply("(min-resolution: " + dpcm_low + "dpcm)"); 670 should_apply("(max-resolution: " + dpcm_high + "dpcm)"); 671 should_not_apply("(max-resolution: " + dpcm_low + "dpcm)"); 672 should_apply("not all and (min-resolution: " + dpcm_high + "dpcm)"); 673 674 expression_should_be_known("scan"); 675 expression_should_be_known("scan: progressive"); 676 expression_should_be_known("scan:interlace"); 677 expression_should_not_be_known("min-scan:interlace"); 678 expression_should_not_be_known("scan: 1"); 679 expression_should_not_be_known("max-scan"); 680 expression_should_not_be_known("max-scan: progressive"); 681 // Assume we don't support tv devices. 682 should_not_apply("(scan)"); 683 should_not_apply("(scan: progressive)"); 684 should_not_apply("(scan: interlace)"); 685 should_apply("not all and (scan)"); 686 should_apply("not all and (scan: progressive)"); 687 should_apply("not all and (scan: interlace)"); 688 689 expression_should_be_known("grid"); 690 expression_should_be_known("grid: 0"); 691 expression_should_be_known("grid: 1"); 692 expression_should_be_known("grid: 1"); 693 expression_should_not_be_known("min-grid"); 694 expression_should_not_be_known("min-grid:0"); 695 expression_should_not_be_known("max-grid: 1"); 696 expression_should_not_be_known("grid: 2"); 697 expression_should_not_be_known("grid: -1"); 698 699 // Assume we don't support grid devices 700 should_not_apply("(grid)"); 701 should_apply("(grid: 0)"); 702 should_not_apply("(grid: 1)"); 703 should_not_apply("(grid: 2)"); 704 should_not_apply("(grid: -1)"); 705 706 for (let toggle of CHROME_ONLY_TOGGLES) { 707 expression_should_not_be_known(toggle); 708 expression_should_not_be_known(toggle + ": 1"); 709 expression_should_not_be_known(toggle + ": 0"); 710 expression_should_not_be_known(toggle + ": -1"); 711 expression_should_not_be_known(toggle + ": true"); 712 expression_should_not_be_known(toggle + ": false"); 713 } 714 715 for (let query of CHROME_ONLY_QUERIES) { 716 expression_should_not_be_known(query); 717 } 718 719 expression_should_be_known("prefers-contrast"); 720 expression_should_be_known("prefers-contrast: more"); 721 expression_should_be_known("prefers-contrast: less"); 722 expression_should_be_known("prefers-contrast: custom"); 723 expression_should_be_known("prefers-contrast: no-preference"); 724 725 expression_should_be_known("forced-colors"); 726 expression_should_be_known("forced-colors: none"); 727 expression_should_be_known("forced-colors: active"); 728 729 // OpenType SVG media features 730 expression_should_not_be_known("(-moz-is-glyph)"); 731 expression_should_not_be_known("not (-moz-is-glyph)"); 732 expression_should_not_be_known("only (-moz-is-glyph)"); 733 expression_should_not_be_known("all and (-moz-is-glyph)"); 734 expression_should_not_be_known("not all and (-moz-is-glyph)"); 735 expression_should_not_be_known("only all and (-moz-is-glyph)"); 736 737 expression_should_not_be_known("(-moz-is-glyph:0)"); 738 expression_should_not_be_known("not (-moz-is-glyph:0)"); 739 expression_should_not_be_known("only (-moz-is-glyph:0)"); 740 expression_should_not_be_known("all and (-moz-is-glyph:0)"); 741 expression_should_not_be_known("not all and (-moz-is-glyph:0)"); 742 expression_should_not_be_known("only all and (-moz-is-glyph:0)"); 743 744 expression_should_not_be_known("(-moz-is-glyph:1)"); 745 expression_should_not_be_known("not (-moz-is-glyph:1)"); 746 expression_should_not_be_known("only (-moz-is-glyph:1)"); 747 expression_should_not_be_known("all and (-moz-is-glyph:1)"); 748 expression_should_not_be_known("not all and (-moz-is-glyph:1)"); 749 expression_should_not_be_known("only all and (-moz-is-glyph:1)"); 750 751 expression_should_not_be_known("(min--moz-is-glyph:0)"); 752 expression_should_not_be_known("(max--moz-is-glyph:0)"); 753 expression_should_not_be_known("(min--moz-is-glyph:1)"); 754 expression_should_not_be_known("(max--moz-is-glyph:1)"); 755 756 should_not_apply("not all and (-moz-is-glyph)"); 757 should_not_apply("(-moz-is-glyph:0)"); 758 should_not_apply("not all and (-moz-is-glyph:1)"); 759 should_not_apply("only all and (-moz-is-glyph:0)"); 760 should_not_apply("(-moz-is-glyph)"); 761 should_not_apply("(-moz-is-glyph:1)"); 762 should_not_apply("not all and (-moz-is-glyph:0)"); 763 should_not_apply("only all and (-moz-is-glyph:1)"); 764 765 // Resource documents (UA-only). 766 expression_should_not_be_known("(-moz-is-resource-document)"); 767 768 // Parsing tests 769 // bug 454227 770 should_apply_unbalanced("(orientation"); 771 should_not_apply_unbalanced("not all and (orientation"); 772 should_not_apply_unbalanced("(orientation:"); 773 should_apply_unbalanced("all,(orientation:"); 774 should_not_apply_unbalanced("(orientation:,all"); 775 should_apply_unbalanced("not all and (grid"); 776 should_not_apply_unbalanced("only all and (grid"); 777 should_not_apply_unbalanced("(grid"); 778 should_apply_unbalanced("all,(grid"); 779 should_not_apply_unbalanced("(grid,all"); 780 // bug 454226 781 should_apply(",all"); 782 should_apply("all,"); 783 should_apply(",all,"); 784 should_apply("all,badmedium"); 785 should_apply("badmedium,all"); 786 should_not_apply(",badmedium,"); 787 should_apply("all,(badexpression)"); 788 should_apply("(badexpression),all"); 789 should_not_apply("(badexpression),badmedium"); 790 should_not_apply("badmedium,(badexpression)"); 791 should_apply("all,[badsyntax]"); 792 should_apply("[badsyntax],all"); 793 should_not_apply("badmedium,[badsyntax]"); 794 should_not_apply("[badsyntax],badmedium"); 795 // bug 528096 796 should_not_apply_unbalanced("((resolution),all"); 797 should_not_apply_unbalanced("(resolution(),all"); 798 should_not_apply_unbalanced("(resolution (),all"); 799 should_not_apply_unbalanced("(resolution:(),all"); 800 801 for (let rangeFeature of ["dynamic-range", "video-dynamic-range"]) { 802 should_apply("(" + rangeFeature + ": standard)"); 803 expression_should_be_known("(" + rangeFeature + ": high)"); 804 expression_should_not_be_known("(" + rangeFeature + ": low)"); 805 } 806 807 handle_posted_items(); 808 } 809 810 /* 811 * The cloning tests have to post tests that wait for onload. However, 812 * we also make a bunch of state changes during the tests above. So we 813 * always change state using the change_state call, with both makes the 814 * change immediately and posts an item in the same queue so that we 815 * make the same state change again later. 816 */ 817 818 var posted_items = []; 819 820 function change_state(func) 821 { 822 func(); 823 posted_items.push({state: func}); 824 } 825 826 function post_clone_test(srcdoc, testfunc) 827 { 828 posted_items.push({srcdoc, testfunc}); 829 } 830 831 function handle_posted_items() 832 { 833 if (posted_items.length == 0) { 834 SimpleTest.finish(); 835 return; 836 } 837 838 if ("state" in posted_items[0]) { 839 var item = posted_items.shift(); 840 item.state(); 841 handle_posted_items(); 842 return; 843 } 844 845 var srcdoc = posted_items[0].srcdoc; 846 iframe.onload = handle_iframe_onload; 847 iframe.srcdoc = srcdoc; 848 } 849 850 function handle_iframe_onload(event) 851 { 852 if (event.target != iframe) 853 return; 854 855 var item = posted_items.shift(); 856 item.testfunc(); 857 handle_posted_items(); 858 } 859 860 </script> 861 </pre> 862 </body> 863 </html>