Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 4 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /web-animations/interfaces/KeyframeEffect/constructor.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<meta charset=utf-8>
<title>KeyframeEffect constructor</title>
<link rel="help"
<link rel="help"
<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/keyframe-utils.js"></script>
<script src="../../resources/keyframe-tests.js"></script>
<body>
<div id="log"></div>
<div id="target"></div>
<script>
'use strict';
const target = document.getElementById('target');
test(t => {
for (const frames of gEmptyKeyframeListTests) {
assert_equals(new KeyframeEffect(target, frames).getKeyframes().length,
0, `number of frames for ${JSON.stringify(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 KeyframeEffect(target, {
left: ['10px', '20px']
}, { easing: easing });
assert_equals(effect.getTiming().easing, expected,
`resulting easing for '${easing}'`);
}
}, 'easing values are parsed correctly when passed to the ' +
'KeyframeEffect constructor in KeyframeEffectOptions');
test(t => {
for (const invalidEasing of gInvalidEasings) {
assert_throws_js(TypeError, () => {
new KeyframeEffect(target, null, { easing: invalidEasing });
}, `TypeError is thrown for easing '${invalidEasing}'`);
}
}, 'Invalid easing values are correctly rejected when passed to the ' +
'KeyframeEffect constructor in KeyframeEffectOptions');
test(t => {
const getKeyframe =
composite => ({ left: [ '10px', '20px' ], composite: composite });
for (const composite of gGoodKeyframeCompositeValueTests) {
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_js(TypeError, () => {
new KeyframeEffect(target, getKeyframe(composite));
});
}
}, 'composite values are parsed correctly when passed to the ' +
'KeyframeEffect constructor in property-indexed keyframes');
test(t => {
const getKeyframes = composite =>
[
{ offset: 0, left: '10px', composite: composite },
{ offset: 1, left: '20px' }
];
for (const composite of gGoodKeyframeCompositeValueTests) {
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_js(TypeError, () => {
new KeyframeEffect(target, getKeyframes(composite));
});
}
}, 'composite values are parsed correctly when passed to the ' +
'KeyframeEffect constructor in regular keyframes');
test(t => {
for (const composite of gGoodOptionsCompositeValueTests) {
const effect = new KeyframeEffect(target, {
left: ['10px', '20px']
}, { composite });
assert_equals(effect.getKeyframes()[0].composite, 'auto',
`resulting composite for '${composite}'`);
}
for (const composite of gBadOptionsCompositeValueTests) {
assert_throws_js(TypeError, () => {
new KeyframeEffect(target, {
left: ['10px', '20px']
}, { composite: composite });
});
}
}, 'composite value is auto if the composite operation specified on the ' +
'keyframe effect is being used');
for (const subtest of gKeyframesTests) {
test(t => {
const effect = new KeyframeEffect(target, subtest.input);
assert_frame_lists_equal(effect.getKeyframes(), subtest.output);
}, `A KeyframeEffect can be constructed with ${subtest.desc}`);
test(t => {
const effect = new KeyframeEffect(target, subtest.input);
const secondEffect = new KeyframeEffect(target, effect.getKeyframes());
assert_frame_lists_equal(secondEffect.getKeyframes(),
effect.getKeyframes());
}, `A KeyframeEffect constructed with ${subtest.desc} roundtrips`);
}
for (const subtest of gInvalidKeyframesTests) {
test(t => {
assert_throws_js(TypeError, () => {
new KeyframeEffect(target, subtest.input);
});
}, `KeyframeEffect constructor throws with ${subtest.desc}`);
}
test(t => {
const effect = new KeyframeEffect(target, { left: ['10px', '20px'] });
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');
assert_equals(timing.iterations, 1.0, 'default iterations');
assert_equals(timing.iterationStart, 0.0, 'default iterationStart');
assert_equals(timing.duration, 'auto', 'default duration');
assert_equals(timing.direction, 'normal', 'default direction');
assert_equals(timing.easing, 'linear', 'default easing');
assert_equals(effect.composite, 'replace', 'default composite');
assert_equals(effect.iterationComposite, 'replace',
'default iterationComposite');
}, 'A KeyframeEffect constructed without any KeyframeEffectOptions object');
for (const subtest of gKeyframeEffectOptionTests) {
test(t => {
const effect = new KeyframeEffect(target, { left: ['10px', '20px'] },
subtest.input);
// Helper function to provide default expected values when the test does
// not supply them.
const expected = (field, defaultValue) => {
return field in subtest.expected ? subtest.expected[field] : defaultValue;
};
const timing = effect.getTiming();
assert_equals(timing.delay, expected('delay', 0),
'timing delay');
assert_equals(timing.fill, expected('fill', 'auto'),
'timing fill');
assert_equals(timing.iterations, expected('iterations', 1),
'timing iterations');
assert_equals(timing.duration, expected('duration', 'auto'),
'timing duration');
assert_equals(timing.direction, expected('direction', 'normal'),
'timing direction');
}, `A KeyframeEffect constructed by ${subtest.desc}`);
}
for (const subtest of gInvalidKeyframeEffectOptionTests) {
test(t => {
assert_throws_js(TypeError, () => {
new KeyframeEffect(target, { left: ['10px', '20px'] }, subtest.input);
});
}, `Invalid KeyframeEffect option by ${subtest.desc}`);
}
test(t => {
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 KeyframeEffect constructed with null target');
test(t => {
const test_error = { name: 'test' };
assert_throws_exactly(test_error, () => {
new KeyframeEffect(target, { get left() { throw test_error }})
});
}, 'KeyframeEffect constructor propagates exceptions generated by accessing'
+ ' the options object');
</script>
</body>