summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-animations/CSSAnimation-canceling.tentative.html
blob: b76af2c24ac636bf3ea73050eb64555d6b0e2100 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
<!doctype html>
<meta charset=utf-8>
<title>Canceling a CSS animation</title>
<!-- TODO: Add a more specific link for this once it is specified. -->
<link rel="help" href="https://drafts.csswg.org/css-animations-2/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/testcommon.js"></script>
<style>
@keyframes translateAnim {
  to { transform: translate(100px) }
}
@keyframes marginLeftAnim {
  to { margin-left: 100px }
}
@keyframes marginLeftAnim100To200 {
  from { margin-left: 100px }
  to { margin-left: 200px }
}
</style>
<div id="log"></div>
<script>
'use strict';

promise_test(async t => {
  const div = addDiv(t, { style: 'animation: translateAnim 100s' });
  const animation = div.getAnimations()[0];

  await animation.ready;

  assert_not_equals(getComputedStyle(div).transform, 'none',
                    'transform style is animated before canceling');
  animation.cancel();
  assert_equals(getComputedStyle(div).transform, 'none',
                'transform style is no longer animated after canceling');
}, 'Animated style is cleared after canceling a running CSS animation');

promise_test(async t => {
  const div = addDiv(t, { style: 'animation: translateAnim 100s forwards' });
  const animation = div.getAnimations()[0];
  animation.finish();

  await animation.ready;

  assert_not_equals(getComputedStyle(div).transform, 'none',
                    'transform style is filling before canceling');
  animation.cancel();
  assert_equals(getComputedStyle(div).transform, 'none',
                'fill style is cleared after canceling');
}, 'Animated style is cleared after canceling a filling CSS animation');

test(t => {
  const div = addDiv(t, { style: 'animation: marginLeftAnim 100s linear' });
  const animation = div.getAnimations()[0];
  animation.cancel();

  assert_equals(getComputedStyle(div).marginLeft, '0px',
                'margin-left style is not animated after canceling');

  animation.currentTime = 50 * 1000;
  assert_equals(getComputedStyle(div).marginLeft, '50px',
                'margin-left style is updated when canceled animation is'
                + ' seeked');
}, 'After canceling an animation, it can still be seeked');

promise_test(async t => {
  const div =
    addDiv(t, { style: 'animation: marginLeftAnim100To200 100s linear' });
  const animation = div.getAnimations()[0];

  await animation.ready;

  animation.cancel();
  assert_equals(getComputedStyle(div).marginLeft, '0px',
                'margin-left style is not animated after canceling');
  animation.play();
  assert_equals(getComputedStyle(div).marginLeft, '100px',
                'margin-left style is animated after re-starting animation');

  await animation.ready;

  assert_equals(animation.playState, 'running',
                'Animation succeeds in running after being re-started');
}, 'After canceling an animation, it can still be re-used');

test(t => {
  const div =
    addDiv(t, { style: 'animation: marginLeftAnim100To200 100s linear' });
  const animation = div.getAnimations()[0];
  animation.cancel();
  assert_equals(getComputedStyle(div).marginLeft, '0px',
                'margin-left style is not animated after canceling');

  // Trigger a change to some animation properties and check that this
  // doesn't cause the animation to become live again
  div.style.animationDuration = '200s';
  assert_equals(getComputedStyle(div).marginLeft, '0px',
                'margin-left style is still not animated after updating'
                + ' animation-duration');
  assert_equals(animation.playState, 'idle',
                'Animation is still idle after updating animation-duration');
}, 'After canceling an animation, updating animation properties doesn\'t make'
   + ' it live again');

test(t => {
  const div =
    addDiv(t, { style: 'animation: marginLeftAnim100To200 100s linear' });
  const animation = div.getAnimations()[0];
  animation.cancel();
  assert_equals(getComputedStyle(div).marginLeft, '0px',
                'margin-left style is not animated after canceling');

  // Make some changes to animation-play-state and check that the
  // animation doesn't become live again. This is because it should be
  // possible to cancel an animation from script such that all future
  // changes to style are ignored.

  // Redundant change
  div.style.animationPlayState = 'running';
  assert_equals(animation.playState, 'idle',
                'Animation is still idle after a redundant change to'
                + ' animation-play-state');

  // Pause
  div.style.animationPlayState = 'paused';
  assert_equals(animation.playState, 'idle',
                'Animation is still idle after setting'
                + ' animation-play-state: paused');

  // Play
  div.style.animationPlayState = 'running';
  assert_equals(animation.playState, 'idle',
                'Animation is still idle after re-setting'
                + ' animation-play-state: running');

}, 'After canceling an animation, updating animation-play-state doesn\'t'
   + ' make it live again');

promise_test(async t => {
  const div = addDiv(t, { style: 'animation: translateAnim 10s both' });
  div.style.marginLeft = '0px';

  const animation = div.getAnimations()[0];

  await animation.ready;

  assert_equals(animation.playState, 'running');

  div.style.animationName = 'none';
  flushComputedStyle(div);

  await waitForFrame();

  assert_equals(animation.playState, 'idle');
  assert_equals(getComputedStyle(div).marginLeft, '0px');
}, 'Setting animation-name to \'none\' cancels the animation');

promise_test(async t => {
  const div = addDiv(t, { style: 'animation: translateAnim 10s both' });
  const animation = div.getAnimations()[0];

  await animation.ready;

  assert_equals(animation.playState, 'running');

  div.style.display = 'none';

  await waitForFrame();

  assert_equals(animation.playState, 'idle');
  assert_equals(getComputedStyle(div).marginLeft, '0px');
}, 'Setting display:none on an element cancel its animations');

promise_test(async t => {
  const parentDiv = addDiv(t);
  const childDiv  = document.createElement('div');
  parentDiv.appendChild(childDiv);

  childDiv.setAttribute('style', 'animation: translateAnim 10s both');
  flushComputedStyle(childDiv);

  const animation = childDiv.getAnimations()[0];

  await animation.ready;

  assert_equals(animation.playState, 'running');

  parentDiv.style.display = 'none';
  await waitForFrame();

  assert_equals(animation.playState, 'idle');
  assert_equals(getComputedStyle(childDiv).marginLeft, '0px');
}, 'Setting display:none on an ancestor element cancels animations on ' +
   'descendants');

</script>