Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
michael@0 | 1 | <!DOCTYPE HTML> |
michael@0 | 2 | <html> |
michael@0 | 3 | <!-- |
michael@0 | 4 | https://bugzilla.mozilla.org/show_bug.cgi?id=816720 |
michael@0 | 5 | --> |
michael@0 | 6 | <head> |
michael@0 | 7 | <title>Test for Bug 816720</title> |
michael@0 | 8 | <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
michael@0 | 9 | <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> |
michael@0 | 10 | <style type="text/css" id="style"></style> |
michael@0 | 11 | </head> |
michael@0 | 12 | <body> |
michael@0 | 13 | |
michael@0 | 14 | <pre id="test"></pre> |
michael@0 | 15 | |
michael@0 | 16 | <p><span id=control-serif>........</span></p> |
michael@0 | 17 | <p><span id=control-monospace>........</span></p> |
michael@0 | 18 | <p><span id=test-font>........</span></p> |
michael@0 | 19 | |
michael@0 | 20 | <style id=other-styles> |
michael@0 | 21 | #test { font-size: 16px; animation: test 1s both } |
michael@0 | 22 | #control-serif { font: 16px serif } |
michael@0 | 23 | #test-font { font: 16px UnlikelyFontName, serif } |
michael@0 | 24 | </style> |
michael@0 | 25 | |
michael@0 | 26 | <script type="application/javascript"> |
michael@0 | 27 | |
michael@0 | 28 | // Monospace fonts available on all the platforms we're testing on. |
michael@0 | 29 | // |
michael@0 | 30 | // XXX Once bug 817220 is fixed we could instead use the value of |
michael@0 | 31 | // font.name.monospace.x-western as the monospace font to use. |
michael@0 | 32 | var MONOSPACE_FONTS = [ |
michael@0 | 33 | "Courier", |
michael@0 | 34 | "Courier New", |
michael@0 | 35 | "Monaco", |
michael@0 | 36 | "DejaVu Sans Mono", |
michael@0 | 37 | "Droid Sans Mono" |
michael@0 | 38 | ]; |
michael@0 | 39 | |
michael@0 | 40 | var test = document.getElementById("test"); |
michael@0 | 41 | var controlSerif = document.getElementById("control-serif"); |
michael@0 | 42 | var controlMonospace = document.getElementById("control-monospace"); |
michael@0 | 43 | var testFont = document.getElementById("test-font"); |
michael@0 | 44 | var otherStyles = document.getElementById("other-styles"); |
michael@0 | 45 | |
michael@0 | 46 | otherStyles.sheet.insertRule("#control-monospace { font: 16px " + |
michael@0 | 47 | MONOSPACE_FONTS + ", serif }", 0); |
michael@0 | 48 | |
michael@0 | 49 | var monospaceWidth = controlMonospace.getBoundingClientRect().width; |
michael@0 | 50 | var serifWidth = controlSerif.getBoundingClientRect().width; |
michael@0 | 51 | |
michael@0 | 52 | // [at-rule type, passing condition, failing condition] |
michael@0 | 53 | var outerRuleInfo = [ |
michael@0 | 54 | ["@media", "all", "not all"], |
michael@0 | 55 | ["@-moz-document", "url-prefix('')", "url-prefix('zzz')"], |
michael@0 | 56 | ["@supports", "(color: green)", "(unknown: unknown)"] |
michael@0 | 57 | ]; |
michael@0 | 58 | |
michael@0 | 59 | // [rule, function to test whether the rule was successfully inserted and applied] |
michael@0 | 60 | var innerRuleInfo = [ |
michael@0 | 61 | ["#test { text-decoration: underline; }", |
michael@0 | 62 | function(aApplied, aParent, aException) { |
michael@0 | 63 | return !aException && |
michael@0 | 64 | window.getComputedStyle(test, "").textDecoration == |
michael@0 | 65 | (aApplied ? "underline" : "none"); |
michael@0 | 66 | }], |
michael@0 | 67 | ["@page { margin: 4cm; }", |
michael@0 | 68 | function(aApplied, aParent, aException) { |
michael@0 | 69 | // just test whether it threw |
michael@0 | 70 | return !aException; |
michael@0 | 71 | }], |
michael@0 | 72 | ["@keyframes test { from { font-size: 100px; } to { font-size: 100px; } }", |
michael@0 | 73 | function(aApplied, aParent, aException) { |
michael@0 | 74 | return !aException && |
michael@0 | 75 | window.getComputedStyle(test, "").fontSize == |
michael@0 | 76 | (aApplied ? "100px" : "16px") |
michael@0 | 77 | }], |
michael@0 | 78 | ["@font-face { font-family: UnlikelyFontName; src: " + |
michael@0 | 79 | MONOSPACE_FONTS.map(function(s) { return "local('" + s + "')" }).join(", ") + "; }", |
michael@0 | 80 | function(aApplied, aParent, aException) { |
michael@0 | 81 | var width = testFont.getBoundingClientRect().width; |
michael@0 | 82 | if (aException) { |
michael@0 | 83 | return false; |
michael@0 | 84 | } |
michael@0 | 85 | if (navigator.oscpu.match(/Linux/) || |
michael@0 | 86 | navigator.oscpu.match(/Android/) || |
michael@0 | 87 | SpecialPowers.Services.appinfo.name == "B2G") { |
michael@0 | 88 | return true; |
michael@0 | 89 | } |
michael@0 | 90 | return Math.abs(width - (aApplied ? monospaceWidth : serifWidth)) <= 1; // bug 769194 prevents local() |
michael@0 | 91 | // fonts working on Android |
michael@0 | 92 | }], |
michael@0 | 93 | ["@charset 'UTF-8';", |
michael@0 | 94 | function(aApplied, aParent, aException) { |
michael@0 | 95 | // just test whether it threw |
michael@0 | 96 | return aParent instanceof CSSRule ? aException : !aException; |
michael@0 | 97 | }], |
michael@0 | 98 | ["@import url(nothing.css);", |
michael@0 | 99 | function(aApplied, aParent, aException) { |
michael@0 | 100 | // just test whether it threw |
michael@0 | 101 | return aParent instanceof CSSRule ? aException : !aException; |
michael@0 | 102 | }], |
michael@0 | 103 | ["@namespace test url(http://example.org);", |
michael@0 | 104 | function(aApplied, aParent, aException) { |
michael@0 | 105 | // just test whether it threw |
michael@0 | 106 | return aParent instanceof CSSRule ? aException : !aException; |
michael@0 | 107 | }], |
michael@0 | 108 | ]; |
michael@0 | 109 | |
michael@0 | 110 | function runTest() |
michael@0 | 111 | { |
michael@0 | 112 | // First, assert that our assumed available fonts are indeed available |
michael@0 | 113 | // and have expected metrics. |
michael@0 | 114 | ok(monospaceWidth > 0, "monospace text has width"); |
michael@0 | 115 | ok(serifWidth > 0, "serif text has width"); |
michael@0 | 116 | ok(Math.abs(monospaceWidth - serifWidth) > 1, "monospace and serif text have sufficiently different widths"); |
michael@0 | 117 | |
michael@0 | 118 | // And that the #test-font element starts off using the "serif" font. |
michael@0 | 119 | var initialFontTestWidth = testFont.getBoundingClientRect().width; |
michael@0 | 120 | is(initialFontTestWidth, serifWidth); |
michael@0 | 121 | |
michael@0 | 122 | // We construct a style sheet with zero, one or two levels of conditional |
michael@0 | 123 | // grouping rules (taken from outerRuleInfo), with one of the inner rules |
michael@0 | 124 | // at the deepest level. |
michael@0 | 125 | var style = document.getElementById("style"); |
michael@0 | 126 | |
michael@0 | 127 | // For each of the outer rule types... |
michael@0 | 128 | for (var outerRule1 = 0; outerRule1 < outerRuleInfo.length; outerRule1++) { |
michael@0 | 129 | // For each of { 0 = don't create an outer rule, |
michael@0 | 130 | // 1 = create an outer rule with a passing condition, |
michael@0 | 131 | // 2 = create an outer rule with a failing condition }... |
michael@0 | 132 | for (var outerRuleCondition1 = 0; outerRuleCondition1 <= 2; outerRuleCondition1++) { |
michael@0 | 133 | |
michael@0 | 134 | // For each of the outer rule types again... |
michael@0 | 135 | for (var outerRule2 = 0; outerRule2 < outerRuleInfo.length; outerRule2++) { |
michael@0 | 136 | // For each of { 0 = don't create an outer rule, |
michael@0 | 137 | // 1 = create an outer rule with a passing condition, |
michael@0 | 138 | // 2 = create an outer rule with a failing condition } again... |
michael@0 | 139 | for (var outerRuleCondition2 = 0; outerRuleCondition2 <= 2; outerRuleCondition2++) { |
michael@0 | 140 | |
michael@0 | 141 | // For each of the inner rule types... |
michael@0 | 142 | for (var innerRule = 0; innerRule < innerRuleInfo.length; innerRule++) { |
michael@0 | 143 | |
michael@0 | 144 | // Clear rules |
michael@0 | 145 | var object = style.sheet; |
michael@0 | 146 | while (object.cssRules.length) { |
michael@0 | 147 | object.deleteRule(0); |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | // We'll record whether the inner rule should have been applied, |
michael@0 | 151 | // according to whether we put passing or failing conditional |
michael@0 | 152 | // grouping rules around it. |
michael@0 | 153 | var applied = true; |
michael@0 | 154 | |
michael@0 | 155 | if (outerRuleCondition1) { |
michael@0 | 156 | // Create an outer conditional rule. |
michael@0 | 157 | object.insertRule([outerRuleInfo[outerRule1][0], |
michael@0 | 158 | outerRuleInfo[outerRule1][outerRuleCondition1], |
michael@0 | 159 | "{}"].join(" "), 0); |
michael@0 | 160 | object = object.cssRules[0]; |
michael@0 | 161 | |
michael@0 | 162 | if (outerRuleCondition1 == 2) { |
michael@0 | 163 | // If we used a failing condition, we don't expect the inner |
michael@0 | 164 | // rule to be applied. |
michael@0 | 165 | applied = false; |
michael@0 | 166 | } |
michael@0 | 167 | } |
michael@0 | 168 | |
michael@0 | 169 | if (outerRuleCondition2) { |
michael@0 | 170 | // Create another outer conditional rule as a child of the first |
michael@0 | 171 | // outer conditional rule (or the style sheet, if we didn't create |
michael@0 | 172 | // a first outer conditional rule). |
michael@0 | 173 | object.insertRule([outerRuleInfo[outerRule2][0], |
michael@0 | 174 | outerRuleInfo[outerRule2][outerRuleCondition2], |
michael@0 | 175 | "{}"].join(" "), 0); |
michael@0 | 176 | object = object.cssRules[0]; |
michael@0 | 177 | |
michael@0 | 178 | if (outerRuleCondition2 == 2) { |
michael@0 | 179 | // If we used a failing condition, we don't expect the inner |
michael@0 | 180 | // rule to be applied. |
michael@0 | 181 | applied = false; |
michael@0 | 182 | } |
michael@0 | 183 | } |
michael@0 | 184 | |
michael@0 | 185 | var outer = object instanceof CSSRule ? object.cssText : "style sheet"; |
michael@0 | 186 | var inner = innerRuleInfo[innerRule][0]; |
michael@0 | 187 | |
michael@0 | 188 | // Insert the inner rule. |
michael@0 | 189 | var exception = null; |
michael@0 | 190 | try { |
michael@0 | 191 | object.insertRule(inner, 0); |
michael@0 | 192 | } catch (e) { |
michael@0 | 193 | exception = e; |
michael@0 | 194 | } |
michael@0 | 195 | |
michael@0 | 196 | ok(innerRuleInfo[innerRule][1](applied, object, exception), |
michael@0 | 197 | "<" + [outerRule1, outerRuleCondition1, outerRule2, |
michael@0 | 198 | outerRuleCondition2, innerRule].join(",") + "> " + |
michael@0 | 199 | "inserting " + inner + " into " + outer.replace(/ *\n */g, ' ')); |
michael@0 | 200 | } |
michael@0 | 201 | } |
michael@0 | 202 | } |
michael@0 | 203 | } |
michael@0 | 204 | } |
michael@0 | 205 | |
michael@0 | 206 | SimpleTest.finish(); |
michael@0 | 207 | } |
michael@0 | 208 | |
michael@0 | 209 | SimpleTest.waitForExplicitFinish(); |
michael@0 | 210 | SpecialPowers.pushPrefEnv({ "set": [["layout.css.supports-rule.enabled", true]] }, runTest); |
michael@0 | 211 | |
michael@0 | 212 | </script> |
michael@0 | 213 | </body> |
michael@0 | 214 | </html> |