summaryrefslogtreecommitdiffstats
path: root/dom/animation/test/css-transitions/file_csstransition-events.html
blob: 5011bc1309bd1ede9f097db6a7e4e307cbbf2d43 (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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
<!doctype html>
<meta charset=utf-8>
<title>Tests for CSS-Transition events</title>
<link rel="help" href="https://drafts.csswg.org/css-transitions-2/#transition-events">
<script src="../testcommon.js"></script>
<body>
<script>
'use strict';

/**
 * Helper class to record the elapsedTime member of each event.
 * The EventWatcher class in testharness.js allows us to wait on
 * multiple events in a certain order but only records the event
 * parameters of the most recent event.
 */
function TransitionEventHandler(target) {
  this.target = target;
  this.target.ontransitionrun = function(evt) {
    this.transitionrun = evt.elapsedTime;
  }.bind(this);
  this.target.ontransitionstart = function(evt) {
    this.transitionstart = evt.elapsedTime;
  }.bind(this);
  this.target.ontransitionend = function(evt) {
    this.transitionend = evt.elapsedTime;
  }.bind(this);
}

TransitionEventHandler.prototype.clear = function() {
  this.transitionrun   = undefined;
  this.transitionstart = undefined;
  this.transitionend   = undefined;
};

function setupTransition(t, transitionStyle) {
  var div, watcher, handler, transition;
  transitionStyle = transitionStyle || 'transition: margin-left 100s 100s';
  div = addDiv(t, { style: transitionStyle });
  watcher = new EventWatcher(t, div, [ 'transitionrun',
                                       'transitionstart',
                                       'transitionend' ]);
  handler = new TransitionEventHandler(div);
  flushComputedStyle(div);

  div.style.marginLeft = '100px';
  flushComputedStyle(div);

  transition = div.getAnimations()[0];

  return [transition, watcher, handler];
}

// On the next frame (i.e. when events are queued), whether or not the
// transition is still pending depends on the implementation.
promise_test(function(t) {
  var [transition, watcher, handler] = setupTransition(t);
  return watcher.wait_for('transitionrun').then(function(evt) {
    assert_equals(evt.elapsedTime, 0.0);
  });
}, 'Idle -> Pending or Before');

promise_test(function(t) {
  var [transition, watcher, handler] = setupTransition(t);
  // Force the transition to leave the idle phase
  transition.startTime = document.timeline.currentTime;
  return watcher.wait_for('transitionrun').then(function(evt) {
    assert_equals(evt.elapsedTime, 0.0);
  });
}, 'Idle -> Before');

promise_test(function(t) {
  var [transition, watcher, handler] = setupTransition(t);
  // Seek to Active phase.
  transition.currentTime = 100 * MS_PER_SEC;
  transition.pause();
  return watcher.wait_for([ 'transitionrun',
                            'transitionstart' ]).then(function(evt) {
    assert_equals(handler.transitionrun, 0.0);
    assert_equals(handler.transitionstart, 0.0);
  });
}, 'Idle or Pending -> Active');

promise_test(function(t) {
  var [transition, watcher, handler] = setupTransition(t);
  // Seek to After phase.
  transition.finish();
  return watcher.wait_for([ 'transitionrun',
                            'transitionstart',
                            'transitionend' ]).then(function(evt) {
    assert_equals(handler.transitionrun, 0.0);
    assert_equals(handler.transitionstart, 0.0);
    assert_equals(handler.transitionend, 100.0);
  });
}, 'Idle or Pending -> After');

promise_test(function(t) {
  var [transition, watcher, handler] = setupTransition(t);

  return Promise.all([ watcher.wait_for('transitionrun'),
                       transition.ready ]).then(function() {
    transition.currentTime = 100 * MS_PER_SEC;
    return watcher.wait_for('transitionstart');
  }).then(function() {
    assert_equals(handler.transitionstart, 0.0);
  });
}, 'Before -> Active');

promise_test(function(t) {
  var [transition, watcher, handler] = setupTransition(t);
  return Promise.all([ watcher.wait_for('transitionrun'),
                       transition.ready ]).then(function() {
    // Seek to After phase.
    transition.currentTime = 200 * MS_PER_SEC;
    return watcher.wait_for([ 'transitionstart', 'transitionend' ]);
  }).then(function(evt) {
    assert_equals(handler.transitionstart, 0.0);
    assert_equals(handler.transitionend, 100.0);
  });
}, 'Before -> After');

promise_test(function(t) {
  var [transition, watcher, handler] = setupTransition(t);
  // Seek to Active phase.
  transition.currentTime = 100 * MS_PER_SEC;
  return watcher.wait_for([ 'transitionrun',
                            'transitionstart' ]).then(function(evt) {
    // Seek to Before phase.
    transition.currentTime = 0;
    return watcher.wait_for('transitionend');
  }).then(function(evt) {
    assert_equals(evt.elapsedTime, 0.0);
  });
}, 'Active -> Before');

promise_test(function(t) {
  var [transition, watcher, handler] = setupTransition(t);
  // Seek to Active phase.
  transition.currentTime = 100 * MS_PER_SEC;
  return watcher.wait_for([ 'transitionrun',
                            'transitionstart' ]).then(function(evt) {
    // Seek to After phase.
    transition.currentTime = 200 * MS_PER_SEC;
    return watcher.wait_for('transitionend');
  }).then(function(evt) {
    assert_equals(evt.elapsedTime, 100.0);
  });
}, 'Active -> After');

promise_test(function(t) {
  var [transition, watcher, handler] = setupTransition(t);
  // Seek to After phase.
  transition.finish();
  return watcher.wait_for([ 'transitionrun',
                            'transitionstart',
                            'transitionend' ]).then(function(evt) {
    // Seek to Before phase.
    transition.currentTime = 0;
    return watcher.wait_for([ 'transitionstart', 'transitionend' ]);
  }).then(function(evt) {
    assert_equals(handler.transitionstart, 100.0);
    assert_equals(handler.transitionend, 0.0);
  });
}, 'After -> Before');

promise_test(function(t) {
  var [transition, watcher, handler] = setupTransition(t);
  // Seek to After phase.
  transition.finish();
  return watcher.wait_for([ 'transitionrun',
                            'transitionstart',
                            'transitionend' ]).then(function(evt) {
    // Seek to Active phase.
    transition.currentTime = 100 * MS_PER_SEC;
    return watcher.wait_for('transitionstart');
  }).then(function(evt) {
    assert_equals(evt.elapsedTime, 100.0);
  });
}, 'After -> Active');

promise_test(function(t) {
  var [transition, watcher, handler] =
    setupTransition(t, 'transition: margin-left 100s -50s');

  return watcher.wait_for([ 'transitionrun',
                            'transitionstart' ]).then(function() {
    assert_equals(handler.transitionrun, 50.0);
    assert_equals(handler.transitionstart, 50.0);
    transition.finish();
    return watcher.wait_for('transitionend');
  }).then(function(evt) {
    assert_equals(evt.elapsedTime, 100.0);
  });
}, 'Calculating the interval start and end time with negative start delay.');

promise_test(function(t) {
  var [transition, watcher, handler] = setupTransition(t);

  return watcher.wait_for('transitionrun').then(function(evt) {
    // We can't set the end delay via generated effect timing.
    // Because CSS-Transition use the AnimationEffectTimingReadOnly.
    transition.effect = new KeyframeEffect(handler.target,
                                           { marginleft: [ '0px', '100px' ]},
                                           { duration: 100 * MS_PER_SEC,
                                             endDelay: -50 * MS_PER_SEC });
    // Seek to Before and play.
    transition.cancel();
    transition.play();
    return watcher.wait_for('transitionstart');
  }).then(function() {
    assert_equals(handler.transitionstart, 0.0);

    // Seek to After phase.
    transition.finish();
    return watcher.wait_for('transitionend');
  }).then(function(evt) {
    assert_equals(evt.elapsedTime, 50.0);
  });
}, 'Calculating the interval start and end time with negative end delay.');

done();
</script>
</body>
</html>