mirror of
https://github.com/servo/servo.git
synced 2025-08-10 07:55:33 +01:00
Update web-platform-tests to revision 0a518aaff73532a26e175789f7e75fa99593ac64
This commit is contained in:
parent
9c172f49d0
commit
abcd4b654f
92 changed files with 2869 additions and 642 deletions
|
@ -0,0 +1,84 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>easing tests</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-easing">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<script src="../resources/effect-easing-tests.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function assert_progress(animation, currentTime, easingFunction) {
|
||||
animation.currentTime = currentTime;
|
||||
var portion = currentTime / animation.effect.timing.duration;
|
||||
assert_approx_equals(animation.effect.getComputedTiming().progress,
|
||||
easingFunction(portion),
|
||||
0.01,
|
||||
'The progress of the animation should be approximately ' +
|
||||
easingFunction(portion) + ' at ' + currentTime + 'ms');
|
||||
}
|
||||
|
||||
gEffectEasingTests.forEach(function(options) {
|
||||
test(function(t) {
|
||||
var target = createDiv(t);
|
||||
var anim = target.animate([ { opacity: 0 }, { opacity: 1 } ],
|
||||
{ duration: 1000 * MS_PER_SEC,
|
||||
fill: 'forwards' });
|
||||
anim.effect.timing.easing = options.easing;
|
||||
assert_equals(anim.effect.timing.easing, options.easing);
|
||||
|
||||
var easing = options.easingFunction;
|
||||
assert_progress(anim, 0, easing);
|
||||
assert_progress(anim, 250 * MS_PER_SEC, easing);
|
||||
assert_progress(anim, 500 * MS_PER_SEC, easing);
|
||||
assert_progress(anim, 750 * MS_PER_SEC, easing);
|
||||
assert_progress(anim, 1000 * MS_PER_SEC, easing);
|
||||
}, options.desc);
|
||||
});
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
|
||||
assert_throws({ name: 'TypeError' },
|
||||
function() {
|
||||
anim.effect.timing.easing = '';
|
||||
});
|
||||
assert_throws({ name: 'TypeError' },
|
||||
function() {
|
||||
anim.effect.timing.easing = 'test';
|
||||
});
|
||||
}, 'Test invalid easing value');
|
||||
|
||||
test(function(t) {
|
||||
var delay = 1000 * MS_PER_SEC;
|
||||
|
||||
var target = createDiv(t);
|
||||
var anim = target.animate([ { opacity: 0 }, { opacity: 1 } ],
|
||||
{ duration: 1000 * MS_PER_SEC,
|
||||
fill: 'both',
|
||||
delay: delay,
|
||||
easing: 'steps(2, start)' });
|
||||
|
||||
anim.effect.timing.easing = 'steps(2, end)';
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0,
|
||||
'easing replace to steps(2, end) at before phase');
|
||||
|
||||
anim.currentTime = delay + 750 * MS_PER_SEC;
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0.5,
|
||||
'change currentTime to active phase');
|
||||
|
||||
anim.effect.timing.easing = 'steps(2, start)';
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'easing replace to steps(2, start) at active phase');
|
||||
|
||||
anim.currentTime = delay + 1500 * MS_PER_SEC;
|
||||
anim.effect.timing.easing = 'steps(2, end)';
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'easing replace to steps(2, end) again at after phase');
|
||||
}, 'Change the easing while the animation is running');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>fill tests</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-fill">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
["none", "forwards", "backwards", "both", ].forEach(function(fill){
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 100);
|
||||
anim.effect.timing.fill = fill;
|
||||
assert_equals(anim.effect.timing.fill, fill, 'set fill ' + fill);
|
||||
assert_equals(anim.effect.getComputedTiming().fill, fill, 'getComputedTiming() after set fill ' + fill);
|
||||
}, 'set fill ' + fill);
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,136 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Tests for discrete animation</title>
|
||||
<link rel="help" href="http://w3c.github.io/web-animations/#animatable-as-string-section">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
|
||||
var anim = div.animate({ fontStyle: [ 'normal', 'italic' ] },
|
||||
{ duration: 1000, fill: 'forwards' });
|
||||
|
||||
assert_equals(getComputedStyle(div).fontStyle, 'normal',
|
||||
'Animation produces \'from\' value at start of interval');
|
||||
anim.currentTime = anim.effect.getComputedTiming().duration / 2 - 1;
|
||||
assert_equals(getComputedStyle(div).fontStyle, 'normal',
|
||||
'Animation produces \'from\' value just before the middle of'
|
||||
+ ' the interval');
|
||||
anim.currentTime++;
|
||||
assert_equals(getComputedStyle(div).fontStyle, 'italic',
|
||||
'Animation produces \'to\' value at exact middle of'
|
||||
+ ' the interval');
|
||||
anim.finish();
|
||||
assert_equals(getComputedStyle(div).fontStyle, 'italic',
|
||||
'Animation produces \'to\' value during forwards fill');
|
||||
}, 'Test animating discrete values');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var originalHeight = getComputedStyle(div).height;
|
||||
|
||||
var anim = div.animate({ height: [ 'auto', '200px' ] },
|
||||
{ duration: 1000, fill: 'forwards' });
|
||||
|
||||
assert_equals(getComputedStyle(div).height, originalHeight,
|
||||
'Animation produces \'from\' value at start of interval');
|
||||
anim.currentTime = anim.effect.getComputedTiming().duration / 2 - 1;
|
||||
assert_equals(getComputedStyle(div).height, originalHeight,
|
||||
'Animation produces \'from\' value just before the middle of'
|
||||
+ ' the interval');
|
||||
anim.currentTime++;
|
||||
assert_equals(getComputedStyle(div).height, '200px',
|
||||
'Animation produces \'to\' value at exact middle of'
|
||||
+ ' the interval');
|
||||
anim.finish();
|
||||
assert_equals(getComputedStyle(div).height, '200px',
|
||||
'Animation produces \'to\' value during forwards fill');
|
||||
}, 'Test discrete animation is used when interpolation fails');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var originalHeight = getComputedStyle(div).height;
|
||||
|
||||
var anim = div.animate({ height: [ 'auto',
|
||||
'200px',
|
||||
'300px',
|
||||
'auto',
|
||||
'400px' ] },
|
||||
{ duration: 1000, fill: 'forwards' });
|
||||
|
||||
// There are five values, so there are four pairs to try to interpolate.
|
||||
// We test at the middle of each pair.
|
||||
assert_equals(getComputedStyle(div).height, originalHeight,
|
||||
'Animation produces \'from\' value at start of interval');
|
||||
anim.currentTime = 125;
|
||||
assert_equals(getComputedStyle(div).height, '200px',
|
||||
'First non-interpolable pair uses discrete interpolation');
|
||||
anim.currentTime += 250;
|
||||
assert_equals(getComputedStyle(div).height, '250px',
|
||||
'Second interpolable pair uses linear interpolation');
|
||||
anim.currentTime += 250;
|
||||
assert_equals(getComputedStyle(div).height, originalHeight,
|
||||
'Third non-interpolable pair uses discrete interpolation');
|
||||
anim.currentTime += 250;
|
||||
assert_equals(getComputedStyle(div).height, '400px',
|
||||
'Fourth non-interpolable pair uses discrete interpolation');
|
||||
}, 'Test discrete animation is used only for pairs of values that cannot'
|
||||
+ ' be interpolated');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var originalHeight = getComputedStyle(div).height;
|
||||
|
||||
// Easing: http://cubic-bezier.com/#.68,0,1,.01
|
||||
// With this curve, we don't reach the 50% point until about 95% of
|
||||
// the time has expired.
|
||||
var anim = div.animate({ fontStyle: [ 'italic', 'oblique' ] },
|
||||
{ duration: 1000, fill: 'forwards',
|
||||
easing: 'cubic-bezier(0.68,0,1,0.01)' });
|
||||
|
||||
assert_equals(getComputedStyle(div).fontStyle, 'italic',
|
||||
'Animation produces \'from\' value at start of interval');
|
||||
anim.currentTime = 940;
|
||||
assert_equals(getComputedStyle(div).fontStyle, 'italic',
|
||||
'Animation produces \'from\' value at 94% of the iteration'
|
||||
+ ' time');
|
||||
anim.currentTime = 960;
|
||||
assert_equals(getComputedStyle(div).fontStyle, 'oblique',
|
||||
'Animation produces \'to\' value at 96% of the iteration'
|
||||
+ ' time');
|
||||
}, 'Test the 50% switch point for discrete animation is based on the'
|
||||
+ ' effect easing');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var originalHeight = getComputedStyle(div).height;
|
||||
|
||||
// Easing: http://cubic-bezier.com/#.68,0,1,.01
|
||||
// With this curve, we don't reach the 50% point until about 95% of
|
||||
// the time has expired.
|
||||
var anim = div.animate([ { fontStyle: 'italic',
|
||||
easing: 'cubic-bezier(0.68,0,1,0.01)' },
|
||||
{ fontStyle: 'oblique' } ],
|
||||
{ duration: 1000, fill: 'forwards' });
|
||||
|
||||
assert_equals(getComputedStyle(div).fontStyle, 'italic',
|
||||
'Animation produces \'from\' value at start of interval');
|
||||
anim.currentTime = 940;
|
||||
assert_equals(getComputedStyle(div).fontStyle, 'italic',
|
||||
'Animation produces \'from\' value at 94% of the iteration'
|
||||
+ ' time');
|
||||
anim.currentTime = 960;
|
||||
assert_equals(getComputedStyle(div).fontStyle, 'oblique',
|
||||
'Animation produces \'to\' value at 96% of the iteration'
|
||||
+ ' time');
|
||||
}, 'Test the 50% switch point for discrete animation is based on the'
|
||||
+ ' keyframe easing');
|
||||
|
||||
</script>
|
|
@ -0,0 +1,120 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Tests for not animatable properties</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#not-animatable-section">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ display: [ 'inline', 'inline-block' ] }, 1000);
|
||||
|
||||
assert_equals(anim.effect.getFrames().length, 0,
|
||||
'Animation specified using property-indexed notation but'
|
||||
+ ' consisting of only non-animatable properties should not'
|
||||
+ ' contain any keyframes');
|
||||
}, '\'display\' property cannot be animated using property-indexed notation');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate([ { display: 'inline' }, { display: 'inline-block' } ],
|
||||
1000);
|
||||
|
||||
assert_equals(anim.effect.getFrames().length, 2,
|
||||
'Animation specified using a keyframe sequence where each'
|
||||
+ ' keyframe contains only non-animatable properties should'
|
||||
+ ' return an equal number of (empty) keyframes');
|
||||
assert_false(anim.effect.getFrames()[0].hasOwnProperty('display'),
|
||||
'Initial keyframe should not have the \'display\' property');
|
||||
assert_false(anim.effect.getFrames()[1].hasOwnProperty('display'),
|
||||
'Final keyframe should not have the \'display\' property');
|
||||
}, '\'display\' property cannot be animated using a keyframe sequence');
|
||||
|
||||
test(function(t) {
|
||||
var properties = {
|
||||
// CSS Animations properties
|
||||
animation: [ 'anim 1s', 'anim 2s' ],
|
||||
animationName: [ 'abc', 'xyz' ],
|
||||
animationTimingFunction: [ 'ease', 'steps(2)' ],
|
||||
animationDelay: [ '1s', '2s' ],
|
||||
animationIterationCount: [ 1, 2 ],
|
||||
animationDirection: [ 'normal', 'reverse' ],
|
||||
animationFillMode: [ 'forwards', 'backwards' ],
|
||||
animationPlayState: [ 'paused', 'running' ],
|
||||
|
||||
// CSS Transitions properties
|
||||
transition: [ 'all 1s', 'all 2s' ],
|
||||
transitionDelay: [ '1s', '2s' ],
|
||||
transitionDuration: [ '1s', '2s' ],
|
||||
transitionProperty: [ 'all', 'opacity' ],
|
||||
transitionTimingFunction: [ 'ease', 'ease-out' ]
|
||||
};
|
||||
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate(properties, 1000);
|
||||
|
||||
assert_equals(anim.effect.getFrames().length, 0,
|
||||
'Animation specified using property-indexed notation but'
|
||||
+ ' consisting of only non-animatable properties should not'
|
||||
+ ' contain any keyframes');
|
||||
}, 'CSS animations and CSS transitions properties cannot be animated using'
|
||||
+ ' property-indexed notation');
|
||||
|
||||
test(function(t) {
|
||||
var frames = [
|
||||
{
|
||||
animation: 'anim 1s',
|
||||
animationName: 'abc',
|
||||
animationTimingFunction: 'ease',
|
||||
animationDelay: '1s',
|
||||
animationIterationCount: 1,
|
||||
animationDirection: 'normal',
|
||||
animationFillMode: 'forwards',
|
||||
animationPlayState: 'paused',
|
||||
transition: 'all 1s',
|
||||
transitionDelay: '1s',
|
||||
transitionDuration: '1s',
|
||||
transitionProperty: 'opacity',
|
||||
transitionTimingFunction: 'ease'
|
||||
},
|
||||
{
|
||||
animation: 'anim 2s',
|
||||
animationName: 'xyz',
|
||||
animationTimingFunction: 'steps(2)',
|
||||
animationDelay: '2s',
|
||||
animationIterationCount: 2,
|
||||
animationDirection: 'reverse',
|
||||
animationFillMode: 'backwards',
|
||||
animationPlayState: 'running',
|
||||
transition: 'all 2s',
|
||||
transitionDelay: '2s',
|
||||
transitionDuration: '2s',
|
||||
transitionProperty: 'all',
|
||||
transitionTimingFunction: 'ease-out'
|
||||
}
|
||||
];
|
||||
var defaultKeyframeProperties = [ 'computedOffset', 'easing', 'offset' ];
|
||||
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate(frames, 1000);
|
||||
|
||||
assert_equals(anim.effect.getFrames().length, 2,
|
||||
'Animation specified using a keyframe sequence where each'
|
||||
+ ' keyframe contains only non-animatable properties should'
|
||||
+ ' return an equal number of (empty) keyframes');
|
||||
assert_array_equals(Object.keys(anim.effect.getFrames()[0]),
|
||||
defaultKeyframeProperties,
|
||||
'Initial keyframe should not contain any properties other'
|
||||
+ ' than the default keyframe properties');
|
||||
assert_array_equals(Object.keys(anim.effect.getFrames()[1]),
|
||||
defaultKeyframeProperties,
|
||||
'Final keyframe should not contain any properties other'
|
||||
+ ' than the default keyframe properties');
|
||||
}, 'CSS animations and CSS transitions properties cannot be animated using'
|
||||
+ ' a sequence of keyframes');
|
||||
</script>
|
|
@ -0,0 +1,86 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Tests that property values respond to changes to their context</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#keyframes-section">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
div.style.fontSize = '10px';
|
||||
var animation = div.animate([ { marginLeft: '10em' },
|
||||
{ marginLeft: '20em' } ], 1000);
|
||||
animation.currentTime = 500;
|
||||
assert_equals(getComputedStyle(div).marginLeft, '150px',
|
||||
'Effect value before updating font-size');
|
||||
div.style.fontSize = '20px';
|
||||
assert_equals(getComputedStyle(div).marginLeft, '300px',
|
||||
'Effect value after updating font-size');
|
||||
}, 'Effect values reflect changes to font-size on element');
|
||||
|
||||
test(function(t) {
|
||||
var parentDiv = createDiv(t);
|
||||
var div = createDiv(t);
|
||||
parentDiv.appendChild(div);
|
||||
parentDiv.style.fontSize = '10px';
|
||||
|
||||
var animation = div.animate([ { marginLeft: '10em' },
|
||||
{ marginLeft: '20em' } ], 1000);
|
||||
animation.currentTime = 500;
|
||||
assert_equals(getComputedStyle(div).marginLeft, '150px',
|
||||
'Effect value before updating font-size on parent element');
|
||||
parentDiv.style.fontSize = '20px';
|
||||
assert_equals(getComputedStyle(div).marginLeft, '300px',
|
||||
'Effect value after updating font-size on parent element');
|
||||
}, 'Effect values reflect changes to font-size on parent element');
|
||||
|
||||
promise_test(function(t) {
|
||||
var parentDiv = createDiv(t);
|
||||
var div = createDiv(t);
|
||||
parentDiv.appendChild(div);
|
||||
parentDiv.style.fontSize = '10px';
|
||||
var animation = div.animate([ { marginLeft: '10em' },
|
||||
{ marginLeft: '20em' } ], 1000);
|
||||
|
||||
animation.pause();
|
||||
animation.currentTime = 500;
|
||||
parentDiv.style.fontSize = '20px';
|
||||
|
||||
return animation.ready.then(function() {
|
||||
assert_equals(getComputedStyle(div).marginLeft, '300px',
|
||||
'Effect value after updating font-size on parent element');
|
||||
});
|
||||
}, 'Effect values reflect changes to font-size when computed style is not'
|
||||
+ ' immediately flushed');
|
||||
|
||||
promise_test(function(t) {
|
||||
var divWith10pxFontSize = createDiv(t);
|
||||
divWith10pxFontSize.style.fontSize = '10px';
|
||||
var divWith20pxFontSize = createDiv(t);
|
||||
divWith20pxFontSize.style.fontSize = '20px';
|
||||
|
||||
var div = createDiv(t);
|
||||
div.remove(); // Detach
|
||||
var animation = div.animate([ { marginLeft: '10em' },
|
||||
{ marginLeft: '20em' } ], 1000);
|
||||
animation.pause();
|
||||
|
||||
return animation.ready.then(function() {
|
||||
animation.currentTime = 500;
|
||||
|
||||
divWith10pxFontSize.appendChild(div);
|
||||
assert_equals(getComputedStyle(div).marginLeft, '150px',
|
||||
'Effect value after attaching to font-size:10px parent');
|
||||
divWith20pxFontSize.appendChild(div);
|
||||
assert_equals(getComputedStyle(div).marginLeft, '300px',
|
||||
'Effect value after attaching to font-size:20px parent');
|
||||
});
|
||||
}, 'Effect values reflect changes to font-size from reparenting');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,371 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animation.finished</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-finished">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var previousFinishedPromise = animation.finished;
|
||||
return animation.ready.then(function() {
|
||||
assert_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise is the same object when playing starts');
|
||||
animation.pause();
|
||||
assert_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise does not change when pausing');
|
||||
animation.play();
|
||||
assert_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise does not change when play() unpauses');
|
||||
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
|
||||
return animation.finished;
|
||||
}).then(function() {
|
||||
assert_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise is the same object when playing completes');
|
||||
});
|
||||
}, 'Test pausing then playing does not change the finished promise');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var previousFinishedPromise = animation.finished;
|
||||
animation.finish();
|
||||
return animation.finished.then(function() {
|
||||
assert_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise is the same object when playing completes');
|
||||
animation.play();
|
||||
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise changes when replaying animation');
|
||||
|
||||
previousFinishedPromise = animation.finished;
|
||||
animation.play();
|
||||
assert_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise is the same after redundant play() call');
|
||||
|
||||
});
|
||||
}, 'Test restarting a finished animation');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var previousFinishedPromise;
|
||||
animation.finish();
|
||||
return animation.finished.then(function() {
|
||||
previousFinishedPromise = animation.finished;
|
||||
animation.playbackRate = -1;
|
||||
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise should be replaced when reversing a ' +
|
||||
'finished promise');
|
||||
animation.currentTime = 0;
|
||||
return animation.finished;
|
||||
}).then(function() {
|
||||
previousFinishedPromise = animation.finished;
|
||||
animation.play();
|
||||
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise is replaced after play() call on ' +
|
||||
'finished, reversed animation');
|
||||
});
|
||||
}, 'Test restarting a reversed finished animation');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var previousFinishedPromise = animation.finished;
|
||||
animation.finish();
|
||||
return animation.finished.then(function() {
|
||||
animation.currentTime = 100 * MS_PER_SEC + 1000;
|
||||
assert_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise is unchanged jumping past end of ' +
|
||||
'finished animation');
|
||||
});
|
||||
}, 'Test redundant finishing of animation');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
// Setup callback to run if finished promise is resolved
|
||||
var finishPromiseResolved = false;
|
||||
animation.finished.then(function() {
|
||||
finishPromiseResolved = true;
|
||||
});
|
||||
return animation.ready.then(function() {
|
||||
// Jump to mid-way in interval and pause
|
||||
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||
animation.pause();
|
||||
return animation.ready;
|
||||
}).then(function() {
|
||||
// Jump to the end
|
||||
// (But don't use finish() since that should unpause as well)
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
return waitForAnimationFrames(2);
|
||||
}).then(function() {
|
||||
assert_false(finishPromiseResolved,
|
||||
'Finished promise should not resolve when paused');
|
||||
});
|
||||
}, 'Finished promise does not resolve when paused');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
// Setup callback to run if finished promise is resolved
|
||||
var finishPromiseResolved = false;
|
||||
animation.finished.then(function() {
|
||||
finishPromiseResolved = true;
|
||||
});
|
||||
return animation.ready.then(function() {
|
||||
// Jump to mid-way in interval and pause
|
||||
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||
animation.pause();
|
||||
// Jump to the end
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
return waitForAnimationFrames(2);
|
||||
}).then(function() {
|
||||
assert_false(finishPromiseResolved,
|
||||
'Finished promise should not resolve when pause-pending');
|
||||
});
|
||||
}, 'Finished promise does not resolve when pause-pending');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
animation.finish();
|
||||
return animation.finished.then(function(resolvedAnimation) {
|
||||
assert_equals(resolvedAnimation, animation,
|
||||
'Object identity of animation passed to Promise callback'
|
||||
+ ' matches the animation object owning the Promise');
|
||||
});
|
||||
}, 'The finished promise is fulfilled with its Animation');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var previousFinishedPromise = animation.finished;
|
||||
|
||||
// Set up listeners on finished promise
|
||||
var retPromise = animation.finished.then(function() {
|
||||
assert_unreached('finished promise was fulfilled');
|
||||
}).catch(function(err) {
|
||||
assert_equals(err.name, 'AbortError',
|
||||
'finished promise is rejected with AbortError');
|
||||
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise should change after the original is ' +
|
||||
'rejected');
|
||||
});
|
||||
|
||||
animation.cancel();
|
||||
|
||||
return retPromise;
|
||||
}, 'finished promise is rejected when an animation is cancelled by calling ' +
|
||||
'cancel()');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var previousFinishedPromise = animation.finished;
|
||||
animation.finish();
|
||||
return animation.finished.then(function() {
|
||||
animation.cancel();
|
||||
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||
'A new finished promise should be created when'
|
||||
+ ' cancelling a finished animation');
|
||||
});
|
||||
}, 'cancelling an already-finished animation replaces the finished promise');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
animation.cancel();
|
||||
// The spec says we still create a new finished promise and reject the old
|
||||
// one even if we're already idle. That behavior might change, but for now
|
||||
// test that we do that.
|
||||
var retPromise = animation.finished.catch(function(err) {
|
||||
assert_equals(err.name, 'AbortError',
|
||||
'finished promise is rejected with AbortError');
|
||||
});
|
||||
|
||||
// Redundant call to cancel();
|
||||
var previousFinishedPromise = animation.finished;
|
||||
animation.cancel();
|
||||
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||
'A redundant call to cancel() should still generate a new'
|
||||
+ ' finished promise');
|
||||
return retPromise;
|
||||
}, 'cancelling an idle animation still replaces the finished promise');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
const HALF_DUR = 100 * MS_PER_SEC / 2;
|
||||
const QUARTER_DUR = 100 * MS_PER_SEC / 4;
|
||||
var gotNextFrame = false;
|
||||
var currentTimeBeforeShortening;
|
||||
animation.currentTime = HALF_DUR;
|
||||
return animation.ready.then(function() {
|
||||
currentTimeBeforeShortening = animation.currentTime;
|
||||
animation.effect.timing.duration = QUARTER_DUR;
|
||||
// Below we use gotNextFrame to check that shortening of the animation
|
||||
// duration causes the finished promise to resolve, rather than it just
|
||||
// getting resolved on the next animation frame. This relies on the fact
|
||||
// that the promises are resolved as a micro-task before the next frame
|
||||
// happens.
|
||||
waitForAnimationFrames(1).then(function() {
|
||||
gotNextFrame = true;
|
||||
});
|
||||
|
||||
return animation.finished;
|
||||
}).then(function() {
|
||||
assert_false(gotNextFrame, 'shortening of the animation duration should ' +
|
||||
'resolve the finished promise');
|
||||
assert_equals(animation.currentTime, currentTimeBeforeShortening,
|
||||
'currentTime should be unchanged when duration shortened');
|
||||
var previousFinishedPromise = animation.finished;
|
||||
animation.effect.timing.duration = 100 * MS_PER_SEC;
|
||||
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise should change after lengthening the ' +
|
||||
'duration causes the animation to become active');
|
||||
});
|
||||
}, 'Test finished promise changes for animation duration changes');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var retPromise = animation.ready.then(function() {
|
||||
animation.playbackRate = 0;
|
||||
animation.currentTime = 100 * MS_PER_SEC + 1000;
|
||||
return waitForAnimationFrames(2);
|
||||
});
|
||||
|
||||
animation.finished.then(t.step_func(function() {
|
||||
assert_unreached('finished promise should not resolve when playbackRate ' +
|
||||
'is zero');
|
||||
}));
|
||||
|
||||
return retPromise;
|
||||
}, 'Test finished promise changes when playbackRate == 0');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
return animation.ready.then(function() {
|
||||
animation.playbackRate = -1;
|
||||
return animation.finished;
|
||||
});
|
||||
}, 'Test finished promise resolves when reaching to the natural boundary.');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var previousFinishedPromise = animation.finished;
|
||||
animation.finish();
|
||||
return animation.finished.then(function() {
|
||||
animation.currentTime = 0;
|
||||
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise should change once a prior ' +
|
||||
'finished promise resolved and the animation ' +
|
||||
'falls out finished state');
|
||||
});
|
||||
}, 'Test finished promise changes when a prior finished promise resolved ' +
|
||||
'and the animation falls out finished state');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var previousFinishedPromise = animation.finished;
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||
assert_equals(animation.finished, previousFinishedPromise,
|
||||
'No new finished promise generated when finished state ' +
|
||||
'is checked asynchronously');
|
||||
}, 'Test no new finished promise generated when finished state ' +
|
||||
'is checked asynchronously');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var previousFinishedPromise = animation.finished;
|
||||
animation.finish();
|
||||
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||
'New finished promise generated when finished state ' +
|
||||
'is checked synchronously');
|
||||
}, 'Test new finished promise generated when finished state ' +
|
||||
'is checked synchronously');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var resolvedFinished = false;
|
||||
animation.finished.then(function() {
|
||||
resolvedFinished = true;
|
||||
});
|
||||
return animation.ready.then(function() {
|
||||
animation.finish();
|
||||
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||
}).then(function() {
|
||||
assert_true(resolvedFinished,
|
||||
'Animation.finished should be resolved even if ' +
|
||||
'the finished state is changed soon');
|
||||
});
|
||||
|
||||
}, 'Test synchronous finished promise resolved even if finished state ' +
|
||||
'is changed soon');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var resolvedFinished = false;
|
||||
animation.finished.then(function() {
|
||||
resolvedFinished = true;
|
||||
});
|
||||
|
||||
return animation.ready.then(function() {
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
animation.finish();
|
||||
}).then(function() {
|
||||
assert_true(resolvedFinished,
|
||||
'Animation.finished should be resolved soon after finish() is ' +
|
||||
'called even if there are other asynchronous promises just before it');
|
||||
});
|
||||
}, 'Test synchronous finished promise resolved even if asynchronous ' +
|
||||
'finished promise happens just before synchronous promise');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
animation.finished.then(t.step_func(function() {
|
||||
assert_unreached('Animation.finished should not be resolved');
|
||||
}));
|
||||
|
||||
return animation.ready.then(function() {
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||
});
|
||||
}, 'Test finished promise is not resolved when the animation ' +
|
||||
'falls out finished state immediately');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
return animation.ready.then(function() {
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
animation.finished.then(t.step_func(function() {
|
||||
assert_unreached('Animation.finished should not be resolved');
|
||||
}));
|
||||
animation.currentTime = 0;
|
||||
});
|
||||
|
||||
}, 'Test finished promise is not resolved once the animation ' +
|
||||
'falls out finished state even though the current finished ' +
|
||||
'promise is generated soon after animation state became finished');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animation.id</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-id">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
assert_equals(animation.id, '', 'id for CSS Animation is initially empty');
|
||||
animation.id = 'anim'
|
||||
|
||||
assert_equals(animation.id, 'anim', 'animation.id reflects the value set');
|
||||
}, 'Animation.id for CSS Animations');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animation.oncancel</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-oncancel">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
async_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var finishedTimelineTime;
|
||||
animation.finished.then().catch(function() {
|
||||
finishedTimelineTime = animation.timeline.currentTime;
|
||||
});
|
||||
|
||||
animation.oncancel = t.step_func_done(function(event) {
|
||||
assert_equals(event.currentTime, null,
|
||||
'event.currentTime should be null');
|
||||
assert_equals(event.timelineTime, finishedTimelineTime,
|
||||
'event.timelineTime should equal to the animation timeline ' +
|
||||
'when finished promise is rejected');
|
||||
});
|
||||
|
||||
animation.cancel();
|
||||
}, 'oncancel event is fired when animation.cancel() is called.');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,122 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animation.onfinish</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-onfinish">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
async_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var finishedTimelineTime;
|
||||
animation.finished.then(function() {
|
||||
finishedTimelineTime = animation.timeline.currentTime;
|
||||
});
|
||||
|
||||
animation.onfinish = t.step_func_done(function(event) {
|
||||
assert_equals(event.currentTime, 0,
|
||||
'event.currentTime should be zero');
|
||||
assert_equals(event.timelineTime, finishedTimelineTime,
|
||||
'event.timelineTime should equal to the animation timeline ' +
|
||||
'when finished promise is resolved');
|
||||
});
|
||||
|
||||
animation.playbackRate = -1;
|
||||
}, 'onfinish event is fired when the currentTime < 0 and ' +
|
||||
'the playbackRate < 0');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
|
||||
var finishedTimelineTime;
|
||||
animation.finished.then(function() {
|
||||
finishedTimelineTime = animation.timeline.currentTime;
|
||||
});
|
||||
|
||||
animation.onfinish = t.step_func_done(function(event) {
|
||||
assert_equals(event.currentTime, 100 * MS_PER_SEC,
|
||||
'event.currentTime should be the effect end');
|
||||
assert_equals(event.timelineTime, finishedTimelineTime,
|
||||
'event.timelineTime should equal to the animation timeline ' +
|
||||
'when finished promise is resolved');
|
||||
});
|
||||
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
}, 'onfinish event is fired when the currentTime > 0 and ' +
|
||||
'the playbackRate > 0');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
|
||||
var finishedTimelineTime;
|
||||
animation.finished.then(function() {
|
||||
finishedTimelineTime = animation.timeline.currentTime;
|
||||
});
|
||||
|
||||
animation.onfinish = t.step_func_done(function(event) {
|
||||
assert_equals(event.currentTime, 100 * MS_PER_SEC,
|
||||
'event.currentTime should be the effect end');
|
||||
assert_equals(event.timelineTime, finishedTimelineTime,
|
||||
'event.timelineTime should equal to the animation timeline ' +
|
||||
'when finished promise is resolved');
|
||||
});
|
||||
|
||||
animation.finish();
|
||||
}, 'onfinish event is fired when animation.finish() is called');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
|
||||
animation.onfinish = function(event) {
|
||||
assert_unreached('onfinish event should not be fired');
|
||||
};
|
||||
|
||||
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||
animation.pause();
|
||||
|
||||
return animation.ready.then(function() {
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
return waitForAnimationFrames(2);
|
||||
});
|
||||
}, 'onfinish event is not fired when paused');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
animation.onfinish = function(event) {
|
||||
assert_unreached('onfinish event should not be fired');
|
||||
};
|
||||
|
||||
return animation.ready.then(function() {
|
||||
animation.playbackRate = 0;
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
return waitForAnimationFrames(2);
|
||||
});
|
||||
}, 'onfinish event is not fired when the playbackRate is zero');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
animation.onfinish = function(event) {
|
||||
assert_unreached('onfinish event should not be fired');
|
||||
};
|
||||
|
||||
return animation.ready.then(function() {
|
||||
animation.currentTime = 100 * MS_PER_SEC;
|
||||
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||
return waitForAnimationFrames(2);
|
||||
});
|
||||
}, 'onfinish event is not fired when the animation falls out ' +
|
||||
'finished state immediately');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,99 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animation.pause()</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-pause">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 1000 * MS_PER_SEC);
|
||||
var previousCurrentTime = animation.currentTime;
|
||||
|
||||
return animation.ready.then(waitForAnimationFrames(1)).then(function() {
|
||||
assert_true(animation.currentTime >= previousCurrentTime,
|
||||
'currentTime is initially increasing');
|
||||
animation.pause();
|
||||
return animation.ready;
|
||||
}).then(function() {
|
||||
previousCurrentTime = animation.currentTime;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_equals(animation.currentTime, previousCurrentTime,
|
||||
'currentTime does not increase after calling pause()');
|
||||
});
|
||||
}, 'pause() a running animation');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 1000 * MS_PER_SEC);
|
||||
|
||||
// Go to idle state then pause
|
||||
animation.cancel();
|
||||
animation.pause();
|
||||
|
||||
assert_equals(animation.currentTime, 0, 'currentTime is set to 0');
|
||||
assert_equals(animation.startTime, null, 'startTime is not set');
|
||||
assert_equals(animation.playState, 'pending', 'initially pause-pending');
|
||||
|
||||
// Check it still resolves as expected
|
||||
return animation.ready.then(function() {
|
||||
assert_equals(animation.playState, 'paused',
|
||||
'resolves to paused state asynchronously');
|
||||
assert_equals(animation.currentTime, 0,
|
||||
'keeps the initially set currentTime');
|
||||
});
|
||||
}, 'pause() from idle');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 1000 * MS_PER_SEC);
|
||||
animation.cancel();
|
||||
animation.playbackRate = -1;
|
||||
animation.pause();
|
||||
|
||||
assert_equals(animation.currentTime, 1000 * MS_PER_SEC,
|
||||
'currentTime is set to the effect end');
|
||||
|
||||
return animation.ready.then(function() {
|
||||
assert_equals(animation.currentTime, 1000 * MS_PER_SEC,
|
||||
'keeps the initially set currentTime');
|
||||
});
|
||||
}, 'pause() from idle with a negative playbackRate');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, {duration: 1000 * MS_PER_SEC,
|
||||
iterations: Infinity});
|
||||
animation.cancel();
|
||||
animation.playbackRate = -1;
|
||||
|
||||
assert_throws('InvalidStateError',
|
||||
function () { animation.pause(); },
|
||||
'Expect InvalidStateError exception on calling pause() ' +
|
||||
'from idle with a negative playbackRate and ' +
|
||||
'infinite-duration animation');
|
||||
}, 'pause() from idle with a negative playbackRate and endless effect');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 1000 * MS_PER_SEC);
|
||||
return animation.ready
|
||||
.then(function(animation) {
|
||||
animation.finish();
|
||||
animation.pause();
|
||||
return animation.ready;
|
||||
}).then(function(animation) {
|
||||
assert_equals(animation.currentTime, 1000 * MS_PER_SEC,
|
||||
'currentTime after pausing finished animation');
|
||||
});
|
||||
}, 'pause() on a finished animation');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,97 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animation.ready</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-ready">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
var originalReadyPromise = animation.ready;
|
||||
var pauseReadyPromise;
|
||||
|
||||
return animation.ready.then(function() {
|
||||
assert_equals(animation.ready, originalReadyPromise,
|
||||
'Ready promise is the same object when playing completes');
|
||||
animation.pause();
|
||||
assert_not_equals(animation.ready, originalReadyPromise,
|
||||
'A new ready promise is created when pausing');
|
||||
pauseReadyPromise = animation.ready;
|
||||
// Wait for the promise to fulfill since if we abort the pause the ready
|
||||
// promise object is reused.
|
||||
return animation.ready;
|
||||
}).then(function() {
|
||||
animation.play();
|
||||
assert_not_equals(animation.ready, pauseReadyPromise,
|
||||
'A new ready promise is created when playing');
|
||||
});
|
||||
}, 'A new ready promise is created when play()/pause() is called');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
|
||||
return animation.ready.then(function() {
|
||||
var promiseBeforeCallingPlay = animation.ready;
|
||||
animation.play();
|
||||
assert_equals(animation.ready, promiseBeforeCallingPlay,
|
||||
'Ready promise has same object identity after redundant call'
|
||||
+ ' to play()');
|
||||
});
|
||||
}, 'Redundant calls to play() do not generate new ready promise objects');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
|
||||
return animation.ready.then(function(resolvedAnimation) {
|
||||
assert_equals(resolvedAnimation, animation,
|
||||
'Object identity of Animation passed to Promise callback'
|
||||
+ ' matches the Animation object owning the Promise');
|
||||
});
|
||||
}, 'The ready promise is fulfilled with its Animation');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
|
||||
var retPromise = animation.ready.then(function() {
|
||||
assert_unreached('ready promise was fulfilled');
|
||||
}).catch(function(err) {
|
||||
assert_equals(err.name, 'AbortError',
|
||||
'ready promise is rejected with AbortError');
|
||||
});
|
||||
|
||||
animation.cancel();
|
||||
|
||||
return retPromise;
|
||||
}, 'ready promise is rejected when a pause-pending animation is cancelled by'
|
||||
+ ' calling cancel()');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
return animation.ready.then(function() {
|
||||
animation.pause();
|
||||
// Set up listeners on pause-pending ready promise
|
||||
var retPromise = animation.ready.then(function() {
|
||||
assert_unreached('ready promise was fulfilled');
|
||||
}).catch(function(err) {
|
||||
assert_equals(err.name, 'AbortError',
|
||||
'ready promise is rejected with AbortError');
|
||||
});
|
||||
animation.cancel();
|
||||
return retPromise;
|
||||
});
|
||||
}, 'ready promise is rejected when a pause-pending animation is cancelled by'
|
||||
+ ' calling cancel()');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,150 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animation.reverse()</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-reverse">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
|
||||
iterations: Infinity});
|
||||
|
||||
// Wait a frame because if currentTime is still 0 when we call
|
||||
// reverse(), it will throw (per spec).
|
||||
return animation.ready.then(waitForAnimationFrames(1)).then(function() {
|
||||
assert_greater_than_equal(animation.currentTime, 0,
|
||||
'currentTime expected to be greater than 0, one frame after starting');
|
||||
animation.currentTime = 50 * MS_PER_SEC;
|
||||
var previousPlaybackRate = animation.playbackRate;
|
||||
animation.reverse();
|
||||
assert_equals(animation.playbackRate, -previousPlaybackRate,
|
||||
'playbackRate should be inverted');
|
||||
});
|
||||
}, 'reverse() inverts playbackRate');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
|
||||
iterations: Infinity});
|
||||
animation.currentTime = 50 * MS_PER_SEC;
|
||||
animation.pause();
|
||||
|
||||
return animation.ready.then(function() {
|
||||
animation.reverse();
|
||||
return animation.ready;
|
||||
}).then(function() {
|
||||
assert_equals(animation.playState, 'running',
|
||||
'Animation.playState should be "running" after reverse()');
|
||||
});
|
||||
}, 'reverse() starts to play when pausing animation');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
animation.currentTime = 50 * MS_PER_SEC;
|
||||
animation.reverse();
|
||||
|
||||
assert_equals(animation.currentTime, 50 * MS_PER_SEC,
|
||||
'reverse() should not change the currentTime ' +
|
||||
'if the currentTime is in the middle of animation duration');
|
||||
}, 'reverse() maintains the same currentTime');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
animation.currentTime = 200 * MS_PER_SEC;
|
||||
animation.reverse();
|
||||
|
||||
assert_equals(animation.currentTime, 100 * MS_PER_SEC,
|
||||
'reverse() should start playing from the animation effect end ' +
|
||||
'if the playbackRate > 0 and the currentTime > effect end');
|
||||
}, 'reverse() when playbackRate > 0 and currentTime > effect end');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
|
||||
animation.currentTime = -200 * MS_PER_SEC;
|
||||
animation.reverse();
|
||||
|
||||
assert_equals(animation.currentTime, 100 * MS_PER_SEC,
|
||||
'reverse() should start playing from the animation effect end ' +
|
||||
'if the playbackRate > 0 and the currentTime < 0');
|
||||
}, 'reverse() when playbackRate > 0 and currentTime < 0');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
animation.playbackRate = -1;
|
||||
animation.currentTime = -200 * MS_PER_SEC;
|
||||
animation.reverse();
|
||||
|
||||
assert_equals(animation.currentTime, 0,
|
||||
'reverse() should start playing from the start of animation time ' +
|
||||
'if the playbackRate < 0 and the currentTime < 0');
|
||||
}, 'reverse() when playbackRate < 0 and currentTime < 0');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
animation.playbackRate = -1;
|
||||
animation.currentTime = 200 * MS_PER_SEC;
|
||||
animation.reverse();
|
||||
|
||||
assert_equals(animation.currentTime, 0,
|
||||
'reverse() should start playing from the start of animation time ' +
|
||||
'if the playbackRate < 0 and the currentTime > effect end');
|
||||
}, 'reverse() when playbackRate < 0 and currentTime > effect end');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
|
||||
iterations: Infinity});
|
||||
animation.currentTime = -200 * MS_PER_SEC;
|
||||
|
||||
assert_throws('InvalidStateError',
|
||||
function () { animation.reverse(); },
|
||||
'reverse() should throw InvalidStateError ' +
|
||||
'if the playbackRate > 0 and the currentTime < 0 ' +
|
||||
'and the target effect is positive infinity');
|
||||
}, 'reverse() when playbackRate > 0 and currentTime < 0 ' +
|
||||
'and the target effect end is positive infinity');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
|
||||
iterations: Infinity});
|
||||
animation.playbackRate = -1;
|
||||
animation.currentTime = -200 * MS_PER_SEC;
|
||||
animation.reverse();
|
||||
|
||||
assert_equals(animation.currentTime, 0,
|
||||
'reverse() should start playing from the start of animation time ' +
|
||||
'if the playbackRate < 0 and the currentTime < 0 ' +
|
||||
'and the target effect is positive infinity');
|
||||
}, 'reverse() when playbackRate < 0 and currentTime < 0 ' +
|
||||
'and the target effect end is positive infinity');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
animation.playbackRate = 0;
|
||||
animation.currentTime = 50 * MS_PER_SEC;
|
||||
animation.reverse();
|
||||
|
||||
assert_equals(animation.playbackRate, 0,
|
||||
'reverse() should preserve playbackRate if the playbackRate == 0');
|
||||
assert_equals(animation.currentTime, 50 * MS_PER_SEC,
|
||||
'reverse() should not affect the currentTime if the playbackRate == 0');
|
||||
t.done();
|
||||
}, 'reverse() when playbackRate == 0');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -37,17 +37,6 @@ function assert_frame_lists_equal(a, b) {
|
|||
|
||||
var gEmptyKeyframeListTests = [
|
||||
[],
|
||||
[{}],
|
||||
[{ easing: "ease-in" }],
|
||||
[{ unknown: "unknown" }, { unknown: "unknown" }],
|
||||
[{ color: "invalid" }, { color: "invalid" }],
|
||||
{ easing: "ease-in" },
|
||||
{ unknown: "unknown" },
|
||||
{ unknown: [] },
|
||||
{ unknown: ["unknown"] },
|
||||
{ unknown: ["unknown", "unknown"] },
|
||||
{ animationName: ["none", "abc"] },
|
||||
{ color: [] },
|
||||
null,
|
||||
undefined,
|
||||
];
|
||||
|
@ -79,7 +68,7 @@ test(function(t) {
|
|||
"resulting easing for '" + easing + "'");
|
||||
});
|
||||
}, "easing values are parsed correctly when passed to the " +
|
||||
"KeyframeEffectReadOnly constructor in PropertyIndexedKeyframes");
|
||||
"KeyframeEffectReadOnly constructor in a property-indexed keyframe");
|
||||
|
||||
test(function(t) {
|
||||
gEasingValueTests.forEach(function(subtest) {
|
||||
|
@ -93,7 +82,7 @@ test(function(t) {
|
|||
"resulting easing for '" + easing + "'");
|
||||
});
|
||||
}, "easing values are parsed correctly when passed to the " +
|
||||
"KeyframeEffectReadOnly constructor in Keyframe");
|
||||
"KeyframeEffectReadOnly constructor in regular keyframes");
|
||||
|
||||
test(function(t) {
|
||||
gEasingValueTests.forEach(function(subtest) {
|
||||
|
@ -135,7 +124,7 @@ test(function(t) {
|
|||
});
|
||||
});
|
||||
}, "composite values are parsed correctly when passed to the " +
|
||||
"KeyframeEffectReadOnly constructor in PropertyIndexedKeyframes");
|
||||
"KeyframeEffectReadOnly constructor in property-indexed keyframes");
|
||||
|
||||
test(function(t) {
|
||||
var getFrames = function(composite) {
|
||||
|
@ -155,7 +144,7 @@ test(function(t) {
|
|||
});
|
||||
});
|
||||
}, "composite values are parsed correctly when passed to the " +
|
||||
"KeyframeEffectReadOnly constructor in Keyframe");
|
||||
"KeyframeEffectReadOnly constructor in regular keyframes");
|
||||
|
||||
test(function(t) {
|
||||
gGoodOptionsCompositeValueTests.forEach(function(composite) {
|
||||
|
@ -176,79 +165,119 @@ test(function(t) {
|
|||
"KeyframeEffectReadOnly constructor in KeyframeTimingOptions");
|
||||
|
||||
var gPropertyIndexedKeyframesTests = [
|
||||
{ desc: "a one property two value PropertyIndexedKeyframes specification",
|
||||
{ desc: "a one property two value property-indexed keyframes specification",
|
||||
input: { left: ["10px", "20px"] },
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px" }] },
|
||||
{ desc: "a one shorthand property two value PropertyIndexedKeyframes specification",
|
||||
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||
left: "10px" },
|
||||
{ offset: null, computedOffset: 1, easing: "linear",
|
||||
left: "20px" }] },
|
||||
{ desc: "a one shorthand property two value property-indexed keyframes"
|
||||
+ " specification",
|
||||
input: { margin: ["10px", "10px 20px 30px 40px"] },
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", marginTop: "10px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
|
||||
{ desc: "a two property (one shorthand and one of its longhand components) two value PropertyIndexedKeyframes specification",
|
||||
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||
margin: "10px" },
|
||||
{ offset: null, computedOffset: 1, easing: "linear",
|
||||
margin: "10px 20px 30px 40px" }] },
|
||||
{ desc: "a two property (one shorthand and one of its longhand components)"
|
||||
+ " two value property-indexed keyframes specification",
|
||||
input: { marginTop: ["50px", "60px"],
|
||||
margin: ["10px", "10px 20px 30px 40px"] },
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "50px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", marginTop: "60px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
|
||||
{ desc: "a two property two value PropertyIndexedKeyframes specification",
|
||||
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||
marginTop: "50px", margin: "10px" },
|
||||
{ offset: null, computedOffset: 1, easing: "linear",
|
||||
marginTop: "60px", margin: "10px 20px 30px 40px" }] },
|
||||
{ desc: "a two property two value property-indexed keyframes specification",
|
||||
input: { left: ["10px", "20px"],
|
||||
top: ["30px", "40px"] },
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "30px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "40px" }] },
|
||||
{ desc: "a two property PropertyIndexedKeyframes specification with different numbers of values",
|
||||
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||
left: "10px", top: "30px" },
|
||||
{ offset: null, computedOffset: 1, easing: "linear",
|
||||
left: "20px", top: "40px" }] },
|
||||
{ desc: "a two property property-indexed keyframes specification with"
|
||||
+ " different numbers of values",
|
||||
input: { left: ["10px", "20px", "30px"],
|
||||
top: ["40px", "50px"] },
|
||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", left: "10px", top: "40px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear", left: "20px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear", left: "30px", top: "50px" }] },
|
||||
{ desc: "a PropertyIndexedKeyframes specification with an invalid value",
|
||||
output: [{ offset: null, computedOffset: 0.0, easing: "linear",
|
||||
left: "10px", top: "40px" },
|
||||
{ offset: null, computedOffset: 0.5, easing: "linear",
|
||||
left: "20px" },
|
||||
{ offset: null, computedOffset: 1.0, easing: "linear",
|
||||
left: "30px", top: "50px" }] },
|
||||
{ desc: "a property-indexed keyframes specification with an invalid value",
|
||||
input: { left: ["10px", "20px", "30px", "40px", "50px"],
|
||||
top: ["15px", "25px", "invalid", "45px", "55px"] },
|
||||
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px", top: "15px" },
|
||||
{ offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px", top: "25px" },
|
||||
{ offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" },
|
||||
{ offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px", top: "45px" },
|
||||
{ offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px", top: "55px" }] },
|
||||
{ desc: "a one property two value PropertyIndexedKeyframes specification that needs to stringify its values",
|
||||
output: [{ offset: null, computedOffset: 0.00, easing: "linear",
|
||||
left: "10px", top: "15px" },
|
||||
{ offset: null, computedOffset: 0.25, easing: "linear",
|
||||
left: "20px", top: "25px" },
|
||||
{ offset: null, computedOffset: 0.50, easing: "linear",
|
||||
left: "30px", top: "invalid" },
|
||||
{ offset: null, computedOffset: 0.75, easing: "linear",
|
||||
left: "40px", top: "45px" },
|
||||
{ offset: null, computedOffset: 1.00, easing: "linear",
|
||||
left: "50px", top: "55px" }] },
|
||||
{ desc: "a one property two value property-indexed keyframes specification"
|
||||
+ " that needs to stringify its values",
|
||||
input: { opacity: [0, 1] },
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", opacity: "0" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }] },
|
||||
{ desc: "a one property one value PropertyIndexedKeyframes specification",
|
||||
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||
opacity: "0" },
|
||||
{ offset: null, computedOffset: 1, easing: "linear",
|
||||
opacity: "1" }] },
|
||||
{ desc: "a one property one value property-indexed keyframes specification",
|
||||
input: { left: ["10px"] },
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] },
|
||||
{ desc: "a one property one non-array value PropertyIndexedKeyframes specification",
|
||||
output: [{ offset: null, computedOffset: 1, easing: "linear",
|
||||
left: "10px" }] },
|
||||
{ desc: "a one property one non-array value property-indexed keyframes"
|
||||
+ " specification",
|
||||
input: { left: "10px" },
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] },
|
||||
{ desc: "a one property two value PropertyIndexedKeyframes specification where the first value is invalid",
|
||||
output: [{ offset: null, computedOffset: 1, easing: "linear",
|
||||
left: "10px" }] },
|
||||
{ desc: "a one property two value property-indexed keyframes specification"
|
||||
+ " where the first value is invalid",
|
||||
input: { left: ["invalid", "10px"] },
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] },
|
||||
{ desc: "a one property two value PropertyIndexedKeyframes specification where the second value is invalid",
|
||||
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||
left: "invalid" },
|
||||
{ offset: null, computedOffset: 1, easing: "linear",
|
||||
left: "10px" }] },
|
||||
{ desc: "a one property two value property-indexed keyframes specification"
|
||||
+ " where the second value is invalid",
|
||||
input: { left: ["10px", "invalid"] },
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear" }] },
|
||||
{ desc: "a two property PropertyIndexedKeyframes specification where one property is missing from the first Keyframe",
|
||||
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||
left: "10px" },
|
||||
{ offset: null, computedOffset: 1, easing: "linear",
|
||||
left: "invalid" }] },
|
||||
{ desc: "a two property property-indexed keyframes specification where one"
|
||||
+ " property is missing from the first keyframe",
|
||||
input: [{ offset: 0, left: "10px" },
|
||||
{ offset: 1, left: "20px", top: "30px" }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "30px" }] },
|
||||
{ desc: "a two property PropertyIndexedKeyframes specification where one property is missing from the last Keyframe",
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
left: "20px", top: "30px" }] },
|
||||
{ desc: "a two property property-indexed keyframes specification where one"
|
||||
+ " property is missing from the last keyframe",
|
||||
input: [{ offset: 0, left: "10px", top: "20px" },
|
||||
{ offset: 1, left: "30px" }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" , top: "20px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "30px" }] },
|
||||
{ desc: "a PropertyIndexedKeyframes specification with repeated values at offset 0 with different easings",
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||
left: "10px" , top: "20px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
left: "30px" }] },
|
||||
{ desc: "a property-indexed keyframes specification with repeated values"
|
||||
+ " at offset 0 with different easings",
|
||||
input: [{ offset: 0.0, left: "100px", easing: "ease" },
|
||||
{ offset: 0.0, left: "200px", easing: "ease" },
|
||||
{ offset: 0.5, left: "300px", easing: "linear" },
|
||||
{ offset: 1.0, left: "400px", easing: "ease-out" },
|
||||
{ offset: 1.0, left: "500px", easing: "step-end" }],
|
||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease", left: "100px" },
|
||||
{ offset: 0.0, computedOffset: 0.0, easing: "ease", left: "200px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear", left: "300px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "ease-out", left: "400px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear", left: "500px" }] },
|
||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",
|
||||
left: "100px" },
|
||||
{ offset: 0.0, computedOffset: 0.0, easing: "ease",
|
||||
left: "200px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||
left: "300px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "ease-out",
|
||||
left: "400px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "step-end",
|
||||
left: "500px" }] },
|
||||
];
|
||||
|
||||
gPropertyIndexedKeyframesTests.forEach(function(subtest) {
|
||||
|
@ -282,41 +311,56 @@ test(function(t) {
|
|||
});
|
||||
new KeyframeEffectReadOnly(target, [kf1, kf2]);
|
||||
assert_array_equals(actualOrder, expectedOrder, "property access order");
|
||||
}, "the KeyframeEffectReadOnly constructor reads Keyframe properties in the " +
|
||||
}, "the KeyframeEffectReadOnly constructor reads keyframe properties in the " +
|
||||
"expected order");
|
||||
|
||||
var gKeyframeSequenceTests = [
|
||||
{ desc: "a one property two Keyframe sequence",
|
||||
{ desc: "a one property two keyframe sequence",
|
||||
input: [{ offset: 0, left: "10px" },
|
||||
{ offset: 1, left: "20px" }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px" }] },
|
||||
{ desc: "a two property two Keyframe sequence",
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px" }]
|
||||
},
|
||||
{ desc: "a two property two keyframe sequence",
|
||||
input: [{ offset: 0, left: "10px", top: "30px" },
|
||||
{ offset: 1, left: "20px", top: "40px" }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "30px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "40px" }] },
|
||||
{ desc: "a one shorthand property two Keyframe sequence",
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||
left: "10px", top: "30px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
left: "20px", top: "40px" }] },
|
||||
{ desc: "a one shorthand property two keyframe sequence",
|
||||
input: [{ offset: 0, margin: "10px" },
|
||||
{ offset: 1, margin: "20px 30px 40px 50px" }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", marginTop: "20px", marginRight: "30px", marginBottom: "40px", marginLeft: "50px" }] },
|
||||
{ desc: "a two property (a shorthand and one of its component longhands) two Keyframe sequence",
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||
margin: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
margin: "20px 30px 40px 50px" }] },
|
||||
{ desc: "a two property (a shorthand and one of its component longhands)"
|
||||
+ " two keyframe sequence",
|
||||
input: [{ offset: 0, margin: "10px", marginTop: "20px" },
|
||||
{ offset: 1, marginTop: "70px", margin: "30px 40px 50px 60px" }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "20px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", marginTop: "70px", marginRight: "40px", marginBottom: "50px", marginLeft: "60px" }] },
|
||||
{ desc: "a Keyframe sequence with duplicate values for a given interior offset",
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||
margin: "10px", marginTop: "20px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
marginTop: "70px", margin: "30px 40px 50px 60px" }] },
|
||||
{ desc: "a keyframe sequence with duplicate values for a given interior"
|
||||
+ " offset",
|
||||
input: [{ offset: 0.0, left: "10px" },
|
||||
{ offset: 0.5, left: "20px" },
|
||||
{ offset: 0.5, left: "30px" },
|
||||
{ offset: 0.5, left: "40px" },
|
||||
{ offset: 1.0, left: "50px" }],
|
||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", left: "10px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear", left: "20px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear", left: "40px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear", left: "50px" }] },
|
||||
{ desc: "a Keyframe sequence with duplicate values for offsets 0 and 1",
|
||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear",
|
||||
left: "10px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||
left: "20px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||
left: "30px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||
left: "40px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear",
|
||||
left: "50px" }] },
|
||||
{ desc: "a keyframe sequence with duplicate values for offsets 0 and 1",
|
||||
input: [{ offset: 0, left: "10px" },
|
||||
{ offset: 0, left: "20px" },
|
||||
{ offset: 0, left: "30px" },
|
||||
|
@ -324,50 +368,72 @@ var gKeyframeSequenceTests = [
|
|||
{ offset: 1, left: "50px" },
|
||||
{ offset: 1, left: "60px" }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
||||
{ offset: 0, computedOffset: 0, easing: "linear", left: "20px" },
|
||||
{ offset: 0, computedOffset: 0, easing: "linear", left: "30px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "40px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "60px" }] },
|
||||
{ desc: "a two property four Keyframe sequence",
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "50px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "60px" }]
|
||||
},
|
||||
{ desc: "a two property four keyframe sequence",
|
||||
input: [{ offset: 0, left: "10px" },
|
||||
{ offset: 0, top: "20px" },
|
||||
{ offset: 1, top: "30px" },
|
||||
{ offset: 1, left: "40px" }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "20px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "40px", top: "30px" }] },
|
||||
{ desc: "a one property Keyframe sequence with some omitted offsets",
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
||||
{ offset: 0, computedOffset: 0, easing: "linear", top: "20px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", top: "30px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "40px" }]
|
||||
},
|
||||
{ desc: "a one property keyframe sequence with some omitted offsets",
|
||||
input: [{ offset: 0.00, left: "10px" },
|
||||
{ offset: 0.25, left: "20px" },
|
||||
{ left: "30px" },
|
||||
{ left: "40px" },
|
||||
{ offset: 1.00, left: "50px" }],
|
||||
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px" },
|
||||
{ offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px" },
|
||||
{ offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" },
|
||||
{ offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px" },
|
||||
{ offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px" }] },
|
||||
{ desc: "a two property Keyframe sequence with some omitted offsets",
|
||||
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear",
|
||||
left: "10px" },
|
||||
{ offset: 0.25, computedOffset: 0.25, easing: "linear",
|
||||
left: "20px" },
|
||||
{ offset: null, computedOffset: 0.50, easing: "linear",
|
||||
left: "30px" },
|
||||
{ offset: null, computedOffset: 0.75, easing: "linear",
|
||||
left: "40px" },
|
||||
{ offset: 1.00, computedOffset: 1.00, easing: "linear",
|
||||
left: "50px" }] },
|
||||
{ desc: "a two property keyframe sequence with some omitted offsets",
|
||||
input: [{ offset: 0.00, left: "10px", top: "20px" },
|
||||
{ offset: 0.25, left: "30px" },
|
||||
{ left: "40px" },
|
||||
{ left: "50px", top: "60px" },
|
||||
{ offset: 1.00, left: "70px", top: "80px" }],
|
||||
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px", top: "20px" },
|
||||
{ offset: 0.25, computedOffset: 0.25, easing: "linear", left: "30px" },
|
||||
{ offset: 0.50, computedOffset: 0.50, easing: "linear", left: "40px" },
|
||||
{ offset: 0.75, computedOffset: 0.75, easing: "linear", left: "50px", top: "60px" },
|
||||
{ offset: 1.00, computedOffset: 1.00, easing: "linear", left: "70px", top: "80px" }] },
|
||||
{ desc: "a one property Keyframe sequence with all omitted offsets",
|
||||
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear",
|
||||
left: "10px", top: "20px" },
|
||||
{ offset: 0.25, computedOffset: 0.25, easing: "linear",
|
||||
left: "30px" },
|
||||
{ offset: null, computedOffset: 0.50, easing: "linear",
|
||||
left: "40px" },
|
||||
{ offset: null, computedOffset: 0.75, easing: "linear",
|
||||
left: "50px", top: "60px" },
|
||||
{ offset: 1.00, computedOffset: 1.00, easing: "linear",
|
||||
left: "70px", top: "80px" }] },
|
||||
{ desc: "a one property keyframe sequence with all omitted offsets",
|
||||
input: [{ left: "10px" },
|
||||
{ left: "20px" },
|
||||
{ left: "30px" },
|
||||
{ left: "40px" },
|
||||
{ left: "50px" }],
|
||||
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px" },
|
||||
{ offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px" },
|
||||
{ offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" },
|
||||
{ offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px" },
|
||||
{ offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px" }] },
|
||||
{ desc: "a Keyframe sequence with different easing values, but the same easing value for a given offset",
|
||||
output: [{ offset: null, computedOffset: 0.00, easing: "linear",
|
||||
left: "10px" },
|
||||
{ offset: null, computedOffset: 0.25, easing: "linear",
|
||||
left: "20px" },
|
||||
{ offset: null, computedOffset: 0.50, easing: "linear",
|
||||
left: "30px" },
|
||||
{ offset: null, computedOffset: 0.75, easing: "linear",
|
||||
left: "40px" },
|
||||
{ offset: null, computedOffset: 1.00, easing: "linear",
|
||||
left: "50px" }] },
|
||||
{ desc: "a keyframe sequence with different easing values, but the same"
|
||||
+ " easing value for a given offset",
|
||||
input: [{ offset: 0.0, easing: "ease", left: "10px"},
|
||||
{ offset: 0.0, easing: "ease", top: "20px"},
|
||||
{ offset: 0.5, easing: "linear", left: "30px" },
|
||||
|
@ -375,62 +441,79 @@ var gKeyframeSequenceTests = [
|
|||
{ offset: 1.0, easing: "step-end", left: "50px" },
|
||||
{ offset: 1.0, easing: "step-end", top: "60px" }],
|
||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",
|
||||
left: "10px", top: "20px" },
|
||||
left: "10px" },
|
||||
{ offset: 0.0, computedOffset: 0.0, easing: "ease",
|
||||
top: "20px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||
left: "30px", top: "40px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear",
|
||||
left: "50px", top: "60px" }] },
|
||||
{ desc: "a Keyframe sequence with different composite values, but the same composite value for a given offset",
|
||||
left: "30px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||
top: "40px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "step-end",
|
||||
left: "50px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "step-end",
|
||||
top: "60px" }] },
|
||||
{ desc: "a keyframe sequence with different composite values, but the"
|
||||
+ " same composite value for a given offset",
|
||||
input: [{ offset: 0.0, composite: "replace", left: "10px" },
|
||||
{ offset: 0.0, composite: "replace", top: "20px" },
|
||||
{ offset: 0.5, composite: "add", left: "30px" },
|
||||
{ offset: 0.5, composite: "add", top: "40px" },
|
||||
{ offset: 1.0, composite: "replace", left: "50px" },
|
||||
{ offset: 1.0, composite: "replace", top: "60px" }],
|
||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", composite: "replace", left: "10px", top: "20px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "add", left: "30px", top: "40px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "50px", top: "60px" }] },
|
||||
{ desc: "a one property two Keyframe sequence that needs to stringify its values",
|
||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear",
|
||||
composite: "replace", left: "10px" },
|
||||
{ offset: 0.0, computedOffset: 0.0, easing: "linear",
|
||||
composite: "replace", top: "20px" },
|
||||
{ offset: 0.5, computedOffset: 0.0, easing: "linear",
|
||||
composite: "add", left: "30px" },
|
||||
{ offset: 0.5, computedOffset: 0.0, easing: "linear",
|
||||
composite: "add", top: "40px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear",
|
||||
composite: "replace", left: "50px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear",
|
||||
composite: "replace", top: "60px" }] },
|
||||
{ desc: "a one property two keyframe sequence that needs to stringify"
|
||||
+ " its values",
|
||||
input: [{ offset: 0, opacity: 0 },
|
||||
{ offset: 1, opacity: 1 }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", opacity: "0" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }] },
|
||||
{ desc: "a Keyframe sequence where shorthand precedes longhand",
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }]
|
||||
},
|
||||
{ desc: "a keyframe sequence where shorthand precedes longhand",
|
||||
input: [{ offset: 0, margin: "10px", marginRight: "20px" },
|
||||
{ offset: 1, margin: "30px" }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
|
||||
{ desc: "a Keyframe sequence where longhand precedes shorthand",
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||
margin: "10px", marginRight: "20px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
margin: "30px" }] },
|
||||
{ desc: "a keyframe sequence where longhand precedes shorthand",
|
||||
input: [{ offset: 0, marginRight: "20px", margin: "10px" },
|
||||
{ offset: 1, margin: "30px" }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
|
||||
{ desc: "a Keyframe sequence where lesser shorthand precedes greater shorthand",
|
||||
input: [{ offset: 0, borderLeft: "1px solid rgb(1, 2, 3)", border: "2px dotted rgb(4, 5, 6)" },
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||
marginRight: "20px", margin: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
margin: "30px" }] },
|
||||
{ desc: "a keyframe sequence where lesser shorthand precedes greater"
|
||||
+ " shorthand",
|
||||
input: [{ offset: 0,
|
||||
borderLeft: "1px solid rgb(1, 2, 3)",
|
||||
border: "2px dotted rgb(4, 5, 6)" },
|
||||
{ offset: 1, border: "3px dashed rgb(7, 8, 9)" }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||
borderBottomColor: "rgb(4, 5, 6)", borderBottomWidth: "2px",
|
||||
borderLeftColor: "rgb(1, 2, 3)", borderLeftWidth: "1px",
|
||||
borderRightColor: "rgb(4, 5, 6)", borderRightWidth: "2px",
|
||||
borderTopColor: "rgb(4, 5, 6)", borderTopWidth: "2px" },
|
||||
borderLeft: "1px solid rgb(1, 2, 3)",
|
||||
border: "2px dotted rgb(4, 5, 6)" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
borderBottomColor: "rgb(7, 8, 9)", borderBottomWidth: "3px",
|
||||
borderLeftColor: "rgb(7, 8, 9)", borderLeftWidth: "3px",
|
||||
borderRightColor: "rgb(7, 8, 9)", borderRightWidth: "3px",
|
||||
borderTopColor: "rgb(7, 8, 9)", borderTopWidth: "3px" }] },
|
||||
{ desc: "a Keyframe sequence where greater shorthand precedes lesser shorthand",
|
||||
input: [{ offset: 0, border: "2px dotted rgb(4, 5, 6)", borderLeft: "1px solid rgb(1, 2, 3)" },
|
||||
border: "3px dashed rgb(7, 8, 9)" }] },
|
||||
{ desc: "a keyframe sequence where greater shorthand precedes lesser"
|
||||
+ " shorthand",
|
||||
input: [{ offset: 0, border: "2px dotted rgb(4, 5, 6)",
|
||||
borderLeft: "1px solid rgb(1, 2, 3)" },
|
||||
{ offset: 1, border: "3px dashed rgb(7, 8, 9)" }],
|
||||
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||
borderBottomColor: "rgb(4, 5, 6)", borderBottomWidth: "2px",
|
||||
borderLeftColor: "rgb(1, 2, 3)", borderLeftWidth: "1px",
|
||||
borderRightColor: "rgb(4, 5, 6)", borderRightWidth: "2px",
|
||||
borderTopColor: "rgb(4, 5, 6)", borderTopWidth: "2px" },
|
||||
border: "2px dotted rgb(4, 5, 6)",
|
||||
borderLeft: "1px solid rgb(1, 2, 3)" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
borderBottomColor: "rgb(7, 8, 9)", borderBottomWidth: "3px",
|
||||
borderLeftColor: "rgb(7, 8, 9)", borderLeftWidth: "3px",
|
||||
borderRightColor: "rgb(7, 8, 9)", borderRightWidth: "3px",
|
||||
borderTopColor: "rgb(7, 8, 9)", borderTopWidth: "3px" }] },
|
||||
border: "3px dashed rgb(7, 8, 9)" }] },
|
||||
];
|
||||
|
||||
gKeyframeSequenceTests.forEach(function(subtest) {
|
||||
|
@ -467,7 +550,7 @@ gInvalidEasingInKeyframeSequenceTests.forEach(function(subtest) {
|
|||
assert_throws(new TypeError, function() {
|
||||
new KeyframeEffectReadOnly(target, subtest.input);
|
||||
});
|
||||
}, "Invalid easing [" + subtest.desc + "] in KeyframeSequence " +
|
||||
}, "Invalid easing [" + subtest.desc + "] in keyframe sequence " +
|
||||
"should be thrown");
|
||||
});
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<script src="../resources/effect-easing-tests.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<div id="target"></div>
|
||||
|
@ -22,54 +23,6 @@ function assert_style_left_at(animation, time, easingFunction) {
|
|||
easingFunction(portion) * 100 + ' at ' + time + 'ms');
|
||||
}
|
||||
|
||||
var gEffectEasingTests = [
|
||||
{
|
||||
desc: 'steps(start) function',
|
||||
easing: 'steps(2, start)',
|
||||
easingFunction: stepStart(2)
|
||||
},
|
||||
{
|
||||
desc: 'steps(end) function',
|
||||
easing: 'steps(2, end)',
|
||||
easingFunction: stepEnd(2)
|
||||
},
|
||||
{
|
||||
desc: 'linear function',
|
||||
easing: 'linear', // cubic-bezier(0, 0, 1.0, 1.0)
|
||||
easingFunction: cubicBezier(0, 0, 1.0, 1.0)
|
||||
},
|
||||
{
|
||||
desc: 'ease function',
|
||||
easing: 'ease', // cubic-bezier(0.25, 0.1, 0.25, 1.0)
|
||||
easingFunction: cubicBezier(0.25, 0.1, 0.25, 1.0)
|
||||
},
|
||||
{
|
||||
desc: 'ease-in function',
|
||||
easing: 'ease-in', // cubic-bezier(0.42, 0, 1.0, 1.0)
|
||||
easingFunction: cubicBezier(0.42, 0, 1.0, 1.0)
|
||||
},
|
||||
{
|
||||
desc: 'ease-in-out function',
|
||||
easing: 'ease-in-out', // cubic-bezier(0.42, 0, 0.58, 1.0)
|
||||
easingFunction: cubicBezier(0.42, 0, 0.58, 1.0)
|
||||
},
|
||||
{
|
||||
desc: 'ease-out function',
|
||||
easing: 'ease-out', // cubic-bezier(0, 0, 0.58, 1.0)
|
||||
easingFunction: cubicBezier(0, 0, 0.58, 1.0)
|
||||
},
|
||||
{
|
||||
desc: 'easing function which produces values greater than 1',
|
||||
easing: 'cubic-bezier(0, 1.5, 1, 1.5)',
|
||||
easingFunction: cubicBezier(0, 1.5, 1, 1.5)
|
||||
},
|
||||
{
|
||||
desc: 'easing function which produces negative values',
|
||||
easing: 'cubic-bezier(0, -0.5 ,1, -0.5)',
|
||||
easingFunction: cubicBezier(0, -0.5, 1, -0.5)
|
||||
},
|
||||
];
|
||||
|
||||
gEffectEasingTests.forEach(function(options) {
|
||||
test(function(t) {
|
||||
var target = createDiv(t);
|
||||
|
@ -694,7 +647,7 @@ var gStepTimingFunctionTests = [
|
|||
{ currentTime: 2500, progress: 0.5 },
|
||||
]
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
gStepTimingFunctionTests.forEach(function(options) {
|
||||
test(function(t) {
|
||||
|
|
|
@ -70,6 +70,46 @@ test(function(t) {
|
|||
}, 'Overlapping keyframes between 0 and 1 use the appropriate value on each'
|
||||
+ ' side of the overlap point');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ visibility: ['hidden','visible'] },
|
||||
{ duration: 100 * MS_PER_SEC, fill: 'both' });
|
||||
|
||||
anim.currentTime = 0;
|
||||
assert_equals(getComputedStyle(div).visibility, 'hidden',
|
||||
'Visibility when progress = 0.');
|
||||
|
||||
anim.currentTime = 10 * MS_PER_SEC + 1;
|
||||
assert_equals(getComputedStyle(div).visibility, 'visible',
|
||||
'Visibility when progress > 0 due to linear easing.');
|
||||
|
||||
anim.finish();
|
||||
assert_equals(getComputedStyle(div).visibility, 'visible',
|
||||
'Visibility when progress = 1.');
|
||||
|
||||
}, "Test visibility clamping behavior.");
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ visibility: ['hidden', 'visible'] },
|
||||
{ duration: 100 * MS_PER_SEC, fill: 'both',
|
||||
easing: 'cubic-bezier(0.25, -0.6, 0, 0.5)' });
|
||||
|
||||
anim.currentTime = 0;
|
||||
assert_equals(getComputedStyle(div).visibility, 'hidden',
|
||||
'Visibility when progress = 0.');
|
||||
|
||||
// Timing function is below zero. So we expected visibility is hidden.
|
||||
anim.currentTime = 10 * MS_PER_SEC + 1;
|
||||
assert_equals(getComputedStyle(div).visibility, 'hidden',
|
||||
'Visibility when progress < 0 due to cubic-bezier easing.');
|
||||
|
||||
anim.currentTime = 60 * MS_PER_SEC;
|
||||
assert_equals(getComputedStyle(div).visibility, 'visible',
|
||||
'Visibility when progress > 0 due to cubic-bezier easing.');
|
||||
|
||||
}, "Test visibility clamping behavior with an easing that has a negative component");
|
||||
|
||||
done();
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
var gEffectEasingTests = [
|
||||
{
|
||||
desc: 'steps(start) function',
|
||||
easing: 'steps(2, start)',
|
||||
easingFunction: stepStart(2)
|
||||
},
|
||||
{
|
||||
desc: 'steps(end) function',
|
||||
easing: 'steps(2, end)',
|
||||
easingFunction: stepEnd(2)
|
||||
},
|
||||
{
|
||||
desc: 'linear function',
|
||||
easing: 'linear', // cubic-bezier(0, 0, 1.0, 1.0)
|
||||
easingFunction: cubicBezier(0, 0, 1.0, 1.0)
|
||||
},
|
||||
{
|
||||
desc: 'ease function',
|
||||
easing: 'ease', // cubic-bezier(0.25, 0.1, 0.25, 1.0)
|
||||
easingFunction: cubicBezier(0.25, 0.1, 0.25, 1.0)
|
||||
},
|
||||
{
|
||||
desc: 'ease-in function',
|
||||
easing: 'ease-in', // cubic-bezier(0.42, 0, 1.0, 1.0)
|
||||
easingFunction: cubicBezier(0.42, 0, 1.0, 1.0)
|
||||
},
|
||||
{
|
||||
desc: 'ease-in-out function',
|
||||
easing: 'ease-in-out', // cubic-bezier(0.42, 0, 0.58, 1.0)
|
||||
easingFunction: cubicBezier(0.42, 0, 0.58, 1.0)
|
||||
},
|
||||
{
|
||||
desc: 'ease-out function',
|
||||
easing: 'ease-out', // cubic-bezier(0, 0, 0.58, 1.0)
|
||||
easingFunction: cubicBezier(0, 0, 0.58, 1.0)
|
||||
},
|
||||
{
|
||||
desc: 'easing function which produces values greater than 1',
|
||||
easing: 'cubic-bezier(0, 1.5, 1, 1.5)',
|
||||
easingFunction: cubicBezier(0, 1.5, 1, 1.5)
|
||||
}
|
||||
];
|
Loading…
Add table
Add a link
Reference in a new issue