test_media_queries.html 37 KB

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