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