• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1suite('group-player', function() {
2  setup(function() {
3    document.timeline._players = [];
4    webAnimations1.timeline._players = [];
5    this.elements = [];
6
7    var animationMargin = function(target) {
8      return new Animation(
9          target,
10          [
11           {marginLeft: '0px'},
12           {marginLeft: '100px'}
13          ],
14          500);
15    };
16    var animationColor = function(target) {
17      return new Animation(
18          target,
19          [
20           {backgroundColor: 'black'},
21           {backgroundColor: 'white'}
22          ],
23          500);
24    };
25    var sequenceEmpty = function() {
26      return new AnimationSequence();
27    };
28    var groupEmpty = function() {
29      return new AnimationGroup();
30    };
31    var sequenceWithEffects = function(target) {
32      return new AnimationSequence(
33          [
34           animationMargin(target),
35           animationColor(target)
36          ]);
37    };
38    var groupWithEffects = function(target) {
39      return new AnimationGroup(
40          [
41           animationMargin(target),
42           animationColor(target)
43          ]);
44    };
45
46    var seqEmpty_source = sequenceEmpty();
47
48    var seqSimple_target = document.createElement('div');
49    this.elements.push(seqSimple_target);
50    var seqSimple_source = sequenceWithEffects(seqSimple_target);
51
52    var seqWithSeq_target = document.createElement('div');
53    this.elements.push(seqWithSeq_target);
54    var seqWithSeq_source = new AnimationSequence(
55        [
56         animationMargin(seqWithSeq_target),
57         animationColor(seqWithSeq_target),
58         sequenceWithEffects(seqWithSeq_target)
59        ]);
60
61    var seqWithGroup_target = document.createElement('div');
62    this.elements.push(seqWithGroup_target);
63    var seqWithGroup_source = new AnimationSequence(
64        [
65         animationMargin(seqWithGroup_target),
66         animationColor(seqWithGroup_target),
67         groupWithEffects(seqWithGroup_target)
68        ]);
69
70    var seqWithEmptyGroup_source = new AnimationSequence([groupEmpty()]);
71    var seqWithEmptySeq_source = new AnimationSequence([sequenceEmpty()]);
72
73    var groupEmpty_source = groupEmpty();
74
75    var groupSimple_target = document.createElement('div');
76    var groupSimple_source = groupWithEffects(groupSimple_target);
77
78    var groupWithSeq_target = document.createElement('div');
79    this.elements.push(groupWithSeq_target);
80    var groupWithSeq_source = new AnimationGroup(
81        [
82         animationMargin(groupWithSeq_target),
83         animationColor(groupWithSeq_target),
84         sequenceWithEffects(groupWithSeq_target)
85        ]);
86
87    var groupWithGroup_target = document.createElement('div');
88    this.elements.push(groupWithGroup_target);
89    var groupWithGroup_source = new AnimationGroup(
90        [
91         animationMargin(groupWithGroup_target),
92         animationColor(groupWithGroup_target),
93         groupWithEffects(groupWithGroup_target)
94        ]);
95
96    var groupWithEmptyGroup_source = new AnimationGroup([groupEmpty()]);
97    var groupWithEmptySeq_source = new AnimationGroup([sequenceEmpty()]);
98
99    this.seqEmpty_source = seqEmpty_source;
100    this.seqSimple_source = seqSimple_source;
101    this.seqWithSeq_source = seqWithSeq_source;
102    this.seqWithGroup_source = seqWithGroup_source;
103    this.seqWithEmptyGroup_source = seqWithEmptyGroup_source;
104    this.seqWithEmptySeq_source = seqWithEmptySeq_source;
105
106    this.groupEmpty_source = groupEmpty_source;
107    this.groupSimple_source = groupSimple_source;
108    this.groupWithSeq_source = groupWithSeq_source;
109    this.groupWithGroup_source = groupWithGroup_source;
110    this.groupWithEmptyGroup_source = groupWithEmptyGroup_source;
111    this.groupWithEmptySeq_source = groupWithEmptySeq_source;
112
113    this.staticAnimation = function(target, value, duration) {
114      var animation = new Animation(target, [{marginLeft: value}, {marginLeft: value}], duration);
115      animation.testValue = value;
116      return animation;
117    };
118    // The following animation structure looks like:
119    // 44444
120    // 11
121    //   33
122    //   2
123    // 0
124    this.complexTarget = document.createElement('div');
125    this.elements.push(this.complexTarget);
126    this.complexSource = new AnimationGroup([
127      this.staticAnimation(this.complexTarget, '4px', 5),
128      new AnimationSequence([
129        this.staticAnimation(this.complexTarget, '1px', 2),
130        new AnimationGroup([
131          this.staticAnimation(this.complexTarget, '3px', 2),
132          this.staticAnimation(this.complexTarget, '2px', 1),
133        ]),
134      ]),
135      this.staticAnimation(this.complexTarget, '0px', 1),
136    ]);
137
138    this.target = document.createElement('div');
139    this.elements.push(this.target);
140
141    for (var i = 0; i < this.elements.length; i++)
142      document.documentElement.appendChild(this.elements[i]);
143  });
144
145  teardown(function() {
146    for (var i = 0; i < this.elements.length; i++) {
147      if (this.elements[i].parent)
148        this.elements[i].parent.removeChild(this.elements[i]);
149    }
150  });
151
152  function simpleAnimationGroup() {
153    return new AnimationGroup([new Animation(document.body, [], 2000), new Animation(document.body, [], 1000), new Animation(document.body, [], 3000)]);
154  }
155
156  function simpleAnimationSequence() {
157    return new AnimationSequence([new Animation(document.body, [], 2000), new Animation(document.body, [], 1000), new Animation(document.body, [], 3000)]);
158  }
159
160  // FIXME: Remove _startOffset.
161  // playerState is [startTime, currentTime, _startOffset?, offset?]
162  // innerPlayerStates is a nested array tree of playerStates e.g. [[0, 0], [[1, -1], [2, -2]]]
163  function checkTimes(player, playerState, innerPlayerStates, description) {
164    description = description ? (description + ' ') : '';
165    _checkTimes(player, playerState, 0, description + 'top player');
166    _checkTimes(player, innerPlayerStates, 0, description + 'inner player');
167  }
168
169  function _checkTimes(player, timingList, index, trace) {
170    assert.isDefined(player, trace + ' exists');
171    if (timingList.length == 0) {
172      assert.equal(player._childPlayers.length, index, trace + ' no remaining players');
173      return;
174    }
175    if (timingList[0] === null || typeof timingList[0] == 'number') {
176      assert.equal(player.startTime, timingList[0], trace + ' startTime');
177      assert.equal(player.currentTime, timingList[1], trace + ' currentTime');
178    } else {
179      _checkTimes(player._childPlayers[index], timingList[0], 0, trace + ' ' + index);
180      _checkTimes(player, timingList.slice(1), index + 1, trace);
181    }
182  }
183
184  test('playing an animationGroup works as expected', function() {
185    tick(90);
186    var p = document.timeline.play(simpleAnimationGroup());
187    checkTimes(p, [null, 0], [[null, 0], [null, 0], [null, 0]]);
188    tick(100);
189    checkTimes(p, [100, 0], [[100, 0], [100, 0], [100, 0]]);
190    tick(300);
191    checkTimes(p, [100, 200], [[100, 200], [100, 200], [100, 200]]);
192    tick(1200);
193    checkTimes(p, [100, 1100], [[100, 1100], [100, 1000], [100, 1100]]);
194    tick(2200);
195    checkTimes(p, [100, 2100], [[100, 2000], [100, 1000], [100, 2100]]);
196    tick(3200);
197    checkTimes(p, [100, 3000], [[100, 2000], [100, 1000], [100, 3000]]);
198  });
199
200  test('can seek an animationGroup', function() {
201    tick(90);
202    var p = document.timeline.play(simpleAnimationGroup());
203    tick(100);
204    checkTimes(p, [100, 0], [[100, 0], [100, 0], [100, 0]]);
205    p.currentTime = 200;
206    checkTimes(p, [-100, 200], [[-100, 200], [-100, 200], [-100, 200]]);
207    p.currentTime = 1100;
208    checkTimes(p, [-1000, 1100], [[-1000, 1100], [-1000, 1100], [-1000, 1100]]);
209    p.currentTime = 2100;
210    checkTimes(p, [-2000, 2100], [[-2000, 2100], [-2000, 2100], [-2000, 2100]]);
211    p.currentTime = 3100;
212    checkTimes(p, [-3000, 3100], [[-3000, 3100], [-3000, 3100], [-3000, 3100]]);
213  });
214
215  test('can startTime seek an animationGroup', function() {
216    tick(90);
217    var p = document.timeline.play(simpleAnimationGroup());
218    tick(100);
219    checkTimes(p, [100, 0], [[100, 0], [100, 0], [100, 0]]);
220    p.startTime = -100;
221    checkTimes(p, [-100, 200], [[-100, 200], [-100, 200], [-100, 200]]);
222    p.startTime = -1000;
223    checkTimes(p, [-1000, 1100], [[-1000, 1100], [-1000, 1000], [-1000, 1100]]);
224    p.startTime = -2000;
225    checkTimes(p, [-2000, 2100], [[-2000, 2000], [-2000, 1000], [-2000, 2100]]);
226    p.startTime = -3000;
227    checkTimes(p, [-3000, 3000], [[-3000, 2000], [-3000, 1000], [-3000, 3000]]);
228  });
229
230  test('playing an animationSequence works as expected', function() {
231    tick(100);
232    var p = document.timeline.play(simpleAnimationSequence());
233    tick(110);
234    checkTimes(p, [110, 0], [[110, 0], [2110, -2000], [3110, -3000]]);
235    tick(210);
236    checkTimes(p, [110, 100], [[110, 100], [2110, -1900], [3110, -2900]]);
237    tick(2210);
238    checkTimes(p, [110, 2100], [[110, 2000], [2110, 100], [3110, -900]]);
239    tick(3210);
240    checkTimes(p, [110, 3100], [[110, 2000], [2110, 1000], [3110, 100]]);
241    tick(6210);
242    checkTimes(p, [110, 6000], [[110, 2000], [2110, 1000], [3110, 3000]]);
243  });
244
245  test('can seek an animationSequence', function() {
246    tick(100);
247    var p = document.timeline.play(simpleAnimationSequence());
248    tick(110);
249    checkTimes(p, [110, 0], [[110, 0], [2110, -2000], [3110, -3000]]);
250    p.currentTime = 100;
251    checkTimes(p, [10, 100], [[10, 100], [2010, -1900], [3010, -2900]]);
252    p.currentTime = 2100;
253    checkTimes(p, [-1990, 2100], [[-1990, 2100], [10, 100], [1010, -900]]);
254    p.currentTime = 3100;
255    checkTimes(p, [-2990, 3100], [[-2990, 3100], [-990, 1100], [10, 100]]);
256    p.currentTime = 6100;
257    checkTimes(p, [-5990, 6100], [[-5990, 6100], [-3990, 4100], [-2990, 3100]]);
258  });
259
260  test('can startTime seek an animationSequence', function() {
261    tick(100);
262    var p = document.timeline.play(simpleAnimationSequence());
263    tick(110);
264    checkTimes(p, [110, 0], [[110, 0], [2110, -2000], [3110, -3000]]);
265    p.startTime = 10;
266    checkTimes(p, [10, 100], [[10, 100], [2010, -1900], [3010, -2900]]);
267    p.startTime = -1990;
268    checkTimes(p, [-1990, 2100], [[-1990, 2000], [10, 100], [1010, -900]]);
269    p.startTime = -2990;
270    checkTimes(p, [-2990, 3100], [[-2990, 2000], [-990, 1000], [10, 100]]);
271    p.startTime = -5990;
272    checkTimes(p, [-5990, 6000], [[-5990, 2000], [-3990, 1000], [-2990, 3000]]);
273  });
274
275  test('complex animation tree timing while playing', function() {
276    tick(90);
277    var player = document.timeline.play(this.complexSource);
278    tick(100);
279    checkTimes(player, [100, 0], [
280      [100, 0], [ // 4
281        [100, 0], [ // 1
282          [102, -2], // 3
283          [102, -2]]], // 2
284      [100, 0], // 0
285    ], 't = 100');
286    tick(101);
287    checkTimes(player, [100, 1], [
288      [100, 1], [ // 4
289        [100, 1], [ // 1
290          [102, -1], // 3
291          [102, -1]]], // 2
292      [100, 1], // 0
293    ], 't = 101');
294    tick(102);
295    checkTimes(player, [100, 2], [
296      [100, 2], [ // 4
297        [100, 2], [ // 1
298          [102, 0], // 3
299          [102, 0]]], // 2
300      [100, 1], // 0
301    ], 't = 102');
302  });
303
304  test('effects apply in the correct order', function() {
305    tick(0);
306    var player = document.timeline.play(this.complexSource);
307    player.currentTime = 0;
308    assert.equal(getComputedStyle(this.complexTarget).marginLeft, '0px');
309    player.currentTime = 1;
310    checkTimes(player, [-1, 1], [[-1, 1, 0], [[-1, 1, 0], [[1, -1, 0], [1, -1, 0]]], [-1, 1, 0]]);
311    assert.equal(getComputedStyle(this.complexTarget).marginLeft, '1px');
312    player.currentTime = 2;
313    // TODO: When we seek we don't limit. Is this OK?
314    checkTimes(player, [-2, 2], [[-2, 2, 0], [[-2, 2, 0], [[0, 0, 0], [0, 0, 0]]], [-2, 2, 0]]);
315    assert.equal(getComputedStyle(this.complexTarget).marginLeft, '2px');
316    player.currentTime = 3;
317    assert.equal(getComputedStyle(this.complexTarget).marginLeft, '3px');
318    player.currentTime = 4;
319    assert.equal(getComputedStyle(this.complexTarget).marginLeft, '4px');
320    player.currentTime = 5;
321    assert.equal(getComputedStyle(this.complexTarget).marginLeft, '0px');
322  });
323
324  test('cancelling group players', function() {
325    tick(0);
326    var player = document.timeline.play(this.complexSource);
327    tick(1);
328    tick(4);
329    assert.equal(getComputedStyle(this.complexTarget).marginLeft, '3px');
330    player.cancel();
331    assert.equal(player.currentTime, null);
332    assert.equal(getComputedStyle(this.complexTarget).marginLeft, '0px');
333  });
334
335  test('cancelling group players before tick', function() {
336    tick(0);
337    var player = document.timeline.play(this.complexSource);
338    player.cancel();
339    assert.equal(player.currentTime, null);
340    assert.equal(getComputedStyle(this.complexTarget).marginLeft, '0px');
341    tick(4);
342    assert.equal(player.currentTime, null);
343    assert.equal(getComputedStyle(this.complexTarget).marginLeft, '0px');
344  });
345
346  test('redundant animation node wrapping', function() {
347    tick(100);
348    var animation = new AnimationSequence([
349      this.staticAnimation(this.target, '0px', 1),
350      new AnimationGroup([
351        new AnimationSequence([
352          this.staticAnimation(this.target, '1px', 1),
353          this.staticAnimation(this.target, '2px', 1),
354        ]),
355      ]),
356    ]);
357    var player = document.timeline.play(animation);
358    assert.equal(getComputedStyle(this.target).marginLeft, '0px');
359    checkTimes(player, [100, 0], [
360      [100, 0, 0, 0], [[ // 0
361        [101, -1, 0, 1], // 1
362        [102, -2, 1, 2]]] // 2
363    ], 't = 100');
364    tick(101);
365    assert.equal(getComputedStyle(this.target).marginLeft, '1px');
366    checkTimes(player, [100, 1], [
367      [100, 1, 0, 0], [[ // 0
368        [101, 0, 0, 1], // 1
369        [102, -1, 1, 2]]] // 2
370    ], 't = 101');
371    tick(102);
372    assert.equal(getComputedStyle(this.target).marginLeft, '2px');
373    assert.equal(document.timeline.currentTime, 102);
374    checkTimes(player, [100, 2], [ // FIXME: Implement limiting on group players
375      [100, 1, 0, 0], [[ // 0
376        [101, 1, 0, 1], // 1
377        [102, 0, 1, 2]]] // 2
378    ], 't = 102');
379    tick(103);
380    assert.equal(getComputedStyle(this.target).marginLeft, '0px');
381    checkTimes(player, [100, 3], [ // FIXME: Implement limiting on group players
382      [100, 1, 0, 0], [[ // 0
383        [101, 1, 0, 1], // 1
384        [102, 1, 1, 2]]] // 2
385    ], 't = 103');
386    if (this.target.parent)
387      this.target.parent.removeChild(target);
388  });
389
390  test('setting the playbackRate on group players', function() {
391    var group = new AnimationGroup([
392      new Animation(null, [], 1234),
393      new Animation(null, [], 1234),
394    ]);
395    var p = document.timeline.play(group);
396    p.playbackRate = 2;
397    assert.equal(p._player.playbackRate, 2, 'Updates the playbackRate of the inner player');
398    p._childPlayers.forEach(function(childPlayer) {
399      assert.equal(childPlayer.playbackRate, 2, 'It also updates the child players');
400    });
401  });
402
403  test('delays on groups work correctly', function() {
404    //   444
405    //  1
406    // 0
407    //   33
408    //   2
409    var animation = new AnimationGroup([
410      new AnimationGroup([
411        this.staticAnimation(this.target, '4px', {duration: 3, delay: 1}),
412        this.staticAnimation(this.target, '1px', {duration: 1, delay: 0}),
413      ], {delay: 1}),
414      new AnimationSequence([
415        this.staticAnimation(this.target, '0px', {duration: 1, delay: 0}),
416        this.staticAnimation(this.target, '3px', {duration: 2, delay: 1}),
417        this.staticAnimation(this.target, '2px', {duration: 1, delay: -2}),
418      ]),
419    ]);
420    var player = document.timeline.play(animation);
421    tick(100);
422    checkTimes(player, [100, 0], [
423      [
424        [101, -1],
425        [101, -1],
426      ], [
427        [100, 0],
428        [101, -1],
429        [104, -4],
430      ]
431    ]);
432    assert.equal(getComputedStyle(this.target).marginLeft, '0px');
433    tick(101);
434    assert.equal(getComputedStyle(this.target).marginLeft, '1px');
435    tick(102);
436    assert.equal(getComputedStyle(this.target).marginLeft, '2px');
437    tick(103);
438    assert.equal(getComputedStyle(this.target).marginLeft, '3px');
439    tick(104);
440    assert.equal(getComputedStyle(this.target).marginLeft, '4px');
441    tick(105);
442    assert.equal(getComputedStyle(this.target).marginLeft, '0px');
443  });
444
445  test('end delays on groups work correctly', function() {
446    // 11
447    //     4
448    // 0
449    //   33
450    //   2
451    var animation = new AnimationSequence([
452      new AnimationSequence([
453        this.staticAnimation(this.target, '1px', {duration: 2, endDelay: 2}),
454        this.staticAnimation(this.target, '4px', {duration: 1, endDelay: 1}),
455      ], {endDelay: -6}),
456      new AnimationSequence([
457        this.staticAnimation(this.target, '0px', {duration: 1, endDelay: 1}),
458        this.staticAnimation(this.target, '3px', {duration: 2, endDelay: -2}),
459        this.staticAnimation(this.target, '2px', {duration: 1, endDelay: 2}),
460      ]),
461    ]);
462    var player = document.timeline.play(animation);
463    tick(100);
464    checkTimes(player, [100, 0], [
465      [
466        [100, 0],
467        [104, -4],
468      ], [
469        [100, 0],
470        [102, -2],
471        [102, -2],
472      ]
473    ]);
474    assert.equal(getComputedStyle(this.target).marginLeft, '0px');
475    tick(101);
476    assert.equal(getComputedStyle(this.target).marginLeft, '1px');
477    tick(102);
478    assert.equal(getComputedStyle(this.target).marginLeft, '2px');
479    tick(103);
480    assert.equal(getComputedStyle(this.target).marginLeft, '3px');
481    tick(104);
482    // FIXME: Group child player limiting bounds should match the parent player's limiting bounds.
483    // assert.equal(getComputedStyle(this.target).marginLeft, '4px');
484    // tick(105);
485    // assert.equal(getComputedStyle(this.target).marginLeft, '0px');
486  });
487
488  // FIXME: This test can be removed when this suite is finished.
489  test('sources are working for basic operations', function() {
490    var players = [];
491    players.push(document.timeline.play(this.seqEmpty_source));
492    players.push(document.timeline.play(this.seqSimple_source));
493    players.push(document.timeline.play(this.seqWithSeq_source));
494    players.push(document.timeline.play(this.seqWithGroup_source));
495    players.push(document.timeline.play(this.seqWithEmptyGroup_source));
496    players.push(document.timeline.play(this.seqWithEmptySeq_source));
497
498    players.push(document.timeline.play(this.groupEmpty_source));
499    players.push(document.timeline.play(this.groupSimple_source));
500    players.push(document.timeline.play(this.groupWithSeq_source));
501    players.push(document.timeline.play(this.groupWithGroup_source));
502    players.push(document.timeline.play(this.groupWithEmptyGroup_source));
503    players.push(document.timeline.play(this.groupWithEmptySeq_source));
504
505    var length = players.length;
506
507    tick(50);
508    for (var i = 0; i < length; i++)
509      players[i].pause();
510
511    tick(100);
512    for (var i = 0; i < length; i++)
513      players[i].play();
514
515    tick(200);
516    for (var i = 0; i < length; i++)
517      players[i].currentTime += 1;
518
519    tick(300);
520    for (var i = 0; i < length; i++)
521      players[i].startTime += 1;
522
523    tick(350);
524    for (var i = 0; i < length; i++)
525      players[i].reverse();
526
527    tick(400);
528    for (var i = 0; i < length; i++)
529      players[i].finish();
530
531    tick(500);
532    tick(600);
533    for (var i = 0; i < length; i++)
534      players[i].cancel();
535
536    for (var i = 0; i < length; i++)
537      players[i].play();
538  });
539
540  test('pausing works as expected with an empty AnimationSequence', function() {
541    var player = document.timeline.play(this.seqEmpty_source);
542    tick(0);
543    assert.equal(player.startTime, 0);
544    assert.equal(player.currentTime, 0);
545
546    player.pause();
547    assert.equal(player.startTime, null);
548    assert.equal(player.currentTime, 0);
549  });
550
551  test('pausing works as expected with a simple AnimationSequence', function() {
552    var player = document.timeline.play(this.seqSimple_source);
553    var target = this.seqSimple_source.children[0].target;
554    tick(0);
555    checkTimes(player, [0, 0], [[0, 0], [500, -500]], 't = 0');
556
557    tick(200);
558    checkTimes(player, [0, 200], [[0, 200], [500, -300]], 't = 200');
559
560    player.pause();
561    checkTimes(player, [null, null], [[null, null], [null, null]], 't = 200');
562    assert.equal(getComputedStyle(target).marginLeft, '40px');
563
564    tick(300);
565    checkTimes(player, [null, 200], [[null, 200], [null, -300]], 't = 300');
566    assert.equal(getComputedStyle(target).marginLeft, '40px');
567
568    player.play();
569    checkTimes(player, [null, 200], [[null, 200], [null, -300]], 't = 300');
570    assert.equal(getComputedStyle(target).marginLeft, '40px');
571
572    tick(301);
573    checkTimes(player, [101, 200], [[101, 200], [601, -300]], 't = 301');
574    assert.equal(getComputedStyle(target).marginLeft, '40px');
575
576    tick(401);
577    checkTimes(player, [101, 300], [[101, 300], [601, -200]], 't = 401');
578    assert.equal(getComputedStyle(target).marginLeft, '60px');
579
580    tick(700);
581    checkTimes(player, [101, 599], [[101, 500], [601, 99]], 't = 700');
582    assert.equal(getComputedStyle(target).marginLeft, '0px');
583  });
584
585  test('pausing before tick works as expected with a simple AnimationSequence', function() {
586    var player = document.timeline.play(this.seqSimple_source);
587    var target = this.seqSimple_source.children[0].target;
588    checkTimes(player, [null, 0], [[null, 0], [null, -500]], 't = 0');
589
590    player.pause();
591    checkTimes(player, [null, null], [[null, null], [null, null]], 't = 0');
592    assert.equal(getComputedStyle(target).marginLeft, '0px');
593
594    tick(10);
595    checkTimes(player, [null, 0], [[null, 0], [null, -500]], 't = 10');
596    assert.equal(getComputedStyle(target).marginLeft, '0px');
597
598    tick(20);
599    checkTimes(player, [null, 0], [[null, 0], [null, -500]], 't = 10');
600    assert.equal(getComputedStyle(target).marginLeft, '0px');
601  });
602
603  test('pausing and seeking before tick works as expected with a simple AnimationSequence', function() {
604    var player = document.timeline.play(this.seqSimple_source);
605    player.pause();
606
607    player.currentTime = 0;
608    checkTimes(player, [null, 0], [[null, 0], [null, -500]], 't = 10');
609
610    player.currentTime = 250;
611    checkTimes(player, [null, 250], [[null, 250], [null, -250]], 't = 10');
612
613    player.currentTime = 500;
614    checkTimes(player, [null, 500], [[null, 500], [null, 0]], 't = 10');
615
616    // FIXME: Expectation should be [null, 1000], [[null, 500], [null, 500]].
617    player.currentTime = 1000;
618    checkTimes(player, [null, 1000], [[null, 1000], [null, 500]], 't = 10');
619  });
620
621  test('pausing works as expected with an AnimationSequence inside an AnimationSequence', function() {
622    var player = document.timeline.play(this.seqWithSeq_source);
623    tick(0);
624    checkTimes(
625        player,
626        [0, 0], [
627          [0, 0],
628          [500, -500], [
629            [1000, -1000],
630            [1500, -1500]]],
631        't = 0');
632
633    tick(200);
634    checkTimes(
635        player,
636        [0, 200], [
637          [0, 200],
638          [500, -300], [
639            [1000, -800],
640            [1500, -1300]]],
641        't = 200');
642
643    player.pause();
644    checkTimes(
645        player,
646        [null, null], [
647          [null, null],
648          [null, null], [
649            [null, null],
650            [null, null]]],
651        't = 200');
652
653    tick(300);
654    checkTimes(
655        player,
656        [null, 200], [
657          [null, 200],
658          [null, -300], [
659            [null, -800],
660            [null, -1300]]],
661        't = 300');
662
663    player.play();
664    tick(310);
665    checkTimes(
666        player,
667        [110, 200], [
668          [110, 200],
669          [610, -300], [
670            [1110, -800],
671            [1610, -1300]]],
672        't = 310');
673
674    tick(1300);
675    checkTimes(
676        player,
677        [110, 1190], [
678          [110, 500],
679          [610, 500], [
680            [1110, 190],
681            [1610, -310]]],
682        't = 1300');
683
684    player.pause();
685    checkTimes(
686        player,
687        [null, null], [
688          [null, 500],
689          [null, 500], [
690            [null, null],
691            [null, null]]],
692        't = 1300');
693
694    tick(1400);
695    checkTimes(
696        player,
697        [null, 1190], [
698          [null, 500],
699          [null, 500], [
700            [null, 190],
701            [null, -310]]],
702        't = 1400');
703
704    player.play();
705    checkTimes(
706        player,
707        [null, 1190], [
708          [null, 500],
709          [null, 500], [
710            [null, 190],
711            [null, -310]]],
712        't = 1400');
713
714    tick(1410);
715    checkTimes(
716        player,
717        [220, 1190], [
718          [220, 500],
719          [720, 500], [
720            [1220, 190],
721            [1720, -310]]],
722        't = 1410');
723
724    tick(1600);
725    checkTimes(
726        player,
727        [220, 1380], [
728          [220, 500],
729          [720, 500], [
730            [1220, 380],
731            [1720, -120]]],
732        't = 1600');
733
734    player.pause();
735    checkTimes(
736        player,
737        [null, null], [
738          [null, 500],
739          [null, 500], [
740            [null, null],
741            [null, null]]],
742        't = 1600');
743
744    tick(1700);
745    checkTimes(
746        player,
747        [null, 1380], [
748          [null, 500],
749          [null, 500], [
750            [null, 380],
751            [null, -120]]],
752        't = 1700');
753
754    player.play();
755    tick(1710);
756    checkTimes(
757        player,
758        [330, 1380], [
759          [330, 500],
760          [830, 500], [
761            [1330, 380],
762            [1830, -120]]],
763        't = 1710');
764
765    tick(2400);
766    checkTimes(
767        player,
768        [330, 2000], [
769          [330, 500],
770          [830, 500], [
771            [1330, 500],
772            [1830, 500]]],
773        't = 2400');
774  });
775
776  test('pausing works as expected with an AnimationGroup inside an AnimationSequence', function() {
777    var player = document.timeline.play(this.seqWithGroup_source);
778    tick(0);
779    checkTimes(
780        player,
781        [0, 0], [
782          [0, 0],
783          [500, -500], [
784            [1000, -1000],
785            [1000, -1000]]],
786        't = 0');
787
788    tick(200);
789    checkTimes(
790        player,
791        [0, 200], [
792          [0, 200],
793          [500, -300], [
794            [1000, -800],
795            [1000, -800]]],
796        't = 200');
797
798    player.pause();
799    checkTimes(
800        player,
801        [null, null], [
802          [null, null],
803          [null, null], [
804            [null, null],
805            [null, null]]],
806        't = 200');
807
808    tick(300);
809    checkTimes(
810        player,
811        [null, 200], [
812          [null, 200],
813          [null, -300], [
814            [null, -800],
815            [null, -800]]],
816        't = 300');
817
818    player.play();
819    tick(310);
820    checkTimes(
821        player,
822        [110, 200], [
823          [110, 200],
824          [610, -300], [
825            [1110, -800],
826            [1110, -800]]],
827        't = 310');
828
829    tick(1310);
830    checkTimes(
831        player,
832        [110, 1200], [
833          [110, 500],
834          [610, 500], [
835            [1110, 200],
836            [1110, 200]]],
837        't = 1310');
838
839    player.pause();
840    checkTimes(
841        player,
842        [null, null], [
843          [null, 500],
844          [null, 500], [
845            [null, null],
846            [null, null]]],
847        't = 1310');
848
849    tick(1400);
850    checkTimes(
851        player,
852        [null, 1200], [
853          [null, 500],
854          [null, 500], [
855            [null, 200],
856            [null, 200]]],
857        't = 1410');
858
859    player.play();
860    tick(1410);
861    checkTimes(
862        player,
863        [210, 1200], [
864          [210, 500],
865          [710, 500], [
866            [1210, 200],
867            [1210, 200]]],
868        't = 1410');
869
870    tick(1610);
871    checkTimes(
872        player,
873        [210, 1400], [
874          [210, 500],
875          [710, 500], [
876            [1210, 400],
877            [1210, 400]]],
878        't = 1610');
879
880    player.pause();
881    tick(1810);
882    checkTimes(
883        player,
884        [null, 1400], [
885          [null, 500],
886          [null, 500], [
887            [null, 400],
888            [null, 400]]],
889        't = 1810');
890
891    player.play();
892    tick(1820);
893    checkTimes(
894        player,
895        [420, 1400], [
896          [420, 500],
897          [920, 500], [
898            [1420, 400],
899            [1420, 400]]],
900        't = 1820');
901
902    tick(2020);
903    checkTimes(
904        player,
905        [420, 1500], [
906          [420, 500],
907          [920, 500], [
908            [1420, 500],
909            [1420, 500]]],
910        't = 2020');
911
912    player.pause();
913    checkTimes(
914        player,
915        [null, 1500], [
916          [null, 500],
917          [null, 500], [
918            [null, 500],
919            [null, 500]]],
920        't = 2020');
921  });
922
923  test('pausing works as expected with an empty AnimationSequence inside an AnimationSequence', function() {
924    var player = document.timeline.play(this.seqWithEmptySeq_source);
925    tick(0);
926    checkTimes(
927        player,
928        [0, 0], [0, 0],
929        't = 0');
930
931    player.pause();
932    checkTimes(
933        player,
934        [null, 0], [null, 0],
935        't = 0 after pause');
936  });
937
938  test('pausing works as expected with an empty AnimationGroup inside an AnimationSequence', function() {
939    var player = document.timeline.play(this.seqWithEmptyGroup_source);
940    tick(0);
941    checkTimes(
942        player,
943        [0, 0], [0, 0],
944        't = 0');
945
946    player.pause();
947    checkTimes(
948        player,
949        [null, 0], [null, 0],
950        't = 0 after pause');
951  });
952
953  test('playState works for groups', function() {
954    var target = document.createElement('div');
955    document.body.appendChild(target);
956    var anim = new AnimationSequence([new Animation(target, [], 100), new Animation(target, [], 100)]);
957    var p = document.timeline.play(anim);
958    assert.equal(p.playState, 'pending');
959    tick(1);
960    assert.equal(p.playState, 'running');
961    assert.equal(p._childPlayers[0]._player.playState, 'running');
962    assert.equal(p._childPlayers[1]._player.playState, 'running');
963    tick(101);
964    assert.equal(p.playState, 'running');
965    assert.equal(p._childPlayers[0]._player.playState, 'finished');
966    assert.equal(p._childPlayers[1]._player.playState, 'running');
967    p.pause();
968    assert.equal(p.playState, 'pending');
969    assert.equal(p._childPlayers[0]._player.playState, 'paused');
970    assert.equal(p._childPlayers[1]._player.playState, 'pending');
971    tick(102);
972    assert.equal(p.playState, 'paused');
973    assert.equal(p._childPlayers[0]._player.playState, 'paused');
974    assert.equal(p._childPlayers[1]._player.playState, 'paused');
975    p.play();
976    assert.equal(p.playState, 'pending');
977    assert.equal(p._childPlayers[0]._player.playState, 'pending');
978    assert.equal(p._childPlayers[1]._player.playState, 'pending');
979    tick(103);
980    assert.equal(p.playState, 'running');
981    assert.equal(p._childPlayers[0]._player.playState, 'finished');
982    assert.equal(p._childPlayers[1]._player.playState, 'running');
983    tick(204);
984    assert.equal(p.playState, 'finished');
985    assert.equal(p._childPlayers[0]._player.playState, 'finished');
986    assert.equal(p._childPlayers[1]._player.playState, 'finished');
987  });
988
989  test('pausing then seeking out of range then seeking into range works', function() {
990    var target = document.createElement('div');
991    var anim = new Animation(target, [], {duration: 2000, fill: 'both'});
992    var group = new AnimationGroup([anim], {fill: 'none'});
993    var player = document.timeline.play(group);
994
995    player.pause();
996    player.currentTime = 3000;
997    tick(100);
998    player.currentTime = 1000;
999    assert.equal(player._childPlayers.length, 1);
1000    assert.equal(player._childPlayers[0]._player.playState, 'paused');
1001    assert.equal(player._childPlayers[0]._player.currentTime, 1000);
1002
1003  });
1004
1005  test('reversing then seeking out of range then seeking into range works', function() {
1006    var target = document.createElement('div');
1007    var anim = new Animation(target, [], {duration: 2000, fill: 'both'});
1008    var group = new AnimationGroup([anim], {fill: 'none'});
1009    var player = document.timeline.play(group);
1010
1011    player.currentTime = 1000;
1012    tick(100);
1013    player.reverse();
1014    player.currentTime = 3000;
1015    tick(110);
1016    player.currentTime = 1000;
1017    assert.equal(player.playbackRate, -1);
1018    assert.equal(player._childPlayers.length, 1);
1019    assert.equal(player._childPlayers[0]._player.playState, 'running');
1020    assert.equal(player._childPlayers[0]._player.currentTime, 1000);
1021    assert.equal(player._childPlayers[0]._player.playbackRate, -1);
1022
1023  });
1024
1025  test('fill none groups with fill none children do not fill', function() {
1026    var anim = new Animation(
1027        this.target,
1028        [{marginLeft: '0px'}, {marginLeft: '100px'}],
1029        {duration: 500, fill: 'none'});
1030    var group = new AnimationGroup([anim], {fill: 'none'});
1031    var player = document.timeline.play(group);
1032
1033    tick(0);
1034    assert.equal(getComputedStyle(this.target).marginLeft, '0px');
1035    tick(250);
1036    assert.equal(getComputedStyle(this.target).marginLeft, '50px');
1037    tick(501);
1038    assert.equal(getComputedStyle(this.target).marginLeft, '0px');
1039    tick(502);
1040  });
1041});
1042