diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /testing/web-platform/tests/web-animations/animation-model | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'testing/web-platform/tests/web-animations/animation-model')
6 files changed, 2093 insertions, 0 deletions
diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/discrete-animation.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/discrete-animation.html new file mode 100644 index 000000000..e43f26d16 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/discrete-animation.html @@ -0,0 +1,135 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Tests for discrete animation</title> +<link rel="help" href="http://w3c.github.io/web-animations/#animatable-as-string-section"> +<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 div = createDiv(t); + + var anim = div.animate({ fontStyle: [ 'normal', 'italic' ] }, + { duration: 1000, fill: 'forwards' }); + + assert_equals(getComputedStyle(div).fontStyle, 'normal', + 'Animation produces \'from\' value at start of interval'); + anim.currentTime = anim.effect.getComputedTiming().duration / 2 - 1; + assert_equals(getComputedStyle(div).fontStyle, 'normal', + 'Animation produces \'from\' value just before the middle of' + + ' the interval'); + anim.currentTime++; + assert_equals(getComputedStyle(div).fontStyle, 'italic', + 'Animation produces \'to\' value at exact middle of' + + ' the interval'); + anim.finish(); + assert_equals(getComputedStyle(div).fontStyle, 'italic', + 'Animation produces \'to\' value during forwards fill'); +}, 'Test animating discrete values'); + +test(function(t) { + var div = createDiv(t); + var originalHeight = getComputedStyle(div).height; + + var anim = div.animate({ height: [ 'auto', '200px' ] }, + { duration: 1000, fill: 'forwards' }); + + assert_equals(getComputedStyle(div).height, originalHeight, + 'Animation produces \'from\' value at start of interval'); + anim.currentTime = anim.effect.getComputedTiming().duration / 2 - 1; + assert_equals(getComputedStyle(div).height, originalHeight, + 'Animation produces \'from\' value just before the middle of' + + ' the interval'); + anim.currentTime++; + assert_equals(getComputedStyle(div).height, '200px', + 'Animation produces \'to\' value at exact middle of' + + ' the interval'); + anim.finish(); + assert_equals(getComputedStyle(div).height, '200px', + 'Animation produces \'to\' value during forwards fill'); +}, 'Test discrete animation is used when interpolation fails'); + +test(function(t) { + var div = createDiv(t); + var originalHeight = getComputedStyle(div).height; + + var anim = div.animate({ height: [ 'auto', + '200px', + '300px', + 'auto', + '400px' ] }, + { duration: 1000, fill: 'forwards' }); + + // There are five values, so there are four pairs to try to interpolate. + // We test at the middle of each pair. + assert_equals(getComputedStyle(div).height, originalHeight, + 'Animation produces \'from\' value at start of interval'); + anim.currentTime = 125; + assert_equals(getComputedStyle(div).height, '200px', + 'First non-interpolable pair uses discrete interpolation'); + anim.currentTime += 250; + assert_equals(getComputedStyle(div).height, '250px', + 'Second interpolable pair uses linear interpolation'); + anim.currentTime += 250; + assert_equals(getComputedStyle(div).height, originalHeight, + 'Third non-interpolable pair uses discrete interpolation'); + anim.currentTime += 250; + assert_equals(getComputedStyle(div).height, '400px', + 'Fourth non-interpolable pair uses discrete interpolation'); +}, 'Test discrete animation is used only for pairs of values that cannot' + + ' be interpolated'); + +test(function(t) { + var div = createDiv(t); + var originalHeight = getComputedStyle(div).height; + + // 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 anim = div.animate({ fontStyle: [ 'italic', 'oblique' ] }, + { duration: 1000, fill: 'forwards', + easing: 'cubic-bezier(0.68,0,1,0.01)' }); + + assert_equals(getComputedStyle(div).fontStyle, 'italic', + 'Animation produces \'from\' value at start of interval'); + anim.currentTime = 940; + assert_equals(getComputedStyle(div).fontStyle, 'italic', + 'Animation produces \'from\' value at 94% of the iteration' + + ' time'); + anim.currentTime = 960; + assert_equals(getComputedStyle(div).fontStyle, 'oblique', + 'Animation produces \'to\' value at 96% of the iteration' + + ' time'); +}, 'Test the 50% switch point for discrete animation is based on the' + + ' effect easing'); + +test(function(t) { + var div = createDiv(t); + var originalHeight = getComputedStyle(div).height; + + // 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 anim = div.animate([ { fontStyle: 'italic', + easing: 'cubic-bezier(0.68,0,1,0.01)' }, + { fontStyle: 'oblique' } ], + { duration: 1000, fill: 'forwards' }); + + assert_equals(getComputedStyle(div).fontStyle, 'italic', + 'Animation produces \'from\' value at start of interval'); + anim.currentTime = 940; + assert_equals(getComputedStyle(div).fontStyle, 'italic', + 'Animation produces \'from\' value at 94% of the iteration' + + ' time'); + anim.currentTime = 960; + assert_equals(getComputedStyle(div).fontStyle, 'oblique', + 'Animation produces \'to\' value at 96% of the iteration' + + ' time'); +}, 'Test the 50% switch point for discrete animation is based on the' + + ' keyframe easing'); + +</script> diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/spacing-keyframes-shapes.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/spacing-keyframes-shapes.html new file mode 100644 index 000000000..9f7cfaea1 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/spacing-keyframes-shapes.html @@ -0,0 +1,152 @@ +<!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> diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/type-per-property.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/type-per-property.html new file mode 100644 index 000000000..9e41b753e --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/type-per-property.html @@ -0,0 +1,1198 @@ +<!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") + ] + }, + "backface-visibility": { + // https://drafts.csswg.org/css-transforms/#propdef-backface-visibility + "tests": [ + discrete("visible", "hidden") + ] + }, + "background-attachment": { + // https://drafts.csswg.org/css-backgrounds-3/#background-attachment + "tests": [ + discrete("fixed", "local") + ] + }, + "background-blend-mode": { + // https://drafts.fxtf.org/compositing-1/#propdef-background-blend-mode + "tests": [ + discrete("multiply", "screen") + ] + }, + "background-clip": { + // https://drafts.csswg.org/css-backgrounds-3/#background-clip + "tests": [ + discrete("padding-box", "content-box") + ] + }, + "background-image": { + // https://drafts.csswg.org/css-backgrounds-3/#background-image + "tests": [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "background-origin": { + // https://drafts.csswg.org/css-backgrounds-3/#background-origin + "tests": [ + discrete("padding-box", "content-box") + ] + }, + "background-repeat": { + // https://drafts.csswg.org/css-backgrounds-3/#background-repeat + "tests": [ + discrete("space", "round") + ] + }, + "border-bottom-style": { + // https://drafts.csswg.org/css-backgrounds-3/#border-bottom-style + "tests": [ + discrete("dotted", "solid") + ] + }, + "border-collapse": { + // https://drafts.csswg.org/css-tables/#propdef-border-collapse + "tests": [ + discrete("collapse", "separate") + ] + }, + "border-image-outset": { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-outset + "tests": [ + discrete("1 1 1 1", "5 5 5 5") + ] + }, + "border-image-repeat": { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-repeat + "tests": [ + discrete("stretch stretch", "repeat repeat") + ] + }, + "border-image-slice": { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-slice + "tests": [ + discrete("1 1 1 1", "5 5 5 5") + ] + }, + "border-image-source": { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-source + "tests": [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "border-image-width": { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-width + "tests": [ + discrete("1 1 1 1", "5 5 5 5") + ] + }, + "border-left-style": { + // https://drafts.csswg.org/css-backgrounds-3/#border-left-style + "tests": [ + discrete("dotted", "solid") + ] + }, + "border-right-style": { + // https://drafts.csswg.org/css-backgrounds-3/#border-right-style + "tests": [ + discrete("dotted", "solid") + ] + }, + "border-top-style": { + // https://drafts.csswg.org/css-backgrounds-3/#border-top-style + "tests": [ + discrete("dotted", "solid") + ] + }, + "box-decoration-break": { + // https://drafts.csswg.org/css-break/#propdef-box-decoration-break + "tests": [ + discrete("slice", "clone") + ] + }, + "box-sizing": { + // https://drafts.csswg.org/css-ui-4/#box-sizing + "tests": [ + discrete("content-box", "border-box") + ] + }, + "caption-side": { + // https://drafts.csswg.org/css-tables/#propdef-caption-side + "tests": [ + discrete("top", "bottom") + ] + }, + "clear": { + // https://drafts.csswg.org/css-page-floats/#propdef-clear + "tests": [ + discrete("left", "right") + ] + }, + "clip-rule": { + // https://drafts.fxtf.org/css-masking-1/#propdef-clip-rule + tests: [ + discrete("evenodd", "nonzero") + ] + }, + "color-adjust": { + // https://drafts.csswg.org/css-color-4/#color-adjust + tests: [ + discrete("economy", "exact") + ] + }, + "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") + ] + }, + "column-fill": { + // https://drafts.csswg.org/css-multicol/#propdef-column-fill + tests: [ + discrete("auto", "balance") + ] + }, + "column-rule-style": { + // https://drafts.csswg.org/css-multicol/#propdef-column-rule-style + tests: [ + discrete("none", "dotted") + ] + }, + "contain": { + // https://drafts.csswg.org/css-containment/#propdef-contain + tests: [ + discrete("strict", "none") + ] + }, + "content": { + // https://drafts.csswg.org/css-content-3/#propdef-content + tests: [ + discrete("\"a\"", "\"b\"") + ], + tagName: "::before" + }, + "counter-increment": { + // https://drafts.csswg.org/css-lists-3/#propdef-counter-increment + tests: [ + discrete("ident-1 1", "ident-2 2") + ] + }, + "counter-reset": { + // https://drafts.csswg.org/css-lists-3/#propdef-counter-reset + tests: [ + discrete("ident-1 1", "ident-2 2") + ] + }, + "cursor": { + // https://drafts.csswg.org/css2/ui.html#propdef-cursor + tests: [ + discrete("pointer", "wait") + ] + }, + "direction": { + // https://drafts.csswg.org/css-writing-modes-3/#propdef-direction + tests: [ + discrete("ltr", "rtl") + ] + }, + "dominant-baseline": { + // https://drafts.csswg.org/css-inline/#propdef-dominant-baseline + tests: [ + discrete("ideographic", "alphabetic") + ] + }, + "empty-cells": { + // https://drafts.csswg.org/css-tables/#propdef-empty-cells + tests: [ + discrete("show", "hide") + ] + }, + "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") + ] + }, + "float": { + // https://drafts.csswg.org/css-page-floats/#propdef-float + tests: [ + discrete("left", "right") + ] + }, + "font-family": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-family + tests: [ + discrete("helvetica", "verdana") + ] + }, + "font-feature-settings": { + // https://drafts.csswg.org/css-fonts/#descdef-font-feature-settings + tests: [ + discrete("\"liga\" 5", "normal") + ] + }, + "font-kerning": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-kerning + tests: [ + discrete("auto", "normal") + ] + }, + "font-language-override": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override + tests: [ + discrete("\"eng\"", "normal") + ] + }, + "font-style": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-style + tests: [ + discrete("italic", "oblique") + ] + }, + "font-synthesis": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-synthesis + tests: [ + discrete("none", "weight style") + ] + }, + "font-variant-alternates": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-alternates + tests: [ + discrete("swash(unknown)", "stylistic(unknown)") + ] + }, + "font-variant-caps": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-caps + tests: [ + discrete("small-caps", "unicase") + ] + }, + "font-variant-east-asian": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-east-asian + tests: [ + discrete("full-width", "proportional-width") + ] + }, + "font-variant-ligatures": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-ligatures + tests: [ + discrete("common-ligatures", "no-common-ligatures") + ] + }, + "font-variant-numeric": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-numeric + tests: [ + discrete("lining-nums", "oldstyle-nums") + ] + }, + "font-variant-position": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-position + tests: [ + discrete("sub", "super") + ] + }, + "grid-auto-columns": { + // https://drafts.csswg.org/css-grid/#propdef-grid-auto-columns + tests: [ + discrete("1px", "5px") + ] + }, + "grid-auto-flow": { + // https://drafts.csswg.org/css-grid/#propdef-grid-auto-flow + tests: [ + discrete("row", "column") + ] + }, + "grid-auto-rows": { + // https://drafts.csswg.org/css-grid/#propdef-grid-auto-rows + tests: [ + discrete("1px", "5px") + ] + }, + "grid-column-end": { + // https://drafts.csswg.org/css-grid/#propdef-grid-column-end + tests: [ + discrete("1", "5") + ] + }, + "grid-column-start": { + // https://drafts.csswg.org/css-grid/#propdef-grid-column-start + tests: [ + discrete("1", "5") + ] + }, + "grid-row-end": { + // https://drafts.csswg.org/css-grid/#propdef-grid-row-end + tests: [ + discrete("1", "5") + ] + }, + "grid-row-start": { + // https://drafts.csswg.org/css-grid/#propdef-grid-row-start + tests: [ + discrete("1", "5") + ] + }, + "grid-template-areas": { + // https://drafts.csswg.org/css-template/#grid-template-areas + tests: [ + discrete("\". . a b\" \". .a b\"", "none") + ] + }, + "grid-template-columns": { + // https://drafts.csswg.org/css-template/#grid-template-columns + tests: [ + discrete("1px", "5px") + ] + }, + "grid-template-rows": { + // https://drafts.csswg.org/css-template/#grid-template-rows + tests: [ + discrete("1px", "5px") + ] + }, + "hyphens": { + // https://drafts.csswg.org/css-text-3/#propdef-hyphens + tests: [ + discrete("manual", "auto") + ] + }, + "image-orientation": { + // https://drafts.csswg.org/css-images-3/#propdef-image-orientation + tests: [ + discrete("0deg", "90deg") + ] + }, + "ime-mode": { + // https://drafts.csswg.org/css-ui/#input-method-editor + tests: [ + discrete("disabled", "auto") + ] + }, + "initial-letter": { + // https://drafts.csswg.org/css-inline/#propdef-initial-letter + tests: [ + discrete("1 2", "3 4") + ] + }, + "isolation": { + // https://drafts.fxtf.org/compositing-1/#propdef-isolation + tests: [ + discrete("auto", "isolate") + ] + }, + "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") + ] + }, + "list-style-image": { + // https://drafts.csswg.org/css-lists-3/#propdef-list-style-image + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "list-style-position": { + // https://drafts.csswg.org/css-lists-3/#propdef-list-style-position + tests: [ + discrete("inside", "outside") + ] + }, + "list-style-type": { + // https://drafts.csswg.org/css-lists-3/#propdef-list-style-type + tests: [ + discrete("circle", "square") + ] + }, + "marker-end": { + // https://svgwg.org/specs/markers/#MarkerEndProperty + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "marker-mid": { + // https://svgwg.org/specs/markers/#MarkerMidProperty + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "marker-start": { + // https://svgwg.org/specs/markers/#MarkerStartProperty + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "mask": { + // https://drafts.fxtf.org/css-masking-1/#the-mask + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "mask-clip": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-clip + tests: [ + discrete("content-box", "border-box") + ] + }, + "mask-composite": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-composite + tests: [ + discrete("add", "subtract") + ] + }, + "mask-image": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-image + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "mask-mode": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-mode + tests: [ + discrete("alpha", "luminance") + ] + }, + "mask-origin": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-origin + tests: [ + discrete("content-box", "border-box") + ] + }, + "mask-repeat": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-repeat + tests: [ + discrete("space", "round") + ] + }, + "mask-type": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-type + tests: [ + discrete("alpha", "luminance") + ] + }, + "mix-blend-mode": { + // https://drafts.fxtf.org/compositing-1/#propdef-mix-blend-mode + tests: [ + discrete("multiply", "screen") + ] + }, + "object-fit": { + // https://drafts.csswg.org/css-images-3/#propdef-object-fit + tests: [ + discrete("fill", "contain") + ] + }, + "order": { + // https://drafts.csswg.org/css-flexbox/#propdef-order + tests: [ + integer() + ] + }, + "outline-style": { + // https://drafts.csswg.org/css-ui/#propdef-outline-style + tests: [ + discrete("none", "dotted") + ] + }, + "overflow-clip-box": { + // https://developer.mozilla.org/en/docs/Web/CSS/overflow-clip-box + tests: [ + discrete("padding-box", "content-box") + ] + }, + "overflow-wrap": { + // https://drafts.csswg.org/css-text-3/#propdef-overflow-wrap + tests: [ + discrete("normal", "break-word") + ] + }, + "overflow-x": { + // https://drafts.csswg.org/css-overflow-3/#propdef-overflow-x + tests: [ + discrete("visible", "hidden") + ] + }, + "overflow-y": { + // https://drafts.csswg.org/css-overflow-3/#propdef-overflow-y + tests: [ + discrete("visible", "hidden") + ] + }, + "page-break-after": { + // https://drafts.csswg.org/css-break-3/#propdef-break-after + tests: [ + discrete("always", "auto") + ] + }, + "page-break-before": { + // https://drafts.csswg.org/css-break-3/#propdef-break-before + tests: [ + discrete("always", "auto") + ] + }, + "page-break-inside": { + // https://drafts.csswg.org/css-break-3/#propdef-break-inside + tests: [ + discrete("auto", "avoid") + ] + }, + "paint-order": { + // https://svgwg.org/svg2-draft/painting.html#PaintOrderProperty + tests: [ + discrete("fill", "stroke") + ] + }, + "pointer-events": { + // https://svgwg.org/svg2-draft/interact.html#PointerEventsProperty + tests: [ + discrete("fill", "none") + ] + }, + "position": { + // https://drafts.csswg.org/css-position/#propdef-position + tests: [ + discrete("absolute", "fixed") + ] + }, + "quotes": { + // https://drafts.csswg.org/css-content-3/#propdef-quotes + tests: [ + discrete("\"“\" \"”\" \"‘\" \"’\"", "\"‘\" \"’\" \"“\" \"”\"") + ] + }, + "resize": { + // https://drafts.csswg.org/css-ui/#propdef-resize + tests: [ + discrete("both", "horizontal") + ] + }, + "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" + }, + "scroll-behavior": { + // https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior + tests: [ + discrete("auto", "smooth") + ] + }, + "scroll-snap-type-x": { + // https://developer.mozilla.org/en/docs/Web/CSS/scroll-snap-type-x + tests: [ + discrete("mandatory", "proximity") + ] + }, + "scroll-snap-type-y": { + // https://developer.mozilla.org/en/docs/Web/CSS/scroll-snap-type-y + tests: [ + discrete("mandatory", "proximity") + ] + }, + "shape-outside": { + // http://dev.w3.org/csswg/css-shapes/#propdef-shape-outside + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "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" + }, + "table-layout": { + // https://drafts.csswg.org/css-tables/#propdef-table-layout + tests: [ + discrete("auto", "fixed") + ] + }, + "text-align": { + // https://drafts.csswg.org/css-text-3/#propdef-text-align + tests: [ + discrete("start", "end") + ] + }, + "text-align-last": { + // https://drafts.csswg.org/css-text-3/#propdef-text-align-last + tests: [ + discrete("start", "end") + ] + }, + "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", "none") + ] + }, + "text-decoration-line": { + // https://drafts.csswg.org/css-text-decor-3/#propdef-text-decoration-line + tests: [ + discrete("underline", "overline") + ] + }, + "text-decoration-style": { + // http://dev.w3.org/csswg/css-text-decor-3/#propdef-text-decoration-style + tests: [ + discrete("solid", "dotted") + ] + }, + "text-emphasis-position": { + // http://dev.w3.org/csswg/css-text-decor-3/#propdef-text-emphasis-position + tests: [ + discrete("over right", "under left") + ] + }, + "text-emphasis-style": { + // http://dev.w3.org/csswg/css-text-decor-3/#propdef-text-emphasis-style + tests: [ + discrete("filled circle", "open dot") + ] + }, + "text-orientation": { + // https://drafts.csswg.org/css-writing-modes-3/#propdef-text-orientation + tests: [ + discrete("upright", "sideways") + ] + }, + "text-overflow": { + // https://drafts.csswg.org/css-ui/#propdef-text-overflow + tests: [ + discrete("clip", "ellipsis") + ] + }, + "text-rendering": { + // https://svgwg.org/svg2-draft/painting.html#TextRenderingProperty + tests: [ + discrete("optimizeSpeed", "optimizeLegibility") + ] + }, + "text-transform": { + // https://drafts.csswg.org/css-text-3/#propdef-text-transform + tests: [ + discrete("capitalize", "uppercase") + ] + }, + "touch-action": { + // https://w3c.github.io/pointerevents/#the-touch-action-css-property + tests: [ + discrete("auto", "none") + ] + }, + "transform-box": { + // https://drafts.csswg.org/css-transforms/#propdef-transform-box + tests: [ + discrete("fill-box", "border-box") + ] + }, + "transform-style": { + // https://drafts.csswg.org/css-transforms/#propdef-transform-style + tests: [ + discrete("flat", "preserve-3d") + ] + }, + "unicode-bidi": { + // https://drafts.csswg.org/css-writing-modes-3/#propdef-unicode-bidi + tests: [ + discrete("embed", "bidi-override") + ] + }, + "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() + ] + }, + "white-space": { + // https://drafts.csswg.org/css-text-4/#propdef-white-space + tests: [ + discrete("pre", "nowrap") + ] + }, + "word-break": { + // https://drafts.csswg.org/css-text-3/#propdef-word-break + tests: [ + discrete("keep-all", "break-all") + ] + }, + "will-change": { + // http://dev.w3.org/csswg/css-will-change/#propdef-will-change + tests: [ + discrete("scroll-position", "contents") + ] + }, + "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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 = createTestElement(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 type = animation.effect.target.type; + var target = type + ? animation.effect.target.parentElement + : animation.effect.target; + testSamples.forEach(function(testSample) { + animation.currentTime = testSample.time; + assert_equals(getComputedStyle(target, type)[idlName], + testSample.expected, + "The value should be " + testSample.expected + + " at " + testSample.time + "ms"); + }); +} + +function createTestElement(t, tagName) { + return tagName && tagName.startsWith("::") + ? createPseudo(t, tagName.substring(2)) + : createElement(t, tagName); +} + +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> diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-context.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-context.html new file mode 100644 index 000000000..07fb6097c --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-context.html @@ -0,0 +1,103 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Tests that property values respond to changes to their context</title> +<link rel="help" href="https://w3c.github.io/web-animations/#keyframes-section"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> + +test(function(t) { + var div = createDiv(t); + div.style.fontSize = '10px'; + var animation = div.animate([ { marginLeft: '10em' }, + { marginLeft: '20em' } ], 1000); + animation.currentTime = 500; + assert_equals(getComputedStyle(div).marginLeft, '150px', + 'Effect value before updating font-size'); + div.style.fontSize = '20px'; + assert_equals(getComputedStyle(div).marginLeft, '300px', + 'Effect value after updating font-size'); +}, 'Effect values reflect changes to font-size on element'); + +test(function(t) { + var parentDiv = createDiv(t); + var div = createDiv(t); + parentDiv.appendChild(div); + parentDiv.style.fontSize = '10px'; + + var animation = div.animate([ { marginLeft: '10em' }, + { marginLeft: '20em' } ], 1000); + animation.currentTime = 500; + assert_equals(getComputedStyle(div).marginLeft, '150px', + 'Effect value before updating font-size on parent element'); + parentDiv.style.fontSize = '20px'; + assert_equals(getComputedStyle(div).marginLeft, '300px', + 'Effect value after updating font-size on parent element'); +}, 'Effect values reflect changes to font-size on parent element'); + +promise_test(function(t) { + var parentDiv = createDiv(t); + var div = createDiv(t); + parentDiv.appendChild(div); + parentDiv.style.fontSize = '10px'; + var animation = div.animate([ { marginLeft: '10em' }, + { marginLeft: '20em' } ], 1000); + + animation.pause(); + animation.currentTime = 500; + parentDiv.style.fontSize = '20px'; + + return animation.ready.then(function() { + assert_equals(getComputedStyle(div).marginLeft, '300px', + 'Effect value after updating font-size on parent element'); + }); +}, 'Effect values reflect changes to font-size when computed style is not' + + ' immediately flushed'); + +promise_test(function(t) { + var divWith10pxFontSize = createDiv(t); + divWith10pxFontSize.style.fontSize = '10px'; + var divWith20pxFontSize = createDiv(t); + divWith20pxFontSize.style.fontSize = '20px'; + + var div = createDiv(t); + div.remove(); // Detach + var animation = div.animate([ { marginLeft: '10em' }, + { marginLeft: '20em' } ], 1000); + animation.pause(); + + return animation.ready.then(function() { + animation.currentTime = 500; + + divWith10pxFontSize.appendChild(div); + assert_equals(getComputedStyle(div).marginLeft, '150px', + 'Effect value after attaching to font-size:10px parent'); + divWith20pxFontSize.appendChild(div); + assert_equals(getComputedStyle(div).marginLeft, '300px', + 'Effect value after attaching to font-size:20px parent'); + }); +}, '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> diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/spacing-keyframes.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/spacing-keyframes.html new file mode 100644 index 000000000..90e26d276 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/spacing-keyframes.html @@ -0,0 +1,391 @@ +<!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> diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/the-effect-value-of-a-keyframe-effect.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/the-effect-value-of-a-keyframe-effect.html new file mode 100644 index 000000000..eb67f669a --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/the-effect-value-of-a-keyframe-effect.html @@ -0,0 +1,114 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Keyframe handling tests</title> +<link rel="help" href="https://w3c.github.io/web-animations/#the-effect-value-of-a-keyframe-animation-effect"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<div id="target"></div> +<script> +'use strict'; + +test(function(t) { + var div = createDiv(t); + var anim = div.animate([ { offset: 0, opacity: 0 }, + { offset: 0, opacity: 0.1 }, + { offset: 0, opacity: 0.2 }, + { offset: 1, opacity: 0.8 }, + { offset: 1, opacity: 0.9 }, + { offset: 1, opacity: 1 } ], + { duration: 1000, + easing: 'cubic-bezier(0.5, -0.5, 0.5, 1.5)' }); + assert_equals(getComputedStyle(div).opacity, '0.2', + 'When progress is zero the last keyframe with offset 0 should' + + ' be used'); + // http://cubic-bezier.com/#.5,-0.5,.5,1.5 + // At t=0.15, the progress should be negative + anim.currentTime = 150; + assert_equals(getComputedStyle(div).opacity, '0', + 'When progress is negative, the first keyframe with a 0 offset' + + ' should be used'); + // At t=0.71, the progress should be just less than 1 + anim.currentTime = 710; + assert_approx_equals(parseFloat(getComputedStyle(div).opacity), 0.8, 0.01, + 'When progress is just less than 1, the first keyframe with an' + + ' offset of 1 should be used as the interval endpoint'); + // At t=0.85, the progress should be > 1 + anim.currentTime = 850; + assert_equals(getComputedStyle(div).opacity, '1', + 'When progress is greater than 1.0, the last keyframe with a 1' + + ' offset should be used'); + anim.finish(); + assert_equals(getComputedStyle(div).opacity, '1', + 'When progress is equal to 1.0, the last keyframe with a 1' + + ' offset should be used'); +}, 'Overlapping keyframes at 0 and 1 use the appropriate value when the' + + ' progress is outside the range [0, 1]'); + +test(function(t) { + var div = createDiv(t); + var anim = div.animate([ { offset: 0, opacity: 0 }, + { offset: 0.5, opacity: 0.3 }, + { offset: 0.5, opacity: 0.5 }, + { offset: 0.5, opacity: 0.7 }, + { offset: 1, opacity: 1 } ], 1000); + anim.currentTime = 250; + assert_equals(getComputedStyle(div).opacity, '0.15', + 'Before the overlap point, the first keyframe from the' + + ' overlap point should be used as interval endpoint'); + anim.currentTime = 500; + assert_equals(getComputedStyle(div).opacity, '0.7', + 'At the overlap point, the last keyframe from the' + + ' overlap point should be used as interval startpoint'); + anim.currentTime = 750; + assert_equals(getComputedStyle(div).opacity, '0.85', + 'After the overlap point, the last keyframe from the' + + ' overlap point should be used as interval startpoint'); +}, 'Overlapping keyframes between 0 and 1 use the appropriate value on each' + + ' side of the overlap point'); + +test(function(t) { + var div = createDiv(t); + var anim = div.animate({ visibility: ['hidden','visible'] }, + { duration: 100 * MS_PER_SEC, fill: 'both' }); + + anim.currentTime = 0; + assert_equals(getComputedStyle(div).visibility, 'hidden', + 'Visibility when progress = 0.'); + + anim.currentTime = 10 * MS_PER_SEC + 1; + assert_equals(getComputedStyle(div).visibility, 'visible', + 'Visibility when progress > 0 due to linear easing.'); + + anim.finish(); + assert_equals(getComputedStyle(div).visibility, 'visible', + 'Visibility when progress = 1.'); + +}, "Test visibility clamping behavior."); + +test(function(t) { + var div = createDiv(t); + var anim = div.animate({ visibility: ['hidden', 'visible'] }, + { duration: 100 * MS_PER_SEC, fill: 'both', + easing: 'cubic-bezier(0.25, -0.6, 0, 0.5)' }); + + anim.currentTime = 0; + assert_equals(getComputedStyle(div).visibility, 'hidden', + 'Visibility when progress = 0.'); + + // Timing function is below zero. So we expected visibility is hidden. + anim.currentTime = 10 * MS_PER_SEC + 1; + assert_equals(getComputedStyle(div).visibility, 'hidden', + 'Visibility when progress < 0 due to cubic-bezier easing.'); + + anim.currentTime = 60 * MS_PER_SEC; + assert_equals(getComputedStyle(div).visibility, 'visible', + 'Visibility when progress > 0 due to cubic-bezier easing.'); + +}, "Test visibility clamping behavior with an easing that has a negative component"); + +done(); +</script> +</body> |