mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Update web-platform-tests to revision 697b971060b2d475a73c1c3755232a4674d61cf5
This commit is contained in:
parent
f60598909a
commit
b97474fbba
236 changed files with 4817 additions and 893 deletions
|
@ -1,62 +1,55 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animatable.animate tests</title>
|
||||
<link rel="help" href="http://w3c.github.io/web-animations/#dom-animatable-animate">
|
||||
<link rel="author" title="Brian Birtles" href="mailto:bbirtles@mozilla.com">
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animatable-animate">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<script src="../resources/keyframe-utils.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
// Tests on Element
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
var anim = div.animate(null);
|
||||
assert_class_string(anim, 'Animation', 'Returned object is an Animation');
|
||||
}, 'Element.animate() creates an Animation object');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
var anim = div.animate(null);
|
||||
assert_class_string(anim.effect, 'KeyframeEffect',
|
||||
'Returned Animation has a KeyframeEffect');
|
||||
}, 'Element.animate() creates an Animation object with a KeyframeEffect');
|
||||
|
||||
// Animatable.animate() passes its |frames| argument to the KeyframeEffect
|
||||
// constructor. As a result, detailed tests of the handling of that argument
|
||||
// are found in the tests for that constructor. Here we just check that the
|
||||
// different types of arguments are correctly passed along.
|
||||
gPropertyIndexedKeyframesTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate(subtest.input, 2000);
|
||||
assert_frame_lists_equal(anim.effect.getFrames(), subtest.output);
|
||||
}, 'Element.animate() accepts ' + subtest.desc);
|
||||
});
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_equals(anim.effect.getFrames().length, 2);
|
||||
assert_equals(anim.effect.getFrames()[0].opacity, '0');
|
||||
assert_equals(anim.effect.getFrames()[1].opacity, '1');
|
||||
}, 'Element.animate() accepts a property-indexed keyframe specification');
|
||||
gKeyframeSequenceTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate(subtest.input, 2000);
|
||||
assert_frame_lists_equal(anim.effect.getFrames(), subtest.output);
|
||||
}, 'Element.animate() accepts ' + subtest.desc);
|
||||
});
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate([ { opacity: 0 }, { opacity: 1 } ], 2000);
|
||||
assert_equals(anim.effect.getFrames().length, 2);
|
||||
assert_equals(anim.effect.getFrames()[0].opacity, '0');
|
||||
assert_equals(anim.effect.getFrames()[1].opacity, '1');
|
||||
}, 'Element.animate() accepts a frame-indexed keyframe specification');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: 0 }, 2000);
|
||||
assert_equals(anim.effect.getFrames().length, 1);
|
||||
assert_equals(anim.effect.getFrames()[0].opacity, '0');
|
||||
}, 'Element.animate() accepts a single-valued keyframe specification');
|
||||
|
||||
// As with the |frames| argument, Animatable.animate() passes its |options|
|
||||
// argument to the KeyframeEffect constructor as well. As a result, detailed
|
||||
// tests of the handling of that argument are found in the tests for that
|
||||
// constructor. Here we just check that the different types of arguments are
|
||||
// correctly passed along.
|
||||
gInvalidKeyframesTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
assert_throws(subtest.expected, function() {
|
||||
div.animate(subtest.input, 2000);
|
||||
});
|
||||
}, 'Element.animate() does not accept ' + subtest.desc);
|
||||
});
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
|
@ -127,13 +120,13 @@ test(function(t) {
|
|||
|
||||
test(function(t) {
|
||||
var pseudoTarget = createPseudo(t, 'before');
|
||||
var anim = pseudoTarget.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
var anim = pseudoTarget.animate(null);
|
||||
assert_class_string(anim, 'Animation', 'The returned object is an Animation');
|
||||
}, 'CSSPseudoElement.animate() creates an Animation object');
|
||||
|
||||
test(function(t) {
|
||||
var pseudoTarget = createPseudo(t, 'before');
|
||||
var anim = pseudoTarget.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
var anim = pseudoTarget.animate(null);
|
||||
assert_equals(anim.effect.target, pseudoTarget,
|
||||
'The returned Animation targets to the correct object');
|
||||
}, 'CSSPseudoElement.animate() creates an Animation object targeting ' +
|
||||
|
|
|
@ -15,11 +15,10 @@ test(function(t) {
|
|||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
anim.effect.timing.duration = 123.45;
|
||||
assert_approx_equals(anim.effect.timing.duration, 123.45, 0.000001,
|
||||
'set duration 123.45');
|
||||
assert_approx_equals(anim.effect.getComputedTiming().duration, 123.45,
|
||||
0.000001,
|
||||
'getComputedTiming() after set duration 123.45');
|
||||
assert_times_equal(anim.effect.timing.duration, 123.45,
|
||||
'set duration 123.45');
|
||||
assert_times_equal(anim.effect.getComputedTiming().duration, 123.45,
|
||||
'getComputedTiming() after set duration 123.45');
|
||||
}, 'set duration 123.45');
|
||||
|
||||
test(function(t) {
|
||||
|
|
|
@ -15,11 +15,10 @@ test(function(t) {
|
|||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
anim.effect.timing.endDelay = 123.45;
|
||||
assert_approx_equals(anim.effect.timing.endDelay, 123.45, 0.000001,
|
||||
'set endDelay 123.45');
|
||||
assert_approx_equals(anim.effect.getComputedTiming().endDelay, 123.45,
|
||||
0.000001,
|
||||
'getComputedTiming() after set endDelay 123.45');
|
||||
assert_times_equal(anim.effect.timing.endDelay, 123.45,
|
||||
'set endDelay 123.45');
|
||||
assert_times_equal(anim.effect.getComputedTiming().endDelay, 123.45,
|
||||
'getComputedTiming() after set endDelay 123.45');
|
||||
}, 'set endDelay 123.45');
|
||||
|
||||
test(function(t) {
|
||||
|
|
|
@ -55,5 +55,19 @@ gTestArguments.forEach(function(args) {
|
|||
}, "Animation can be constructed " + args.description);
|
||||
});
|
||||
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(null,
|
||||
{ left: ["10px", "20px"] },
|
||||
{ duration: 10000,
|
||||
fill: "forwards" });
|
||||
var anim = new Animation(effect, document.timeline);
|
||||
anim.pause();
|
||||
assert_equals(effect.getComputedTiming().progress, 0.0);
|
||||
anim.currentTime += 5000;
|
||||
assert_equals(effect.getComputedTiming().progress, 0.5);
|
||||
anim.finish();
|
||||
assert_equals(effect.getComputedTiming().progress, 1.0);
|
||||
}, "Animation constructed by an effect with null target runs normally");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -96,11 +96,10 @@ promise_test(function(t) {
|
|||
assert_equals(animation.playState, 'finished',
|
||||
'The play state of a paused animation should become ' +
|
||||
'"finished" after finish() is called');
|
||||
assert_approx_equals(animation.startTime,
|
||||
animation.timeline.currentTime - 100 * MS_PER_SEC,
|
||||
0.0001,
|
||||
'The start time of a paused animation should be set ' +
|
||||
'after calling finish()');
|
||||
assert_times_equal(animation.startTime,
|
||||
animation.timeline.currentTime - 100 * MS_PER_SEC,
|
||||
'The start time of a paused animation should be set ' +
|
||||
'after calling finish()');
|
||||
});
|
||||
}, 'Test finish() while paused');
|
||||
|
||||
|
@ -117,11 +116,10 @@ test(function(t) {
|
|||
assert_equals(animation.playState, 'finished',
|
||||
'The play state of a pause-pending animation should become ' +
|
||||
'"finished" after finish() is called');
|
||||
assert_approx_equals(animation.startTime,
|
||||
animation.timeline.currentTime - 100 * MS_PER_SEC / 2,
|
||||
0.0001,
|
||||
'The start time of a pause-pending animation should ' +
|
||||
'be set after calling finish()');
|
||||
assert_times_equal(animation.startTime,
|
||||
animation.timeline.currentTime - 100 * MS_PER_SEC / 2,
|
||||
'The start time of a pause-pending animation should ' +
|
||||
'be set after calling finish()');
|
||||
}, 'Test finish() while pause-pending with positive playbackRate');
|
||||
|
||||
test(function(t) {
|
||||
|
@ -148,11 +146,10 @@ test(function(t) {
|
|||
assert_equals(animation.playState, 'finished',
|
||||
'The play state of a play-pending animation should become ' +
|
||||
'"finished" after finish() is called');
|
||||
assert_approx_equals(animation.startTime,
|
||||
animation.timeline.currentTime - 100 * MS_PER_SEC / 0.5,
|
||||
0.0001,
|
||||
'The start time of a play-pending animation should ' +
|
||||
'be set after calling finish()');
|
||||
assert_times_equal(animation.startTime,
|
||||
animation.timeline.currentTime - 100 * MS_PER_SEC / 0.5,
|
||||
'The start time of a play-pending animation should ' +
|
||||
'be set after calling finish()');
|
||||
}, 'Test finish() while play-pending');
|
||||
|
||||
// FIXME: Add a test for when we are play-pending without an active timeline.
|
||||
|
@ -206,5 +203,45 @@ promise_test(function(t) {
|
|||
'Animation.finish()');
|
||||
});
|
||||
}, 'Test finish() resolves finished promise synchronously');
|
||||
|
||||
promise_test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
|
||||
var animation = new Animation(effect, document.timeline);
|
||||
var resolvedFinished = false;
|
||||
animation.finished.then(function() {
|
||||
resolvedFinished = true;
|
||||
});
|
||||
|
||||
return animation.ready.then(function() {
|
||||
animation.finish();
|
||||
}).then(function() {
|
||||
assert_true(resolvedFinished,
|
||||
'Animation.finished should be resolved soon after ' +
|
||||
'Animation.finish()');
|
||||
});
|
||||
}, 'Test finish() resolves finished promise synchronously with an animation ' +
|
||||
'without a target');
|
||||
|
||||
promise_test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
|
||||
var animation = new Animation(effect, document.timeline);
|
||||
animation.play();
|
||||
|
||||
var resolvedFinished = false;
|
||||
animation.finished.then(function() {
|
||||
resolvedFinished = true;
|
||||
});
|
||||
|
||||
return animation.ready.then(function() {
|
||||
animation.currentTime = animation.effect.getComputedTiming().endTime - 1;
|
||||
return waitForAnimationFrames(2);
|
||||
}).then(function() {
|
||||
assert_true(resolvedFinished,
|
||||
'Animation.finished should be resolved soon after ' +
|
||||
'Animation finishes normally');
|
||||
});
|
||||
}, 'Test normally finished animation resolves finished promise synchronously ' +
|
||||
'with an animation without a target');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animation.startTime tests</title>
|
||||
<link rel="help"
|
||||
href="https://w3c.github.io/web-animations/#dom-animation-starttime">
|
||||
<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 animation = new Animation(new KeyframeEffect(createDiv(t), null),
|
||||
document.timeline);
|
||||
assert_equals(animation.startTime, null, 'startTime is unresolved');
|
||||
}, 'startTime of a newly created (idle) animation is unresolved');
|
||||
|
||||
test(function(t) {
|
||||
var animation = new Animation(new KeyframeEffect(createDiv(t), null),
|
||||
document.timeline);
|
||||
animation.play();
|
||||
assert_equals(animation.startTime, null, 'startTime is unresolved');
|
||||
}, 'startTime of a play-pending animation is unresolved');
|
||||
|
||||
test(function(t) {
|
||||
var animation = new Animation(new KeyframeEffect(createDiv(t), null),
|
||||
document.timeline);
|
||||
animation.pause();
|
||||
assert_equals(animation.startTime, null, 'startTime is unresolved');
|
||||
}, 'startTime of a pause-pending animation is unresolved');
|
||||
|
||||
test(function(t) {
|
||||
var animation = createDiv(t).animate(null);
|
||||
assert_equals(animation.startTime, null, 'startTime is unresolved');
|
||||
}, 'startTime of a play-pending animation created using Element.animate'
|
||||
+ ' shortcut is unresolved');
|
||||
|
||||
promise_test(function(t) {
|
||||
var animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
return animation.ready.then(function() {
|
||||
assert_greater_than(animation.startTime, 0, 'startTime when running');
|
||||
});
|
||||
}, 'startTime is resolved when running');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,55 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>document.getAnimations tests</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-document-getanimations">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
var gKeyFrames = { 'marginLeft': ['100px', '200px'] };
|
||||
|
||||
test(function(t) {
|
||||
assert_equals(document.getAnimations().length, 0,
|
||||
'getAnimations returns an empty sequence for a document ' +
|
||||
'with no animations');
|
||||
}, 'Test document.getAnimations for non-animated content');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim1 = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
var anim2 = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
assert_equals(document.getAnimations().length, 2,
|
||||
'getAnimation returns running animations');
|
||||
|
||||
anim1.finish();
|
||||
anim2.finish();
|
||||
assert_equals(document.getAnimations().length, 0,
|
||||
'getAnimation only returns running animations');
|
||||
}, 'Test document.getAnimations for script-generated animations')
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim1 = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
var anim2 = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
assert_array_equals(document.getAnimations(),
|
||||
[ anim1, anim2 ],
|
||||
'getAnimations() returns running animations');
|
||||
}, 'Test the order of document.getAnimations with script generated animations')
|
||||
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
|
||||
var anim = new Animation(effect, document.timeline);
|
||||
anim.play();
|
||||
|
||||
assert_equals(document.getAnimations().length, 0,
|
||||
'document.getAnimations() only returns animations targeting ' +
|
||||
'elements in this document');
|
||||
}, 'Test document.getAnimations with null target');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,11 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>KeyframeEffectReadOnly constructor tests</title>
|
||||
<link rel="help" href="http://w3c.github.io/web-animations/#the-keyframeeffect-interfaces">
|
||||
<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au">
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#the-keyframeeffect-interfaces">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<script src="../resources/keyframe-utils.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<div id="target"></div>
|
||||
|
@ -19,28 +19,6 @@
|
|||
|
||||
var target = document.getElementById("target");
|
||||
|
||||
function assert_frames_equal(a, b, name) {
|
||||
assert_equals(Object.keys(a).sort().toString(),
|
||||
Object.keys(b).sort().toString(),
|
||||
"properties on " + name);
|
||||
for (var p in a) {
|
||||
assert_equals(a[p], b[p], "value for '" + p + "' on " + name);
|
||||
}
|
||||
}
|
||||
|
||||
function assert_frame_lists_equal(a, b) {
|
||||
assert_equals(a.length, b.length, "number of frames");
|
||||
for (var i = 0; i < Math.min(a.length, b.length); i++) {
|
||||
assert_frames_equal(a[i], b[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}
|
||||
|
||||
var gEmptyKeyframeListTests = [
|
||||
[],
|
||||
null,
|
||||
undefined,
|
||||
];
|
||||
|
||||
test(function(t) {
|
||||
gEmptyKeyframeListTests.forEach(function(frames) {
|
||||
assert_equals(new KeyframeEffectReadOnly(target, frames).getFrames().length,
|
||||
|
@ -48,14 +26,6 @@ test(function(t) {
|
|||
});
|
||||
}, "a KeyframeEffectReadOnly can be constructed with no frames");
|
||||
|
||||
// [specified easing value, expected easing value]
|
||||
var gEasingValueTests = [
|
||||
["linear", "linear"],
|
||||
["ease-in-out", "ease-in-out"],
|
||||
["Ease\\2d in-out", "ease-in-out"],
|
||||
["ease /**/", "ease"],
|
||||
];
|
||||
|
||||
test(function(t) {
|
||||
gEasingValueTests.forEach(function(subtest) {
|
||||
var easing = subtest[0];
|
||||
|
@ -97,18 +67,6 @@ test(function(t) {
|
|||
}, "easing values are parsed correctly when passed to the " +
|
||||
"KeyframeEffectReadOnly constructor in KeyframeTimingOptions");
|
||||
|
||||
var gGoodKeyframeCompositeValueTests = [
|
||||
"replace", "add", "accumulate", undefined
|
||||
];
|
||||
|
||||
var gGoodOptionsCompositeValueTests = [
|
||||
"replace", "add", "accumulate"
|
||||
];
|
||||
|
||||
var gBadCompositeValueTests = [
|
||||
"unrecognised", "replace ", "Replace", null
|
||||
];
|
||||
|
||||
test(function(t) {
|
||||
var getFrame = function(composite) {
|
||||
return { left: [ "10px", "20px" ], composite: composite };
|
||||
|
@ -120,8 +78,8 @@ test(function(t) {
|
|||
});
|
||||
gBadCompositeValueTests.forEach(function(composite) {
|
||||
assert_throws(new TypeError, function() {
|
||||
new KeyframeEffectReadOnly(target, getFrame(composite));
|
||||
});
|
||||
new KeyframeEffectReadOnly(target, getFrame(composite));
|
||||
});
|
||||
});
|
||||
}, "composite values are parsed correctly when passed to the " +
|
||||
"KeyframeEffectReadOnly constructor in property-indexed keyframes");
|
||||
|
@ -140,8 +98,8 @@ test(function(t) {
|
|||
});
|
||||
gBadCompositeValueTests.forEach(function(composite) {
|
||||
assert_throws(new TypeError, function() {
|
||||
new KeyframeEffectReadOnly(target, getFrames(composite));
|
||||
});
|
||||
new KeyframeEffectReadOnly(target, getFrames(composite));
|
||||
});
|
||||
});
|
||||
}, "composite values are parsed correctly when passed to the " +
|
||||
"KeyframeEffectReadOnly constructor in regular keyframes");
|
||||
|
@ -156,130 +114,14 @@ test(function(t) {
|
|||
});
|
||||
gBadCompositeValueTests.forEach(function(composite) {
|
||||
assert_throws(new TypeError, function() {
|
||||
new KeyframeEffectReadOnly(target, {
|
||||
left: ["10px", "20px"]
|
||||
}, { composite: composite });
|
||||
});
|
||||
new KeyframeEffectReadOnly(target, {
|
||||
left: ["10px", "20px"]
|
||||
}, { composite: composite });
|
||||
});
|
||||
});
|
||||
}, "composite values are parsed correctly when passed to the " +
|
||||
"KeyframeEffectReadOnly constructor in KeyframeTimingOptions");
|
||||
|
||||
var gPropertyIndexedKeyframesTests = [
|
||||
{ desc: "a one property two value property-indexed keyframes specification",
|
||||
input: { left: ["10px", "20px"] },
|
||||
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: 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: 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: 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: 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: 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: 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: null, computedOffset: 1, easing: "linear",
|
||||
left: "10px" }] },
|
||||
{ desc: "a one property one non-array value property-indexed keyframes"
|
||||
+ " specification",
|
||||
input: { left: "10px" },
|
||||
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: 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: 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 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 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: "step-end",
|
||||
left: "500px" }] },
|
||||
];
|
||||
|
||||
gPropertyIndexedKeyframesTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(target, subtest.input);
|
||||
|
@ -314,208 +156,6 @@ test(function(t) {
|
|||
}, "the KeyframeEffectReadOnly constructor reads keyframe properties in the " +
|
||||
"expected order");
|
||||
|
||||
var gKeyframeSequenceTests = [
|
||||
{ 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",
|
||||
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",
|
||||
input: [{ offset: 0, margin: "10px" },
|
||||
{ offset: 1, margin: "20px 30px 40px 50px" }],
|
||||
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",
|
||||
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: "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" },
|
||||
{ offset: 1, left: "40px" },
|
||||
{ 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: "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" },
|
||||
{ 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: 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: 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: 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" },
|
||||
{ offset: 0.5, easing: "linear", top: "40px" },
|
||||
{ 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" },
|
||||
{ offset: 0.0, computedOffset: 0.0, easing: "ease",
|
||||
top: "20px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||
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" },
|
||||
{ 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",
|
||||
input: [{ offset: 0, margin: "10px", marginRight: "20px" },
|
||||
{ offset: 1, margin: "30px" }],
|
||||
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",
|
||||
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",
|
||||
borderLeft: "1px solid rgb(1, 2, 3)",
|
||||
border: "2px dotted rgb(4, 5, 6)" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
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",
|
||||
border: "2px dotted rgb(4, 5, 6)",
|
||||
borderLeft: "1px solid rgb(1, 2, 3)" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
border: "3px dashed rgb(7, 8, 9)" }] },
|
||||
];
|
||||
|
||||
gKeyframeSequenceTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(target, subtest.input);
|
||||
|
@ -530,20 +170,13 @@ gKeyframeSequenceTests.forEach(function(subtest) {
|
|||
" roundtrips");
|
||||
});
|
||||
|
||||
var gInvalidEasingInKeyframeSequenceTests = [
|
||||
{ desc: "a blank easing",
|
||||
input: [{ easing: "" }] },
|
||||
{ desc: "an unrecognized easing",
|
||||
input: [{ easing: "unrecognized" }] },
|
||||
{ desc: "an 'initial' easing",
|
||||
input: [{ easing: "initial" }] },
|
||||
{ desc: "an 'inherit' easing",
|
||||
input: [{ easing: "inherit" }] },
|
||||
{ desc: "a variable easing",
|
||||
input: [{ easing: "var(--x)" }] },
|
||||
{ desc: "a multi-value easing",
|
||||
input: [{ easing: "ease-in-out, ease-out" }] }
|
||||
];
|
||||
gInvalidKeyframesTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
assert_throws(subtest.expected, function() {
|
||||
new KeyframeEffectReadOnly(target, subtest.input);
|
||||
});
|
||||
}, "KeyframeEffectReadOnly constructor throws with " + subtest.desc);
|
||||
});
|
||||
|
||||
gInvalidEasingInKeyframeSequenceTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
|
@ -556,7 +189,7 @@ gInvalidEasingInKeyframeSequenceTests.forEach(function(subtest) {
|
|||
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(target,
|
||||
{left: ["10px", "20px"]});
|
||||
{ left: ["10px", "20px"] });
|
||||
|
||||
var timing = effect.timing;
|
||||
assert_equals(timing.delay, 0, "default delay");
|
||||
|
@ -576,48 +209,10 @@ test(function(t) {
|
|||
}, "a KeyframeEffectReadOnly constructed without any " +
|
||||
"KeyframeEffectOptions object");
|
||||
|
||||
var gKeyframeEffectOptionTests = [
|
||||
{ desc: "an empty KeyframeEffectOptions object",
|
||||
input: { },
|
||||
expected: { } },
|
||||
{ desc: "a normal KeyframeEffectOptions object",
|
||||
input: { delay: 1000,
|
||||
fill: "auto",
|
||||
iterations: 5.5,
|
||||
duration: "auto",
|
||||
direction: "alternate" },
|
||||
expected: { delay: 1000,
|
||||
fill: "auto",
|
||||
iterations: 5.5,
|
||||
duration: "auto",
|
||||
direction: "alternate" } },
|
||||
{ desc: "a double value",
|
||||
input: 3000,
|
||||
expected: { duration: 3000 } },
|
||||
{ desc: "+Infinity",
|
||||
input: Infinity,
|
||||
expected: { duration: Infinity } },
|
||||
{ desc: "an Infinity duration",
|
||||
input: { duration: Infinity },
|
||||
expected: { duration: Infinity } },
|
||||
{ desc: "an auto duration",
|
||||
input: { duration: "auto" },
|
||||
expected: { duration: "auto" } },
|
||||
{ desc: "an Infinity iterations",
|
||||
input: { iterations: Infinity },
|
||||
expected: { iterations: Infinity } },
|
||||
{ desc: "an auto fill",
|
||||
input: { fill: "auto" },
|
||||
expected: { fill: "auto" } },
|
||||
{ desc: "a forwards fill",
|
||||
input: { fill: "forwards" },
|
||||
expected: { fill: "forwards" } }
|
||||
];
|
||||
|
||||
gKeyframeEffectOptionTests.forEach(function(stest) {
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(target,
|
||||
{left: ["10px", "20px"]},
|
||||
{ left: ["10px", "20px"] },
|
||||
stest.input);
|
||||
|
||||
// Helper function to provide default expected values when the test does
|
||||
|
@ -641,57 +236,6 @@ gKeyframeEffectOptionTests.forEach(function(stest) {
|
|||
}, "a KeyframeEffectReadOnly constructed by " + stest.desc);
|
||||
});
|
||||
|
||||
var gInvalidKeyframeEffectOptionTests = [
|
||||
{ desc: "-Infinity",
|
||||
input: -Infinity,
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "NaN",
|
||||
input: NaN,
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a negative value",
|
||||
input: -1,
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a negative Infinity duration",
|
||||
input: { duration: -Infinity },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a NaN duration",
|
||||
input: { duration: NaN },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a negative duration",
|
||||
input: { duration: -1 },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a string duration",
|
||||
input: { duration: "merrychristmas" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a negative Infinity iterations",
|
||||
input: { iterations: -Infinity},
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a NaN iterations",
|
||||
input: { iterations: NaN },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a negative iterations",
|
||||
input: { iterations: -1 },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a blank easing",
|
||||
input: { easing: "" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "an unrecognized easing",
|
||||
input: { easing: "unrecognised" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "an 'initial' easing",
|
||||
input: { easing: "initial" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "an 'inherit' easing",
|
||||
input: { easing: "inherit" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a variable easing",
|
||||
input: { easing: "var(--x)" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a multi-value easing",
|
||||
input: { easing: "ease-in-out, ease-out" },
|
||||
expected: { name: "TypeError" } }
|
||||
];
|
||||
|
||||
gInvalidKeyframeEffectOptionTests.forEach(function(stest) {
|
||||
test(function(t) {
|
||||
assert_throws(stest.expected, function() {
|
||||
|
@ -703,9 +247,16 @@ gInvalidKeyframeEffectOptionTests.forEach(function(stest) {
|
|||
});
|
||||
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffect(target,
|
||||
{ left: ["10px", "20px"] });
|
||||
var effect = new KeyframeEffectReadOnly(null,
|
||||
{ left: ["10px", "20px"] },
|
||||
{ duration: 100 * MS_PER_SEC,
|
||||
fill: "forwards" });
|
||||
assert_equals(effect.target, null,
|
||||
"Effect created with null target has correct target");
|
||||
}, "a KeyframeEffectReadOnly constructed with null target");
|
||||
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffect(target, null);
|
||||
assert_class_string(effect, "KeyframeEffect");
|
||||
assert_class_string(effect.timing, "AnimationEffectTiming");
|
||||
}, "KeyframeEffect constructor creates an AnimationEffectTiming timing object");
|
||||
|
@ -718,7 +269,5 @@ test(function(t) {
|
|||
});
|
||||
}, "KeyframeEffect constructor propagates exceptions generated by accessing"
|
||||
+ " the options object");
|
||||
|
||||
done();
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>KeyframeEffect setFrames() tests</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-keyframeeffect-setframes">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<script src="../resources/keyframe-utils.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
var target = document.getElementById('target');
|
||||
|
||||
test(function(t) {
|
||||
gEmptyKeyframeListTests.forEach(function(frame) {
|
||||
var effect = new KeyframeEffect(target, {});
|
||||
effect.setFrames(frame);
|
||||
assert_frame_lists_equal(effect.getFrames(), []);
|
||||
});
|
||||
}, 'Keyframes can be replaced with an empty keyframe');
|
||||
|
||||
gPropertyIndexedKeyframesTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffect(target, {});
|
||||
effect.setFrames(subtest.input);
|
||||
assert_frame_lists_equal(effect.getFrames(), subtest.output);
|
||||
}, 'Keyframes can be replaced with ' + subtest.desc);
|
||||
});
|
||||
|
||||
gKeyframeSequenceTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffect(target, {});
|
||||
effect.setFrames(subtest.input);
|
||||
assert_frame_lists_equal(effect.getFrames(), subtest.output);
|
||||
}, 'Keyframes can be replaced with ' + subtest.desc);
|
||||
});
|
||||
|
||||
gInvalidKeyframesTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffect(target, {});
|
||||
assert_throws(subtest.expected, function() {
|
||||
effect.setFrames(subtest.input);
|
||||
});
|
||||
}, 'KeyframeEffect constructor throws with ' + subtest.desc);
|
||||
});
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,89 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Writable effect.target tests</title>
|
||||
<link rel="help"
|
||||
href="https://w3c.github.io/web-animations/#dom-keyframeeffect-target">
|
||||
<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";
|
||||
|
||||
var gKeyFrames = { 'marginLeft': ['0px', '100px'] };
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
|
||||
effect.target = div;
|
||||
|
||||
var anim = new Animation(effect, document.timeline);
|
||||
anim.play();
|
||||
|
||||
anim.currentTime = 50 * MS_PER_SEC;
|
||||
assert_equals(getComputedStyle(div).marginLeft, '50px',
|
||||
'Value at 50% progress');
|
||||
}, 'Test setting target before constructing the associated animation');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
div.style.marginLeft = '10px';
|
||||
var effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
|
||||
var anim = new Animation(effect, document.timeline);
|
||||
anim.play();
|
||||
|
||||
anim.currentTime = 50 * MS_PER_SEC;
|
||||
assert_equals(getComputedStyle(div).marginLeft, '10px',
|
||||
'Value at 50% progress before setting new target');
|
||||
effect.target = div;
|
||||
assert_equals(getComputedStyle(div).marginLeft, '50px',
|
||||
'Value at 50% progress after setting new target');
|
||||
}, 'Test setting target from null to a valid target');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
div.style.marginLeft = '10px';
|
||||
var anim = div.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
|
||||
anim.currentTime = 50 * MS_PER_SEC;
|
||||
assert_equals(getComputedStyle(div).marginLeft, '50px',
|
||||
'Value at 50% progress before clearing the target')
|
||||
|
||||
anim.effect.target = null;
|
||||
assert_equals(getComputedStyle(div).marginLeft, '10px',
|
||||
'Value after clearing the target')
|
||||
}, 'Test setting target from a valid target to null');
|
||||
|
||||
test(function(t) {
|
||||
var a = createDiv(t);
|
||||
var b = createDiv(t);
|
||||
a.style.marginLeft = '10px';
|
||||
b.style.marginLeft = '20px';
|
||||
var anim = a.animate(gKeyFrames, 100 * MS_PER_SEC);
|
||||
|
||||
anim.currentTime = 50 * MS_PER_SEC;
|
||||
assert_equals(getComputedStyle(a).marginLeft, '50px',
|
||||
'Value of 1st element (currently targeted) before ' +
|
||||
'changing the effect target');
|
||||
assert_equals(getComputedStyle(b).marginLeft, '20px',
|
||||
'Value of 2nd element (currently not targeted) before ' +
|
||||
'changing the effect target');
|
||||
anim.effect.target = b;
|
||||
assert_equals(getComputedStyle(a).marginLeft, '10px',
|
||||
'Value of 1st element (currently not targeted) after ' +
|
||||
'changing the effect target');
|
||||
assert_equals(getComputedStyle(b).marginLeft, '50px',
|
||||
'Value of 2nd element (currently targeted) after ' +
|
||||
'changing the effect target');
|
||||
|
||||
// This makes sure the animation property is changed correctly on new
|
||||
// targeted element.
|
||||
anim.currentTime = 75 * MS_PER_SEC;
|
||||
assert_equals(getComputedStyle(b).marginLeft, '75px',
|
||||
'Value of 2nd target (currently targeted) after ' +
|
||||
'changing the animation current time.');
|
||||
}, 'Test setting target from a valid target to another target');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,530 @@
|
|||
"use strict";
|
||||
|
||||
// Utility functions and common keyframe test data.
|
||||
|
||||
// ------------------------------
|
||||
// Helper functions
|
||||
// ------------------------------
|
||||
|
||||
/**
|
||||
* Test equality between two lists of computed keyframes
|
||||
* @param {Array.<ComputedKeyframe>} a - actual computed keyframes
|
||||
* @param {Array.<ComputedKeyframe>} b - expected computed keyframes
|
||||
*/
|
||||
function assert_frame_lists_equal(a, b) {
|
||||
assert_equals(a.length, b.length, "number of frames");
|
||||
for (var i = 0; i < Math.min(a.length, b.length); i++) {
|
||||
assert_frames_equal(a[i], b[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}
|
||||
|
||||
/** Helper */
|
||||
function assert_frames_equal(a, b, name) {
|
||||
assert_equals(Object.keys(a).sort().toString(),
|
||||
Object.keys(b).sort().toString(),
|
||||
"properties on " + name);
|
||||
for (var p in a) {
|
||||
assert_equals(a[p], b[p], "value for '" + p + "' on " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// Easing values
|
||||
// ------------------------------
|
||||
|
||||
// [specified easing value, expected easing value]
|
||||
var gEasingValueTests = [
|
||||
["linear", "linear"],
|
||||
["ease-in-out", "ease-in-out"],
|
||||
["Ease\\2d in-out", "ease-in-out"],
|
||||
["ease /**/", "ease"],
|
||||
];
|
||||
|
||||
var gInvalidEasingInKeyframeSequenceTests = [
|
||||
{ desc: "a blank easing",
|
||||
input: [{ easing: "" }] },
|
||||
{ desc: "an unrecognized easing",
|
||||
input: [{ easing: "unrecognized" }] },
|
||||
{ desc: "an 'initial' easing",
|
||||
input: [{ easing: "initial" }] },
|
||||
{ desc: "an 'inherit' easing",
|
||||
input: [{ easing: "inherit" }] },
|
||||
{ desc: "a variable easing",
|
||||
input: [{ easing: "var(--x)" }] },
|
||||
{ desc: "a multi-value easing",
|
||||
input: [{ easing: "ease-in-out, ease-out" }] }
|
||||
];
|
||||
|
||||
// ------------------------------
|
||||
// Composite values
|
||||
// ------------------------------
|
||||
|
||||
var gGoodKeyframeCompositeValueTests = [
|
||||
"replace", "add", "accumulate", undefined
|
||||
];
|
||||
|
||||
var gGoodOptionsCompositeValueTests = [
|
||||
"replace", "add", "accumulate"
|
||||
];
|
||||
|
||||
var gBadCompositeValueTests = [
|
||||
"unrecognised", "replace ", "Replace", null
|
||||
];
|
||||
|
||||
// ------------------------------
|
||||
// Keyframes
|
||||
// ------------------------------
|
||||
|
||||
var gEmptyKeyframeListTests = [
|
||||
[],
|
||||
null,
|
||||
undefined,
|
||||
];
|
||||
|
||||
var gPropertyIndexedKeyframesTests = [
|
||||
{ desc: "a one property two value property-indexed keyframes specification",
|
||||
input: { left: ["10px", "20px"] },
|
||||
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: 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: 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: 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: 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: 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: 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: null, computedOffset: 1, easing: "linear",
|
||||
left: "10px" }] },
|
||||
{ desc: "a one property one non-array value property-indexed keyframes"
|
||||
+ " specification",
|
||||
input: { left: "10px" },
|
||||
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: 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: 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 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 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: "step-end",
|
||||
left: "500px" }] },
|
||||
];
|
||||
|
||||
var gKeyframeSequenceTests = [
|
||||
{ desc: "a one property one keyframe sequence",
|
||||
input: [{ offset: 1, left: "10px" }],
|
||||
output: [{ offset: null, computedOffset: 1, easing: "linear",
|
||||
left: "10px" }] },
|
||||
{ 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",
|
||||
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",
|
||||
input: [{ offset: 0, margin: "10px" },
|
||||
{ offset: 1, margin: "20px 30px 40px 50px" }],
|
||||
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",
|
||||
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: "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" },
|
||||
{ offset: 1, left: "40px" },
|
||||
{ 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: "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" },
|
||||
{ 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 single keyframe sequence with omitted offsets",
|
||||
input: [{ left: "10px" }],
|
||||
output: [{ offset: null, computedOffset: 1, easing: "linear",
|
||||
left: "10px" }] },
|
||||
{ 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: 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: 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: 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" },
|
||||
{ offset: 0.5, easing: "linear", top: "40px" },
|
||||
{ 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" },
|
||||
{ offset: 0.0, computedOffset: 0.0, easing: "ease",
|
||||
top: "20px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||
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" },
|
||||
{ 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",
|
||||
input: [{ offset: 0, margin: "10px", marginRight: "20px" },
|
||||
{ offset: 1, margin: "30px" }],
|
||||
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",
|
||||
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",
|
||||
borderLeft: "1px solid rgb(1, 2, 3)",
|
||||
border: "2px dotted rgb(4, 5, 6)" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
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",
|
||||
border: "2px dotted rgb(4, 5, 6)",
|
||||
borderLeft: "1px solid rgb(1, 2, 3)" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||
border: "3px dashed rgb(7, 8, 9)" }] }
|
||||
];
|
||||
|
||||
var gInvalidKeyframesTests = [
|
||||
{ desc: "keyframes with an out-of-bounded positive offset",
|
||||
input: [ { opacity: 0 },
|
||||
{ opacity: 0.5, offset: 2 },
|
||||
{ opacity: 1 } ],
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "keyframes with an out-of-bounded negative offset",
|
||||
input: [ { opacity: 0 },
|
||||
{ opacity: 0.5, offset: -1 },
|
||||
{ opacity: 1 } ],
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "keyframes not loosely sorted by offset",
|
||||
input: [ { opacity: 0, offset: 1 },
|
||||
{ opacity: 1, offset: 0 } ],
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "property-indexed keyframes with an invalid easing value",
|
||||
input: { opacity: [ 0, 0.5, 1 ],
|
||||
easing: "inherit" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a keyframe sequence with an invalid easing value",
|
||||
input: [ { opacity: 0, easing: "jumpy" },
|
||||
{ opacity: 1 } ],
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "keyframes with an invalid composite value",
|
||||
input: [ { opacity: 0, composite: "alternate" },
|
||||
{ opacity: 1 } ],
|
||||
expected: { name: "TypeError" } }
|
||||
];
|
||||
|
||||
// ------------------------------
|
||||
// KeyframeEffectOptions
|
||||
// ------------------------------
|
||||
|
||||
var gKeyframeEffectOptionTests = [
|
||||
{ desc: "an empty KeyframeEffectOptions object",
|
||||
input: { },
|
||||
expected: { } },
|
||||
{ desc: "a normal KeyframeEffectOptions object",
|
||||
input: { delay: 1000,
|
||||
fill: "auto",
|
||||
iterations: 5.5,
|
||||
duration: "auto",
|
||||
direction: "alternate" },
|
||||
expected: { delay: 1000,
|
||||
fill: "auto",
|
||||
iterations: 5.5,
|
||||
duration: "auto",
|
||||
direction: "alternate" } },
|
||||
{ desc: "a double value",
|
||||
input: 3000,
|
||||
expected: { duration: 3000 } },
|
||||
{ desc: "+Infinity",
|
||||
input: Infinity,
|
||||
expected: { duration: Infinity } },
|
||||
{ desc: "an Infinity duration",
|
||||
input: { duration: Infinity },
|
||||
expected: { duration: Infinity } },
|
||||
{ desc: "an auto duration",
|
||||
input: { duration: "auto" },
|
||||
expected: { duration: "auto" } },
|
||||
{ desc: "an Infinity iterations",
|
||||
input: { iterations: Infinity },
|
||||
expected: { iterations: Infinity } },
|
||||
{ desc: "an auto fill",
|
||||
input: { fill: "auto" },
|
||||
expected: { fill: "auto" } },
|
||||
{ desc: "a forwards fill",
|
||||
input: { fill: "forwards" },
|
||||
expected: { fill: "forwards" } }
|
||||
];
|
||||
|
||||
var gInvalidKeyframeEffectOptionTests = [
|
||||
{ desc: "-Infinity",
|
||||
input: -Infinity,
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "NaN",
|
||||
input: NaN,
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a negative value",
|
||||
input: -1,
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a negative Infinity duration",
|
||||
input: { duration: -Infinity },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a NaN duration",
|
||||
input: { duration: NaN },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a negative duration",
|
||||
input: { duration: -1 },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a string duration",
|
||||
input: { duration: "merrychristmas" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a negative Infinity iterations",
|
||||
input: { iterations: -Infinity},
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a NaN iterations",
|
||||
input: { iterations: NaN },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a negative iterations",
|
||||
input: { iterations: -1 },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a blank easing",
|
||||
input: { easing: "" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "an unrecognized easing",
|
||||
input: { easing: "unrecognised" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "an 'initial' easing",
|
||||
input: { easing: "initial" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "an 'inherit' easing",
|
||||
input: { easing: "inherit" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a variable easing",
|
||||
input: { easing: "var(--x)" },
|
||||
expected: { name: "TypeError" } },
|
||||
{ desc: "a multi-value easing",
|
||||
input: { easing: "ease-in-out, ease-out" },
|
||||
expected: { name: "TypeError" } }
|
||||
];
|
|
@ -8,9 +8,23 @@ policies and contribution forms [3].
|
|||
[3] http://www.w3.org/2004/10/27-testcases
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var MS_PER_SEC = 1000;
|
||||
|
||||
// The recommended minimum precision to use for time values[1].
|
||||
//
|
||||
// [1] https://w3c.github.io/web-animations/#precision-of-time-values
|
||||
var TIME_PRECISION = 0.0005; // ms
|
||||
|
||||
// Allow implementations to substitute an alternative method for comparing
|
||||
// times based on their precision requirements.
|
||||
if (!window.assert_times_equal) {
|
||||
window.assert_times_equal = function(actual, expected, description) {
|
||||
assert_approx_equals(actual, expected, TIME_PRECISION, description);
|
||||
}
|
||||
}
|
||||
|
||||
// creates div element, appends it to the document body and
|
||||
// removes the created element during test cleanup
|
||||
function createDiv(test, doc) {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Active time tests</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#active-time">
|
||||
<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';
|
||||
|
||||
async_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, { delay: 1 });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, null);
|
||||
anim.finished.then(t.step_func(function() {
|
||||
assert_equals(anim.effect.getComputedTiming().progress, null);
|
||||
t.done();
|
||||
}));
|
||||
}, 'Test progress during before and after phase when fill is none');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,11 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>currentIteration of KeyframeEffectReadOnly getComputedTiming() tests</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffectreadonly-getcomputedtiming">
|
||||
<link rel="author" title="Daisuke Akatsuka" href="mailto:daisuke@mozilla-japan.org">
|
||||
<title>Current iteration tests</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#current-iteration">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
|
@ -1,11 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>progress of KeyframeEffectReadOnly getComputedTiming() tests</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffectreadonly-getcomputedtiming">
|
||||
<link rel="author" title="Daisuke Akatsuka" href="mailto:daisuke@mozilla-japan.org">
|
||||
<title>Simple iteration progress tests</title>
|
||||
<link rel="help"
|
||||
href="https://w3c.github.io/web-animations/#simple-iteration-progress">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
@ -34,16 +34,6 @@ function executeTests(tests, description) {
|
|||
});
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, { delay: 1 });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, null);
|
||||
anim.finished.then(t.step_func(function() {
|
||||
assert_equals(anim.effect.getComputedTiming().progress, null);
|
||||
t.done();
|
||||
}));
|
||||
}, 'Test progress during before and after phase when fill is none');
|
||||
|
||||
var gTests_zero_iterations = [
|
||||
{
|
||||
input: { iterations: 0,
|
|
@ -0,0 +1,205 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Setting the start time tests</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#set-the-animation-start-time">
|
||||
<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)
|
||||
{
|
||||
// It should only be possible to set *either* the start time or the current
|
||||
// time for an animation that does not have an active timeline.
|
||||
|
||||
var animation =
|
||||
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC));
|
||||
|
||||
assert_equals(animation.currentTime, null, 'Intial current time');
|
||||
assert_equals(animation.startTuime, null, 'Intial start time');
|
||||
|
||||
animation.currentTime = 1000;
|
||||
assert_equals(animation.currentTime, 1000,
|
||||
'Setting the current time succeeds');
|
||||
assert_equals(animation.startTime, null,
|
||||
'Start time remains null after setting current time');
|
||||
|
||||
animation.startTime = 1000;
|
||||
assert_equals(animation.startTime, 1000,
|
||||
'Setting the start time succeeds');
|
||||
assert_equals(animation.currentTime, null,
|
||||
'Setting the start time clears the current time');
|
||||
|
||||
animation.startTime = null;
|
||||
assert_equals(animation.startTime, null,
|
||||
'Setting the start time to an unresolved time succeeds');
|
||||
assert_equals(animation.currentTime, null, 'The current time is unaffected');
|
||||
|
||||
}, 'Setting the start time of an animation without an active timeline');
|
||||
|
||||
test(function(t)
|
||||
{
|
||||
// Setting an unresolved start time on an animation without an active
|
||||
// timeline should not clear the current time.
|
||||
|
||||
var animation =
|
||||
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC));
|
||||
|
||||
assert_equals(animation.currentTime, null, 'Intial current time');
|
||||
assert_equals(animation.startTuime, null, 'Intial start time');
|
||||
|
||||
animation.currentTime = 1000;
|
||||
assert_equals(animation.currentTime, 1000,
|
||||
'Setting the current time succeeds');
|
||||
assert_equals(animation.startTime, null,
|
||||
'Start time remains null after setting current time');
|
||||
|
||||
animation.startTime = null;
|
||||
assert_equals(animation.startTime, null, 'Start time remains unresolved');
|
||||
assert_equals(animation.currentTime, 1000, 'Current time is unaffected');
|
||||
|
||||
}, 'Setting an unresolved start time an animation without an active timeline'
|
||||
+ ' does not clear the current time');
|
||||
|
||||
test(function(t)
|
||||
{
|
||||
var animation =
|
||||
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
|
||||
document.timeline);
|
||||
|
||||
// So long as a hold time is set, querying the current time will return
|
||||
// the hold time.
|
||||
|
||||
// Since the start time is unresolved at this point, setting the current time
|
||||
// will set the hold time
|
||||
animation.currentTime = 1000;
|
||||
assert_equals(animation.currentTime, 1000,
|
||||
'The current time is calculated from the hold time');
|
||||
|
||||
// If we set the start time, however, we should clear the hold time.
|
||||
animation.startTime = document.timeline.currentTime - 2000;
|
||||
assert_times_equal(animation.currentTime, 2000,
|
||||
'The current time is calculated from the start time,'
|
||||
+ ' not the hold time');
|
||||
|
||||
// Sanity check
|
||||
assert_equals(animation.playState, 'running',
|
||||
'Animation reports it is running after setting a resolved'
|
||||
+ ' start time');
|
||||
}, 'Setting the start time clears the hold time');
|
||||
|
||||
test(function(t)
|
||||
{
|
||||
var animation =
|
||||
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
|
||||
document.timeline);
|
||||
|
||||
// Set up a running animation (i.e. both start time and current time
|
||||
// are resolved).
|
||||
animation.startTime = document.timeline.currentTime - 1000;
|
||||
assert_equals(animation.playState, 'running');
|
||||
assert_times_equal(animation.currentTime, 1000,
|
||||
'Current time is resolved for a running animation')
|
||||
|
||||
// Clear start time
|
||||
animation.startTime = null;
|
||||
assert_times_equal(animation.currentTime, 1000,
|
||||
'Hold time is set after start time is made unresolved');
|
||||
assert_equals(animation.playState, 'paused',
|
||||
'Animation reports it is paused after setting an unresolved'
|
||||
+ ' start time');
|
||||
}, 'Setting an unresolved start time sets the hold time');
|
||||
|
||||
promise_test(function(t)
|
||||
{
|
||||
var animation =
|
||||
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
|
||||
document.timeline);
|
||||
|
||||
var readyPromiseCallbackCalled = false;
|
||||
animation.ready.then(function() { readyPromiseCallbackCalled = true; } );
|
||||
|
||||
// Put the animation in the play-pending state
|
||||
animation.play();
|
||||
|
||||
// Sanity check
|
||||
assert_equals(animation.playState, 'pending',
|
||||
'Animation is in play-pending state');
|
||||
|
||||
// Setting the start time should resolve the 'ready' promise, i.e.
|
||||
// it should schedule a microtask to run the promise callbacks.
|
||||
animation.startTime = document.timeline.currentTime;
|
||||
assert_false(readyPromiseCallbackCalled,
|
||||
'Ready promise callback is not called synchronously');
|
||||
|
||||
// If we schedule another microtask then it should run immediately after
|
||||
// the ready promise resolution microtask.
|
||||
return Promise.resolve().then(function() {
|
||||
assert_true(readyPromiseCallbackCalled,
|
||||
'Ready promise callback called after setting startTime');
|
||||
});
|
||||
}, 'Setting the start time resolves a pending ready promise');
|
||||
|
||||
promise_test(function(t)
|
||||
{
|
||||
var animation =
|
||||
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
|
||||
document.timeline);
|
||||
|
||||
var readyPromiseCallbackCalled = false;
|
||||
animation.ready.then(function() { readyPromiseCallbackCalled = true; } );
|
||||
|
||||
// Put the animation in the pause-pending state
|
||||
animation.startTime = document.timeline.currentTime;
|
||||
animation.pause();
|
||||
|
||||
// Sanity check
|
||||
assert_equals(animation.playState, 'pending',
|
||||
'Animation is in pause-pending state');
|
||||
|
||||
// Setting the start time should resolve the 'ready' promise although
|
||||
// the resolution callbacks when be run in a separate microtask.
|
||||
animation.startTime = null;
|
||||
assert_false(readyPromiseCallbackCalled,
|
||||
'Ready promise callback is not called synchronously');
|
||||
|
||||
return Promise.resolve().then(function() {
|
||||
assert_true(readyPromiseCallbackCalled,
|
||||
'Ready promise callback called after setting startTime');
|
||||
});
|
||||
}, 'Setting the start time resolves a pending pause task');
|
||||
|
||||
promise_test(function(t)
|
||||
{
|
||||
var animation =
|
||||
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
|
||||
document.timeline);
|
||||
|
||||
// Set start time such that the current time is past the end time
|
||||
animation.startTime = document.timeline.currentTime
|
||||
- 110 * MS_PER_SEC;
|
||||
assert_equals(animation.playState, 'finished',
|
||||
'Seeked to finished state using the startTime');
|
||||
|
||||
// If the 'did seek' flag is true, the current time should be greater than
|
||||
// the effect end.
|
||||
assert_greater_than(animation.currentTime,
|
||||
animation.effect.getComputedTiming().endTime,
|
||||
'Setting the start time updated the finished state with'
|
||||
+ ' the \'did seek\' flag set to true');
|
||||
|
||||
// Furthermore, that time should persist if we have correctly updated
|
||||
// the hold time
|
||||
var finishedCurrentTime = animation.currentTime;
|
||||
return waitForAnimationFrames(1).then(function() {
|
||||
assert_equals(animation.currentTime, finishedCurrentTime,
|
||||
'Current time does not change after seeking past the effect'
|
||||
+ ' end time by setting the current time');
|
||||
});
|
||||
}, 'Setting the start time updates the finished state');
|
||||
|
||||
</script>
|
||||
</body>
|
Loading…
Add table
Add a link
Reference in a new issue