Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: third_party/WebKit/LayoutTests/animations/responsive/resources/responsive-test.js

Issue 1450123003: Add SVG animation support to responsive-test.js (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@_responsiveNeutralValueFormat
Patch Set: Review changes Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /* 5 /*
6 Exported function: 6 Exported functions:
7 assertResponsive 7 assertCSSResponsive
8 assertSVGResponsive
8 9
9 Call signature: 10 Options format: {
10 assertResponsive({ 11 ?targetTag: <Target element tag name>,
11 property: <CSS Property>, 12 property: <Property/Attribute name>,
12 ?from: <CSS Value>, 13 ?getter(target): <Reads animated value from target>,
13 ?to: <CSS Value>, 14 ?from: <Value>,
15 ?to: <Value>,
14 configurations: [{ 16 configurations: [{
15 state: { 17 state: {
16 ?underlying: <CSS Value>, 18 ?underlying: <Value>,
17 ?inherited: <CSS Value>, 19 ?inherited: <CSS Value>,
18 }, 20 },
19 expect: [ 21 expect: [
20 { at: <Float>, is: <CSS Value> } 22 { at: <Float>, is: <Value> },
21 ], 23 ],
22 }], 24 }],
23 }) 25 }
24 26
25 Description: 27 Description:
26 assertResponsive takes a property specific interpolation and a list of style 28 assertCSSResponsive() and assertSVGResponsive() take a property
27 configurations with interpolation expectations that apply to each 29 specific interpolation and a list of style configurations with interpolation
28 configuration. 30 expectations that apply to each configuration.
29 It starts the interpolation in every configuration, changes the 31 It starts the interpolation in every configuration, changes the
30 state to every other configuration (n * (n - 1) complexity) and asserts that 32 state to every other configuration (n * (n - 1) complexity) and asserts that
31 each destination configuration's expectations are met. 33 each destination configuration's expectations are met.
32 Each animation target can be assigned custom styles via the ".target" selector. 34 Each animation target can be assigned custom styles via the ".target" selector.
33 This test is designed to catch stale interpolation caches. 35 This test is designed to catch stale interpolation caches.
34 */ 36 */
35 37
36 (function() { 38 (function() {
37 'use strict'; 39 'use strict';
38 var pendingResponsiveTests = []; 40 var pendingResponsiveTests = [];
41 var htmlNamespace = 'http://www.w3.org/1999/xhtml';
42 var svgNamespace = 'http://www.w3.org/2000/svg';
39 43
40 function assertResponsive(options) { 44 function assertCSSResponsive(options) {
41 pendingResponsiveTests.push(options); 45 pendingResponsiveTests.push({
46 options,
47 bindings: {
48 prefixProperty(property) {
49 return property;
50 },
51 createTargetContainer(container) {
52 return createElement('div', container);
53 },
54 createTarget(container) {
55 return createElement('div', container, 'target');
56 },
57 setValue(target, property, value) {
58 target.style[property] = value;
59 },
60 getAnimatedValue(target, property) {
61 return getComputedStyle(target)[property];
62 },
63 },
64 });
65 }
66
67 function assertSVGResponsive(options) {
68 pendingResponsiveTests.push({
69 options,
70 bindings: {
71 prefixProperty(property) {
72 return 'svg' + property[0].toUpperCase() + property.slice(1);
73 },
74 createTargetContainer(container) {
75 var svgRoot = createElement('svg', container, 'svg-root', svgNamespace);
76 svgRoot.setAttribute('width', 0);
77 svgRoot.setAttribute('height', 0);
78 return svgRoot;
79 },
80 createTarget(targetContainer) {
81 console.assert(options.targetTag);
82 return createElement(options.targetTag, targetContainer, 'target', svgNa mespace);
83 },
84 setValue(target, property, value) {
85 target.setAttribute(property, value);
86 },
87 getAnimatedValue(target, property) {
88 return options.getter ? options.getter(target) : target[property].animVa l;
89 },
90 },
91 });
42 } 92 }
43 93
44 function createStateTransitions(configurations) { 94 function createStateTransitions(configurations) {
45 var stateTransitions = []; 95 var stateTransitions = [];
46 for (var i = 0; i < configurations.length; i++) { 96 for (var i = 0; i < configurations.length; i++) {
47 var beforeConfiguration = configurations[i]; 97 var beforeConfiguration = configurations[i];
48 for (var j = 0; j < configurations.length; j++) { 98 for (var j = 0; j < configurations.length; j++) {
49 var afterConfiguration = configurations[j]; 99 var afterConfiguration = configurations[j];
50 if (j != i) { 100 if (j != i) {
51 stateTransitions.push({ 101 stateTransitions.push({
52 before: beforeConfiguration, 102 before: beforeConfiguration,
53 after: afterConfiguration, 103 after: afterConfiguration,
54 }); 104 });
55 } 105 }
56 } 106 }
57 } 107 }
58 return stateTransitions; 108 return stateTransitions;
59 } 109 }
60 110
61 function createElement(tag, container, className) { 111 function createElement(tag, container, className, namespace) {
62 var element = document.createElement(tag); 112 var element = document.createElementNS(namespace || htmlNamespace, tag);
63 if (container) { 113 if (container) {
64 container.appendChild(element); 114 container.appendChild(element);
65 } 115 }
66 if (className) { 116 if (className) {
67 element.classList.add(className); 117 element.classList.add(className);
68 } 118 }
69 return element; 119 return element;
70 } 120 }
71 121
72 function createTargets(n, container) { 122 function createTargets(bindings, n, container) {
73 var targets = []; 123 var targets = [];
74 for (var i = 0; i < n; i++) { 124 for (var i = 0; i < n; i++) {
75 targets.push(createElement('div', container, 'target')); 125 targets.push(bindings.createTarget(container));
76 } 126 }
77 return targets; 127 return targets;
78 } 128 }
79 129
80 function setState(targets, property, state) { 130 function setState(bindings, targets, property, state) {
81 if (state.inherited) { 131 if (state.inherited) {
82 var parent = targets[0].parentElement; 132 var parent = targets[0].parentElement;
83 console.assert(targets.every(function(target) { return target.parentElement === parent; })); 133 console.assert(targets.every(function(target) { return target.parentElement === parent; }));
84 parent.style[property] = state.inherited; 134 bindings.setValue(parent, property, state.inherited);
85 } 135 }
86 if (state.underlying) { 136 if (state.underlying) {
87 for (var target of targets) { 137 for (var target of targets) {
88 target.style[property] = state.underlying; 138 bindings.setValue(target, property, state.underlying);
89 } 139 }
90 } 140 }
91 } 141 }
92 142
93 function keyframeText(options, keyframeName) { 143 function keyframeText(options, keyframeName) {
94 return (keyframeName in options) ? `[${options[keyframeName]}]` : 'neutral'; 144 return (keyframeName in options) ? `[${options[keyframeName]}]` : 'neutral';
95 } 145 }
96 146
97 function createKeyframes(options) { 147 function createKeyframes(prefixedProperty, options) {
98 var keyframes = []; 148 var keyframes = [];
99 if ('from' in options) { 149 if ('from' in options) {
100 keyframes.push({ 150 keyframes.push({
101 offset: 0, 151 offset: 0,
102 [options.property]: options.from, 152 [prefixedProperty]: options.from,
103 }); 153 });
104 } 154 }
105 if ('to' in options) { 155 if ('to' in options) {
106 keyframes.push({ 156 keyframes.push({
107 offset: 1, 157 offset: 1,
108 [options.property]: options.to, 158 [prefixedProperty]: options.to,
109 }); 159 });
110 } 160 }
111 return keyframes; 161 return keyframes;
112 } 162 }
113 163
114 function startPausedAnimations(targets, keyframes, fractions) { 164 function startPausedAnimations(targets, keyframes, fractions) {
115 console.assert(targets.length == fractions.length); 165 console.assert(targets.length == fractions.length);
116 for (var i = 0; i < targets.length; i++) { 166 for (var i = 0; i < targets.length; i++) {
117 var target = targets[i]; 167 var target = targets[i];
118 var fraction = fractions[i]; 168 var fraction = fractions[i];
119 console.assert(fraction >= 0 && fraction < 1); 169 console.assert(fraction >= 0 && fraction < 1);
120 var animation = target.animate(keyframes, 1); 170 var animation = target.animate(keyframes, 1);
121 animation.currentTime = fraction; 171 animation.currentTime = fraction;
122 animation.pause(); 172 animation.pause();
123 } 173 }
124 } 174 }
125 175
126 function runPendingResponsiveTests() { 176 function runPendingResponsiveTests() {
127 var stateTransitionTests = []; 177 return new Promise(function(resolve) {
128 pendingResponsiveTests.forEach(function(options) { 178 var stateTransitionTests = [];
129 var property = options.property; 179 pendingResponsiveTests.forEach(function(responsiveTest) {
130 var from = options.from; 180 var options = responsiveTest.options;
131 var to = options.to; 181 var bindings = responsiveTest.bindings;
132 var keyframes = createKeyframes(options); 182 var property = options.property;
133 var fromText = keyframeText(options, 'from'); 183 var prefixedProperty = bindings.prefixProperty(property);
134 var toText = keyframeText(options, 'to'); 184 var from = options.from;
185 var to = options.to;
186 var keyframes = createKeyframes(prefixedProperty, options);
187 var fromText = keyframeText(options, 'from');
188 var toText = keyframeText(options, 'to');
135 189
136 var stateTransitions = createStateTransitions(options.configurations); 190 var stateTransitions = createStateTransitions(options.configurations);
137 stateTransitions.forEach(function(stateTransition) { 191 stateTransitions.forEach(function(stateTransition) {
138 var before = stateTransition.before; 192 var before = stateTransition.before;
139 var after = stateTransition.after; 193 var after = stateTransition.after;
140 var container = createElement('div', document.body); 194 var container = bindings.createTargetContainer(document.body);
141 var targets = createTargets(after.expect.length, container); 195 var targets = createTargets(bindings, after.expect.length, container);
142 196
143 setState(targets, property, before.state); 197 setState(bindings, targets, property, before.state);
144 startPausedAnimations(targets, keyframes, after.expect.map(function(expect ation) { return expectation.at; })); 198 startPausedAnimations(targets, keyframes, after.expect.map(function(expe ctation) { return expectation.at; }));
145 stateTransitionTests.push({ 199 stateTransitionTests.push({
146 applyStateTransition() { 200 applyStateTransition() {
147 setState(targets, property, after.state); 201 setState(bindings, targets, property, after.state);
148 }, 202 },
149 assert() { 203 assert() {
150 for (var i = 0; i < targets.length; i++) { 204 for (var i = 0; i < targets.length; i++) {
151 var target = targets[i]; 205 var target = targets[i];
152 var expectation = after.expect[i]; 206 var expectation = after.expect[i];
153 var actual = getComputedStyle(target)[property]; 207 var actual = bindings.getAnimatedValue(target, property);
154 test(function() { 208 test(function() {
155 assert_equals(actual, expectation.is); 209 assert_equals(actual, expectation.is);
156 }, `Animation on property <${property}> from ${fromText} to ${toText } with ${JSON.stringify(before.state)} changed to ${JSON.stringify(after.state)} at (${expectation.at}) is [${expectation.is}]`); 210 }, `Animation on property <${prefixedProperty}> from ${fromText} t o ${toText} with ${JSON.stringify(before.state)} changed to ${JSON.stringify(aft er.state)} at (${expectation.at}) is [${expectation.is}]`);
157 } 211 }
158 }, 212 },
213 });
159 }); 214 });
160 }); 215 });
216
217 for (var stateTransitionTest of stateTransitionTests) {
218 stateTransitionTest.applyStateTransition();
219 }
220
221 requestAnimationFrame(function() {
222 for (var stateTransitionTest of stateTransitionTests) {
223 stateTransitionTest.assert();
224 }
225 resolve();
226 });
161 }); 227 });
162
163 // Separate style modification from measurement as different phases to avoid a style recalc storm.
164 for (var stateTransitionTest of stateTransitionTests) {
165 stateTransitionTest.applyStateTransition();
166 }
167 for (var stateTransitionTest of stateTransitionTests) {
168 stateTransitionTest.assert();
169 }
170 } 228 }
171 229
172 function loadScript(url) { 230 function loadScript(url) {
173 return new Promise(function(resolve) { 231 return new Promise(function(resolve) {
174 var script = document.createElement('script'); 232 var script = document.createElement('script');
175 script.src = url; 233 script.src = url;
176 script.onload = resolve; 234 script.onload = resolve;
177 document.head.appendChild(script); 235 document.head.appendChild(script);
178 }); 236 });
179 } 237 }
180 238
181 loadScript('../../resources/testharness.js').then(function() { 239 loadScript('../../resources/testharness.js').then(function() {
182 return loadScript('../../resources/testharnessreport.js'); 240 return loadScript('../../resources/testharnessreport.js');
183 }).then(function() { 241 }).then(function() {
184 var asyncHandle = async_test('This test uses responsive-test.js.') 242 var asyncHandle = async_test('This test uses responsive-test.js.')
185 requestAnimationFrame(function() { 243 runPendingResponsiveTests().then(function() {
186 runPendingResponsiveTests(); 244 asyncHandle.done();
187 asyncHandle.done()
188 }); 245 });
189 }); 246 });
190 247
191 248
192 window.assertResponsive = assertResponsive; 249 window.assertCSSResponsive = assertCSSResponsive;
250 window.assertSVGResponsive = assertSVGResponsive;
193 251
194 })(); 252 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698