mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-10 05:08:36 +02:00
Automatic update from web-platform-tests Add timeouts for EventWatchers on CSS animation tests (#22282) Previously the test harness could timeout while waiting on the event watcher. In this patch, a timeout was added to the watchers in cases where the events should fire on the next animation frame. With the change, we still see timeouts on individual tests, but no longer see the test harness timing out. Next steps: 1. Add animationcancel. For some reason, this event got overlooked previously and was never implemented. Adding this event resolves the majority of timeouts (confirmed in an experimental patch). 2. Reconnect and event delegate after calls to animation.effect. Currently, the lack of a delegate on the new effect halts the dispatching of subsequent animation events. Bug: 1059968 Change-Id: Ib5bf46762e316a5f3d5f33aa95bf74edaf42e773 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2105424 Reviewed-by: Yi Gu <yigu@chromium.org> Commit-Queue: Kevin Ellis <kevers@chromium.org> Cr-Commit-Position: refs/heads/master@{#750745} Co-authored-by: Kevin Ellis <kevers@chromium.org> -- wpt-commits: c1c943f3d9e3fe023e401a39db1a66e535a50561 wpt-pr: 22282
211 lines
6.7 KiB
HTML
211 lines
6.7 KiB
HTML
<!doctype html>
|
|
<meta charset=utf-8>
|
|
<title>CSSAnimation.effect</title>
|
|
<meta name="timeout" content="long">
|
|
<!-- TODO: Add a more specific link for this once it is specified. -->
|
|
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#cssanimation">
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script src="support/testcommon.js"></script>
|
|
<style>
|
|
@keyframes anim {
|
|
from {
|
|
margin-left: 0px;
|
|
}
|
|
to {
|
|
margin-left: 100px;
|
|
}
|
|
}
|
|
</style>
|
|
<div id="log"></div>
|
|
<script>
|
|
'use strict';
|
|
|
|
promise_test(async t => {
|
|
const div = addDiv(t);
|
|
div.style.animation = 'anim 100s';
|
|
|
|
const watcher = new EventWatcher(t, div, [ 'animationend',
|
|
'animationcancel' ],
|
|
fastEventsTimeout);
|
|
const animation = div.getAnimations()[0];
|
|
await animation.ready;
|
|
|
|
animation.currentTime = 50 * MS_PER_SEC;
|
|
animation.effect = null;
|
|
assert_equals(animation.playState, 'finished');
|
|
assert_equals(getComputedStyle(div).marginLeft, '0px');
|
|
await watcher.wait_for('animationend');
|
|
}, 'Setting a null effect on a running animation fires an animationend event');
|
|
|
|
promise_test(async t => {
|
|
const div = addDiv(t);
|
|
div.style.animation = 'anim 100s';
|
|
|
|
const animation = div.getAnimations()[0];
|
|
await animation.ready;
|
|
|
|
animation.currentTime = 50 * MS_PER_SEC;
|
|
animation.effect = new KeyframeEffect(div,
|
|
{ left: [ '0px' , '100px'] },
|
|
100 * MS_PER_SEC);
|
|
assert_equals(getComputedStyle(div).marginLeft, '0px');
|
|
assert_equals(getComputedStyle(div).left, '50px');
|
|
}, 'Replacing an animation\'s effect with an effect that targets a different ' +
|
|
'property should update both properties');
|
|
|
|
promise_test(async t => {
|
|
const div = addDiv(t);
|
|
div.style.animation = 'anim 100s';
|
|
|
|
const animation = div.getAnimations()[0];
|
|
await animation.ready;
|
|
|
|
animation.currentTime = 50 * MS_PER_SEC;
|
|
animation.effect = new KeyframeEffect(div,
|
|
{ left: [ '0px' , '100px'] },
|
|
20 * MS_PER_SEC);
|
|
assert_equals(animation.playState, 'finished');
|
|
}, 'Replacing an animation\'s effect with a shorter one that should have ' +
|
|
'already finished, the animation finishes immediately');
|
|
|
|
promise_test(async t => {
|
|
const div = addDiv(t);
|
|
div.style.animation = 'anim 100s';
|
|
|
|
const animation = div.getAnimations()[0];
|
|
assert_true(animation.pending);
|
|
|
|
animation.effect = new KeyframeEffect(div,
|
|
{ left: [ '0px' , '100px'] },
|
|
100 * MS_PER_SEC);
|
|
assert_true(animation.pending);
|
|
|
|
await animation.ready;
|
|
|
|
assert_false(animation.pending);
|
|
}, 'A play-pending animation\'s effect whose effect is replaced still exits ' +
|
|
'the pending state');
|
|
|
|
promise_test(async t => {
|
|
const div1 = addDiv(t);
|
|
const div2 = addDiv(t);
|
|
|
|
const watcher1 = new EventWatcher(t, div1, 'animationstart',
|
|
fastEventsTimeout);
|
|
// Watch |div2| as well to ensure it does *not* get events.
|
|
const watcher2 = new EventWatcher(t, div2, 'animationstart');
|
|
|
|
div1.style.animation = 'anim 100s';
|
|
|
|
const animation = div1.getAnimations()[0];
|
|
animation.effect = new KeyframeEffect(div2,
|
|
{ left: [ '0px', '100px' ] },
|
|
100 * MS_PER_SEC);
|
|
|
|
await watcher1.wait_for('animationstart');
|
|
|
|
assert_equals(animation.effect.target, div2);
|
|
|
|
// Then wait a couple of frames and check that no event was dispatched.
|
|
await waitForAnimationFrames(2);
|
|
}, 'CSS animation events are dispatched at the original element even after'
|
|
+ ' setting an effect with a different target element');
|
|
|
|
promise_test(async t => {
|
|
const div = addDiv(t);
|
|
const watcher = new EventWatcher(t, div, [ 'animationstart',
|
|
'animationend',
|
|
'animationcancel' ],
|
|
fastEventsTimeout);
|
|
div.style.animation = 'anim 100s';
|
|
const animation = div.getAnimations()[0];
|
|
animation.finish();
|
|
|
|
await watcher.wait_for([ 'animationstart', 'animationend' ]);
|
|
// Set a longer effect
|
|
animation.effect = new KeyframeEffect(div,
|
|
{ left: [ '0px', '100px' ] },
|
|
200 * MS_PER_SEC);
|
|
await watcher.wait_for('animationstart');
|
|
}, 'After replacing a finished animation\'s effect with a longer one ' +
|
|
'it fires an animationstart event');
|
|
|
|
test(t => {
|
|
const div = addDiv(t);
|
|
|
|
// Create custom keyframes so we can tweak them
|
|
const stylesheet = document.styleSheets[0];
|
|
const keyframes = '@keyframes anim-custom { to { left: 100px } }';
|
|
const ruleIndex = stylesheet.insertRule(keyframes, 0);
|
|
const keyframesRule = stylesheet.cssRules[ruleIndex];
|
|
|
|
t.add_cleanup(function() {
|
|
stylesheet.deleteRule(ruleIndex);
|
|
});
|
|
|
|
div.style.animation = 'anim-custom 100s';
|
|
|
|
// Replace the effect
|
|
const animation = div.getAnimations()[0];
|
|
animation.effect = new KeyframeEffect(
|
|
div,
|
|
{ left: '200px' },
|
|
200 * MS_PER_SEC
|
|
);
|
|
|
|
// Update the timing properties
|
|
div.style.animationDuration = '4s';
|
|
div.style.animationIterationCount = '6';
|
|
div.style.animationDirection = 'reverse';
|
|
div.style.animationDelay = '8s';
|
|
div.style.animationFillMode = 'both';
|
|
div.style.animationPlayState = 'paused';
|
|
|
|
// Update the keyframes
|
|
keyframesRule.deleteRule(0);
|
|
keyframesRule.appendRule('to { left: 300px }');
|
|
|
|
// Check nothing (except the play state) changed
|
|
assert_equals(
|
|
animation.effect.getTiming().duration,
|
|
200 * MS_PER_SEC,
|
|
'duration should be the value set by the API'
|
|
);
|
|
assert_equals(
|
|
animation.effect.getTiming().iterations,
|
|
1,
|
|
'iterations should be the value set by the API'
|
|
);
|
|
assert_equals(
|
|
animation.effect.getTiming().direction,
|
|
'normal',
|
|
'direction should be the value set by the API'
|
|
);
|
|
assert_equals(
|
|
animation.effect.getTiming().delay,
|
|
0,
|
|
'delay should be the value set by the API'
|
|
);
|
|
assert_equals(
|
|
animation.effect.getTiming().fill,
|
|
'auto',
|
|
'fill should be the value set by the API'
|
|
);
|
|
assert_equals(
|
|
animation.effect.getKeyframes()[0].left,
|
|
'200px',
|
|
'keyframes should be the value set by the API'
|
|
);
|
|
|
|
// Unlike the other properties animation-play-state maps to the Animation
|
|
// not the KeyframeEffect so it should be overridden.
|
|
assert_equals(
|
|
animation.playState,
|
|
'paused',
|
|
'play state should be the value set by style'
|
|
);
|
|
}, 'Replacing the effect of a CSSAnimation causes subsequent changes to'
|
|
+ ' corresponding animation-* properties to be ignored');
|
|
|
|
</script>
|