test_media_queries.html (32439B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>Media Queries Self-Contained Test Suite</title> 5 <link rel="author" title="L. David Baron" href="https://dbaron.org/"> 6 <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"> 7 <link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com"> 8 <link rel="help" href="https://www.w3.org/TR/css3-mediaqueries/#media0"> 9 <script type="text/javascript" src="/resources/testharness.js"></script> 10 <script type="text/javascript" src="/resources/testharnessreport.js"></script> 11 </head> 12 <body onload="run()"> 13 <div id=log></div> 14 <iframe id="subdoc" src="support/media_queries_iframe.html"></iframe> 15 <div id="content" style="display: none"></div> 16 17 <script type="text/javascript"> 18 setup({ "explicit_done": true }); 19 20 function run() { 21 var subdoc = document.getElementById("subdoc").contentDocument; 22 var subwin = document.getElementById("subdoc").contentWindow; 23 var style = subdoc.getElementById("style"); 24 var iframe_style = document.getElementById("subdoc").style; 25 var body_cs = subdoc.defaultView.getComputedStyle(subdoc.body, ""); 26 var testGroup = ""; 27 28 function query_applies(q) { 29 style.setAttribute("media", q); 30 return body_cs.getPropertyValue("text-decoration-line") == "underline"; 31 } 32 33 function not(predicate) { 34 return (...args) => !predicate(...args); 35 } 36 37 function test_predicate(input, predicate, name) { 38 test(() => { 39 // lazily evaluate template string to avoid including device-specific data in test name 40 var escaped = JSON.stringify(input); 41 var evaled = eval("`" + escaped.substring(1, escaped.length - 1) + "`"); 42 // Also avoid an assert message for the same reason. (Relevant for 43 // failing tests). 44 assert_true(predicate(evaled)) 45 }, `${testGroup ? testGroup + ": " : ""}${name}: ${input}`); 46 } 47 48 function should_apply(q) { 49 test_predicate(q, query_applies, "should_apply"); 50 } 51 52 function should_not_apply(q) { 53 test_predicate(q, not(query_applies), "should_not_apply"); 54 } 55 56 /* 57 * Functions to test whether a query is parseable at all. (Should not 58 * be used for parse errors within expressions.) 59 */ 60 var parse_test_style_element = document.createElement("style"); 61 parse_test_style_element.type = "text/css"; 62 parse_test_style_element.disabled = true; // for performance, hopefully 63 var parse_test_style_text = document.createTextNode(""); 64 parse_test_style_element.appendChild(parse_test_style_text); 65 document.getElementsByTagName("head")[0] 66 .appendChild(parse_test_style_element); 67 68 function query_is_parseable(q) { 69 parse_test_style_text.data = "@media screen, " + q + " {}"; 70 var sheet = parse_test_style_element.sheet; // XXX yikes, not live! 71 if (sheet.cssRules.length == 1 && 72 sheet.cssRules[0].type == CSSRule.MEDIA_RULE) 73 return sheet.cssRules[0].media.mediaText != "screen, not all"; 74 75 assert_unreached( 76 "unexpected result testing whether query " + q + " is parseable"); 77 } 78 79 function query_should_be_parseable(q) { 80 test_predicate(q, query_is_parseable, "query_should_be_parseable"); 81 } 82 83 function query_should_not_be_parseable(q) { 84 test_predicate(q, not(query_is_parseable), "query_should_not_be_parseable"); 85 } 86 87 /* 88 * Functions to test whether a single media expression is "unknown" or not. 89 * 90 * https://drafts.csswg.org/mediaqueries-4/#evaluating 91 */ 92 93 function expression_is_parseable(e) { 94 return query_is_parseable(`(${e})`); 95 } 96 97 function expression_is_known(e) { 98 return query_applies(`(${e}), not all and (${e})`); 99 } 100 101 function expression_should_be_known(e) { 102 // We don't bother with expression_is_parseable here, because it must be parseable to be known 103 test_predicate(e, expression_is_known, "expression_should_be_known"); 104 } 105 106 function expression_should_be_unknown(e) { 107 test_predicate(e, expression_is_parseable, "expression_should_be_parseable"); 108 test_predicate(e, not(expression_is_known), "expression_should_be_unknown"); 109 } 110 111 // The no-type syntax doesn't mix with the not and only keywords. 112 query_should_be_parseable("(orientation)"); 113 query_should_be_parseable("not (orientation)"); 114 expression_should_be_known("(orientation)"); 115 expression_should_be_known("not (orientation)"); 116 query_should_not_be_parseable("only (orientation)"); 117 query_should_be_parseable("all and (orientation)"); 118 query_should_be_parseable("not all and (orientation)"); 119 query_should_be_parseable("only all and (orientation)"); 120 121 query_should_not_be_parseable("not not (orientation)"); 122 query_should_be_parseable("(orientation) and (orientation)"); 123 query_should_be_parseable("(orientation) or (orientation)"); 124 query_should_be_parseable("(orientation) or ((orientation) and ((orientation) or (orientation) or (not (orientation))))"); 125 expression_should_be_known("(orientation) and (orientation)"); 126 expression_should_be_known("(orientation) or (orientation)"); 127 expression_should_be_known("(orientation) or ((orientation) and ((orientation) or (orientation) or (not (orientation))))"); 128 129 query_should_not_be_parseable("all and (orientation) or (orientation)"); 130 query_should_be_parseable("all and (orientation) and (orientation)"); 131 132 query_should_not_be_parseable("(orientation) and (orientation) or (orientation)"); 133 query_should_not_be_parseable("(orientation) and not (orientation)"); 134 135 var features = [ "width", "height", "device-width", "device-height" ]; 136 var separators = [ ":", ">", ">=", "=", "<=", "<" ]; 137 var feature; 138 var i; 139 for (i in features) { 140 feature = features[i]; 141 expression_should_be_known(feature); 142 expression_should_be_unknown("min-" + feature); 143 expression_should_be_unknown("max-" + feature); 144 for (let separator of separators) { 145 expression_should_be_known(feature + " " + separator + " 0"); 146 expression_should_be_known(feature + " " + separator + " 0px"); 147 expression_should_be_known(feature + " " + separator + " 0em"); 148 expression_should_be_known(feature + " " + separator + " -0"); 149 expression_should_be_known(feature + " " + separator + " -0cm"); 150 expression_should_be_known(feature + " " + separator + " 1px"); 151 expression_should_be_known(feature + " " + separator + " 0.001mm"); 152 expression_should_be_known(feature + " " + separator + " 100000px"); 153 if (separator == ":") { 154 expression_should_be_known("min-" + feature + " " + separator + " -0"); 155 expression_should_be_known("max-" + feature + " " + separator + " -0"); 156 } else { 157 expression_should_be_unknown("min-" + feature + " " + separator + " -0"); 158 expression_should_be_unknown("max-" + feature + " " + separator + " -0"); 159 let multi_range = "0px " + separator + " " + feature + " " + separator + " 100000px" 160 if (separator == "=") { 161 expression_should_be_unknown(multi_range); 162 } else { 163 expression_should_be_known(multi_range); 164 } 165 } 166 if (separator == ">=") { 167 expression_should_be_unknown(feature + " > = 0px"); 168 } else if (separator == "<=") { 169 expression_should_be_unknown(feature + " < = 0px"); 170 } 171 172 expression_should_be_known(feature + " " + separator + " -1px"); 173 if (separator == ":") { 174 expression_should_be_known("min-" + feature + " " + separator + " -1px"); 175 expression_should_be_known("max-" + feature + " " + separator + " -1px"); 176 } else { 177 expression_should_be_unknown("min-" + feature + " " + separator + " -1px"); 178 expression_should_be_unknown("max-" + feature + " " + separator + " -1px"); 179 } 180 expression_should_be_known(feature + " " + separator + " -0.00001mm"); 181 expression_should_be_known(feature + " " + separator + " -100000em"); 182 183 for (let separator2 of separators) { 184 // https://drafts.csswg.org/mediaqueries-4/#typedef-mf-range 185 if (separator[0] == separator2[0] && (separator[0] == '<' || separator[0] == '>')) { 186 expression_should_be_known(`0px ${separator} ${feature} ${separator2} 0px`); 187 } else { 188 expression_should_be_unknown(`0px ${separator} ${feature} ${separator2} 0px`); 189 } 190 } 191 } 192 } 193 194 var content_div = document.getElementById("content"); 195 content_div.style.font = "medium sans-serif"; 196 var em_size = 197 getComputedStyle(content_div, "").fontSize.match(/^(\d+)px$/)[1]; 198 199 // in this test, assume the common underlying implementation is correct 200 var width_val = 117; // pick two not-too-round numbers 201 var height_val = 76; 202 iframe_style.width = width_val + "px"; 203 iframe_style.height = height_val + "px"; 204 var device_width = window.screen.width; 205 var device_height = window.screen.height; 206 features = { 207 "width": width_val, 208 "height": height_val, 209 "device-width": device_width, 210 "device-height": device_height 211 }; 212 for (feature in features) { 213 var value = features[feature]; 214 should_apply("all and (" + feature + ": ${value}px)"); 215 should_apply("all and (" + feature + " = ${value}px)"); 216 should_not_apply("all and (" + feature + ": ${value + 1}px)"); 217 should_not_apply("all and (" + feature + ": ${value - 1}px)"); 218 should_not_apply("all and (" + feature + " = ${value + 1}px)"); 219 should_not_apply("all and (" + feature + " = ${value - 1}px)"); 220 221 should_apply("all and (min-" + feature + ": ${value}px)"); 222 should_not_apply("all and (min-" + feature + ": ${value + 1}px)"); 223 should_apply("all and (min-" + feature + ": ${value - 1}px)"); 224 should_apply("all and (max-" + feature + ": ${value}px)"); 225 should_apply("all and (max-" + feature + ": ${value + 1}px)"); 226 should_not_apply("all and (max-" + feature + ": ${value - 1}px)"); 227 should_not_apply("all and (min-" + feature + ": ${Math.ceil(value/em_size) + 1}em)"); 228 should_apply("all and (min-" + feature + ": ${Math.floor(value/em_size) - 1}em)"); 229 should_apply("all and (max-" + feature + ": ${Math.ceil(value/em_size) + 1}em)"); 230 should_not_apply("all and (max-" + feature + ": ${Math.floor(value/em_size) - 1}em)"); 231 232 should_apply("(" + feature + " <= ${value}px)"); 233 should_apply("(" + feature + " >= ${value}px)"); 234 235 should_apply("(0px < " + feature + " <= ${value}px)"); 236 should_apply("(${value}px >= " + feature + " > 0px)"); 237 238 should_not_apply("(0px < " + feature + " < ${value}px)"); 239 should_not_apply("(${value}px > " + feature + " > 0px)"); 240 241 should_not_apply("(" + feature + " < ${value}px)"); 242 should_not_apply("(" + feature + " > ${value}px)"); 243 244 should_apply("(" + feature + " < ${value + 1}px)"); 245 should_apply("(" + feature + " <= ${value + 1}px)"); 246 should_not_apply("(" + feature + " > ${value + 1}px)"); 247 should_not_apply("(" + feature + " >= ${value + 1}px)"); 248 249 should_apply("(" + feature + " > ${value - 1}px)"); 250 should_apply("(" + feature + " >= ${value - 1}px)"); 251 should_not_apply("(" + feature + " < ${value - 1}px)"); 252 should_not_apply("(" + feature + " <= ${value - 1}px)"); 253 254 should_apply("(${value - 1}px < " + feature + ")"); 255 should_apply("(${value - 1}px <= " + feature + ")"); 256 should_not_apply("(${value - 1}px > " + feature + ")"); 257 should_not_apply("(${value - 1}px >= " + feature + ")"); 258 259 should_apply("(${value - 1}px < " + feature + " < ${value + 1}px)"); 260 should_apply("(${value - 1}px < " + feature + " <= ${value}px)"); 261 should_apply("(${value}px <= " + feature + " < ${value + 1}px)"); 262 should_apply("(${value + 1}px > " + feature + " > ${value - 1}px)"); 263 should_apply("(${value + 1}px > " + feature + " >= ${value}px)"); 264 should_apply("(${value}px >= " + feature + " > ${value - 1}px)"); 265 should_not_apply("(${value}px > " + feature + " > ${value - 1}px)"); 266 should_not_apply("(${value + 1}px > " + feature + " > ${value}px)"); 267 } 268 269 iframe_style.width = "0"; 270 testGroup = "width = 0, height != 0"; 271 should_apply("all and (height)"); 272 should_not_apply("all and (width)"); 273 iframe_style.height = "0"; 274 testGroup = "width = 0, height = 0" 275 should_not_apply("all and (height)"); 276 should_not_apply("all and (width)"); 277 should_apply("all and (device-height)"); 278 should_apply("all and (device-width)"); 279 iframe_style.width = width_val + "px"; 280 testGroup = "width != 0, height = 0"; 281 should_not_apply("all and (height)"); 282 should_apply("all and (width)"); 283 iframe_style.height = height_val + "px"; 284 testGroup = "width != 0, height != 0"; 285 should_apply("all and (height)"); 286 should_apply("all and (width)"); 287 testGroup = ""; 288 289 testGroup = "ratio that reduces to 59/40"; 290 iframe_style.width = "236px"; 291 iframe_style.height = "160px"; 292 expression_should_be_known("orientation"); 293 expression_should_be_known("orientation: portrait"); 294 expression_should_be_known("orientation: landscape"); 295 expression_should_be_unknown("min-orientation"); 296 expression_should_be_unknown("min-orientation: portrait"); 297 expression_should_be_unknown("min-orientation: landscape"); 298 expression_should_be_unknown("max-orientation"); 299 expression_should_be_unknown("max-orientation: portrait"); 300 expression_should_be_unknown("max-orientation: landscape"); 301 should_apply("(orientation)"); 302 should_apply("(orientation: landscape)"); 303 should_not_apply("(orientation: portrait)"); 304 should_apply("not all and (orientation: portrait)"); 305 306 testGroup = "ratio that reduces to 59/80"; 307 iframe_style.height = "320px"; 308 should_apply("(orientation)"); 309 should_not_apply("(orientation: landscape)"); 310 should_apply("not all and (orientation: landscape)"); 311 should_apply("(orientation: portrait)"); 312 testGroup = ""; 313 314 should_apply("(aspect-ratio: 59/80)"); 315 should_not_apply("(aspect-ratio: 58/80)"); 316 should_not_apply("(aspect-ratio: 59/81)"); 317 should_not_apply("(aspect-ratio: 60/80)"); 318 should_not_apply("(aspect-ratio: 59/79)"); 319 should_apply("(aspect-ratio: 177/240)"); 320 should_apply("(aspect-ratio: 413/560)"); 321 should_apply("(aspect-ratio: 5900/8000)"); 322 should_not_apply("(aspect-ratio: 5901/8000)"); 323 should_not_apply("(aspect-ratio: 5899/8000)"); 324 should_not_apply("(aspect-ratio: 5900/8001)"); 325 should_not_apply("(aspect-ratio: 5900/7999)"); 326 should_apply("(aspect-ratio)"); 327 328 should_apply("(min-aspect-ratio: 59/80)"); 329 should_apply("(min-aspect-ratio: 58/80)"); 330 should_apply("(min-aspect-ratio: 59/81)"); 331 should_not_apply("(min-aspect-ratio: 60/80)"); 332 should_not_apply("(min-aspect-ratio: 59/79)"); 333 expression_should_be_unknown("min-aspect-ratio"); 334 335 should_apply("(max-aspect-ratio: 59/80)"); 336 should_not_apply("(max-aspect-ratio: 58/80)"); 337 should_not_apply("(max-aspect-ratio: 59/81)"); 338 should_apply("(max-aspect-ratio: 60/80)"); 339 should_apply("(max-aspect-ratio: 59/79)"); 340 expression_should_be_unknown("max-aspect-ratio"); 341 342 var real_dar = device_width + "/" + device_height; 343 var high_dar_1 = (device_width + 1) + "/" + device_height; 344 var high_dar_2 = device_width + "/" + (device_height - 1); 345 var low_dar_1 = (device_width - 1) + "/" + device_height; 346 var low_dar_2 = device_width + "/" + (device_height + 1); 347 should_apply("(device-aspect-ratio: ${real_dar})"); 348 should_apply("not all and (device-aspect-ratio: ${high_dar_1})"); 349 should_not_apply("all and (device-aspect-ratio: ${high_dar_2})"); 350 should_not_apply("all and (device-aspect-ratio: ${low_dar_1})"); 351 should_apply("not all and (device-aspect-ratio: ${low_dar_2})"); 352 should_apply("(device-aspect-ratio)"); 353 354 should_apply("(min-device-aspect-ratio: ${real_dar})"); 355 should_not_apply("all and (min-device-aspect-ratio: ${high_dar_1})"); 356 should_apply("not all and (min-device-aspect-ratio: ${high_dar_2})"); 357 should_not_apply("not all and (min-device-aspect-ratio: ${low_dar_1})"); 358 should_apply("all and (min-device-aspect-ratio: ${low_dar_2})"); 359 expression_should_be_unknown("min-device-aspect-ratio"); 360 361 should_apply("all and (max-device-aspect-ratio: ${real_dar})"); 362 should_apply("(max-device-aspect-ratio: ${high_dar_1})"); 363 should_apply("(max-device-aspect-ratio: ${high_dar_2})"); 364 should_not_apply("all and (max-device-aspect-ratio: ${low_dar_1})"); 365 should_apply("not all and (max-device-aspect-ratio: ${low_dar_2})"); 366 expression_should_be_unknown("max-device-aspect-ratio"); 367 368 features = [ "max-aspect-ratio", "device-aspect-ratio" ]; 369 for (i in features) { 370 feature = features[i]; 371 expression_should_be_known(feature + ": 1/1"); 372 expression_should_be_known(feature + ": 1 /1"); 373 expression_should_be_known(feature + ": 1 / \t\n1"); 374 expression_should_be_known(feature + ": 1/\r1"); 375 expression_should_be_known(feature + ": 1"); 376 expression_should_be_known(feature + ": 0.5"); 377 expression_should_be_known(feature + ": 1.0/1"); 378 expression_should_be_known(feature + ": 1/1.0"); 379 expression_should_be_known(feature + ": 1.0/1.0"); 380 expression_should_be_known(feature + ": 0/1"); 381 expression_should_be_known(feature + ": 1/0"); 382 expression_should_be_known(feature + ": 0/0"); 383 expression_should_be_unknown(feature + ": -1/1"); 384 expression_should_be_unknown(feature + ": 1/-1"); 385 expression_should_be_unknown(feature + ": -1/-1"); 386 expression_should_be_unknown(feature + ": invalid"); 387 expression_should_be_unknown(feature + ": 1 / invalid"); 388 expression_should_be_unknown(feature + ": 1 invalid"); 389 } 390 391 var is_monochrome = query_applies("all and (min-monochrome: 1)"); 392 var is_color = query_applies("all and (min-color: 1)"); 393 test(function() { 394 assert_not_equals(is_monochrome, is_color, "should be either monochrome or color"); 395 }, "monochrome_and_color"); 396 397 function depth_query(prefix, depth) { 398 return "all and (" + prefix + (is_color ? "color" : "monochrome") + 399 ":" + depth + ")"; 400 } 401 402 var depth = 0; 403 do { 404 if (depth > 50) { 405 break; 406 } 407 } while (query_applies(depth_query("min-", ++depth))); 408 test(function() { 409 assert_false(50 < depth); 410 }, "find_depth"); 411 --depth; 412 413 should_apply(depth_query("", depth)); 414 should_not_apply(depth_query("", depth - 1)); 415 should_not_apply(depth_query("", depth + 1)); 416 should_apply(depth_query("max-", depth)); 417 should_not_apply(depth_query("max-", depth - 1)); 418 should_apply(depth_query("max-", depth + 1)); 419 420 (is_color ? should_apply : should_not_apply)("all and (color)"); 421 expression_should_be_unknown("max-color"); 422 expression_should_be_unknown("min-color"); 423 (is_color ? should_not_apply : should_apply)("all and (monochrome)"); 424 expression_should_be_unknown("max-monochrome"); 425 expression_should_be_unknown("min-monochrome"); 426 (is_color ? should_apply : should_not_apply)("not all and (monochrome)"); 427 (is_color ? should_not_apply : should_apply)("not all and (color)"); 428 (is_color ? should_apply : should_not_apply)("only all and (color)"); 429 (is_color ? should_not_apply : should_apply)("only all and (monochrome)"); 430 431 features = [ "color", "min-monochrome", "max-color-index" ]; 432 for (i in features) { 433 feature = features[i]; 434 expression_should_be_known(feature + ": 1"); 435 expression_should_be_known(feature + ": 327"); 436 expression_should_be_known(feature + ": 0"); 437 expression_should_be_unknown(feature + ": 1.0"); 438 expression_should_be_known(feature + ": -1"); 439 expression_should_be_unknown(feature + ": 1/1"); 440 } 441 442 // Presume that we never support indexed color (at least not usefully 443 // enough to call it indexed color). 444 should_apply("(color-index: 0)"); 445 should_not_apply("(color-index: 1)"); 446 should_apply("(min-color-index: 0)"); 447 should_not_apply("(min-color-index: 1)"); 448 should_apply("(max-color-index: 0)"); 449 should_apply("(max-color-index: 1)"); 450 should_apply("(max-color-index: 157)"); 451 452 features = [ "resolution", "min-resolution", "max-resolution" ]; 453 for (i in features) { 454 feature = features[i]; 455 expression_should_be_known(feature + ": 3dpi"); 456 expression_should_be_known(feature + ":3dpi"); 457 expression_should_be_known(feature + ": 3.0dpi"); 458 expression_should_be_known(feature + ": 3.4dpi"); 459 expression_should_be_known(feature + "\t: 120dpcm"); 460 expression_should_be_known(feature + ": 1dppx"); 461 expression_should_be_known(feature + ": 1x"); 462 expression_should_be_known(feature + ": 1.5dppx"); 463 expression_should_be_known(feature + ": 1.5x"); 464 expression_should_be_known(feature + ": 2.0dppx"); 465 expression_should_be_known(feature + ": 0dpi"); 466 expression_should_be_known(feature + ": 0dppx"); 467 expression_should_be_known(feature + ": 0x"); 468 expression_should_be_known(feature + ": calc(6x / 2)"); 469 expression_should_be_unknown(feature + ": -3dpi"); 470 } 471 472 // Find the resolution using max-resolution 473 var resolution = 0; 474 do { 475 ++resolution; 476 if (resolution > 10000) { 477 break; 478 } 479 } while (!query_applies("(max-resolution: " + resolution + "dpi)")); 480 test(function() { 481 assert_false(10000 < resolution); 482 }, "find_resolution"); 483 484 // resolution should now be Math.ceil() of the actual resolution. 485 var dpi_high; 486 var dpi_low = resolution - 1; 487 if (query_applies(`(min-resolution: ${resolution}dpi)`)) { // query_applies, so template literal! 488 // It's exact! 489 testGroup = "resolution is exact"; 490 should_apply("(resolution: ${resolution}dpi)"); 491 should_apply("(resolution: ${Math.floor(resolution/96)}dppx)"); 492 should_apply("(resolution: ${Math.floor(resolution/96)}x)"); 493 should_not_apply("(resolution: ${resolution + 1}dpi)"); 494 should_not_apply("(resolution: ${resolution - 1}dpi)"); 495 dpi_high = resolution + 1; 496 } else { 497 // We have no way to test resolution applying since it need not be 498 // an integer. 499 testGroup = "resolution is inexact"; 500 should_not_apply("(resolution: ${resolution}dpi)"); 501 should_not_apply("(resolution: ${resolution - 1}dpi)"); 502 dpi_high = resolution; 503 } 504 testGroup = ""; 505 506 should_apply("(min-resolution: ${dpi_low}dpi)"); 507 should_not_apply("not all and (min-resolution: ${dpi_low}dpi)"); 508 should_apply("not all and (min-resolution: ${dpi_high}dpi)"); 509 should_not_apply("all and (min-resolution: ${dpi_high}dpi)"); 510 511 // Test dpcm units based on what we computed in dpi. 512 var dpcm_high = Math.ceil(dpi_high / 2.54); 513 var dpcm_low = Math.floor(dpi_low / 2.54); 514 should_apply("(min-resolution: ${dpcm_low}dpcm)"); 515 should_apply("(max-resolution: ${dpcm_high}dpcm)"); 516 should_not_apply("(max-resolution: ${dpcm_low}dpcm)"); 517 should_apply("not all and (min-resolution: ${dpcm_high}dpcm)"); 518 519 expression_should_be_known("scan"); 520 expression_should_be_known("scan: progressive"); 521 expression_should_be_known("scan:interlace"); 522 expression_should_be_unknown("min-scan:interlace"); 523 expression_should_be_unknown("scan: 1"); 524 expression_should_be_unknown("max-scan"); 525 expression_should_be_unknown("max-scan: progressive"); 526 // Assume we don't support tv devices. 527 should_not_apply("(scan)"); 528 should_not_apply("(scan: progressive)"); 529 should_not_apply("(scan: interlace)"); 530 should_apply("not all and (scan)"); 531 should_apply("not all and (scan: progressive)"); 532 should_apply("not all and (scan: interlace)"); 533 534 expression_should_be_known("grid"); 535 expression_should_be_known("grid: 0"); 536 expression_should_be_known("grid: 1"); 537 expression_should_be_unknown("min-grid"); 538 expression_should_be_unknown("min-grid:0"); 539 expression_should_be_unknown("max-grid: 1"); 540 expression_should_be_unknown("grid: 2"); 541 expression_should_be_unknown("grid: -1"); 542 543 // Assume we don't support grid devices 544 should_not_apply("(grid)"); 545 should_apply("(grid: 0)"); 546 should_not_apply("(grid: 1)"); 547 should_not_apply("(grid: 2)"); 548 should_not_apply("(grid: -1)"); 549 550 // Parsing tests 551 // bug 454227 552 should_apply("(orientation"); 553 should_not_apply("not all and (orientation"); 554 should_not_apply("(orientation:"); 555 should_not_apply("(orientation:)"); 556 should_not_apply("(orientation: )"); 557 should_apply("all,(orientation:"); 558 should_not_apply("(orientation:,all"); 559 should_apply("not all and (grid"); 560 should_not_apply("only all and (grid"); 561 should_not_apply("(grid"); 562 should_apply("all,(grid"); 563 should_not_apply("(grid,all"); 564 // bug 454226 565 should_apply(",all"); 566 should_apply("all,"); 567 should_apply(",all,"); 568 should_apply("all,badmedium"); 569 should_apply("badmedium,all"); 570 should_not_apply(",badmedium,"); 571 should_apply("all,(badexpression)"); 572 should_apply("(badexpression),all"); 573 should_not_apply("(badexpression),badmedium"); 574 should_not_apply("badmedium,(badexpression)"); 575 should_apply("all,[badsyntax]"); 576 should_apply("[badsyntax],all"); 577 should_not_apply("badmedium,[badsyntax]"); 578 should_not_apply("[badsyntax],badmedium"); 579 580 // Parsing tests based on Acid3 581 query_should_not_be_parseable("all and color :"); 582 query_should_not_be_parseable("all and color : 1"); 583 should_not_apply("all and min-color : 1"); 584 should_not_apply("(bogus)"); 585 should_not_apply("not all and (bogus)") 586 should_not_apply("only all and (bogus)") 587 588 // Parsing tests for overflow-block from mediaqueries-4 589 expression_should_be_known("overflow-block") 590 expression_should_be_known("overflow-block: none") 591 expression_should_be_known("overflow-block: paged") 592 expression_should_be_known("overflow-block: scroll") 593 expression_should_be_unknown("overflow-block: optional-paged") 594 expression_should_be_unknown("overflow-block: some-random-invalid-thing") 595 596 // Sanity check for overflow-block 597 test(function() { 598 var any_overflow_block = query_applies("(overflow-block)"); 599 var overflow_block_none = query_applies("(overflow-block: none)"); 600 assert_not_equals(any_overflow_block, overflow_block_none, "overflow-block should be equivalent to not (overflow-block: none)"); 601 }, "Sanity check for overflow-block"); 602 603 // Parsing tests for overflow-inline from mediaqueries-4 604 expression_should_be_known("overflow-inline") 605 expression_should_be_known("overflow-inline: none") 606 expression_should_be_known("overflow-inline: scroll") 607 expression_should_be_unknown("overflow-inline: some-random-invalid-thing") 608 609 // Sanity check for overflow-inline 610 test(function() { 611 var any_overflow_inline = query_applies("(overflow-inline)"); 612 var overflow_inline_none = query_applies("(overflow-inline: none)"); 613 assert_not_equals(any_overflow_inline, overflow_inline_none, "overflow-inline should be equivalent to not (overflow-inline: none)"); 614 }, "Sanity check for overflow-inline"); 615 616 // Parsing tests for update from mediaqueries-4 617 expression_should_be_known("update") 618 expression_should_be_known("update: none") 619 expression_should_be_known("update: slow") 620 expression_should_be_known("update: fast") 621 expression_should_be_unknown("update: some-random-invalid-thing") 622 623 // Sanity check for update 624 test(function() { 625 var any_update = query_applies("(update)"); 626 var update_none = query_applies("(update: none)"); 627 assert_not_equals(any_update, update_none, "update should be equivalent to not (update: none)"); 628 }, "Sanity check for update"); 629 630 // Parsing tests for interaction media features. 631 expression_should_be_known("hover") 632 expression_should_be_known("hover: hover") 633 expression_should_be_known("hover: none") 634 expression_should_be_known("any-hover") 635 expression_should_be_known("any-hover: hover") 636 expression_should_be_known("any-hover: none") 637 638 test(function() { 639 assert_equals(query_applies("(hover)"), query_applies("(hover: hover)")); 640 } , "(hover) == (hover: hover)"); 641 642 test(function() { 643 assert_not_equals(query_applies("(hover)"), query_applies("(hover: none)")); 644 }, "(hover) == not (hover: none)"); 645 646 test(function() { 647 assert_equals(query_applies("(any-hover)"), query_applies("(any-hover: hover)")); 648 }, "(any-hover) == (any-hover: hover)"); 649 650 test(function() { 651 assert_not_equals(query_applies("(any-hover)"), query_applies("(any-hover: none)")); 652 }, "(any-hover) == not (any-hover: none)"); 653 654 expression_should_be_known("pointer") 655 expression_should_be_known("pointer: coarse") 656 expression_should_be_known("pointer: fine") 657 expression_should_be_known("pointer: none") 658 expression_should_be_known("any-pointer") 659 expression_should_be_known("any-pointer: coarse") 660 expression_should_be_known("any-pointer: fine") 661 expression_should_be_known("any-pointer: none") 662 663 test(function() { 664 assert_equals(query_applies("(pointer)"), 665 query_applies("(pointer: coarse)") || query_applies("(pointer: fine)")); 666 }, "(pointer) == (pointer: coarse) or (pointer: fine)"); 667 668 test(function() { 669 assert_not_equals(query_applies("(pointer)"), 670 query_applies("(pointer: none)")); 671 }, "(pointer) == not (pointer: none)"); 672 673 test(function() { 674 assert_equals(query_applies("(any-pointer)"), 675 query_applies("(any-pointer: coarse)") || query_applies("(any-pointer: fine)")); 676 }, "(any-pointer) == (any-pointer: coarse) or (any-pointer: fine)"); 677 678 test(function() { 679 assert_not_equals(query_applies("(any-pointer)"), 680 query_applies("(any-pointer: none)")); 681 }, "(any-pointer) == not (any-pointer: none)"); 682 683 iframe_style.width = '100px'; 684 iframe_style.height = '0px'; 685 686 testGroup = "'or' keyword" 687 should_not_apply("(height) or (height)"); 688 should_apply("(width) or (height)"); 689 should_apply("(height) or (width)"); 690 should_apply("(height) or (width) or (height)"); 691 query_should_not_be_parseable("screen or (width)"); 692 query_should_not_be_parseable("screen and (width) or (height)"); 693 694 testGroup = "nesting" 695 should_not_apply("((height))"); 696 should_apply("((width))"); 697 should_apply("(((((width)))))"); 698 should_apply("(((((width"); 699 700 testGroup = "'not' keyword" 701 should_not_apply("not (width)"); 702 should_apply("not (height)"); 703 should_apply("not ((width) and (height))"); 704 should_not_apply("not ((width) or (height))"); 705 should_not_apply("not ((width) and (not (height)))"); 706 query_should_not_be_parseable("not (width) and not (height)"); 707 query_should_not_be_parseable("not not (width)"); 708 query_should_be_parseable("not unknown(width) "); 709 710 testGroup = "three-valued logic" 711 should_not_apply("(unknown)"); 712 should_not_apply("not (unknown)"); 713 should_not_apply("((unknown) and (width))"); 714 should_not_apply("not ((unknown) and (width))"); 715 should_not_apply("((unknown) and (height))"); 716 should_apply("not ((unknown) and (height))"); 717 should_apply("((unknown) or (width))"); 718 should_not_apply("not ((unknown) or (width))"); 719 should_not_apply("((unknown) or (height))"); 720 should_not_apply("not ((unknown) or (height))"); 721 should_apply("(width) or (not ((unknown) and (width)))"); 722 should_not_apply("(width) and (not ((unknown) and (width)))"); 723 should_apply("(width) or (not ((unknown) or (width)))"); 724 should_not_apply("(width) and (not ((unknown) or (width)))"); 725 should_apply("(width) or (not ((unknown) and (height)))"); 726 should_apply("(width) and (not ((unknown) and (height)))"); 727 should_apply("(width) or (not ((unknown) or (height)))"); 728 should_not_apply("(width) and (not ((unknown) or (height)))"); 729 should_not_apply("unknown(width)"); 730 should_not_apply("not unknown(width)"); 731 should_apply("not (unknown(width) and (height))"); 732 should_not_apply("not (unknown(width) or (height))"); 733 734 testGroup = "" 735 done(); 736 } 737 738 </script> 739 </body> 740 </html>