mirror of
https://github.com/servo/servo.git
synced 2025-08-07 22:45:34 +01:00
Update web-platform-tests to revision e87f38097902e16348d4e17f4fe3bc2d0112bff1
This commit is contained in:
parent
2f8fa32e91
commit
db5631a086
381 changed files with 11610 additions and 4232 deletions
|
@ -8,6 +8,8 @@
|
|||
<script src="../../resources/easing-tests.js"></script>
|
||||
<script src="../../resources/keyframe-utils.js"></script>
|
||||
<script src="../../resources/keyframe-tests.js"></script>
|
||||
<script src="../../resources/timing-utils.js"></script>
|
||||
<script src="../../resources/timing-tests.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<iframe width="10" height="10" id="iframe"></iframe>
|
||||
|
@ -17,8 +19,7 @@
|
|||
// Tests on Element
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate(null);
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_class_string(anim, 'Animation', 'Returned object is an Animation');
|
||||
}, 'Element.animate() creates an Animation object');
|
||||
|
||||
|
@ -57,26 +58,9 @@ test(t => {
|
|||
}, 'Element.animate() creates an Animation object with a KeyframeEffect'
|
||||
+ ' that is created in the relevant realm of the target element');
|
||||
|
||||
test(t => {
|
||||
const iframe = window.frames[0];
|
||||
const div = createDiv(t, iframe.document);
|
||||
const anim = div.animate(null);
|
||||
assert_equals(Object.getPrototypeOf(anim.effect.timing),
|
||||
iframe.AnimationEffectTiming.prototype,
|
||||
'The prototype of the created AnimationEffectTiming is that'
|
||||
+ ' defined on the relevant global for the target element');
|
||||
assert_not_equals(Object.getPrototypeOf(anim.effect.timing),
|
||||
AnimationEffectTiming.prototype,
|
||||
'The prototype of the created AnimationEffectTiming is NOT'
|
||||
+ ' that of the current global');
|
||||
}, 'Element.animate() creates an Animation object with a KeyframeEffect'
|
||||
+ ' whose AnimationEffectTiming object is created in the relevant realm'
|
||||
+ ' of the target element');
|
||||
|
||||
for (const subtest of gEmptyKeyframeListTests) {
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate(subtest, 2000);
|
||||
const anim = createDiv(t).animate(subtest, 2000);
|
||||
assert_not_equals(anim, null);
|
||||
}, 'Element.animate() accepts empty keyframe lists ' +
|
||||
`(input: ${JSON.stringify(subtest)})`);
|
||||
|
@ -84,8 +68,7 @@ for (const subtest of gEmptyKeyframeListTests) {
|
|||
|
||||
for (const subtest of gKeyframesTests) {
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate(subtest.input, 2000);
|
||||
const anim = createDiv(t).animate(subtest.input, 2000);
|
||||
assert_frame_lists_equal(anim.effect.getKeyframes(), subtest.output);
|
||||
}, `Element.animate() accepts ${subtest.desc}`);
|
||||
}
|
||||
|
@ -99,54 +82,101 @@ for (const subtest of gInvalidKeyframesTests) {
|
|||
}, `Element.animate() does not accept ${subtest.desc}`);
|
||||
}
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 2000);
|
||||
assert_equals(anim.effect.getTiming().duration, 2000);
|
||||
assert_default_timing_except(anim.effect, ['duration']);
|
||||
}, 'Element.animate() accepts a double as an options argument');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null,
|
||||
{ duration: Infinity, fill: 'forwards' });
|
||||
assert_equals(anim.effect.getTiming().duration, Infinity);
|
||||
assert_equals(anim.effect.getTiming().fill, 'forwards');
|
||||
assert_default_timing_except(anim.effect, ['duration', 'fill']);
|
||||
}, 'Element.animate() accepts a KeyframeAnimationOptions argument');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_default_timing_except(anim.effect, []);
|
||||
}, 'Element.animate() accepts an absent options argument');
|
||||
|
||||
for (const invalid of gBadDelayValues) {
|
||||
test(t => {
|
||||
assert_throws(new TypeError, () => {
|
||||
createDiv(t).animate(null, { delay: invalid });
|
||||
});
|
||||
}, `Element.animate() does not accept invalid delay value: ${invalid}`);
|
||||
}
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, { duration: 'auto' });
|
||||
assert_equals(anim.effect.getTiming().duration, 'auto', 'set duration \'auto\'');
|
||||
assert_equals(anim.effect.getComputedTiming().duration, 0,
|
||||
'getComputedTiming() after set duration \'auto\'');
|
||||
}, 'Element.animate() accepts a duration of \'auto\' using a dictionary'
|
||||
+ ' object');
|
||||
|
||||
for (const invalid of gBadDurationValues) {
|
||||
if (typeof invalid === 'string' && !isNaN(parseFloat(invalid))) {
|
||||
continue;
|
||||
}
|
||||
test(t => {
|
||||
assert_throws(new TypeError, () => {
|
||||
createDiv(t).animate(null, invalid);
|
||||
});
|
||||
}, 'Element.animate() does not accept invalid duration value: '
|
||||
+ (typeof invalid === 'string' ? `"${invalid}"` : invalid));
|
||||
}
|
||||
|
||||
for (const invalid of gBadDurationValues) {
|
||||
test(t => {
|
||||
assert_throws(new TypeError, () => {
|
||||
createDiv(t).animate(null, { duration: invalid });
|
||||
});
|
||||
}, 'Element.animate() does not accept invalid duration value: '
|
||||
+ (typeof invalid === 'string' ? `"${invalid}"` : invalid)
|
||||
+ ' using a dictionary object');
|
||||
}
|
||||
|
||||
for (const invalidEasing of gInvalidEasings) {
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
assert_throws(new TypeError, () => {
|
||||
div.animate({ easing: invalidEasing }, 2000);
|
||||
createDiv(t).animate({ easing: invalidEasing }, 2000);
|
||||
});
|
||||
}, `Element.animate() does not accept invalid easing: '${invalidEasing}'`);
|
||||
}
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_equals(anim.effect.timing.duration, 2000);
|
||||
// Also check that unspecified parameters receive their default values
|
||||
assert_equals(anim.effect.timing.fill, 'auto');
|
||||
}, 'Element.animate() accepts a double as an options argument');
|
||||
for (const invalid of gBadIterationStartValues) {
|
||||
test(t => {
|
||||
assert_throws(new TypeError, () => {
|
||||
createDiv(t).animate(null, { iterationStart: invalid });
|
||||
});
|
||||
}, 'Element.animate() does not accept invalid iterationStart value: ' +
|
||||
invalid);
|
||||
}
|
||||
|
||||
for (const invalid of gBadIterationsValues) {
|
||||
test(t => {
|
||||
assert_throws(new TypeError, () => {
|
||||
createDiv(t).animate(null, { iterations: invalid });
|
||||
});
|
||||
}, 'Element.animate() does not accept invalid iterations value: ' +
|
||||
invalid);
|
||||
}
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ duration: Infinity, fill: 'forwards' });
|
||||
assert_equals(anim.effect.timing.duration, Infinity);
|
||||
assert_equals(anim.effect.timing.fill, 'forwards');
|
||||
// Also check that unspecified parameters receive their default values
|
||||
assert_equals(anim.effect.timing.direction, 'normal');
|
||||
}, 'Element.animate() accepts a KeyframeAnimationOptions argument');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] });
|
||||
assert_equals(anim.effect.timing.duration, 'auto');
|
||||
}, 'Element.animate() accepts an absent options argument');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
const anim = createDiv(t).animate(null, 2000);
|
||||
assert_equals(anim.id, '');
|
||||
}, 'Element.animate() correctly sets the id attribute when no id is specified');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, { id: 'test' });
|
||||
const anim = createDiv(t).animate(null, { id: 'test' });
|
||||
assert_equals(anim.id, 'test');
|
||||
}, 'Element.animate() correctly sets the id attribute');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
const anim = createDiv(t).animate(null, 2000);
|
||||
assert_equals(anim.timeline, document.timeline);
|
||||
}, 'Element.animate() correctly sets the Animation\'s timeline');
|
||||
|
||||
|
@ -157,7 +187,7 @@ async_test(t => {
|
|||
|
||||
iframe.addEventListener('load', t.step_func(() => {
|
||||
const div = createDiv(t, iframe.contentDocument);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
const anim = div.animate(null, 2000);
|
||||
assert_equals(anim.timeline, iframe.contentDocument.timeline);
|
||||
iframe.remove();
|
||||
t.done();
|
||||
|
@ -168,8 +198,7 @@ async_test(t => {
|
|||
'triggered on an element in a different document');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
const anim = createDiv(t).animate(null, 2000);
|
||||
assert_equals(anim.playState, 'running');
|
||||
}, 'Element.animate() calls play on the Animation');
|
||||
|
||||
|
|
|
@ -75,12 +75,14 @@ test(t => {
|
|||
assert_array_equals(div.getAnimations(), [],
|
||||
'Animation should not be returned when it is finished');
|
||||
|
||||
animation.effect.timing.duration += 100 * MS_PER_SEC;
|
||||
animation.effect.updateTiming({
|
||||
duration: animation.effect.getTiming().duration + 100 * MS_PER_SEC,
|
||||
});
|
||||
assert_array_equals(div.getAnimations(), [animation],
|
||||
'Animation should be returned after extending the'
|
||||
+ ' duration');
|
||||
|
||||
animation.effect.timing.duration = 0;
|
||||
animation.effect.updateTiming({ duration: 0 });
|
||||
assert_array_equals(div.getAnimations(), [],
|
||||
'Animation should not be returned after setting the'
|
||||
+ ' duration to zero');
|
||||
|
@ -91,13 +93,13 @@ test(t => {
|
|||
const div = createDiv(t);
|
||||
const animation = div.animate(null, 100 * MS_PER_SEC);
|
||||
|
||||
animation.effect.timing.endDelay = -200 * MS_PER_SEC;
|
||||
animation.effect.updateTiming({ endDelay: -200 * MS_PER_SEC });
|
||||
assert_array_equals(div.getAnimations(), [],
|
||||
'Animation should not be returned after setting a'
|
||||
+ ' negative end delay such that the end time is less'
|
||||
+ ' than the current time');
|
||||
|
||||
animation.effect.timing.endDelay = 100 * MS_PER_SEC;
|
||||
animation.effect.updateTiming({ endDelay: 100 * MS_PER_SEC });
|
||||
assert_array_equals(div.getAnimations(), [animation],
|
||||
'Animation should be returned after setting a positive'
|
||||
+ ' end delay such that the end time is more than the'
|
||||
|
@ -113,17 +115,17 @@ test(t => {
|
|||
assert_array_equals(div.getAnimations(), [],
|
||||
'Animation should not be returned when it is finished');
|
||||
|
||||
animation.effect.timing.iterations = 10;
|
||||
animation.effect.updateTiming({ iterations: 10 });
|
||||
assert_array_equals(div.getAnimations(), [animation],
|
||||
'Animation should be returned after inreasing the'
|
||||
+ ' number of iterations');
|
||||
|
||||
animation.effect.timing.iterations = 0;
|
||||
animation.effect.updateTiming({ iterations: 0 });
|
||||
assert_array_equals(div.getAnimations(), [],
|
||||
'Animations should not be returned after setting the'
|
||||
+ ' iteration count to zero');
|
||||
|
||||
animation.effect.timing.iterations = Infinity;
|
||||
animation.effect.updateTiming({ iterations: Infinity });
|
||||
assert_array_equals(div.getAnimations(), [animation],
|
||||
'Animation should be returned after inreasing the'
|
||||
+ ' number of iterations to infinity');
|
||||
|
|
|
@ -29,7 +29,7 @@ test(t => {
|
|||
const div = createDiv(t);
|
||||
const animation = div.animate({ marginLeft: ['100px', '200px'] },
|
||||
100 * MS_PER_SEC);
|
||||
animation.effect.timing.easing = 'linear';
|
||||
animation.effect.updateTiming({ easing: 'linear' });
|
||||
animation.cancel();
|
||||
assert_equals(getComputedStyle(div).marginLeft, '0px',
|
||||
'margin-left style is not animated after cancelling');
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
const gTarget = document.getElementById('target');
|
||||
|
||||
function createEffect() {
|
||||
return new KeyframeEffectReadOnly(gTarget, { opacity: [0, 1] });
|
||||
return new KeyframeEffect(gTarget, { opacity: [0, 1] });
|
||||
}
|
||||
|
||||
function createNull() {
|
||||
|
@ -82,10 +82,9 @@ for (const args of gTestArguments) {
|
|||
}
|
||||
|
||||
test(t => {
|
||||
const effect = new KeyframeEffectReadOnly(null,
|
||||
{ left: ['10px', '20px'] },
|
||||
{ duration: 10000,
|
||||
fill: 'forwards' });
|
||||
const effect = new KeyframeEffect(null,
|
||||
{ left: ['10px', '20px'] },
|
||||
{ duration: 10000, fill: 'forwards' });
|
||||
const anim = new Animation(effect, document.timeline);
|
||||
anim.pause();
|
||||
assert_equals(effect.getComputedTiming().progress, 0.0);
|
||||
|
@ -100,7 +99,7 @@ async_test(t => {
|
|||
|
||||
iframe.addEventListener('load', t.step_func(() => {
|
||||
const div = createDiv(t, iframe.contentDocument);
|
||||
const effect = new KeyframeEffectReadOnly(div, null, 10000);
|
||||
const effect = new KeyframeEffect(div, null, 10000);
|
||||
const anim = new Animation(effect);
|
||||
assert_equals(anim.timeline, document.timeline);
|
||||
iframe.remove();
|
||||
|
|
|
@ -14,7 +14,7 @@ test(t => {
|
|||
const anim = new Animation();
|
||||
assert_equals(anim.effect, null, 'initial effect is null');
|
||||
|
||||
const newEffect = new KeyframeEffectReadOnly(createDiv(t), null);
|
||||
const newEffect = new KeyframeEffect(createDiv(t), null);
|
||||
anim.effect = newEffect;
|
||||
assert_equals(anim.effect, newEffect, 'new effect is set');
|
||||
}, 'effect is set correctly.');
|
||||
|
|
|
@ -189,7 +189,7 @@ promise_test(t => {
|
|||
animation.currentTime = HALF_DUR;
|
||||
return animation.ready.then(() => {
|
||||
currentTimeBeforeShortening = animation.currentTime;
|
||||
animation.effect.timing.duration = QUARTER_DUR;
|
||||
animation.effect.updateTiming({ 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
|
||||
|
@ -206,7 +206,7 @@ promise_test(t => {
|
|||
assert_equals(animation.currentTime, currentTimeBeforeShortening,
|
||||
'currentTime should be unchanged when duration shortened');
|
||||
const previousFinishedPromise = animation.finished;
|
||||
animation.effect.timing.duration = 100 * MS_PER_SEC;
|
||||
animation.effect.updateTiming({ 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');
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
<script type="text/plain" id="Animation-IDL">
|
||||
enum AnimationPlayState { "idle", "pending", "running", "paused", "finished" };
|
||||
|
||||
[Constructor (optional AnimationEffectReadOnly? effect = null,
|
||||
[Constructor (optional AnimationEffect? effect = null,
|
||||
optional AnimationTimeline? timeline)]
|
||||
interface Animation : EventTarget {
|
||||
attribute DOMString id;
|
||||
attribute AnimationEffectReadOnly? effect;
|
||||
attribute AnimationEffect? effect;
|
||||
attribute AnimationTimeline? timeline;
|
||||
attribute double? startTime;
|
||||
attribute double? currentTime;
|
||||
|
|
|
@ -195,7 +195,5 @@ for (const stest of gEndTimeTests) {
|
|||
|
||||
}, `getComputedTiming().endTime for ${stest.desc}`);
|
||||
}
|
||||
|
||||
done();
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,475 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>AnimationEffect.updateTiming</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/web-animations-1/#dom-animationeffect-updatetiming">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<script src="../../resources/easing-tests.js"></script>
|
||||
<script src="../../resources/timing-tests.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
// ------------------------------
|
||||
// delay
|
||||
// ------------------------------
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 100);
|
||||
anim.effect.updateTiming({ delay: 100 });
|
||||
assert_equals(anim.effect.getTiming().delay, 100, 'set delay 100');
|
||||
assert_equals(anim.effect.getComputedTiming().delay, 100,
|
||||
'getComputedTiming() after set delay 100');
|
||||
}, 'Allows setting the delay to a positive number');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 100);
|
||||
anim.effect.updateTiming({ delay: -100 });
|
||||
assert_equals(anim.effect.getTiming().delay, -100, 'set delay -100');
|
||||
assert_equals(anim.effect.getComputedTiming().delay, -100,
|
||||
'getComputedTiming() after set delay -100');
|
||||
}, 'Allows setting the delay to a negative number');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 100);
|
||||
anim.effect.updateTiming({ delay: 100 });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, null);
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, null);
|
||||
}, 'Allows setting the delay of an animation in progress: positive delay that'
|
||||
+ ' causes the animation to be no longer in-effect');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, { fill: 'both', duration: 100 });
|
||||
anim.effect.updateTiming({ delay: -50 });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0.5);
|
||||
}, 'Allows setting the delay of an animation in progress: negative delay that'
|
||||
+ ' seeks into the active interval');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, { fill: 'both', duration: 100 });
|
||||
anim.effect.updateTiming({ delay: -100 });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1);
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 0);
|
||||
}, 'Allows setting the delay of an animation in progress: large negative delay'
|
||||
+ ' that causes the animation to be finished');
|
||||
|
||||
for (const invalid of gBadDelayValues) {
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.updateTiming({ delay: invalid });
|
||||
});
|
||||
}, `Throws when setting invalid delay value: ${invalid}`);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------
|
||||
// endDelay
|
||||
// ------------------------------
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 2000);
|
||||
anim.effect.updateTiming({ endDelay: 123.45 });
|
||||
assert_time_equals_literal(anim.effect.getTiming().endDelay, 123.45,
|
||||
'set endDelay 123.45');
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().endDelay, 123.45,
|
||||
'getComputedTiming() after set endDelay 123.45');
|
||||
}, 'Allows setting the endDelay to a positive number');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 2000);
|
||||
anim.effect.updateTiming({ endDelay: -1000 });
|
||||
assert_equals(anim.effect.getTiming().endDelay, -1000, 'set endDelay -1000');
|
||||
assert_equals(anim.effect.getComputedTiming().endDelay, -1000,
|
||||
'getComputedTiming() after set endDelay -1000');
|
||||
}, 'Allows setting the endDelay to a negative number');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 2000);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.updateTiming({ endDelay: Infinity });
|
||||
});
|
||||
}, 'Throws when setting the endDelay to infinity');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 2000);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.updateTiming({ endDelay: -Infinity });
|
||||
});
|
||||
}, 'Throws when setting the endDelay to negative infinity');
|
||||
|
||||
|
||||
// ------------------------------
|
||||
// fill
|
||||
// ------------------------------
|
||||
|
||||
for (const fill of ['none', 'forwards', 'backwards', 'both']) {
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 100);
|
||||
anim.effect.updateTiming({ fill });
|
||||
assert_equals(anim.effect.getTiming().fill, fill, 'set fill ' + fill);
|
||||
assert_equals(anim.effect.getComputedTiming().fill, fill,
|
||||
'getComputedTiming() after set fill ' + fill);
|
||||
}, `Allows setting the fill to '${fill}'`);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------
|
||||
// iterationStart
|
||||
// ------------------------------
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null,
|
||||
{ iterationStart: 0.2,
|
||||
iterations: 1,
|
||||
fill: 'both',
|
||||
duration: 100,
|
||||
delay: 1 });
|
||||
anim.effect.updateTiming({ iterationStart: 2.5 });
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
|
||||
}, 'Allows setting the iterationStart of an animation in progress:'
|
||||
+ ' backwards-filling');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null,
|
||||
{ iterationStart: 0.2,
|
||||
iterations: 1,
|
||||
fill: 'both',
|
||||
duration: 100,
|
||||
delay: 0 });
|
||||
anim.effect.updateTiming({ iterationStart: 2.5 });
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
|
||||
}, 'Allows setting the iterationStart of an animation in progress:'
|
||||
+ ' active phase');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null,
|
||||
{ iterationStart: 0.2,
|
||||
iterations: 1,
|
||||
fill: 'both',
|
||||
duration: 100,
|
||||
delay: 0 });
|
||||
anim.finish();
|
||||
anim.effect.updateTiming({ iterationStart: 2.5 });
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 3);
|
||||
}, 'Allows setting the iterationStart of an animation in progress:'
|
||||
+ ' forwards-filling');
|
||||
|
||||
for (const invalid of gBadIterationStartValues) {
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.updateTiming({ iterationStart: invalid });
|
||||
}, `setting ${invalid}`);
|
||||
}, `Throws when setting invalid iterationStart value: ${invalid}`);
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// iterations
|
||||
// ------------------------------
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 2000);
|
||||
anim.effect.updateTiming({ iterations: 2 });
|
||||
assert_equals(anim.effect.getTiming().iterations, 2, 'set duration 2');
|
||||
assert_equals(anim.effect.getComputedTiming().iterations, 2,
|
||||
'getComputedTiming() after set iterations 2');
|
||||
}, 'Allows setting iterations to a double value');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 2000);
|
||||
anim.effect.updateTiming({ iterations: Infinity });
|
||||
assert_equals(anim.effect.getTiming().iterations, Infinity,
|
||||
'set duration Infinity');
|
||||
assert_equals(anim.effect.getComputedTiming().iterations, Infinity,
|
||||
'getComputedTiming() after set iterations Infinity');
|
||||
}, 'Allows setting iterations to infinity');
|
||||
|
||||
for (const invalid of gBadIterationsValues) {
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.updateTiming({ iterations: invalid });
|
||||
});
|
||||
}, `Throws when setting invalid iterations value: ${invalid}`);
|
||||
}
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, { duration: 100000, fill: 'both' });
|
||||
|
||||
anim.finish();
|
||||
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'progress when animation is finished');
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
|
||||
'current iteration when animation is finished');
|
||||
|
||||
anim.effect.updateTiming({ iterations: 2 });
|
||||
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress,
|
||||
0,
|
||||
'progress after adding an iteration');
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().currentIteration,
|
||||
1,
|
||||
'current iteration after adding an iteration');
|
||||
|
||||
anim.effect.updateTiming({ iterations: 0 });
|
||||
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0,
|
||||
'progress after setting iterations to zero');
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
|
||||
'current iteration after setting iterations to zero');
|
||||
|
||||
anim.effect.updateTiming({ iterations: Infinity });
|
||||
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0,
|
||||
'progress after setting iterations to Infinity');
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 1,
|
||||
'current iteration after setting iterations to Infinity');
|
||||
}, 'Allows setting the iterations of an animation in progress');
|
||||
|
||||
|
||||
// ------------------------------
|
||||
// duration
|
||||
// ------------------------------
|
||||
|
||||
for (const duration of gGoodDurationValues) {
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 2000);
|
||||
anim.effect.updateTiming({ duration: duration.specified });
|
||||
if (typeof duration.specified === 'number') {
|
||||
assert_time_equals_literal(anim.effect.getTiming().duration,
|
||||
duration.specified,
|
||||
'Updates specified duration');
|
||||
} else {
|
||||
assert_equals(anim.effect.getTiming().duration, duration.specified,
|
||||
'Updates specified duration');
|
||||
}
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().duration,
|
||||
duration.computed,
|
||||
'Updates computed duration');
|
||||
}, `Allows setting the duration to ${duration.specified}`);
|
||||
}
|
||||
|
||||
for (const invalid of gBadDurationValues) {
|
||||
test(t => {
|
||||
assert_throws(new TypeError, () => {
|
||||
createDiv(t).animate(null, { duration: invalid });
|
||||
});
|
||||
}, 'Throws when setting invalid duration: '
|
||||
+ (typeof invalid === 'string' ? `"${invalid}"` : invalid));
|
||||
}
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, { duration: 100000, fill: 'both' });
|
||||
anim.finish();
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'progress when animation is finished');
|
||||
anim.effect.updateTiming({ duration: anim.effect.getTiming().duration * 2 });
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5,
|
||||
'progress after doubling the duration');
|
||||
anim.effect.updateTiming({ duration: 0 });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'progress after setting duration to zero');
|
||||
anim.effect.updateTiming({ duration: 'auto' });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'progress after setting duration to \'auto\'');
|
||||
}, 'Allows setting the duration of an animation in progress');
|
||||
|
||||
promise_test(t => {
|
||||
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
return anim.ready.then(() => {
|
||||
const originalStartTime = anim.startTime;
|
||||
const originalCurrentTime = anim.currentTime;
|
||||
assert_time_equals_literal(
|
||||
anim.effect.getComputedTiming().duration,
|
||||
100 * MS_PER_SEC,
|
||||
'Initial duration should be as set on KeyframeEffect'
|
||||
);
|
||||
|
||||
anim.effect.updateTiming({ duration: 200 * MS_PER_SEC });
|
||||
assert_time_equals_literal(
|
||||
anim.effect.getComputedTiming().duration,
|
||||
200 * MS_PER_SEC,
|
||||
'Effect duration should have been updated'
|
||||
);
|
||||
assert_times_equal(anim.startTime, originalStartTime,
|
||||
'startTime should be unaffected by changing effect ' +
|
||||
'duration');
|
||||
assert_times_equal(anim.currentTime, originalCurrentTime,
|
||||
'currentTime should be unaffected by changing effect ' +
|
||||
'duration');
|
||||
});
|
||||
}, 'Allows setting the duration of an animation in progress such that the' +
|
||||
' the start and current time do not change');
|
||||
|
||||
|
||||
// ------------------------------
|
||||
// direction
|
||||
// ------------------------------
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, 2000);
|
||||
|
||||
const directions = ['normal', 'reverse', 'alternate', 'alternate-reverse'];
|
||||
for (const direction of directions) {
|
||||
anim.effect.updateTiming({ direction: direction });
|
||||
assert_equals(anim.effect.getTiming().direction, direction,
|
||||
`set direction to ${direction}`);
|
||||
}
|
||||
}, 'Allows setting the direction to each of the possible keywords');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null, {
|
||||
duration: 10000,
|
||||
direction: 'normal',
|
||||
});
|
||||
anim.currentTime = 7000;
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
|
||||
'progress before updating direction');
|
||||
|
||||
anim.effect.updateTiming({ direction: 'reverse' });
|
||||
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
|
||||
'progress after updating direction');
|
||||
}, 'Allows setting the direction of an animation in progress from \'normal\' to'
|
||||
+ ' \'reverse\'');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null,
|
||||
{ duration: 10000, direction: 'normal' });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0,
|
||||
'progress before updating direction');
|
||||
|
||||
anim.effect.updateTiming({ direction: 'reverse' });
|
||||
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'progress after updating direction');
|
||||
}, 'Allows setting the direction of an animation in progress from \'normal\' to'
|
||||
+ ' \'reverse\' while at start of active interval');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null,
|
||||
{ fill: 'backwards',
|
||||
duration: 10000,
|
||||
delay: 10000,
|
||||
direction: 'normal' });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0,
|
||||
'progress before updating direction');
|
||||
|
||||
anim.effect.updateTiming({ direction: 'reverse' });
|
||||
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'progress after updating direction');
|
||||
}, 'Allows setting the direction of an animation in progress from \'normal\' to'
|
||||
+ ' \'reverse\' while filling backwards');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null,
|
||||
{ iterations: 2,
|
||||
duration: 10000,
|
||||
direction: 'normal' });
|
||||
anim.currentTime = 17000;
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
|
||||
'progress before updating direction');
|
||||
|
||||
anim.effect.updateTiming({ direction: 'alternate' });
|
||||
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
|
||||
'progress after updating direction');
|
||||
}, 'Allows setting the direction of an animation in progress from \'normal\' to'
|
||||
+ ' \'alternate\'');
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null,
|
||||
{ iterations: 2,
|
||||
duration: 10000,
|
||||
direction: 'alternate' });
|
||||
anim.currentTime = 17000;
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
|
||||
'progress before updating direction');
|
||||
|
||||
anim.effect.updateTiming({ direction: 'alternate-reverse' });
|
||||
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
|
||||
'progress after updating direction');
|
||||
}, 'Allows setting the direction of an animation in progress from \'alternate\''
|
||||
+ ' to \'alternate-reverse\'');
|
||||
|
||||
|
||||
// ------------------------------
|
||||
// easing
|
||||
// ------------------------------
|
||||
|
||||
function assert_progress(animation, currentTime, easingFunction) {
|
||||
animation.currentTime = currentTime;
|
||||
const portion = currentTime / animation.effect.getTiming().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`);
|
||||
}
|
||||
|
||||
for (const options of gEasingTests) {
|
||||
test(t => {
|
||||
const target = createDiv(t);
|
||||
const anim = target.animate(null,
|
||||
{ duration: 1000 * MS_PER_SEC,
|
||||
fill: 'forwards' });
|
||||
anim.effect.updateTiming({ easing: options.easing });
|
||||
assert_equals(anim.effect.getTiming().easing,
|
||||
options.serialization || options.easing);
|
||||
|
||||
const 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);
|
||||
}, `Allows setting the easing to a ${options.desc}`);
|
||||
}
|
||||
|
||||
for (const easing of gRoundtripEasings) {
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
anim.effect.updateTiming({ easing: easing });
|
||||
assert_equals(anim.effect.getTiming().easing, easing);
|
||||
}, `Updates the specified value when setting the easing to '${easing}'`);
|
||||
}
|
||||
|
||||
test(t => {
|
||||
const delay = 1000 * MS_PER_SEC;
|
||||
|
||||
const target = createDiv(t);
|
||||
const anim = target.animate(null,
|
||||
{ duration: 1000 * MS_PER_SEC,
|
||||
fill: 'both',
|
||||
delay: delay,
|
||||
easing: 'steps(2, start)' });
|
||||
|
||||
anim.effect.updateTiming({ 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.updateTiming({ 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.updateTiming({ easing: 'steps(2, end)' });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'easing replace to steps(2, end) again at after phase');
|
||||
}, 'Allows setting the easing of an animation in progress');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,78 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>AnimationEffectTiming.delay</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-delay">
|
||||
<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(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_equals(anim.effect.timing.delay, 0);
|
||||
}, 'Has the default value 0');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
|
||||
anim.effect.timing.delay = 100;
|
||||
assert_equals(anim.effect.timing.delay, 100, 'set delay 100');
|
||||
assert_equals(anim.effect.getComputedTiming().delay, 100,
|
||||
'getComputedTiming() after set delay 100');
|
||||
}, 'Can be set to a positive number');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
|
||||
anim.effect.timing.delay = -100;
|
||||
assert_equals(anim.effect.timing.delay, -100, 'set delay -100');
|
||||
assert_equals(anim.effect.getComputedTiming().delay, -100,
|
||||
'getComputedTiming() after set delay -100');
|
||||
}, 'Can be set to a negative number');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
|
||||
anim.effect.timing.delay = 100;
|
||||
assert_equals(anim.effect.getComputedTiming().progress, null);
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, null);
|
||||
}, 'Can set a positive delay on an animation without a backwards fill to'
|
||||
+ ' make it no longer active');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ fill: 'both',
|
||||
duration: 100 });
|
||||
anim.effect.timing.delay = -50;
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0.5);
|
||||
}, 'Can set a negative delay to seek into the active interval');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ fill: 'both',
|
||||
duration: 100 });
|
||||
anim.effect.timing.delay = -100;
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1);
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 0);
|
||||
}, 'Can set a large negative delay to finishing an animation');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate(null);
|
||||
for (let invalid of [NaN, Infinity]) {
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.timing.delay = invalid;
|
||||
}, `setting ${invalid}`);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
div.animate({}, { delay: invalid });
|
||||
}, `animate() with ${invalid}`);
|
||||
}
|
||||
}, 'Throws when setting invalid values');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,108 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>AnimationEffectTiming.direction</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-direction">
|
||||
<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(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_equals(anim.effect.timing.direction, 'normal');
|
||||
}, 'Has the default value \'normal\'');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
|
||||
const directions = ['normal', 'reverse', 'alternate', 'alternate-reverse'];
|
||||
for (const direction of directions) {
|
||||
anim.effect.timing.direction = direction;
|
||||
assert_equals(anim.effect.timing.direction, direction,
|
||||
`set direction to ${direction}`);
|
||||
}
|
||||
}, 'Can be set to each of the possible keywords');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate(null, { duration: 10000, direction: 'normal' });
|
||||
anim.currentTime = 7000;
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
|
||||
'progress before updating direction');
|
||||
|
||||
anim.effect.timing.direction = 'reverse';
|
||||
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
|
||||
'progress after updating direction');
|
||||
}, 'Can be changed from \'normal\' to \'reverse\' while in progress');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ duration: 10000,
|
||||
direction: 'normal' });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0,
|
||||
'progress before updating direction');
|
||||
|
||||
anim.effect.timing.direction = 'reverse';
|
||||
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'progress after updating direction');
|
||||
}, 'Can be changed from \'normal\' to \'reverse\' while at start of active'
|
||||
+ ' interval');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ fill: 'backwards',
|
||||
duration: 10000,
|
||||
delay: 10000,
|
||||
direction: 'normal' });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0,
|
||||
'progress before updating direction');
|
||||
|
||||
anim.effect.timing.direction = 'reverse';
|
||||
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'progress after updating direction');
|
||||
}, 'Can be changed from \'normal\' to \'reverse\' while filling backwards');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ iterations: 2,
|
||||
duration: 10000,
|
||||
direction: 'normal' });
|
||||
anim.currentTime = 17000;
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
|
||||
'progress before updating direction');
|
||||
|
||||
anim.effect.timing.direction = 'alternate';
|
||||
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
|
||||
'progress after updating direction');
|
||||
}, 'Can be changed from \'normal\' to \'alternate\' while in progress');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ iterations: 2,
|
||||
duration: 10000,
|
||||
direction: 'alternate' });
|
||||
anim.currentTime = 17000;
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
|
||||
'progress before updating direction');
|
||||
|
||||
anim.effect.timing.direction = 'alternate-reverse';
|
||||
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
|
||||
'progress after updating direction');
|
||||
}, 'Can be changed from \'alternate\' to \'alternate-reverse\' while in'
|
||||
+ ' progress');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,190 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>AnimationEffectTiming.duration</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-duration">
|
||||
<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(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_equals(anim.effect.timing.duration, 'auto');
|
||||
}, 'Has the default value \'auto\'');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
anim.effect.timing.duration = 123.45;
|
||||
assert_time_equals_literal(anim.effect.timing.duration, 123.45,
|
||||
'set duration 123.45');
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().duration, 123.45,
|
||||
'getComputedTiming() after set duration 123.45');
|
||||
}, 'Can be set to a double value');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
anim.effect.timing.duration = 'auto';
|
||||
assert_equals(anim.effect.timing.duration, 'auto', 'set duration \'auto\'');
|
||||
assert_equals(anim.effect.getComputedTiming().duration, 0,
|
||||
'getComputedTiming() after set duration \'auto\'');
|
||||
}, 'Can be set to the string \'auto\'');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, { duration: 'auto' });
|
||||
assert_equals(anim.effect.timing.duration, 'auto', 'set duration \'auto\'');
|
||||
assert_equals(anim.effect.getComputedTiming().duration, 0,
|
||||
'getComputedTiming() after set duration \'auto\'');
|
||||
}, 'Can be set to \'auto\' using a dictionary object');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
anim.effect.timing.duration = Infinity;
|
||||
assert_equals(anim.effect.timing.duration, Infinity, 'set duration Infinity');
|
||||
assert_equals(anim.effect.getComputedTiming().duration, Infinity,
|
||||
'getComputedTiming() after set duration Infinity');
|
||||
}, 'Can be set to Infinity');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
div.animate({ opacity: [ 0, 1 ] }, -1);
|
||||
});
|
||||
}, 'animate() throws when passed a negative number');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
div.animate({ opacity: [ 0, 1 ] }, -Infinity);
|
||||
});
|
||||
}, 'animate() throws when passed negative Infinity');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
div.animate({ opacity: [ 0, 1 ] }, NaN);
|
||||
});
|
||||
}, 'animate() throws when passed a NaN value');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
div.animate({ opacity: [ 0, 1 ] }, { duration: -1 });
|
||||
});
|
||||
}, 'animate() throws when passed a negative number using a dictionary object');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
div.animate({ opacity: [ 0, 1 ] }, { duration: -Infinity });
|
||||
});
|
||||
}, 'animate() throws when passed negative Infinity using a dictionary object');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
div.animate({ opacity: [ 0, 1 ] }, { duration: NaN });
|
||||
});
|
||||
}, 'animate() throws when passed a NaN value using a dictionary object');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
div.animate({ opacity: [ 0, 1 ] }, { duration: 'abc' });
|
||||
});
|
||||
}, 'animate() throws when passed a string other than \'auto\' using a'
|
||||
+ ' dictionary object');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
div.animate({ opacity: [ 0, 1 ] }, { duration: '100' });
|
||||
});
|
||||
}, 'animate() throws when passed a string containing a number using a'
|
||||
+ ' dictionary object');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.timing.duration = -1;
|
||||
});
|
||||
}, 'Throws when setting a negative number');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.timing.duration = -Infinity;
|
||||
});
|
||||
}, 'Throws when setting negative infinity');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.timing.duration = NaN;
|
||||
});
|
||||
}, 'Throws when setting a NaN value');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.timing.duration = 'abc';
|
||||
});
|
||||
}, 'Throws when setting a string other than \'auto\'');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.timing.duration = '100';
|
||||
});
|
||||
}, 'Throws when setting a string containing a number');
|
||||
|
||||
promise_test(t => {
|
||||
const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
return anim.ready.then(() => {
|
||||
const originalStartTime = anim.startTime;
|
||||
const originalCurrentTime = anim.currentTime;
|
||||
assert_equals(anim.effect.getComputedTiming().duration, 100 * MS_PER_SEC,
|
||||
'Initial duration should be as set on KeyframeEffect');
|
||||
|
||||
anim.effect.timing.duration = 200 * MS_PER_SEC;
|
||||
assert_equals(anim.effect.getComputedTiming().duration, 200 * MS_PER_SEC,
|
||||
'Effect duration should have been updated');
|
||||
assert_times_equal(anim.startTime, originalStartTime,
|
||||
'startTime should be unaffected by changing effect ' +
|
||||
'duration');
|
||||
assert_times_equal(anim.currentTime, originalCurrentTime,
|
||||
'currentTime should be unaffected by changing effect ' +
|
||||
'duration');
|
||||
});
|
||||
}, 'Extending an effect\'s duration does not change the start or current time');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate(null, { duration: 100000, fill: 'both' });
|
||||
anim.finish();
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'progress when animation is finished');
|
||||
anim.effect.timing.duration *= 2;
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5,
|
||||
'progress after doubling the duration');
|
||||
anim.effect.timing.duration = 0;
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'progress after setting duration to zero');
|
||||
anim.effect.timing.duration = 'auto';
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'progress after setting duration to \'auto\'');
|
||||
}, 'Can be updated while the animation is in progress');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,96 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>AnimationEffectTiming.easing</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/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/easing-tests.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_equals(anim.effect.timing.easing, 'linear');
|
||||
}, 'Has the default value \'linear\'');
|
||||
|
||||
function assert_progress(animation, currentTime, easingFunction) {
|
||||
animation.currentTime = currentTime;
|
||||
const 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`);
|
||||
}
|
||||
|
||||
for (const options of gEasingTests) {
|
||||
test(t => {
|
||||
const target = createDiv(t);
|
||||
const 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.serialization || options.easing);
|
||||
|
||||
const 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);
|
||||
}
|
||||
|
||||
for (const invalidEasing of gInvalidEasings) {
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
|
||||
assert_throws({ name: 'TypeError' },
|
||||
() => {
|
||||
anim.effect.timing.easing = invalidEasing;
|
||||
});
|
||||
}, `Throws on invalid easing: '${invalidEasing}'`);
|
||||
}
|
||||
|
||||
for (const easing of gRoundtripEasings) {
|
||||
test(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
anim.effect.timing.easing = easing;
|
||||
assert_equals(anim.effect.timing.easing, easing);
|
||||
}, `Canonical easing '${easing}' is returned as set`);
|
||||
}
|
||||
|
||||
test(t => {
|
||||
const delay = 1000 * MS_PER_SEC;
|
||||
|
||||
const target = createDiv(t);
|
||||
const 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');
|
||||
}, 'Allows the easing to be changed while the animation is in progress');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,89 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>AnimationEffectTiming.endDelay</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-enddelay">
|
||||
<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(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_equals(anim.effect.timing.endDelay, 0);
|
||||
}, 'Has the default value 0');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
anim.effect.timing.endDelay = 123.45;
|
||||
assert_time_equals_literal(anim.effect.timing.endDelay, 123.45,
|
||||
'set endDelay 123.45');
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().endDelay, 123.45,
|
||||
'getComputedTiming() after set endDelay 123.45');
|
||||
}, 'Can be set to a positive number');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
anim.effect.timing.endDelay = -1000;
|
||||
assert_equals(anim.effect.timing.endDelay, -1000, 'set endDelay -1000');
|
||||
assert_equals(anim.effect.getComputedTiming().endDelay, -1000,
|
||||
'getComputedTiming() after set endDelay -1000');
|
||||
}, 'Can be set to a negative number');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.timing.endDelay = Infinity;
|
||||
}, 'we can not assign Infinity to timing.endDelay');
|
||||
}, 'Throws when setting infinity');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.timing.endDelay = -Infinity;
|
||||
}, 'we can not assign negative Infinity to timing.endDelay');
|
||||
}, 'Throws when setting negative infinity');
|
||||
|
||||
async_test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ duration: 100000, endDelay: 50000 });
|
||||
anim.onfinish = t.step_func(event => {
|
||||
assert_unreached('finish event should not be fired');
|
||||
});
|
||||
|
||||
anim.ready.then(() => {
|
||||
anim.currentTime = 100000;
|
||||
return waitForAnimationFrames(2);
|
||||
}).then(t.step_func(() => {
|
||||
t.done();
|
||||
}));
|
||||
}, 'finish event is not fired at the end of the active interval when the'
|
||||
+ ' endDelay has not expired');
|
||||
|
||||
async_test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ duration: 100000, endDelay: 30000 });
|
||||
anim.ready.then(() => {
|
||||
anim.currentTime = 110000; // during endDelay
|
||||
anim.onfinish = t.step_func(event => {
|
||||
assert_unreached('onfinish event should not be fired during endDelay');
|
||||
});
|
||||
return waitForAnimationFrames(2);
|
||||
}).then(t.step_func(() => {
|
||||
anim.onfinish = t.step_func(event => {
|
||||
t.done();
|
||||
});
|
||||
anim.currentTime = 130000; // after endTime
|
||||
}));
|
||||
}, 'finish event is fired after the endDelay has expired');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,30 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>AnimationEffectTiming.fill</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-fill">
|
||||
<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(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_equals(anim.effect.timing.fill, 'auto');
|
||||
}, 'Has the default value \'auto\'');
|
||||
|
||||
for (const fill of ['none', 'forwards', 'backwards', 'both']) {
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const 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);
|
||||
}, `Can set fill to ${fill}`);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,80 +0,0 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>AnimationEffectTiming and AnimationEffectTimingReadOnly IDL</title>
|
||||
<link rel="help"
|
||||
href="https://drafts.csswg.org/web-animations/#animationeffecttiming">
|
||||
<link rel="help"
|
||||
href="https://drafts.csswg.org/web-animations/#animationeffecttimingreadonly">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/WebIDLParser.js"></script>
|
||||
<script src="/resources/idlharness.js"></script>
|
||||
<div id="log"></div>
|
||||
<script type="text/plain" id="AnimationEffectTimingReadOnly-IDL">
|
||||
enum FillMode { "none", "forwards", "backwards", "both", "auto" };
|
||||
enum PlaybackDirection {
|
||||
"normal",
|
||||
"reverse",
|
||||
"alternate",
|
||||
"alternate-reverse"
|
||||
};
|
||||
|
||||
dictionary AnimationEffectTimingProperties {
|
||||
double delay = 0.0;
|
||||
double endDelay = 0.0;
|
||||
FillMode fill = "auto";
|
||||
double iterationStart = 0.0;
|
||||
unrestricted double iterations = 1.0;
|
||||
(unrestricted double or DOMString) duration = "auto";
|
||||
PlaybackDirection direction = "normal";
|
||||
DOMString easing = "linear";
|
||||
};
|
||||
|
||||
[Exposed=Window]
|
||||
interface AnimationEffectTimingReadOnly {
|
||||
readonly attribute double delay;
|
||||
readonly attribute double endDelay;
|
||||
readonly attribute FillMode fill;
|
||||
readonly attribute double iterationStart;
|
||||
readonly attribute unrestricted double iterations;
|
||||
readonly attribute (unrestricted double or DOMString) duration;
|
||||
readonly attribute PlaybackDirection direction;
|
||||
readonly attribute DOMString easing;
|
||||
};
|
||||
</script>
|
||||
<script type="text/plain" id="AnimationEffectTiming-IDL">
|
||||
[Exposed=Window]
|
||||
interface AnimationEffectTiming : AnimationEffectTimingReadOnly {
|
||||
inherit attribute double delay;
|
||||
inherit attribute double endDelay;
|
||||
inherit attribute FillMode fill;
|
||||
inherit attribute double iterationStart;
|
||||
inherit attribute unrestricted double iterations;
|
||||
inherit attribute (unrestricted double or DOMString) duration;
|
||||
inherit attribute PlaybackDirection direction;
|
||||
inherit attribute DOMString easing;
|
||||
};
|
||||
</script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
const idlArray = new IdlArray();
|
||||
|
||||
idlArray.add_idls(
|
||||
document.getElementById('AnimationEffectTimingReadOnly-IDL').textContent
|
||||
);
|
||||
idlArray.add_idls(
|
||||
document.getElementById('AnimationEffectTiming-IDL').textContent
|
||||
);
|
||||
|
||||
idlArray.add_objects({
|
||||
AnimationEffectTiming: [
|
||||
'(new KeyframeEffect(null, null)).timing'
|
||||
],
|
||||
AnimationEffectTimingReadOnly: [
|
||||
'(new KeyframeEffectReadOnly(null, null)).timing'
|
||||
],
|
||||
});
|
||||
idlArray.test();
|
||||
|
||||
</script>
|
|
@ -1,72 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>AnimationEffectTiming.iterationStart</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-iterationstart">
|
||||
<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(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_equals(anim.effect.timing.iterationStart, 0);
|
||||
}, 'Has the default value 0');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ iterationStart: 0.2,
|
||||
iterations: 1,
|
||||
fill: 'both',
|
||||
duration: 100,
|
||||
delay: 1 });
|
||||
anim.effect.timing.iterationStart = 2.5;
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
|
||||
}, 'Changing the value updates computed timing when backwards-filling');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ iterationStart: 0.2,
|
||||
iterations: 1,
|
||||
fill: 'both',
|
||||
duration: 100,
|
||||
delay: 0 });
|
||||
anim.effect.timing.iterationStart = 2.5;
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
|
||||
}, 'Changing the value updates computed timing during the active phase');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ iterationStart: 0.2,
|
||||
iterations: 1,
|
||||
fill: 'both',
|
||||
duration: 100,
|
||||
delay: 0 });
|
||||
anim.finish();
|
||||
anim.effect.timing.iterationStart = 2.5;
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 3);
|
||||
}, 'Changing the value updates computed timing when forwards-filling');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate(null);
|
||||
for (let invalid of [-1, NaN, Infinity]) {
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.timing.iterationStart = invalid;
|
||||
}, `setting ${invalid}`);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
div.animate({}, { iterationStart: invalid });
|
||||
}, `animate() with ${invalid}`);
|
||||
}
|
||||
}, 'Throws when setting invalid values');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,96 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>AnimationEffectTiming.iterations</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-iterations">
|
||||
<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(t => {
|
||||
const anim = createDiv(t).animate(null);
|
||||
assert_equals(anim.effect.timing.iterations, 1);
|
||||
}, 'Has the default value 1');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
anim.effect.timing.iterations = 2;
|
||||
assert_equals(anim.effect.timing.iterations, 2, 'set duration 2');
|
||||
assert_equals(anim.effect.getComputedTiming().iterations, 2,
|
||||
'getComputedTiming() after set iterations 2');
|
||||
}, 'Can be set to a double value');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
anim.effect.timing.iterations = Infinity;
|
||||
assert_equals(anim.effect.timing.iterations, Infinity, 'set duration Infinity');
|
||||
assert_equals(anim.effect.getComputedTiming().iterations, Infinity,
|
||||
'getComputedTiming() after set iterations Infinity');
|
||||
}, 'Can be set to infinity');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.timing.iterations = -1;
|
||||
});
|
||||
}, 'Throws when setting a negative number');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.timing.iterations = -Infinity;
|
||||
});
|
||||
}, 'Throws when setting negative infinity');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
anim.effect.timing.iterations = NaN;
|
||||
});
|
||||
}, 'Throws when setting a NaN value');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const anim = div.animate(null, { duration: 100000, fill: 'both' });
|
||||
|
||||
anim.finish();
|
||||
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||
'progress when animation is finished');
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
|
||||
'current iteration when animation is finished');
|
||||
|
||||
anim.effect.timing.iterations = 2;
|
||||
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().progress,
|
||||
0,
|
||||
'progress after adding an iteration');
|
||||
assert_time_equals_literal(anim.effect.getComputedTiming().currentIteration,
|
||||
1,
|
||||
'current iteration after adding an iteration');
|
||||
|
||||
anim.effect.timing.iterations = 0;
|
||||
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0,
|
||||
'progress after setting iterations to zero');
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
|
||||
'current iteration after setting iterations to zero');
|
||||
|
||||
anim.effect.timing.iterations = Infinity;
|
||||
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0,
|
||||
'progress after setting iterations to Infinity');
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 1,
|
||||
'current iteration after setting iterations to Infinity');
|
||||
}, 'Can be updated while the animation is in progress');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -42,7 +42,7 @@ test(t => {
|
|||
}, 'Test the order of document.getAnimations with script generated animations')
|
||||
|
||||
test(t => {
|
||||
const effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
|
||||
const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
|
||||
const anim = new Animation(effect, document.timeline);
|
||||
anim.play();
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>KeyframeEffect and KeyframeEffectReadOnly constructor</title>
|
||||
<title>KeyframeEffect constructor</title>
|
||||
<link rel="help"
|
||||
href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-keyframeeffect">
|
||||
<link rel="help"
|
||||
|
@ -21,49 +21,48 @@ const target = document.getElementById('target');
|
|||
|
||||
test(t => {
|
||||
for (const frames of gEmptyKeyframeListTests) {
|
||||
assert_equals(new KeyframeEffectReadOnly(target, frames)
|
||||
.getKeyframes().length,
|
||||
assert_equals(new KeyframeEffect(target, frames).getKeyframes().length,
|
||||
0, `number of frames for ${JSON.stringify(frames)}`);
|
||||
}
|
||||
}, 'A KeyframeEffectReadOnly can be constructed with no frames');
|
||||
}, 'A KeyframeEffect can be constructed with no frames');
|
||||
|
||||
test(t => {
|
||||
for (const subtest of gEasingParsingTests) {
|
||||
const easing = subtest[0];
|
||||
const expected = subtest[1];
|
||||
const effect = new KeyframeEffectReadOnly(target, {
|
||||
const effect = new KeyframeEffect(target, {
|
||||
left: ['10px', '20px']
|
||||
}, { easing: easing });
|
||||
assert_equals(effect.timing.easing, expected,
|
||||
assert_equals(effect.getTiming().easing, expected,
|
||||
`resulting easing for '${easing}'`);
|
||||
}
|
||||
}, 'easing values are parsed correctly when passed to the ' +
|
||||
'KeyframeEffectReadOnly constructor in KeyframeEffectOptions');
|
||||
'KeyframeEffect constructor in KeyframeEffectOptions');
|
||||
|
||||
test(t => {
|
||||
for (const invalidEasing of gInvalidEasings) {
|
||||
assert_throws(new TypeError, () => {
|
||||
new KeyframeEffectReadOnly(target, null, { easing: invalidEasing });
|
||||
new KeyframeEffect(target, null, { easing: invalidEasing });
|
||||
}, `TypeError is thrown for easing '${invalidEasing}'`);
|
||||
}
|
||||
}, 'Invalid easing values are correctly rejected when passed to the ' +
|
||||
'KeyframeEffectReadOnly constructor in KeyframeEffectOptions');
|
||||
'KeyframeEffect constructor in KeyframeEffectOptions');
|
||||
|
||||
test(t => {
|
||||
const getKeyframe =
|
||||
composite => ({ left: [ '10px', '20px' ], composite: composite });
|
||||
for (const composite of gGoodKeyframeCompositeValueTests) {
|
||||
const effect = new KeyframeEffectReadOnly(target, getKeyframe(composite));
|
||||
const effect = new KeyframeEffect(target, getKeyframe(composite));
|
||||
assert_equals(effect.getKeyframes()[0].composite, composite,
|
||||
`resulting composite for '${composite}'`);
|
||||
}
|
||||
for (const composite of gBadKeyframeCompositeValueTests) {
|
||||
assert_throws(new TypeError, () => {
|
||||
new KeyframeEffectReadOnly(target, getKeyframe(composite));
|
||||
new KeyframeEffect(target, getKeyframe(composite));
|
||||
});
|
||||
}
|
||||
}, 'composite values are parsed correctly when passed to the ' +
|
||||
'KeyframeEffectReadOnly constructor in property-indexed keyframes');
|
||||
'KeyframeEffect constructor in property-indexed keyframes');
|
||||
|
||||
test(t => {
|
||||
const getKeyframes = composite =>
|
||||
|
@ -72,29 +71,29 @@ test(t => {
|
|||
{ offset: 1, left: '20px' }
|
||||
];
|
||||
for (const composite of gGoodKeyframeCompositeValueTests) {
|
||||
const effect = new KeyframeEffectReadOnly(target, getKeyframes(composite));
|
||||
const effect = new KeyframeEffect(target, getKeyframes(composite));
|
||||
assert_equals(effect.getKeyframes()[0].composite, composite,
|
||||
`resulting composite for '${composite}'`);
|
||||
}
|
||||
for (const composite of gBadKeyframeCompositeValueTests) {
|
||||
assert_throws(new TypeError, () => {
|
||||
new KeyframeEffectReadOnly(target, getKeyframes(composite));
|
||||
new KeyframeEffect(target, getKeyframes(composite));
|
||||
});
|
||||
}
|
||||
}, 'composite values are parsed correctly when passed to the ' +
|
||||
'KeyframeEffectReadOnly constructor in regular keyframes');
|
||||
'KeyframeEffect constructor in regular keyframes');
|
||||
|
||||
test(t => {
|
||||
for (const composite of gGoodOptionsCompositeValueTests) {
|
||||
const effect = new KeyframeEffectReadOnly(target, {
|
||||
const effect = new KeyframeEffect(target, {
|
||||
left: ['10px', '20px']
|
||||
}, { composite: composite });
|
||||
}, { composite });
|
||||
assert_equals(effect.getKeyframes()[0].composite, null,
|
||||
`resulting composite for '${composite}'`);
|
||||
}
|
||||
for (const composite of gBadOptionsCompositeValueTests) {
|
||||
assert_throws(new TypeError, () => {
|
||||
new KeyframeEffectReadOnly(target, {
|
||||
new KeyframeEffect(target, {
|
||||
left: ['10px', '20px']
|
||||
}, { composite: composite });
|
||||
});
|
||||
|
@ -104,32 +103,30 @@ test(t => {
|
|||
|
||||
for (const subtest of gKeyframesTests) {
|
||||
test(t => {
|
||||
const effect = new KeyframeEffectReadOnly(target, subtest.input);
|
||||
const effect = new KeyframeEffect(target, subtest.input);
|
||||
assert_frame_lists_equal(effect.getKeyframes(), subtest.output);
|
||||
}, `A KeyframeEffectReadOnly can be constructed with ${subtest.desc}`);
|
||||
}, `A KeyframeEffect can be constructed with ${subtest.desc}`);
|
||||
|
||||
test(t => {
|
||||
const effect = new KeyframeEffectReadOnly(target, subtest.input);
|
||||
const secondEffect =
|
||||
new KeyframeEffectReadOnly(target, effect.getKeyframes());
|
||||
const effect = new KeyframeEffect(target, subtest.input);
|
||||
const secondEffect = new KeyframeEffect(target, effect.getKeyframes());
|
||||
assert_frame_lists_equal(secondEffect.getKeyframes(),
|
||||
effect.getKeyframes());
|
||||
}, `A KeyframeEffectReadOnly constructed with ${subtest.desc} roundtrips`);
|
||||
}, `A KeyframeEffect constructed with ${subtest.desc} roundtrips`);
|
||||
}
|
||||
|
||||
for (const subtest of gInvalidKeyframesTests) {
|
||||
test(t => {
|
||||
assert_throws(new TypeError, () => {
|
||||
new KeyframeEffectReadOnly(target, subtest.input);
|
||||
new KeyframeEffect(target, subtest.input);
|
||||
});
|
||||
}, `KeyframeEffectReadOnly constructor throws with ${subtest.desc}`);
|
||||
}, `KeyframeEffect constructor throws with ${subtest.desc}`);
|
||||
}
|
||||
|
||||
test(t => {
|
||||
const effect = new KeyframeEffectReadOnly(target,
|
||||
{ left: ['10px', '20px'] });
|
||||
const effect = new KeyframeEffect(target, { left: ['10px', '20px'] });
|
||||
|
||||
const timing = effect.timing;
|
||||
const timing = effect.getTiming();
|
||||
assert_equals(timing.delay, 0, 'default delay');
|
||||
assert_equals(timing.endDelay, 0, 'default endDelay');
|
||||
assert_equals(timing.fill, 'auto', 'default fill');
|
||||
|
@ -142,14 +139,12 @@ test(t => {
|
|||
assert_equals(effect.composite, 'replace', 'default composite');
|
||||
assert_equals(effect.iterationComposite, 'replace',
|
||||
'default iterationComposite');
|
||||
}, 'A KeyframeEffectReadOnly constructed without any ' +
|
||||
'KeyframeEffectOptions object');
|
||||
}, 'A KeyframeEffect constructed without any KeyframeEffectOptions object');
|
||||
|
||||
for (const subtest of gKeyframeEffectOptionTests) {
|
||||
test(t => {
|
||||
const effect = new KeyframeEffectReadOnly(target,
|
||||
{ left: ['10px', '20px'] },
|
||||
subtest.input);
|
||||
const effect = new KeyframeEffect(target, { left: ['10px', '20px'] },
|
||||
subtest.input);
|
||||
|
||||
// Helper function to provide default expected values when the test does
|
||||
// not supply them.
|
||||
|
@ -157,7 +152,7 @@ for (const subtest of gKeyframeEffectOptionTests) {
|
|||
return field in subtest.expected ? subtest.expected[field] : defaultValue;
|
||||
};
|
||||
|
||||
const timing = effect.timing;
|
||||
const timing = effect.getTiming();
|
||||
assert_equals(timing.delay, expected('delay', 0),
|
||||
'timing delay');
|
||||
assert_equals(timing.fill, expected('fill', 'auto'),
|
||||
|
@ -169,27 +164,24 @@ for (const subtest of gKeyframeEffectOptionTests) {
|
|||
assert_equals(timing.direction, expected('direction', 'normal'),
|
||||
'timing direction');
|
||||
|
||||
}, `A KeyframeEffectReadOnly constructed by ${subtest.desc}`);
|
||||
}, `A KeyframeEffect constructed by ${subtest.desc}`);
|
||||
}
|
||||
|
||||
for (const subtest of gInvalidKeyframeEffectOptionTests) {
|
||||
test(t => {
|
||||
assert_throws(new TypeError, () => {
|
||||
new KeyframeEffectReadOnly(target,
|
||||
{ left: ['10px', '20px'] },
|
||||
subtest.input);
|
||||
new KeyframeEffect(target, { left: ['10px', '20px'] }, subtest.input);
|
||||
});
|
||||
}, `Invalid KeyframeEffectReadOnly option by ${subtest.desc}`);
|
||||
}, `Invalid KeyframeEffect option by ${subtest.desc}`);
|
||||
}
|
||||
|
||||
test(t => {
|
||||
const effect = new KeyframeEffectReadOnly(null,
|
||||
{ left: ['10px', '20px'] },
|
||||
{ duration: 100 * MS_PER_SEC,
|
||||
fill: 'forwards' });
|
||||
const effect = new KeyframeEffect(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');
|
||||
}, 'A KeyframeEffect constructed with null target');
|
||||
|
||||
test(t => {
|
||||
const test_error = { name: 'test' };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>KeyframeEffect and KeyframeEffectReadOnly copy constructor</title>
|
||||
<title>KeyframeEffect copy constructor</title>
|
||||
<link rel="help"
|
||||
href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-keyframeeffect-source">
|
||||
<link rel="help"
|
||||
|
@ -14,21 +14,21 @@
|
|||
'use strict';
|
||||
|
||||
test(t => {
|
||||
const effect = new KeyframeEffectReadOnly(createDiv(t), null);
|
||||
const copiedEffect = new KeyframeEffectReadOnly(effect);
|
||||
const effect = new KeyframeEffect(createDiv(t), null);
|
||||
const copiedEffect = new KeyframeEffect(effect);
|
||||
assert_equals(copiedEffect.target, effect.target, 'same target');
|
||||
}, 'Copied KeyframeEffectReadOnly has the same target');
|
||||
}, 'Copied KeyframeEffect has the same target');
|
||||
|
||||
test(t => {
|
||||
const effect =
|
||||
new KeyframeEffectReadOnly(null,
|
||||
[ { marginLeft: '0px' },
|
||||
{ marginLeft: '-20px', easing: 'ease-in',
|
||||
offset: 0.1 },
|
||||
{ marginLeft: '100px', easing: 'ease-out' },
|
||||
{ marginLeft: '50px' } ]);
|
||||
new KeyframeEffect(null,
|
||||
[ { marginLeft: '0px' },
|
||||
{ marginLeft: '-20px', easing: 'ease-in',
|
||||
offset: 0.1 },
|
||||
{ marginLeft: '100px', easing: 'ease-out' },
|
||||
{ marginLeft: '50px' } ]);
|
||||
|
||||
const copiedEffect = new KeyframeEffectReadOnly(effect);
|
||||
const copiedEffect = new KeyframeEffect(effect);
|
||||
const keyframesA = effect.getKeyframes();
|
||||
const keyframesB = copiedEffect.getKeyframes();
|
||||
assert_equals(keyframesA.length, keyframesB.length, 'same keyframes length');
|
||||
|
@ -50,34 +50,33 @@ test(t => {
|
|||
assert_equals(keyframesA[i].marginLeft, keyframesB[i].marginLeft,
|
||||
`Keyframe ${i} has the same property value pair`);
|
||||
}
|
||||
}, 'Copied KeyframeEffectReadOnly has the same keyframes');
|
||||
}, 'Copied KeyframeEffect has the same keyframes');
|
||||
|
||||
test(t => {
|
||||
const effect =
|
||||
new KeyframeEffectReadOnly(null, null,
|
||||
{ iterationComposite: 'accumulate' });
|
||||
new KeyframeEffect(null, null, { iterationComposite: 'accumulate' });
|
||||
|
||||
const copiedEffect = new KeyframeEffectReadOnly(effect);
|
||||
const copiedEffect = new KeyframeEffect(effect);
|
||||
assert_equals(copiedEffect.iterationComposite, effect.iterationComposite,
|
||||
'same iterationCompositeOperation');
|
||||
assert_equals(copiedEffect.composite, effect.composite,
|
||||
'same compositeOperation');
|
||||
}, 'Copied KeyframeEffectReadOnly has the same KeyframeEffectOptions');
|
||||
}, 'Copied KeyframeEffect has the same KeyframeEffectOptions');
|
||||
|
||||
test(t => {
|
||||
const effect = new KeyframeEffectReadOnly(null, null,
|
||||
{ duration: 100 * MS_PER_SEC,
|
||||
delay: -1 * MS_PER_SEC,
|
||||
endDelay: 2 * MS_PER_SEC,
|
||||
fill: 'forwards',
|
||||
iterationStart: 2,
|
||||
iterations: 20,
|
||||
easing: 'ease-out',
|
||||
direction: 'alternate' } );
|
||||
const effect = new KeyframeEffect(null, null,
|
||||
{ duration: 100 * MS_PER_SEC,
|
||||
delay: -1 * MS_PER_SEC,
|
||||
endDelay: 2 * MS_PER_SEC,
|
||||
fill: 'forwards',
|
||||
iterationStart: 2,
|
||||
iterations: 20,
|
||||
easing: 'ease-out',
|
||||
direction: 'alternate' } );
|
||||
|
||||
const copiedEffect = new KeyframeEffectReadOnly(effect);
|
||||
const timingA = effect.timing;
|
||||
const timingB = copiedEffect.timing;
|
||||
const copiedEffect = new KeyframeEffect(effect);
|
||||
const timingA = effect.getTiming();
|
||||
const timingB = copiedEffect.getTiming();
|
||||
assert_not_equals(timingA, timingB, 'different timing objects');
|
||||
assert_equals(timingA.delay, timingB.delay, 'same delay');
|
||||
assert_equals(timingA.endDelay, timingB.endDelay, 'same endDelay');
|
||||
|
@ -88,19 +87,7 @@ test(t => {
|
|||
assert_equals(timingA.duration, timingB.duration, 'same duration');
|
||||
assert_equals(timingA.direction, timingB.direction, 'same direction');
|
||||
assert_equals(timingA.easing, timingB.easing, 'same easing');
|
||||
}, 'Copied KeyframeEffectReadOnly has the same timing content');
|
||||
|
||||
test(t => {
|
||||
const effect = new KeyframeEffectReadOnly(createDiv(t), null);
|
||||
assert_equals(effect.constructor.name, 'KeyframeEffectReadOnly');
|
||||
assert_equals(effect.timing.constructor.name,
|
||||
'AnimationEffectTimingReadOnly');
|
||||
|
||||
// Make a mutable copy
|
||||
const copiedEffect = new KeyframeEffect(effect);
|
||||
assert_equals(copiedEffect.constructor.name, 'KeyframeEffect');
|
||||
assert_equals(copiedEffect.timing.constructor.name, 'AnimationEffectTiming');
|
||||
}, 'KeyframeEffect constructed from a KeyframeEffectReadOnly is mutable');
|
||||
}, 'Copied KeyframeEffect has the same timing content');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<script src="/resources/WebIDLParser.js"></script>
|
||||
<script src="/resources/idlharness.js"></script>
|
||||
<div id="log"></div>
|
||||
<script type="text/plain" id="AnimationEffectTimingReadOnly-IDL">
|
||||
<script type="text/plain" id="AnimationEffect-IDL">
|
||||
enum FillMode { "none", "forwards", "backwards", "both", "auto" };
|
||||
enum PlaybackDirection {
|
||||
"normal",
|
||||
|
@ -18,7 +18,7 @@ enum PlaybackDirection {
|
|||
"alternate-reverse"
|
||||
};
|
||||
|
||||
dictionary AnimationEffectTimingProperties {
|
||||
dictionary EffectTiming {
|
||||
double delay = 0.0;
|
||||
double endDelay = 0.0;
|
||||
FillMode fill = "auto";
|
||||
|
@ -29,38 +29,37 @@ dictionary AnimationEffectTimingProperties {
|
|||
DOMString easing = "linear";
|
||||
};
|
||||
|
||||
[Exposed=Window]
|
||||
interface AnimationEffectTimingReadOnly {
|
||||
readonly attribute double delay;
|
||||
readonly attribute double endDelay;
|
||||
readonly attribute FillMode fill;
|
||||
readonly attribute double iterationStart;
|
||||
readonly attribute unrestricted double iterations;
|
||||
readonly attribute (unrestricted double or DOMString) duration;
|
||||
readonly attribute PlaybackDirection direction;
|
||||
readonly attribute DOMString easing;
|
||||
dictionary OptionalEffectTiming {
|
||||
double delay;
|
||||
double endDelay;
|
||||
FillMode fill;
|
||||
double iterationStart;
|
||||
unrestricted double iterations;
|
||||
(unrestricted double or DOMString) duration;
|
||||
PlaybackDirection direction;
|
||||
DOMString easing;
|
||||
};
|
||||
</script>
|
||||
<script type="text/plain" id="AnimationEffectReadOnly-IDL">
|
||||
dictionary ComputedTimingProperties : AnimationEffectTimingProperties {
|
||||
unrestricted double endTime;
|
||||
unrestricted double activeDuration;
|
||||
double? localTime;
|
||||
double? progress;
|
||||
unrestricted double? currentIteration;
|
||||
|
||||
dictionary ComputedEffectTiming : EffectTiming {
|
||||
unrestricted double endTime = 0.0;
|
||||
unrestricted double activeDuration = 0.0;
|
||||
double? localTime = null;
|
||||
double? progress = null;
|
||||
unrestricted double? currentIteration = null;
|
||||
};
|
||||
|
||||
[Exposed=Window]
|
||||
interface AnimationEffectReadOnly {
|
||||
readonly attribute AnimationEffectTimingReadOnly timing;
|
||||
ComputedTimingProperties getComputedTiming();
|
||||
interface AnimationEffect {
|
||||
EffectTiming getTiming();
|
||||
ComputedEffectTiming getComputedTiming();
|
||||
void updateTiming(optional OptionalEffectTiming timing);
|
||||
};
|
||||
</script>
|
||||
<script type="text/plain" id="KeyframeEffectReadOnly-IDL">
|
||||
<script type="text/plain" id="KeyframeEffect-IDL">
|
||||
enum IterationCompositeOperation { "replace", "accumulate" };
|
||||
enum CompositeOperation { "replace", "add", "accumulate" };
|
||||
|
||||
dictionary KeyframeEffectOptions : AnimationEffectTimingProperties {
|
||||
dictionary KeyframeEffectOptions : EffectTiming {
|
||||
IterationCompositeOperation iterationComposite = "replace";
|
||||
CompositeOperation composite = "replace";
|
||||
};
|
||||
|
@ -69,24 +68,13 @@ dictionary KeyframeEffectOptions : AnimationEffectTimingProperties {
|
|||
Constructor ((Element or CSSPseudoElement)? target,
|
||||
object? keyframes,
|
||||
optional (unrestricted double or KeyframeEffectOptions) options),
|
||||
Constructor (KeyframeEffectReadOnly source)]
|
||||
interface KeyframeEffectReadOnly : AnimationEffectReadOnly {
|
||||
readonly attribute (Element or CSSPseudoElement)? target;
|
||||
readonly attribute IterationCompositeOperation iterationComposite;
|
||||
readonly attribute CompositeOperation composite;
|
||||
Constructor (KeyframeEffect source)]
|
||||
interface KeyframeEffect : AnimationEffect {
|
||||
attribute (Element or CSSPseudoElement)? target;
|
||||
attribute IterationCompositeOperation iterationComposite;
|
||||
attribute CompositeOperation composite;
|
||||
|
||||
sequence<object> getKeyframes ();
|
||||
};
|
||||
</script>
|
||||
<script type="text/plain" id="KeyframeEffect-IDL">
|
||||
[Exposed=Window,
|
||||
Constructor ((Element or CSSPseudoElement)? target,
|
||||
object? keyframes,
|
||||
optional (unrestricted double or KeyframeEffectOptions) options),
|
||||
Constructor (KeyframeEffectReadOnly source)]
|
||||
interface KeyframeEffect : KeyframeEffectReadOnly {
|
||||
inherit attribute (Element or CSSPseudoElement)? target;
|
||||
inherit attribute IterationCompositeOperation iterationComposite;
|
||||
inherit attribute CompositeOperation composite;
|
||||
void setKeyframes (object? keyframes);
|
||||
};
|
||||
</script>
|
||||
|
@ -98,20 +86,13 @@ const idlArray = new IdlArray();
|
|||
idlArray.add_untested_idls('interface CSSPseudoElement {};');
|
||||
idlArray.add_untested_idls('interface Element {};');
|
||||
idlArray.add_untested_idls(
|
||||
document.getElementById('AnimationEffectTimingReadOnly-IDL').textContent
|
||||
);
|
||||
idlArray.add_idls(
|
||||
document.getElementById('AnimationEffectReadOnly-IDL').textContent
|
||||
);
|
||||
idlArray.add_idls(
|
||||
document.getElementById('KeyframeEffectReadOnly-IDL').textContent
|
||||
document.getElementById('AnimationEffect-IDL').textContent
|
||||
);
|
||||
idlArray.add_idls(
|
||||
document.getElementById('KeyframeEffect-IDL').textContent
|
||||
);
|
||||
idlArray.add_objects({
|
||||
KeyframeEffect: ['new KeyframeEffect(null, null)'],
|
||||
KeyframeEffectReadOnly: ['new KeyframeEffectReadOnly(null, null)'],
|
||||
});
|
||||
|
||||
idlArray.test();
|
||||
|
|
|
@ -19,7 +19,8 @@ test(t => {
|
|||
anim.pause();
|
||||
|
||||
anim.currentTime =
|
||||
anim.effect.timing.duration * 2 + anim.effect.timing.duration / 2;
|
||||
anim.effect.getComputedTiming().duration * 2 +
|
||||
anim.effect.getComputedTiming().duration / 2;
|
||||
assert_equals(getComputedStyle(div).marginLeft, '25px',
|
||||
'Animated style at 50s of the third iteration');
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
'use strict';
|
||||
|
||||
// This file only tests the KeyframeEffect constructor since it is
|
||||
// assumed that the implementation of the KeyframeEffectReadOnly constructor,
|
||||
// assumed that the implementation of the KeyframeEffect constructor,
|
||||
// Animatable.animate() method, and KeyframeEffect.setKeyframes() method will
|
||||
// all share common machinery and it is not necessary to test each method.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue