Update web-platform-tests to revision e03a9b1341ae9bdb1e4fa03765257b84d26fe2f1

This commit is contained in:
Josh Matthews 2017-10-16 11:11:04 -04:00
parent 7d05c76d18
commit 20a833eb75
5167 changed files with 4696 additions and 297370 deletions

View file

@ -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"] });

View file

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

View file

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

View file

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