Update web-platform-tests to revision 8a2ceb5f18911302b7a5c1cd2791f4ab50ad4326

This commit is contained in:
Josh Matthews 2017-10-12 09:25:50 -04:00
parent 462c272380
commit 1f531f66ea
5377 changed files with 174916 additions and 84369 deletions

View file

@ -190,7 +190,7 @@ var gCSSProperties = {
'border-image-outset': {
// https://drafts.csswg.org/css-backgrounds-3/#border-image-outset
types: [
{ type: 'discrete', options: [ [ '1 1 1 1', '5 5 5 5' ] ] }
{ type: 'discrete', options: [ [ '1 2 3 4', '5 6 7 8' ] ] }
]
},
'border-image-repeat': {
@ -202,7 +202,7 @@ var gCSSProperties = {
'border-image-slice': {
// https://drafts.csswg.org/css-backgrounds-3/#border-image-slice
types: [
{ type: 'discrete', options: [ [ '1 1 1 1', '5 5 5 5' ] ] }
{ type: 'discrete', options: [ [ '1 2 3 4', '5 6 7 8' ] ] }
]
},
'border-image-source': {
@ -216,7 +216,7 @@ var gCSSProperties = {
'border-image-width': {
// https://drafts.csswg.org/css-backgrounds-3/#border-image-width
types: [
{ type: 'discrete', options: [ [ '1 1 1 1', '5 5 5 5' ] ] }
{ type: 'discrete', options: [ [ '1 2 3 4', '5 6 7 8' ] ] }
]
},
'border-left-color': {
@ -471,8 +471,7 @@ var gCSSProperties = {
},
'fill-opacity': {
// https://svgwg.org/svg2-draft/painting.html#FillOpacityProperty
types: [
]
types: [ 'opacity' ]
},
'fill-rule': {
// https://svgwg.org/svg2-draft/painting.html#FillRuleProperty
@ -517,8 +516,7 @@ var gCSSProperties = {
},
'flood-opacity': {
// https://drafts.fxtf.org/filters/#propdef-flood-opacity
types: [
]
types: [ 'opacity' ]
},
'font-size': {
// https://drafts.csswg.org/css-fonts-3/#propdef-font-size
@ -532,8 +530,7 @@ var gCSSProperties = {
},
'font-stretch': {
// https://drafts.csswg.org/css-fonts-3/#propdef-font-stretch
types: [
]
types: [ 'fontStretch' ]
},
'font-style': {
// https://drafts.csswg.org/css-fonts/#propdef-font-style
@ -621,6 +618,16 @@ var gCSSProperties = {
{ type: 'discrete', options: [ [ 'sub', 'super' ] ] }
]
},
'font-variation-settings': {
// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-variation-settings
types: [
'fontVariationSettings',
{ type: 'discrete',
options: [ ['"wght" 1.1, "wdth" 1', '"wdth" 5'],
['"wdth" 5', 'normal']
] },
]
},
'font-weight': {
// https://drafts.csswg.org/css-fonts-3/#propdef-font-weight
types: [
@ -1225,8 +1232,7 @@ var gCSSProperties = {
},
'stop-opacity': {
// https://svgwg.org/svg2-draft/pservers.html#StopOpacityProperty
types: [
]
types: [ 'opacity' ]
},
'stroke': {
// https://svgwg.org/svg2-draft/painting.html#StrokeProperty
@ -1235,7 +1241,10 @@ var gCSSProperties = {
},
'stroke-dasharray': {
// https://svgwg.org/svg2-draft/painting.html#StrokeDasharrayProperty
types: [ 'dasharray' ]
types: [
'dasharray',
{ type: 'discrete', options: [ [ 'none', '10, 20' ] ] }
]
},
'stroke-dashoffset': {
// https://svgwg.org/svg2-draft/painting.html#StrokeDashoffsetProperty
@ -1464,16 +1473,43 @@ var gCSSProperties = {
};
function testAnimationSamples(animation, idlName, testSamples) {
var type = animation.effect.target.type;
var target = type
? animation.effect.target.parentElement
: animation.effect.target;
testSamples.forEach(function(testSample) {
const type = animation.effect.target.type;
const target = animation.effect.target.constructor.name === 'CSSPseudoElement'
? animation.effect.target.parentElement
: animation.effect.target;
testSamples.forEach(testSample => {
animation.currentTime = testSample.time;
assert_equals(getComputedStyle(target, type)[idlName],
testSample.expected,
'The value should be ' + testSample.expected +
' at ' + testSample.time + 'ms');
`The value should be ${testSample.expected}` +
` at ${testSample.time}ms`);
});
}
function toOrderedArray(string) {
return string.split(/\s*,\s/).sort();
}
// This test is for some list-based CSS properties such as font-variant-settings
// don't specify an order for serializing computed values.
// This test is for such the property.
function testAnimationSamplesWithAnyOrder(animation, idlName, testSamples) {
const type = animation.effect.target.type;
const target = animation.effect.target.constructor.name === 'CSSPseudoElement'
? animation.effect.target.parentElement
: animation.effect.target;
testSamples.forEach(testSample => {
animation.currentTime = testSample.time;
// Convert to array and sort the expected and actual value lists first
// before comparing them.
const computedValues =
toOrderedArray(getComputedStyle(target, type)[idlName]);
const expectedValues = toOrderedArray(testSample.expected);
assert_array_equals(computedValues, expectedValues,
`The computed values should be ${expectedValues}` +
` at ${testSample.time}ms`);
});
}

View file

@ -884,6 +884,35 @@ const transformListType = {
[{ time: 500, expected: rotate3dToMatrix(1, 1, 0, Math.PI * 2 / 4) }]);
}, property + ': matrix3d');
// This test aims for forcing the two mismatched transforms to be
// decomposed into matrix3d before interpolation. Therefore, we not only
// test the interpolation, but also test the 3D matrix decomposition.
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation =
target.animate({ [idlName]: ['scale(0.3)',
// scale(0.5) translateZ(1px)
'matrix3d(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1)'] },
1000);
testAnimationSampleMatrices(animation, idlName,
[{ time: 500, expected: [ 0.4, 0, 0, 0,
0, 0.4, 0, 0,
0, 0, 1, 0,
0, 0, 0.5, 1] }]);
}, property + ': mismatched 3D transforms');
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation =
target.animate({ [idlName]: ['rotateY(60deg)', 'none' ] }, 1000);
testAnimationSampleMatrices(animation, idlName,
// rotateY(30deg) == rotate3D(0, 1, 0, 30deg)
[{ time: 500, expected: rotate3dToMatrix(0, 1, 0, Math.PI / 6) }]);
}, property + ': rotateY');
},
testAddition: function(property, setup) {
@ -1198,10 +1227,190 @@ const transformListType = {
[{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) },
{ time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]);
}, property + ': matrix3d');
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var matrixArray = [ 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 1, 1 ];
target.style[idlName] = createMatrixFromArray(matrixArray);
var animation =
target.animate({ [idlName]: [ 'none', 'none' ] },
{ duration: 1000, fill: 'both', composite: 'accumulate' });
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: matrixArray },
{ time: 1000, expected: matrixArray }]);
}, property + ': none');
},
};
const filterListType = {
testInterpolation: function(property, setup) {
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation = target.animate({ [idlName]:
['blur(10px)', 'blur(50px)'] },
1000);
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'blur(30px)' }]);
}, property + ': blur function' );
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation = target.animate({ [idlName]: ['hue-rotate(0deg)',
'hue-rotate(100deg)'] },
1000);
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'hue-rotate(50deg)' }]);
}, property + ': hue-rotate function with same unit(deg)' );
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation = target.animate({ [idlName]: ['hue-rotate(10deg)',
'hue-rotate(100rad)'] },
1000);
// 10deg = 0.1745rad.
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'hue-rotate(50.0873rad)' }]);
}, property + ': hue-rotate function with different unit(deg -> rad)');
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation = target.animate(
{ [idlName]:
['drop-shadow(10px 10px 10px rgba(255, 0, 0, 0.4))',
'drop-shadow(50px 50px 50px rgba(0, 0, 255, 0.8))'] },
1000);
testAnimationSamples(
animation, idlName,
[{ time: 500,
expected: 'drop-shadow(rgba(85, 0, 170, 0.6) 30px 30px 30px)' }]);
}, property + ': drop-shadow function' );
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation = target.animate(
{ [idlName]:
['brightness(0.1) contrast(0.1) grayscale(0.1) invert(0.1) ' +
'opacity(0.1) saturate(0.1) sepia(0.1)',
'brightness(0.5) contrast(0.5) grayscale(0.5) invert(0.5) ' +
'opacity(0.5) saturate(0.5) sepia(0.5)'] },
1000);
testAnimationSamples(animation, idlName,
[{ time: 500,
expected: 'brightness(0.3) contrast(0.3) grayscale(0.3) ' +
'invert(0.3) opacity(0.3) saturate(0.3) sepia(0.3)' }]);
}, property + ': percentage or numeric-specifiable functions' +
'(number value)');
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation = target.animate(
{ [idlName]:
['brightness(10%) contrast(10%) grayscale(10%) invert(10%) ' +
'opacity(10%) saturate(10%) sepia(10%)',
'brightness(50%) contrast(50%) grayscale(50%) invert(50%) ' +
'opacity(50%) saturate(50%) sepia(50%)'] },
1000);
testAnimationSamples(animation, idlName,
[{ time: 500,
expected: 'brightness(0.3) contrast(0.3) grayscale(0.3) ' +
'invert(0.3) opacity(0.3) saturate(0.3) sepia(0.3)' }]);
}, property + ': percentage or numeric-specifiable functions' +
'(percentage value)');
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation = target.animate(
{ [idlName]:
// To make missing filter-function-lists, specified the grayscale.
['grayscale(0)',
'grayscale(1) brightness(0) contrast(0) opacity(0) saturate(0)' ]},
1000);
testAnimationSamples(animation, idlName,
[{ time: 500,
expected: 'grayscale(0.5) brightness(0.5) contrast(0.5) ' +
'opacity(0.5) saturate(0.5)' }]);
}, property + ': interpolate different length of filter-function-list ' +
' with function which lacuna value is 1');
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation = target.animate(
{ [idlName]:
// To make missing filter-function-lists, specified the opacity.
['opoacity(1)',
'opacity(0) grayscale(1) invert(1) sepia(1) blur(10px)'] },
1000);
testAnimationSamples(animation, idlName,
[{ time: 500,
expected:
'opacity(0.5) grayscale(0.5) invert(0.5) sepia(0.5) blur(5px)' }]);
}, property + ': interpolate different length of filter-function-list ' +
' with function which lacuna value is 0');
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
target.style.color = "rgba(255, 0, 0, 0.4)";
var animation = target.animate(
{ [idlName]:
['blur(0px)',
'blur(10px) drop-shadow(10px 10px 10px rgba(0, 0, 255, 0.8))'] },
1000);
testAnimationSamples(animation, idlName,
[{ time: 500,
// The lacuna value of drop-shadow's color is taken from
// the color property.
expected: 'blur(5px) drop-shadow(rgba(85, 0, 170, 0.6) 5px 5px 5px' }]);
}, property + ': interpolate different length of filter-function-list ' +
'with drop-shadow function');
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation = target.animate({ [idlName]: ['none', 'blur(10px)'] },
1000);
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'blur(5px)' }]);
}, property + ': interpolate from none');
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation = target.animate(
{ [idlName]:
['blur(0px) url(\"#f1\")',
'blur(10px) url(\"#f2\")']},
1000);
testAnimationSamples(animation, idlName,
[{ time: 499, expected: 'blur(0px) url(\"#f1\")' },
{ time: 500, expected: 'blur(10px) url(\"#f2\")' }]);
}, property + ': url function (interpoalte as discrete)');
},
testAddition: function(property, setup) {
test(function(t) {
var idlName = propertyToIDL(property);
@ -1331,6 +1540,18 @@ const textShadowListType = {
[{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px, '
+ 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]);
}, property + ': mismatched list length (from shorter to longer)');
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
target.style.color = 'rgb(0, 255, 0)';
var animation =
target.animate({ [idlName]: [ 'currentcolor 0px 0px 0px',
'currentcolor 10px 10px 10px'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(0, 255, 0) 5px 5px 5px' }]);
}, property + ': with currentcolor');
},
testAddition: function(property, setup) {
@ -1440,6 +1661,18 @@ const boxShadowListType = {
[{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px 10px, '
+ 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]);
}, property + ': mismatched list length (from longer to shorter)');
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
target.style.color = 'rgb(0, 255, 0)';
var animation =
target.animate({ [idlName]: [ 'currentcolor 0px 0px 0px 0px',
'currentcolor 10px 10px 10px 10px'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(0, 255, 0) 5px 5px 5px 5px' }]);
}, property + ': with currentcolor');
},
testAddition: function(property, setup) {
@ -1610,6 +1843,118 @@ const dasharrayType = {
},
}
const fontStretchType = {
testInterpolation: function(property, setup) {
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation =
target.animate({ [idlName]: ['ultra-condensed', 'extra-condensed'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 499, expected: 'ultra-condensed' },
{ time: 500, expected: 'extra-condensed' }]);
}, property + ' supports animating as a font-stretch (adjacent values)');
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
var animation =
target.animate({ [idlName]: ['ultra-condensed', 'condensed'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'extra-condensed' }]);
}, property + ' supports animating as a font-stretch (between value)');
},
testAdditionOrAccumulation: function(property, setup, composite) {
test(function(t) {
var idlName = propertyToIDL(property);
var target = createTestElement(t, setup);
target.style[idlName] = 'condensed';
var animation =
target.animate({ [idlName]: ['expanded', 'ultra-expanded'] },
{ duration: 1000, composite: composite });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'normal' },
{ time: 250, expected: 'semi-expanded' }]);
}, property + ' uses font-stretch behavior for composite type ' + composite);
},
testAddition: function(property, setup) {
this.testAdditionOrAccumulation(property, setup, 'add');
},
testAccumulation: function(property, setup) {
this.testAdditionOrAccumulation(property, setup, 'accumulate');
},
}
const fontVariationSettingsType = {
testInterpolation: (property, setup) => {
test(t => {
const idlName = propertyToIDL(property);
const target = createTestElement(t, setup);
const animation =
target.animate({ [idlName]: ['"wght" 1.1', '"wght" 1.5'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: '"wght" 1.1' },
{ time: 250, expected: '"wght" 1.2' },
{ time: 750, expected: '"wght" 1.4' } ]);
}, `${property} supports animation as float`);
test(t => {
const idlName = propertyToIDL(property);
const target = createTestElement(t, setup);
const animation =
target.animate({ [idlName]: ['"wdth" 1, "wght" 1.1',
'"wght" 1.5, "wdth" 5'] },
{ duration: 1000, fill: 'both' });
testAnimationSamplesWithAnyOrder(
animation, idlName,
[{ time: 0, expected: '"wdth" 1, "wght" 1.1' },
{ time: 250, expected: '"wdth" 2, "wght" 1.2' },
{ time: 750, expected: '"wdth" 4, "wght" 1.4' } ]);
}, `${property} supports animation as float with multiple tags`);
test(t => {
const idlName = propertyToIDL(property);
const target = createTestElement(t, setup);
const animation =
target.animate({ [idlName]: ['"wdth" 1, "wght" 1.1',
'"wght" 10, "wdth" 5, "wght" 1.5'] },
{ duration: 1000, fill: 'both' });
testAnimationSamplesWithAnyOrder(
animation, idlName,
[{ time: 250, expected: '"wdth" 2, "wght" 1.2' },
{ time: 750, expected: '"wdth" 4, "wght" 1.4' } ]);
}, `${property} supports animation as float with multiple duplicate tags`);
},
testAdditionOrAccumulation: (property, setup, composite) => {
test(t => {
const idlName = propertyToIDL(property);
const target = createTestElement(t, setup);
target.style[idlName] = '"wght" 1';
const animation =
target.animate({ [idlName]: ['"wght" 1.1', '"wght" 1.5'] },
{ duration: 1000, composite: composite });
testAnimationSamples(animation, idlName,
[{ time: 250, expected: '"wght" 2.2' },
{ time: 750, expected: '"wght" 2.4' } ]);
}, `${property} with composite type ${composite}`);
},
testAddition: function(property, setup) {
this.testAdditionOrAccumulation(property, setup, 'add');
},
testAccumulation: function(property, setup) {
this.testAdditionOrAccumulation(property, setup, 'accumulate');
},
}
const types = {
color: colorType,
discrete: discreteType,
@ -1629,5 +1974,6 @@ const types = {
rect: rectType,
position: positionType,
dasharray: dasharrayType,
fontStretch: fontStretchType,
fontVariationSettings: fontVariationSettingsType,
};

View file

@ -1,210 +0,0 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Keyframe spacing tests on filters</title>
<link rel="help" href="https://w3c.github.io/web-animations/#spacing-keyframes">
<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";
// Help function for testing the computed offsets by the distance array.
function assert_animation_offsets(anim, dist) {
const frames = anim.effect.getKeyframes();
const cumDist = dist.reduce( (prev, curr) => {
prev.push(prev.length == 0 ? curr : curr + prev[prev.length - 1]);
return prev;
}, []);
const total = cumDist[cumDist.length - 1];
for (var i = 0; i < frames.length; ++i) {
assert_equals(frames[i].computedOffset, cumDist[i] / total,
'computedOffset of frame ' + i);
}
}
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'blur(1px)'},
{ filter: 'none' }, // The default value is 0px.
{ filter: 'blur(10px)' },
{ filter: 'blur(8px)' } ],
{ spacing: 'paced(filter)' });
var dist = [ 0, 1, 10, (10 - 8) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on blur' );
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'brightness(50%)'},
{ filter: 'none' }, // The default value is 1.
{ filter: 'brightness(2)' },
{ filter: 'brightness(175%)' } ],
{ spacing: 'paced(filter)' });
var dist = [ 0, (1 - 0.5), (2 - 1), (2.0 - 1.75) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on brightness' );
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'contrast(50%)'},
{ filter: 'none' }, // The default value is 1.
{ filter: 'contrast(2)' },
{ filter: 'contrast(175%)' } ],
{ spacing: 'paced(filter)' });
var dist = [ 0, (1 - 0.5), (2 - 1), (2.0 - 1.75) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on contrast' );
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'drop-shadow(10px 10px 10px blue)'},
{ filter: 'none' },
// none filter: 'drop-shadow(0, 0, 0, rgba(0, 0, 0, 0))'
{ filter: 'drop-shadow(5px 5px 1px black)' },
{ filter: 'drop-shadow(20px 20px yellow)' } ],
{ spacing: 'paced(filter)' });
// Blue: rgba(0, 0, 255, 1.0) = rgba( 0%, 0%, 100%, 100%).
// Black: rgba(0, 0, 0, 1.0) = rgba( 0%, 0%, 0%, 100%).
// Yellow: rgba(255, 255, 0, 1.0) = rgba(100%, 100%, 0%, 100%).
var dist = [ 0,
Math.sqrt(10 * 10 + 10 * 10 + 10 * 10 + (1 * 1 + 1 * 1)),
Math.sqrt(5 * 5 + 5 * 5 + 1 * 1 + (1 * 1)),
Math.sqrt(15 * 15 + 15 * 15 + 1 * 1 + (1 * 1 + 1 * 1)) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on drop-shadow' );
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'drop-shadow(10px 10px 10px)'},
{ filter: 'drop-shadow(0 0)' },
{ filter: 'drop-shadow(5px 5px 1px black)' },
{ filter: 'drop-shadow(20px 20px yellow)' } ],
{ spacing: 'paced(filter)' });
// Black: rgba(0, 0, 0, 1.0) = rgba( 0%, 0%, 0%, 100%).
// Yellow: rgba(255, 255, 0, 1.0) = rgba(100%, 100%, 0%, 100%).
var dist = [ 0,
Math.sqrt(10 * 10 + 10 * 10 + 10 * 10),
0, // The distance is zero because the 2nd frame uses no-color.
Math.sqrt(15 * 15 + 15 * 15 + 1 * 1 + (1 * 1 + 1 * 1)) ];
assert_animation_offsets(anim, dist);
}, 'Test getting zero distance when computing distance between ' +
'color and no-color on drop-shadow');
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'grayscale(50%)'},
{ filter: 'none' }, // The default value is 0.
// Values of grayscale over 100% are clamped to 1.
{ filter: 'grayscale(2)' },
{ filter: 'grayscale(75%)' } ],
{ spacing: 'paced(filter)' });
var dist = [ 0, 0.5, 1, (1.0 - 0.75) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on grayscale' );
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'hue-rotate(180deg)'},
{ filter: 'none' }, // The default value is 0deg.
{ filter: 'hue-rotate(720deg)' },
{ filter: 'hue-rotate(-180deg)' } ],
{ spacing: 'paced(filter)' });
var dist = [ 0, 180, 720, 720 + 180 ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on hue-rotate' );
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'invert(50%)'},
{ filter: 'none' }, // The default value is 0.
// Values of invert over 100% are clamped to 1.
{ filter: 'invert(2)' },
{ filter: 'invert(75%)' } ],
{ spacing: 'paced(filter)' });
var dist = [ 0, 0.5, 1, (1.0 - 0.75) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on invert' );
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'opacity(50%)'},
{ filter: 'none' }, // The default value is 1.
// Values of opacity over 100% are clamped to 1.
{ filter: 'opacity(2)' },
{ filter: 'opacity(75%)' } ],
{ spacing: 'paced(filter)' });
var dist = [ 0, (1 - 0.5), (1 - 1), (1.0 - 0.75) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on opacity' );
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'saturate(50%)'},
{ filter: 'none' }, // The default value is 1.
{ filter: 'saturate(2)' },
{ filter: 'saturate(175%)' } ],
{ spacing: 'paced(filter)' });
var dist = [ 0, (1 - 0.5), (2 - 1), (2.0 - 1.75) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on saturate' );
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'sepia(50%)'},
{ filter: 'none' }, // The default value is 0.
// Values of sepia over 100% are clamped to 1.
{ filter: 'sepia(2)' },
{ filter: 'sepia(75%)' } ],
{ spacing: 'paced(filter)' });
var dist = [ 0, 0.5, 1, (1.0 - 0.75) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on sepia' );
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'grayscale(50%) opacity(100%) blur(5px)' },
{ filter: 'none' },
// none filter: 'grayscale(0) opacity(1) blur(0px)'
{ filter: 'grayscale(100%) opacity(50%) blur(1px)' },
{ filter: 'grayscale(75%) opacity(50%)' } ],
{ spacing: 'paced(filter)' });
var dist = [ 0,
Math.sqrt(0.5 * 0.5 + 5 * 5),
Math.sqrt(1 * 1 + 0.5 * 0.5 + 1 * 1),
Math.sqrt(0.25 * 0.25 + 1 * 1) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on filter function lists with consistent sequence' );
test(function(t) {
var anim =
createDiv(t).animate([ { filter: 'grayscale(50%) opacity(100%)' },
{ filter: 'opacity(10%) grayscale(50%)' },
{ filter: 'grayscale(100%) opacity(50%) blur(1px)' },
{ filter: 'grayscale(75%) opacity(50%)' } ],
{ spacing: 'paced(filter)' });
var dist = [ 0,
0,
0,
Math.sqrt(0.25 * 0.25 + 1 * 1) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on filter function lists with inconsistent sequence' );
</script>
</body>

View file

@ -1,152 +0,0 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Keyframe spacing tests on shapes</title>
<link rel="help" href="https://w3c.github.io/web-animations/#spacing-keyframes">
<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";
// Help function for testing the computed offsets by the distance array.
function assert_animation_offsets(anim, dist) {
const frames = anim.effect.getKeyframes();
const cumDist = dist.reduce( (prev, curr) => {
prev.push(prev.length == 0 ? curr : curr + prev[prev.length - 1]);
return prev;
}, []);
const total = cumDist[cumDist.length - 1];
for (var i = 0; i < frames.length; ++i) {
assert_equals(frames[i].computedOffset, cumDist[i] / total,
'computedOffset of frame ' + i);
}
}
test(function(t) {
var anim =
createDiv(t).animate([ { clipPath: 'circle(20px)' },
{ clipPath: 'ellipse(10px 20px)' },
{ clipPath: 'polygon(50px 0px, 100px 50px, ' +
' 50px 100px, 0px 50px)' },
{ clipPath: 'inset(20px round 10px)' } ],
{ spacing: 'paced(clip-path)' });
const frames = anim.effect.getKeyframes();
const slots = frames.length - 1;
for (var i = 0; i < frames.length; ++i) {
assert_equals(frames[i].computedOffset, i / slots,
'computedOffset of frame ' + i);
}
}, 'Test falling back to distribute spacing when using different basic shapes');
test(function(t) {
var anim =
createDiv(t).animate([ { clipPath: 'circle(10px)' },
{ clipPath: 'circle(20px) content-box' },
{ clipPath: 'circle(70px)' },
{ clipPath: 'circle(10px) padding-box' } ],
{ spacing: 'paced(clip-path)' });
const frames = anim.effect.getKeyframes();
const slots = frames.length - 1;
for (var i = 0; i < frames.length; ++i) {
assert_equals(frames[i].computedOffset, i / slots,
'computedOffset of frame ' + i);
}
}, 'Test falling back to distribute spacing when using different ' +
'reference boxes');
test(function(t) {
// 1st: circle(calc(20px) at calc(20px + 0%) calc(10px + 0%))
// 2nd: circle(calc(50px) at calc(10px + 0%) calc(10px + 0%))
// 3rd: circle(70px at calc(10px + 0%) calc(50px + 0%))
// 4th: circle(10px at calc(50px + 0%) calc(30px + 0%))
var anim =
createDiv(t).animate([ { clipPath: 'circle(calc(10px + 10px) ' +
' at 20px 10px)' },
{ clipPath: 'circle(calc(20px + 30px) ' +
' at 10px 10px)' },
{ clipPath: 'circle(70px at 10px 50px)' },
{ clipPath: 'circle(10px at 50px 30px)' } ],
{ spacing: 'paced(clip-path)' });
var dist = [ 0,
Math.sqrt(30 * 30 + 10 * 10),
Math.sqrt(20 * 20 + 40 * 40),
Math.sqrt(60 * 60 + 40 * 40 + 20 * 20) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on circle' );
test(function(t) {
// 1st: ellipse(20px calc(20px) at calc(0px + 50%) calc(0px + 50%))
// 2nd: ellipse(20px calc(50px) at calc(0px + 50%) calc(0px + 50%))
// 3rd: ellipse(30px 70px at calc(0px + 50%) calc(0px + 50%))
// 4th: ellipse(30px 10px at calc(0px + 50%) calc(0px + 50%))
var anim =
createDiv(t).animate([ { clipPath: 'ellipse(20px calc(10px + 10px))' },
{ clipPath: 'ellipse(20px calc(20px + 30px))' },
{ clipPath: 'ellipse(30px 70px)' },
{ clipPath: 'ellipse(30px 10px)' } ],
{ spacing: 'paced(clip-path)' });
var dist = [ 0,
Math.sqrt(30 * 30),
Math.sqrt(10 * 10 + 20 * 20),
Math.sqrt(60 * 60) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on ellipse' );
test(function(t) {
// 1st: polygon(nonzero, 50px 0px, 100px 50px, 50px 100px, 0px 50px)
// 2nd: polygon(nonzero, 40px 0px, 100px 70px, 10px 100px, 0px 70px)
// 3rd: polygon(nonzero, 100px 0px, 100px 100px, 10px 80px, 0px 50px)
// 4th: polygon(nonzero, 100px 100px, -10px 100px, 20px 80px, 20px 50px)
var anim =
createDiv(t).animate([ { clipPath: 'polygon(50px 0px, 100px 50px, ' +
' 50px 100px, 0px 50px)' },
{ clipPath: 'polygon(40px 0px, 100px 70px, ' +
' 10px 100px, 0px 70px)' },
{ clipPath: 'polygon(100px 0px, 100px 100px, ' +
' 10px 80px, 0px 50px)' },
{ clipPath: 'polygon(100px 100px, -10px 100px, ' +
' 20px 80px, 20px 50px)' } ],
{ spacing: 'paced(clip-path)' });
var dist = [ 0,
Math.sqrt(10 * 10 + 20 * 20 + 40 * 40 + 20 * 20),
Math.sqrt(60 * 60 + 30 * 30 + 20 * 20 + 20 * 20),
Math.sqrt(100 * 100 + 110 * 110 + 10 * 10 + 20 * 20) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on polygon' );
test(function(t) {
// Note: Rounding corners are 4 CSS pair values and
// each pair has x & y components.
// 1st: inset(5px 5px 5px 5px round 40px 30px 20px 5px / 40px 30px 20px 5px)
// 2nd: inset(10px 5px 10px 5px round 50px 60px / 50px 60px)
// 3rd: inset(40px 40px 40px 40px round 10px / 10px)
// 4th: inset(30px 40px 30px 40px round 20px / 20px)
var anim =
createDiv(t).animate([ { clipPath: 'inset(5px 5px 5px 5px ' +
' round 40px 30px 20px 5px)' },
{ clipPath: 'inset(10px 5px round 50px 60px)' },
{ clipPath: 'inset(40px 40px round 10px)' },
{ clipPath: 'inset(30px 40px round 20px)' } ],
{ spacing: 'paced(clip-path)' });
var dist = [ 0,
Math.sqrt(5 * 5 * 2 + (50 - 40) * (50 - 40) * 2 +
(60 - 30) * (60 - 30) * 2 +
(50 - 20) * (50 - 20) * 2 +
(60 - 5) * (60 - 5) * 2),
Math.sqrt(30 * 30 * 2 + 35 * 35 * 2 + (50 - 10) * (50 - 10) * 4 +
(60 - 10) * (60 - 10) * 4),
Math.sqrt(10 * 10 * 2 + (20 - 10) * (20 - 10) * 8) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on inset' );
</script>
</body>

View file

@ -1,242 +0,0 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Keyframe spacing tests on transform</title>
<link rel="help" href="https://w3c.github.io/web-animations/#spacing-keyframes">
<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";
const pi = Math.PI;
const cos = Math.cos;
const sin = Math.sin;
const tan = Math.tan;
const sqrt = Math.sqrt;
// Help function for testing the computed offsets by the distance array.
function assert_animation_offsets(anim, dist) {
const epsilon = 0.00000001;
const frames = anim.effect.getKeyframes();
const cumDist = dist.reduce( (prev, curr) => {
prev.push(prev.length == 0 ? curr : curr + prev[prev.length - 1]);
return prev;
}, []);
const total = cumDist[cumDist.length - 1];
for (var i = 0; i < frames.length; ++i) {
assert_approx_equals(frames[i].computedOffset, cumDist[i] / total,
epsilon, 'computedOffset of frame ' + i);
}
}
function getAngleDist(rotate1, rotate2) {
function quaternion(axis, angle) {
var x = axis[0] * sin(angle/2.0);
var y = axis[1] * sin(angle/2.0);
var z = axis[2] * sin(angle/2.0);
var w = cos(angle/2.0);
return { 'x': x, 'y': y, 'z': z, 'w': w };
}
var q1 = quaternion(rotate1.axis, rotate1.angle);
var q2 = quaternion(rotate2.axis, rotate2.angle);
var dotProduct = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
return 2.0 * Math.acos(dotProduct);
}
function createMatrix(elements, Is3D) {
return (Is3D ? "matrix3d" : "matrix") + "(" + elements.join() + ")";
}
test(function(t) {
var anim = createDiv(t).animate([ { transform: "none" },
{ transform: "translate(-20px)" },
{ transform: "translate(100px)" },
{ transform: "translate(50px)"} ],
{ spacing: "paced(transform)" });
assert_animation_offsets(anim, [ 0, 20, 120, 50 ]);
}, 'Test spacing on translate' );
test(function(t) {
var anim =
createDiv(t).animate([ { transform: "none" },
{ transform: "translate3d(-20px, 10px, 100px)" },
{ transform: "translate3d(100px, 200px, 50px)" },
{ transform: "translate(50px, -10px)"} ],
{ spacing: "paced(transform)" });
var dist = [ 0,
sqrt(20 * 20 + 10 * 10 + 100 * 100),
sqrt(120 * 120 + 190 * 190 + 50 * 50),
sqrt(50 * 50 + 210 * 210 + 50 * 50) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on translate3d' );
test(function(t) {
var anim = createDiv(t).animate([ { transform: "scale(0.5)" },
{ transform: "scale(4.5)" },
{ transform: "scale(2.5)" },
{ transform: "none"} ],
{ spacing: "paced(transform)" });
assert_animation_offsets(anim, [ 0, 4.0, 2.0, 1.5 ]);
}, 'Test spacing on scale' );
test(function(t) {
var anim = createDiv(t).animate([ { transform: "scale(0.5, 0.5)" },
{ transform: "scale3d(4.5, 5.0, 2.5)" },
{ transform: "scale3d(2.5, 1.0, 2.0)" },
{ transform: "scale3d(1, 0.5, 1.0)"} ],
{ spacing:"paced(transform)" });
var dist = [ 0,
sqrt(4.0 * 4.0 + 4.5 * 4.5 + 1.5 * 1.5),
sqrt(2.0 * 2.0 + 4.0 * 4.0 + 0.5 * 0.5),
sqrt(1.5 * 1.5 + 0.5 * 0.5 + 1.0 * 1.0) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on scale3d' );
test(function(t) {
var anim = createDiv(t).animate([ { transform: "rotate(60deg)" },
{ transform: "none" },
{ transform: "rotate(720deg)" },
{ transform: "rotate(-360deg)"} ],
{ spacing: "paced(transform)" });
assert_animation_offsets(anim, [ 0, 60, 720, 1080 ]);
}, 'Test spacing on rotate' );
test(function(t) {
var anim = createDiv(t).animate([ { transform: "rotate3d(1,0,0,60deg)" },
{ transform: "rotate3d(1,0,0,70deg)" },
{ transform: "rotate3d(0,0,1,-110deg)" },
{ transform: "rotate3d(1,0,0,219deg)"} ],
{ spacing: "paced(transform)" });
var dist = [ 0,
getAngleDist({ axis: [1,0,0], angle: 60 * pi / 180 },
{ axis: [1,0,0], angle: 70 * pi / 180 }),
getAngleDist({ axis: [0,1,0], angle: 70 * pi / 180 },
{ axis: [0,0,1], angle: -110 * pi / 180 }),
getAngleDist({ axis: [0,0,1], angle: -110 * pi / 180 },
{ axis: [1,0,0], angle: 219 * pi / 180 }) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on rotate3d' );
test(function(t) {
var anim = createDiv(t).animate([ { transform: "skew(60deg)" },
{ transform: "none" },
{ transform: "skew(-90deg)" },
{ transform: "skew(90deg)"} ],
{ spacing: "paced(transform)" });
assert_animation_offsets(anim, [ 0, 60, 90, 180 ]);
}, 'Test spacing on skew' );
test(function(t) {
var anim = createDiv(t).animate([ { transform: "skew(60deg, 30deg)" },
{ transform: "none" },
{ transform: "skew(-90deg, 60deg)" },
{ transform: "skew(90deg, 60deg)"} ],
{ spacing: "paced(transform)" });
var dist = [ 0,
sqrt(60 * 60 + 30 * 30),
sqrt(90 * 90 + 60 * 60),
sqrt(180 * 180 + 0) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on skew along both X and Y' );
test(function(t) {
// We calculate the distance of two perspective functions by converting them
// into two matrix3ds, and then do matrix decomposition to get two
// perspective vectors, so the equivalent perspective vectors are:
// perspective 1: (0, 0, -1/128, 1);
// perspective 2: (0, 0, -1/infinity = 0, 1);
// perspective 3: (0, 0, -1/1024, 1);
// perspective 4: (0, 0, -1/32, 1);
var anim = createDiv(t).animate([ { transform: "perspective(128px)" },
{ transform: "none" },
{ transform: "perspective(1024px)" },
{ transform: "perspective(32px)"} ],
{ spacing: "paced(transform)" });
assert_animation_offsets(anim, [ 0, 1/128, 1/1024, 1/32 - 1/1024 ]);
}, 'Test spacing on perspective' );
test(function(t) {
var anim =
createDiv(t).animate([ { transform: "none" },
{ transform: "rotate(180deg) translate(0px)" },
{ transform: "rotate(180deg) translate(1000px)" },
{ transform: "rotate(360deg) translate(1000px)"} ],
{ spacing: "paced(transform)" });
var dist = [ 0,
sqrt(pi * pi + 0),
sqrt(1000 * 1000),
sqrt(pi * pi + 0) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on matched transform lists' );
test(function(t) {
// matrix1 => translate(100px, 50px), skewX(60deg).
// matrix2 => translate(1000px), rotate(180deg).
// matrix3 => translate(1000px), scale(1.5, 0.7).
const matrix1 = createMatrix([ 1, 0, tan(pi/4.0), 1, 100, 50 ]);
const matrix2 = createMatrix([ cos(pi), sin(pi),
-sin(pi), cos(pi),
1000, 0 ]);
const matrix3 = createMatrix([ 1.5, 0, 0, 0.7, 1000, 0 ]);
var anim = createDiv(t).animate([ { transform: "none" },
{ transform: matrix1 },
{ transform: matrix2 },
{ transform: matrix3 } ],
{ spacing: "paced(transform)" });
var dist = [ 0,
sqrt(100 * 100 + 50 * 50 + pi/4 * pi/4),
sqrt(900 * 900 + 50 * 50 + pi * pi + pi/4 * pi/4),
sqrt(pi * pi + 0.5 * 0.5 + 0.3 * 0.3) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on matrix' );
test(function(t) {
// matrix1 => translate3d(100px, 50px, -10px), skew(60deg).
// matrix2 => translate3d(1000px, 0, 0), rotate3d(1, 0, 0, 180deg).
// matrix3 => translate3d(1000px, 0, 0), scale3d(1.5, 0.7, 2.2).
const matrix1 = createMatrix([ 1, 0, 0, 0,
tan(pi/4.0), 1, 0, 0,
0, 0, 1, 0,
100, 50, -10, 1 ], true);
const matrix2 = createMatrix([ 1, 0, 0, 0,
0, cos(pi), sin(pi), 0,
0, -sin(pi), cos(pi), 0,
1000, 0, 0, 1 ], true);
const matrix3 = createMatrix([ 1.5, 0, 0, 0,
0, 0.7, 0, 0,
0, 0, 2.2, 0,
1000, 0, 0, 1 ], true);
var anim = createDiv(t).animate([ { transform: "none" },
{ transform: matrix1 },
{ transform: matrix2 },
{ transform: matrix3 } ],
{ spacing: "paced(transform)" });
var dist = [ 0,
sqrt(100 * 100 + 50 * 50 + 10 * 10 + pi/4 * pi/4),
sqrt(900 * 900 + 50 * 50 + 10 * 10 + pi/4 * pi/4 + pi * pi),
sqrt(0.5 * 0.5 + 0.3 * 0.3 + 1.2 * 1.2 + pi * pi) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on matrix3d' );
test(function(t) {
var anim =
createDiv(t).animate([ { transform: "none" },
{ transform: "translate(100px, 50px) skew(45deg)" },
{ transform: "translate(1000px) " +
"rotate3d(1, 0, 0, 180deg)" },
{ transform: "translate(1000px) " +
"scale3d(2.5, 0.5, 0.7)" } ],
{ spacing: "paced(transform)" });
var dist = [ 0,
sqrt(100 * 100 + 50 * 50 + pi/4 * pi/4),
sqrt(900 * 900 + 50 * 50 + pi/4 * pi/4 + pi * pi),
sqrt(1.5 * 1.5 + 0.5 * 0.5 + 0.3 * 0.3 + pi * pi) ];
assert_animation_offsets(anim, dist);
}, 'Test spacing on mismatched transform list' );
</script>
</body>

View file

@ -1,391 +0,0 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Keyframe spacing tests</title>
<link rel="help" href="https://w3c.github.io/web-animations/#spacing-keyframes">
<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(function(t) {
var anim = createDiv(t).animate([ { marginLeft: '0px' },
{ marginLeft: '-20px' },
{ marginLeft: '100px' },
{ marginLeft: '50px' } ],
{ duration: 100 * MS_PER_SEC });
var frames = anim.effect.getKeyframes();
var slots = frames.length - 1;
assert_equals(frames[0].computedOffset, 0.0, '1st frame offset');
assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset');
assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset');
assert_equals(frames[3].computedOffset, 1.0, 'last frame offset');
}, 'Test distribute spacing');
test(function(t) {
var anim = createDiv(t).animate([ { marginLeft: '0px' },
{ marginLeft: '-20px' },
{ marginLeft: '100px', offset: 0.5 },
{ marginLeft: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'distribute' });
var frames = anim.effect.getKeyframes();
assert_equals(frames[0].computedOffset, 0.0, '1st frame offset');
assert_equals(frames[1].computedOffset, 0.5 * 1 / 2, '2nd frame offset');
assert_equals(frames[2].computedOffset, 0.5, '3rd frame offset');
assert_equals(frames[3].computedOffset, 1.0, 'last frame offset');
}, 'Test distribute spacing with specific offsets');
test(function(t) {
var anim = createDiv(t).animate(null,
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
var frames = anim.effect.getKeyframes();
assert_equals(frames.length, 0, "empty keyframe list");
}, 'Test paced spacing without any keyframe');
test(function(t) {
var anim = createDiv(t).animate([ { marginLeft: '0px' },
{ marginLeft: '-20px' },
{ marginLeft: '100px' },
{ marginLeft: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
var frames = anim.effect.getKeyframes();
var cumDist = [0, 20, 140, 190];
assert_equals(frames[0].computedOffset, 0.0,
'1st frame offset');
assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
'2nd frame offset');
assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
'3rd frame offset');
assert_equals(frames[3].computedOffset, 1.0,
'last frame offset');
}, 'Test paced spacing');
test(function(t) {
var anim = createDiv(t).animate([ { marginLeft: '0px' },
{ marginLeft: '-20px' },
{ marginLeft: '100px', offset: 0.5 },
{ marginLeft: '120px' },
{ marginLeft: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
var frames = anim.effect.getKeyframes();
var cumDist1 = [ 0, 20, 140 ];
var cumDist2 = [ 0, 20, 90 ];
assert_equals(frames[1].computedOffset, 0.5 * cumDist1[1] / cumDist1[2],
'2nd frame offset');
assert_equals(frames[2].computedOffset, 0.5,
'3rd frame offset');
assert_equals(frames[3].computedOffset, 0.5 + 0.5 * cumDist2[1] / cumDist2[2],
'4th frame offset');
}, 'Test paced spacing with specific offsets');
test(function(t) {
var anim = createDiv(t).animate([ { marginLeft: '0px' },
{ marginLeft: '0px' },
{ marginLeft: '100px' },
{ marginLeft: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
var frames = anim.effect.getKeyframes();
var cumDist = [0, 0, 100, 150];
assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
'2nd frame offset');
assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
'3rd frame offset');
}, 'Test paced spacing if some paced property values are equal');
test(function(t) {
var anim = createDiv(t).animate([ { marginLeft: '0px' },
{ marginLeft: '0px' },
{ marginLeft: '0px' },
{ marginLeft: '0px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
var frames = anim.effect.getKeyframes();
var slots = frames.length - 1;
assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset');
assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset');
}, 'Test falling back to distribute spacing if all paced property value ' +
'are equal');
test(function(t) {
var anim = createDiv(t).animate([ { margin: '0px' },
{ marginTop: '-20px' },
{ marginLeft: '100px' },
{ margin: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
var frames = anim.effect.getKeyframes();
assert_equals(frames[1].computedOffset, frames[2].computedOffset * 1 / 2,
'2nd frame offset using distribute spacing');
assert_equals(frames[2].computedOffset, 100 / 150,
'3rd frame offset using paced spacing');
}, 'Test paced spacing if there a keyframe without the paced property');
test(function(t) {
var anim = createDiv(t).animate([ { margin: '0px' },
{ marginTop: '40px' },
{ marginTop: '-20px' },
{ marginLeft: '40px' },
{ marginTop: '60px' },
{ margin: '10px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
var frames = anim.effect.getKeyframes();
var cumDist = [0, 0, 0, 40, 40, 70];
assert_equals(frames[1].computedOffset, frames[3].computedOffset * 1 / 3,
'2nd frame offset using distribute spacing');
assert_equals(frames[2].computedOffset, frames[3].computedOffset * 2 / 3,
'3rd frame offset using distribute spacing');
assert_equals(frames[3].computedOffset, cumDist[3] / cumDist[5],
'4th frame offset using paced spacing');
assert_equals(frames[4].computedOffset,
frames[3].computedOffset +
(1 - frames[3].computedOffset) * 1 / 2,
'5th frame offset using distribute spacing');
}, 'Test paced spacing if a paced property that appears on only some ' +
'keyframes');
test(function(t) {
var anim = createDiv(t).animate([ { margin: '0px' },
{ marginTop: '-20px', offset: 0.5 },
{ marginLeft: '40px' },
{ marginLeft: '100px' },
{ margin: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
var frames = anim.effect.getKeyframes();
assert_equals(frames[2].computedOffset, 0.5 + 0.5 * 1 / 3,
'3rd frame offset using distribute spacing because it is the ' +
'first paceable keyframe');
assert_equals(frames[3].computedOffset,
frames[2].computedOffset +
(1.0 - frames[2].computedOffset) * 60 / 110,
'4th frame offset using paced spacing');
}, 'Test paced spacing if a paced property that appears on only some ' +
'keyframes and there is a specific offset');
test(function(t) {
var anim = createDiv(t).animate([ { margin: '0px' },
{ marginTop: '20px', offset: 0.2 },
{ marginTop: '40px' },
{ marginTop: '-20px' },
{ marginLeft: '-20px' },
{ marginLeft: '40px' },
{ marginTop: '60px' },
{ marginLeft: '100px' },
{ marginTop: '50px' },
{ marginTop: '100px', offset: 0.8 },
{ margin: '0px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
var frames = anim.effect.getKeyframes();
// Test distribute spacing in (A, Paced A] and [Paced B, frame B).
var slots = frames.length - 3;
var start = 0.2;
var diff = 0.8 - start;
assert_equals(frames[2].computedOffset, start + diff * 1.0 / slots,
'3nd frame offset using distribute spacing');
assert_equals(frames[3].computedOffset, start + diff * 2.0 / slots,
'4rd frame offset using distribute spacing');
assert_equals(frames[4].computedOffset, start + diff * 3.0 / slots,
'5th frame offset using distribute spacing because it is ' +
'the first paceable keyframe');
assert_equals(frames[7].computedOffset, start + diff * 6.0 / slots,
'8th frame offset using distribute spacing because it is ' +
'the last paceable keyframe');
assert_equals(frames[8].computedOffset, start + diff * 7.0 / slots,
'9th frame offset using distribute spacing');
// Test paced spacing and other null computed offsets in (Paced A, Paced B).
var cumDist = [0, 60, 60, 120];
assert_equals(frames[5].computedOffset,
frames[4].computedOffset + cumDist[2] / cumDist[3] *
(frames[7].computedOffset - frames[4].computedOffset),
'6th frame offset using paced spacing');
assert_equals(frames[6].computedOffset,
frames[5].computedOffset + 1.0 / 2.0 *
(frames[7].computedOffset - frames[5].computedOffset),
'7th frame offset using distribute spacing');
}, 'Test paced spacing where there are some keyframes without offsets and ' +
'without the paced property before the first paceable keyframe and ' +
'after the last paceable keyframe');
test(function(t) {
var anim = createDiv(t).animate([ { margin: '0px' },
{ margin: '-20px' },
{ margin: '100px' },
{ margin: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin)' });
var frames = anim.effect.getKeyframes();
var cumDist = [0, 20, 140, 190];
assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
'2nd frame offset');
assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
'3rd frame offset');
}, 'Test paced spacing for using shorthand property');
test(function(t) {
var anim =
createDiv(t).animate([ { marginLeft: '0px', marginRight: '0px',
marginTop: '10px', marginBottom: '10px' },
{ marginLeft: '-20px', marginRight: '-20px',
marginTop: '0px', marginBottom: '0px' },
{ marginLeft: '100px', marginRight: '100px',
marginTop: '-50px', marginBottom: '-50px' },
{ marginLeft: '50px', marginRight: '50px',
marginTop: '80px', marginBottom: '80px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin)' });
var frames = anim.effect.getKeyframes();
var dist = [ 0,
Math.sqrt(20 * 20 * 2 + 10 * 10 * 2),
Math.sqrt(120 * 120 * 2 + 50 * 50 * 2),
Math.sqrt(50 * 50 * 2 + 130 * 130 * 2) ];
var cumDist = [];
dist.reduce(function(prev, curr, i) { return cumDist[i] = prev + curr; }, 0);
assert_approx_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
0.0001, '2nd frame offset');
assert_approx_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
0.0001, '3rd frame offset');
}, 'Test paced spacing using shorthand property where only the longhand ' +
'components are specified');
test(function(t) {
var anim = createDiv(t).animate([ { marginLeft: '0px', marginTop: '0px' },
{ marginLeft: '-20px', marginTop: '-20px' },
{ marginLeft: '100px', marginTop: '100px' },
{ marginLeft: '50px', marginTop: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin)' });
var frames = anim.effect.getKeyframes();
var slots = frames.length - 1;
assert_equals(frames[1].computedOffset, 1 / slots, '2nd frame offset');
assert_equals(frames[2].computedOffset, 2 / slots, '3rd frame offset');
}, 'Test falling back to distribute spacing if all keyframe miss some ' +
'components');
test(function(t) {
var anim = createDiv(t).animate([ { margin: '0px' },
{ marginLeft: '-20px' },
{ marginTop: '40px' },
{ margin: '100px' },
{ margin: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin)' });
var frames = anim.effect.getKeyframes();
assert_equals(frames[1].computedOffset, frames[3].computedOffset * 1 / 3,
'2nd frame offset using distribute spacing');
assert_equals(frames[2].computedOffset, frames[3].computedOffset * 2 / 3,
'3rd frame offset using distribute spacing');
assert_equals(frames[3].computedOffset, 100 / 150,
'4th frame offset using paced spacing');
}, 'Test paced spacing only for keyframes specifying all longhand ' +
'components, and falling back to distribute spacing for the reset');
test(function(t) {
var anim = createDiv(t).animate([ { margin: '0px' },
{ marginLeft: '-20px' },
{ marginTop: '40px', offset: 0.5 },
{ margin: '100px' },
{ margin: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin)' });
var frames = anim.effect.getKeyframes();
assert_equals(frames[1].computedOffset, 0.5 * 1 / 2,
'2nd frame offset using distribute spacing');
assert_equals(frames[3].computedOffset, 0.5 + 0.5 * 1 / 2,
'4th frame offset using distribute spacing because it is the ' +
'first paceable keyframe from a non-null offset keyframe');
}, 'Test paced spacing only for keyframes specifying all some components, ' +
'and falling back to distribute spacing for the reset with some specific ' +
'offsets');
// Tests for setting spacing by KeyframeEffect.spacing.
test(function(t) {
var anim = createDiv(t).animate([ { marginLeft: '0px' },
{ marginLeft: '-20px' },
{ marginLeft: '100px' },
{ marginLeft: '50px' } ],
{ duration: 100 * MS_PER_SEC });
anim.effect.spacing = 'paced(margin-left)';
var frames = anim.effect.getKeyframes();
var cumDist = [0, 20, 140, 190];
assert_equals(frames[0].computedOffset, 0.0,
'1st frame offset');
assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
'2nd frame offset');
assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
'3rd frame offset');
assert_equals(frames[3].computedOffset, 1.0,
'last frame offset');
}, 'Test paced spacing by setter');
test(function(t) {
var anim = createDiv(t).animate([ { marginLeft: '0px' },
{ marginLeft: '-20px' },
{ marginLeft: '100px' },
{ marginLeft: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
anim.effect.spacing = 'distribute';
var frames = anim.effect.getKeyframes();
var slots = frames.length - 1;
assert_equals(frames[0].computedOffset, 0.0, '1st frame offset');
assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset');
assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset');
assert_equals(frames[3].computedOffset, 1.0, 'last frame offset');
}, 'Test distribute spacing by setter');
test(function(t) {
var anim =
createDiv(t).animate([ { marginLeft: '0px', borderRadius: '0%' },
{ marginLeft: '-20px', borderRadius: '50%' },
{ marginLeft: '100px', borderRadius: '25%' },
{ marginLeft: '50px', borderRadius: '100%' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
anim.effect.spacing = 'paced(border-radius)';
var frames = anim.effect.getKeyframes();
var cumDist = [0, 50, 50 + 25, 50 + 25 + 75];
assert_equals(frames[0].computedOffset, 0.0,
'1st frame offset');
assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
'2nd frame offset');
assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
'3rd frame offset');
assert_equals(frames[3].computedOffset, 1.0,
'last frame offset');
}, 'Test paced spacing by changing the paced property');
</script>
</body>

View file

@ -0,0 +1,108 @@
<!doctype html>
<meta charset=utf-8>
<title>Animatable.animate tests in combination with elements in documents
without a browsing context</title>
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animatable-animate">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<div id="log"></div>
<script>
'use strict';
//
// The following tests relate to animations on elements in documents without
// a browsing context. This is NOT the same as documents that are not bound to
// a document tree.
//
function getXHRDoc(t) {
return new Promise(resolve => {
const xhr = new XMLHttpRequest();
xhr.open('GET', '../../resources/xhr-doc.py');
xhr.responseType = 'document';
xhr.onload = t.step_func(() => {
assert_equals(xhr.readyState, xhr.DONE,
'Request should complete successfully');
assert_equals(xhr.status, 200,
'Response should be OK');
resolve(xhr.responseXML);
});
xhr.send();
});
}
promise_test(t => {
return getXHRDoc(t).then(xhrdoc => {
const div = xhrdoc.getElementById('test');
const anim = div.animate(null);
assert_class_string(anim.timeline, 'DocumentTimeline',
'Animation should have a timeline');
assert_equals(anim.timeline, xhrdoc.timeline,
'Animation timeline should be the default document timeline'
+ ' of the XHR doc');
assert_not_equals(anim.timeline, document.timeline,
'Animation timeline should NOT be the same timeline as'
+ ' the default document timeline for the current'
+ ' document');
});
}, 'Element.animate() creates an animation with the correct timeline'
+ ' when called on an element in a document without a browsing context');
//
// The following tests are cross-cutting tests that are not specific to the
// Animatable.animate() interface. Instead, they draw on assertions from
// various parts of the spec. These assertions are tested in other tests
// but are repeated here to confirm that user agents are not doing anything
// different in the particular case of document without a browsing context.
//
promise_test(t => {
return getXHRDoc(t).then(xhrdoc => {
const div = xhrdoc.getElementById('test');
const anim = div.animate(null);
// Since a document from XHR will not be active by itself, its document
// timeline will also be inactive.
assert_equals(anim.timeline.currentTime, null,
'Document timeline time should be null');
});
}, 'The timeline associated with an animation trigger on an element in'
+ ' a document without a browsing context is inactive');
promise_test(t => {
let anim;
return getXHRDoc(t).then(xhrdoc => {
const div = xhrdoc.getElementById('test');
anim = div.animate(null);
anim.timeline = document.timeline;
assert_equals(anim.playState, 'pending',
'The animation should be initially pending');
return waitForAnimationFrames(2);
}).then(() => {
// Because the element is in a document without a browsing context, it will
// not be rendered and hence the user agent will never deem it ready to
// animate.
assert_equals(anim.playState, 'pending',
'The animation should still be pending after replacing'
+ ' the document timeline');
});
}, 'Replacing the timeline of an animation targetting an element in a'
+ ' document without a browsing context leaves it in the pending state');
promise_test(t => {
let anim;
return getXHRDoc(t).then(xhrdoc => {
const div = xhrdoc.getElementById('test');
anim = div.animate({ opacity: [ 0, 1 ] }, 1000);
anim.timeline = document.timeline;
document.body.appendChild(div);
assert_equals(getComputedStyle(div).opacity, '0',
'Style should be updated');
});
}, 'Replacing the timeline of an animation targetting an element in a'
+ ' document without a browsing context and then adopting that element'
+ ' causes it to start updating style');
</script>
</body>

View file

@ -25,7 +25,7 @@ interface DocumentTimeline : AnimationTimeline {
var idlArray;
test(function() {
idlArray = new IdlArray();
idlArray.add_untested_idls(
idlArray.add_idls(
document.getElementById('AnimationTimeline-IDL').textContent);
idlArray.add_idls(
document.getElementById('DocumentTimeline-IDL').textContent);

View file

@ -228,8 +228,6 @@ test(function(t) {
assert_equals(effect.composite, "replace", "default composite");
assert_equals(effect.iterationComposite, "replace",
"default iterationComposite");
assert_equals(effect.spacing, "distribute",
"default spacing");
}, "a KeyframeEffectReadOnly constructed without any " +
"KeyframeEffectOptions object");

View file

@ -447,15 +447,15 @@ test(function(t) {
anim.pause();
anim.currentTime = anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0, 1, -1, 0, 0, 0)', // rotate(90deg)
'Animated transform(rotate) style at 50s of the first iteration');
anim.currentTime = anim.effect.timing.duration * 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(1, 0, 0, 1, 0, 0)', // rotate(360deg)
'Animated transform(rotate) style at 0s of the third iteration');
anim.currentTime += anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0, 1, -1, 0, 0, 0)', // rotate(450deg)
'Animated transform(rotate) style at 50s of the third iteration');
}, 'iterationComposite of transform(rotate) animation');
@ -471,16 +471,16 @@ test(function(t) {
anim.pause();
anim.currentTime = anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5)
'Animated transform(scale) style at 50s of the first iteration');
anim.currentTime = anim.effect.timing.duration * 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0, 0, 0, 0, 0, 0)', // scale(0); scale(1) is an identity element,
// not accumulated.
'Animated transform(scale) style at 0s of the third iteration');
anim.currentTime += anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5); scale(1) an identity
// element, not accumulated.
'Animated transform(scale) style at 50s of the third iteration');
@ -497,15 +497,15 @@ test(function(t) {
anim.pause();
anim.currentTime = anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(1.5, 0, 0, 1.5, 0, 0)', // scale(1.5)
'Animated transform(scale) style at 50s of the first iteration');
anim.currentTime = anim.effect.timing.duration * 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(3, 0, 0, 3, 0, 0)', // scale(1 + (2 -1) + (2 -1))
'Animated transform(scale) style at 0s of the third iteration');
anim.currentTime += anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(3.5, 0, 0, 3.5, 0, 0)', // (scale(3) + scale(4)) * 0.5
'Animated transform(scale) style at 50s of the third iteration');
}, 'iterationComposite of transform: [ scale(1), scale(2) ] animation');
@ -521,15 +521,15 @@ test(function(t) {
anim.pause();
anim.currentTime = anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(1, 0, 0, 1, 0, 0)', // scale(1)
'Animated transform(scale) style at 50s of the first iteration');
anim.currentTime = anim.effect.timing.duration * 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(2, 0, 0, 2, 0, 0)', // (scale(0) + scale(2-1)*2)
'Animated transform(scale) style at 0s of the third iteration');
anim.currentTime += anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(3, 0, 0, 3, 0, 0)', // (scale(2) + scale(4)) * 0.5
'Animated transform(scale) style at 50s of the third iteration');
}, 'iterationComposite of transform: scale(2) animation');
@ -546,15 +546,15 @@ test(function(t) {
anim.pause();
anim.currentTime = anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0, 1, -1, 0, 0, 5)', // rotate(90deg) translateX(5px)
'Animated transform list at 50s of the first iteration');
anim.currentTime = anim.effect.timing.duration * 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(1, 0, 0, 1, 20, 0)', // rotate(360deg) translateX(20px)
'Animated transform list at 0s of the third iteration');
anim.currentTime += anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(0, 1, -1, 0, 0, 25)', // rotate(450deg) translateX(25px)
'Animated transform list at 50s of the third iteration');
}, 'iterationComposite of transform list animation');
@ -571,16 +571,16 @@ test(function(t) {
anim.pause();
anim.currentTime = anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(2.5, 0, 0, 2.5, 15, 0)',
'Animated transform of matrix function at 50s of the first iteration');
anim.currentTime = anim.effect.timing.duration * 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
// scale(2) + (scale(3-1)*2) + translateX(30px)*2
'matrix(6, 0, 0, 6, 60, 0)',
'Animated transform of matrix function at 0s of the third iteration');
anim.currentTime += anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
// from: matrix(6, 0, 0, 6, 60, 0)
// to: matrix(7, 0, 0, 7, 90, 0)
// = scale(3) + (scale(3-1)*2) + translateX(30px)*3
@ -600,20 +600,20 @@ test(function(t) {
anim.pause();
anim.currentTime = anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
// Interpolate between matrix(2, 0, 0, 2, 0, 0) = translateX(0px) scale(2)
// and matrix(3, 0, 0, 3, 30, 0) = scale(3) translateX(10px)
'matrix(2.5, 0, 0, 2.5, 15, 0)',
'Animated transform list at 50s of the first iteration');
anim.currentTime = anim.effect.timing.duration * 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
// 'from' and 'to' value are mismatched, so accumulate
// matrix(2, 0, 0, 2, 0, 0) onto matrix(3, 0, 0, 3, 30, 0) * 2
// = scale(2) + (scale(3-1)*2) + translateX(30px)*2
'matrix(6, 0, 0, 6, 60, 0)',
'Animated transform list at 0s of the third iteration');
anim.currentTime += anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
// Interpolate between matrix(6, 0, 0, 6, 60, 0)
// and matrix(7, 0, 0, 7, 210, 0) = scale(7) translate(30px)
'matrix(6.5, 0, 0, 6.5, 135, 0)',
@ -634,20 +634,20 @@ test(function(t) {
anim.pause();
anim.currentTime = anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
// Interpolate between matrix(1, 0, 0, 1, 0, 0) = translateX(0px)
// and matrix(2, 0, 0, 2, 20, 0) = scale(2) translateX(10px)
'matrix(1.5, 0, 0, 1.5, 10, 0)',
'Animated transform list at 50s of the first iteration');
anim.currentTime = anim.effect.timing.duration * 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
// 'from' and 'to' value are mismatched, so accumulate
// matrix(1, 0, 0, 1, 0, 0) onto matrix(2, 0, 0, 2, 20, 0) * 2
// = scale(1) + (scale(2-1)*2) + translateX(20px)*2
'matrix(3, 0, 0, 3, 40, 0)',
'Animated transform list at 0s of the third iteration');
anim.currentTime += anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
// Interpolate between matrix(3, 0, 0, 3, 40, 0)
// and matrix(4, 0, 0, 4, 120, 0) =
// scale(2 + (2-1)*2) translate(10px * 3)
@ -668,16 +668,19 @@ test(function(t) {
anim.pause();
anim.currentTime = anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
'matrix(1, 0, 0, 1, 5, 0)', // (0px + 10px) / 2
assert_matrix_equals(getComputedStyle(div).transform,
// translateX(none) -> translateX(10px) @ 50%
'matrix(1, 0, 0, 1, 5, 0)',
'Animated transform list at 50s of the first iteration');
anim.currentTime = anim.effect.timing.duration * 2;
assert_equals(getComputedStyle(div).transform,
'matrix(1, 0, 0, 1, 0, 0)', // 'none' overrides any transforms.
assert_matrix_equals(getComputedStyle(div).transform,
// translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 0%
'matrix(1, 0, 0, 1, 20, 0)',
'Animated transform list at 0s of the third iteration');
anim.currentTime += anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
'matrix(1, 0, 0, 1, 15, 0)', // (0px + 10px*2)/2
assert_matrix_equals(getComputedStyle(div).transform,
// translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 50%
'matrix(1, 0, 0, 1, 25, 0)',
'Animated transform list at 50s of the third iteration');
}, 'iterationComposite of transform from none to translate');
@ -699,16 +702,16 @@ test(function(t) {
anim.pause();
anim.currentTime = anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 40, 1)',
'Animated transform of matrix3d function at 50s of the first iteration');
anim.currentTime = anim.effect.timing.duration * 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
// translateZ(30px) + (translateZ(50px)*2)
'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)',
'Animated transform of matrix3d function at 0s of the third iteration');
anim.currentTime += anim.effect.timing.duration / 2;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
// from: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)
// to: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 150, 1)
'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 140, 1)',
@ -727,7 +730,7 @@ test(function(t) {
anim.pause();
anim.currentTime = 0;
assert_equals(getComputedStyle(div).transform,
assert_matrix_equals(getComputedStyle(div).transform,
'matrix(1, 0, 0, 1, 0, 0)', // Actually not rotated at all.
'Animated transform of rotate3d function at 50s of the first iteration');
anim.currentTime = anim.effect.timing.duration * 2;

View file

@ -258,9 +258,10 @@ test(() => {
{done: true},
]));
assert_frame_lists_equal(effect.getKeyframes(), [
{offset: null, computedOffset: 1, easing: 'linear', left: '100px,200px'}
{offset: null, computedOffset: 1, easing: 'linear'}
]);
}, 'Custom iterator with value list in keyframe should give bizarre string representation of list.');
}, 'Custom iterator with value list in keyframe should not contain invalid ' +
'property value pair of list.');
test(function(t) {
var keyframe = {};

View file

@ -85,76 +85,5 @@ test(function(t) {
'changing the animation current time.');
}, 'Test setting target from a valid target to another target');
test(function(t) {
var anim = createDiv(t).animate([ { marginLeft: '0px' },
{ marginLeft: '-20px' },
{ marginLeft: '100px' },
{ marginLeft: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
anim.effect.target = null;
var frames = anim.effect.getKeyframes();
var slots = frames.length - 1;
assert_equals(frames[0].computedOffset, 0.0, '1st frame offset');
assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset');
assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset');
assert_equals(frames[3].computedOffset, 1.0, 'last frame offset');
}, 'Test falling back to distribute spacing mode after setting null target');
test(function(t) {
var effect = new KeyframeEffect(null,
[ { marginLeft: '0px' },
{ marginLeft: '-20px' },
{ marginLeft: '100px' },
{ marginLeft: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
var frames = effect.getKeyframes();
var slots = frames.length - 1;
assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset');
assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset');
}, 'Test falling back to distribute spacing mode if there is no context ' +
'element');
test(function(t) {
var div1 = createDiv(t);
var div2 = createDiv(t);
div1.style.marginLeft = '-20px';
div2.style.marginLeft = '-50px';
var child1 = document.createElement('div');
var child2 = document.createElement('div');
div1.appendChild(child1);
div2.appendChild(child2);
// body
// / \
// div1 div2
// (-20px) (-50px)
// | |
// child1 child2
var anim = child1.animate([ { marginLeft: '0px' },
{ marginLeft: 'inherit' },
{ marginLeft: '100px' },
{ marginLeft: '50px' } ],
{ duration: 100 * MS_PER_SEC,
spacing: 'paced(margin-left)' });
var frames = anim.effect.getKeyframes();
var cumDist = [0, 20, 140, 190];
assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
'2nd frame offset');
assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
'3rd frame offset');
anim.effect.target = child2;
frames = anim.effect.getKeyframes();
cumDist = [0, 50, 200, 250];
assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3],
'2nd frame offset after setting a new target');
assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3],
'3rd frame offset after setting a new target');
}, 'Test paced spacing mode after setting a new target');
</script>
</body>

View file

@ -1,60 +0,0 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>KeyframeEffect spacing attribute tests</title>
<link rel="help"
href="https://w3c.github.io/web-animations/#dom-keyframeeffect-spacing">
<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(function(t) {
var anim = createDiv(t).animate(null);
assert_throws(new TypeError, function() {
anim.effect.spacing = '';
});
}, 'Test throwing TypeError if using empty string');
test(function(t) {
var anim = createDiv(t).animate(null);
assert_throws(new TypeError, function() {
anim.effect.spacing = 'dist';
});
}, 'Test throwing TypeError if not using the correct keyword');
test(function(t) {
var anim = createDiv(t).animate(null);
anim.effect.spacing = 'paced(A)';
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test falling back to distribute spacing if using a unrecognized property');
test(function(t) {
var anim = createDiv(t).animate(null);
anim.effect.spacing = 'paced(--bg-color)';
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test falling back to distribute spacing if using CSS variables');
test(function(t) {
var anim = createDiv(t).animate(null);
anim.effect.spacing = 'paced(animation-duration)';
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test falling back to distribute spacing if using a non-animatable ' +
'property');
test(function(t) {
var anim = createDiv(t).animate(null);
anim.effect.spacing = 'distribute';
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test spacing value if setting distribute');
test(function(t) {
var anim = createDiv(t).animate(null);
anim.effect.spacing = 'paced(transform)';
assert_equals(anim.effect.spacing, 'paced(transform)', 'spacing mode');
}, 'Test spacing value if setting paced');
</script>
</body>

View file

@ -1,239 +0,0 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>KeyframeEffectReadOnly spacing attribute tests</title>
<link rel="help"
href="https://w3c.github.io/web-animations/#dom-keyframeeffectreadonly-spacing">
<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(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: '' });
});
}, 'Test throwing TypeError if using empty string');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'dist' });
});
}, 'Test throwing TypeError if not using the correct keyword');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: ' paced(margin-left)' });
});
}, 'Test throwing TypeError if adding leading spaces');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(margin-left) ' });
});
}, 'Test throwing TypeError if adding trailing spaces');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced( margin-left)' });
});
}, 'Test throwing TypeError if adding leading spaces before the ' +
'paced property');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(margin-left )' });
});
}, 'Test throwing TypeError if adding trailing spaces after the ' +
'paced property');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced()' });
});
}, 'Test throwing TypeError if these is no paced property');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(.margin)' });
});
}, 'Test throwing TypeError if using a non-ident started string with ' +
'a period');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(1margin)' });
});
}, 'Test throwing TypeError if using a non-ident started string with ' +
'a number');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(\\)' });
});
}, 'Test throwing TypeError if using a non-ident started string with ' +
'an invalid escape');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(\\\fmargin)' });
});
}, 'Test throwing TypeError if using a non-ident started string with ' +
'an invalid escape (FF)');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(\\\rmargin)' });
});
}, 'Test throwing TypeError if using a non-ident started string with ' +
'an invalid escape (CR)');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(\\\nmargin)' });
});
}, 'Test throwing TypeError if using a non-ident started string with ' +
'an invalid escape (LF)');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(- )' });
});
}, 'Test throwing TypeError if using a non-ident started string with ' +
'a leading minus and an invalid name-start code point');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(-\\)' });
});
}, 'Test throwing TypeError if using a non-ident started string with ' +
'a leading minus and an invalid escape');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(-\\\fmargin)' });
});
}, 'Test throwing TypeError if using a non-ident started string with ' +
'a leading minus and an invalid escape (FF)');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(-\\\rmargin)' });
});
}, 'Test throwing TypeError if using a non-ident started string with ' +
'a leading minus and an invalid escape (CR)');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(-\\\nmargin)' });
});
}, 'Test throwing TypeError if using a non-ident started string with ' +
'a leading minus and an invalid escape (LF)');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(--\\)' });
});
}, 'Test throwing TypeError if using a non-ident string with an invalid ' +
'escape');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(--\\\fmargin)' });
});
}, 'Test throwing TypeError if using a non-ident string with an invalid ' +
'escape (FF)');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(--\\\rmargin)' });
});
}, 'Test throwing TypeError if using a non-ident string with an invalid ' +
'escape (CR)');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(--\\\nmargin)' });
});
}, 'Test throwing TypeError if using a non-ident string with an invalid ' +
'escape (LF)');
test(function(t) {
assert_throws(new TypeError, function() {
createDiv(t).animate(null, { spacing: 'paced(margin.left)' });
});
}, 'Test throwing TypeError if using a non-ident string with an invalid name ' +
'code point');
test(function(t) {
var anim = createDiv(t).animate(null, { spacing: 'paced(A)' });
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test falling back to distribute spacing if using a unrecognized property');
test(function(t) {
var anim = createDiv(t).animate(null, { spacing: 'paced(\\.margin)' });
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test falling back to distribute spacing if using a unrecognized property ' +
'which starts with a valid escape (Full stop)');
test(function(t) {
var anim = createDiv(t).animate(null, { spacing: 'paced(\\ margin)' });
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test falling back to distribute spacing if using a unrecognized property ' +
'which starts with a valid escape (white space)');
test(function(t) {
var anim = createDiv(t).animate(null, { spacing: 'paced(_margin)' });
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test falling back to distribute spacing if using a unrecognized property ' +
'which starts with a valid escape (low line)');
test(function(t) {
var anim = createDiv(t).animate(null, { spacing: 'paced(-_margin)' });
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test falling back to distribute spacing if using a unrecognized property ' +
'which starts with a minus and a low line');
test(function(t) {
var anim = createDiv(t).animate(null, { spacing: 'paced(-\\.margin)' });
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test falling back to distribute spacing if using a unrecognized property ' +
'which starts with a minus and a valid escape');
test(function(t) {
var anim = createDiv(t).animate(null, { spacing: 'paced(--bg-color)' });
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test falling back to distribute spacing if using CSS variables');
test(function(t) {
var anim = createDiv(t).animate(null, { spacing: 'paced(animation)' });
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test falling back to distribute spacing if using a non-animatable ' +
'shorthand property');
test(function(t) {
var anim = createDiv(t).animate(null,
{ spacing: 'paced(animation-duration)' });
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test falling back to distribute spacing if using a non-animatable ' +
'property');
test(function(t) {
var anim = createDiv(t).animate(null);
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test default value of spacing');
test(function(t) {
var anim = createDiv(t).animate(null, { spacing: 'distribute' });
assert_equals(anim.effect.spacing, 'distribute', 'spacing mode');
}, 'Test spacing value if setting distribute');
test(function(t) {
var anim = createDiv(t).animate(null, { spacing: 'paced(margin-left)' });
assert_equals(anim.effect.spacing, 'paced(margin-left)', 'spacing mode');
}, 'Test spacing value if setting paced');
</script>
</body>

View file

@ -128,7 +128,7 @@ var gPropertyIndexedKeyframesTests = [
{ offset: null, computedOffset: 0.25, easing: "linear",
left: "20px", top: "25px" },
{ offset: null, computedOffset: 0.50, easing: "linear",
left: "30px", top: "invalid" },
left: "30px" },
{ offset: null, computedOffset: 0.75, easing: "linear",
left: "40px", top: "45px" },
{ offset: null, computedOffset: 1.00, easing: "linear",
@ -166,8 +166,7 @@ var gPropertyIndexedKeyframesTests = [
{ desc: "a one property two value property-indexed keyframes specification"
+ " where the first value is invalid",
input: { left: ["invalid", "10px"] },
output: [{ offset: null, computedOffset: 0, easing: "linear",
left: "invalid" },
output: [{ offset: null, computedOffset: 0, easing: "linear" },
{ offset: null, computedOffset: 1, easing: "linear",
left: "10px" }] },
{ desc: "a one property two value property-indexed keyframes specification"
@ -175,8 +174,7 @@ var gPropertyIndexedKeyframesTests = [
input: { left: ["10px", "invalid"] },
output: [{ offset: null, computedOffset: 0, easing: "linear",
left: "10px" },
{ offset: null, computedOffset: 1, easing: "linear",
left: "invalid" }] },
{ offset: null, computedOffset: 1, easing: "linear" }] },
];
var gKeyframeSequenceTests = [

View file

@ -0,0 +1,5 @@
def main(request, response):
headers = [("Content-type", "text/html;charset=utf-8")]
content = "<!doctype html><div id=test></div>"
return headers, content

View file

@ -78,7 +78,8 @@ function createStyle(test, rules, doc) {
// Create a pseudo element
function createPseudo(test, type) {
createStyle(test, { '@keyframes anim': '',
['.pseudo::' + type]: 'animation: anim 10s;' });
['.pseudo::' + type]: 'animation: anim 10s; ' +
'content: \'\';' });
var div = createDiv(test);
div.classList.add('pseudo');
var anims = document.getAnimations();
@ -238,6 +239,6 @@ function assert_matrix_equals(actual, expected, description) {
'dimension of the matrix: ' + description);
for (var i = 0; i < actualMatrixArray.length; i++) {
assert_approx_equals(actualMatrixArray[i], expectedMatrixArray[i], 0.0001,
'expecetd ' + expected + ' but got ' + actual + ": " + description);
'expected ' + expected + ' but got ' + actual + ": " + description);
}
}