mirror of
https://github.com/servo/servo.git
synced 2025-08-08 23:15:33 +01:00
Update web-platform-tests to revision e03a9b1341ae9bdb1e4fa03765257b84d26fe2f1
This commit is contained in:
parent
7d05c76d18
commit
20a833eb75
5167 changed files with 4696 additions and 297370 deletions
|
@ -29,35 +29,7 @@ test(function(t) {
|
|||
}, "a KeyframeEffectReadOnly can be constructed with no frames");
|
||||
|
||||
test(function(t) {
|
||||
gEasingValueTests.forEach(function(subtest) {
|
||||
var easing = subtest[0];
|
||||
var expected = subtest[1];
|
||||
var effect = new KeyframeEffectReadOnly(target, {
|
||||
left: ["10px", "20px"],
|
||||
easing: easing
|
||||
});
|
||||
assert_equals(effect.getKeyframes()[0].easing, expected,
|
||||
"resulting easing for '" + easing + "'");
|
||||
});
|
||||
}, "easing values are parsed correctly when passed to the " +
|
||||
"KeyframeEffectReadOnly constructor in a property-indexed keyframe");
|
||||
|
||||
test(function(t) {
|
||||
gEasingValueTests.forEach(function(subtest) {
|
||||
var easing = subtest[0];
|
||||
var expected = subtest[1];
|
||||
var effect = new KeyframeEffectReadOnly(target, [
|
||||
{ offset: 0, left: "10px", easing: easing },
|
||||
{ offset: 1, left: "20px" }
|
||||
]);
|
||||
assert_equals(effect.getKeyframes()[0].easing, expected,
|
||||
"resulting easing for '" + easing + "'");
|
||||
});
|
||||
}, "easing values are parsed correctly when passed to the " +
|
||||
"KeyframeEffectReadOnly constructor in regular keyframes");
|
||||
|
||||
test(function(t) {
|
||||
gEasingValueTests.forEach(function(subtest) {
|
||||
gEasingParsingTests.forEach(function(subtest) {
|
||||
var easing = subtest[0];
|
||||
var expected = subtest[1];
|
||||
var effect = new KeyframeEffectReadOnly(target, {
|
||||
|
@ -69,15 +41,6 @@ test(function(t) {
|
|||
}, "easing values are parsed correctly when passed to the " +
|
||||
"KeyframeEffectReadOnly constructor in KeyframeEffectOptions");
|
||||
|
||||
test(function(t) {
|
||||
gInvalidEasings.forEach(invalidEasing => {
|
||||
assert_throws(new TypeError, () => {
|
||||
new KeyframeEffectReadOnly(target, { easing: invalidEasing });
|
||||
}, `TypeError is thrown for easing '${invalidEasing}'`);
|
||||
});
|
||||
}, 'invalid easing values are correctly rejected when passed to the ' +
|
||||
'KeyframeEffectReadOnly constructor in regular keyframes');
|
||||
|
||||
test(function(t) {
|
||||
gInvalidEasings.forEach(invalidEasing => {
|
||||
assert_throws(new TypeError, () => {
|
||||
|
@ -158,26 +121,6 @@ gPropertyIndexedKeyframesTests.forEach(function(subtest) {
|
|||
" roundtrips");
|
||||
});
|
||||
|
||||
test(function(t) {
|
||||
var expectedOrder = ["composite", "easing", "offset", "left", "marginLeft"];
|
||||
var actualOrder = [];
|
||||
var kf1 = {};
|
||||
var kf2 = { marginLeft: "10px", left: "20px", offset: 1 };
|
||||
[{ p: "marginLeft", v: "10px" },
|
||||
{ p: "left", v: "20px" },
|
||||
{ p: "offset", v: "0" },
|
||||
{ p: "easing", v: "linear" },
|
||||
{ p: "composite", v: "replace" }].forEach(function(e) {
|
||||
Object.defineProperty(kf1, e.p, {
|
||||
enumerable: true,
|
||||
get: function() { actualOrder.push(e.p); return e.v; }
|
||||
});
|
||||
});
|
||||
new KeyframeEffectReadOnly(target, [kf1, kf2]);
|
||||
assert_array_equals(actualOrder, expectedOrder, "property access order");
|
||||
}, "the KeyframeEffectReadOnly constructor reads keyframe properties in the " +
|
||||
"expected order");
|
||||
|
||||
gKeyframeSequenceTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(target, subtest.input);
|
||||
|
@ -202,15 +145,6 @@ gInvalidKeyframesTests.forEach(function(subtest) {
|
|||
}, "KeyframeEffectReadOnly constructor throws with " + subtest.desc);
|
||||
});
|
||||
|
||||
gInvalidEasingInKeyframeSequenceTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
assert_throws(new TypeError, function() {
|
||||
new KeyframeEffectReadOnly(target, subtest.input);
|
||||
});
|
||||
}, "Invalid easing [" + subtest.desc + "] in keyframe sequence " +
|
||||
"should be thrown");
|
||||
});
|
||||
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(target,
|
||||
{ left: ["10px", "20px"] });
|
||||
|
|
|
@ -0,0 +1,353 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Tests for processing a keyframes argument (property access)</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#processing-a-keyframes-argument">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<script src="../../resources/keyframe-utils.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
// This file only tests the KeyframeEffect constructor since it is
|
||||
// assumed that the implementation of the KeyframeEffectReadOnly constructor,
|
||||
// Animatable.animate() method, and KeyframeEffect.setKeyframes() method will
|
||||
// all share common machinery and it is not necessary to test each method.
|
||||
|
||||
// Test that only animatable properties are accessed
|
||||
|
||||
const gNonAnimatableProps = [
|
||||
'animation', // Shorthands where all the longhand sub-properties are not
|
||||
// animatable, are also not animatable.
|
||||
'animationDelay',
|
||||
'animationDirection',
|
||||
'animationDuration',
|
||||
'animationFillMode',
|
||||
'animationIterationCount',
|
||||
'animationName',
|
||||
'animationPlayState',
|
||||
'animationTimingFunction',
|
||||
'transition',
|
||||
'transitionDelay',
|
||||
'transitionDuration',
|
||||
'transitionProperty',
|
||||
'transitionTimingFunction',
|
||||
'display',
|
||||
'unsupportedProperty',
|
||||
'font-size', // Supported property that uses dashes
|
||||
];
|
||||
|
||||
function TestKeyframe(testProp) {
|
||||
let _propAccessCount = 0;
|
||||
|
||||
Object.defineProperty(this, testProp, {
|
||||
get: () => { _propAccessCount++; },
|
||||
enumerable: true,
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'propAccessCount', {
|
||||
get: () => _propAccessCount
|
||||
});
|
||||
}
|
||||
|
||||
function GetTestKeyframeSequence(testProp) {
|
||||
return [ new TestKeyframe(testProp) ]
|
||||
}
|
||||
|
||||
for (const prop of gNonAnimatableProps) {
|
||||
test(() => {
|
||||
const testKeyframe = new TestKeyframe(prop);
|
||||
|
||||
new KeyframeEffect(null, testKeyframe);
|
||||
|
||||
assert_equals(testKeyframe.propAccessCount, 0, 'Accessor not called');
|
||||
}, `non-animatable property '${prop}' is not accessed when using`
|
||||
+ ' a property-indexed keyframe object');
|
||||
}
|
||||
|
||||
for (const prop of gNonAnimatableProps) {
|
||||
test(() => {
|
||||
const testKeyframes = GetTestKeyframeSequence(prop);
|
||||
|
||||
new KeyframeEffect(null, testKeyframes);
|
||||
|
||||
assert_equals(testKeyframes[0].propAccessCount, 0, 'Accessor not called');
|
||||
}, `non-animatable property '${prop}' is not accessed when using`
|
||||
+ ' a keyframe sequence');
|
||||
}
|
||||
|
||||
// Test equivalent forms of property-indexed and sequenced keyframe syntax
|
||||
|
||||
function assertEquivalentKeyframeSyntax(keyframesA, keyframesB) {
|
||||
const processedKeyframesA =
|
||||
new KeyframeEffect(null, keyframesA).getKeyframes();
|
||||
const processedKeyframesB =
|
||||
new KeyframeEffect(null, keyframesB).getKeyframes();
|
||||
assert_frame_lists_equal(processedKeyframesA, processedKeyframesB);
|
||||
}
|
||||
|
||||
const gEquivalentSyntaxTests = [
|
||||
{
|
||||
description: 'two properties with one value',
|
||||
indexedKeyframes: {
|
||||
left: '100px',
|
||||
opacity: ['1'],
|
||||
},
|
||||
sequencedKeyframes: [
|
||||
{ left: '100px', opacity: '1' },
|
||||
],
|
||||
},
|
||||
{
|
||||
description: 'two properties with three values',
|
||||
indexedKeyframes: {
|
||||
left: ['10px', '100px', '150px'],
|
||||
opacity: ['1', '0', '1'],
|
||||
},
|
||||
sequencedKeyframes: [
|
||||
{ left: '10px', opacity: '1' },
|
||||
{ left: '100px', opacity: '0' },
|
||||
{ left: '150px', opacity: '1' },
|
||||
],
|
||||
},
|
||||
{
|
||||
description: 'two properties with different numbers of values',
|
||||
indexedKeyframes: {
|
||||
left: ['0px', '100px', '200px'],
|
||||
opacity: ['0', '1']
|
||||
},
|
||||
sequencedKeyframes: [
|
||||
{ left: '0px', opacity: '0' },
|
||||
{ left: '100px' },
|
||||
{ left: '200px', opacity: '1' },
|
||||
],
|
||||
},
|
||||
{
|
||||
description: 'same easing applied to all keyframes',
|
||||
indexedKeyframes: {
|
||||
left: ['10px', '100px', '150px'],
|
||||
opacity: ['1', '0', '1'],
|
||||
easing: 'ease',
|
||||
},
|
||||
sequencedKeyframes: [
|
||||
{ left: '10px', opacity: '1', easing: 'ease' },
|
||||
{ left: '100px', opacity: '0', easing: 'ease' },
|
||||
{ left: '150px', opacity: '1', easing: 'ease' },
|
||||
],
|
||||
},
|
||||
{
|
||||
description: 'same composite applied to all keyframes',
|
||||
indexedKeyframes: {
|
||||
left: ['0px', '100px'],
|
||||
composite: 'add',
|
||||
},
|
||||
sequencedKeyframes: [
|
||||
{ left: '0px', composite: 'add' },
|
||||
{ left: '100px', composite: 'add' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
for (const {description, indexedKeyframes, sequencedKeyframes} of
|
||||
gEquivalentSyntaxTests) {
|
||||
test(() => {
|
||||
assertEquivalentKeyframeSyntax(indexedKeyframes, sequencedKeyframes);
|
||||
}, `Equivalent property-indexed and sequenced keyframes: ${description}`);
|
||||
}
|
||||
|
||||
// Test handling of custom iterable objects.
|
||||
|
||||
function createIterable(iterations) {
|
||||
return {
|
||||
[Symbol.iterator]() {
|
||||
let i = 0;
|
||||
return {
|
||||
next() {
|
||||
return iterations[i++];
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test(() => {
|
||||
const effect = new KeyframeEffect(null, createIterable([
|
||||
{ done: false, value: { left: '100px' } },
|
||||
{ done: false, value: { left: '300px' } },
|
||||
{ done: false, value: { left: '200px' } },
|
||||
{ done: true },
|
||||
]));
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{ offset: null, computedOffset: 0, easing: 'linear', left: '100px' },
|
||||
{ offset: null, computedOffset: 0.5, easing: 'linear', left: '300px' },
|
||||
{ offset: null, computedOffset: 1, easing: 'linear', left: '200px' },
|
||||
]);
|
||||
}, 'Keyframes are read from a custom iterator');
|
||||
|
||||
test(() => {
|
||||
const keyframes = createIterable([
|
||||
{ done: false, value: { left: '100px' } },
|
||||
{ done: false, value: { left: '300px' } },
|
||||
{ done: false, value: { left: '200px' } },
|
||||
{ done: true },
|
||||
]);
|
||||
keyframes.easing = 'ease-in-out';
|
||||
keyframes.offset = '0.1';
|
||||
const effect = new KeyframeEffect(null, keyframes);
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{ offset: null, computedOffset: 0, easing: 'linear', left: '100px' },
|
||||
{ offset: null, computedOffset: 0.5, easing: 'linear', left: '300px' },
|
||||
{ offset: null, computedOffset: 1, easing: 'linear', left: '200px' },
|
||||
]);
|
||||
}, "'easing' and 'offset' are ignored on iterable objects");
|
||||
|
||||
test(() => {
|
||||
const effect = new KeyframeEffect(null, createIterable([
|
||||
{ done: false, value: { left: '100px', top: '200px' } },
|
||||
{ done: false, value: { left: '300px' } },
|
||||
{ done: false, value: { left: '200px', top: '100px' } },
|
||||
{ done: true },
|
||||
]));
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{ offset: null, computedOffset: 0, easing: 'linear', left: '100px',
|
||||
top: '200px' },
|
||||
{ offset: null, computedOffset: 0.5, easing: 'linear', left: '300px' },
|
||||
{ offset: null, computedOffset: 1, easing: 'linear', left: '200px',
|
||||
top: '100px' },
|
||||
]);
|
||||
}, 'Keyframes are read from a custom iterator with multiple properties'
|
||||
+ ' specified');
|
||||
|
||||
test(() => {
|
||||
const effect = new KeyframeEffect(null, createIterable([
|
||||
{ done: false, value: { left: '100px' } },
|
||||
{ done: false, value: { left: '250px', offset: 0.75 } },
|
||||
{ done: false, value: { left: '200px' } },
|
||||
{ done: true },
|
||||
]));
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{ offset: null, computedOffset: 0, easing: 'linear', left: '100px' },
|
||||
{ offset: 0.75, computedOffset: 0.75, easing: 'linear', left: '250px' },
|
||||
{ offset: null, computedOffset: 1, easing: 'linear', left: '200px' },
|
||||
]);
|
||||
}, 'Keyframes are read from a custom iterator with where an offset is'
|
||||
+ ' specified');
|
||||
|
||||
test(() => {
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
new KeyframeEffect(null, createIterable([
|
||||
{ done: false, value: { left: '100px' } },
|
||||
{ done: false, value: 1234 },
|
||||
{ done: false, value: { left: '200px' } },
|
||||
{ done: true },
|
||||
]));
|
||||
});
|
||||
}, 'Reading from a custom iterator that returns a non-object keyframe'
|
||||
+ ' should throw');
|
||||
|
||||
test(() => {
|
||||
const effect = new KeyframeEffect(null, createIterable([
|
||||
{ done: false, value: { left: ['100px', '200px'] } },
|
||||
{ done: true },
|
||||
]));
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{ offset: null, computedOffset: 1, easing: 'linear' }
|
||||
]);
|
||||
}, 'A list of values returned from a custom iterator should be ignored');
|
||||
|
||||
test(() => {
|
||||
const keyframe = {};
|
||||
Object.defineProperty(keyframe, 'width', { value: '200px' });
|
||||
Object.defineProperty(keyframe, 'height', {
|
||||
value: '100px',
|
||||
enumerable: true,
|
||||
});
|
||||
assert_equals(keyframe.width, '200px', 'width of keyframe is readable');
|
||||
assert_equals(keyframe.height, '100px', 'height of keyframe is readable');
|
||||
|
||||
const effect = new KeyframeEffect(null, [keyframe, { height: '200px' }]);
|
||||
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{ offset: null, computedOffset: 0, easing: 'linear', height: '100px' },
|
||||
{ offset: null, computedOffset: 1, easing: 'linear', height: '200px' },
|
||||
]);
|
||||
}, 'Only enumerable properties on keyframes are read');
|
||||
|
||||
test(() => {
|
||||
const KeyframeParent = function() { this.width = '100px'; };
|
||||
KeyframeParent.prototype = { height: '100px' };
|
||||
const Keyframe = function() { this.top = '100px'; };
|
||||
Keyframe.prototype = Object.create(KeyframeParent.prototype);
|
||||
Object.defineProperty(Keyframe.prototype, 'left', {
|
||||
value: '100px',
|
||||
enumerable: true,
|
||||
});
|
||||
const keyframe = new Keyframe();
|
||||
|
||||
const effect = new KeyframeEffect(null, [keyframe, { top: '200px' }]);
|
||||
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{ offset: null, computedOffset: 0, easing: 'linear', top: '100px' },
|
||||
{ offset: null, computedOffset: 1, easing: 'linear', top: '200px' },
|
||||
]);
|
||||
}, 'Only properties defined directly on keyframes are read');
|
||||
|
||||
test(() => {
|
||||
const keyframes = {};
|
||||
Object.defineProperty(keyframes, 'width', ['100px', '200px']);
|
||||
Object.defineProperty(keyframes, 'height', {
|
||||
value: ['100px', '200px'],
|
||||
enumerable: true,
|
||||
});
|
||||
|
||||
const effect = new KeyframeEffect(null, keyframes);
|
||||
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{ offset: null, computedOffset: 0, easing: 'linear', height: '100px' },
|
||||
{ offset: null, computedOffset: 1, easing: 'linear', height: '200px' },
|
||||
]);
|
||||
}, 'Only enumerable properties on property-indexed keyframes are read');
|
||||
|
||||
test(() => {
|
||||
const KeyframesParent = function() { this.width = '100px'; };
|
||||
KeyframesParent.prototype = { height: '100px' };
|
||||
const Keyframes = function() { this.top = ['100px', '200px']; };
|
||||
Keyframes.prototype = Object.create(KeyframesParent.prototype);
|
||||
Object.defineProperty(Keyframes.prototype, 'left', {
|
||||
value: ['100px', '200px'],
|
||||
enumerable: true,
|
||||
});
|
||||
const keyframes = new Keyframes();
|
||||
|
||||
const effect = new KeyframeEffect(null, keyframes);
|
||||
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{ offset: null, computedOffset: 0, easing: 'linear', top: '100px' },
|
||||
{ offset: null, computedOffset: 1, easing: 'linear', top: '200px' },
|
||||
]);
|
||||
}, 'Only properties defined directly on property-indexed keyframes are read');
|
||||
|
||||
test(() => {
|
||||
const expectedOrder = ['composite', 'easing', 'offset', 'left', 'marginLeft'];
|
||||
const actualOrder = [];
|
||||
const kf1 = {};
|
||||
for (const {prop, value} of [{ prop: 'marginLeft', value: '10px' },
|
||||
{ prop: 'left', value: '20px' },
|
||||
{ prop: 'offset', value: '0' },
|
||||
{ prop: 'easing', value: 'linear' },
|
||||
{ prop: 'composite', value: 'replace' }]) {
|
||||
Object.defineProperty(kf1, prop, {
|
||||
enumerable: true,
|
||||
get: () => { actualOrder.push(prop); return value; }
|
||||
});
|
||||
}
|
||||
const kf2 = { marginLeft: '10px', left: '20px', offset: 1 };
|
||||
|
||||
new KeyframeEffect(target, [kf1, kf2]);
|
||||
|
||||
assert_array_equals(actualOrder, expectedOrder, 'property access order');
|
||||
}, 'Properties are read in ascending order by Unicode codepoint');
|
||||
|
||||
</script>
|
|
@ -0,0 +1,102 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Tests for processing a keyframes argument (easing)</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#processing-a-keyframes-argument">
|
||||
<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>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
test(() => {
|
||||
for (const [easing, expected] of gEasingParsingTests) {
|
||||
const effect = new KeyframeEffect(target, {
|
||||
left: ['10px', '20px'],
|
||||
easing: easing
|
||||
});
|
||||
assert_equals(effect.getKeyframes()[0].easing, expected,
|
||||
`resulting easing for '${easing}'`);
|
||||
}
|
||||
}, 'easing values are parsed correctly when set on a property-indexed'
|
||||
+ ' keyframe');
|
||||
|
||||
test(() => {
|
||||
for (const [easing, expected] of gEasingParsingTests) {
|
||||
const effect = new KeyframeEffect(target, [
|
||||
{ offset: 0, left: '10px', easing: easing },
|
||||
{ offset: 1, left: '20px' }
|
||||
]);
|
||||
assert_equals(effect.getKeyframes()[0].easing, expected,
|
||||
`resulting easing for '${easing}'`);
|
||||
}
|
||||
}, 'easing values are parsed correctly when using a keyframe sequence');
|
||||
|
||||
test(() => {
|
||||
for (const invalidEasing of gInvalidEasings) {
|
||||
assert_throws(new TypeError, () => {
|
||||
new KeyframeEffect(target, { easing: invalidEasing });
|
||||
}, `TypeError is thrown for easing '${invalidEasing}'`);
|
||||
}
|
||||
}, 'Invalid easing values are correctly rejected when set on a property-'
|
||||
+ 'indexed keyframe');
|
||||
|
||||
test(() => {
|
||||
for (const invalidEasing of gInvalidEasings) {
|
||||
assert_throws(new TypeError, () => {
|
||||
new KeyframeEffect(target, [{ easing: invalidEasing }]);
|
||||
}, `TypeError is thrown for easing '${invalidEasing}'`);
|
||||
}
|
||||
}, 'Invalid easing values are correctly rejected when using a keyframe'
|
||||
+ ' sequence');
|
||||
|
||||
test(() => {
|
||||
let propAccessCount = 0;
|
||||
const keyframe = {};
|
||||
const addProp = prop => {
|
||||
Object.defineProperty(keyframe, prop, {
|
||||
get: () => { propAccessCount++; },
|
||||
enumerable: true
|
||||
});
|
||||
}
|
||||
addProp('height');
|
||||
addProp('width');
|
||||
keyframe.easing = 'easy-peasy';
|
||||
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
new KeyframeEffect(target, keyframe);
|
||||
});
|
||||
assert_equals(propAccessCount, 2,
|
||||
'All properties were read before throwing the easing error');
|
||||
}, 'Errors from invalid easings on a property-indexed keyframe are thrown after reading all properties');
|
||||
|
||||
test(() => {
|
||||
let propAccessCount = 0;
|
||||
|
||||
const addProp = (keyframe, prop) => {
|
||||
Object.defineProperty(keyframe, prop, {
|
||||
get: () => { propAccessCount++; },
|
||||
enumerable: true
|
||||
});
|
||||
}
|
||||
|
||||
const kf1 = {};
|
||||
addProp(kf1, 'height');
|
||||
addProp(kf1, 'width');
|
||||
kf1.easing = 'easy-peasy';
|
||||
|
||||
const kf2 = {};
|
||||
addProp(kf2, 'height');
|
||||
addProp(kf2, 'width');
|
||||
|
||||
assert_throws({ name: 'TypeError' }, () => {
|
||||
new KeyframeEffect(target, [ kf1, kf2 ]);
|
||||
});
|
||||
assert_equals(propAccessCount, 4,
|
||||
'All properties were read before throwing the easing error');
|
||||
}, 'Errors from invalid easings on a keyframe sequence are thrown after reading all properties');
|
||||
|
||||
</script>
|
|
@ -1,331 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>KeyframeEffectReadOnly constructor tests</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#processing-a-keyframes-argument">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<script src="../../resources/keyframe-utils.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
// Test the "process a keyframe-like object" procedure.
|
||||
//
|
||||
// This file only tests the KeyframeEffectReadOnly constructor since it is
|
||||
// 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.
|
||||
|
||||
// Test that only animatable properties are accessed
|
||||
|
||||
var gNonAnimatableProps = [
|
||||
'animation', // Shorthands where all the longhand sub-properties are not
|
||||
// animatable, are also not animatable.
|
||||
'animationDelay',
|
||||
'animationDirection',
|
||||
'animationDuration',
|
||||
'animationFillMode',
|
||||
'animationIterationCount',
|
||||
'animationName',
|
||||
'animationPlayState',
|
||||
'animationTimingFunction',
|
||||
'transition',
|
||||
'transitionDelay',
|
||||
'transitionDuration',
|
||||
'transitionProperty',
|
||||
'transitionTimingFunction',
|
||||
'display',
|
||||
'unsupportedProperty',
|
||||
'font-size', // Supported property that uses dashes
|
||||
];
|
||||
|
||||
function TestKeyframe(testProp) {
|
||||
var _propAccessCount = 0;
|
||||
|
||||
Object.defineProperty(this, testProp, {
|
||||
get: function() { _propAccessCount++; },
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'propAccessCount', {
|
||||
get: function() { return _propAccessCount; }
|
||||
});
|
||||
}
|
||||
|
||||
function GetTestKeyframeSequence(testProp) {
|
||||
return [ new TestKeyframe(testProp) ]
|
||||
}
|
||||
|
||||
gNonAnimatableProps.forEach(function(prop) {
|
||||
test(function(t) {
|
||||
var testKeyframe = new TestKeyframe(prop);
|
||||
|
||||
new KeyframeEffectReadOnly(null, testKeyframe);
|
||||
|
||||
assert_equals(testKeyframe.propAccessCount, 0, 'Accessor not called');
|
||||
}, 'non-animatable property \'' + prop + '\' is not accessed when using'
|
||||
+ ' a property-indexed keyframe object');
|
||||
});
|
||||
|
||||
gNonAnimatableProps.forEach(function(prop) {
|
||||
test(function(t) {
|
||||
var testKeyframes = GetTestKeyframeSequence(prop);
|
||||
|
||||
new KeyframeEffectReadOnly(null, testKeyframes);
|
||||
|
||||
assert_equals(testKeyframes[0].propAccessCount, 0, 'Accessor not called');
|
||||
}, 'non-animatable property \'' + prop + '\' is not accessed when using'
|
||||
+ ' a keyframe sequence');
|
||||
});
|
||||
|
||||
// Test equivalent forms of property indexed and sequenced keyframe syntax
|
||||
|
||||
function assertEquivalentKeyframeSyntax(keyframesA, keyframesB) {
|
||||
var processedKeyframesA = new KeyframeEffectReadOnly(null, keyframesA).getKeyframes();
|
||||
var processedKeyframesB = new KeyframeEffectReadOnly(null, keyframesB).getKeyframes();
|
||||
assert_frame_lists_equal(processedKeyframesA, processedKeyframesB);
|
||||
}
|
||||
|
||||
var gEquivalentSyntaxTests = [
|
||||
{
|
||||
description: 'two properties with one value',
|
||||
indexedKeyframes: {
|
||||
left: '100px',
|
||||
opacity: ['1'],
|
||||
},
|
||||
sequencedKeyframes: [
|
||||
{left: '100px', opacity: '1'},
|
||||
],
|
||||
},
|
||||
{
|
||||
description: 'two properties with three values',
|
||||
indexedKeyframes: {
|
||||
left: ['10px', '100px', '150px'],
|
||||
opacity: ['1', '0', '1'],
|
||||
},
|
||||
sequencedKeyframes: [
|
||||
{left: '10px', opacity: '1'},
|
||||
{left: '100px', opacity: '0'},
|
||||
{left: '150px', opacity: '1'},
|
||||
],
|
||||
},
|
||||
{
|
||||
description: 'two properties with different numbers of values',
|
||||
indexedKeyframes: {
|
||||
left: ['0px', '100px', '200px'],
|
||||
opacity: ['0', '1']
|
||||
},
|
||||
sequencedKeyframes: [
|
||||
{left: '0px', opacity: '0'},
|
||||
{left: '100px'},
|
||||
{left: '200px', opacity: '1'},
|
||||
],
|
||||
},
|
||||
{
|
||||
description: 'same offset applied to all keyframes',
|
||||
indexedKeyframes: {
|
||||
left: ['0px', '100px'],
|
||||
offset: 0.5,
|
||||
},
|
||||
sequencedKeyframes: [
|
||||
{left: '0px', offset: 0.5},
|
||||
{left: '100px', offset: 0.5},
|
||||
],
|
||||
},
|
||||
{
|
||||
description: 'same easing applied to all keyframes',
|
||||
indexedKeyframes: {
|
||||
left: ['10px', '100px', '150px'],
|
||||
opacity: ['1', '0', '1'],
|
||||
easing: 'ease',
|
||||
},
|
||||
sequencedKeyframes: [
|
||||
{left: '10px', opacity: '1', easing: 'ease'},
|
||||
{left: '100px', opacity: '0', easing: 'ease'},
|
||||
{left: '150px', opacity: '1', easing: 'ease'},
|
||||
],
|
||||
},
|
||||
{
|
||||
description: 'same composite applied to all keyframes',
|
||||
indexedKeyframes: {
|
||||
left: ['0px', '100px'],
|
||||
composite: 'add',
|
||||
},
|
||||
sequencedKeyframes: [
|
||||
{left: '0px', composite: 'add'},
|
||||
{left: '100px', composite: 'add'},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
gEquivalentSyntaxTests.forEach(function({description, indexedKeyframes, sequencedKeyframes}) {
|
||||
test(function(t) {
|
||||
assertEquivalentKeyframeSyntax(indexedKeyframes, sequencedKeyframes);
|
||||
}, 'Equivalent property indexed and sequenced keyframes: ' + description);
|
||||
});
|
||||
|
||||
// Test handling of custom iterable objects.
|
||||
|
||||
function createIterable(iterations) {
|
||||
return {
|
||||
[Symbol.iterator]() {
|
||||
var i = 0;
|
||||
return {
|
||||
next() {
|
||||
return iterations[i++];
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test(() => {
|
||||
var effect = new KeyframeEffect(null, createIterable([
|
||||
{done: false, value: {left: '100px'}},
|
||||
{done: false, value: {left: '300px'}},
|
||||
{done: false, value: {left: '200px'}},
|
||||
{done: true},
|
||||
]));
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{offset: null, computedOffset: 0, easing: 'linear', left: '100px'},
|
||||
{offset: null, computedOffset: 0.5, easing: 'linear', left: '300px'},
|
||||
{offset: null, computedOffset: 1, easing: 'linear', left: '200px'},
|
||||
]);
|
||||
}, 'Custom iterator with basic keyframes.');
|
||||
|
||||
test(() => {
|
||||
var keyframes = createIterable([
|
||||
{done: false, value: {left: '100px'}},
|
||||
{done: false, value: {left: '300px'}},
|
||||
{done: false, value: {left: '200px'}},
|
||||
{done: true},
|
||||
]);
|
||||
keyframes.easing = 'ease-in-out';
|
||||
keyframes.offset = '0.1';
|
||||
var effect = new KeyframeEffect(null, keyframes);
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{offset: null, computedOffset: 0, easing: 'linear', left: '100px'},
|
||||
{offset: null, computedOffset: 0.5, easing: 'linear', left: '300px'},
|
||||
{offset: null, computedOffset: 1, easing: 'linear', left: '200px'},
|
||||
]);
|
||||
}, 'easing and offset are ignored on iterable objects.');
|
||||
|
||||
test(() => {
|
||||
var effect = new KeyframeEffect(null, createIterable([
|
||||
{done: false, value: {left: '100px', top: '200px'}},
|
||||
{done: false, value: {left: '300px'}},
|
||||
{done: false, value: {left: '200px', top: '100px'}},
|
||||
{done: true},
|
||||
]));
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{offset: null, computedOffset: 0, easing: 'linear', left: '100px', top: '200px'},
|
||||
{offset: null, computedOffset: 0.5, easing: 'linear', left: '300px'},
|
||||
{offset: null, computedOffset: 1, easing: 'linear', left: '200px', top: '100px'},
|
||||
]);
|
||||
}, 'Custom iterator with multiple properties specified.');
|
||||
|
||||
test(() => {
|
||||
var effect = new KeyframeEffect(null, createIterable([
|
||||
{done: false, value: {left: '100px'}},
|
||||
{done: false, value: {left: '250px', offset: 0.75}},
|
||||
{done: false, value: {left: '200px'}},
|
||||
{done: true},
|
||||
]));
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{offset: null, computedOffset: 0, easing: 'linear', left: '100px'},
|
||||
{offset: 0.75, computedOffset: 0.75, easing: 'linear', left: '250px'},
|
||||
{offset: null, computedOffset: 1, easing: 'linear', left: '200px'},
|
||||
]);
|
||||
}, 'Custom iterator with offset specified.');
|
||||
|
||||
test(() => {
|
||||
assert_throws({name: 'TypeError'}, function() {
|
||||
new KeyframeEffect(null, createIterable([
|
||||
{done: false, value: {left: '100px'}},
|
||||
{done: false, value: 1234},
|
||||
{done: false, value: {left: '200px'}},
|
||||
{done: true},
|
||||
]));
|
||||
});
|
||||
}, 'Custom iterator with non object keyframe should throw.');
|
||||
|
||||
test(() => {
|
||||
var effect = new KeyframeEffect(null, createIterable([
|
||||
{done: false, value: {left: ['100px', '200px']}},
|
||||
{done: true},
|
||||
]));
|
||||
assert_frame_lists_equal(effect.getKeyframes(), [
|
||||
{offset: null, computedOffset: 1, easing: 'linear'}
|
||||
]);
|
||||
}, 'Custom iterator with value list in keyframe should not contain invalid ' +
|
||||
'property value pair of list.');
|
||||
|
||||
test(function(t) {
|
||||
var keyframe = {};
|
||||
Object.defineProperty(keyframe, 'width', {value: '200px'});
|
||||
Object.defineProperty(keyframe, 'height', {
|
||||
value: '100px',
|
||||
enumerable: true});
|
||||
assert_equals(keyframe.width, '200px', 'width of keyframe is readable');
|
||||
assert_equals(keyframe.height, '100px', 'height of keyframe is readable');
|
||||
var anim = createDiv(t).animate([keyframe, {height: '200px'}], 1);
|
||||
assert_frame_lists_equal(anim.effect.getKeyframes(), [
|
||||
{offset: null, computedOffset: 0, easing: 'linear', height: '100px'},
|
||||
{offset: null, computedOffset: 1, easing: 'linear', height: '200px'},
|
||||
]);
|
||||
}, 'Only enumerable properties on keyframes are considered');
|
||||
|
||||
test(function(t) {
|
||||
var KeyframeParent = function() { this.width = '100px'; };
|
||||
KeyframeParent.prototype = { height: '100px' };
|
||||
var Keyframe = function() { this.top = '100px'; };
|
||||
Keyframe.prototype = Object.create(KeyframeParent.prototype);
|
||||
Object.defineProperty(Keyframe.prototype, 'left', {
|
||||
value: '100px',
|
||||
enumerable: 'true'});
|
||||
var keyframe = new Keyframe();
|
||||
var anim = createDiv(t).animate([keyframe, {top: '200px'}], 1);
|
||||
assert_frame_lists_equal(anim.effect.getKeyframes(), [
|
||||
{offset: null, computedOffset: 0, easing: 'linear', top: '100px'},
|
||||
{offset: null, computedOffset: 1, easing: 'linear', top: '200px'},
|
||||
]);
|
||||
}, 'Only properties defined directly on keyframes are considered');
|
||||
|
||||
test(function(t) {
|
||||
var keyframes = {};
|
||||
Object.defineProperty(keyframes, 'width', ['100px', '200px']);
|
||||
Object.defineProperty(keyframes, 'height', {
|
||||
value: ['100px', '200px'],
|
||||
enumerable: true});
|
||||
var anim = createDiv(t).animate(keyframes, 1);
|
||||
assert_frame_lists_equal(anim.effect.getKeyframes(), [
|
||||
{offset: null, computedOffset: 0, easing: 'linear', height: '100px'},
|
||||
{offset: null, computedOffset: 1, easing: 'linear', height: '200px'},
|
||||
]);
|
||||
}, 'Only enumerable properties on property indexed keyframes are considered');
|
||||
|
||||
test(function(t) {
|
||||
var KeyframesParent = function() { this.width = '100px'; };
|
||||
KeyframesParent.prototype = { height: '100px' };
|
||||
var Keyframes = function() { this.top = ['100px', '200px']; };
|
||||
Keyframes.prototype = Object.create(KeyframesParent.prototype);
|
||||
Object.defineProperty(Keyframes.prototype, 'left', {
|
||||
value: ['100px', '200px'],
|
||||
enumerable: 'true'});
|
||||
var keyframes = new Keyframes();
|
||||
var anim = createDiv(t).animate(keyframes, 1);
|
||||
assert_frame_lists_equal(anim.effect.getKeyframes(), [
|
||||
{offset: null, computedOffset: 0, easing: 'linear', top: '100px'},
|
||||
{offset: null, computedOffset: 1, easing: 'linear', top: '200px'},
|
||||
]);
|
||||
}, 'Only properties defined directly on property indexed keyframes are considered');
|
||||
|
||||
// FIXME: Test that properties are accessed in ascending order by Unicode
|
||||
// codepoint
|
||||
// (There is an existing test for this in
|
||||
// keyframe-effect/constructor.html that should be moved here.)
|
||||
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue