OLD | NEW |
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <meta charset=utf-8> | 2 <meta charset=utf-8> |
3 <title>KeyframeEffectReadOnly constructor tests</title> | 3 <title>KeyframeEffectReadOnly constructor tests</title> |
4 <link rel="help" href="https://w3c.github.io/web-animations/#processing-a-keyfra
mes-argument"> | 4 <link rel="help" href="https://w3c.github.io/web-animations/#processing-a-keyfra
mes-argument"> |
5 <script src="/resources/testharness.js"></script> | 5 <script src="/resources/testharness.js"></script> |
6 <script src="/resources/testharnessreport.js"></script> | 6 <script src="/resources/testharnessreport.js"></script> |
7 <script src="../../testcommon.js"></script> | 7 <script src="../../testcommon.js"></script> |
| 8 <script src="../../resources/keyframe-utils.js"></script> |
8 <body> | 9 <body> |
9 <div id="log"></div> | 10 <div id="log"></div> |
10 <div id="target"></div> | 11 <div id="target"></div> |
11 <script> | 12 <script> |
12 'use strict'; | 13 'use strict'; |
13 | 14 |
14 // Test the "process a keyframe-like object" procedure. | 15 // Test the "process a keyframe-like object" procedure. |
15 // | 16 // |
16 // This file only tests the KeyframeEffectReadOnly constructor since it is | 17 // This file only tests the KeyframeEffectReadOnly constructor since it is |
17 // assumed that the implementation of the KeyframeEffect constructor, | 18 // assumed that the implementation of the KeyframeEffect constructor, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 test(function(t) { | 73 test(function(t) { |
73 var testKeyframes = GetTestKeyframeSequence(prop); | 74 var testKeyframes = GetTestKeyframeSequence(prop); |
74 | 75 |
75 new KeyframeEffectReadOnly(null, testKeyframes); | 76 new KeyframeEffectReadOnly(null, testKeyframes); |
76 | 77 |
77 assert_equals(testKeyframes[0].propAccessCount, 0, 'Accessor not called'); | 78 assert_equals(testKeyframes[0].propAccessCount, 0, 'Accessor not called'); |
78 }, 'non-animatable property \'' + prop + '\' is not accessed when using' | 79 }, 'non-animatable property \'' + prop + '\' is not accessed when using' |
79 + ' a keyframe sequence'); | 80 + ' a keyframe sequence'); |
80 }); | 81 }); |
81 | 82 |
82 // FIXME: Test that non-enumerable properties are not accessed | 83 // Test equivalent forms of property indexed and sequenced keyframe syntax |
| 84 |
| 85 function assertEquivalentKeyframeSyntax(keyframesA, keyframesB) { |
| 86 var processedKeyframesA = new KeyframeEffectReadOnly(null, keyframesA).getKeyf
rames(); |
| 87 var processedKeyframesB = new KeyframeEffectReadOnly(null, keyframesB).getKeyf
rames(); |
| 88 assert_frame_lists_equal(processedKeyframesA, processedKeyframesB); |
| 89 } |
| 90 |
| 91 var gEquivalentSyntaxTests = [ |
| 92 { |
| 93 description: 'two properties with one value', |
| 94 indexedKeyframes: { |
| 95 left: '100px', |
| 96 opacity: ['1'], |
| 97 }, |
| 98 sequencedKeyframes: [ |
| 99 {left: '100px', opacity: '1'}, |
| 100 ], |
| 101 }, |
| 102 { |
| 103 description: 'two properties with three values', |
| 104 indexedKeyframes: { |
| 105 left: ['10px', '100px', '150px'], |
| 106 opacity: ['1', '0', '1'], |
| 107 }, |
| 108 sequencedKeyframes: [ |
| 109 {left: '10px', opacity: '1'}, |
| 110 {left: '100px', opacity: '0'}, |
| 111 {left: '150px', opacity: '1'}, |
| 112 ], |
| 113 }, |
| 114 { |
| 115 description: 'two properties with different numbers of values', |
| 116 indexedKeyframes: { |
| 117 left: ['0px', '100px', '200px'], |
| 118 opacity: ['0', '1'] |
| 119 }, |
| 120 sequencedKeyframes: [ |
| 121 {left: '0px', opacity: '0'}, |
| 122 {left: '100px'}, |
| 123 {left: '200px', opacity: '1'}, |
| 124 ], |
| 125 }, |
| 126 { |
| 127 description: 'same offset applied to all keyframes', |
| 128 indexedKeyframes: { |
| 129 left: ['0px', '100px'], |
| 130 offset: 0.5, |
| 131 }, |
| 132 sequencedKeyframes: [ |
| 133 {left: '0px', offset: 0.5}, |
| 134 {left: '100px', offset: 0.5}, |
| 135 ], |
| 136 }, |
| 137 { |
| 138 description: 'same easing applied to all keyframes', |
| 139 indexedKeyframes: { |
| 140 left: ['10px', '100px', '150px'], |
| 141 opacity: ['1', '0', '1'], |
| 142 easing: 'ease', |
| 143 }, |
| 144 sequencedKeyframes: [ |
| 145 {left: '10px', opacity: '1', easing: 'ease'}, |
| 146 {left: '100px', opacity: '0', easing: 'ease'}, |
| 147 {left: '150px', opacity: '1', easing: 'ease'}, |
| 148 ], |
| 149 }, |
| 150 { |
| 151 description: 'same composite applied to all keyframes', |
| 152 indexedKeyframes: { |
| 153 left: ['0px', '100px'], |
| 154 composite: 'add', |
| 155 }, |
| 156 sequencedKeyframes: [ |
| 157 {left: '0px', composite: 'add'}, |
| 158 {left: '100px', composite: 'add'}, |
| 159 ], |
| 160 }, |
| 161 ]; |
| 162 |
| 163 gEquivalentSyntaxTests.forEach(function({description, indexedKeyframes, sequence
dKeyframes}) { |
| 164 test(function(t) { |
| 165 assertEquivalentKeyframeSyntax(indexedKeyframes, sequencedKeyframes); |
| 166 }, 'Equivalent property indexed and sequenced keyframes: ' + description); |
| 167 }); |
| 168 |
| 169 // Test handling of custom iterable objects. |
| 170 |
| 171 function createIterable(iterations) { |
| 172 return { |
| 173 [Symbol.iterator]() { |
| 174 var i = 0; |
| 175 return { |
| 176 next() { |
| 177 return iterations[i++]; |
| 178 }, |
| 179 }; |
| 180 }, |
| 181 }; |
| 182 } |
| 183 |
| 184 test(() => { |
| 185 var effect = new KeyframeEffect(null, createIterable([ |
| 186 {done: false, value: {left: '100px'}}, |
| 187 {done: false, value: {left: '300px'}}, |
| 188 {done: false, value: {left: '200px'}}, |
| 189 {done: true}, |
| 190 ])); |
| 191 assert_frame_lists_equal(effect.getKeyframes(), [ |
| 192 {offset: null, computedOffset: 0, easing: 'linear', left: '100px'}, |
| 193 {offset: null, computedOffset: 0.5, easing: 'linear', left: '300px'}, |
| 194 {offset: null, computedOffset: 1, easing: 'linear', left: '200px'}, |
| 195 ]); |
| 196 }, 'Custom iterator with basic keyframes.'); |
| 197 |
| 198 test(() => { |
| 199 var keyframes = createIterable([ |
| 200 {done: false, value: {left: '100px'}}, |
| 201 {done: false, value: {left: '300px'}}, |
| 202 {done: false, value: {left: '200px'}}, |
| 203 {done: true}, |
| 204 ]); |
| 205 keyframes.easing = 'ease-in-out'; |
| 206 keyframes.offset = '0.1'; |
| 207 var effect = new KeyframeEffect(null, keyframes); |
| 208 assert_frame_lists_equal(effect.getKeyframes(), [ |
| 209 {offset: null, computedOffset: 0, easing: 'linear', left: '100px'}, |
| 210 {offset: null, computedOffset: 0.5, easing: 'linear', left: '300px'}, |
| 211 {offset: null, computedOffset: 1, easing: 'linear', left: '200px'}, |
| 212 ]); |
| 213 }, 'easing and offset are ignored on iterable objects.'); |
| 214 |
| 215 test(() => { |
| 216 var effect = new KeyframeEffect(null, createIterable([ |
| 217 {done: false, value: {left: '100px', top: '200px'}}, |
| 218 {done: false, value: {left: '300px'}}, |
| 219 {done: false, value: {left: '200px', top: '100px'}}, |
| 220 {done: true}, |
| 221 ])); |
| 222 assert_frame_lists_equal(effect.getKeyframes(), [ |
| 223 {offset: null, computedOffset: 0, easing: 'linear', left: '100px', top: '200
px'}, |
| 224 {offset: null, computedOffset: 0.5, easing: 'linear', left: '300px'}, |
| 225 {offset: null, computedOffset: 1, easing: 'linear', left: '200px', top: '100
px'}, |
| 226 ]); |
| 227 }, 'Custom iterator with multiple properties specified.'); |
| 228 |
| 229 test(() => { |
| 230 var effect = new KeyframeEffect(null, createIterable([ |
| 231 {done: false, value: {left: '100px'}}, |
| 232 {done: false, value: {left: '250px', offset: 0.75}}, |
| 233 {done: false, value: {left: '200px'}}, |
| 234 {done: true}, |
| 235 ])); |
| 236 assert_frame_lists_equal(effect.getKeyframes(), [ |
| 237 {offset: null, computedOffset: 0, easing: 'linear', left: '100px'}, |
| 238 {offset: 0.75, computedOffset: 0.75, easing: 'linear', left: '250px'}, |
| 239 {offset: null, computedOffset: 1, easing: 'linear', left: '200px'}, |
| 240 ]); |
| 241 }, 'Custom iterator with offset specified.'); |
| 242 |
| 243 test(() => { |
| 244 assert_throws({name: 'TypeError'}, function() { |
| 245 new KeyframeEffect(null, createIterable([ |
| 246 {done: false, value: {left: '100px'}}, |
| 247 {done: false, value: 1234}, |
| 248 {done: false, value: {left: '200px'}}, |
| 249 {done: true}, |
| 250 ])); |
| 251 }); |
| 252 }, 'Custom iterator with non object keyframe should throw.'); |
| 253 |
| 254 test(() => { |
| 255 var effect = new KeyframeEffect(null, createIterable([ |
| 256 {done: false, value: {left: ['100px', '200px']}}, |
| 257 {done: true}, |
| 258 ])); |
| 259 assert_frame_lists_equal(effect.getKeyframes(), [ |
| 260 {offset: null, computedOffset: 1, easing: 'linear', left: '100px,200px'} |
| 261 ]); |
| 262 }, 'Custom iterator with value list in keyframe should give bizarre string repre
sentation of list.'); |
| 263 |
| 264 test(function(t) { |
| 265 var keyframe = {}; |
| 266 Object.defineProperty(keyframe, 'width', {value: '200px'}); |
| 267 Object.defineProperty(keyframe, 'height', { |
| 268 value: '100px', |
| 269 enumerable: true}); |
| 270 assert_equals(keyframe.width, '200px', 'width of keyframe is readable'); |
| 271 assert_equals(keyframe.height, '100px', 'height of keyframe is readable'); |
| 272 var anim = createDiv(t).animate([keyframe, {height: '200px'}], 1); |
| 273 assert_frame_lists_equal(anim.effect.getKeyframes(), [ |
| 274 {offset: null, computedOffset: 0, easing: 'linear', height: '100px'}, |
| 275 {offset: null, computedOffset: 1, easing: 'linear', height: '200px'}, |
| 276 ]); |
| 277 }, 'Only enumerable properties on keyframes are considered'); |
| 278 |
| 279 test(function(t) { |
| 280 var KeyframeParent = function() { this.width = '100px'; }; |
| 281 KeyframeParent.prototype = { height: '100px' }; |
| 282 var Keyframe = function() { this.top = '100px'; }; |
| 283 Keyframe.prototype = Object.create(KeyframeParent.prototype); |
| 284 Object.defineProperty(Keyframe.prototype, 'left', { |
| 285 value: '100px', |
| 286 enumerable: 'true'}); |
| 287 var keyframe = new Keyframe(); |
| 288 var anim = createDiv(t).animate([keyframe, {top: '200px'}], 1); |
| 289 assert_frame_lists_equal(anim.effect.getKeyframes(), [ |
| 290 {offset: null, computedOffset: 0, easing: 'linear', top: '100px'}, |
| 291 {offset: null, computedOffset: 1, easing: 'linear', top: '200px'}, |
| 292 ]); |
| 293 }, 'Only properties defined directly on keyframes are considered'); |
| 294 |
| 295 test(function(t) { |
| 296 var keyframes = {}; |
| 297 Object.defineProperty(keyframes, 'width', ['100px', '200px']); |
| 298 Object.defineProperty(keyframes, 'height', { |
| 299 value: ['100px', '200px'], |
| 300 enumerable: true}); |
| 301 var anim = createDiv(t).animate(keyframes, 1); |
| 302 assert_frame_lists_equal(anim.effect.getKeyframes(), [ |
| 303 {offset: null, computedOffset: 0, easing: 'linear', height: '100px'}, |
| 304 {offset: null, computedOffset: 1, easing: 'linear', height: '200px'}, |
| 305 ]); |
| 306 }, 'Only enumerable properties on property indexed keyframes are considered'); |
| 307 |
| 308 test(function(t) { |
| 309 var KeyframesParent = function() { this.width = '100px'; }; |
| 310 KeyframesParent.prototype = { height: '100px' }; |
| 311 var Keyframes = function() { this.top = ['100px', '200px']; }; |
| 312 Keyframes.prototype = Object.create(KeyframesParent.prototype); |
| 313 Object.defineProperty(Keyframes.prototype, 'left', { |
| 314 value: ['100px', '200px'], |
| 315 enumerable: 'true'}); |
| 316 var keyframes = new Keyframes(); |
| 317 var anim = createDiv(t).animate(keyframes, 1); |
| 318 assert_frame_lists_equal(anim.effect.getKeyframes(), [ |
| 319 {offset: null, computedOffset: 0, easing: 'linear', top: '100px'}, |
| 320 {offset: null, computedOffset: 1, easing: 'linear', top: '200px'}, |
| 321 ]); |
| 322 }, 'Only properties defined directly on property indexed keyframes are considere
d'); |
83 | 323 |
84 // FIXME: Test that properties are accessed in ascending order by Unicode | 324 // FIXME: Test that properties are accessed in ascending order by Unicode |
85 // codepoint | 325 // codepoint |
86 // (There is an existing test for this in | 326 // (There is an existing test for this in |
87 // keyframe-effect/constructor.html that should be moved here.) | 327 // keyframe-effect/constructor.html that should be moved here.) |
88 | 328 |
89 </script> | 329 </script> |
OLD | NEW |