summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-properties-values-api/at-property-animation.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/css/css-properties-values-api/at-property-animation.html')
-rw-r--r--testing/web-platform/tests/css/css-properties-values-api/at-property-animation.html298
1 files changed, 298 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-properties-values-api/at-property-animation.html b/testing/web-platform/tests/css/css-properties-values-api/at-property-animation.html
new file mode 100644
index 0000000000..9f81ae846e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-properties-values-api/at-property-animation.html
@@ -0,0 +1,298 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.css-houdini.org/css-properties-values-api-1">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="./resources/utils.js"></script>
+<div id=outer>
+ <div id=div></div>
+</div>
+<script>
+
+test_with_at_property({
+ syntax: '"<length>"',
+ inherits: false,
+ initialValue: '0px'
+}, (name) => {
+ with_style_node(`
+ @keyframes test {
+ from { ${name}: 100px; }
+ to { ${name}: 200px; }
+ }
+ #div { animation: test 100s -50s linear; }
+ `, () => {
+ assert_equals(getComputedStyle(div).getPropertyValue(name), '150px');
+ });
+}, '@keyframes works with @property');
+
+test_with_at_property({
+ syntax: '"<length>"',
+ inherits: false,
+ initialValue: '0px'
+}, (name) => {
+ with_style_node(`
+ @property ${name} {
+ syntax: "<color>";
+ inherits: false;
+ initial-value: black;
+ }
+ @keyframes test {
+ from { ${name}: rgb(100, 100, 100); }
+ to { ${name}: rgb(200, 200, 200); }
+ }
+ #div { animation: test 100s -50s linear; }
+ `, () => {
+ assert_equals(getComputedStyle(div).getPropertyValue(name), 'rgb(150, 150, 150)');
+ });
+}, '@keyframes picks up the latest @property in the document');
+
+test_with_at_property({
+ syntax: '"<length>"',
+ inherits: false,
+ initialValue: '0px'
+}, (name) => {
+ // These keyframes are initially invalid for the declared custom property.
+ let animation = div.animate([
+ { [name]: 'rgb(100, 100, 100)'},
+ { [name]: 'rgb(200, 200, 200)'},
+ ], { duration: 10000, delay: -5000, easing: 'linear' });
+ let cs = getComputedStyle(div);
+ assert_equals(cs.getPropertyValue(name), '0px');
+
+ // Redeclare the property as a <color>, effectively making the existing
+ // keyframes valid.
+ with_at_property({
+ name: name,
+ syntax: '"<color>"',
+ inherits: false,
+ initialValue: 'black'
+ }, (name) => {
+ assert_equals(cs.getPropertyValue(name), 'rgb(150, 150, 150)');
+ });
+
+ animation.finish();
+}, 'Ongoing animation picks up redeclared custom property');
+
+test_with_at_property({
+ syntax: '"<length>"',
+ inherits: false,
+ initialValue: '0px'
+}, (name) => {
+ // These keyframes are initially invalid for the declared custom property.
+ let animation = div.animate([
+ { [name]: 'rgb(100, 100, 100)'},
+ { [name]: 'rgb(200, 200, 200)'},
+ ], { duration: 10000, delay: -5000, easing: 'linear' });
+ let cs = getComputedStyle(div);
+ assert_equals(cs.getPropertyValue(name), '0px');
+
+ // Setting the keyframes to something that matches <length> makes the
+ // interpolation valid.
+ animation.effect.setKeyframes([
+ {[name]: '100px'},
+ {[name]: '200px'}
+ ]);
+ assert_equals(cs.getPropertyValue(name), '150px');
+
+ animation.finish();
+}, 'Ongoing animation matches new keyframes against the current registration');
+
+test_with_at_property({
+ syntax: '"<length>"',
+ inherits: false,
+ initialValue: '0px'
+}, (name) => {
+ let animation = div.animate([
+ { [name]: 'initial'},
+ { [name]: '400px'},
+ ], { duration: 10000, delay: -5000, easing: 'linear' });
+ let cs = getComputedStyle(div);
+ assert_equals(cs.getPropertyValue(name), '200px');
+
+ // Change initial value.
+ with_at_property({
+ name: name,
+ syntax: '"<length>"',
+ inherits: false,
+ initialValue: '100px'
+ }, (name) => {
+ assert_equals(cs.getPropertyValue(name), '250px');
+ });
+
+ animation.finish();
+}, 'Ongoing animation picks up redeclared intial value');
+
+test_with_at_property({
+ syntax: '"<length>"',
+ inherits: false,
+ initialValue: '0px'
+}, (name) => {
+ try {
+ document.body.style = `${name}: 100px`;
+ // Note that 'inherit' here refers to #outer, which has the initial
+ // value. (#outer did not inherit from body, since the property is not
+ // yet declared as inherited).
+ let animation = div.animate([
+ { [name]: 'inherit'},
+ { [name]: '400px'},
+ ], { duration: 10000, delay: -5000, easing: 'linear' });
+ let cs = getComputedStyle(div);
+ assert_equals(cs.getPropertyValue(name), '200px');
+
+ // Change inherits to 'true'. The value should now propagate from body
+ // to #outer.
+ with_at_property({
+ name: name,
+ syntax: '"<length>"',
+ inherits: true,
+ initialValue: '0px'
+ }, (name) => {
+ assert_equals(cs.getPropertyValue(name), '250px');
+ });
+
+ animation.finish();
+ } finally {
+ document.body.style = '';
+ }
+}, 'Ongoing animation picks up redeclared inherits flag');
+
+test_with_at_property({
+ syntax: '"<length>"',
+ inherits: false,
+ initialValue: '0px'
+}, (name) => {
+ try {
+ outer.style = `${name}: 100px`;
+ // 'unset' should take the initial value (not the value from #outer), since
+ // the property is not declared as inherited.
+ let animation = div.animate([
+ { [name]: 'unset'},
+ { [name]: '400px'},
+ ], { duration: 10000, delay: -5000, easing: 'linear' });
+ let cs = getComputedStyle(div);
+ assert_equals(cs.getPropertyValue(name), '200px');
+
+ // Change inherits to 'true'. 'unset' now refers to #outer's value.
+ with_at_property({
+ name: name,
+ syntax: '"<length>"',
+ inherits: true,
+ initialValue: '0px'
+ }, (name) => {
+ assert_equals(cs.getPropertyValue(name), '250px');
+ });
+
+ animation.finish();
+ } finally {
+ outer.style = '';
+ }
+}, 'Ongoing animation picks up redeclared meaning of \'unset\'');
+
+test_with_at_property({
+ syntax: '"<color>"',
+ inherits: false,
+ initialValue: 'red'
+}, (name) => {
+ try {
+ assert_equals(getComputedStyle(div).getPropertyValue(name), 'rgb(255, 0, 0)');
+ div.style = `transition: ${name} steps(2, start) 100s; ${name}: blue`;
+ assert_equals(getComputedStyle(div).getPropertyValue(name), 'rgb(128, 0, 128)');
+ } finally {
+ div.style = '';
+ }
+}, 'Transitioning from initial value');
+
+test_with_at_property({
+ syntax: '"<color>"',
+ inherits: false,
+ initialValue: 'red'
+}, (name) => {
+ try {
+ div.style = `${name}: blue;`;
+ assert_equals(getComputedStyle(div).getPropertyValue(name), 'rgb(0, 0, 255)');
+ div.style = `transition: ${name} steps(2, start) 100s; ${name}: green`;
+ assert_equals(getComputedStyle(div).getPropertyValue(name), 'rgb(0, 64, 128)');
+ } finally {
+ div.style = '';
+ }
+}, 'Transitioning from specified value');
+
+test_with_at_property({
+ syntax: '"<length>"',
+ inherits: false,
+ initialValue: '100px'
+}, (name) => {
+ with_style_node(`div { transition: ${name} steps(2, start) 100s; }`, () => {
+ assert_equals(getComputedStyle(div).getPropertyValue(name), '100px');
+ // Re-declaring the property with a different initial value effectively
+ // means the computed value has changed. This means we should transition
+ // from the old initial value to the new initial value.
+ with_at_property({
+ name: name,
+ syntax: '"<length>"',
+ inherits: false,
+ initialValue: '200px'
+ }, () => {
+ assert_equals(getComputedStyle(div).getPropertyValue(name), '150px');
+ });
+ });
+}, 'Transition triggered by initial value change');
+
+test_with_at_property({
+ syntax: '"<length>"',
+ inherits: false,
+ initialValue: '100px'
+}, (name) => {
+ with_style_node(`div { transition: ${name} steps(2, start) 100s; }`, () => {
+ assert_equals(getComputedStyle(div).getPropertyValue(name), '100px');
+ with_at_property({
+ name: name,
+ syntax: '"<color>"',
+ inherits: false,
+ initialValue: 'green'
+ }, () => {
+ assert_equals(getComputedStyle(div).getPropertyValue(name), 'rgb(0, 128, 0)');
+ });
+ });
+}, 'No transition when changing types');
+
+test(() => {
+ let name = generate_name();
+ with_style_node(`div { ${name}: 100px; transition: ${name} steps(2, start) 100s; }`, () => {
+ assert_equals(getComputedStyle(div).getPropertyValue(name), '100px');
+
+ let style1 = document.createElement('style');
+ style1.textContent = `
+ @property ${name} {
+ syntax: "<length>";
+ inherits: false;
+ initial-value: 200px;
+ }
+ `;
+
+ let style2 = document.createElement('style');
+ style2.textContent = `div { ${name}: 400px; }`;
+
+ try {
+ // Register the property:
+ document.body.append(style1);
+ // The token sequence ' 100px' is now interpreted as a length '100px'.
+ assert_equals(getComputedStyle(div).getPropertyValue(name), '100px');
+
+ // Change the computed value:
+ document.body.append(style2);
+ // This should cause an interpolation between 100px and 400px:
+ assert_equals(getComputedStyle(div).getPropertyValue(name), '250px');
+
+ // In the middle of the transition above, remove the @property rule
+ // (making the computed value a token sequence again). We should snap
+ // to the new token sequence.
+ style1.remove();
+ assert_equals(getComputedStyle(div).getPropertyValue(name), '400px');
+ } finally {
+ style1.remove();
+ style2.remove();
+ }
+ });
+}, 'No transition when removing @property rule');
+
+</script>