<!doctype html> <head> <meta charset=utf-8> <title>Bug 1254419 - Test the values returned by KeyframeEffectReadOnly.getProperties()</title> <script type="application/javascript" src="../testharness.js"></script> <script type="application/javascript" src="../testharnessreport.js"></script> <script type="application/javascript" src="../testcommon.js"></script> </head> <body> <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1254419" target="_blank">Mozilla Bug 1254419</a> <div id="log"></div> <style> :root { --var-100px: 100px; --var-100px-200px: 100px 200px; } div { font-size: 10px; /* For calculating em-based units */ } </style> <script> 'use strict'; function assert_properties_equal(actual, expected) { assert_equals(actual.length, expected.length); var compareProperties = (a, b) => a.property == b.property ? 0 : (a.property < b.property ? -1 : 1); var sortedActual = actual.sort(compareProperties); var sortedExpected = expected.sort(compareProperties); // We want to serialize the values in the following form: // // { offset: 0, easing: linear, composite: replace, value: 5px }, ... // // So that we can just compare strings and, in the failure case, // easily see where the differences lie. var serializeMember = value => { return typeof value === 'undefined' ? '<not set>' : value; } var serializeValues = values => values.map(value => '{ ' + [ 'offset', 'value', 'easing', 'composite' ].map( member => `${member}: ${serializeMember(value[member])}` ).join(', ') + ' }') .join(', '); for (var i = 0; i < sortedActual.length; i++) { assert_equals(sortedActual[i].property, sortedExpected[i].property, 'CSS property name should match'); assert_equals(serializeValues(sortedActual[i].values), serializeValues(sortedExpected[i].values), `Values arrays do not match for ` + `${sortedActual[i].property} property`); } } // Shorthand for constructing a value object function value(offset, value, composite, easing) { return { offset: offset, value: value, easing: easing, composite: composite }; } var gTests = [ // --------------------------------------------------------------------- // // Tests for property-indexed specifications // // --------------------------------------------------------------------- { desc: 'a one-property two-value property-indexed specification', frames: { left: ['10px', '20px'] }, expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '20px', 'replace') ] } ] }, { desc: 'a one-shorthand-property two-value property-indexed' + ' specification', frames: { margin: ['10px', '10px 20px 30px 40px'] }, expected: [ { property: 'margin-top', values: [ value(0, '10px', 'replace', 'linear'), value(1, '10px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '10px', 'replace', 'linear'), value(1, '20px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '10px', 'replace', 'linear'), value(1, '30px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '40px', 'replace') ] } ] }, { desc: 'a two-property (one shorthand and one of its longhand' + ' components) two-value property-indexed specification', frames: { marginTop: ['50px', '60px'], margin: ['10px', '10px 20px 30px 40px'] }, expected: [ { property: 'margin-top', values: [ value(0, '50px', 'replace', 'linear'), value(1, '60px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '10px', 'replace', 'linear'), value(1, '20px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '10px', 'replace', 'linear'), value(1, '30px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '40px', 'replace') ] } ] }, { desc: 'a two-property property-indexed specification with different' + ' numbers of values', frames: { left: ['10px', '20px', '30px'], top: ['40px', '50px'] }, expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(0.5, '20px', 'replace', 'linear'), value(1, '30px', 'replace') ] }, { property: 'top', values: [ value(0, '40px', 'replace', 'linear'), value(1, '50px', 'replace') ] } ] }, { desc: 'a property-indexed specification with an invalid value', frames: { left: ['10px', '20px', '30px', '40px', '50px'], top: ['15px', '25px', 'invalid', '45px', '55px'] }, expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(0.25, '20px', 'replace', 'linear'), value(0.5, '30px', 'replace', 'linear'), value(0.75, '40px', 'replace', 'linear'), value(1, '50px', 'replace') ] }, { property: 'top', values: [ value(0, '15px', 'replace', 'linear'), value(0.25, '25px', 'replace', 'linear'), value(0.75, '45px', 'replace', 'linear'), value(1, '55px', 'replace') ] } ] }, { desc: 'a one-property two-value property-indexed specification that' + ' needs to stringify its values', frames: { opacity: [0, 1] }, expected: [ { property: 'opacity', values: [ value(0, '0', 'replace', 'linear'), value(1, '1', 'replace') ] } ] }, { desc: 'a property-indexed keyframe where a lesser shorthand precedes' + ' a greater shorthand', frames: { borderLeft: [ '1px solid rgb(1, 2, 3)', '2px solid rgb(4, 5, 6)' ], border: [ '3px dotted rgb(7, 8, 9)', '4px dashed rgb(10, 11, 12)' ] }, expected: [ { property: 'border-bottom-color', values: [ value(0, 'rgb(7, 8, 9)', 'replace', 'linear'), value(1, 'rgb(10, 11, 12)', 'replace') ] }, { property: 'border-left-color', values: [ value(0, 'rgb(1, 2, 3)', 'replace', 'linear'), value(1, 'rgb(4, 5, 6)', 'replace') ] }, { property: 'border-right-color', values: [ value(0, 'rgb(7, 8, 9)', 'replace', 'linear'), value(1, 'rgb(10, 11, 12)', 'replace') ] }, { property: 'border-top-color', values: [ value(0, 'rgb(7, 8, 9)', 'replace', 'linear'), value(1, 'rgb(10, 11, 12)', 'replace') ] }, { property: 'border-bottom-width', values: [ value(0, '3px', 'replace', 'linear'), value(1, '4px', 'replace') ] }, { property: 'border-left-width', values: [ value(0, '1px', 'replace', 'linear'), value(1, '2px', 'replace') ] }, { property: 'border-right-width', values: [ value(0, '3px', 'replace', 'linear'), value(1, '4px', 'replace') ] }, { property: 'border-top-width', values: [ value(0, '3px', 'replace', 'linear'), value(1, '4px', 'replace') ] }, { property: 'border-bottom-style', values: [ value(0, 'dotted', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-left-style', values: [ value(0, 'solid', 'replace', 'linear'), value(1, 'solid', 'replace') ] }, { property: 'border-right-style', values: [ value(0, 'dotted', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-top-style', values: [ value(0, 'dotted', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-image-outset', values: [ value(0, '0 0 0 0', 'replace', 'linear'), value(1, '0 0 0 0', 'replace') ] }, { property: 'border-image-repeat', values: [ value(0, 'stretch stretch', 'replace', 'linear'), value(1, 'stretch stretch', 'replace') ] }, { property: 'border-image-slice', values: [ value(0, '100% 100% 100% 100%', 'replace', 'linear'), value(1, '100% 100% 100% 100%', 'replace') ] }, { property: 'border-image-source', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: 'border-image-width', values: [ value(0, '1 1 1 1', 'replace', 'linear'), value(1, '1 1 1 1', 'replace') ] }, { property: '-moz-border-bottom-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: '-moz-border-left-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: '-moz-border-right-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: '-moz-border-top-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] } ] }, { desc: 'a property-indexed keyframe where a greater shorthand precedes' + ' a lesser shorthand', frames: { border: [ '3px dotted rgb(7, 8, 9)', '4px dashed rgb(10, 11, 12)' ], borderLeft: [ '1px solid rgb(1, 2, 3)', '2px solid rgb(4, 5, 6)' ] }, expected: [ { property: 'border-bottom-color', values: [ value(0, 'rgb(7, 8, 9)', 'replace', 'linear'), value(1, 'rgb(10, 11, 12)', 'replace') ] }, { property: 'border-left-color', values: [ value(0, 'rgb(1, 2, 3)', 'replace', 'linear'), value(1, 'rgb(4, 5, 6)', 'replace') ] }, { property: 'border-right-color', values: [ value(0, 'rgb(7, 8, 9)', 'replace', 'linear'), value(1, 'rgb(10, 11, 12)', 'replace') ] }, { property: 'border-top-color', values: [ value(0, 'rgb(7, 8, 9)', 'replace', 'linear'), value(1, 'rgb(10, 11, 12)', 'replace') ] }, { property: 'border-bottom-width', values: [ value(0, '3px', 'replace', 'linear'), value(1, '4px', 'replace') ] }, { property: 'border-left-width', values: [ value(0, '1px', 'replace', 'linear'), value(1, '2px', 'replace') ] }, { property: 'border-right-width', values: [ value(0, '3px', 'replace', 'linear'), value(1, '4px', 'replace') ] }, { property: 'border-top-width', values: [ value(0, '3px', 'replace', 'linear'), value(1, '4px', 'replace') ] }, { property: 'border-bottom-style', values: [ value(0, 'dotted', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-left-style', values: [ value(0, 'solid', 'replace', 'linear'), value(1, 'solid', 'replace') ] }, { property: 'border-right-style', values: [ value(0, 'dotted', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-top-style', values: [ value(0, 'dotted', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-image-outset', values: [ value(0, '0 0 0 0', 'replace', 'linear'), value(1, '0 0 0 0', 'replace') ] }, { property: 'border-image-repeat', values: [ value(0, 'stretch stretch', 'replace', 'linear'), value(1, 'stretch stretch', 'replace') ] }, { property: 'border-image-slice', values: [ value(0, '100% 100% 100% 100%', 'replace', 'linear'), value(1, '100% 100% 100% 100%', 'replace') ] }, { property: 'border-image-source', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: 'border-image-width', values: [ value(0, '1 1 1 1', 'replace', 'linear'), value(1, '1 1 1 1', 'replace') ] }, { property: '-moz-border-bottom-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: '-moz-border-left-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: '-moz-border-right-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: '-moz-border-top-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] } ] }, // --------------------------------------------------------------------- // // Tests for keyframe sequences // // --------------------------------------------------------------------- { desc: 'a keyframe sequence specification with repeated values at' + ' offset 0/1 with different easings', frames: [ { offset: 0.0, left: '100px', easing: 'ease' }, { offset: 0.0, left: '200px', easing: 'ease' }, { offset: 0.5, left: '300px', easing: 'linear' }, { offset: 1.0, left: '400px', easing: 'ease-out' }, { offset: 1.0, left: '500px', easing: 'step-end' } ], expected: [ { property: 'left', values: [ value(0, '100px', 'replace'), value(0, '200px', 'replace', 'ease'), value(0.5, '300px', 'replace', 'linear'), value(1, '400px', 'replace'), value(1, '500px', 'replace') ] } ] }, { desc: 'a one-property two-keyframe sequence', frames: [ { offset: 0, left: '10px' }, { offset: 1, left: '20px' } ], expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '20px', 'replace') ] } ] }, { desc: 'a two-property two-keyframe sequence', frames: [ { offset: 0, left: '10px', top: '30px' }, { offset: 1, left: '20px', top: '40px' } ], expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '20px', 'replace') ] }, { property: 'top', values: [ value(0, '30px', 'replace', 'linear'), value(1, '40px', 'replace') ] } ] }, { desc: 'a one shorthand property two-keyframe sequence', frames: [ { offset: 0, margin: '10px' }, { offset: 1, margin: '20px 30px 40px 50px' } ], expected: [ { property: 'margin-top', values: [ value(0, '10px', 'replace', 'linear'), value(1, '20px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '10px', 'replace', 'linear'), value(1, '30px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '10px', 'replace', 'linear'), value(1, '40px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '50px', 'replace') ] } ] }, { desc: 'a two-property (a shorthand and one of its component longhands)' + ' two-keyframe sequence', frames: [ { offset: 0, margin: '10px', marginTop: '20px' }, { offset: 1, marginTop: '70px', margin: '30px 40px 50px 60px' } ], expected: [ { property: 'margin-top', values: [ value(0, '20px', 'replace', 'linear'), value(1, '70px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '10px', 'replace', 'linear'), value(1, '40px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '10px', 'replace', 'linear'), value(1, '50px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '60px', 'replace') ] } ] }, { desc: 'a keyframe sequence with duplicate values for a given interior' + ' offset', frames: [ { offset: 0.0, left: '10px' }, { offset: 0.5, left: '20px' }, { offset: 0.5, left: '30px' }, { offset: 0.5, left: '40px' }, { offset: 1.0, left: '50px' } ], expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(0.5, '20px', 'replace'), value(0.5, '40px', 'replace', 'linear'), value(1, '50px', 'replace') ] } ] }, { desc: 'a keyframe sequence with duplicate values for offsets 0 and 1', frames: [ { offset: 0, left: '10px' }, { offset: 0, left: '20px' }, { offset: 0, left: '30px' }, { offset: 1, left: '40px' }, { offset: 1, left: '50px' }, { offset: 1, left: '60px' } ], expected: [ { property: 'left', values: [ value(0, '10px', 'replace'), value(0, '30px', 'replace', 'linear'), value(1, '40px', 'replace'), value(1, '60px', 'replace') ] } ] }, { desc: 'a two-property four-keyframe sequence', frames: [ { offset: 0, left: '10px' }, { offset: 0, top: '20px' }, { offset: 1, top: '30px' }, { offset: 1, left: '40px' } ], expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '40px', 'replace') ] }, { property: 'top', values: [ value(0, '20px', 'replace', 'linear'), value(1, '30px', 'replace') ] } ] }, { desc: 'a one-property keyframe sequence with some omitted offsets', frames: [ { offset: 0.00, left: '10px' }, { offset: 0.25, left: '20px' }, { left: '30px' }, { left: '40px' }, { offset: 1.00, left: '50px' } ], expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(0.25, '20px', 'replace', 'linear'), value(0.5, '30px', 'replace', 'linear'), value(0.75, '40px', 'replace', 'linear'), value(1, '50px', 'replace') ] } ] }, { desc: 'a two-property keyframe sequence with some omitted offsets', frames: [ { offset: 0.00, left: '10px', top: '20px' }, { offset: 0.25, left: '30px' }, { left: '40px' }, { left: '50px', top: '60px' }, { offset: 1.00, left: '70px', top: '80px' } ], expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(0.25, '30px', 'replace', 'linear'), value(0.5, '40px', 'replace', 'linear'), value(0.75, '50px', 'replace', 'linear'), value(1, '70px', 'replace') ] }, { property: 'top', values: [ value(0, '20px', 'replace', 'linear'), value(0.75, '60px', 'replace', 'linear'), value(1, '80px', 'replace') ] } ] }, { desc: 'a one-property keyframe sequence with all omitted offsets', frames: [ { left: '10px' }, { left: '20px' }, { left: '30px' }, { left: '40px' }, { left: '50px' } ], expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(0.25, '20px', 'replace', 'linear'), value(0.5, '30px', 'replace', 'linear'), value(0.75, '40px', 'replace', 'linear'), value(1, '50px', 'replace') ] } ] }, { desc: 'a keyframe sequence with different easing values, but the' + ' same easing value for a given offset', frames: [ { offset: 0.0, easing: 'ease', left: '10px'}, { offset: 0.0, easing: 'ease', top: '20px'}, { offset: 0.5, easing: 'linear', left: '30px' }, { offset: 0.5, easing: 'linear', top: '40px' }, { offset: 1.0, easing: 'step-end', left: '50px' }, { offset: 1.0, easing: 'step-end', top: '60px' } ], expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'ease'), value(0.5, '30px', 'replace', 'linear'), value(1, '50px', 'replace') ] }, { property: 'top', values: [ value(0, '20px', 'replace', 'ease'), value(0.5, '40px', 'replace', 'linear'), value(1, '60px', 'replace') ] } ] }, { desc: 'a one-property two-keyframe sequence that needs to' + ' stringify its values', frames: [ { offset: 0, opacity: 0 }, { offset: 1, opacity: 1 } ], expected: [ { property: 'opacity', values: [ value(0, '0', 'replace', 'linear'), value(1, '1', 'replace') ] } ] }, { desc: 'a keyframe sequence where shorthand precedes longhand', frames: [ { offset: 0, margin: '10px', marginRight: '20px' }, { offset: 1, margin: '30px' } ], expected: [ { property: 'margin-top', values: [ value(0, '10px', 'replace', 'linear'), value(1, '30px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '20px', 'replace', 'linear'), value(1, '30px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '10px', 'replace', 'linear'), value(1, '30px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '30px', 'replace') ] } ] }, { desc: 'a keyframe sequence where longhand precedes shorthand', frames: [ { offset: 0, marginRight: '20px', margin: '10px' }, { offset: 1, margin: '30px' } ], expected: [ { property: 'margin-top', values: [ value(0, '10px', 'replace', 'linear'), value(1, '30px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '20px', 'replace', 'linear'), value(1, '30px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '10px', 'replace', 'linear'), value(1, '30px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '30px', 'replace') ] } ] }, { desc: 'a keyframe sequence where lesser shorthand precedes greater' + ' shorthand', frames: [ { offset: 0, borderLeft: '1px solid rgb(1, 2, 3)', border: '2px dotted rgb(4, 5, 6)' }, { offset: 1, border: '3px dashed rgb(7, 8, 9)' } ], expected: [ { property: 'border-bottom-color', values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'), value(1, 'rgb(7, 8, 9)', 'replace') ] }, { property: 'border-left-color', values: [ value(0, 'rgb(1, 2, 3)', 'replace', 'linear'), value(1, 'rgb(7, 8, 9)', 'replace') ] }, { property: 'border-right-color', values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'), value(1, 'rgb(7, 8, 9)', 'replace') ] }, { property: 'border-top-color', values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'), value(1, 'rgb(7, 8, 9)', 'replace') ] }, { property: 'border-bottom-width', values: [ value(0, '2px', 'replace', 'linear'), value(1, '3px', 'replace') ] }, { property: 'border-left-width', values: [ value(0, '1px', 'replace', 'linear'), value(1, '3px', 'replace') ] }, { property: 'border-right-width', values: [ value(0, '2px', 'replace', 'linear'), value(1, '3px', 'replace') ] }, { property: 'border-top-width', values: [ value(0, '2px', 'replace', 'linear'), value(1, '3px', 'replace') ] }, { property: 'border-bottom-style', values: [ value(0, 'dotted', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-left-style', values: [ value(0, 'solid', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-right-style', values: [ value(0, 'dotted', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-top-style', values: [ value(0, 'dotted', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-image-outset', values: [ value(0, '0 0 0 0', 'replace', 'linear'), value(1, '0 0 0 0', 'replace') ] }, { property: 'border-image-repeat', values: [ value(0, 'stretch stretch', 'replace', 'linear'), value(1, 'stretch stretch', 'replace') ] }, { property: 'border-image-slice', values: [ value(0, '100% 100% 100% 100%', 'replace', 'linear'), value(1, '100% 100% 100% 100%', 'replace') ] }, { property: 'border-image-source', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: 'border-image-width', values: [ value(0, '1 1 1 1', 'replace', 'linear'), value(1, '1 1 1 1', 'replace') ] }, { property: '-moz-border-bottom-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: '-moz-border-left-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: '-moz-border-right-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: '-moz-border-top-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] } ] }, { desc: 'a keyframe sequence where greater shorthand precedes' + ' lesser shorthand', frames: [ { offset: 0, border: '2px dotted rgb(4, 5, 6)', borderLeft: '1px solid rgb(1, 2, 3)' }, { offset: 1, border: '3px dashed rgb(7, 8, 9)' } ], expected: [ { property: 'border-bottom-color', values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'), value(1, 'rgb(7, 8, 9)', 'replace') ] }, { property: 'border-left-color', values: [ value(0, 'rgb(1, 2, 3)', 'replace', 'linear'), value(1, 'rgb(7, 8, 9)', 'replace') ] }, { property: 'border-right-color', values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'), value(1, 'rgb(7, 8, 9)', 'replace') ] }, { property: 'border-top-color', values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'), value(1, 'rgb(7, 8, 9)', 'replace') ] }, { property: 'border-bottom-width', values: [ value(0, '2px', 'replace', 'linear'), value(1, '3px', 'replace') ] }, { property: 'border-left-width', values: [ value(0, '1px', 'replace', 'linear'), value(1, '3px', 'replace') ] }, { property: 'border-right-width', values: [ value(0, '2px', 'replace', 'linear'), value(1, '3px', 'replace') ] }, { property: 'border-top-width', values: [ value(0, '2px', 'replace', 'linear'), value(1, '3px', 'replace') ] }, { property: 'border-bottom-style', values: [ value(0, 'dotted', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-left-style', values: [ value(0, 'solid', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-right-style', values: [ value(0, 'dotted', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-top-style', values: [ value(0, 'dotted', 'replace', 'linear'), value(1, 'dashed', 'replace') ] }, { property: 'border-image-outset', values: [ value(0, '0 0 0 0', 'replace', 'linear'), value(1, '0 0 0 0', 'replace') ] }, { property: 'border-image-repeat', values: [ value(0, 'stretch stretch', 'replace', 'linear'), value(1, 'stretch stretch', 'replace') ] }, { property: 'border-image-slice', values: [ value(0, '100% 100% 100% 100%', 'replace', 'linear'), value(1, '100% 100% 100% 100%', 'replace') ] }, { property: 'border-image-source', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: 'border-image-width', values: [ value(0, '1 1 1 1', 'replace', 'linear'), value(1, '1 1 1 1', 'replace') ] }, { property: '-moz-border-bottom-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: '-moz-border-left-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: '-moz-border-right-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] }, { property: '-moz-border-top-colors', values: [ value(0, 'none', 'replace', 'linear'), value(1, 'none', 'replace') ] } ] }, // --------------------------------------------------------------------- // // Tests for unit conversion // // --------------------------------------------------------------------- { desc: 'em units are resolved to px values', frames: { left: ['10em', '20em'] }, expected: [ { property: 'left', values: [ value(0, '100px', 'replace', 'linear'), value(1, '200px', 'replace') ] } ] }, { desc: 'calc() expressions are resolved to the equivalent units', frames: { left: ['calc(10em + 10px)', 'calc(10em + 10%)'] }, expected: [ { property: 'left', values: [ value(0, 'calc(110px)', 'replace', 'linear'), value(1, 'calc(100px + 10%)', 'replace') ] } ] }, // --------------------------------------------------------------------- // // Tests for CSS variable handling conversion // // --------------------------------------------------------------------- { desc: 'CSS variables are resolved to their corresponding values', frames: { left: ['10px', 'var(--var-100px)'] }, expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '100px', 'replace') ] } ] }, { desc: 'CSS variables in calc() expressions are resolved', frames: { left: ['10px', 'calc(var(--var-100px) / 2 - 10%)'] }, expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(1, 'calc(50px + -10%)', 'replace') ] } ] }, { desc: 'CSS variables in shorthands are resolved to their corresponding' + ' values', frames: { margin: ['10px', 'var(--var-100px-200px)'] }, expected: [ { property: 'margin-top', values: [ value(0, '10px', 'replace', 'linear'), value(1, '100px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '10px', 'replace', 'linear'), value(1, '200px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '10px', 'replace', 'linear'), value(1, '100px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '200px', 'replace') ] } ] }, // --------------------------------------------------------------------- // // Tests for properties that parse correctly but which we fail to // convert to computed values. // // --------------------------------------------------------------------- { desc: 'a property that can\'t be resolved to computed values in' + ' initial keyframe', frames: [ { margin: '5px', simulateComputeValuesFailure: true }, { margin: '5px' } ], expected: [ ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' initial keyframe where we have enough values to create' + ' a final segment', frames: [ { margin: '5px', simulateComputeValuesFailure: true }, { margin: '5px' }, { margin: '5px' } ], expected: [ ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' initial overlapping keyframes (first in series of two)', frames: [ { margin: '5px', offset: 0, simulateComputeValuesFailure: true }, { margin: '5px', offset: 0 }, { margin: '5px' } ], expected: [ { property: 'margin-top', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] } ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' initial overlapping keyframes (second in series of two)', frames: [ { margin: '5px', offset: 0 }, { margin: '5px', offset: 0, simulateComputeValuesFailure: true }, { margin: '5px' } ], expected: [ { property: 'margin-top', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] } ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' initial overlapping keyframes (second in series of three)', frames: [ { margin: '5px', offset: 0 }, { margin: '5px', offset: 0, simulateComputeValuesFailure: true }, { margin: '5px', offset: 0 }, { margin: '5px' } ], expected: [ { property: 'margin-top', values: [ value(0, '5px', 'replace'), value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '5px', 'replace'), value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '5px', 'replace'), value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '5px', 'replace'), value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] } ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' final keyframe', frames: [ { margin: '5px' }, { margin: '5px', simulateComputeValuesFailure: true } ], expected: [ ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' final keyframe where it forms the last segment in the series', frames: [ { margin: '5px' }, { margin: '5px', marginLeft: '5px', marginRight: '5px', marginBottom: '5px', // margin-top sorts last and only it will be missing since // the other longhand components are specified simulateComputeValuesFailure: true } ], expected: [ { property: 'margin-bottom', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] } ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' final keyframe where we have enough values to create' + ' an initial segment', frames: [ { margin: '5px' }, { margin: '5px' }, { margin: '5px', simulateComputeValuesFailure: true } ], expected: [ ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' final overlapping keyframes (first in series of two)', frames: [ { margin: '5px' }, { margin: '5px', offset: 1, simulateComputeValuesFailure: true }, { margin: '5px', offset: 1 } ], expected: [ { property: 'margin-top', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] } ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' final overlapping keyframes (second in series of two)', frames: [ { margin: '5px' }, { margin: '5px', offset: 1 }, { margin: '5px', offset: 1, simulateComputeValuesFailure: true } ], expected: [ { property: 'margin-top', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] } ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' final overlapping keyframes (second in series of three)', frames: [ { margin: '5px' }, { margin: '5px', offset: 1 }, { margin: '5px', offset: 1, simulateComputeValuesFailure: true }, { margin: '5px', offset: 1 } ], expected: [ { property: 'margin-top', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace'), value(1, '5px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace'), value(1, '5px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace'), value(1, '5px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace'), value(1, '5px', 'replace') ] } ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' intermediate keyframe', frames: [ { margin: '5px' }, { margin: '5px', simulateComputeValuesFailure: true }, { margin: '5px' } ], expected: [ { property: 'margin-top', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] } ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' initial keyframe along with other values', // simulateComputeValuesFailure only applies to shorthands so we can set // it on the same keyframe and it will only apply to |margin| and not // |left|. frames: [ { margin: '77%', left: '10px', simulateComputeValuesFailure: true }, { margin: '5px', left: '20px' } ], expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '20px', 'replace') ] } ], }, { desc: 'a property that can\'t be resolved to computed values in' + ' initial keyframe along with other values where those' + ' values sort after the property with missing values', frames: [ { margin: '77%', right: '10px', simulateComputeValuesFailure: true }, { margin: '5px', right: '20px' } ], expected: [ { property: 'right', values: [ value(0, '10px', 'replace', 'linear'), value(1, '20px', 'replace') ] } ], }, { desc: 'a property that can\'t be resolved to computed values in' + ' final keyframe along with other values', frames: [ { margin: '5px', left: '10px' }, { margin: '5px', left: '20px', simulateComputeValuesFailure: true } ], expected: [ { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '20px', 'replace') ] } ], }, { desc: 'a property that can\'t be resolved to computed values in' + ' final keyframe along with other values where those' + ' values sort after the property with missing values', frames: [ { margin: '5px', right: '10px' }, { margin: '5px', right: '20px', simulateComputeValuesFailure: true } ], expected: [ { property: 'right', values: [ value(0, '10px', 'replace', 'linear'), value(1, '20px', 'replace') ] } ], }, { desc: 'a property that can\'t be resolved to computed values in' + ' an intermediate keyframe along with other values', frames: [ { margin: '5px', left: '10px' }, { margin: '5px', left: '20px', simulateComputeValuesFailure: true }, { margin: '5px', left: '30px' } ], expected: [ { property: 'margin-top', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(0.5, '20px', 'replace', 'linear'), value(1, '30px', 'replace') ] } ] }, { desc: 'a property that can\'t be resolved to computed values in' + ' an intermediate keyframe by itself', frames: [ { margin: '5px', left: '10px' }, { margin: '5px', simulateComputeValuesFailure: true }, { margin: '5px', left: '30px' } ], expected: [ { property: 'margin-top', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-right', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-bottom', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'margin-left', values: [ value(0, '5px', 'replace', 'linear'), value(1, '5px', 'replace') ] }, { property: 'left', values: [ value(0, '10px', 'replace', 'linear'), value(1, '30px', 'replace') ] } ] }, ]; gTests.forEach(function(subtest) { test(function(t) { var div = addDiv(t); var animation = div.animate(subtest.frames, 100 * MS_PER_SEC); assert_properties_equal(animation.effect.getProperties(), subtest.expected); }, subtest.desc); }); </script> </body>