OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
46 * results. This function may not be used in a ref test. | 46 * results. This function may not be used in a ref test. |
47 * * convertToReference - This is intended to be used interactively to | 47 * * convertToReference - This is intended to be used interactively to |
48 * construct a reference given the results of a test. To build a | 48 * construct a reference given the results of a test. To build a |
49 * reference, run the test, open the inspector and trigger this | 49 * reference, run the test, open the inspector and trigger this |
50 * function, then copy/paste the results. | 50 * function, then copy/paste the results. |
51 */ | 51 */ |
52 'use strict'; | 52 'use strict'; |
53 (function() { | 53 (function() { |
54 var webkitPrefix = 'webkitAnimation' in document.documentElement.style ? '-web kit-' : ''; | 54 var webkitPrefix = 'webkitAnimation' in document.documentElement.style ? '-web kit-' : ''; |
55 var isRefTest = false; | 55 var isRefTest = false; |
56 var webAnimationsTest = typeof document.head.animate === 'function'; | |
dstockwell
2014/03/20 00:35:45
Element.prototype.animate
alancutter (OOO until 2018)
2014/03/20 04:59:56
Done.
| |
56 var startEvent = webkitPrefix ? 'webkitAnimationStart' : 'animationstart'; | 57 var startEvent = webkitPrefix ? 'webkitAnimationStart' : 'animationstart'; |
57 var endEvent = webkitPrefix ? 'webkitAnimationEnd' : 'animationend'; | 58 var endEvent = webkitPrefix ? 'webkitAnimationEnd' : 'animationend'; |
58 var testCount = 0; | 59 var testCount = 0; |
59 var animationEventCount = 0; | 60 var animationEventCount = 0; |
60 // FIXME: This should be 0, but 0 duration animations are broken in at least | 61 // FIXME: This should be 0, but 0 duration animations are broken in at least |
61 // pre-Web-Animations Blink, WebKit and Gecko. | 62 // pre-Web-Animations Blink, WebKit and Gecko. |
62 var durationSeconds = 0.001; | 63 var durationSeconds = 0.001; |
63 var iterationCount = 0.5; | 64 var iterationCount = 0.5; |
64 var delaySeconds = 0; | 65 var delaySeconds = 0; |
65 var cssText = '.test:hover:before {\n' + | 66 var cssText = '.test:hover:before {\n' + |
66 ' content: attr(description);\n' + | 67 ' content: attr(description);\n' + |
67 ' position: absolute;\n' + | 68 ' position: absolute;\n' + |
68 ' z-index: 1000;\n' + | 69 ' z-index: 1000;\n' + |
69 ' background: gold;\n' + | 70 ' background: gold;\n' + |
70 '}\n'; | 71 '}\n'; |
71 var fragment = document.createDocumentFragment(); | 72 var fragment = document.createDocumentFragment(); |
73 var fragmentAttachedListeners = []; | |
72 var style = document.createElement('style'); | 74 var style = document.createElement('style'); |
75 var cssTests = document.createElement('div'); | |
76 cssTests.id = 'css-tests'; | |
73 var afterTestCallback = null; | 77 var afterTestCallback = null; |
74 fragment.appendChild(style); | 78 fragment.appendChild(style); |
79 fragment.appendChild(cssTests); | |
80 | |
81 if (webAnimationsTest) { | |
82 var waTests = document.createElement('div'); | |
83 waTests.id = 'web-animations-tests'; | |
84 fragment.appendChild(waTests); | |
85 } | |
75 | 86 |
76 var updateScheduled = false; | 87 var updateScheduled = false; |
77 function maybeScheduleUpdate() { | 88 function maybeScheduleUpdate() { |
78 if (updateScheduled) { | 89 if (updateScheduled) { |
79 return; | 90 return; |
80 } | 91 } |
81 updateScheduled = true; | 92 updateScheduled = true; |
82 setTimeout(function() { | 93 setTimeout(function() { |
83 updateScheduled = false; | 94 updateScheduled = false; |
84 style.innerHTML = cssText; | 95 style.innerHTML = cssText; |
85 document.body.appendChild(fragment); | 96 document.body.appendChild(fragment); |
97 fragmentAttachedListeners.forEach(function(listener) {listener();}); | |
86 }, 0); | 98 }, 0); |
87 } | 99 } |
88 | 100 |
89 function dumpResults() { | 101 function dumpResults() { |
90 var targets = document.querySelectorAll('.target.active'); | 102 var targets = document.querySelectorAll('.target.active'); |
91 if (isRefTest) { | 103 if (isRefTest) { |
92 // Convert back to reference to avoid cases where the computed style is | 104 // Convert back to reference to avoid cases where the computed style is |
93 // out of sync with the compositor. | 105 // out of sync with the compositor. |
94 for (var i = 0; i < targets.length; i++) { | 106 for (var i = 0; i < targets.length; i++) { |
95 targets[i].convertToReference(); | 107 targets[i].convertToReference(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
149 | 161 |
150 function testInterpolationAt(fractions, params) { | 162 function testInterpolationAt(fractions, params) { |
151 if (!Array.isArray(fractions)) { | 163 if (!Array.isArray(fractions)) { |
152 fractions = [fractions]; | 164 fractions = [fractions]; |
153 } | 165 } |
154 assertInterpolation(params, fractions.map(function(fraction) { | 166 assertInterpolation(params, fractions.map(function(fraction) { |
155 return {at: fraction}; | 167 return {at: fraction}; |
156 })); | 168 })); |
157 } | 169 } |
158 | 170 |
159 function describeTest(params) { | 171 function createTestContainer(description, className) { |
160 return params.property + ': from [' + params.from + '] to [' + params.to + ' ]'; | 172 var testContainer = document.createElement('div'); |
173 testContainer.setAttribute('description', description); | |
174 testContainer.classList.add('test'); | |
175 if (className) { | |
176 testContainer.classList.add(className); | |
177 } | |
178 return testContainer; | |
179 } | |
180 | |
181 function convertPropertyToCamelCase(property) { | |
182 return property.replace(/^-/, '').replace(/-\w/g, function(m) {return m[1].t oUpperCase();}); | |
183 } | |
184 | |
185 function describeCSSTest(params) { | |
186 return 'CSS ' + params.property + ': from [' + params.from + '] to [' + para ms.to + ']'; | |
187 } | |
188 | |
189 function describeWATest(params) { | |
190 return 'element.animate() ' + convertPropertyToCamelCase(params.property) + ': from [' + params.from + '] to [' + params.to + ']'; | |
161 } | 191 } |
162 | 192 |
163 function assertInterpolation(params, expectations) { | 193 function assertInterpolation(params, expectations) { |
164 // If the prefixed property is not supported, try to unprefix it. | 194 // If the prefixed property is not supported, try to unprefix it. |
165 if (/^-[^-]+-/.test(params.property) && !CSS.supports(params.property, 'init ial')) { | 195 if (/^-[^-]+-/.test(params.property) && !CSS.supports(params.property, 'init ial')) { |
166 var unprefixed = params.property.replace(/^-[^-]+-/, ''); | 196 var unprefixed = params.property.replace(/^-[^-]+-/, ''); |
167 if (CSS.supports(unprefixed, 'initial')) { | 197 if (CSS.supports(unprefixed, 'initial')) { |
168 params.property = unprefixed; | 198 params.property = unprefixed; |
169 } | 199 } |
170 } | 200 } |
171 var testId = defineKeyframes(params); | 201 var testId = defineKeyframes(params); |
172 var nextCaseId = 0; | 202 var nextCaseId = 0; |
173 var testContainer = document.createElement('div'); | 203 var cssTestContainer = createTestContainer(describeCSSTest(params), testId); |
174 testContainer.setAttribute('description', describeTest(params)); | 204 cssTests.appendChild(cssTestContainer); |
175 testContainer.classList.add('test'); | 205 if (webAnimationsTest) { |
176 testContainer.classList.add(testId); | 206 var waTestContainer = createTestContainer(describeWATest(params), testId); |
177 fragment.appendChild(testContainer); | 207 waTests.appendChild(waTestContainer); |
208 } | |
178 expectations.forEach(function(expectation) { | 209 expectations.forEach(function(expectation) { |
179 testContainer.appendChild(makeInterpolationTest( | 210 cssTestContainer.appendChild(makeInterpolationTest( |
180 expectation.at, testId, 'case-' + ++nextCaseId, params, expectation.is )); | 211 true, expectation.at, testId, 'case-' + ++nextCaseId, params, expectat ion.is)); |
181 }); | 212 }); |
213 if (webAnimationsTest) { | |
214 expectations.forEach(function(expectation) { | |
215 waTestContainer.appendChild(makeInterpolationTest( | |
216 false, expectation.at, testId, 'case-' + ++nextCaseId, params, expec tation.is)); | |
217 }); | |
218 } | |
182 maybeScheduleUpdate(); | 219 maybeScheduleUpdate(); |
183 } | 220 } |
184 | 221 |
185 var nextKeyframeId = 0; | 222 var nextKeyframeId = 0; |
186 function defineKeyframes(params) { | 223 function defineKeyframes(params) { |
187 var testId = 'test-' + ++nextKeyframeId; | 224 var testId = 'test-' + ++nextKeyframeId; |
188 cssText += '@' + webkitPrefix + 'keyframes ' + testId + ' { \n' + | 225 cssText += '@' + webkitPrefix + 'keyframes ' + testId + ' { \n' + |
189 ' 0% { ' + params.property + ': ' + params.from + '; }\n' + | 226 ' 0% { ' + params.property + ': ' + params.from + '; }\n' + |
190 ' 100% { ' + params.property + ': ' + params.to + '; }\n' + | 227 ' 100% { ' + params.property + ': ' + params.to + '; }\n' + |
191 '}\n'; | 228 '}\n'; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
236 var url = /url\(([^\)]*)\)/g.exec(matches[i])[1]; | 273 var url = /url\(([^\)]*)\)/g.exec(matches[i])[1]; |
237 var anchor = document.createElement('a'); | 274 var anchor = document.createElement('a'); |
238 anchor.href = url; | 275 anchor.href = url; |
239 anchor.pathname = '...' + anchor.pathname.substring(anchor.pathname.last IndexOf('/')); | 276 anchor.pathname = '...' + anchor.pathname.substring(anchor.pathname.last IndexOf('/')); |
240 value = value.replace(matches[i], 'url(' + anchor.href + ')'); | 277 value = value.replace(matches[i], 'url(' + anchor.href + ')'); |
241 } | 278 } |
242 } | 279 } |
243 return value; | 280 return value; |
244 } | 281 } |
245 | 282 |
246 function makeInterpolationTest(fraction, testId, caseId, params, expectation) { | 283 function makeInterpolationTest(cssTest, fraction, testId, caseId, params, expe ctation) { |
247 console.assert(expectation === undefined || !isRefTest); | 284 console.assert(expectation === undefined || !isRefTest); |
248 var targetContainer = createTargetContainer(caseId); | 285 var targetContainer = createTargetContainer(caseId); |
249 var target = targetContainer.querySelector('.target') || targetContainer; | 286 var target = targetContainer.querySelector('.target') || targetContainer; |
250 target.classList.add('active'); | 287 target.classList.add('active'); |
251 var replicaContainer, replica; | 288 var replicaContainer, replica; |
252 if (expectation !== undefined) { | 289 if (expectation !== undefined) { |
253 replicaContainer = createTargetContainer(caseId); | 290 replicaContainer = createTargetContainer(caseId); |
254 replica = replicaContainer.querySelector('.target') || replicaContainer; | 291 replica = replicaContainer.querySelector('.target') || replicaContainer; |
255 replica.classList.add('replica'); | 292 replica.classList.add('replica'); |
256 replica.style.setProperty(params.property, expectation); | 293 replica.style.setProperty(params.property, expectation); |
257 } | 294 } |
258 target.getResultString = function() { | 295 target.getResultString = function() { |
259 if (!CSS.supports(params.property, expectation)) { | 296 if (!CSS.supports(params.property, expectation)) { |
260 return 'FAIL: [' + params.property + ': ' + expectation + '] is not supp orted'; | 297 return 'FAIL: [' + params.property + ': ' + expectation + '] is not supp orted'; |
261 } | 298 } |
262 var value = getComputedStyle(this).getPropertyValue(params.property); | 299 var value = getComputedStyle(this).getPropertyValue(params.property); |
263 var result = ''; | 300 var result = ''; |
264 var reason = ''; | 301 var reason = ''; |
302 var property = cssTest ? params.property : convertPropertyToCamelCase(para ms.property); | |
265 if (expectation !== undefined) { | 303 if (expectation !== undefined) { |
266 var parsedExpectation = getComputedStyle(replica).getPropertyValue(param s.property); | 304 var parsedExpectation = getComputedStyle(replica).getPropertyValue(param s.property); |
267 var pass = normalizeValue(value) === normalizeValue(parsedExpectation); | 305 var pass = normalizeValue(value) === normalizeValue(parsedExpectation); |
268 result = pass ? 'PASS: ' : 'FAIL: '; | 306 result = pass ? 'PASS: ' : 'FAIL: '; |
269 reason = pass ? '' : ', expected [' + expectation + ']' + | 307 reason = pass ? '' : ', expected [' + expectation + ']' + |
270 (expectation === parsedExpectation ? '' : ' (parsed as [' + sanitize Urls(parsedExpectation) + '])'); | 308 (expectation === parsedExpectation ? '' : ' (parsed as [' + sanitize Urls(parsedExpectation) + '])'); |
271 value = pass ? expectation : sanitizeUrls(value); | 309 value = pass ? expectation : sanitizeUrls(value); |
272 } | 310 } |
273 return result + params.property + ' from [' + params.from + '] to ' + | 311 return result + property + ' from [' + params.from + '] to ' + |
274 '[' + params.to + '] was [' + value + ']' + | 312 '[' + params.to + '] was [' + value + ']' + |
275 ' at ' + fraction + reason; | 313 ' at ' + fraction + reason; |
276 }; | 314 }; |
277 target.convertToReference = function() { | 315 target.convertToReference = function() { |
278 this.style[params.property] = getComputedStyle(this).getPropertyValue(para ms.property); | 316 this.style[params.property] = getComputedStyle(this).getPropertyValue(para ms.property); |
279 }; | 317 }; |
280 var easing = createEasing(fraction); | 318 var easing = createEasing(fraction); |
281 cssText += '.' + testId + ' .' + caseId + '.active {\n' + | |
282 ' ' + webkitPrefix + 'animation: ' + testId + ' ' + durationSeconds + ' s forwards;\n' + | |
283 ' ' + webkitPrefix + 'animation-timing-function: ' + easing + ';\n' + | |
284 ' ' + webkitPrefix + 'animation-iteration-count: ' + iterationCount + ' ;\n' + | |
285 ' ' + webkitPrefix + 'animation-delay: ' + delaySeconds + 's;\n' + | |
286 '}\n'; | |
287 testCount++; | 319 testCount++; |
320 if (cssTest) { | |
321 cssText += '.' + testId + ' .' + caseId + '.active {\n' + | |
322 ' ' + webkitPrefix + 'animation: ' + testId + ' ' + durationSeconds + 's forwards;\n' + | |
323 ' ' + webkitPrefix + 'animation-timing-function: ' + easing + ';\n' + | |
324 ' ' + webkitPrefix + 'animation-iteration-count: ' + iterationCount + ';\n' + | |
325 ' ' + webkitPrefix + 'animation-delay: ' + delaySeconds + 's;\n' + | |
326 '}\n'; | |
327 } else { | |
328 var keyframes = [{}, {}]; | |
329 keyframes[0][convertPropertyToCamelCase(params.property)] = params.from; | |
330 keyframes[1][convertPropertyToCamelCase(params.property)] = params.to; | |
331 fragmentAttachedListeners.push(function() { | |
332 target.animate(keyframes, { | |
333 fill: 'forwards', | |
334 duration: 1, | |
335 easing: easing, | |
336 delay: -0.5, | |
337 iterations: 0.5, | |
338 }); | |
339 animationEnded(); | |
340 }); | |
341 } | |
288 var testFragment = document.createDocumentFragment(); | 342 var testFragment = document.createDocumentFragment(); |
289 testFragment.appendChild(targetContainer); | 343 testFragment.appendChild(targetContainer); |
290 replica && testFragment.appendChild(replicaContainer); | 344 replica && testFragment.appendChild(replicaContainer); |
291 testFragment.appendChild(document.createTextNode('\n')); | 345 testFragment.appendChild(document.createTextNode('\n')); |
292 return testFragment; | 346 return testFragment; |
293 } | 347 } |
294 | 348 |
295 var finished = false; | 349 var finished = false; |
296 function finishTest() { | 350 function finishTest() { |
297 finished = true; | 351 finished = true; |
(...skipping 13 matching lines...) Expand all Loading... | |
311 } | 365 } |
312 | 366 |
313 if (window.testRunner) { | 367 if (window.testRunner) { |
314 testRunner.waitUntilDone(); | 368 testRunner.waitUntilDone(); |
315 } | 369 } |
316 | 370 |
317 function isLastAnimationEvent() { | 371 function isLastAnimationEvent() { |
318 return !finished && animationEventCount === testCount; | 372 return !finished && animationEventCount === testCount; |
319 } | 373 } |
320 | 374 |
321 function endEventListener() { | 375 function animationEnded() { |
322 animationEventCount++; | 376 animationEventCount++; |
323 if (!isLastAnimationEvent()) { | 377 if (!isLastAnimationEvent()) { |
324 return; | 378 return; |
325 } | 379 } |
326 finishTest(); | 380 finishTest(); |
327 } | 381 } |
328 | 382 |
329 if (window.internals) { | 383 if (window.internals) { |
330 durationSeconds = 0; | 384 durationSeconds = 0; |
331 document.documentElement.addEventListener(endEvent, endEventListener); | 385 document.documentElement.addEventListener(endEvent, animationEnded); |
332 } else if (webkitPrefix) { | 386 } else if (webkitPrefix) { |
333 durationSeconds = 1e9; | 387 durationSeconds = 1e9; |
334 iterationCount = 1; | 388 iterationCount = 1; |
335 delaySeconds = -durationSeconds / 2; | 389 delaySeconds = -durationSeconds / 2; |
336 document.documentElement.addEventListener(startEvent, function() { | 390 document.documentElement.addEventListener(startEvent, function() { |
337 animationEventCount++; | 391 animationEventCount++; |
338 if (!isLastAnimationEvent()) { | 392 if (!isLastAnimationEvent()) { |
339 return; | 393 return; |
340 } | 394 } |
341 setTimeout(finishTest, 0); | 395 setTimeout(finishTest, 0); |
342 }); | 396 }); |
343 } else { | 397 } else { |
344 document.documentElement.addEventListener(endEvent, endEventListener); | 398 document.documentElement.addEventListener(endEvent, animationEnded); |
345 } | 399 } |
346 | 400 |
347 if (!window.testRunner) { | 401 if (!window.testRunner) { |
348 setTimeout(function() { | 402 setTimeout(function() { |
349 if (finished) { | 403 if (finished) { |
350 return; | 404 return; |
351 } | 405 } |
352 finishTest(); | 406 finishTest(); |
353 }, 10000); | 407 }, 10000); |
354 } | 408 } |
355 | 409 |
356 window.runAsRefTest = runAsRefTest; | 410 window.runAsRefTest = runAsRefTest; |
357 window.testInterpolationAt = testInterpolationAt; | 411 window.testInterpolationAt = testInterpolationAt; |
358 window.assertInterpolation = assertInterpolation; | 412 window.assertInterpolation = assertInterpolation; |
359 window.convertToReference = convertToReference; | 413 window.convertToReference = convertToReference; |
360 window.afterTest = afterTest; | 414 window.afterTest = afterTest; |
361 })(); | 415 })(); |
OLD | NEW |