Update web-platform-tests to revision e87f38097902e16348d4e17f4fe3bc2d0112bff1

This commit is contained in:
WPT Sync Bot 2018-03-17 21:12:30 -04:00
parent 2f8fa32e91
commit db5631a086
381 changed files with 11610 additions and 4232 deletions

View file

@ -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');

View file

@ -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');

View file

@ -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');

View file

@ -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();

View file

@ -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.');

View file

@ -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');

View file

@ -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;

View file

@ -195,7 +195,5 @@ for (const stest of gEndTimeTests) {
}, `getComputedTiming().endTime for ${stest.desc}`);
}
done();
</script>
</body>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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();

View file

@ -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' };

View file

@ -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>

View file

@ -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();

View file

@ -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');

View file

@ -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.