mirror of
https://github.com/servo/servo.git
synced 2025-10-04 02:29:12 +01:00
Update web-platform-tests to revision dc5cbf088edcdb266541d4e5a76149a2c6e716a0
This commit is contained in:
parent
1d40075f03
commit
079092dfea
2381 changed files with 90360 additions and 17722 deletions
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -0,0 +1,569 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Tests for animation types</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#animation-types">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<style>
|
||||
html {
|
||||
font-size: 10px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
var gCSSProperties = {
|
||||
"align-content": {
|
||||
// https://drafts.csswg.org/css-align/#propdef-align-content
|
||||
tests: [
|
||||
discrete("flex-start", "flex-end")
|
||||
]
|
||||
},
|
||||
"align-items": {
|
||||
// https://drafts.csswg.org/css-align/#propdef-align-items
|
||||
tests: [
|
||||
discrete("flex-start", "flex-end")
|
||||
]
|
||||
},
|
||||
"align-self": {
|
||||
// https://drafts.csswg.org/css-align/#propdef-align-self
|
||||
tests: [
|
||||
discrete("flex-start", "flex-end")
|
||||
]
|
||||
},
|
||||
"clip-rule": {
|
||||
// https://drafts.fxtf.org/css-masking-1/#propdef-clip-rule
|
||||
tests: [
|
||||
discrete("evenodd", "nonzero")
|
||||
]
|
||||
},
|
||||
"color-interpolation": {
|
||||
// https://svgwg.org/svg2-draft/painting.html#ColorInterpolationProperty
|
||||
tests: [
|
||||
discrete("linearRGB", "auto")
|
||||
]
|
||||
},
|
||||
"color-interpolation-filters": {
|
||||
// https://drafts.fxtf.org/filters-1/#propdef-color-interpolation-filters
|
||||
tests: [
|
||||
discrete("sRGB", "linearRGB")
|
||||
]
|
||||
},
|
||||
"dominant-baseline": {
|
||||
// https://drafts.csswg.org/css-inline/#propdef-dominant-baseline
|
||||
tests: [
|
||||
discrete("ideographic", "alphabetic")
|
||||
]
|
||||
},
|
||||
"fill-rule": {
|
||||
// https://svgwg.org/svg2-draft/painting.html#FillRuleProperty
|
||||
tests: [
|
||||
discrete("evenodd", "nonzero")
|
||||
]
|
||||
},
|
||||
"flex-basis": {
|
||||
// https://drafts.csswg.org/css-flexbox/#propdef-flex-basis
|
||||
tests: [
|
||||
lengthPercentageOrCalc(),
|
||||
discrete("auto", "10px")
|
||||
]
|
||||
},
|
||||
"flex-direction": {
|
||||
// https://drafts.csswg.org/css-flexbox/#propdef-flex-direction
|
||||
tests: [
|
||||
discrete("row", "row-reverse")
|
||||
]
|
||||
},
|
||||
"flex-grow": {
|
||||
// https://drafts.csswg.org/css-flexbox/#flex-grow-property
|
||||
tests: [
|
||||
positiveNumber()
|
||||
]
|
||||
},
|
||||
"flex-shrink": {
|
||||
// https://drafts.csswg.org/css-flexbox/#propdef-flex-shrink
|
||||
tests: [
|
||||
positiveNumber()
|
||||
]
|
||||
},
|
||||
"flex-wrap": {
|
||||
// https://drafts.csswg.org/css-flexbox/#propdef-flex-wrap
|
||||
tests: [
|
||||
discrete("nowrap", "wrap")
|
||||
]
|
||||
},
|
||||
"font-style": {
|
||||
// https://drafts.csswg.org/css-fonts/#propdef-font-style
|
||||
tests: [
|
||||
discrete("italic", "oblique")
|
||||
]
|
||||
},
|
||||
"image-rendering": {
|
||||
// https://drafts.csswg.org/css-images/#propdef-image-rendering
|
||||
tests: [
|
||||
discrete("optimizeQuality", "pixelated")
|
||||
]
|
||||
},
|
||||
"justify-content": {
|
||||
// https://drafts.csswg.org/css-align/#propdef-justify-content
|
||||
tests: [
|
||||
discrete("baseline", "last-baseline")
|
||||
]
|
||||
},
|
||||
"justify-items": {
|
||||
// https://drafts.csswg.org/css-align/#propdef-justify-items
|
||||
tests: [
|
||||
discrete("baseline", "last-baseline")
|
||||
]
|
||||
},
|
||||
"justify-self": {
|
||||
// https://drafts.csswg.org/css-align/#propdef-justify-self
|
||||
tests: [
|
||||
discrete("baseline", "last-baseline")
|
||||
]
|
||||
},
|
||||
"mask-type": {
|
||||
// https://drafts.fxtf.org/css-masking-1/#propdef-mask-type
|
||||
tests: [
|
||||
discrete("alpha", "luminance")
|
||||
]
|
||||
},
|
||||
"order": {
|
||||
// https://drafts.csswg.org/css-flexbox/#propdef-order
|
||||
tests: [
|
||||
integer()
|
||||
]
|
||||
},
|
||||
"pointer-events": {
|
||||
// https://svgwg.org/svg2-draft/interact.html#PointerEventsProperty
|
||||
tests: [
|
||||
discrete("fill", "none")
|
||||
]
|
||||
},
|
||||
"ruby-align": {
|
||||
// https://drafts.csswg.org/css-ruby-1/#propdef-ruby-align
|
||||
tests: [
|
||||
discrete("start", "center")
|
||||
]
|
||||
},
|
||||
"ruby-position": {
|
||||
// https://drafts.csswg.org/css-ruby-1/#propdef-ruby-position
|
||||
tests: [
|
||||
discrete("under", "over")
|
||||
],
|
||||
tagName: "ruby"
|
||||
},
|
||||
"shape-rendering": {
|
||||
// https://svgwg.org/svg2-draft/painting.html#ShapeRenderingProperty
|
||||
tests: [
|
||||
discrete("optimizeSpeed", "crispEdges")
|
||||
]
|
||||
},
|
||||
"stroke-linecap": {
|
||||
// https://svgwg.org/svg2-draft/painting.html#StrokeLinecapProperty
|
||||
tests: [
|
||||
discrete("round", "square")
|
||||
]
|
||||
},
|
||||
"stroke-linejoin": {
|
||||
// https://svgwg.org/svg2-draft/painting.html#StrokeLinejoinProperty
|
||||
tests: [
|
||||
discrete("round", "miter")
|
||||
],
|
||||
tagName: "rect"
|
||||
},
|
||||
"text-anchor": {
|
||||
// https://svgwg.org/svg2-draft/text.html#TextAnchorProperty
|
||||
tests: [
|
||||
discrete("middle", "end")
|
||||
]
|
||||
},
|
||||
"text-combine-upright": {
|
||||
// https://drafts.csswg.org/css-writing-modes-3/#propdef-text-combine-upright
|
||||
tests: [
|
||||
discrete("all", "digits")
|
||||
]
|
||||
},
|
||||
"text-decoration-line": {
|
||||
// https://drafts.csswg.org/css-text-decor-3/#propdef-text-decoration-line
|
||||
tests: [
|
||||
discrete("underline", "overline")
|
||||
]
|
||||
},
|
||||
"text-orientation": {
|
||||
// https://drafts.csswg.org/css-writing-modes-3/#propdef-text-orientation
|
||||
tests: [
|
||||
discrete("upright", "sideways")
|
||||
]
|
||||
},
|
||||
"text-rendering": {
|
||||
// https://svgwg.org/svg2-draft/painting.html#TextRenderingProperty
|
||||
tests: [
|
||||
discrete("optimizeSpeed", "optimizeLegibility")
|
||||
]
|
||||
},
|
||||
"vector-effect": {
|
||||
// https://svgwg.org/svg2-draft/coords.html#VectorEffectProperty
|
||||
tests: [
|
||||
discrete("none", "non-scaling-stroke")
|
||||
]
|
||||
},
|
||||
"visibility": {
|
||||
// https://drafts.csswg.org/css2/visufx.html#propdef-visibility
|
||||
tests: [
|
||||
visibility()
|
||||
]
|
||||
},
|
||||
"word-break": {
|
||||
// https://drafts.csswg.org/css-text-3/#propdef-word-break
|
||||
tests: [
|
||||
discrete("keep-all", "break-all")
|
||||
]
|
||||
},
|
||||
"writing-mode": {
|
||||
// https://drafts.csswg.org/css-writing-modes-3/#propdef-writing-mode
|
||||
tests: [
|
||||
discrete("vertical-rl", "sideways-rl")
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
for (var property in gCSSProperties) {
|
||||
if (!isSupported(property)) {
|
||||
continue;
|
||||
}
|
||||
var testData = gCSSProperties[property];
|
||||
testData.tests.forEach(function(testFunction) {
|
||||
testFunction(property, testData);
|
||||
});
|
||||
}
|
||||
|
||||
function discrete(from, to) {
|
||||
return function(property, options) {
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = [from, to];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: from.toLowerCase() },
|
||||
{ time: 499, expected: from.toLowerCase() },
|
||||
{ time: 500, expected: to.toLowerCase() },
|
||||
{ time: 1000, expected: to.toLowerCase() }]);
|
||||
}, property + " uses discrete animation when animating between '"
|
||||
+ from + "' and '" + to + "' with linear easing");
|
||||
|
||||
test(function(t) {
|
||||
// Easing: http://cubic-bezier.com/#.68,0,1,.01
|
||||
// With this curve, we don't reach the 50% point until about 95% of
|
||||
// the time has expired.
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = [from, to];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both",
|
||||
easing: "cubic-bezier(0.68,0,1,0.01)" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: from.toLowerCase() },
|
||||
{ time: 940, expected: from.toLowerCase() },
|
||||
{ time: 960, expected: to.toLowerCase() }]);
|
||||
}, property + " uses discrete animation when animating between '"
|
||||
+ from + "' and '" + to + "' with effect easing");
|
||||
|
||||
test(function(t) {
|
||||
// Easing: http://cubic-bezier.com/#.68,0,1,.01
|
||||
// With this curve, we don't reach the 50% point until about 95% of
|
||||
// the time has expired.
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = [from, to];
|
||||
keyframes.easing = "cubic-bezier(0.68,0,1,0.01)";
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: from.toLowerCase() },
|
||||
{ time: 940, expected: from.toLowerCase() },
|
||||
{ time: 960, expected: to.toLowerCase() }]);
|
||||
}, property + " uses discrete animation when animating between '"
|
||||
+ from + "' and '" + to + "' with keyframe easing");
|
||||
}
|
||||
}
|
||||
|
||||
function length() {
|
||||
return function(property, options) {
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = ["10px", "50px"];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "10px" },
|
||||
{ time: 500, expected: "30px" },
|
||||
{ time: 1000, expected: "50px" }]);
|
||||
}, property + " supports animating as a length");
|
||||
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = ["1rem", "5rem"];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "10px" },
|
||||
{ time: 500, expected: "30px" },
|
||||
{ time: 1000, expected: "50px" }]);
|
||||
}, property + " supports animating as a length of rem");
|
||||
}
|
||||
}
|
||||
|
||||
function percentage() {
|
||||
return function(property, options) {
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = ["10%", "50%"];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "10%" },
|
||||
{ time: 500, expected: "30%" },
|
||||
{ time: 1000, expected: "50%" }]);
|
||||
}, property + " supports animating as a percentage");
|
||||
}
|
||||
}
|
||||
|
||||
function integer() {
|
||||
return function(property, options) {
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = [-2, 2];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "-2" },
|
||||
{ time: 500, expected: "0" },
|
||||
{ time: 1000, expected: "2" }]);
|
||||
}, property + " supports animating as an integer");
|
||||
}
|
||||
}
|
||||
|
||||
function positiveNumber() {
|
||||
return function(property, options) {
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = [1.1, 1.5];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "1.1" },
|
||||
{ time: 500, expected: "1.3" },
|
||||
{ time: 1000, expected: "1.5" }]);
|
||||
}, property + " supports animating as a positive number");
|
||||
}
|
||||
}
|
||||
|
||||
function lengthPercentageOrCalc() {
|
||||
return function(property, options) {
|
||||
length()(property, options);
|
||||
percentage()(property, options);
|
||||
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = ["10px", "20%"];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "10px" },
|
||||
{ time: 500, expected: "calc(5px + 10%)" },
|
||||
{ time: 1000, expected: "20%" }]);
|
||||
}, property + " supports animating as combination units 'px' and '%'");
|
||||
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = ["10%", "2em"];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "10%" },
|
||||
{ time: 500, expected: "calc(10px + 5%)" },
|
||||
{ time: 1000, expected: "20px" }]);
|
||||
}, property + " supports animating as combination units '%' and 'em'");
|
||||
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = ["1em", "2rem"];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "10px" },
|
||||
{ time: 500, expected: "15px" },
|
||||
{ time: 1000, expected: "20px" }]);
|
||||
}, property + " supports animating as combination units 'em' and 'rem'");
|
||||
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = ["10px", "calc(1em + 20%)"];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "10px" },
|
||||
{ time: 500, expected: "calc(10px + 10%)" },
|
||||
{ time: 1000, expected: "calc(10px + 20%)" }]);
|
||||
}, property + " supports animating as combination units 'px' and 'calc'");
|
||||
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = ["calc(10px + 10%)", "calc(1em + 1rem + 20%)"];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0,
|
||||
expected: "calc(10px + 10%)" },
|
||||
{ time: 500,
|
||||
expected: "calc(15px + 15%)" },
|
||||
{ time: 1000,
|
||||
expected: "calc(20px + 20%)" }]);
|
||||
}, property + " supports animating as a calc");
|
||||
}
|
||||
}
|
||||
|
||||
function visibility() {
|
||||
return function(property, options) {
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = ["visible", "hidden"];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "visible" },
|
||||
{ time: 999, expected: "visible" },
|
||||
{ time: 1000, expected: "hidden" }]);
|
||||
}, property + " uses visibility animation when animating "
|
||||
+ "from 'visible' to 'hidden'");
|
||||
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = ["hidden", "visible"];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "hidden" },
|
||||
{ time: 1, expected: "visible" },
|
||||
{ time: 1000, expected: "visible" }]);
|
||||
}, property + " uses visibility animation when animating "
|
||||
+ "from 'hidden' to 'visible'");
|
||||
|
||||
test(function(t) {
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = ["hidden", "collapse"];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation = target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "hidden" },
|
||||
{ time: 499, expected: "hidden" },
|
||||
{ time: 500, expected: "collapse" },
|
||||
{ time: 1000, expected: "collapse" }]);
|
||||
}, property + " uses visibility animation when animating "
|
||||
+ "from 'hidden' to 'collapse'");
|
||||
|
||||
test(function(t) {
|
||||
// Easing: http://cubic-bezier.com/#.68,-.55,.26,1.55
|
||||
// With this curve, the value is less than 0 till about 34%
|
||||
// also more than 1 since about 63%
|
||||
var idlName = propertyToIDL(property);
|
||||
var keyframes = {};
|
||||
keyframes[idlName] = ["visible", "hidden"];
|
||||
var target = createElement(t, options.tagName);
|
||||
var animation =
|
||||
target.animate(keyframes,
|
||||
{ duration: 1000, fill: "both",
|
||||
easing: "cubic-bezier(0.68, -0.55, 0.26, 1.55)" });
|
||||
testAnimationSamples(animation, idlName,
|
||||
[{ time: 0, expected: "visible" },
|
||||
{ time: 1, expected: "visible" },
|
||||
{ time: 330, expected: "visible" },
|
||||
{ time: 340, expected: "visible" },
|
||||
{ time: 620, expected: "visible" },
|
||||
{ time: 630, expected: "hidden" },
|
||||
{ time: 1000, expected: "hidden" }]);
|
||||
}, property + " uses visibility animation when animating "
|
||||
+ "from 'visible' to 'hidden' with easeInOutBack easing");
|
||||
}
|
||||
}
|
||||
|
||||
function testAnimationSamples(animation, idlName, testSamples) {
|
||||
var target = animation.effect.target;
|
||||
testSamples.forEach(function(testSample) {
|
||||
animation.currentTime = testSample.time;
|
||||
assert_equals(getComputedStyle(target)[idlName], testSample.expected,
|
||||
"The value should be " + testSample.expected +
|
||||
" at " + testSample.time + "ms");
|
||||
});
|
||||
}
|
||||
|
||||
function isSupported(property) {
|
||||
var testKeyframe = new TestKeyframe(propertyToIDL(property));
|
||||
try {
|
||||
// Since TestKeyframe returns 'undefined' for |property|,
|
||||
// the KeyframeEffect constructor will throw
|
||||
// if the string "undefined" is not a valid value for the property.
|
||||
new KeyframeEffect(null, testKeyframe);
|
||||
} catch(e) {}
|
||||
return testKeyframe.propAccessCount !== 0;
|
||||
}
|
||||
|
||||
function TestKeyframe(testProp) {
|
||||
var _propAccessCount = 0;
|
||||
|
||||
Object.defineProperty(this, testProp, {
|
||||
get: function() { _propAccessCount++; },
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'propAccessCount', {
|
||||
get: function() { return _propAccessCount; }
|
||||
});
|
||||
}
|
||||
|
||||
function propertyToIDL(property) {
|
||||
// https://w3c.github.io/web-animations/#animation-property-name-to-idl-attribute-name
|
||||
if (property === "float") {
|
||||
return "cssFloat";
|
||||
}
|
||||
return property.replace(/-[a-z]/gi,
|
||||
function (str) {
|
||||
return str.substr(1).toUpperCase(); });
|
||||
}
|
||||
|
||||
</script>
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
@ -82,5 +81,23 @@ promise_test(function(t) {
|
|||
});
|
||||
}, 'Effect values reflect changes to font-size from reparenting');
|
||||
|
||||
test(function(t) {
|
||||
var divA = createDiv(t);
|
||||
divA.style.fontSize = '10px';
|
||||
|
||||
var divB = createDiv(t);
|
||||
divB.style.fontSize = '20px';
|
||||
|
||||
var animation = divA.animate([ { marginLeft: '10em' },
|
||||
{ marginLeft: '20em' } ], 1000);
|
||||
animation.currentTime = 500;
|
||||
assert_equals(getComputedStyle(divA).marginLeft, '150px',
|
||||
'Effect value before updating target element');
|
||||
|
||||
animation.effect.target = divB;
|
||||
assert_equals(getComputedStyle(divB).marginLeft, '300px',
|
||||
'Effect value after updating target element');
|
||||
}, 'Effect values reflect changes to target element');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<script src="../../resources/keyframe-utils.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<iframe width="10" height="10" id="iframe"></iframe>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
|
@ -19,13 +20,57 @@ test(function(t) {
|
|||
assert_class_string(anim, 'Animation', 'Returned object is an Animation');
|
||||
}, 'Element.animate() creates an Animation object');
|
||||
|
||||
test(function(t) {
|
||||
var iframe = window.frames[0];
|
||||
var div = createDiv(t, iframe.document);
|
||||
var anim = Element.prototype.animate.call(div, null);
|
||||
assert_equals(Object.getPrototypeOf(anim), iframe.Animation.prototype,
|
||||
'The prototype of the created Animation is that defined on'
|
||||
+ ' the relevant global for the target element');
|
||||
assert_not_equals(Object.getPrototypeOf(anim), Animation.prototype,
|
||||
'The prototype of the created Animation is NOT that of'
|
||||
+ ' the current global');
|
||||
}, 'Element.animate() creates an Animation object in the relevant realm of'
|
||||
+ ' the target element');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate(null);
|
||||
var anim = Element.prototype.animate.call(div, null);
|
||||
assert_class_string(anim.effect, 'KeyframeEffect',
|
||||
'Returned Animation has a KeyframeEffect');
|
||||
}, 'Element.animate() creates an Animation object with a KeyframeEffect');
|
||||
|
||||
test(function(t) {
|
||||
var iframe = window.frames[0];
|
||||
var div = createDiv(t, iframe.document);
|
||||
var anim = Element.prototype.animate.call(div, null);
|
||||
assert_equals(Object.getPrototypeOf(anim.effect),
|
||||
iframe.KeyframeEffect.prototype,
|
||||
'The prototype of the created KeyframeEffect is that defined on'
|
||||
+ ' the relevant global for the target element');
|
||||
assert_not_equals(Object.getPrototypeOf(anim.effect),
|
||||
KeyframeEffect.prototype,
|
||||
'The prototype of the created KeyframeEffect is NOT that of'
|
||||
+ ' the current global');
|
||||
}, 'Element.animate() creates an Animation object with a KeyframeEffect'
|
||||
+ ' that is created in the relevant realm of the target element');
|
||||
|
||||
test(function(t) {
|
||||
var iframe = window.frames[0];
|
||||
var div = createDiv(t, iframe.document);
|
||||
var anim = div.animate(null);
|
||||
assert_equals(Object.getPrototypeOf(anim.effect.timing),
|
||||
iframe.AnimationEffectTiming.prototype,
|
||||
'The prototype of the created AnimationEffectTiming is that'
|
||||
+ ' defined on the relevant global for the target element');
|
||||
assert_not_equals(Object.getPrototypeOf(anim.effect.timing),
|
||||
AnimationEffectTiming.prototype,
|
||||
'The prototype of the created AnimationEffectTiming is NOT'
|
||||
+ ' that of the current global');
|
||||
}, 'Element.animate() creates an Animation object with a KeyframeEffect'
|
||||
+ ' whose AnimationEffectTiming object is created in the relevant realm'
|
||||
+ ' of the target element');
|
||||
|
||||
gPropertyIndexedKeyframesTests.forEach(function(subtest) {
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -13,45 +13,52 @@
|
|||
"use strict";
|
||||
|
||||
var gTarget = document.getElementById("target");
|
||||
var gEffect = new KeyframeEffectReadOnly(gTarget, { opacity: [0, 1] });
|
||||
|
||||
function createEffect() {
|
||||
return new KeyframeEffectReadOnly(gTarget, { opacity: [0, 1] });
|
||||
}
|
||||
|
||||
function createNull() {
|
||||
return null;
|
||||
}
|
||||
|
||||
var gTestArguments = [
|
||||
{
|
||||
effect: null,
|
||||
createEffect: createNull,
|
||||
timeline: null,
|
||||
expectedTimeline: null,
|
||||
expectedTimelineDescription: "null",
|
||||
description: "with null effect and null timeline"
|
||||
},
|
||||
{
|
||||
effect: null,
|
||||
createEffect: createNull,
|
||||
timeline: document.timeline,
|
||||
expectedTimeline: document.timeline,
|
||||
expectedTimelineDescription: "document.timeline",
|
||||
description: "with null effect and non-null timeline"
|
||||
},
|
||||
{
|
||||
effect: null,
|
||||
createEffect: createNull,
|
||||
expectedTimeline: document.timeline,
|
||||
expectedTimelineDescription: "document.timeline",
|
||||
description: "with null effect and no timeline parameter"
|
||||
},
|
||||
{
|
||||
effect: gEffect,
|
||||
createEffect: createEffect,
|
||||
timeline: null,
|
||||
expectedTimeline: null,
|
||||
expectedTimelineDescription: "null",
|
||||
description: "with non-null effect and null timeline"
|
||||
},
|
||||
{
|
||||
effect: gEffect,
|
||||
createEffect: createEffect,
|
||||
timeline: document.timeline,
|
||||
expectedTimeline: document.timeline,
|
||||
expectedTimelineDescription: "document.timeline",
|
||||
description: "with non-null effect and non-null timeline"
|
||||
},
|
||||
{
|
||||
effect: gEffect,
|
||||
createEffect: createEffect,
|
||||
expectedTimeline: document.timeline,
|
||||
expectedTimelineDescription: "document.timeline",
|
||||
description: "with non-null effect and no timeline parameter"
|
||||
|
@ -60,11 +67,12 @@ var gTestArguments = [
|
|||
|
||||
gTestArguments.forEach(function(args) {
|
||||
test(function(t) {
|
||||
var animation = new Animation(args.effect, args.timeline);
|
||||
var effect = args.createEffect();
|
||||
var animation = new Animation(effect, args.timeline);
|
||||
|
||||
assert_not_equals(animation, null,
|
||||
"An animation sohuld be created");
|
||||
assert_equals(animation.effect, args.effect,
|
||||
assert_equals(animation.effect, effect,
|
||||
"Animation returns the same effect passed to " +
|
||||
"the Constructor");
|
||||
assert_equals(animation.timeline, args.expectedTimeline,
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -6,7 +6,6 @@ href="https://w3c.github.io/web-animations/#dom-animation-starttime">
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -28,7 +28,8 @@ gEffectEasingTests.forEach(function(options) {
|
|||
{ duration: 1000 * MS_PER_SEC,
|
||||
fill: 'forwards' });
|
||||
anim.effect.timing.easing = options.easing;
|
||||
assert_equals(anim.effect.timing.easing, options.easing);
|
||||
assert_equals(anim.effect.timing.easing,
|
||||
options.serialization || options.easing);
|
||||
|
||||
var easing = options.easingFunction;
|
||||
assert_progress(anim, 0, easing);
|
||||
|
@ -39,18 +40,16 @@ gEffectEasingTests.forEach(function(options) {
|
|||
}, options.desc);
|
||||
});
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
|
||||
assert_throws({ name: 'TypeError' },
|
||||
function() {
|
||||
anim.effect.timing.easing = '';
|
||||
});
|
||||
assert_throws({ name: 'TypeError' },
|
||||
function() {
|
||||
anim.effect.timing.easing = 'test';
|
||||
});
|
||||
}, 'Test invalid easing value');
|
||||
gInvalidEasingTests.forEach(function(options) {
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
|
||||
assert_throws({ name: 'TypeError' },
|
||||
function() {
|
||||
anim.effect.timing.easing = options.easing;
|
||||
});
|
||||
}, 'Invalid effect easing value test: \'' + options.easing + '\'');
|
||||
});
|
||||
|
||||
test(function(t) {
|
||||
var delay = 1000 * MS_PER_SEC;
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -104,15 +104,15 @@ test(function(t) {
|
|||
'set currentTime before endTime');
|
||||
|
||||
anim.currentTime = 5000;
|
||||
assert_equals(getComputedStyle(div).opacity, '0',
|
||||
assert_equals(getComputedStyle(div).opacity, '0.5',
|
||||
'set currentTime same as endTime');
|
||||
|
||||
anim.currentTime = 9999;
|
||||
assert_equals(getComputedStyle(div).opacity, '0',
|
||||
assert_equals(getComputedStyle(div).opacity, '0.5',
|
||||
'set currentTime during duration');
|
||||
|
||||
anim.currentTime = 10000;
|
||||
assert_equals(getComputedStyle(div).opacity, '0',
|
||||
assert_equals(getComputedStyle(div).opacity, '0.5',
|
||||
'set currentTime after endTime');
|
||||
}, 'change currentTime when fill forwards and endDelay is negative');
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
|
|
@ -669,5 +669,15 @@ gStepTimingFunctionTests.forEach(function(options) {
|
|||
}, options.description);
|
||||
});
|
||||
|
||||
gInvalidEasingTests.forEach(function(options) {
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
assert_throws({ name: 'TypeError' },
|
||||
function() {
|
||||
div.animate({ easing: options.easing }, 100 * MS_PER_SEC);
|
||||
});
|
||||
}, 'Invalid keyframe easing value: \'' + options.easing + '\'');
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<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>
|
||||
|
@ -79,7 +80,246 @@ gNonAnimatableProps.forEach(function(prop) {
|
|||
+ ' a keyframe sequence');
|
||||
});
|
||||
|
||||
// FIXME: Test that non-enumerable properties are not accessed
|
||||
// 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', left: '100px,200px'}
|
||||
]);
|
||||
}, 'Custom iterator with value list in keyframe should give bizarre string representation 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
|
||||
|
|
|
@ -1,13 +1,42 @@
|
|||
var gEffectEasingTests = [
|
||||
{
|
||||
desc: 'steps(start) function',
|
||||
desc: 'step-start function',
|
||||
easing: 'step-start',
|
||||
easingFunction: stepStart(1),
|
||||
serialization: 'steps(1, start)'
|
||||
},
|
||||
{
|
||||
desc: 'steps(1, start) function',
|
||||
easing: 'steps(1, start)',
|
||||
easingFunction: stepStart(1)
|
||||
},
|
||||
{
|
||||
desc: 'steps(2, start) function',
|
||||
easing: 'steps(2, start)',
|
||||
easingFunction: stepStart(2)
|
||||
},
|
||||
{
|
||||
desc: 'steps(end) function',
|
||||
desc: 'step-end function',
|
||||
easing: 'step-end',
|
||||
easingFunction: stepEnd(1),
|
||||
serialization: 'steps(1)'
|
||||
},
|
||||
{
|
||||
desc: 'steps(1) function',
|
||||
easing: 'steps(1)',
|
||||
easingFunction: stepEnd(1)
|
||||
},
|
||||
{
|
||||
desc: 'steps(1, end) function',
|
||||
easing: 'steps(1, end)',
|
||||
easingFunction: stepEnd(1),
|
||||
serialization: 'steps(1)'
|
||||
},
|
||||
{
|
||||
desc: 'steps(2, end) function',
|
||||
easing: 'steps(2, end)',
|
||||
easingFunction: stepEnd(2)
|
||||
easingFunction: stepEnd(2),
|
||||
serialization: 'steps(2)'
|
||||
},
|
||||
{
|
||||
desc: 'linear function',
|
||||
|
@ -40,3 +69,30 @@ var gEffectEasingTests = [
|
|||
easingFunction: cubicBezier(0, 1.5, 1, 1.5)
|
||||
}
|
||||
];
|
||||
|
||||
var gInvalidEasingTests = [
|
||||
{
|
||||
easing: ''
|
||||
},
|
||||
{
|
||||
easing: 'test'
|
||||
},
|
||||
{
|
||||
easing: 'cubic-bezier(1.1, 0, 1, 1)'
|
||||
},
|
||||
{
|
||||
easing: 'cubic-bezier(0, 0, 1.1, 1)'
|
||||
},
|
||||
{
|
||||
easing: 'cubic-bezier(-0.1, 0, 1, 1)'
|
||||
},
|
||||
{
|
||||
easing: 'cubic-bezier(0, 0, -0.1, 1)'
|
||||
},
|
||||
{
|
||||
easing: 'steps(-1, start)'
|
||||
},
|
||||
{
|
||||
easing: 'steps(0.1, start)'
|
||||
},
|
||||
];
|
||||
|
|
|
@ -257,6 +257,10 @@ var gKeyframeSequenceTests = [
|
|||
input: [{ left: "10px" }],
|
||||
output: [{ offset: null, computedOffset: 1, easing: "linear",
|
||||
left: "10px" }] },
|
||||
{ desc: "a single keyframe sequence with string offset",
|
||||
input: [{ offset: '0.5', left: "10px" }],
|
||||
output: [{ offset: 0.5, computedOffset: 1, easing: "linear",
|
||||
left: "10px" }] },
|
||||
{ desc: "a one property keyframe sequence with some omitted offsets",
|
||||
input: [{ offset: 0.00, left: "10px" },
|
||||
{ offset: 0.25, left: "20px" },
|
||||
|
@ -321,9 +325,9 @@ var gKeyframeSequenceTests = [
|
|||
left: "30px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||
top: "40px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "step-end",
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "steps(1)",
|
||||
left: "50px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "step-end",
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "steps(1)",
|
||||
top: "60px" }] },
|
||||
{ desc: "a keyframe sequence with different composite values, but the"
|
||||
+ " same composite value for a given offset",
|
||||
|
@ -432,7 +436,7 @@ var gKeyframeSequenceTests = [
|
|||
left: "300px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "ease-out",
|
||||
left: "400px" },
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "step-end",
|
||||
{ offset: 1.0, computedOffset: 1.0, easing: "steps(1)",
|
||||
left: "500px" }] },
|
||||
];
|
||||
|
||||
|
|
|
@ -28,15 +28,22 @@ if (!window.assert_times_equal) {
|
|||
// creates div element, appends it to the document body and
|
||||
// removes the created element during test cleanup
|
||||
function createDiv(test, doc) {
|
||||
return createElement(test, 'div', doc);
|
||||
}
|
||||
|
||||
// creates element of given tagName, appends it to the document body and
|
||||
// removes the created element during test cleanup
|
||||
// if tagName is null or undefined, returns div element
|
||||
function createElement(test, tagName, doc) {
|
||||
if (!doc) {
|
||||
doc = document;
|
||||
}
|
||||
var div = doc.createElement('div');
|
||||
doc.body.appendChild(div);
|
||||
var element = doc.createElement(tagName || 'div');
|
||||
doc.body.appendChild(element);
|
||||
test.add_cleanup(function() {
|
||||
div.remove();
|
||||
element.remove();
|
||||
});
|
||||
return div;
|
||||
return element;
|
||||
}
|
||||
|
||||
// Creates a style element with the specified rules, appends it to the document
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Active time tests</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#active-time">
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#calculating-the-active-time">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
|
@ -10,15 +10,133 @@
|
|||
<script>
|
||||
'use strict';
|
||||
|
||||
async_test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, { delay: 1 });
|
||||
test(function(t) {
|
||||
var tests = [ { fill: 'none', progress: null },
|
||||
{ fill: 'backwards', progress: 0 },
|
||||
{ fill: 'forwards', progress: null },
|
||||
{ fill: 'both', progress: 0 } ];
|
||||
tests.forEach(function(test) {
|
||||
var anim = createDiv(t).animate(null, { delay: 1, fill: test.fill });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, test.progress,
|
||||
'Progress in before phase when using \'' + test.fill
|
||||
+ '\' fill');
|
||||
});
|
||||
}, 'Active time in before phase');
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 1000);
|
||||
anim.currentTime = 500;
|
||||
assert_times_equal(anim.effect.getComputedTiming().progress, 0.5);
|
||||
}, 'Active time in active phase and no start delay is the local time');
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, { duration: 1000, delay: 500 });
|
||||
anim.currentTime = 1000;
|
||||
assert_times_equal(anim.effect.getComputedTiming().progress, 0.5);
|
||||
}, 'Active time in active phase and positive start delay is the local time'
|
||||
+ ' minus the start delay');
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, { duration: 1000, delay: -500 });
|
||||
assert_times_equal(anim.effect.getComputedTiming().progress, 0.5);
|
||||
}, 'Active time in active phase and negative start delay is the local time'
|
||||
+ ' minus the start delay');
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null);
|
||||
assert_equals(anim.effect.getComputedTiming().progress, null);
|
||||
anim.finished.then(t.step_func(function() {
|
||||
assert_equals(anim.effect.getComputedTiming().progress, null);
|
||||
t.done();
|
||||
}));
|
||||
}, 'Test progress during before and after phase when fill is none');
|
||||
}, 'Active time in after phase with no fill is unresolved');
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, { fill: 'backwards' });
|
||||
assert_equals(anim.effect.getComputedTiming().progress, null);
|
||||
}, 'Active time in after phase with backwards-only fill is unresolved');
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, { duration: 1000,
|
||||
iterations: 2.3,
|
||||
delay: 500, // Should have no effect
|
||||
fill: 'forwards' });
|
||||
anim.finish();
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
|
||||
assert_times_equal(anim.effect.getComputedTiming().progress, 0.3);
|
||||
}, 'Active time in after phase with forwards fill is the active duration');
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, { duration: 0,
|
||||
iterations: Infinity,
|
||||
fill: 'forwards' });
|
||||
anim.finish();
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, Infinity);
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 1);
|
||||
}, 'Active time in after phase with forwards fill, zero-duration, and '
|
||||
+ ' infinite iteration count is the active duration');
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, { duration: 1000,
|
||||
iterations: 2.3,
|
||||
delay: 500,
|
||||
endDelay: 4000,
|
||||
fill: 'forwards' });
|
||||
anim.finish();
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
|
||||
assert_times_equal(anim.effect.getComputedTiming().progress, 0.3);
|
||||
}, 'Active time in after phase with forwards fill and positive end delay'
|
||||
+ ' is the active duration');
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, { duration: 1000,
|
||||
iterations: 2.3,
|
||||
delay: 500,
|
||||
endDelay: -800,
|
||||
fill: 'forwards' });
|
||||
anim.finish();
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 1);
|
||||
assert_times_equal(anim.effect.getComputedTiming().progress, 0.5);
|
||||
}, 'Active time in after phase with forwards fill and negative end delay'
|
||||
+ ' is the active duration + end delay');
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, { duration: 1000,
|
||||
iterations: 2.3,
|
||||
delay: 500,
|
||||
endDelay: -3000,
|
||||
fill: 'forwards' });
|
||||
anim.finish();
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 0);
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0);
|
||||
}, 'Active time in after phase with forwards fill and negative end delay'
|
||||
+ ' greater in magnitude than the active duration is zero');
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, { duration: 1000,
|
||||
iterations: 2.3,
|
||||
delay: 500,
|
||||
endDelay: -4000,
|
||||
fill: 'forwards' });
|
||||
anim.finish();
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 0);
|
||||
assert_equals(anim.effect.getComputedTiming().progress, 0);
|
||||
}, 'Active time in after phase with forwards fill and negative end delay'
|
||||
+ ' greater in magnitude than the sum of the active duration and start delay'
|
||||
+ ' is zero');
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, { duration: 1000,
|
||||
iterations: 2.3,
|
||||
delay: 500,
|
||||
fill: 'both' });
|
||||
anim.finish();
|
||||
assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
|
||||
assert_times_equal(anim.effect.getComputedTiming().progress, 0.3);
|
||||
}, 'Active time in after phase with \'both\' fill is the active duration');
|
||||
|
||||
test(function(t) {
|
||||
// Create an effect with a non-zero duration so we ensure we're not just
|
||||
// testing the after-phase behavior.
|
||||
var effect = new KeyframeEffect(null, null, 1);
|
||||
assert_equals(effect.getComputedTiming().progress, null);
|
||||
}, 'Active time when the local time is unresolved, is unresolved');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<script>
|
||||
'use strict';
|
||||
|
||||
function executeTests(tests, description) {
|
||||
function runTests(tests, description) {
|
||||
tests.forEach(function(currentTest) {
|
||||
var testParams = '';
|
||||
for (var attr in currentTest.input) {
|
||||
|
@ -29,7 +29,7 @@ function executeTests(tests, description) {
|
|||
assert_equals(anim.effect.getComputedTiming().currentIteration,
|
||||
currentTest.after);
|
||||
}
|
||||
}, description + testParams);
|
||||
}, description + ':' + testParams);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,14 @@ async_test(function(t) {
|
|||
}));
|
||||
}, 'Test currentIteration during before and after phase when fill is none');
|
||||
|
||||
var gTests_zero_iterations = [
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// Zero iteration duration tests
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
runTests([
|
||||
{
|
||||
input: { iterations: 0,
|
||||
iterationStart: 0,
|
||||
|
@ -142,9 +149,16 @@ var gTests_zero_iterations = [
|
|||
active: 3,
|
||||
after: 3
|
||||
}
|
||||
];
|
||||
], 'Test zero iterations');
|
||||
|
||||
var gTests_integer_iterations = [
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// Tests where the iteration count is an integer
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
runTests([
|
||||
{
|
||||
input: { iterations: 3,
|
||||
iterationStart: 0,
|
||||
|
@ -240,9 +254,16 @@ var gTests_integer_iterations = [
|
|||
before: 3,
|
||||
active: 3
|
||||
}
|
||||
];
|
||||
], 'Test integer iterations');
|
||||
|
||||
var gTests_fractional_iterations = [
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// Tests where the iteration count is a fraction
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
runTests([
|
||||
{
|
||||
input: { iterations: 3.5,
|
||||
iterationStart: 0,
|
||||
|
@ -338,9 +359,16 @@ var gTests_fractional_iterations = [
|
|||
before: 3,
|
||||
active: 3
|
||||
}
|
||||
];
|
||||
], 'Test fractional iterations');
|
||||
|
||||
var gTests_infinity_iterations = [
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// Tests where the iteration count is Infinity
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
runTests([
|
||||
{
|
||||
input: { iterations: Infinity,
|
||||
iterationStart: 0,
|
||||
|
@ -433,12 +461,124 @@ var gTests_infinity_iterations = [
|
|||
before: 3,
|
||||
active: 3
|
||||
}
|
||||
];
|
||||
], 'Test infinity iterations');
|
||||
|
||||
executeTests(gTests_zero_iterations, "Test zero iterations:");
|
||||
executeTests(gTests_integer_iterations, "Test integer iterations:");
|
||||
executeTests(gTests_fractional_iterations, "Test fractional iterations:");
|
||||
executeTests(gTests_infinity_iterations, "Test infinity iterations:");
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// End delay tests
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
runTests([
|
||||
{
|
||||
input: { duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: 50 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 0
|
||||
},
|
||||
|
||||
{
|
||||
input: { duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -50 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 0
|
||||
},
|
||||
|
||||
{
|
||||
input: { duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -100 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 0
|
||||
},
|
||||
|
||||
{
|
||||
input: { duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -200 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 0
|
||||
},
|
||||
|
||||
{
|
||||
input: { iterationStart: 0.5,
|
||||
duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: 50 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 1
|
||||
},
|
||||
|
||||
{
|
||||
input: { iterationStart: 0.5,
|
||||
duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -50 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 0
|
||||
},
|
||||
|
||||
{
|
||||
input: { iterationStart: 0.5,
|
||||
duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -100 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 0
|
||||
},
|
||||
|
||||
{
|
||||
input: { iterations: 2,
|
||||
duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -100 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 0
|
||||
},
|
||||
|
||||
{
|
||||
input: { iterations: 1,
|
||||
iterationStart: 2,
|
||||
duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -50 },
|
||||
before: 2,
|
||||
active: 2,
|
||||
after: 2
|
||||
},
|
||||
|
||||
{
|
||||
input: { iterations: 1,
|
||||
iterationStart: 2,
|
||||
duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -100 },
|
||||
before: 2,
|
||||
active: 2,
|
||||
after: 2
|
||||
},
|
||||
], 'Test end delay');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Tests for phases and states</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#animation-effect-phases-and-states">
|
||||
<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';
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// Phases
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
function assert_phase_at_time(animation, phase, currentTime) {
|
||||
animation.currentTime = currentTime;
|
||||
|
||||
if (phase === 'active') {
|
||||
// If the fill mode is 'none', then progress will only be non-null if we
|
||||
// are in the active phase.
|
||||
animation.effect.timing.fill = 'none';
|
||||
assert_not_equals(animation.effect.getComputedTiming().progress, null,
|
||||
'Animation effect is in active phase when current time'
|
||||
+ ' is ' + currentTime + 'ms');
|
||||
} else {
|
||||
// The easiest way to distinguish between the 'before' phase and the 'after'
|
||||
// phase is to toggle the fill mode. For example, if the progress is null
|
||||
// will the fill node is 'none' but non-null when the fill mode is
|
||||
// 'backwards' then we are in the before phase.
|
||||
animation.effect.timing.fill = 'none';
|
||||
assert_equals(animation.effect.getComputedTiming().progress, null,
|
||||
'Animation effect is in ' + phase + ' phase when current time'
|
||||
+ ' is ' + currentTime + 'ms'
|
||||
+ ' (progress is null with \'none\' fill mode)');
|
||||
|
||||
animation.effect.timing.fill = phase === 'before'
|
||||
? 'backwards'
|
||||
: 'forwards';
|
||||
assert_not_equals(animation.effect.getComputedTiming().progress, null,
|
||||
'Animation effect is in ' + phase + ' phase when current'
|
||||
+ ' time is ' + currentTime + 'ms'
|
||||
+ ' (progress is non-null with appropriate fill mode)');
|
||||
}
|
||||
}
|
||||
|
||||
test(function(t) {
|
||||
var animation = createDiv(t).animate(null, 1);
|
||||
|
||||
[ { currentTime: -1, phase: 'before' },
|
||||
{ currentTime: 0, phase: 'active' },
|
||||
{ currentTime: 1, phase: 'after' } ]
|
||||
.forEach(function(test) {
|
||||
assert_phase_at_time(animation, test.phase, test.currentTime);
|
||||
});
|
||||
}, 'Phase calculation for a simple animation effect');
|
||||
|
||||
test(function(t) {
|
||||
var animation = createDiv(t).animate(null, { duration: 1, delay: 1 });
|
||||
|
||||
[ { currentTime: 0, phase: 'before' },
|
||||
{ currentTime: 1, phase: 'active' },
|
||||
{ currentTime: 2, phase: 'after' } ]
|
||||
.forEach(function(test) {
|
||||
assert_phase_at_time(animation, test.phase, test.currentTime);
|
||||
});
|
||||
}, 'Phase calculation for an animation effect with a positive start delay');
|
||||
|
||||
test(function(t) {
|
||||
var animation = createDiv(t).animate(null, { duration: 1, delay: -1 });
|
||||
|
||||
[ { currentTime: -2, phase: 'before' },
|
||||
{ currentTime: -1, phase: 'active' },
|
||||
{ currentTime: 0, phase: 'after' } ]
|
||||
.forEach(function(test) {
|
||||
assert_phase_at_time(animation, test.phase, test.currentTime);
|
||||
});
|
||||
}, 'Phase calculation for an animation effect with a negative start delay');
|
||||
|
||||
test(function(t) {
|
||||
var animation = createDiv(t).animate(null, { duration: 1, endDelay: 1 });
|
||||
|
||||
[ { currentTime: -1, phase: 'before' },
|
||||
{ currentTime: 0, phase: 'active' },
|
||||
{ currentTime: 1, phase: 'after' },
|
||||
{ currentTime: 2, phase: 'after' } ]
|
||||
.forEach(function(test) {
|
||||
assert_phase_at_time(animation, test.phase, test.currentTime);
|
||||
});
|
||||
}, 'Phase calculation for an animation effect with a positive end delay');
|
||||
|
||||
test(function(t) {
|
||||
var animation = createDiv(t).animate(null, { duration: 2, endDelay: -1 });
|
||||
|
||||
[ { currentTime: -1, phase: 'before' },
|
||||
{ currentTime: 0, phase: 'active' },
|
||||
{ currentTime: 0.9, phase: 'active' },
|
||||
{ currentTime: 1, phase: 'after' } ]
|
||||
.forEach(function(test) {
|
||||
assert_phase_at_time(animation, test.phase, test.currentTime);
|
||||
});
|
||||
}, 'Phase calculation for an animation effect with a negative end delay lesser'
|
||||
+ ' in magnitude than the active duration');
|
||||
|
||||
test(function(t) {
|
||||
var animation = createDiv(t).animate(null, { duration: 1, endDelay: -1 });
|
||||
|
||||
[ { currentTime: -1, phase: 'before' },
|
||||
{ currentTime: 0, phase: 'after' },
|
||||
{ currentTime: 1, phase: 'after' } ]
|
||||
.forEach(function(test) {
|
||||
assert_phase_at_time(animation, test.phase, test.currentTime);
|
||||
});
|
||||
}, 'Phase calculation for an animation effect with a negative end delay equal'
|
||||
+ ' in magnitude to the active duration');
|
||||
|
||||
test(function(t) {
|
||||
var animation = createDiv(t).animate(null, { duration: 1, endDelay: -2 });
|
||||
|
||||
[ { currentTime: -2, phase: 'before' },
|
||||
{ currentTime: -1, phase: 'after' } ]
|
||||
.forEach(function(test) {
|
||||
assert_phase_at_time(animation, test.phase, test.currentTime);
|
||||
});
|
||||
}, 'Phase calculation for an animation effect with a negative end delay'
|
||||
+ ' greater in magnitude than the active duration');
|
||||
|
||||
test(function(t) {
|
||||
var animation = createDiv(t).animate(null, { duration: 2,
|
||||
delay: 1,
|
||||
endDelay: -1 });
|
||||
|
||||
[ { currentTime: 0, phase: 'before' },
|
||||
{ currentTime: 1, phase: 'active' },
|
||||
{ currentTime: 2, phase: 'after' } ]
|
||||
.forEach(function(test) {
|
||||
assert_phase_at_time(animation, test.phase, test.currentTime);
|
||||
});
|
||||
}, 'Phase calculation for an animation effect with a positive start delay'
|
||||
+ ' and a negative end delay lesser in magnitude than the active duration');
|
||||
|
||||
test(function(t) {
|
||||
var animation = createDiv(t).animate(null, { duration: 1,
|
||||
delay: -1,
|
||||
endDelay: -1 });
|
||||
|
||||
[ { currentTime: -2, phase: 'before' },
|
||||
{ currentTime: -1, phase: 'after' } ]
|
||||
.forEach(function(test) {
|
||||
assert_phase_at_time(animation, test.phase, test.currentTime);
|
||||
});
|
||||
}, 'Phase calculation for an animation effect with a negative start delay'
|
||||
+ ' and a negative end delay equal in magnitude to the active duration');
|
||||
|
||||
test(function(t) {
|
||||
var animation = createDiv(t).animate(null, { duration: 1,
|
||||
delay: -1,
|
||||
endDelay: -2 });
|
||||
|
||||
[ { currentTime: -3, phase: 'before' },
|
||||
{ currentTime: -2, phase: 'after' } ]
|
||||
.forEach(function(test) {
|
||||
assert_phase_at_time(animation, test.phase, test.currentTime);
|
||||
});
|
||||
}, 'Phase calculation for an animation effect with a negative start delay'
|
||||
+ ' and a negative end delay equal greater in magnitude than the active'
|
||||
+ ' duration');
|
||||
|
||||
test(function(t) {
|
||||
var animation = createDiv(t).animate(null, 1);
|
||||
animation.playbackRate = -1;
|
||||
|
||||
[ { currentTime: -1, phase: 'before' },
|
||||
{ currentTime: 0, phase: 'before' },
|
||||
{ currentTime: 1, phase: 'active' },
|
||||
{ currentTime: 2, phase: 'after' } ]
|
||||
.forEach(function(test) {
|
||||
assert_phase_at_time(animation, test.phase, test.currentTime);
|
||||
});
|
||||
}, 'Phase calculation for a simple animation effect with negative playback'
|
||||
+ ' rate');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -11,7 +11,7 @@
|
|||
<script>
|
||||
'use strict';
|
||||
|
||||
function executeTests(tests, description) {
|
||||
function runTests(tests, description) {
|
||||
tests.forEach(function(currentTest) {
|
||||
var testParams = '';
|
||||
for (var attr in currentTest.input) {
|
||||
|
@ -30,11 +30,18 @@ function executeTests(tests, description) {
|
|||
assert_equals(anim.effect.getComputedTiming().progress,
|
||||
currentTest.after);
|
||||
}
|
||||
}, description + testParams);
|
||||
}, description + ':' + testParams);
|
||||
});
|
||||
}
|
||||
|
||||
var gTests_zero_iterations = [
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// Zero iteration duration tests
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
runTests([
|
||||
{
|
||||
input: { iterations: 0,
|
||||
iterationStart: 0,
|
||||
|
@ -133,9 +140,16 @@ var gTests_zero_iterations = [
|
|||
active: 0,
|
||||
after: 0
|
||||
}
|
||||
];
|
||||
], 'Test zero iterations');
|
||||
|
||||
var gTests_integer_iterations = [
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// Tests where the iteration count is an integer
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
runTests([
|
||||
{
|
||||
input: { iterations: 3,
|
||||
iterationStart: 0,
|
||||
|
@ -231,9 +245,16 @@ var gTests_integer_iterations = [
|
|||
before: 0,
|
||||
active: 0
|
||||
}
|
||||
];
|
||||
], 'Test integer iterations');
|
||||
|
||||
var gTests_fractional_iterations = [
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// Tests where the iteration count is a fraction
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
runTests([
|
||||
{
|
||||
input: { iterations: 3.5,
|
||||
iterationStart: 0,
|
||||
|
@ -329,9 +350,16 @@ var gTests_fractional_iterations = [
|
|||
before: 0,
|
||||
active: 0
|
||||
}
|
||||
];
|
||||
], 'Test fractional iterations');
|
||||
|
||||
var gTests_infinity_iterations = [
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// Tests where the iteration count is Infinity
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
runTests([
|
||||
{
|
||||
input: { iterations: Infinity,
|
||||
iterationStart: 0,
|
||||
|
@ -424,12 +452,124 @@ var gTests_infinity_iterations = [
|
|||
before: 0,
|
||||
active: 0
|
||||
}
|
||||
];
|
||||
], 'Test infinity iterations');
|
||||
|
||||
executeTests(gTests_zero_iterations, "Test zero iterations:");
|
||||
executeTests(gTests_integer_iterations, "Test integer iterations:");
|
||||
executeTests(gTests_fractional_iterations, "Test fractional iterations:");
|
||||
executeTests(gTests_infinity_iterations, "Test infinity iterations:");
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// End delay tests
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
runTests([
|
||||
{
|
||||
input: { duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: 50 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 1
|
||||
},
|
||||
|
||||
{
|
||||
input: { duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -50 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 0.5
|
||||
},
|
||||
|
||||
{
|
||||
input: { duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -100 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 0
|
||||
},
|
||||
|
||||
{
|
||||
input: { duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -200 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 0
|
||||
},
|
||||
|
||||
{
|
||||
input: { iterationStart: 0.5,
|
||||
duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: 50 },
|
||||
before: 0.5,
|
||||
active: 0.5,
|
||||
after: 0.5
|
||||
},
|
||||
|
||||
{
|
||||
input: { iterationStart: 0.5,
|
||||
duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -50 },
|
||||
before: 0.5,
|
||||
active: 0.5,
|
||||
after: 1
|
||||
},
|
||||
|
||||
{
|
||||
input: { iterationStart: 0.5,
|
||||
duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -100 },
|
||||
before: 0.5,
|
||||
active: 0.5,
|
||||
after: 0.5
|
||||
},
|
||||
|
||||
{
|
||||
input: { iterations: 2,
|
||||
duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -100 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 1
|
||||
},
|
||||
|
||||
{
|
||||
input: { iterations: 1,
|
||||
iterationStart: 2,
|
||||
duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -50 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 0.5
|
||||
},
|
||||
|
||||
{
|
||||
input: { iterations: 1,
|
||||
iterationStart: 2,
|
||||
duration: 100,
|
||||
delay: 1,
|
||||
fill: 'both',
|
||||
endDelay: -100 },
|
||||
before: 0,
|
||||
active: 0,
|
||||
after: 0
|
||||
},
|
||||
], 'Test end delay');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,331 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Tests for updating the finished state of an animation</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#updating-the-finished-state">
|
||||
<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';
|
||||
|
||||
//
|
||||
// NOTE TO THE POOR PERSON WHO HAS TO MERGE THIS WITH THE TEST OF THE SAME
|
||||
// NAME FROM BLINK
|
||||
//
|
||||
// There is a pull request from Blink at:
|
||||
//
|
||||
// https://github.com/w3c/web-platform-tests/pull/3328
|
||||
//
|
||||
// which this file will surely conflict with.
|
||||
//
|
||||
// However, those tests cover a different part of the same algorithm. They
|
||||
// are mostly concerned with testing events and promises rather than the
|
||||
// timing part of the algorithm.
|
||||
//
|
||||
// The tests below cover the first part of the algorithm. So, please keep both
|
||||
// sets of tests and delete this comment. Preferably put the tests in this
|
||||
// file first.
|
||||
//
|
||||
// Thank you!
|
||||
//
|
||||
|
||||
|
||||
// CASE 1: playback rate > 0 and current time >= target effect end
|
||||
// (Also the start time is resolved and there is pending task)
|
||||
|
||||
// Did seek = false
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
|
||||
// Here and in the following tests we wait until ready resolves as
|
||||
// otherwise we don't have a resolved start time. We test the case
|
||||
// where the start time is unresolved in a subsequent test.
|
||||
return anim.ready.then(function() {
|
||||
// Seek to 1ms before the target end and wait a frame (> 16ms)
|
||||
anim.currentTime = 100 * MS_PER_SEC - 1;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_equals(anim.currentTime, 100 * MS_PER_SEC,
|
||||
'Hold time is set to target end clamping current time');
|
||||
});
|
||||
}, 'Updating the finished state when playing past end');
|
||||
|
||||
// Did seek = true
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
return anim.ready.then(function() {
|
||||
anim.currentTime = 200 * MS_PER_SEC;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_equals(anim.currentTime, 200 * MS_PER_SEC,
|
||||
'Hold time is set so current time should NOT change');
|
||||
});
|
||||
}, 'Updating the finished state when seeking past end');
|
||||
|
||||
// Test current time == target end
|
||||
//
|
||||
// We can't really write a test for current time == target end with
|
||||
// did seek = false since that would imply setting up an animation where
|
||||
// the next animation frame time happens to exactly align with the target end.
|
||||
//
|
||||
// Fortunately, we don't need to test that case since even if the implementation
|
||||
// fails to set the hold time on such a tick, it should be mostly unobservable
|
||||
// (on the subsequent tick the hold time will be set to the same value anyway).
|
||||
|
||||
// Did seek = true
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
return anim.ready.then(function() {
|
||||
anim.currentTime = 100 * MS_PER_SEC;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_equals(anim.currentTime, 100 * MS_PER_SEC,
|
||||
'Hold time is set so current time should NOT change');
|
||||
});
|
||||
}, 'Updating the finished state when seeking exactly to end');
|
||||
|
||||
|
||||
// CASE 2: playback rate < 0 and current time <= 0
|
||||
// (Also the start time is resolved and there is pending task)
|
||||
|
||||
// Did seek = false
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
anim.playbackRate = -1;
|
||||
anim.play(); // Make sure animation is not initially finished
|
||||
return anim.ready.then(function() {
|
||||
// Seek to 1ms before 0 end and wait a frame (> 16ms)
|
||||
anim.currentTime = 1;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_equals(anim.currentTime, 0 * MS_PER_SEC,
|
||||
'Hold time is set to zero clamping current time');
|
||||
});
|
||||
}, 'Updating the finished state when playing in reverse past zero');
|
||||
|
||||
// Did seek = true
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
anim.playbackRate = -1;
|
||||
anim.play();
|
||||
return anim.ready.then(function() {
|
||||
anim.currentTime = -100 * MS_PER_SEC;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_equals(anim.currentTime, -100 * MS_PER_SEC,
|
||||
'Hold time is set so current time should NOT change');
|
||||
});
|
||||
}, 'Updating the finished state when seeking a reversed animation past zero');
|
||||
|
||||
// As before, it's difficult to test current time == 0 for did seek = false but
|
||||
// it doesn't really matter.
|
||||
|
||||
// Did seek = true
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
anim.playbackRate = -1;
|
||||
anim.play();
|
||||
return anim.ready.then(function() {
|
||||
anim.currentTime = 0;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_equals(anim.currentTime, 0 * MS_PER_SEC,
|
||||
'Hold time is set so current time should NOT change');
|
||||
});
|
||||
}, 'Updating the finished state when seeking a reversed animation exactly'
|
||||
+ ' to zero');
|
||||
|
||||
// CASE 3: playback rate > 0 and current time < target end OR
|
||||
// playback rate < 0 and current time > 0
|
||||
// (Also the start time is resolved and there is pending task)
|
||||
|
||||
// Did seek = false; playback rate > 0
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
|
||||
// We want to test that the hold time is cleared so first we need to
|
||||
// put the animation in a state where the hold time is set.
|
||||
anim.finish();
|
||||
return anim.ready.then(function() {
|
||||
assert_equals(anim.currentTime, 100 * MS_PER_SEC,
|
||||
'Hold time is initially set');
|
||||
// Then extend the duration so that the hold time is cleared and on
|
||||
// the next tick the current time will increase.
|
||||
anim.effect.timing.duration *= 2;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_greater_than(anim.currentTime, 100 * MS_PER_SEC,
|
||||
'Hold time is not set so current time should increase');
|
||||
});
|
||||
}, 'Updating the finished state when playing before end');
|
||||
|
||||
// Did seek = true; playback rate > 0
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
anim.finish();
|
||||
return anim.ready.then(function() {
|
||||
anim.currentTime = 50 * MS_PER_SEC;
|
||||
// When did seek = true, updating the finished state: (i) updates
|
||||
// the animation's start time and (ii) clears the hold time.
|
||||
// We can test both by checking that the currentTime is initially
|
||||
// updated and then increases.
|
||||
assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated');
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_greater_than(anim.currentTime, 50 * MS_PER_SEC,
|
||||
'Hold time is not set so current time should increase');
|
||||
});
|
||||
}, 'Updating the finished state when seeking before end');
|
||||
|
||||
// Did seek = false; playback rate < 0
|
||||
//
|
||||
// Unfortunately it is not possible to test this case. We need to have
|
||||
// a hold time set, a resolved start time, and then perform some
|
||||
// operation that updates the finished state with did seek set to true.
|
||||
//
|
||||
// However, the only situation where this could arrive is when we
|
||||
// replace the timeline and that procedure is likely to change. For all
|
||||
// other cases we either have an unresolved start time (e.g. when
|
||||
// paused), we don't have a set hold time (e.g. regular playback), or
|
||||
// the current time is zero (and anything that gets us out of that state
|
||||
// will set did seek = true).
|
||||
|
||||
// Did seek = true; playback rate < 0
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
anim.playbackRate = -1;
|
||||
return anim.ready.then(function() {
|
||||
anim.currentTime = 50 * MS_PER_SEC;
|
||||
assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated');
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_less_than(anim.currentTime, 50 * MS_PER_SEC,
|
||||
'Hold time is not set so current time should decrease');
|
||||
});
|
||||
}, 'Updating the finished state when seeking a reversed animation before end');
|
||||
|
||||
// CASE 4: playback rate == 0
|
||||
|
||||
// current time < 0
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
anim.playbackRate = 0;
|
||||
return anim.ready.then(function() {
|
||||
anim.currentTime = -100 * MS_PER_SEC;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_equals(anim.currentTime, -100 * MS_PER_SEC,
|
||||
'Hold time should not be cleared so current time should'
|
||||
+ ' NOT change');
|
||||
});
|
||||
}, 'Updating the finished state when playback rate is zero and the'
|
||||
+ ' current time is less than zero');
|
||||
|
||||
// current time < target end
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
anim.playbackRate = 0;
|
||||
return anim.ready.then(function() {
|
||||
anim.currentTime = 50 * MS_PER_SEC;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_equals(anim.currentTime, 50 * MS_PER_SEC,
|
||||
'Hold time should not be cleared so current time should'
|
||||
+ ' NOT change');
|
||||
});
|
||||
}, 'Updating the finished state when playback rate is zero and the'
|
||||
+ ' current time is less than end');
|
||||
|
||||
// current time > target end
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
anim.playbackRate = 0;
|
||||
return anim.ready.then(function() {
|
||||
anim.currentTime = 200 * MS_PER_SEC;
|
||||
return waitForAnimationFrames(1);
|
||||
}).then(function() {
|
||||
assert_equals(anim.currentTime, 200 * MS_PER_SEC,
|
||||
'Hold time should not be cleared so current time should'
|
||||
+ ' NOT change');
|
||||
});
|
||||
}, 'Updating the finished state when playback rate is zero and the'
|
||||
+ ' current time is greater than end');
|
||||
|
||||
// CASE 5: current time unresolved
|
||||
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
anim.cancel();
|
||||
// Trigger a change that will cause the "update the finished state"
|
||||
// procedure to run.
|
||||
anim.effect.timing.duration = 200 * MS_PER_SEC;
|
||||
assert_equals(anim.currentTime, null,
|
||||
'The animation hold time / start time should not be updated');
|
||||
// The "update the finished state" procedure is supposed to run after any
|
||||
// change to timing, but just in case an implementation defers that, let's
|
||||
// wait a frame and check that the hold time / start time has still not been
|
||||
// updated.
|
||||
return waitForAnimationFrames(1).then(function() {
|
||||
assert_equals(anim.currentTime, null,
|
||||
'The animation hold time / start time should not be updated');
|
||||
});
|
||||
}, 'Updating the finished state when current time is unresolved');
|
||||
|
||||
// CASE 6: has a pending task
|
||||
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
anim.cancel();
|
||||
anim.currentTime = 75 * MS_PER_SEC;
|
||||
anim.play();
|
||||
// We now have a pending task and a resolved current time.
|
||||
//
|
||||
// In the next step we will adjust the timing so that the current time
|
||||
// is greater than the target end. At this point the "update the finished
|
||||
// state" procedure should run and if we fail to check for a pending task
|
||||
// we will set the hold time to the target end, i.e. 50ms.
|
||||
anim.effect.timing.duration = 50 * MS_PER_SEC;
|
||||
assert_equals(anim.currentTime, 75 * MS_PER_SEC,
|
||||
'Hold time should not be updated');
|
||||
}, 'Updating the finished state when there is a pending task');
|
||||
|
||||
// CASE 7: start time unresolved
|
||||
|
||||
// Did seek = false
|
||||
promise_test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
anim.cancel();
|
||||
// Make it so that only the start time is unresolved (to avoid overlapping
|
||||
// with the test case where current time is unresolved)
|
||||
anim.currentTime = 150 * MS_PER_SEC;
|
||||
// Trigger a change that will cause the "update the finished state"
|
||||
// procedure to run (did seek = false).
|
||||
anim.effect.timing.duration = 200 * MS_PER_SEC;
|
||||
return waitForAnimationFrames(1).then(function() {
|
||||
assert_equals(anim.currentTime, 150 * MS_PER_SEC,
|
||||
'The animation hold time should not be updated');
|
||||
assert_equals(anim.startTime, null,
|
||||
'The animation start time should not be updated');
|
||||
});
|
||||
}, 'Updating the finished state when start time is unresolved and'
|
||||
+ ' did seek = false');
|
||||
|
||||
// Did seek = true
|
||||
test(function(t) {
|
||||
var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
|
||||
anim.cancel();
|
||||
anim.currentTime = 150 * MS_PER_SEC;
|
||||
// Trigger a change that will cause the "update the finished state"
|
||||
// procedure to run.
|
||||
anim.currentTime = 50 * MS_PER_SEC;
|
||||
assert_equals(anim.currentTime, 50 * MS_PER_SEC,
|
||||
'The animation hold time should not be updated');
|
||||
assert_equals(anim.startTime, null,
|
||||
'The animation start time should not be updated');
|
||||
}, 'Updating the finished state when start time is unresolved and'
|
||||
+ ' did seek = true');
|
||||
|
||||
</script>
|
||||
</body>
|
Loading…
Add table
Add a link
Reference in a new issue