Bug 1839315: part 4) Link from `SheetLoadData::mWasAlternate` to spec. r=emilio DONTBUILD
[gecko.git] / layout / style / test / test_logical_properties.html
bloba6947791cbe335be4d3d8b4003b9de79d8f87d05
1 <!DOCTYPE html>
2 <meta charset=utf-8>
3 <title>Test for handling of logical and physical properties</title>
4 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
5 <script src="/tests/SimpleTest/SimpleTest.js"></script>
7 <style id="sheet"></style>
9 <!-- specify size for <body> to avoid unconstrained-isize warnings
10 when writing-mode of the test <div> is vertical-* -->
11 <body style="width:100px; height: 100px;">
12 <div id="test" class="test"></div>
13 </body>
15 <script>
16 var gSheet = document.getElementById("sheet");
17 var gTest = document.getElementById("test");
19 // list of groups of physical and logical box properties, such as
21 // { left: "margin-left", right: "margin-right",
22 // top: "margin-top", bottom: "margin-bottom",
23 // inlineStart: "margin-inline-start", inlineEnd: "margin-inline-end",
24 // blockStart: "margin-block-start", blockEnd: "margin-block-end",
25 // type: "length", prerequisites: "..." }
27 // where the type is a key from the gValues object and the prerequisites
28 // is a declaration including gCSSProperties' listed prerequisites for
29 // all four physical properties.
30 var gBoxPropertyGroups;
32 // list of groups of physical and logical axis properties, such as
34 // { horizontal: "width", vertical: "height",
35 // inline: "inline-size", block: "block-size",
36 // type: "length", prerequisites: "..." }
37 var gAxisPropertyGroups;
39 // values to use while testing
40 var gValues = {
41 "length": ["1px", "2px", "3px", "4px", "5px"],
42 "color": ["rgb(1, 1, 1)", "rgb(2, 2, 2)", "rgb(3, 3, 3)", "rgb(4, 4, 4)", "rgb(5, 5, 5)"],
43 "border-style": ["solid", "dashed", "dotted", "double", "groove"],
46 // Six unique overall writing modes for property-mapping purposes.
47 // Note that text-orientation does not affect these mappings, now that
48 // the proposed sideways-left value no longer exists (superseded in CSS
49 // Writing Modes by writing-mode: sideways-lr).
50 var gWritingModes = [
51 { style: [
52 "writing-mode: horizontal-tb; direction: ltr; ",
54 blockStart: "top", blockEnd: "bottom", inlineStart: "left", inlineEnd: "right",
55 block: "vertical", inline: "horizontal" },
56 { style: [
57 "writing-mode: horizontal-tb; direction: rtl; ",
59 blockStart: "top", blockEnd: "bottom", inlineStart: "right", inlineEnd: "left",
60 block: "vertical", inline: "horizontal" },
61 { style: [
62 "writing-mode: vertical-rl; direction: rtl; ",
63 "writing-mode: sideways-rl; direction: rtl; ",
65 blockStart: "right", blockEnd: "left", inlineStart: "bottom", inlineEnd: "top",
66 block: "horizontal", inline: "vertical" },
67 { style: [
68 "writing-mode: vertical-rl; direction: ltr; ",
69 "writing-mode: sideways-rl; direction: ltr; ",
71 blockStart: "right", blockEnd: "left", inlineStart: "top", inlineEnd: "bottom",
72 block: "horizontal", inline: "vertical" },
73 { style: [
74 "writing-mode: vertical-lr; direction: rtl; ",
75 "writing-mode: sideways-lr; direction: ltr; ",
77 blockStart: "left", blockEnd: "right", inlineStart: "bottom", inlineEnd: "top",
78 block: "horizontal", inline: "vertical" },
79 { style: [
80 "writing-mode: vertical-lr; direction: ltr; ",
81 "writing-mode: sideways-lr; direction: rtl; ",
83 blockStart: "left", blockEnd: "right", inlineStart: "top", inlineEnd: "bottom",
84 block: "horizontal", inline: "vertical" },
87 function init() {
88 gBoxPropertyGroups = [];
90 for (var p in gCSSProperties) {
91 var type = gCSSProperties[p].type;
93 if ((type == CSS_TYPE_SHORTHAND_AND_LONGHAND ||
94 type == CSS_TYPE_LONGHAND && gCSSProperties[p].logical) &&
95 /-inline-end/.test(p)) {
96 var valueType;
97 if (/margin|padding|width|inset|offset/.test(p)) {
98 valueType = "length";
99 } else if (/color/.test(p)) {
100 valueType = "color";
101 } else if (/border.*style/.test(p)) {
102 valueType = "border-style";
103 } else {
104 throw `unexpected property ${p}`;
106 var group = {
107 inlineStart: p.replace("-inline-end", "-inline-start"),
108 inlineEnd: p,
109 blockStart: p.replace("-inline-end", "-block-start"),
110 blockEnd: p.replace("-inline-end", "-block-end"),
111 type: valueType
113 if (/^(offset|inset)/.test(p)) {
114 group.left = "left";
115 group.right = "right";
116 group.top = "top";
117 group.bottom = "bottom";
118 } else {
119 group.left = p.replace("-inline-end", "-left");
120 group.right = p.replace("-inline-end", "-right");
121 group.top = p.replace("-inline-end", "-top");
122 group.bottom = p.replace("-inline-end", "-bottom");
124 group.prerequisites =
125 make_declaration(gCSSProperties[group.top].prerequisites) +
126 make_declaration(gCSSProperties[group.right].prerequisites) +
127 make_declaration(gCSSProperties[group.bottom].prerequisites) +
128 make_declaration(gCSSProperties[group.left].prerequisites);
129 gBoxPropertyGroups.push(group);
133 // We don't populate this automatically since the only entries we have, for
134 // inline-size etc., don't lend themselves to automatically determining
135 // the names "width", "height", "min-width", etc.
136 gAxisPropertyGroups = [];
137 ["", "max-", "min-"].forEach(function(aPrefix) {
138 gAxisPropertyGroups.push({
139 horizontal: `${aPrefix}width`, vertical: `${aPrefix}height`,
140 inline: `${aPrefix}inline-size`, block: `${aPrefix}block-size`,
141 type: "length",
142 prerequisites:
143 make_declaration(gCSSProperties[`${aPrefix}height`].prerequisites)
148 function test_computed_values(aTestName, aRules, aExpectedValues) {
149 gSheet.textContent = aRules;
150 var cs = getComputedStyle(gTest);
151 aExpectedValues.forEach(function(aPair) {
152 is(cs.getPropertyValue(aPair[0]), aPair[1], `${aTestName}, ${aPair[0]}`);
154 gSheet.textContent = "";
157 function make_declaration(aObject) {
158 var decl = "";
159 if (aObject) {
160 for (var p in aObject) {
161 decl += `${p}: ${aObject[p]}; `;
164 return decl;
167 function start() {
168 var script = document.createElement("script");
169 script.src = "property_database.js";
170 script.onload = function() {
171 init();
172 run_tests();
174 document.body.appendChild(script);
177 function run_axis_test_for_writing_mode(aGroup, aWritingMode, aWritingModeDecl) {
178 var values = gValues[aGroup.type];
179 var decl;
181 // Test that logical axis properties are converted to their physical
182 // equivalent correctly when all four are present on a single
183 // declaration, with no overwriting of previous properties and
184 // no physical properties present. We put the writing mode properties
185 // on a separate declaration to test that the computed values of these
186 // properties are used, rather than those on the same declaration.
188 decl = aGroup.prerequisites +
189 `${aGroup.inline}: ${values[0]}; ` +
190 `${aGroup.block}: ${values[1]}; `;
191 test_computed_values('logical properties on one declaration, writing ' +
192 'mode properties on another, ' +
193 `'${aWritingModeDecl}'`,
194 `.test { ${aWritingModeDecl} } ` +
195 `.test { ${decl} }`,
196 [[aGroup[aWritingMode.inline], values[0]],
197 [aGroup[aWritingMode.block], values[1]]]);
200 // Test that logical and physical axis properties are cascaded together,
201 // honoring their relative order on a single declaration.
203 // (a) with a single logical property after the physical ones
205 ["inline", "block"].forEach(function(aLogicalAxis) {
206 decl = aWritingModeDecl + aGroup.prerequisites +
207 `${aGroup.horizontal}: ${values[0]}; ` +
208 `${aGroup.vertical}: ${values[1]}; ` +
209 `${aGroup[aLogicalAxis]}: ${values[2]}; `;
210 var expected = ["horizontal", "vertical"].map(
211 (axis, i) => [aGroup[axis],
212 values[axis == aWritingMode[aLogicalAxis] ? 2 : i]]
214 test_computed_values(`${aLogicalAxis} last on single declaration, ` +
215 `'${aWritingModeDecl}'`,
216 `.test { ${decl} }`,
217 expected);
220 // (b) with a single physical property after the logical ones
222 ["horizontal", "vertical"].forEach(function(aPhysicalAxis) {
223 decl = aWritingModeDecl + aGroup.prerequisites +
224 `${aGroup.inline}: ${values[0]}; ` +
225 `${aGroup.block}: ${values[1]}; ` +
226 `${aGroup[aPhysicalAxis]}: ${values[2]}; `;
227 var expected = ["inline", "block"].map(
228 (axis, i) => [aGroup[aWritingMode[axis]],
229 values[aWritingMode[axis] == aPhysicalAxis ? 2 : i]]
231 test_computed_values(`${aPhysicalAxis} last on single declaration, ` +
232 `'${aWritingModeDecl}'`,
233 `.test { ${decl} }`,
234 expected);
238 // Test that logical and physical axis properties are cascaded properly when
239 // on different declarations.
241 var loDecl; // lower specifity
242 var hiDecl; // higher specificity
244 // (a) with a logical property in the high specificity rule
246 loDecl = aWritingModeDecl + aGroup.prerequisites +
247 `${aGroup.horizontal}: ${values[0]}; ` +
248 `${aGroup.vertical}: ${values[1]}; `;
250 ["inline", "block"].forEach(function(aLogicalAxis) {
251 hiDecl = `${aGroup[aLogicalAxis]}: ${values[2]}; `;
252 var expected = ["horizontal", "vertical"].map(
253 (axis, i) => [aGroup[axis],
254 values[axis == aWritingMode[aLogicalAxis] ? 2 : i]]
256 test_computed_values(`${aLogicalAxis}, two declarations, ` +
257 `'${aWritingModeDecl}'`,
258 `#test { ${hiDecl} } ` +
259 `.test { ${loDecl} }`,
260 expected);
263 // (b) with a physical property in the high specificity rule
265 loDecl = aWritingModeDecl + aGroup.prerequisites +
266 `${aGroup.inline}: ${values[0]}; ` +
267 `${aGroup.block}: ${values[1]}; `;
269 ["horizontal", "vertical"].forEach(function(aPhysicalAxis) {
270 hiDecl = `${aGroup[aPhysicalAxis]}: ${values[2]}; `;
271 var expected = ["inline", "block"].map(
272 (axis, i) => [aGroup[aWritingMode[axis]],
273 values[aWritingMode[axis] == aPhysicalAxis ? 2 : i]]
275 test_computed_values(`${aPhysicalAxis}, two declarations, ` +
276 `'${aWritingModeDecl}'`,
277 `#test { ${hiDecl} } ` +
278 `.test { ${loDecl} }`,
279 expected);
283 function run_box_test_for_writing_mode(aGroup, aWritingMode, aWritingModeDecl) {
284 var values = gValues[aGroup.type];
285 var decl;
287 // Test that logical box properties are converted to their physical
288 // equivalent correctly when all four are present on a single
289 // declaration, with no overwriting of previous properties and
290 // no physical properties present. We put the writing mode properties
291 // on a separate declaration to test that the computed values of these
292 // properties are used, rather than those on the same declaration.
294 decl = aGroup.prerequisites +
295 `${aGroup.inlineStart}: ${values[0]}; ` +
296 `${aGroup.inlineEnd}: ${values[1]}; ` +
297 `${aGroup.blockStart}: ${values[2]}; ` +
298 `${aGroup.blockEnd}: ${values[3]}; `;
299 test_computed_values('logical properties on one declaration, writing ' +
300 'mode properties on another, ' +
301 `'${aWritingModeDecl}'`,
302 `.test { ${aWritingModeDecl} } ` +
303 `.test { ${decl} }`,
304 [[aGroup[aWritingMode.inlineStart], values[0]],
305 [aGroup[aWritingMode.inlineEnd], values[1]],
306 [aGroup[aWritingMode.blockStart], values[2]],
307 [aGroup[aWritingMode.blockEnd], values[3]]]);
309 // Test that logical and physical box properties are cascaded together,
310 // honoring their relative order on a single declaration.
312 // (a) with a single logical property after the physical ones
314 ["inlineStart", "inlineEnd", "blockStart", "blockEnd"].forEach(function(aLogicalSide) {
315 decl = aWritingModeDecl + aGroup.prerequisites +
316 `${aGroup.left}: ${values[0]}; ` +
317 `${aGroup.right}: ${values[1]}; ` +
318 `${aGroup.top}: ${values[2]}; ` +
319 `${aGroup.bottom}: ${values[3]}; ` +
320 `${aGroup[aLogicalSide]}: ${values[4]}; `;
321 var expected = ["left", "right", "top", "bottom"].map(
322 (side, i) => [aGroup[side],
323 values[side == aWritingMode[aLogicalSide] ? 4 : i]]
325 test_computed_values(`${aLogicalSide} last on single declaration, ` +
326 `'${aWritingModeDecl}'`,
327 `.test { ${decl} }`,
328 expected);
331 // (b) with a single physical property after the logical ones
333 ["left", "right", "top", "bottom"].forEach(function(aPhysicalSide) {
334 decl = aWritingModeDecl + aGroup.prerequisites +
335 `${aGroup.inlineStart}: ${values[0]}; ` +
336 `${aGroup.inlineEnd}: ${values[1]}; ` +
337 `${aGroup.blockStart}: ${values[2]}; ` +
338 `${aGroup.blockEnd}: ${values[3]}; ` +
339 `${aGroup[aPhysicalSide]}: ${values[4]}; `;
340 var expected = ["inlineStart", "inlineEnd", "blockStart", "blockEnd"].map(
341 (side, i) => [aGroup[aWritingMode[side]],
342 values[aWritingMode[side] == aPhysicalSide ? 4 : i]]
344 test_computed_values(`${aPhysicalSide} last on single declaration, ` +
345 `'${aWritingModeDecl}'`,
346 `.test { ${decl} }`,
347 expected);
351 // Test that logical and physical box properties are cascaded properly when
352 // on different declarations.
354 var loDecl; // lower specifity
355 var hiDecl; // higher specificity
357 // (a) with a logical property in the high specificity rule
359 loDecl = aWritingModeDecl + aGroup.prerequisites +
360 `${aGroup.left}: ${values[0]}; ` +
361 `${aGroup.right}: ${values[1]}; ` +
362 `${aGroup.top}: ${values[2]}; ` +
363 `${aGroup.bottom}: ${values[3]}; `;
365 ["inlineStart", "inlineEnd", "blockStart", "blockEnd"].forEach(function(aLogicalSide) {
366 hiDecl = `${aGroup[aLogicalSide]}: ${values[4]}; `;
367 var expected = ["left", "right", "top", "bottom"].map(
368 (side, i) => [aGroup[side],
369 values[side == aWritingMode[aLogicalSide] ? 4 : i]]
371 test_computed_values(`${aLogicalSide}, two declarations, ` +
372 `'${aWritingModeDecl}'`,
373 `#test { ${hiDecl} } ` +
374 `.test { ${loDecl} }`,
375 expected);
378 // (b) with a physical property in the high specificity rule
380 loDecl = aWritingModeDecl + aGroup.prerequisites +
381 `${aGroup.inlineStart}: ${values[0]}; ` +
382 `${aGroup.inlineEnd}: ${values[1]}; ` +
383 `${aGroup.blockStart}: ${values[2]}; ` +
384 `${aGroup.blockEnd}: ${values[3]}; `;
386 ["left", "right", "top", "bottom"].forEach(function(aPhysicalSide) {
387 hiDecl = `${aGroup[aPhysicalSide]}: ${values[4]}; `;
388 var expected = ["inlineStart", "inlineEnd", "blockStart", "blockEnd"].map(
389 (side, i) => [aGroup[aWritingMode[side]],
390 values[aWritingMode[side] == aPhysicalSide ? 4 : i]]
392 test_computed_values(`${aPhysicalSide}, two declarations, ` +
393 `'${aWritingModeDecl}'`,
394 `#test { ${hiDecl} } ` +
395 `.test { ${loDecl} }`,
396 expected);
400 function run_tests() {
401 gBoxPropertyGroups.forEach(function(aGroup) {
402 gWritingModes.forEach(function(aWritingMode) {
403 aWritingMode.style.forEach(function(aWritingModeDecl) {
404 run_box_test_for_writing_mode(aGroup, aWritingMode, aWritingModeDecl);
409 gAxisPropertyGroups.forEach(function(aGroup) {
410 gWritingModes.forEach(function(aWritingMode) {
411 aWritingMode.style.forEach(function(aWritingModeDecl) {
412 run_axis_test_for_writing_mode(aGroup, aWritingMode, aWritingModeDecl);
417 SimpleTest.finish();
420 SimpleTest.waitForExplicitFinish();
421 start();
422 </script>