Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /* | |
| 6 Exported function: | |
| 7 assertResponsive | |
| 8 | |
| 9 Call signature: | |
| 10 assertResponsive({ | |
| 11 property: <CSS Property>, | |
| 12 from: ?<CSS Value>, | |
| 13 to: ?<CSS Value>, | |
| 14 configurations: [{ | |
| 15 state: { | |
| 16 ?targetStyle: { <CSS Property>: <CSS Value> }, | |
| 17 ?parentStyle: { <CSS Property>: <CSS Value> }, | |
| 18 }, | |
| 19 expect: [ | |
| 20 { at: <Float>, is: <CSS Value> } | |
| 21 ], | |
| 22 }], | |
| 23 }) | |
| 24 | |
| 25 Description: | |
| 26 assertResponsive takes a property specific interpolation and a list of style | |
| 27 configurations with interpolation expectations that apply to each | |
| 28 configuration. | |
| 29 It starts the interpolation in every configuration, changes the | |
| 30 state to every other configuration (n * (n - 1) complexity) and asserts that | |
| 31 each destination configuration's expectations are met. | |
| 32 This test is designed to catch stale interpolation caches. | |
| 33 */ | |
| 34 | |
| 35 (function() { | |
| 36 'use strict'; | |
| 37 var sharedStyle = null; | |
| 38 var animationCount = 0; | |
| 39 var pendingResponsiveTests = []; | |
| 40 | |
| 41 function assertResponsive(options) { | |
| 42 pendingResponsiveTests.push(options); | |
| 43 } | |
| 44 | |
| 45 function createTransitions(configurations) { | |
| 46 var transitions = []; | |
| 47 for (var i = 0; i < configurations.length; i++) { | |
| 48 var beforeConfiguration = configurations[i]; | |
| 49 var beforeExpect = beforeConfiguration.expect; | |
| 50 for (var j = i; j < configurations.length; j++) { | |
| 51 if (j == i) { | |
| 52 continue; | |
| 53 } | |
|
shans
2015/06/18 06:26:02
for (var j = i + 1; ...
alancutter (OOO until 2018)
2015/06/18 07:11:32
"var j = i" was a debugging tweak that got acciden
| |
| 54 var afterConfiguration = configurations[j]; | |
| 55 var afterExpect = afterConfiguration.expect; | |
| 56 | |
| 57 console.assert(beforeExpect.length == afterExpect.length); | |
| 58 for (var k = 0; k < beforeExpect.length; k++) { | |
| 59 console.assert(beforeExpect[k].at == afterExpect[k].at); | |
|
shans
2015/06/18 06:26:02
It's really not very obvious from the input data s
alancutter (OOO until 2018)
2015/06/18 07:11:32
On second thought there's no reason to require thi
| |
| 60 } | |
| 61 | |
| 62 transitions.push({ | |
| 63 before: beforeConfiguration, | |
| 64 after: afterConfiguration, | |
| 65 }); | |
| 66 } | |
| 67 } | |
| 68 return transitions; | |
| 69 } | |
| 70 | |
| 71 function createElement(tag, container) { | |
| 72 var element = document.createElement(tag); | |
| 73 if (container) { | |
| 74 container.appendChild(element); | |
| 75 } | |
| 76 return element; | |
| 77 } | |
| 78 | |
| 79 function createTargets(n, container) { | |
| 80 var targets = []; | |
| 81 for (var i = 0; i < n; i++) { | |
| 82 targets.push(createElement('div', container)); | |
| 83 } | |
| 84 return targets; | |
| 85 } | |
| 86 | |
| 87 function setInlineStyle(target, style) { | |
|
shans
2015/06/18 06:26:02
This seems predicated on specifying style dictiona
alancutter (OOO until 2018)
2015/06/18 07:11:32
I can't think of any tests that would need more th
| |
| 88 for (var property in style) { | |
| 89 target.style[property] = style[property]; | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 function setState(targets, state) { | |
| 94 var parentStyle = state.parentStyle; | |
| 95 if (parentStyle) { | |
| 96 var parent = targets[0].parentElement; | |
| 97 console.assert(targets.every(function(target) { return target.parentElement === parent; })); | |
| 98 setInlineStyle(parent, parentStyle); | |
| 99 } | |
| 100 var targetStyle = state.targetStyle; | |
| 101 if (targetStyle) { | |
| 102 for (var target of targets) { | |
| 103 setInlineStyle(target, targetStyle); | |
| 104 } | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 function createAnimationName() { | |
| 109 return 'anim' + (animationCount++); | |
| 110 } | |
| 111 | |
| 112 function createKeyframes(animationName, property, from, to) { | |
| 113 return ` | |
| 114 @keyframes ${animationName} { | |
| 115 from { ${property}: ${from}; } | |
| 116 to { ${property}: ${to}; } | |
| 117 }`; | |
| 118 } | |
| 119 | |
| 120 function addGlobalStyle(styleText) { | |
| 121 if (!sharedStyle) { | |
| 122 sharedStyle = createElement('style', document.documentElement); | |
| 123 } | |
| 124 sharedStyle.textContent += styleText; | |
| 125 } | |
| 126 | |
| 127 function startPausedAnimations(targets, animationName, fractions) { | |
| 128 console.assert(targets.length == fractions.length); | |
| 129 for (var i = 0; i < targets.length; i++) { | |
| 130 var target = targets[i]; | |
| 131 var fraction = fractions[i]; | |
| 132 console.assert(fraction >= 0 && fraction <= 1); | |
| 133 target.style.animation = `${animationName} 1s linear both paused`; | |
| 134 target.style.animationDelay = `${-fraction}s`; | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 function runPendingResponsiveTests() { | |
| 139 var transitionTests = []; | |
| 140 pendingResponsiveTests.forEach(function(options) { | |
| 141 var property = options.property; | |
| 142 var from = options.from; | |
| 143 var to = options.to; | |
| 144 var animationName = createAnimationName(); | |
| 145 addGlobalStyle(createKeyframes(animationName, property, from, to)); | |
| 146 | |
| 147 var transitions = createTransitions(options.configurations); | |
| 148 transitions.forEach(function(transition) { | |
| 149 var before = transition.before; | |
| 150 var after = transition.after; | |
| 151 var container = createElement('div', document.body); | |
| 152 var targets = createTargets(before.expect.length, container); | |
| 153 | |
| 154 setState(targets, before.state); | |
| 155 startPausedAnimations(targets, animationName, before.expect.map(function(e xpectation) { return expectation.at; })); | |
| 156 transitionTests.push({ | |
| 157 applyTransition() { | |
| 158 setState(targets, after.state); | |
| 159 }, | |
| 160 assert() { | |
| 161 for (var i = 0; i < targets.length; i++) { | |
| 162 var target = targets[i]; | |
| 163 var expectation = after.expect[i]; | |
| 164 var actual = getComputedStyle(target)[property]; | |
| 165 test(function() { | |
| 166 assert_equals(actual, expectation.is); | |
| 167 }, `Animation on property <${property}> from [${from}] to [${to}] wi th ${JSON.stringify(before.state)} changed to ${JSON.stringify(after.state)} at (${expectation.at}) is [${expectation.is}]`); | |
| 168 } | |
| 169 }, | |
| 170 }); | |
| 171 }); | |
| 172 }); | |
| 173 | |
| 174 // Force style recalc to instantiate animations internally. | |
| 175 getComputedStyle(document.body).color; | |
| 176 | |
| 177 // Separate style application and measurement into different phases to avoid a style recalc storm. | |
| 178 for (var transitionTest of transitionTests) { | |
| 179 transitionTest.applyTransition(); | |
| 180 } | |
| 181 for (var transitionTest of transitionTests) { | |
| 182 transitionTest.assert(); | |
| 183 } | |
|
shans
2015/06/18 06:26:02
why are these separate loops?
alancutter (OOO until 2018)
2015/06/18 07:11:32
The above comment describes. I batch the style mod
| |
| 184 } | |
| 185 | |
| 186 function loadScript(url) { | |
| 187 return new Promise(function(resolve) { | |
| 188 var script = document.createElement('script'); | |
| 189 script.src = url; | |
| 190 script.onload = resolve; | |
| 191 document.head.appendChild(script); | |
| 192 }); | |
| 193 } | |
| 194 | |
| 195 loadScript('../../resources/testharness.js').then(function() { | |
| 196 return loadScript('../../resources/testharnessreport.js'); | |
| 197 }).then(function() { | |
| 198 var asyncHandle = async_test('This test uses responsive-test.js.') | |
| 199 requestAnimationFrame(function() { | |
| 200 runPendingResponsiveTests(); | |
| 201 asyncHandle.done() | |
| 202 }); | |
| 203 }); | |
| 204 | |
| 205 | |
| 206 window.assertResponsive = assertResponsive; | |
| 207 | |
| 208 })(); | |
| OLD | NEW |