tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_logical_properties.html (16434B)


      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>
      6 
      7 <style id="sheet"></style>
      8 
      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>
     14 
     15 <script>
     16 var gSheet = document.getElementById("sheet");
     17 var gTest  = document.getElementById("test");
     18 
     19 // list of groups of physical and logical box properties, such as
     20 //
     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: "..." }
     26 //
     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;
     31 
     32 // list of groups of physical and logical axis properties, such as
     33 //
     34 // { horizontal: "width", vertical: "height",
     35 //   inline: "inline-size", block: "block-size",
     36 //   type: "length", prerequisites: "..." }
     37 var gAxisPropertyGroups;
     38 
     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"],
     44 };
     45 
     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; ",
     53    ],
     54    blockStart: "top", blockEnd: "bottom", inlineStart: "left", inlineEnd: "right",
     55    block: "vertical", inline: "horizontal" },
     56  { style: [
     57      "writing-mode: horizontal-tb; direction: rtl; ",
     58    ],
     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; ",
     64    ],
     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; ",
     70    ],
     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; ",
     76    ],
     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; ",
     82    ],
     83    blockStart: "left", blockEnd: "right", inlineStart: "top", inlineEnd: "bottom",
     84    block: "horizontal", inline: "vertical" },
     85 ];
     86 
     87 function init() {
     88  gBoxPropertyGroups = [];
     89 
     90  for (var p in gCSSProperties) {
     91    var type = gCSSProperties[p].type;
     92 
     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}`;
    105      }
    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
    112      };
    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");
    123      }
    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);
    130    }
    131  }
    132 
    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)
    144    });
    145  });
    146 }
    147 
    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]}`);
    153  });
    154  gSheet.textContent = "";
    155 }
    156 
    157 function make_declaration(aObject) {
    158  var decl = "";
    159  if (aObject) {
    160    for (var p in aObject) {
    161      decl += `${p}: ${aObject[p]}; `;
    162    }
    163  }
    164  return decl;
    165 }
    166 
    167 function start() {
    168  var script = document.createElement("script");
    169  script.src = "property_database.js";
    170  script.onload = function() {
    171    init();
    172    run_tests();
    173  };
    174  document.body.appendChild(script);
    175 }
    176 
    177 function run_axis_test_for_writing_mode(aGroup, aWritingMode, aWritingModeDecl) {
    178  var values = gValues[aGroup.type];
    179  var decl;
    180 
    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.
    187 
    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]]]);
    198 
    199 
    200  // Test that logical and physical axis properties are cascaded together,
    201  // honoring their relative order on a single declaration.
    202 
    203  // (a) with a single logical property after the physical ones
    204 
    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]]
    213    );
    214    test_computed_values(`${aLogicalAxis} last on single declaration, ` +
    215                           `'${aWritingModeDecl}'`,
    216                         `.test { ${decl} }`,
    217                         expected);
    218  });
    219 
    220  // (b) with a single physical property after the logical ones
    221 
    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]]
    230    );
    231    test_computed_values(`${aPhysicalAxis} last on single declaration, ` +
    232                           `'${aWritingModeDecl}'`,
    233                         `.test { ${decl} }`,
    234                         expected);
    235  });
    236 
    237 
    238  // Test that logical and physical axis properties are cascaded properly when
    239  // on different declarations.
    240 
    241  var loDecl;  // lower specifity
    242  var hiDecl;  // higher specificity
    243 
    244  // (a) with a logical property in the high specificity rule
    245 
    246  loDecl = aWritingModeDecl + aGroup.prerequisites +
    247           `${aGroup.horizontal}: ${values[0]}; ` +
    248           `${aGroup.vertical}: ${values[1]}; `;
    249 
    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]]
    255    );
    256    test_computed_values(`${aLogicalAxis}, two declarations, ` +
    257                           `'${aWritingModeDecl}'`,
    258                         `#test { ${hiDecl} } ` +
    259                         `.test { ${loDecl} }`,
    260                         expected);
    261  });
    262 
    263  // (b) with a physical property in the high specificity rule
    264 
    265  loDecl = aWritingModeDecl + aGroup.prerequisites +
    266           `${aGroup.inline}: ${values[0]}; ` +
    267           `${aGroup.block}: ${values[1]}; `;
    268 
    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]]
    274    );
    275    test_computed_values(`${aPhysicalAxis}, two declarations, ` +
    276                           `'${aWritingModeDecl}'`,
    277                         `#test { ${hiDecl} } ` +
    278                         `.test { ${loDecl} }`,
    279                         expected);
    280  });
    281 }
    282 
    283 function run_box_test_for_writing_mode(aGroup, aWritingMode, aWritingModeDecl) {
    284  var values = gValues[aGroup.type];
    285  var decl;
    286 
    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.
    293 
    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]]]);
    308 
    309  // Test that logical and physical box properties are cascaded together,
    310  // honoring their relative order on a single declaration.
    311 
    312  // (a) with a single logical property after the physical ones
    313 
    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]]
    324    );
    325    test_computed_values(`${aLogicalSide} last on single declaration, ` +
    326                           `'${aWritingModeDecl}'`,
    327                         `.test { ${decl} }`,
    328                         expected);
    329  });
    330 
    331  // (b) with a single physical property after the logical ones
    332 
    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]]
    343    );
    344    test_computed_values(`${aPhysicalSide} last on single declaration, ` +
    345                           `'${aWritingModeDecl}'`,
    346                         `.test { ${decl} }`,
    347                         expected);
    348  });
    349 
    350 
    351  // Test that logical and physical box properties are cascaded properly when
    352  // on different declarations.
    353 
    354  var loDecl;  // lower specifity
    355  var hiDecl;  // higher specificity
    356 
    357  // (a) with a logical property in the high specificity rule
    358 
    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]}; `;
    364 
    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]]
    370    );
    371    test_computed_values(`${aLogicalSide}, two declarations, ` +
    372                           `'${aWritingModeDecl}'`,
    373                         `#test { ${hiDecl} } ` +
    374                         `.test { ${loDecl} }`,
    375                         expected);
    376  });
    377 
    378  // (b) with a physical property in the high specificity rule
    379 
    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]}; `;
    385 
    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]]
    391    );
    392    test_computed_values(`${aPhysicalSide}, two declarations, ` +
    393                           `'${aWritingModeDecl}'`,
    394                         `#test { ${hiDecl} } ` +
    395                         `.test { ${loDecl} }`,
    396                         expected);
    397  });
    398 }
    399 
    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);
    405      });
    406    });
    407  });
    408 
    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);
    413      });
    414    });
    415  });
    416 
    417  SimpleTest.finish();
    418 }
    419 
    420 SimpleTest.waitForExplicitFinish();
    421 start();
    422 </script>