tor-browser

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

random-computed.tentative.html (32554B)


      1 <!DOCTYPE html>
      2 <link rel="help" href="https://drafts.csswg.org/css-values-5/#random">
      3 <link rel="author" title="sam@webkit.org">
      4 <meta name="timeout" content="long">
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <script src="../support/computed-testcommon.js"></script>
      8 <div id="container">
      9  <div id="target"></div>
     10 </div>
     11 <style>
     12  @property --x {
     13    syntax: "<number>";
     14    inherits: true;
     15    initial-value: 3;
     16  }
     17  @property --y {
     18    syntax: "<number>";
     19    inherits: true;
     20    initial-value: 3;
     21  }
     22  @property --random-length-1 {
     23    syntax: "<length>";
     24    inherits: true;
     25    initial-value: 3px;
     26  }
     27  @property --random-length-2 {
     28    syntax: "<length>";
     29    inherits: true;
     30    initial-value: 3px;
     31  }
     32  .randomNoIdentifier {
     33    width: random(0px, 100px);
     34    height: random(0px, 100px);
     35    left: random(0px, 100000px);
     36    right: random(0px, 100000px);
     37    margin: random(0px, 100000px) random(0px, 100000px);
     38    --x: random(0, 100);
     39    --y: random(0, 100);
     40    --random-length-1: random(fixed random(0, 1), 10px, 100px);
     41    --random-length-2: random(fixed random(0, 1), 10px, 100px);
     42  }
     43  .randomMatchElement {
     44    width: random(element-shared, 0px, 100px);
     45    height: random(element-shared, 0px, 100px);
     46    left: random(element-shared, 0px, 100000px);
     47    right: random(element-shared, 0px, 100000px);
     48    margin: random(element-shared 0px, 100000px) random(element-shared 0px, 100000px);
     49    translate: random(element-shared, 10%, 30%);
     50    scale: random(element-shared, 1, 3) random(element-shared, 3, 9);
     51  }
     52  .randomIdentifier {
     53    width: random(--identifier, 0px, 100px);
     54    height: random(--identifier, 0px, 100px);
     55    left: random(--identifier, 0px, 100000px);
     56    right: random(--identifier, 0px, 100000px);
     57    margin: random(--identifier 0px, 100000px) random(--identifier 0px, 100000px);
     58  }
     59  .randomMatchElementAndIdentifier {
     60    width: random(element-shared --other-identifier, 0px, 100px);
     61    height: random(element-shared --other-identifier, 0px, 100px);
     62    left: random(element-shared --other-identifier, 0px, 100000px);
     63    right: random(element-shared --other-identifier, 0px, 100000px);
     64    margin: random(element-shared --other-identifier 0px, 100000px) random(element-shared --other-identifier 0px, 100000px);
     65  }
     66  .randomFixed {
     67    width: random(fixed 0.5, 10px, 100px);
     68    height: random(fixed 0.5, 10px, 100px);
     69    left: random(fixed 0.5, 0px, 100000px);
     70    right: random(fixed 0.5, 0px, 100000px);
     71    margin: random(fixed 0.5 0px, 100000px) random(fixed 0.5 0px, 100000px);
     72  }
     73 </style>
     74 <script>
     75 
     76 // Run each test a number of times to increase the likelyhood that failure is not the cause of random chance.
     77 const iterations = 5;
     78 
     79 // Since actual and expected values are generated randomly, `assert_equals()`
     80 // does not generate deterministic test failure output. Chrome relies on test
     81 // failure output to be deterministic and stable for failing test expectations.
     82 function test_random_equals(actual, expected, message = "Random values should be equal") {
     83  assert_true(actual == expected, message);
     84 }
     85 
     86 function test_random_computed_value(property, specified, computed, titleExtra, options = {}) {
     87  if (!computed)
     88    computed = specified;
     89 
     90  test(() => {
     91    for (i = 0; i < iterations; ++i) {
     92      const target = document.getElementById('target');
     93      assert_true(property in getComputedStyle(target), property + " doesn't seem to be supported in the computed style");
     94      assert_true(CSS.supports(property, specified), "'" + specified + "' is a supported value for " + property + ".");
     95      target.style[property] = '';
     96      target.style[property] = specified;
     97 
     98      let readValue = getComputedStyle(target)[property];
     99      if (options.comparisonFunction) {
    100        options.comparisonFunction(readValue, computed);
    101      } else if (Array.isArray(computed)) {
    102        assert_in_array(readValue, computed);
    103      } else {
    104        test_random_equals(readValue, computed);
    105      }
    106      if (readValue !== specified) {
    107        target.style[property] = '';
    108        target.style[property] = readValue;
    109        test_random_equals(getComputedStyle(target)[property], readValue,
    110                      'computed value should round-trip');
    111      }
    112    }
    113  }, `Property ${property} value '${specified}'${titleExtra ? ' ' + titleExtra : ''}`);
    114 }
    115 
    116 function test_random_computed_value_greater_or_lower_than(property, specified, expected, titleExtra) {
    117  test(() => {
    118    for (i = 0; i < iterations; ++i) {
    119      const target = document.getElementById('target');
    120      assert_true(property in getComputedStyle(target), property + " doesn't seem to be supported in the computed style");
    121      assert_true(CSS.supports(property, specified), "'" + specified + "' is a supported value for " + property + ".");
    122      target.style[property] = '';
    123      target.style[property] = specified;
    124      let readValue = parseFloat(getComputedStyle(target)[property]);
    125      assert_true(isFinite(readValue), specified + " expected finite value but got " + readValue)
    126      assert_false(isNaN(readValue),   specified + " expected finite value but got " + readValue)
    127      if (expected > 0)
    128        assert_greater_than_equal(readValue, expected, specified);
    129      else
    130        assert_less_than_equal(readValue, expected, specified);
    131    }
    132  }, `Property ${property} value '${specified}'${titleExtra ? ' ' + titleExtra : ''}`);
    133 }
    134 
    135 function test_random_computed_value_in_range(property, specified, computedMin, computedMax, titleExtra) {
    136  test(() => {
    137    for (i = 0; i < iterations; ++i) {
    138      const target = document.getElementById('target');
    139      assert_true(property in getComputedStyle(target), property + " doesn't seem to be supported in the computed style");
    140      assert_true(CSS.supports(property, specified), "'" + specified + "' is a supported value for " + property + ".");
    141      target.style[property] = '';
    142      target.style[property] = specified;
    143 
    144      let readValue = getComputedStyle(target)[property];
    145 
    146      let readValueNumber = parseFloat(readValue);
    147      let computedMinNumber = parseFloat(computedMin);
    148      let computedMaxNumber = parseFloat(computedMax);
    149 
    150      assert_greater_than_equal(readValueNumber, computedMinNumber, specified);
    151      assert_less_than_equal(readValueNumber, computedMaxNumber, specified);
    152    }
    153  }, `Property ${property} value '${specified}'${titleExtra ? ' ' + titleExtra : ''}`);
    154 }
    155 
    156 function test_pseudo_element_random_computed_value_in_range(property, pseudo_element, specified, computedMin, computedMax, titleExtra) {
    157  test(() => {
    158    for (i = 0; i < iterations; ++i) {
    159      const styleEl = document.head.appendChild(document.createElement("style"));
    160      styleEl.innerHTML = `#target${pseudo_element} \{ ${property}: ${specified}; \}`;
    161 
    162      try {
    163        const target = document.getElementById("target");
    164        let readValue = getComputedStyle(target, pseudo_element)[property];
    165 
    166        let readValueNumber = parseFloat(readValue);
    167        let computedMinNumber = parseFloat(computedMin);
    168        let computedMaxNumber = parseFloat(computedMax);
    169 
    170        assert_greater_than_equal(readValueNumber, computedMinNumber, specified);
    171        assert_less_than_equal(readValueNumber, computedMaxNumber, specified);
    172      } finally {
    173        document.head.removeChild(styleEl);
    174      }
    175    }
    176  }, `Property ${property} value on pseudo element '${pseudo_element}' '${specified}'${titleExtra ? ' ' + titleExtra : ''}`);
    177 }
    178 
    179 function test_random_computed_value_has_fixed(property, specified, minPercentage, maxPercentage, expectedFixedValue = undefined, titleExtra = undefined) {
    180  test(() => {
    181    for (i = 0; i < iterations; ++i) {
    182      const target = document.getElementById('target');
    183      assert_true(property in getComputedStyle(target), property + " doesn't seem to be supported in the computed style");
    184      assert_true(CSS.supports(property, specified), "'" + specified + "' is a supported value for " + property + ".");
    185      target.style[property] = '';
    186      target.style[property] = specified;
    187 
    188      let readValue = getComputedStyle(target)[property];
    189 
    190      // strip 'random(' and ')'.
    191      let stippedReadValue = readValue.replace('random(', '').replace(')', '');
    192 
    193      // split into the three main components
    194      let [fixedComponent, minComponent, maxComponent] = stippedReadValue.split(', ');
    195 
    196      // split fixed component into its two components
    197      let [fixedString, fixedValue] = fixedComponent.split(' ');
    198 
    199      test_random_equals(fixedString, 'fixed', `Computed value for ${specified} should include 'fixed'`);
    200      if (expectedFixedValue) {
    201        test_random_equals(parseFloat(fixedValue), expectedFixedValue, `Random value for ${specified} should be ${expectedFixedValue}`);
    202      } else {
    203        assert_greater_than_equal(parseFloat(fixedValue), 0, specified);
    204        assert_less_than(parseFloat(fixedValue), 1, specified);
    205      }
    206      test_random_equals(minComponent, minPercentage, specified);
    207      test_random_equals(maxComponent, maxPercentage, specified);
    208    }
    209  }, `Property ${property} value '${specified}'${titleExtra ? ' ' + titleExtra : ''}`);
    210 }
    211 
    212 function test_random_base_is_not_1(property, specified) {
    213  test(() => {
    214    for (i = 0; i < iterations; ++i) {
    215      const target = document.getElementById('target');
    216      assert_true(property in getComputedStyle(target), property + " doesn't seem to be supported in the computed style");
    217      assert_true(CSS.supports(property, specified), "'" + specified + "' is a supported value for " + property + ".");
    218      target.style[property] = '';
    219      target.style[property] = specified;
    220      const computed = target.computedStyleMap().get(property);
    221      assert_true(computed instanceof CSSUnitValue);
    222      assert_false(computed.value == 100.0, "Random base value should not be clamped to 1");
    223    }
    224  }, `Property ${property} value '${specified}'`);
    225 }
    226 
    227 function test_random_shared_by_property(property, random_value, random_element_shared_value) {
    228  test(() => {
    229    const holder = document.createElement('div');
    230    document.body.appendChild(holder);
    231    var randomValuesSameOnDifferentElements = true;
    232    try {
    233      for (let i = 0; i < iterations; ++i) {
    234        const t1 = document.createElement('div');
    235        holder.appendChild(t1);
    236        const t2 = document.createElement('div');
    237        holder.appendChild(t2);
    238 
    239        t1.style[property] = random_value;
    240        t2.style[property] = random_value;
    241        let t1Computed = getComputedStyle(t1)[property];
    242        let t2Computed = getComputedStyle(t2)[property];
    243        if (t1Computed != t2Computed) {
    244          randomValuesSameOnDifferentElements = false;
    245        }
    246 
    247        t1.style[property] = random_element_shared_value;
    248        t2.style[property] = random_element_shared_value;
    249        let t1ComputedElementShared = getComputedStyle(t1)[property];
    250        let t2ComputedElementShared = getComputedStyle(t2)[property];
    251        test_random_equals(t1ComputedElementShared, t2ComputedElementShared,
    252                           `${random_element_shared_value} values on different elements should be equal`);
    253      }
    254      assert_false(randomValuesSameOnDifferentElements,
    255                   `${random_value} values on different elements should not be equal`);
    256    } finally {
    257      document.body.removeChild(holder);
    258    }
    259  }, `Shared by property '${property}'`);
    260 }
    261 
    262 const property = 'scale';
    263 
    264 test_random_computed_value_in_range(property, 'random(1, 11)', '1', '11');
    265 test_random_computed_value_in_range(property, 'random(--foo, 2, 12)', '2', '12');
    266 test_random_computed_value_in_range(property, 'random(--foo element-shared, 3, 13)', '3', '13');
    267 test_random_computed_value_in_range(property, 'random(element-shared --foo, 4, 14)', '4', '14');
    268 
    269 test_random_computed_value(property, 'random(0, 10, 5)', ['0', '5', '10']);
    270 test_random_computed_value(property, 'random(--foo, 10, 20, 5)', ['10', '15', '20']);
    271 test_random_computed_value(property, 'random(--foo element-shared, 20, 30, 5)', ['20', '25', '30']);
    272 test_random_computed_value(property, 'random(element-shared --foo, 30, 40, 5)', ['30', '35', '40']);
    273 
    274 // Test out of order.
    275 test_random_computed_value(property, 'random(100, 10)', '100');
    276 test_random_computed_value(property, 'random(-10, -100)', '-10');
    277 
    278 // Test negative range values
    279 test_random_computed_value_in_range(property, 'random(-100, -10)', '-100', '-10');
    280 
    281 // Test negative step values (treated as if step is not there)
    282 test_random_computed_value_in_range(property, 'random(40, 50, -5)', '40', '50');
    283 
    284 // Test nested expressions
    285 test_random_computed_value_in_range(property, 'random(5 * 1, 30 / 2)', '5', '15');
    286 
    287 // Test nested in expressions
    288 test_random_computed_value_in_range(property, 'calc(2 * random(6, 16))', '12', '32');
    289 
    290 // Test NaN
    291 test_random_computed_value(property, 'random(NaN, 100)', '0');
    292 test_random_computed_value(property, 'random(10, NaN)', '0');
    293 test_random_computed_value(property, 'random(NaN, NaN)', '0');
    294 test_random_computed_value(property, 'random(NaN, 100, 10)', '0');
    295 test_random_computed_value(property, 'random(10, NaN, 10)', '0');
    296 test_random_computed_value(property, 'random(NaN, NaN, 10)', '0');
    297 test_random_computed_value(property, 'random(NaN, 100, NaN)', '0');
    298 test_random_computed_value(property, 'random(10, NaN, NaN)', '0');
    299 test_random_computed_value(property, 'random(NaN, NaN, NaN)', '0');
    300 test_random_computed_value(property, 'random(10, 100, NaN)', '0');
    301 test_random_computed_value(property, 'calc(10 + random(NaN, 100))', '0');
    302 test_random_computed_value(property, 'calc(10 + random(10, NaN))', '0');
    303 test_random_computed_value(property, 'calc(10 + random(NaN, NaN))', '0');
    304 test_random_computed_value(property, 'calc(10 + random(NaN, 100, 10))', '0');
    305 test_random_computed_value(property, 'calc(10 + random(10, NaN, 10))', '0');
    306 test_random_computed_value(property, 'calc(10 + random(NaN, NaN, 10))', '0');
    307 test_random_computed_value(property, 'calc(10 + random(NaN, 100, NaN))', '0');
    308 test_random_computed_value(property, 'calc(10 + random(10, NaN, NaN))', '0');
    309 test_random_computed_value(property, 'calc(10 + random(NaN, NaN, NaN))', '0');
    310 test_random_computed_value(property, 'calc(10 + random(10, 100, NaN))', '0');
    311 
    312 // Test infinity
    313 
    314 const REALLY_LARGE = 1e6;
    315 const REALLY_LARGE_NEGATIVE = -REALLY_LARGE;
    316 
    317 test_random_computed_value_greater_or_lower_than(property, 'random(infinity, 100)', REALLY_LARGE);
    318 test_random_computed_value_greater_or_lower_than(property, 'random(infinity, infinity)', REALLY_LARGE);
    319 test_random_computed_value_greater_or_lower_than(property, 'random(infinity, 100, 10)', REALLY_LARGE);
    320 test_random_computed_value_greater_or_lower_than(property, 'random(infinity, infinity, 10)', REALLY_LARGE);
    321 test_random_computed_value_greater_or_lower_than(property, 'random(infinity, 100, infinity)', REALLY_LARGE);
    322 test_random_computed_value_greater_or_lower_than(property, 'random(infinity, infinity, infinity)', REALLY_LARGE);
    323 test_random_computed_value_greater_or_lower_than(property, 'calc(10 + random(infinity, 100))', REALLY_LARGE);
    324 test_random_computed_value_greater_or_lower_than(property, 'calc(10 + random(infinity, infinity))', REALLY_LARGE);
    325 test_random_computed_value_greater_or_lower_than(property, 'calc(10 + random(infinity, infinity, 10))', REALLY_LARGE);
    326 test_random_computed_value_greater_or_lower_than(property, 'calc(10 + random(infinity, 100, infinity))', REALLY_LARGE);
    327 test_random_computed_value_greater_or_lower_than(property, 'calc(10 + random(infinity, infinity, infinity))', REALLY_LARGE);
    328 test_random_computed_value_greater_or_lower_than(property, 'calc(10 + random(infinity, 100, 10))', REALLY_LARGE);
    329 test_random_computed_value(property, 'random(10, infinity)', '0');
    330 test_random_computed_value(property, 'random(10, infinity, 10)', '0');
    331 test_random_computed_value(property, 'random(10, infinity, infinity)', '0');
    332 test_random_computed_value(property, 'calc(10 + random(10, infinity))', '0');
    333 test_random_computed_value(property, 'calc(10 + random(10, infinity, 10))', '0');
    334 test_random_computed_value(property, 'calc(10 + random(10, infinity, infinity))', '0');
    335 test_random_computed_value(property, 'random(10, 100, infinity)', '10');
    336 test_random_computed_value(property, 'calc(10 + random(10, 100, infinity))', '20');
    337 // Negative steps, even infinitely negative steps, are ignored.
    338 test_random_computed_value_in_range(property, 'random(10, 100, -infinity)', '10', '100');
    339 test_random_computed_value_in_range(property, 'calc(10 + random(10, 100, -infinity))', '20', '110');
    340 
    341 // Test pseudo on psuedo elements
    342 test_pseudo_element_random_computed_value_in_range(property, '::before', 'random(7, 17)', '7', '17');
    343 test_pseudo_element_random_computed_value_in_range(property, '::before', 'random(--bar, 8, 18)', '8', '18');
    344 test_pseudo_element_random_computed_value_in_range(property, '::before', 'random(element-shared, 9, 19)', '9', '19');
    345 test_pseudo_element_random_computed_value_in_range(property, '::before', 'random(element-shared --foo, 10, 20)', '10', '20');
    346 
    347 // Test unresolvable percentage values
    348 test_random_computed_value_has_fixed('translate', 'random(10%, 100%)', '10%', '100%');
    349 test_random_computed_value_has_fixed('translate', 'random(3 * 10% , 10 * 10%)', '30%', '100%');
    350 test_random_computed_value_has_fixed('translate', 'random(10%, 1%)', '10%', '1%');
    351 test_random_computed_value_has_fixed('translate', 'random(--identifier element-shared, 10%, 100%)', '10%', '100%');
    352 
    353 // Test resolvable percentage values
    354 test_random_computed_value('font-size', 'random(30%, 10%)', '4.8px');
    355 test_random_computed_value('font-size', 'random(10px * 10% / 1%, 0%)', '100px');
    356 
    357 // Test out of range math functions for fixed value
    358 test_random_base_is_not_1('width', 'random(fixed random(1, 2), 10px, 100px)');
    359 test_random_computed_value_has_fixed('translate', 'random(fixed random(-2, -1), 10%, 100%)', '10%', '100%', 0);
    360 
    361 // Random inside function
    362 test_random_computed_value('color', 'rgb(random(30, 10) random(60, 10) random(90, 10))', 'rgb(30, 60, 90)');
    363 test_random_computed_value('color', 'rgb(from blue random(51, 10) random(g + 51, g) random(b, b))', 'color(srgb 0.2 0.2 1)');
    364 test_random_computed_value('color', 'color-mix(in srgb, rgb(random(30, 10) 0 0), rgb(random(21, 10) 0 0))', 'color(srgb 0.1 0 0)');
    365 test_random_computed_value('math-depth', 'add(random(30, 10))', '30');
    366 test_random_computed_value('view-transition-name', 'ident("myident" random(30, 10))', 'myident30');
    367 test_random_computed_value('background-image', 'image-set(url("http://example.com/image.png") calc(random(fixed 0.3, 0, 10) * 1x))', 'image-set(url("http://example.com/image.png") 3dppx)');
    368 
    369 test_random_shared_by_property('color',
    370                               'color-mix(in srgb, rgb(from blue random(10, 30) random(g, g + 30) random(b, b)), rgb(random(10, 90) 0 0))',
    371                               'color-mix(in srgb, rgb(from blue random(element-shared, 10, 30) random(element-shared, g, g + 30) random(element-shared, b, b)), rgb(random(element-shared, 10, 90) 0 0))');
    372 test_random_shared_by_property('math-depth', 'add(random(1, 100))', 'add(random(element-shared, 1, 100))');
    373 test_random_shared_by_property('view-transition-name',
    374                               'ident("myident" random(1, 100))',
    375                               'ident("myident" random(element-shared, 1, 100))');
    376 
    377 // Test random value sharing
    378 test(() => {
    379  const holder = document.createElement('div');
    380  document.body.appendChild(holder);
    381 
    382  try {
    383    const el = document.createElement('div');
    384    el.className = 'randomNoIdentifier';
    385    holder.appendChild(el);
    386    const elComputedLeft = getComputedStyle(el)['left'];
    387 
    388    var allSame = true;
    389    var allHaveSameLeftAndRight = true;
    390    for (i = 0; i < iterations; ++i) {
    391      const other = document.createElement('div');
    392      other.className = 'randomNoIdentifier';
    393      holder.appendChild(other);
    394      const otherComputedLeft = getComputedStyle(other)['left'];
    395      if (elComputedLeft != otherComputedLeft) {
    396        allSame = false;
    397      }
    398      const otherComputedRight = getComputedStyle(other)['right'];
    399      if (elComputedLeft != otherComputedRight) {
    400        allHaveSameLeftAndRight = false;
    401      }
    402    }
    403 
    404    assert_false(allSame);
    405    assert_false(allHaveSameLeftAndRight);
    406  } finally {
    407    document.body.removeChild(holder);
    408  }
    409 }, `Maximum random: 'random(a, b)'`);
    410 
    411 test(() => {
    412  const holder = document.createElement('div');
    413  document.body.appendChild(holder);
    414 
    415  try {
    416    var allHaveSameMarginTopAndMarginLeft = true;
    417    var allHaveSameMarginTopAndMarginBottom = true;
    418    for (i = 0; i < iterations; ++i) {
    419      const other = document.createElement('div');
    420      other.className = 'randomNoIdentifier';
    421      holder.appendChild(other);
    422      const otherComputedMarginLeft = getComputedStyle(other)['margin-left'];
    423      const otherComputedMarginTop = getComputedStyle(other)['margin-top'];
    424      const otherComputedMarginBottom = getComputedStyle(other)['margin-bottom'];
    425      if (otherComputedMarginLeft != otherComputedMarginTop) {
    426        allHaveSameMarginTopAndMarginLeft = false;
    427      }
    428      if (otherComputedMarginBottom != otherComputedMarginTop) {
    429        allHaveSameMarginTopAndMarginBottom = false;
    430      }
    431    }
    432 
    433    assert_false(allHaveSameMarginTopAndMarginLeft);
    434    assert_true(allHaveSameMarginTopAndMarginBottom);
    435  } finally {
    436    document.body.removeChild(holder);
    437  }
    438 }, `Maximum random - shorthand: random(a, b)`);
    439 
    440 test(() => {
    441  const holder = document.createElement('div');
    442  document.body.appendChild(holder);
    443 
    444  try {
    445    for (let i = 0; i < iterations; ++i) {
    446      const other1 = document.createElement('div');
    447      other1.style.animationIterationCount = 'random(element-shared, 0, 100), random(element-shared, 0, 100)';
    448      holder.appendChild(other1);
    449      let [computed11, computed12] = getComputedStyle(other1)['animation-iteration-count'].split(', ');
    450      const other2 = document.createElement('div');
    451      other2.style.animationIterationCount = '300, random(element-shared, 0, 100)';
    452      holder.appendChild(other2);
    453      let [computed21, computed22] = getComputedStyle(other2)['animation-iteration-count'].split(', ');
    454      assert_false(computed11 == computed12, "Random values for same property name but different value indexes should differ");
    455      test_random_equals(computed11, computed22);
    456    }
    457  } finally {
    458    document.body.removeChild(holder);
    459  }
    460 }, `Shared by property name and value index: random(element-shared, a, b)`);
    461 
    462 test(() => {
    463  const holder = document.createElement('div');
    464  document.body.appendChild(holder);
    465 
    466  try {
    467    const el = document.createElement('div');
    468    el.className = 'randomMatchElement';
    469    holder.appendChild(el);
    470    const elScale = getComputedStyle(el)['scale'];
    471 
    472    var allHaveSameScaleXAndScaleY = true;
    473    var allSame = true;
    474    for (i = 0; i < iterations; ++i) {
    475      const other = document.createElement('div');
    476      other.className = 'randomMatchElement';
    477      holder.appendChild(other);
    478      const otherScale = getComputedStyle(other)['scale'];
    479      if (elScale != otherScale) {
    480        allSame = false;
    481      }
    482      let [scaleX, scaleY] = otherScale.split(' ');
    483      if (scaleX != scaleY) {
    484        allHaveSameScaleXAndScaleY = false;
    485      }
    486    }
    487 
    488    assert_false(allHaveSameScaleXAndScaleY);
    489    assert_true(allSame);
    490  } finally {
    491    document.body.removeChild(holder);
    492  }
    493 }, `Maximum random - list: random(a, b)`);
    494 
    495 test(() => {
    496  const holder = document.createElement('div');
    497  document.body.appendChild(holder);
    498 
    499  try {
    500    for (i = 0; i < iterations; ++i) {
    501      const el = document.createElement('div');
    502      el.className = 'randomNoIdentifier';
    503      holder.appendChild(el);
    504      const elComputedLength1 = getComputedStyle(el).getPropertyValue('--random-length-1');
    505      const elComputedLength2 = getComputedStyle(el).getPropertyValue('--random-length-2');
    506      assert_false(elComputedLength1 == elComputedLength2,
    507                   "Different custom properties on the same element should not have equal values");
    508    }
    509  } finally {
    510    document.body.removeChild(holder);
    511  }
    512 }, `Nested random inside custom property: 'random(a, b)'`);
    513 
    514 test(() => {
    515  const holder = document.createElement('div');
    516  document.body.appendChild(holder);
    517 
    518  try {
    519    for (i = 0; i < iterations; ++i) {
    520      const el = document.createElement('div');
    521      el.className = 'randomNoIdentifier';
    522      holder.appendChild(el);
    523      const elComputedX = getComputedStyle(el).getPropertyValue('--x');
    524      const elComputedY = getComputedStyle(el).getPropertyValue('--y');
    525      assert_false(elComputedX == elComputedY,
    526                   "Different custom properties on the same element should not have equal values");
    527    }
    528  } finally {
    529    document.body.removeChild(holder);
    530  }
    531 }, `Maximum random custom property: 'random(a, b)'`);
    532 
    533 test(() => {
    534  const holder = document.createElement('div');
    535  document.body.appendChild(holder);
    536 
    537  try {
    538    for (i = 0; i < iterations; ++i) {
    539      const el = document.createElement('div');
    540      el.className = 'randomIdentifier';
    541      holder.appendChild(el);
    542 
    543      let elComputedWidth = getComputedStyle(el)['width'];
    544      let elComputedHeight = getComputedStyle(el)['height'];
    545 
    546      test_random_equals(elComputedWidth, elComputedHeight,
    547                           "width and height values on same element should be equal");
    548    }
    549  } finally {
    550    document.body.removeChild(holder);
    551  }
    552 }, `Shared by name within an element: 'random(--identifier, a, b)'`);
    553 
    554 test(() => {
    555  const holder = document.createElement('div');
    556  document.body.appendChild(holder);
    557 
    558  try {
    559    var allHaveSameMarginTopAndMarginLeft = true;
    560    for (i = 0; i < iterations; ++i) {
    561      const other = document.createElement('div');
    562      other.className = 'randomIdentifier';
    563      holder.appendChild(other);
    564      const otherComputedMarginLeft = getComputedStyle(other)['margin-left'];
    565      const otherComputedMarginTop = getComputedStyle(other)['margin-top'];
    566      if (otherComputedMarginLeft != otherComputedMarginTop) {
    567        allHaveSameMarginTopAndMarginLeft = false;
    568      }
    569    }
    570 
    571    assert_true(allHaveSameMarginTopAndMarginLeft);
    572  } finally {
    573    document.body.removeChild(holder);
    574  }
    575 }, `Shared by name within an element - shorthand: random(--identifier, a, b))`);
    576 
    577 test(() => {
    578  const holder = document.createElement('div');
    579  document.body.appendChild(holder);
    580 
    581  try {
    582    for (i = 0; i < iterations; ++i) {
    583      const t1 = document.createElement('div');
    584      t1.className = 'randomMatchElement';
    585      holder.appendChild(t1);
    586      const t2 = document.createElement('div');
    587      t2.className = 'randomMatchElement';
    588      holder.appendChild(t2);
    589 
    590      let t1ComputedWidth = getComputedStyle(t1)['width'];
    591      let t2ComputedWidth = getComputedStyle(t2)['width'];
    592 
    593      test_random_equals(t1ComputedWidth, t2ComputedWidth,
    594                           "width values on different elements should be equal");
    595    }
    596  } finally {
    597    document.body.removeChild(holder);
    598  }
    599 }, `Shared between elements within a property: random(element-shared, a, b)`);
    600 
    601 test(() => {
    602  const holder = document.createElement('div');
    603  document.body.appendChild(holder);
    604  var allSame = true;
    605  try {
    606    for (let i = 0; i < iterations; ++i) {
    607      const t1 = document.createElement('div');
    608      t1.style['color'] = 'color-mix(in srgb, rgb(0 random(0, 255) 0) 50%, rgb(random(0, 255) 0 0) 50%)';
    609      holder.appendChild(t1);
    610 
    611      let t1ComputedColor = getComputedStyle(t1)['color'];
    612      let [r, g, b] = t1ComputedColor.replace('color(srgb ', '').split(' ');
    613      if (r != g) {
    614        allSame = false;
    615      }
    616    }
    617    assert_false(allSame,
    618                 "random() values on different positions should not be equal");
    619  } finally {
    620    document.body.removeChild(holder);
    621  }
    622 }, `Shared between elements within a property, random inside color functions: random(element-shared, a, b)`);
    623 
    624 test(() => {
    625  const holder = document.createElement('div');
    626  document.body.appendChild(holder);
    627 
    628  try {
    629    for (i = 0; i < iterations; ++i) {
    630      const t1 = document.createElement('div');
    631      t1.className = 'randomMatchElement';
    632      holder.appendChild(t1);
    633      const t2 = document.createElement('div');
    634      t2.className = 'randomMatchElement';
    635      holder.appendChild(t2);
    636 
    637      let t1ComputedWidth = getComputedStyle(t1)['translate'];
    638      let t2ComputedWidth = getComputedStyle(t2)['translate'];
    639 
    640      test_random_equals(t1ComputedWidth, t2ComputedWidth,
    641                           "translate values with percentages on different elements should be equal");
    642    }
    643  } finally {
    644    document.body.removeChild(holder);
    645  }
    646 }, `Shared between elements within a property, percentage values: random(element-shared, a, b)`);
    647 
    648 test(() => {
    649  const holder = document.createElement('div');
    650  document.body.appendChild(holder);
    651 
    652  try {
    653    var allHaveSameMarginTopAndMarginLeft = true;
    654    for (i = 0; i < iterations; ++i) {
    655      const other = document.createElement('div');
    656      other.className = 'randomMatchElement';
    657      holder.appendChild(other);
    658      const otherComputedMarginLeft = getComputedStyle(other)['margin-left'];
    659      const otherComputedMarginTop = getComputedStyle(other)['margin-top'];
    660      if (otherComputedMarginLeft != otherComputedMarginTop) {
    661        allHaveSameMarginTopAndMarginLeft = false;
    662      }
    663    }
    664 
    665    assert_true(allHaveSameMarginTopAndMarginLeft);
    666  } finally {
    667    document.body.removeChild(holder);
    668  }
    669 }, `Shared between elements within a property - shorthand: random(element-shared, a, b)`);
    670 
    671 test(() => {
    672  const holder = document.createElement('div');
    673  document.body.appendChild(holder);
    674 
    675  try {
    676    for (i = 0; i < iterations; ++i) {
    677      const t1 = document.createElement('div');
    678      t1.className = 'randomMatchElementAndIdentifier';
    679      holder.appendChild(t1);
    680      const t2 = document.createElement('div');
    681      t2.className = 'randomMatchElementAndIdentifier';
    682      holder.appendChild(t2);
    683 
    684      let t1ComputedWidth = getComputedStyle(t1)['width'];
    685      let t2ComputedHeight = getComputedStyle(t2)['height'];
    686 
    687      test_random_equals(t1ComputedWidth, t2ComputedHeight,
    688                           "width and height values on different elements should be equal");
    689    }
    690  } finally {
    691    document.body.removeChild(holder);
    692  }
    693 }, `Shared globally: random(--identifier element-shared, a, b)`);
    694 
    695 test(() => {
    696  const holder = document.createElement('div');
    697  document.body.appendChild(holder);
    698 
    699  try {
    700    var allHaveSameMarginTopAndMarginLeft = true;
    701    for (i = 0; i < iterations; ++i) {
    702      const other = document.createElement('div');
    703      other.className = 'randomMatchElementAndIdentifier';
    704      holder.appendChild(other);
    705      const otherComputedMarginLeft = getComputedStyle(other)['margin-left'];
    706      const otherComputedMarginTop = getComputedStyle(other)['margin-top'];
    707      if (otherComputedMarginLeft != otherComputedMarginTop) {
    708        allHaveSameMarginTopAndMarginLeft = false;
    709      }
    710    }
    711 
    712    assert_true(allHaveSameMarginTopAndMarginLeft);
    713  } finally {
    714    document.body.removeChild(holder);
    715  }
    716 }, `Shared globally - shorthand: random(element-shared, a, b)`);
    717 
    718 test(() => {
    719  const holder = document.createElement('div');
    720  document.body.appendChild(holder);
    721 
    722  try {
    723    for (i = 0; i < iterations; ++i) {
    724      const t1 = document.createElement('div');
    725      t1.className = 'randomFixed';
    726      holder.appendChild(t1);
    727 
    728      let t1ComputedWidth = getComputedStyle(t1)['width'];
    729 
    730      test_random_equals(t1ComputedWidth, "55px", "Random value with fixed should be 55px");
    731    }
    732  } finally {
    733    document.body.removeChild(holder);
    734  }
    735 }, `Fixed: random(fixed <number>, a, b)`);
    736 
    737 // Test random value sharing
    738 test(() => {
    739  const holder = document.createElement('div');
    740  document.body.appendChild(holder);
    741 
    742  try {
    743    const el = document.createElement('div');
    744    el.className = 'randomIdentifier';
    745    holder.appendChild(el);
    746    const elComputedHeight = getComputedStyle(el)['height'];
    747 
    748    var allSame = true;
    749    for (i = 0; i < iterations; ++i) {
    750      const other = document.createElement('div');
    751      other.className = 'randomIdentifier';
    752      holder.appendChild(other);
    753      const otherComputedHeight = getComputedStyle(other)['height'];
    754      if (elComputedHeight != otherComputedHeight) {
    755        allSame = false;
    756      }
    757    }
    758    assert_false(allSame);
    759  } finally {
    760    document.body.removeChild(holder);
    761  }
    762 }, `Different between elements with same identifier random(--identifier, a, b)`);
    763 
    764 </script>