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>