| <!DOCTYPE html> |
| <link rel="help" href="https://drafts.csswg.org/css-values-5/#random"> |
| <link rel="author" title="[email protected]"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="../support/computed-testcommon.js"></script> |
| <div id="container" style="font-size: 20"> |
| <div id="target"></div> |
| </div> |
| <div id="noIdentifier1" class="randomNoIdentifier"></div> |
| <div id="noIdentifier2" class="randomNoIdentifier"></div> |
| <div id="identifier1" class="randomIdentifier"></div> |
| <div id="identifier2" class="randomIdentifier"></div> |
| <div id="identicalArguments1"></div> |
| <div id="identicalArguments2"></div> |
| <div id="identicalArgumentsAfterMath1"></div> |
| <div id="identicalArgumentsAfterMath2"></div> |
| <div id="identicalArgumentsAfterUnitResolution1"></div> |
| <div id="identicalArgumentsAfterUnitResolution2"></div> |
| <div id="identicalTwoProperties"></div> |
| <div id="identicalTwoPropertiesWithIdentifier"></div> |
| <div id="identicalTwoPropertiesWithPerElement"></div> |
| <div id="identicalTwoPropertiesWithPerElementAndIdentifier"></div> |
| <style> |
| .randomPerElement { width: random(per-element, 0px, 100000px); } |
| .randomNoIdentifier { width: random(10px, 110px); } |
| .randomIdentifier { width: random(--identifier, 20px, 120px); } |
| |
| #identicalArguments1 { width: random(30px, 130px); } |
| #identicalArguments2 { width: random(30px, 130px); } |
| |
| #identicalArgumentsAfterMath1 { width: random(5 * 10px, 2 * 75px); } |
| #identicalArgumentsAfterMath2 { width: random(100px / 2, 300px / 2); } |
| |
| #identicalArgumentsAfterUnitResolution1 { width: random(160px, 320px); } |
| #identicalArgumentsAfterUnitResolution2 { font-size: 16px; width: random(10em, 20em); } |
| |
| #identicalTwoProperties { |
| width: random(60px, 160px); |
| height: random(60px, 160px); |
| } |
| |
| #identicalTwoPropertiesWithIdentifier { |
| width: random(--another-identifier, 70px, 170px); |
| height: random(--another-identifier, 70px, 170px); |
| } |
| |
| #identicalTwoPropertiesWithPerElement { |
| width: random(per-element, 80px, 180px); |
| height: random(per-element, 80px, 180px); |
| } |
| |
| #identicalTwoPropertiesWithPerElementAndIdentifier { |
| width: random(per-element --yet-another-identifier, 90px, 190px); |
| height: random(--yet-another-identifier per-element, 90px, 190px); |
| } |
| </style> |
| <script> |
| function test_computed_value_in_range(property, specified, computedMin, computedMax, titleExtra) { |
| test(() => { |
| const target = document.getElementById('target'); |
| assert_true(property in getComputedStyle(target), property + " doesn't seem to be supported in the computed style"); |
| assert_true(CSS.supports(property, specified), "'" + specified + "' is a supported value for " + property + "."); |
| target.style[property] = ''; |
| target.style[property] = specified; |
| |
| let readValue = getComputedStyle(target)[property]; |
| |
| let readValueNumber = parseFloat(readValue); |
| let computedMinNumber = parseFloat(computedMin); |
| let computedMaxNumber = parseFloat(computedMax); |
| |
| assert_greater_than_equal(readValueNumber, computedMinNumber, specified); |
| assert_less_than_equal(readValueNumber, computedMaxNumber, specified); |
| }, `Property ${property} value '${specified}'${titleExtra ? ' ' + titleExtra : ''}`); |
| } |
| |
| function test_pseudo_element_computed_value_in_range(property, pseudo_element, specified, computedMin, computedMax, titleExtra) { |
| test(() => { |
| const styleEl = document.head.appendChild(document.createElement("style")); |
| styleEl.innerHTML = `#target${pseudo_element} \{ ${property}: ${specified}; \}`; |
| |
| try { |
| const target = document.getElementById("target"); |
| let readValue = getComputedStyle(target, pseudo_element)[property]; |
| |
| let readValueNumber = parseFloat(readValue); |
| let computedMinNumber = parseFloat(computedMin); |
| let computedMaxNumber = parseFloat(computedMax); |
| |
| assert_greater_than_equal(readValueNumber, computedMinNumber, specified); |
| assert_less_than_equal(readValueNumber, computedMaxNumber, specified); |
| } finally { |
| document.head.removeChild(styleEl); |
| } |
| }, `Property ${property} value on pseudo element '${pseudo_element}' '${specified}'${titleExtra ? ' ' + titleExtra : ''}`); |
| } |
| |
| const property = 'scale'; |
| |
| test_computed_value_in_range(property, 'random(1, 11)', '1', '11'); |
| test_computed_value_in_range(property, 'random(--foo, 2, 12)', '2', '12'); |
| test_computed_value_in_range(property, 'random(--foo per-element, 3, 13)', '3', '13'); |
| test_computed_value_in_range(property, 'random(per-element --foo, 4, 14)', '4', '14'); |
| |
| test_computed_value(property, 'random(0, 10, by 5)', ['0', '5', '10']); |
| test_computed_value(property, 'random(--foo, 10, 20, by 5)', ['10', '15', '20']); |
| test_computed_value(property, 'random(--foo per-element, 20, 30, by 5)', ['20', '25', '30']); |
| test_computed_value(property, 'random(per-element --foo, 30, 40, by 5)', ['30', '35', '40']); |
| |
| // Test out of order. |
| test_computed_value(property, 'random(100, 10)', '100'); |
| test_computed_value(property, 'random(-10, -100)', '-10'); |
| |
| // Test negative values |
| test_computed_value_in_range(property, 'random(-100, -10)', '-100', '-10'); |
| test_computed_value(property, 'random(40, 50, by -5)', '40'); |
| |
| // Test nested expressions |
| test_computed_value_in_range(property, 'random(5 * 1, 30 / 2)', '5', '15'); |
| |
| // Test nested in expressions |
| test_computed_value_in_range(property, 'calc(2 * random(6, 16))', '12', '32'); |
| |
| // Test NaN |
| test_computed_value(property, 'random(NaN, 100)', '0'); |
| test_computed_value(property, 'random(10, NaN)', '0'); |
| test_computed_value(property, 'random(NaN, NaN)', '0'); |
| test_computed_value(property, 'random(NaN, 100, by 10)', '0'); |
| test_computed_value(property, 'random(10, NaN, by 10)', '0'); |
| test_computed_value(property, 'random(NaN, NaN, by 10)', '0'); |
| test_computed_value(property, 'random(NaN, 100, by NaN)', '0'); |
| test_computed_value(property, 'random(10, NaN, by NaN)', '0'); |
| test_computed_value(property, 'random(NaN, NaN, by NaN)', '0'); |
| test_computed_value(property, 'random(10, 100, by NaN)', '0'); |
| test_computed_value(property, 'calc(10 + random(NaN, 100))', '0'); |
| test_computed_value(property, 'calc(10 + random(10, NaN))', '0'); |
| test_computed_value(property, 'calc(10 + random(NaN, NaN))', '0'); |
| test_computed_value(property, 'calc(10 + random(NaN, 100, by 10))', '0'); |
| test_computed_value(property, 'calc(10 + random(10, NaN, by 10))', '0'); |
| test_computed_value(property, 'calc(10 + random(NaN, NaN, by 10))', '0'); |
| test_computed_value(property, 'calc(10 + random(NaN, 100, by NaN))', '0'); |
| test_computed_value(property, 'calc(10 + random(10, NaN, by NaN))', '0'); |
| test_computed_value(property, 'calc(10 + random(NaN, NaN, by NaN))', '0'); |
| test_computed_value(property, 'calc(10 + random(10, 100, by NaN))', '0'); |
| |
| // Test infinity |
| test_computed_value(property, 'random(infinity, 100)', '0'); |
| test_computed_value(property, 'random(10, infinity)', '0'); |
| test_computed_value(property, 'random(infinity, infinity)', '0'); |
| test_computed_value(property, 'random(infinity, 100, by 10)', '0'); |
| test_computed_value(property, 'random(10, infinity, by 10)', '0'); |
| test_computed_value(property, 'random(infinity, infinity, by 10)', '0'); |
| test_computed_value(property, 'random(infinity, 100, by infinity)', '0'); |
| test_computed_value(property, 'random(10, infinity, by infinity)', '0'); |
| test_computed_value(property, 'random(infinity, infinity, by infinity)', '0'); |
| test_computed_value(property, 'calc(10 + random(infinity, 100))', '0'); |
| test_computed_value(property, 'calc(10 + random(10, infinity))', '0'); |
| test_computed_value(property, 'calc(10 + random(infinity, infinity))', '0'); |
| test_computed_value(property, 'calc(10 + random(infinity, 100, by 10))', '0'); |
| test_computed_value(property, 'calc(10 + random(10, infinity, by 10))', '0'); |
| test_computed_value(property, 'calc(10 + random(infinity, infinity, by 10))', '0'); |
| test_computed_value(property, 'calc(10 + random(infinity, 100, by infinity))', '0'); |
| test_computed_value(property, 'calc(10 + random(10, infinity, by infinity))', '0'); |
| test_computed_value(property, 'calc(10 + random(infinity, infinity, by infinity))', '0'); |
| // If only step is infinite, min is used. |
| test_computed_value(property, 'random(10, 100, by infinity)', '10'); |
| test_computed_value(property, 'random(10, 100, by -infinity)', '10'); |
| test_computed_value(property, 'calc(10 + random(10, 100, by infinity))', '20'); |
| test_computed_value(property, 'calc(10 + random(10, 100, by -infinity))', '20'); |
| |
| // Test pseudo on psuedo elements |
| test_pseudo_element_computed_value_in_range('scale', '::before', 'random(7, 17)', '7', '17'); |
| test_pseudo_element_computed_value_in_range('scale', '::before', 'random(--bar, 8, 18)', '8', '18'); |
| test_pseudo_element_computed_value_in_range('scale', '::before', 'random(per-element, 9, 19)', '9', '19'); |
| test_pseudo_element_computed_value_in_range('scale', '::before', 'random(per-element --foo, 10, 20)', '10', '20'); |
| |
| // Test identifier caching |
| test(() => { |
| const t1 = document.getElementById('noIdentifier1'); |
| const t2 = document.getElementById('noIdentifier2'); |
| |
| let t1Computed = getComputedStyle(t1)['width']; |
| let t2Computed = getComputedStyle(t2)['width']; |
| |
| assert_equals(t1Computed, t2Computed); |
| }, `Uses of a style rule on two elements with 'random(...)'`); |
| |
| test(() => { |
| const t1 = document.getElementById('identifier1'); |
| const t2 = document.getElementById('identifier2'); |
| |
| let t1Computed = getComputedStyle(t1)['width']; |
| let t2Computed = getComputedStyle(t2)['width']; |
| |
| assert_equals(t1Computed, t2Computed); |
| }, `Uses of a style rule on two elements with 'random(--identifier, ...)'`); |
| |
| test(() => { |
| const t1 = document.getElementById('identicalArguments1'); |
| const t2 = document.getElementById('identicalArguments2'); |
| |
| let t1Computed = getComputedStyle(t1)['width']; |
| let t2Computed = getComputedStyle(t2)['width']; |
| |
| assert_equals(t1Computed, t2Computed); |
| }, `Uses of two style rules on two elements with identical arguments`); |
| |
| test(() => { |
| const t1 = document.getElementById('identicalArgumentsAfterMath1'); |
| const t2 = document.getElementById('identicalArgumentsAfterMath2'); |
| |
| let t1Computed = getComputedStyle(t1)['width']; |
| let t2Computed = getComputedStyle(t2)['width']; |
| |
| assert_equals(t1Computed, t2Computed); |
| }, `Uses of two style rules on two elements with identical arguments after math has been resolved`); |
| |
| test(() => { |
| const t1 = document.getElementById('identicalArgumentsAfterUnitResolution1'); |
| const t2 = document.getElementById('identicalArgumentsAfterUnitResolution2'); |
| |
| let t1Computed = getComputedStyle(t1)['width']; |
| let t2Computed = getComputedStyle(t2)['width']; |
| |
| assert_equals(t1Computed, t2Computed); |
| }, `Uses of two style rules on two elements with identical arguments after unit resolution`); |
| |
| test(() => { |
| const style = 'width: calc(410px, 500px)'; |
| |
| const el1 = document.createElement('div'); |
| el1.style = style; |
| document.body.appendChild(el1); |
| const el1Computed = getComputedStyle(el1)['width']; |
| |
| const el2 = document.createElement('div'); |
| el2.style = style; |
| document.body.appendChild(el2); |
| const el2Computed = getComputedStyle(el2)['width']; |
| |
| assert_equals(el1Computed, el2Computed); |
| }, `Uses of two style rules on two elements with identical arguments accross two different style resolutions`); |
| |
| test(() => { |
| const el = document.getElementById('identicalTwoProperties'); |
| |
| let widthComputed = getComputedStyle(el)['width']; |
| let heightComputed = getComputedStyle(el)['height']; |
| |
| assert_equals(widthComputed, heightComputed); |
| }, `Uses of a style rule for two properies on an element with identical uses of random(...).`); |
| |
| test(() => { |
| const el = document.getElementById('identicalTwoPropertiesWithIdentifier'); |
| |
| let widthComputed = getComputedStyle(el)['width']; |
| let heightComputed = getComputedStyle(el)['height']; |
| |
| assert_equals(widthComputed, heightComputed); |
| }, `Uses of a style rule for two properies on an element with identical uses of random(--identifier, ...).`); |
| |
| test(() => { |
| const el = document.getElementById('identicalTwoPropertiesWithPerElement'); |
| |
| let widthComputed = getComputedStyle(el)['width']; |
| let heightComputed = getComputedStyle(el)['height']; |
| |
| assert_equals(widthComputed, heightComputed); |
| }, `Uses of a style rule for two properies on an element with identical uses of random(per-elemnent, ...).`); |
| |
| test(() => { |
| const el = document.getElementById('identicalTwoPropertiesWithPerElementAndIdentifier'); |
| |
| let widthComputed = getComputedStyle(el)['width']; |
| let heightComputed = getComputedStyle(el)['height']; |
| |
| assert_equals(widthComputed, heightComputed); |
| }, `Uses of a style rule for two properies on an element with identical uses of random(per-elemnent --identifier, ...).`); |
| |
| test(() => { |
| const el = document.createElement('div'); |
| el.className = 'randomPerElement'; |
| document.body.appendChild(el); |
| const elComputed = getComputedStyle(el)['width']; |
| |
| // It is statistically improbable that all 100 elements will have |
| // the same width when picked as a random number between 0 and 100000. |
| var allSame = true; |
| for (i = 0; i < 100; ++i) { |
| const other = document.createElement('div'); |
| other.className = 'randomPerElement'; |
| document.body.appendChild(other); |
| const otherComputed = getComputedStyle(other)['width']; |
| if (elComputed != otherComputed) { |
| allSame = false; |
| } |
| } |
| |
| assert_false(allSame); |
| }, `Uses of a style rule on multiple elements with 'random(per-element, ...)'`); |
| |
| </script> |