Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / layout / style / test / test_value_storage.html
bloba5ee652be11cb5c8f82f7d16f16cabedda7c6150
1 <!DOCTYPE HTML>
2 <html>
3 <!--
4 -->
5 <head>
6 <title>Test for parsing, storage, and serialization of CSS values</title>
7 <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
8 <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
9 <script type="text/javascript" src="property_database.js"></script>
10 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
11 </head>
12 <body>
13 <p id="display"></p>
14 <div id="content" style="display: none">
16 <div id="testnode"></div>
18 </div>
19 <pre id="test">
20 <script class="testbody" type="text/javascript">
22 /** Test for parsing, storage, and serialization of CSS values **/
25 * The idempotence tests here deserve a little bit of explanation. What
26 * we're testing here are the following operations:
27 * parse: string -> CSS rule
28 * serialize: CSS rule -> string (normalization 1)
29 * (this actually has two variants that go through partly different
30 * codepaths, which we exercise with getPropertyValue and cssText)
31 * compute: CSS rule -> computed style
32 * cserialize: computed style -> string (normalization 2)
34 * Both serialize and cserialize do some normalization, so we can't test
35 * for pure round-tripping, and we also can't compare their output since
36 * they could normalize differently. (We might at some point in the
37 * future want to guarantee that any output of cserialize is
38 * untouched by going through parse+serialize, though.)
40 * So we test idempotence of parse + serialize by running the whole
41 * operation twice. Likewise for parse + compute + cserialize.
43 * Slightly more interestingly, we test that serialize + parse is the
44 * identity transform by comparing the output of parse + compute +
45 * cserialize to the output of parse + serialize + parse + compute +
46 * cserialize.
49 var gShorthandsWithoutCondensingSerialize = {
50 "-moz-border-radius": true,
51 "-moz-outline-radius": true,
52 "background": true, // really there, but not complete
53 "cue": true,
54 "font": true,
55 "list-style": true,
56 "outline": true,
57 "pause": true,
60 var gNotAccepted = {
61 "-moz-column-width": [ "50%" ],
62 "list-style": [ "none disc outside" ],
65 var gSystemFont = {
66 "caption": true,
67 "icon": true,
68 "menu": true,
69 "message-box": true,
70 "small-caption": true,
71 "status-bar": true,
74 var gBadCompute = {
75 // output wrapped around to positive, in exponential notation
76 "-moz-box-ordinal-group": [ "-1", "-1000" ],
79 var gShortenableValues = {
80 "border-color": [ "currentColor currentColor currentcolor CURRENTcolor" ],
81 "border-style": [ "none none none none", "groove none none none", "none none double none" ],
84 function xfail_accepted(property, value)
86 if (property in gNotAccepted &&
87 gNotAccepted[property].indexOf(value) != -1)
88 return true;
90 return false;
93 function xfail_accepted_split(property, subprop, value)
95 if (property in gNotAccepted &&
96 gNotAccepted[property].indexOf(value) != -1)
97 return true;
99 return false;
102 function xfail_ser_val(property, value)
104 if (property != "font" && xfail_accepted(property, value))
105 // We already failed the first test, which will make us always pass this
106 // one.
107 return false;
109 if (property in gShorthandsWithoutCondensingSerialize)
110 return true;
112 // We output unneeded -moz-use-text-color only in the value getter and
113 // not the serialization.
114 // XXXbz is there any way we could actually filter for that, so that colors
115 // other than green could be used in the property database here?
116 if ((property.match(/^border(|-bottom|-left|-right|-top)$/) ||
117 property.match(/^-moz-border(|-start|-end)$/)) &&
118 !value.match(/(green|currentcolor)/i))
119 return true;
121 // We condense multiple values in the serialization, but not in the
122 // value getter.
123 if (property.match(/^(border-(color|style|width)|margin|padding)$/) &&
124 value.split(" ").length != 4)
125 return true;
126 if (property in gShortenableValues &&
127 gShortenableValues[property].indexOf(value) != -1)
128 return true;
130 return false;
133 function xfail_idparseser(property, value)
135 if (property != "font" && xfail_accepted(property, value))
136 // We already failed the first test, which will make us always pass this
137 // one.
138 return false;
140 return false;
143 function xfail_idserparse_compute(property, value)
145 return false;
148 function xfail_idsersplitparse_compute(property, subprop, value, step1subcomp)
150 return false;
153 function xfail_idparsesplitser(property, value)
155 return false;
158 function xfail_compute(property, value)
160 if (property in gBadCompute &&
161 gBadCompute[property].indexOf(value) != -1)
162 return true;
164 return false;
167 function xfail_split_compute(property, value)
169 return false;
172 var gElement = document.getElementById("testnode");
173 var gDeclaration = gElement.style;
174 var gComputedStyle = window.getComputedStyle(gElement, "");
176 function test_property(property)
178 var info = gCSSProperties[property];
180 var test_computed = !("backend_only" in info);
182 function test_value(value) {
183 gDeclaration.setProperty(property, value, "");
185 var idx, func;
187 var step1val = gDeclaration.getPropertyValue(property);
188 var step1vals = [];
189 var step1ser = gDeclaration.cssText;
190 if ("subproperties" in info)
191 for (idx in info.subproperties)
192 step1vals.push(gDeclaration.getPropertyValue(info.subproperties[idx]));
193 var step1comp;
194 var step1comps = [];
195 if (test_computed && info.type != CSS_TYPE_TRUE_SHORTHAND)
196 step1comp = gComputedStyle.getPropertyValue(property);
197 if (test_computed && "subproperties" in info)
198 for (idx in info.subproperties)
199 step1comps.push(gComputedStyle.getPropertyValue(info.subproperties[idx]));
201 func = xfail_accepted(property, value) ? todo_isnot : isnot;
202 func(step1val, "", "setting '" + value + "' on '" + property + "'");
203 if ("subproperties" in info)
204 for (idx in info.subproperties) {
205 var subprop = info.subproperties[idx];
206 func = xfail_accepted_split(property, subprop, value)
207 ? todo_isnot : isnot;
208 func(gDeclaration.getPropertyValue(subprop), "",
209 "setting '" + value + "' on '" + property + "'");
212 // We don't care particularly about the whitespace or the placement of
213 // semicolons, but for simplicity we'll test the current behavior.
214 func = xfail_ser_val(property, value) ? todo_is : is;
215 var expected_serialization = "";
216 if (step1val != "")
217 expected_serialization = property + ": " + step1val + ";";
218 func(step1ser, expected_serialization,
219 "serialization should match property value");
221 gDeclaration.removeProperty(property);
222 gDeclaration.setProperty(property, step1val, "");
224 func = xfail_idparseser(property, value) ? todo_is : is;
225 func(gDeclaration.getPropertyValue(property), step1val,
226 "parse+serialize should be idempotent for '" +
227 property + ": " + value + "'");
228 if (test_computed && info.type != CSS_TYPE_TRUE_SHORTHAND) {
229 func = xfail_idserparse_compute(property, value) ? todo_is : is;
230 func(gComputedStyle.getPropertyValue(property), step1comp,
231 "serialize+parse should be identity transform for '" +
232 property + ": " + value + "'");
235 if ("subproperties" in info &&
236 // Using setProperty over subproperties is not sufficient for
237 // system fonts, since the shorthand does more than its parts.
238 (property != "font" || !(value in gSystemFont))) {
239 gDeclaration.removeProperty(property);
240 for (idx in info.subproperties) {
241 var subprop = info.subproperties[idx];
242 gDeclaration.setProperty(subprop, step1vals[idx], "");
245 // Now that all the subprops are set, check their values. Note that we
246 // need this in a separate loop, in case parts of the shorthand affect
247 // the computed values of other parts.
248 for (idx in info.subproperties) {
249 var subprop = info.subproperties[idx];
250 if (test_computed && !("backend_only" in gCSSProperties[subprop])) {
251 func =
252 xfail_idsersplitparse_compute(property, subprop, value, step1comps[idx])
253 ? todo_is : is;
254 func(gComputedStyle.getPropertyValue(subprop), step1comps[idx],
255 "serialize(" + subprop + ")+parse should be the identity " +
256 "transform for '" + property + ": " + value + "'");
259 func = xfail_idparsesplitser(property, value) ? todo_is : is;
260 func(gDeclaration.getPropertyValue(property), step1val,
261 "parse+split+serialize should be idempotent for '" +
262 property + ": " + value + "'");
265 if (test_computed && info.type != CSS_TYPE_TRUE_SHORTHAND) {
266 gDeclaration.removeProperty(property);
267 gDeclaration.setProperty(property, step1comp, "");
268 func = xfail_compute(property, value) ? todo_is : is;
269 func(gComputedStyle.getPropertyValue(property), step1comp,
270 "parse+compute+serialize should be idempotent for '" +
271 property + ": " + value + "'");
273 if (test_computed && "subproperties" in info) {
274 gDeclaration.removeProperty(property);
275 for (idx in info.subproperties) {
276 var subprop = info.subproperties[idx];
277 if ("backend_only" in gCSSProperties[subprop])
278 continue;
279 gDeclaration.setProperty(subprop, step1comps[idx], "");
282 // Now that all the subprops are set, check their values. Note that we
283 // need this in a separate loop, in case parts of the shorthand affect
284 // the computed values of other parts.
285 func = xfail_split_compute(property, value) ? todo_is : is;
286 for (idx in info.subproperties) {
287 var subprop = info.subproperties[idx];
288 if ("backend_only" in gCSSProperties[subprop])
289 continue;
290 func(gComputedStyle.getPropertyValue(subprop), step1comps[idx],
291 "parse+compute+serialize(" + subprop + ") should be idempotent for '" +
292 property + ": " + value + "'");
296 gDeclaration.removeProperty(property);
299 var idx;
300 for (idx in info.initial_values)
301 test_value(info.initial_values[idx]);
302 for (idx in info.other_values)
303 test_value(info.other_values[idx]);
306 // To avoid triggering the slow script dialog, we have to test one
307 // property at a time.
308 SimpleTest.waitForExplicitFinish();
309 var props = [];
310 for (var prop in gCSSProperties)
311 props.push(prop);
312 props = props.reverse();
313 function do_one(l) {
314 if (l.length == 0) {
315 // SimpleTest.finish() is really slow, so we have to disable the
316 // slow script dialog for this part
317 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
318 var prefService = Components.classes["@mozilla.org/preferences-service;1"].
319 getService(Components.interfaces.nsIPrefService);
320 var domBranch = prefService.getBranch("dom.");
321 var oldVal = domBranch.getIntPref("max_script_run_time");
322 domBranch.setIntPref("max_script_run_time", 0);
324 SimpleTest.finish();
326 domBranch.setIntPref("max_script_run_time", oldVal);
328 return;
330 test_property(l.pop());
331 setTimeout(do_one, 0, l);
333 setTimeout(do_one, 0, props);
335 </script>
336 </pre>
337 </body>
338 </html>