Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  test_transitions_per_property.html   Sprache: HTML

 
 products/Sources/formale Sprachen/C/Firefox/layout/style/test/test_transitions_per_property.html


<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=435441
-->

<head>
  <title>Test for Bug 435441</title>
  <meta charset=utf-8>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="text/javascript" src="property_database.js"></script>
  <script type="text/javascript" src="animation_utils.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
  <style type="text/css">

  #display > p { margin-top: 0; margin-bottom: 0; }

  </style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435441">Mozilla Bug 435441</a>

<!--
  fixed-height container so percentage heights compute to different
  (i.e., nonzero) values
  fixed-width container so that percentages for margin-top and
  margin-bottom are all relative to the same size container (rather than
  one that depends on whether we're tall enough to need a scrollbar)

  Use a 20px font size and line-height so that percentage line-height
  and vertical-align doesn't accumulate rounding error.
  -->

<div style="height: 50px; width: 300px; font-size: 20px; line-height: 20px">

<div id="display">
</div>

</div>
<pre id="test">
<script type="application/javascript">

/* eslint no-shadow: ["error", {"allow": ["prop""div"]}] */
/* eslint-disable dot-notation */


/** Test for Bug 435441 **/

SimpleTest.requestLongerTimeout(2);
SimpleTest.waitForExplicitFinish();

function has_num(str)
{
    return !!String(str).match(/^([\d.]+)/);
}

function any_unit_to_num(str)
{
    return Number(String(str).match(/^([\d.]+)/)[1]);
}

var FUNC_NEGATIVE = "cubic-bezier(0.25, -2, 0.75, 1)";
var FUNC_OVERONE = "cubic-bezier(0.25, 0, 0.75, 3)";

var supported_properties = {
    "aspect-ratio" : [ test_aspect_ratio_transition ],
    "border-bottom-left-radius": [ test_radius_transition ],
    "border-bottom-right-radius": [ test_radius_transition ],
    "border-top-left-radius": [ test_radius_transition ],
    "border-top-right-radius": [ test_radius_transition ],
    "border-start-start-radius": [ test_radius_transition ],
    "border-start-end-radius": [ test_radius_transition ],
    "border-end-start-radius": [ test_radius_transition ],
    "border-end-end-radius": [ test_radius_transition ],
    "-moz-box-flex": [ test_float_zeroToOne_transition,
                       test_float_aboveOne_transition,
                       test_float_zeroToOne_clamped ],
    "box-shadow": [ test_shadow_transition ],
    "column-count": [ test_pos_integer_or_auto_transition,
                      test_integer_at_least_one_clamping ],
    "column-rule-color": [ test_color_transition,
                           test_currentcolor_transition ],
    "column-rule-width": [ test_length_transition,
                           test_length_clamped ],
    "column-width": [ test_length_transition,
                      test_length_clamped ],
    "cx": [ test_length_transition, test_percent_transition,
            test_length_unclamped, test_percent_unclamped ],
    "cy": [ test_length_transition, test_percent_transition,
            test_length_unclamped, test_percent_unclamped ],
    "background-color": [ test_color_transition,
                          test_currentcolor_transition ],
    "background-position": [ test_background_position_transition,
                             test_length_percent_pair_unclamped ],
    "background-position-x": [ test_background_position_coord_transition,
                               test_length_transition,
                               test_percent_transition,
                             // FIXME: We don't currently test clamping,
                             // since background-position-x uses calc() as
                             // an intermediate form.
                             /* test_length_percent_pair_unclamped */ ],
    "background-position-y": [ test_background_position_coord_transition,
                               test_length_transition,
                               test_percent_transition,
                             // FIXME: We don't currently test clamping,
                             // since background-position-y uses calc() as
                             // an intermediate form.
                             /* test_length_percent_pair_unclamped */ ],
    "background-size": [ test_background_size_transition,
                         test_length_percent_pair_clamped ],
    "border-bottom-color": [ test_color_transition,
                             test_currentcolor_transition ],
    "border-bottom-width": [ test_length_transition,
                             test_length_clamped ],
    "border-left-color": [ test_color_transition,
                           test_currentcolor_transition ],
    "border-left-width": [ test_length_transition,
                           test_length_clamped ],
    "border-right-color": [ test_color_transition,
                            test_currentcolor_transition ],
    "border-right-width": [ test_length_transition,
                            test_length_clamped ],
    "border-spacing": [ test_length_pair_transition,
                        test_length_pair_transition_clamped ],
    "border-top-color": [ test_color_transition,
                          test_currentcolor_transition ],
    "border-top-width": [ test_length_transition,
                          test_length_clamped ],
    "bottom": [ test_length_transition, test_percent_transition,
                test_length_percent_calc_transition,
                test_length_unclamped, test_percent_unclamped ],
    "accent-color": [ test_color_transition,
                      test_currentcolor_transition,
                      test_auto_color_transition ],
    "caret-color": [ test_color_transition,
                     test_currentcolor_transition,
                     test_auto_color_transition ],
    "clip": [ test_rect_transition ],
    "clip-path": [ test_basic_shape_or_url_transition,
                   test_path_function ],
    "color": [ test_color_transition,
               test_currentcolor_transition ],
    "d": [ test_path_function ],
    "fill": [ test_color_transition,
              test_currentcolor_transition ],
    "fill-opacity" : [ test_float_zeroToOne_transition,
                       // opacity is clamped in computed style
                       // (not parsing/interpolation)
                       test_float_zeroToOne_clamped ],
    "filter" : [ test_filter_transition ],
    "flex-basis": [ test_length_transition, test_percent_transition,
                    test_length_clamped, test_percent_clamped,
                    test_flex_basis_content_transition ],
    "flex-grow": [ test_float_zeroToOne_transition,
                   test_float_aboveOne_transition ],
    "flex-shrink": [ test_float_zeroToOne_transition,
                     test_float_aboveOne_transition ],
    "flood-color": [ test_color_transition,
                     test_currentcolor_transition ],
    "flood-opacity" : [ test_float_zeroToOne_transition,
                        // opacity is clamped in computed style
                        // (not parsing/interpolation)
                        test_float_zeroToOne_clamped ],
    "font-size": [ test_length_transition, test_percent_transition,
                   test_length_percent_calc_transition,
                   test_length_clamped, test_percent_clamped ],
    "font-size-adjust": [ test_float_zeroToOne_transition,
                          test_float_aboveOne_transition,
                          /* FIXME: font-size-adjust treats zero specially */
                          /* test_float_zeroToOne_clamped */ ],
    "font-stretch": [ test_percent_transition, test_percent_clamped ],
    "font-weight": [ test_font_weight ],
    "column-gap": [ test_grid_gap ],
    "row-gap": [ test_grid_gap ],
    "height": [ test_length_transition, test_percent_transition,
                test_length_percent_calc_transition,
                test_length_clamped, test_percent_clamped ],
    "left": [ test_length_transition, test_percent_transition,
              test_length_percent_calc_transition,
              test_length_unclamped, test_percent_unclamped ],
    "letter-spacing": [ test_length_transition, test_percent_transition,
                        test_length_unclamped, test_percent_unclamped ],
    "lighting-color": [ test_color_transition,
                        test_currentcolor_transition ],
    // NOTE: when calc() is supported on 'line-height', we should add
    // test_length_percent_calc_transition.
    "line-height": [ test_length_transition, test_percent_transition,
                     test_length_clamped, test_percent_clamped ],
    "margin-bottom": [ test_length_transition, test_percent_transition,
                       test_length_percent_calc_transition,
                       test_length_unclamped, test_percent_unclamped ],
    "margin-left": [ test_length_transition, test_percent_transition,
                     test_length_percent_calc_transition,
                     test_length_unclamped, test_percent_unclamped ],
    "margin-right": [ test_length_transition, test_percent_transition,
                      test_length_percent_calc_transition,
                      test_length_unclamped, test_percent_unclamped ],
    "margin-top": [ test_length_transition, test_percent_transition,
                    test_length_percent_calc_transition,
                    test_length_unclamped, test_percent_unclamped ],
    "mask-position": [ test_background_position_transition,
                       test_length_percent_pair_unclamped ],
    "mask-position-x": [ test_background_position_coord_transition,
                         test_length_transition,
                         test_percent_transition,
                         // FIXME: We don't currently test clamping,
                         // since background-position-x uses calc() as
                         // an intermediate form.
                         /* test_length_percent_pair_unclamped */ ],
    "mask-position-y": [ test_background_position_coord_transition,
                         test_length_transition,
                         test_percent_transition,
                         // FIXME: We don't currently test clamping,
                         // since background-position-y uses calc() as
                         // an intermediate form.
                         /* test_length_percent_pair_unclamped */ ],
    "mask-size": [ test_background_size_transition,
                   test_length_percent_pair_clamped ],
    "max-height": [ test_length_transition, test_percent_transition,
                    test_length_clamped, test_percent_clamped ],
    "max-width": [ test_length_transition, test_percent_transition,
                   test_length_clamped, test_percent_clamped ],
    "min-height": [ test_length_transition, test_percent_transition,
                    test_length_clamped, test_percent_clamped ],
    "min-width": [ test_length_transition, test_percent_transition,
                   test_length_clamped, test_percent_clamped ],
    "object-position": [ test_background_position_transition ],
    "overflow-clip-margin": [ test_length_transition ],
    "opacity" : [ test_float_zeroToOne_transition,
                  // opacity is clamped in computed style
                  // (not parsing/interpolation)
                  test_float_zeroToOne_clamped ],
    "order": [ test_integer_transition ],
    "outline-color": [ test_color_transition,
                       test_currentcolor_transition ],
    "outline-offset": [ test_length_transition, test_length_unclamped ],
    "outline-width": [ test_length_transition, test_length_clamped ],
    "padding-bottom": [ test_length_transition, test_percent_transition,
                        test_length_percent_calc_transition,
                        test_length_clamped, test_percent_clamped ],
    "padding-left": [ test_length_transition, test_percent_transition,
                      test_length_percent_calc_transition,
                      test_length_clamped, test_percent_clamped ],
    "padding-right": [ test_length_transition, test_percent_transition,
                       test_length_percent_calc_transition,
                       test_length_clamped, test_percent_clamped ],
    "padding-top": [ test_length_transition, test_percent_transition,
                     test_length_percent_calc_transition,
                     test_length_clamped, test_percent_clamped ],
    "perspective": [ test_length_transition ],
    "perspective-origin": [ test_length_pair_transition,
                            test_length_percent_pair_transition,
                            test_length_percent_pair_unclamped ],
    "right": [ test_length_transition, test_percent_transition,
               test_length_percent_calc_transition,
               test_length_unclamped, test_percent_unclamped ],
    "r": [ test_length_transition, test_percent_transition,
           test_length_clamped, test_percent_clamped ],
    "rx": [ test_length_transition, test_percent_transition,
            test_length_clamped, test_percent_clamped ],
    "ry": [ test_length_transition, test_percent_transition,
            test_length_clamped, test_percent_clamped ],
    "shape-image-threshold": [ test_float_zeroToOne_transition,
                               // shape-image-threshold (like opacity) is
                               // clamped in computed style
                               // (not parsing/interpolation)
                               test_float_zeroToOne_clamped ],
    "shape-margin": [ test_length_transition, test_percent_transition,
                      test_length_clamped, test_percent_clamped ],
    "shape-outside": [ test_basic_shape_or_url_transition ],
    "stop-color": [ test_color_transition,
                    test_currentcolor_transition ],
    "stop-opacity" : [ test_float_zeroToOne_transition,
                       // opacity is clamped in computed style
                       // (not parsing/interpolation)
                       test_float_zeroToOne_clamped ],
    "stroke": [ test_color_transition,
                test_currentcolor_transition ],
    "stroke-dasharray": [ test_dasharray_transition ],
    "stroke-dashoffset": [ test_length_transition, test_percent_transition,
                           test_length_unclamped, test_percent_unclamped, ],
    "stroke-miterlimit": [ test_float_zeroToOne_transition,
                           test_float_aboveOne_transition,
                           test_float_aboveZero_clamped ],
    "stroke-opacity" : [ test_float_zeroToOne_transition,
                         // opacity is clamped in computed style
                         // (not parsing/interpolation)
                         test_float_zeroToOne_clamped ],
    "stroke-width": [ test_length_transition, test_percent_transition,
                      test_length_clamped, test_percent_clamped, ],
    "tab-size": [ test_float_zeroToOne_transition,
                  test_float_aboveOne_transition, test_length_clamped ],
    "text-decoration": [ test_color_shorthand_transition,
                         test_currentcolor_shorthand_transition ],
    "text-decoration-color": [ test_color_transition,
                               test_currentcolor_transition ],
    "text-emphasis-color": [ test_color_transition,
                             test_currentcolor_transition ],
    "text-indent": [ test_length_transition, test_percent_transition,
                     test_length_unclamped, test_percent_unclamped ],
    "text-shadow": [ test_shadow_transition ],
    "top": [ test_length_transition, test_percent_transition,
             test_length_percent_calc_transition,
             test_length_unclamped, test_percent_unclamped ],
    "transform": [ test_transform_transition ],
    "transform-origin": [ test_length_pair_transition,
                          test_length_percent_pair_transition,
                          test_length_percent_pair_unclamped ],
    "rotate": [ test_rotate_transition ],
    "scale": [ test_scale_transition ],
    "translate": [ test_translate_transition ],
    "vertical-align": [ test_length_transition, test_percent_transition,
                        test_length_unclamped, test_percent_unclamped ],
    "visibility": [ test_visibility_transition ],
    "width": [ test_length_transition, test_percent_transition,
               test_length_percent_calc_transition,
               test_length_clamped, test_percent_clamped ],
    "word-spacing": [ test_length_transition, test_percent_transition,
                      test_length_unclamped, test_percent_unclamped ],
    "x": [ test_length_transition, test_percent_transition,
           test_length_unclamped, test_percent_unclamped ],
    "y": [ test_length_transition, test_percent_transition,
           test_length_unclamped, test_percent_unclamped ],
    "z-index": [ test_integer_transition, test_pos_integer_or_auto_transition ],
    "-webkit-line-clamp": [ test_pos_integer_or_none_transition ],
    "-webkit-text-fill-color": [ test_color_transition,
                                 test_currentcolor_transition ],
    "-webkit-text-stroke-color": [ test_color_transition,
                                   test_currentcolor_transition ],
    "text-underline-offset": [ test_length_transition ],
    "text-decoration-thickness": [ test_length_transition ],
    "scroll-margin-top": [
      test_length_transition,
    ],
    "scroll-margin-right": [
      test_length_transition,
    ],
    "scroll-margin-bottom": [
      test_length_transition,
    ],
    "scroll-margin-left": [
      test_length_transition,
    ],
    "scroll-padding-top": [
      test_length_transition, test_percent_transition,
      test_length_clamped, test_percent_clamped,
    ],
    "scroll-padding-right": [
      test_length_transition, test_percent_transition,
      test_length_clamped, test_percent_clamped,
    ],
    "scroll-padding-bottom": [
      test_length_transition, test_percent_transition,
      test_length_clamped, test_percent_clamped,
    ],
    "scroll-padding-left": [
      test_length_transition, test_percent_transition,
      test_length_clamped, test_percent_clamped,
    ],
    "scrollbar-color": [ test_scrollbar_color_transition ],
};

if (IsCSSPropertyPrefEnabled("layout.css.backdrop-filter.enabled")) {
  supported_properties["backdrop-filter"] = [ test_filter_transition ];
}

if (IsCSSPropertyPrefEnabled("layout.css.font-variations.enabled")) {
  supported_properties["font-variation-settings"] = [ test_font_variations_transition ];
}

if (IsCSSPropertyPrefEnabled("layout.css.contain-intrinsic-size.enabled")) {
  supported_properties["contain-intrinsic-width"] = [ test_length_transition, test_auto_with_length_transition ];
  supported_properties["contain-intrinsic-height"] = supported_properties["contain-intrinsic-width"];
}

supported_properties["content-visibility"] = [test_content_visibility_transition];

if (IsCSSPropertyPrefEnabled("layout.css.zoom.enabled")) {
  Object.assign(supported_properties, {
    "zoom": [ test_number_transition, test_percent_transition ],
  });
}

// For properties which are well-tested by web-platform-tests, we don't need to
// test animations/transitions again on them.
var skipped_transitionable_properties = [
  "border-image-outset",
  "border-image-slice",
  "border-image-width",
  "font-style",  // Tests being added in https://github.com/web-platform-tests/wpt/pull/37570
  "grid-template-columns",
  "grid-template-rows",
  "hyphenate-limit-chars",  // WPT tests being added in bug 1521723.
  "offset-path",
  "offset-distance",
  "offset-rotate",
  "offset-anchor",
  "offset-position",
]

// Logical properties.
for (const logical_side of ["inline-start""inline-end""block-start""block-end"]) {
  supported_properties["border-" + logical_side + "-color"] = supported_properties["border-top-color"];
  supported_properties["border-" + logical_side + "-width"] = supported_properties["border-top-width"];
  supported_properties["margin-" + logical_side] = supported_properties["margin-top"];
  supported_properties["padding-" + logical_side] = supported_properties["padding-top"];
  supported_properties["inset-" + logical_side] = supported_properties["top"];
  supported_properties["scroll-margin-" + logical_side] = supported_properties["scroll-margin-top"];
  supported_properties["scroll-padding-" + logical_side] = supported_properties["scroll-padding-top"];
}

for (const logical_size of ["inline""block"]) {
  supported_properties[logical_size + "-size"] = supported_properties["width"];
  supported_properties["min-" + logical_size + "-size"] = supported_properties["min-width"];
  supported_properties["max-" + logical_size + "-size"] = supported_properties["max-width"];
  if (IsCSSPropertyPrefEnabled("layout.css.contain-intrinsic-size.enabled")) {
    supported_properties["contain-intrinsic-" + logical_size + "-size"] = supported_properties["contain-intrinsic-width"];
  }
}

var div = document.getElementById("display");
var cs = getComputedStyle(div"");
var winUtils = SpecialPowers.getDOMWindowUtils(window);

function computeMatrix(v) {
  div.style.setProperty("transform", v, "");
  var result = cs.getPropertyValue("transform");
  div.style.removeProperty("transform");
  return result;
}
var c_rot_15 = computeMatrix("rotate(15deg)");
is(c_rot_15.substring(0,6), "matrix""should compute to matrix value");
var c_rot_60 = computeMatrix("rotate(60deg)");
is(c_rot_60.substring(0,6), "matrix""should compute to matrix value");

var transformTests = [
  // rotate
  { start: 'none', end: 'rotate(60deg)',
    expected_uncomputed: 'rotate(15deg)',
    expected: c_rot_15 },
  { start: 'rotate(0)', end: 'rotate(60deg)',
    expected_uncomputed: 'rotate(15deg)',
    expected: c_rot_15 },
  { start: 'rotate(0deg)', end: 'rotate(60deg)',
    expected_uncomputed: 'rotate(15deg)',
    expected: c_rot_15 },
  { start: 'none', end: c_rot_60,
    expected: c_rot_15 },
  { start: 'none', end: 'rotate(360deg)',
    expected_uncomputed: 'rotate(90deg)',
    expected: computeMatrix('rotate(90deg)') },
  { start: 'none', end: 'rotatez(360deg)',
    expected_uncomputed: 'rotate(90deg)',
    expected: computeMatrix('rotate(90deg)') },
  { start: 'none', end: 'rotate(720deg)',
    expected_uncomputed: 'rotate(180deg)',
    expected: computeMatrix('rotate(180deg)') },
  { start: 'none', end: 'rotate(720deg)',
    expected_uncomputed: 'rotatez(180deg)',
    expected: computeMatrix('rotate(180deg)') },
  { start: 'none', end: 'rotate(1080deg)',
    expected_uncomputed: 'rotate(270deg)',
    expected: computeMatrix('rotate(270deg)') },
  { start: 'none', end: 'rotate(1080deg)',
    expected_uncomputed: 'rotate(270deg)',
    expected: computeMatrix('rotatez(270deg)') },
  { start: 'none', end: 'rotate(1440deg)',
    expected_uncomputed: 'rotate(360deg)',
    expected: computeMatrix('scale(1)'),
    round_error_ok: true },
  { start: 'none', end: 'rotatey(60deg)',
    expected_uncomputed: 'rotatey(15deg)',
    expected: computeMatrix('rotatey(15deg)') },
  { start: 'none', end: 'rotatey(720deg)',
    expected_uncomputed: 'rotatey(180deg)',
    expected: computeMatrix('rotatey(180deg)') },
  { start: 'none', end: 'rotatex(60deg)',
    expected_uncomputed: 'rotatex(15deg)',
    expected: computeMatrix('rotatex(15deg)') },
  { start: 'none', end: 'rotatex(720deg)',
    expected_uncomputed: 'rotatex(180deg)',
    expected: computeMatrix('rotatex(180deg)') },

  // translate
  { start: 'translate(20px)', end: 'none',
    expected_uncomputed: 'translate(15px)',
    expected: 'matrix(1, 0, 0, 1, 15, 0)' },
  { start: 'translate(20px, 12px)', end: 'none',
    expected_uncomputed: 'translate(15px, 9px)',
    expected: 'matrix(1, 0, 0, 1, 15, 9)' },
  { start: 'translateX(-20px)', end: 'none',
    expected_uncomputed: 'translateX(-15px)',
    expected: 'matrix(1, 0, 0, 1, -15, 0)' },
  { start: 'translateY(-40px)', end: 'none',
    expected_uncomputed: 'translateY(-30px)',
    expected: 'matrix(1, 0, 0, 1, 0, -30)' },
  { start: 'translateZ(40px)', end: 'none',
    expected_uncomputed: 'translateZ(30px)',
    expected: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 30, 1)' },
  { start: 'none', end: 'translate3D(40px, 60px, -40px)',
    expected_uncomputed: 'translate3D(10px, 15px, -10px)',
    expected: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10, 15, -10, 1)' },
  // percentages are relative to 300px (width) and 50px (height)
  // per the prerequisites in property_database.js
  { start: 'translate(20%)', end: 'none',
    expected_uncomputed: 'translate(15%)',
    expected: 'matrix(1, 0, 0, 1, 45, 0)',
    round_error_ok: true },
  { start: 'translate(20%, 12%)', end: 'none',
    expected_uncomputed: 'translate(15%, 9%)',
    expected: 'matrix(1, 0, 0, 1, 45, 4.5)',
    round_error_ok: true },
  { start: 'translateX(-20%)', end: 'none',
    expected_uncomputed: 'translateX(-15%)',
    expected: 'matrix(1, 0, 0, 1, -45, 0)',
    round_error_ok: true },
  { start: 'translateY(-40%)', end: 'none',
    expected_uncomputed: 'translateY(-30%)',
    expected: 'matrix(1, 0, 0, 1, 0, -15)',
    round_error_ok: true },
  { start: 'none', end: 'rotate(90deg) translate(20%, 20%) rotate(-90deg)',
    expected_uncomputed: 'rotate(22.5deg) translate(5%, 5%) rotate(-22.5deg)',
    round_error_ok: true },
  { start: 'none', end: 'rotate(-90deg) translate(20%, 20%) rotate(90deg)',
    expected_uncomputed: 'rotate(-22.5deg) translate(5%, 5%) rotate(22.5deg)',
    round_error_ok: true },
  // test percent translation using matrix decomposition
  { start: 'matrix(1, 0, 0, 1, 0, 0)',
    end: 'rotate(90deg) translate(20%, 20%) rotate(-90deg)',
    expected: 'matrix(1, 0, 0, 1, -2.5, 15)',
    round_error_ok: true },
  { start: 'matrix(1, 0, 0, 1, 0, 0)',
    end: 'rotate(-90deg) translate(20%, 20%) rotate(90deg)',
    expected: 'matrix(1, 0, 0, 1, 2.5, -15)',
    round_error_ok: true },
  // test calc() in translate
  // Note that font-size: is 20px, and that percentages are relative
  // to 300px (width) and 50px (height) per the prerequisites in
  // property_database.js
  { start: 'translateX(20%)', /* 60px */
    end: 'translateX(calc(10% + 1em))', /* 30px + 20px = 50px */
    expected_uncomputed: 'translateX(calc(17.5% + 0.25em))',
    expected: 'matrix(1, 0, 0, 1, 57.5, 0)' },
  { start: 'translate(calc(0.75 * 3em + 1.5 * 10%), calc(0.5 * 5em + 0.5 * 8%))', /* 90px, 52px */
    end: 'rotate(90deg) translateY(20%) rotate(90deg) translateY(calc(10% + 0.5em)) rotate(180deg)', /* -10px, -15px */
    expected: 'matrix(1, 0, 0, 1, 65, 35.25)' },

  // scale
  { start: 'scale(2)', end: 'none',
    expected_uncomputed: 'scale(1.75)',
    expected: 'matrix(1.75, 0, 0, 1.75, 0, 0)' },
  { start: 'none', end: 'scale(0.4)',
    expected_uncomputed: 'scale(0.85)',
    expected: 'matrix(0.85, 0, 0, 0.85, 0, 0)',
    round_error_ok: true },
  { start: 'scale(2)', end: 'scale(-2)',
    expected_uncomputed: 'scale(1)',
    expected: 'matrix(1, 0, 0, 1, 0, 0)' },
  { start: 'scale(2)', end: 'scale(-6)',
    expected_uncomputed: 'scale(0)',
    expected: 'matrix(0, 0, 0, 0, 0, 0)' },
  { start: 'scale(2, 0.4)', end: 'none',
    expected_uncomputed: 'scale(1.75, 0.55)',
    expected: 'matrix(1.75, 0, 0, 0.55, 0, 0)',
    round_error_ok: true },
  { start: 'scaleX(3)', end: 'none',
    expected_uncomputed: 'scaleX(2.5)',
    expected: 'matrix(2.5, 0, 0, 1, 0, 0)' },
  { start: 'scaleY(5)', end: 'none',
    expected_uncomputed: 'scaleY(4)',
    expected: 'matrix(1, 0, 0, 4, 0, 0)' },
  { start: 'scaleZ(5)', end: 'none',
    expected_uncomputed: 'scaleZ(4)',
    expected: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1)' },
  { start: 'none', end: 'scale3D(5, 5, 5)',
    expected_uncomputed: 'scale3D(2, 2, 2)',
    expected: 'matrix3d(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1)' },

  // skew
  { start: 'skewX(45deg)', end: 'none',
    expected_uncomputed: 'skewX(33.75deg)' },
  { start: 'skewY(45deg)', end: 'none',
    expected_uncomputed: 'skewY(33.75deg)' },
  { start: 'skew(45deg)', end: 'none',
    expected_uncomputed: 'skew(33.75deg)' },
  { start: 'skew(45deg, 45deg)', end: 'none',
    expected_uncomputed: 'skew(33.75deg, 33.75deg)' },
  { start: 'skewX(45deg)', end: 'skewX(-45deg)',
    expected_uncomputed: 'skewX(22.5deg)' },
  { start: 'skewX(0)', end: 'skewX(-45deg)',
    expected_uncomputed: 'skewX(-11.25deg)' },
  { start: 'skewY(45deg)', end: 'skewY(-45deg)',
    expected_uncomputed: 'skewY(22.5deg)' },

  // matrix : skewX
  { start: 'matrix(1, 0, 3, 1, 0, 0)', end: 'none',
    expected: 'matrix(1, 0, ' + 3 * 0.75 + ', 1, 0, 0)',
    round_error_ok: true },
  { start: 'skewX(0)', end: 'skewX(-45deg) translate(0)',
    expected_uncomputed: 'skewX(-11.25deg) translate(0)' },
  // matrix : rotate
  { start: 'rotate(-30deg)', end: 'matrix(0, 1, -1, 0, 0, 0)',
    expected: 'matrix(1, 0, 0, 1, 0, 0)',
    round_error_ok: true },
  { start: 'rotate(-30deg) translateX(0)',
    end: 'translateX(0) rotate(-90deg)',
    expected: computeMatrix('rotate(-45deg)'),
    round_error_ok: true },
  // extended shorter transform list
  { start: 'skewY(60deg)', end: 'skewY(-60deg) translateX(0)',
    expected_uncomputed: 'skewY(30deg) translateX(0)' },


  // matrix decomposition

  // Four pairs of the same matrix expressed different ways.
  { start: 'matrix(-1, 0, 0, -1, 0, 0)', /* rotate(180deg) */
    end: 'matrix(1, 0, 0, 1, 0, 0)',
    expected: computeMatrix('rotate(135deg)') },
  { start: 'scale(-1)', end: 'none',
    expected_uncomputed: 'scale(-0.5)',
    expected: 'matrix(-0.5, 0, 0, -0.5, 0, 0)' },
  { start: 'rotate(180deg)', end: 'none',
    expected_uncomputed: 'rotate(135deg)' },
  { start: 'rotate(-180deg)', end: 'none',
    expected_uncomputed: 'rotate(-135deg)',
    expected: computeMatrix('rotate(225deg)') },

  // matrix followed by scale
  { start: 'matrix(2, 0, 0, 2, 10, 20) scale(2)',
    end: 'none',
    expected: 'matrix(3.0625, 0, 0, 3.0625, 7.5, 15)' },

  // ... and a bunch of similar possibilities.  The spec isn't settled
  // here; there are multiple options.  See:
  // http://lists.w3.org/Archives/Public/www-style/2010Jun/0602.html
  { start: 'matrix(-1, 0, 0, 1, 0, 0)', /* scaleX(-1) */
    end: 'matrix(1, 0, 0, 1, 0, 0)',
    expected: computeMatrix('scaleX(-0.5)') },

  { start: 'matrix(1, 0, 0, -1, 0, 0)', /* rotate(-180deg) scaleX(-1) */
    end: 'matrix(1, 0, 0, 1, 0, 0)',
    expected: computeMatrix('rotate(-135deg) scaleX(-0.5)') },

  { start: 'matrix(0, 1, 1, 0, 0, 0)', /* rotate(-90deg) scaleX(-1) */
    end: 'matrix(1, 0, 0, 1, 0, 0)',
    expected: computeMatrix('rotate(-67.5deg) scaleX(-0.5)') },

  { start: 'matrix(0, -1, 1, 0, 0, 0)', /* rotate(-90deg) */
    end: 'matrix(1, 0, 0, 1, 0, 0)',
    expected: computeMatrix('rotate(-67.5deg)') },

  { start: 'matrix(0, 1, -1, 0, 0, 0)', /* rotate(90deg) */
    end: 'matrix(1, 0, 0, 1, 0, 0)',
    expected: computeMatrix('rotate(67.5deg)') },

  { start: 'matrix(0, -1, -1, 0, 0, 0)', /* rotate(90deg) scaleX(-1) */
    end: 'matrix(1, 0, 0, 1, 0, 0)',
    expected: computeMatrix('rotate(67.5deg) scaleX(-0.5)') },

  // Similar decomposition tests, but with skewX.  I checked visually
  // that the sign of the skew was correct by checking visually that
  // the animations in
  // https://dbaron.org/css/test/2010/transition-negative-determinant
  // don't flip when they finish, and then wrote tests corresponding
  // to the current code's behavior.
  // ... start with four with positive determinants
  { start: 'none',
    end: 'matrix(1, 0, 1.5, 1, 0, 0)',
    /* skewX(atan(1.5)) */
    expected: 'matrix(1, 0, ' + 1.5 * 0.25 + ', 1, 0, 0)',
    round_error_ok: true },
  { start: 'none',
    end: 'matrix(-1, 0, 2, -1, 0, 0)',
            /* rotate(180deg) skewX(atan(-2)) */
    expected: computeMatrix('rotate(45deg) matrix(1, 0, ' + -2 * 0.25 + ', 1, 0, 0)'),
    round_error_ok: true },
  { start: 'none',
    end: 'matrix(0, -1, 1, -3, 0, 0)',
            /* rotate(-90deg) skewX(atan(3)) */
    expected: computeMatrix('rotate(-22.5deg) matrix(1, 0, ' + 3 * 0.25 + ', 1, 0, 0)'),
    round_error_ok: true },
  { start: 'none',
    end: 'matrix(0, 1, -1, 4, 0, 0)',
            /* rotate(90deg) skewX(atan(4)) */
    expected: computeMatrix('rotate(22.5deg) matrix(1, 0, ' + 4 * 0.25 + ', 1, 0, 0)'),
    round_error_ok: true },
  // and then four with negative determinants
  { start: 'none',
    end: 'matrix(1, 0, 1, -1, 0, 0)',
            /* rotate(-180deg) skewX(atan(-1)) scaleX(-1) */
    expected: computeMatrix('rotate(-45deg) matrix(1, 0, ' + -1 * 0.25 + ', 1, 0, 0) scaleX(0.5)'),
    round_error_ok: true },
  { start: 'none',
    end: 'matrix(-1, 0, -1, 1, 0, 0)',
            /* skewX(atan(-1)) scaleX(-1) */
    expected: computeMatrix('matrix(1, 0, ' + -1 * 0.25 + ', 1, 0, 0) scaleX(0.5)') },
  { start: 'none',
    end: 'matrix(0, 1, 1, -2, 0, 0)',
            /* rotate(-90deg) skewX(atan(2)) scaleX(-1) */
    expected: computeMatrix('rotate(-22.5deg) matrix(1, 0, ' + 2 * 0.25 + ', 1, 0, 0) scaleX(0.5)'),
    round_error_ok: true },
  { start: 'none',
    end: 'matrix(0, -1, -1, 0.5, 0, 0)',
            /* rotate(90deg) skewX(atan(0.5)) scaleX(-1) */
    expected: computeMatrix('rotate(22.5deg) matrix(1, 0, ' + 0.5 * 0.25 + ', 1, 0, 0) scaleX(0.5)'),
    round_error_ok: true },

  // lists
  { start: 'translate(10px) skewY(45deg)',
    end: 'translate(30px) skewY(-45deg)',
    expected_uncomputed: 'translate(15px) skewY(22.5deg)' },
  { start: 'skewY(45deg) rotate(90deg)',
    end: 'skewY(-45deg) rotate(90deg)',
    expected_uncomputed: 'skewY(22.5deg) rotate(90deg)' },
  { start: 'skewX(45deg) rotate(90deg)',
    end: 'skewX(-45deg) rotate(90deg)',
    expected_uncomputed: 'skewX(22.5deg) rotate(90deg)' },

  // extended lists
  { start: 'skewY(45deg) rotate(90deg) translate(0)',
    end: 'skewY(-45deg) rotate(90deg)',
    expected_uncomputed: 'skewY(22.5deg) rotate(90deg) translate(0)' },
  { start: 'skewX(-60deg) rotate(90deg) translate(0)',
    end: 'skewX(60deg) rotate(90deg)',
    expected_uncomputed: 'skewX(-30deg) rotate(90deg) translate(0)' },
];

// We intentionally use a non-default reference-box so we always serialize it.
// Therefore, we can reuse these tests for clip-path and shape-outside.
// Bug 1313619: Add some tests for two basic shapes with an explicit
// reference-box and a default one, for each property (because they use
// different default reference-box).
const basicShapesTests = [
  { start: "none", end: "none",
    expected: ["none"] },
  // none to shape
  { start: "none",
    end: "circle(500px at 500px 500px) content-box",
    expected: ["circle", ["500px at 500px 500px"], "content-box"]
  },
  { start: "none",
    end: "ellipse(500px 500px at 500px 500px) content-box",
    expected: ["ellipse", ["500px 500px at 500px 500px"], "content-box"]
  },
  { start: "none",
    end: "polygon(evenodd, 500px 500px, 500px 500px) content-box",
    expected: ["polygon", ["evenodd, 500px 500px, 500px 500px"], "content-box"]
  },
  { start: "none",
    end: "inset(500px 500px 500px 500px round 500px 500px) content-box",
    expected: ["inset", ["500px round 500px"], "content-box"]
  },
  // matching functions
  { start: "circle(100px)", end: "circle(500px)",
    expected: ["circle", ["200px"]] },
  { start: "ellipse(100px 100px)", end: "ellipse(500px 500px)",
    expected: ["ellipse", ["200px 200px"]] },
  { start: "circle(100px at 100px 100px) content-box",
    end: "circle(500px at 500px 500px) content-box",
    expected: ["circle", ["200px at 200px 200px"], "content-box"]
  },
  { start: "ellipse(100px 100px at 100px 100px) content-box",
    end: "ellipse(500px 500px at 500px 500px) content-box",
    expected: ["ellipse", ["200px 200px at 200px 200px"], "content-box"]
  },
  { start: "polygon(evenodd, 100px 100px, 100px 100px) content-box",
    end: "polygon(evenodd, 500px 500px, 500px 500px) content-box",
    expected: ["polygon", ["evenodd, 200px 200px, 200px 200px"], "content-box"]
  },
  { start: "inset(100px 100px 100px 100px round 100px 100px) content-box",
    end: "inset(500px 500px 500px 500px round 500px 500px) content-box",
    expected: ["inset", ["200px round 200px"], "content-box"]
  },
  // matching functions percentage
  { start: "circle(100%)", end: "circle(500%)",
    expected: ["circle", ["200%"]] },
  { start: "ellipse(100% 100%)", end: "ellipse(500% 500%)",
    expected: ["ellipse", ["200% 200%"]] },
  { start: "circle(100% at 100% 100%) content-box",
    end: "circle(500% at 500% 500%) content-box",
    expected: ["circle", ["200% at 200% 200%"], "content-box"]
  },
  { start: "ellipse(100% 100% at 100% 100%) content-box",
    end: "ellipse(500% 500% at 500% 500%) content-box",
    expected: ["ellipse", ["200% 200% at 200% 200%"], "content-box"]
  },
  { start: "polygon(evenodd, 100% 100%, 100% 100%) content-box",
    end: "polygon(evenodd, 500% 500%, 500% 500%) content-box",
    expected: ["polygon", ["evenodd, 200% 200%, 200% 200%"], "content-box"]
  },
  { start: "inset(100% 100% 100% 100% round 100% 100%) content-box",
    end: "inset(500% 500% 500% 500% round 500% 500%) content-box",
    expected: ["inset", ["200% round 200%"], "content-box"] },
  // matching functions with calc() values
  { start: "circle(calc(80px + 20px))", end: "circle(calc(200px + 300px))",
    expected: ["circle", ["200px"]] },
  { start: "circle(calc(80% + 20%))", end: "circle(calc(200% + 300%))",
    expected: ["circle", ["200%"]] },
  { start: "circle(calc(10px + 20%))", end: "circle(calc(50px + 40%))",
    expected: ["circle", ["calc(25% + 20px)"]] },
  // matching functions with interpolation between percentage/pixel values
  { start: "circle(20px)", end: "circle(100%)",
    expected: ["circle", ["calc(25% + 15px)"]] },
  { start: "ellipse(100% 100px at 8px 20%) content-box",
    end:   "ellipse(40px 4% at 80% 60px) content-box",
    expected: ["ellipse", ["calc(75% + 10px) calc(1% + 75px) at " +
                           "calc(20% + 6px) calc(15% + 15px)"],
               "content-box"] },
  // no interpolation for keywords
  { start: "circle()", end: "circle(50px)",
    expected: ["circle", ["50px"]] },
  { start: "circle(closest-side)", end: "circle(500px)",
    expected: ["circle", ["500px"]] },
  { start: "circle(farthest-side)", end: "circle(500px)",
    expected: ["circle", ["500px"]] },
  { start: "circle(500px)", end: "circle(farthest-side)",
    expected: ["circle", ["farthest-side"]]},
  { start: "circle(500px)", end: "circle(closest-side)",
    expected: ["circle", [""]]},
  { start: "ellipse()", end: "ellipse(50px 50px)",
    expected: ["ellipse", ["50px 50px"]] },
  { start: "ellipse(closest-side closest-side)", end: "ellipse(500px 500px)",
    expected: ["ellipse", ["500px 500px"]] },
  { start: "ellipse(farthest-side closest-side)", end: "ellipse(500px 500px)",
    expected: ["ellipse", ["500px 500px"]] },
  { start: "ellipse(farthest-side farthest-side)", end: "ellipse(500px 500px)",
    expected: ["ellipse", ["500px 500px"]] },
  { start: "ellipse(500px 500px)", end: "ellipse(farthest-side farthest-side)",
    expected: ["ellipse", ["farthest-side farthest-side"]] },
  { start: "ellipse(500px 500px)", end: "ellipse(closest-side closest-side)",
    expected: ["ellipse", [""]] },
  // mismatching boxes
  { start: "circle(100px at 100px 100px) border-box",
    end: "circle(500px at 500px 500px) content-box",
    expected: ["circle", ["500px at 500px 500px"], "content-box"]
  },
  { start: "ellipse(100px 100px at 100px 100px) border-box",
    end: "ellipse(500px 500px at 500px 500px) content-box",
    expected: ["ellipse", ["500px 500px at 500px 500px"], "content-box"]
  },
  { start: "polygon(evenodd, 100px 100px, 100px 100px) border-box",
    end: "polygon(evenodd, 500px 500px, 500px 500px) content-box",
    expected: ["polygon", ["evenodd, 500px 500px, 500px 500px"], "content-box"]
  },
  { start: "inset(100px 100px 100px 100px round 100px 100px) border-box",
    end: "inset(500px 500px 500px 500px round 500px 500px) content-box",
    expected: ["inset", ["500px round 500px"], "content-box"]
  },
  // mismatching functions
  { start: "circle(100px at 100px 100px) content-box",
    end: "ellipse(500px 500px at 500px 500px) content-box",
    expected: ["ellipse", ["500px 500px at 500px 500px"], "content-box"]
  },
  { start: "inset(0px round 20px)", end: "ellipse(500px 500px)",
    expected: ["ellipse", ["500px 500px"]]
  },
  // shape to reference box
  { start: "circle(20px)", end: "content-box", expected: ["content-box"] },
  { start: "content-box", end: "circle(20px)", expected: ["circle", ["20px"]] },
  // url to shape
  { start: "circle(20px)", end: "url(http://localhost/a.png)", expected: ["url", ["\"http://localhost/a.png\""]] },
  { start: "url(http://localhost/a.png)", end: "circle(20px)", expected: ["circle", ["20px"]] },
  // url to none
  { start: "none", end: "url(http://localhost/a.png)", expected: ["url", ["\"http://localhost/a.png\""]] },
  { start: "http://localhost/a.png", end: "none", expected: ["none"] },
];

const basicShapesWithFragmentUrlTests = [
  // Fragment url to shape
  { start: "circle(20px)", end: "url('#a')", expected: ["url", ["\"#a\""]] },
  { start: "url('#a')", end: "circle(20px)", expected: ["circle", ["20px"]] },
  // Fragment url to none
  { start: "none", end: "url('#a')", expected: ["url", ["\"#a\""]] },
  { start: "url('#a')", end: "none", expected: ["none"] },
];

// We have a lot of tests in web-platform-tests already, so here we only test
// basic interpolation cases.
const pathFunctionTests = [
  { start: "none", end: "none",
    expected: ["none"] },
  // none to path
  { start: "none",
    end: "path('M 100 100')",
    expected: ["path"'"M 100 100"']
  },
  // path to none
  { start: "path('M 100 100')",
    end: "none",
    expected: ["none"]
  },
  // mismatch
  {
    start: "path('M 0 0 H 100 H 200')",
    end: "path('M 0 0 H 500')",
    expected: ["path"'"M 0 0 H 500"']
  },
  {
    start: "path('M 0 0 V 100')",
    end: "path('M 0 0 H 500')",
    expected: ["path"'"M 0 0 H 500"']
  },
  // match
  {
    start: "path('M 100 100')",
    end: "path('M 100 500')",
    expected: ["path"'"M 100 200"']
  },
  {
    start: "path('M 10 10 L 100 100')",
    end: "path('M 10 10 L 100 500')",
    expected: ["path"'"M 10 10 L 100 200"']
  },
  {
    start: "path('M 10 10 H 100')",
    end: "path('M 10 10 H 500')",
    expected: ["path"'"M 10 10 H 200"']
  },
  {
    start: "path('M 10 10 V 100')",
    end: "path('M 10 10 V 500')",
    expected: ["path"'"M 10 10 V 200"']
  },
  {
    start: "path('M 10 10 C 32 42 52 62 120 2200')",
    end: "path('M 10 10 C 40 50 60 70 200 3000')",
    expected: ["path"'"M 10 10 C 34 44 54 64 140 2400"']
  },
  {
    start: "path('M 10 10 S 45 67 89 123')",
    end: "path('M 10 10 S 61 51 113 99')",
    expected: ["path"'"M 10 10 S 49 63 95 117"']
  },
  {
    start: "path('M 10 10 Q 32 42 120 2200')",
    end: "path('M 10 10 Q 40 50 200 3000')",
    expected: ["path"'"M 10 10 Q 34 44 140 2400"']
  },
  {
    start: "path('M 10 10 T 100 200')",
    end: "path('M 10 10 T 500 280')",
    expected: ["path"'"M 10 10 T 200 220"']
  },
  {
    start: "path('M 10 10 A 10 20 30 0 1 140 450')",
    end: "path('M 10 10 A 50 60 70 0 1 380 290')",
    expected: ["path"'"M 10 10 A 20 30 40 0 1 200 410"']
  },
  {
    start: "path('M 10 10 A 10 20 30 1 0 140 450')",
    end: "path('M 10 10 A 50 60 70 0 1 380 290')",
    expected: ["path"'"M 10 10 A 20 30 40 1 0 200 410"']
  },
  // mix relative and absolute coordinates
  {
    start: "path('m 10 20 h 30 v 60 h 10 v -10 l 110 60')",
    // =="path('M 10 20 H 40 V 80 H 50 V 70 L 160 130')"
    end: "path('M 130 140 H 120 V 160 H 130 V 150 L 200 170')",
    expected: ["path"'"M 40 50 H 60 V 100 H 70 V 90 L 170 140"']
  },
];

const clipPathPathFunctionTests = [
  // match fill-rule
  {
    start: "path(nonzero, 'M 100 100')",
    end: "path(nonzero, 'M 100 500')",
    expected: ["path"'"M 100 200"']
  },
  {
    start: "path(evenodd, 'M 100 100')",
    end: "path(evenodd, 'M 100 500')",
    expected: ["path"'evenodd, "M 100 200"']
  },
  // mismatch fill-rule
  {
    start: "path(nonzero, 'M 100 100')",
    end: "path(evenodd, 'M 100 500')",
    expected: ["path"'evenodd, "M 100 500"']
  },
];

var filterTests = [
  { start: "none", end: "none",
    expected: ["none"] },
  // function from none (number/length)
  { start: "none", end: "brightness(0.5)",
    expected: ["brightness", 0.875] },
  { start: "none", end: "contrast(0.5)",
    expected: ["contrast", 0.875] },
  { start: "none", end: "grayscale(0.5)",
    expected: ["grayscale", 0.125] },
  { start: "none", end: "invert(0.5)",
    expected: ["invert", 0.125] },
  { start: "none", end: "opacity(0.5)",
    expected: ["opacity", 0.875] },
  { start: "none", end: "saturate(0.5)",
    expected: ["saturate", 0.875] },
  { start: "none", end: "sepia(0.5)",
    expected: ["sepia", 0.125] },
  { start: "none", end: "blur(50px)",
    expected: ["blur", 12.5] },
  // function to none (number/length)
  { start: "brightness(0.5)", end: "none",
    expected: ["brightness", 0.625] },
  { start: "contrast(0.5)", end: "none",
    expected: ["contrast", 0.625] },
  { start: "grayscale(0.5)", end: "none",
    expected: ["grayscale", 0.375] },
  { start: "invert(0.5)", end: "none",
    expected: ["invert", 0.375] },
  { start: "opacity(0.5)", end: "none",
    expected: ["opacity", 0.625] },
  { start: "saturate(0.5)", end: "none",
    expected: ["saturate", 0.625] },
  { start: "sepia(0.5)", end: "none",
    expected: ["sepia", 0.375] },
  { start: "blur(50px)", end: "none",
    expected: ["blur", 37.5] },
  // function to same function (number/length)
  { start: "brightness(0.25)", end: "brightness(0.75)",
    expected: ["brightness", 0.375] },
  { start: "contrast(0.25)", end: "contrast(0.75)",
    expected: ["contrast", 0.375] },
  { start: "grayscale(0.25)", end: "grayscale(0.75)",
    expected: ["grayscale", 0.375] },
  { start: "invert(0.25)", end: "invert(0.75)",
    expected: ["invert", 0.375] },
  { start: "opacity(0.25)", end: "opacity(0.75)",
    expected: ["opacity", 0.375] },
  { start: "saturate(0.25)", end: "saturate(0.75)",
    expected: ["saturate", 0.375] },
  { start: "sepia(0.25)", end: "sepia(0.75)",
    expected: ["sepia", 0.375] },
  { start: "blur(25px)", end: "blur(75px)",
    expected: ["blur", 37.5] },
  // function to same function (percent)
  { start: "brightness(25%)", end: "brightness(75%)",
    expected: ["brightness", 0.375] },
  { start: "contrast(25%)", end: "contrast(75%)",
    expected: ["contrast", 0.375] },
  { start: "grayscale(25%)", end: "grayscale(75%)",
    expected: ["grayscale", 0.375] },
  { start: "invert(25%)", end: "invert(75%)",
    expected: ["invert", 0.375] },
  { start: "opacity(25%)", end: "opacity(75%)",
    expected: ["opacity", 0.375] },
  { start: "saturate(25%)", end: "saturate(75%)",
    expected: ["saturate", 0.375] },
  { start: "sepia(25%)", end: "sepia(75%)",
    expected: ["sepia", 0.375] },
  // function to same function (percent, number/length)
  { start: "brightness(0.25)", end: "brightness(75%)",
    expected: ["brightness", 0.375] },
  { start: "contrast(25%)", end: "contrast(0.75)",
    expected: ["contrast", 0.375] },
  // hue-rotate with different angle values
  { start: "hue-rotate(0deg)", end: "hue-rotate(720deg)",
    expected: ["hue-rotate""180deg"] },
  { start: "hue-rotate(0rad)", end: "hue-rotate("+4*Math.PI+"rad)",
    expected: ["hue-rotate""180deg"] },
  { start: "hue-rotate(0grad)", end: "hue-rotate(800grad)",
    expected: ["hue-rotate""180deg"] },
  { start: "hue-rotate(0turn)", end: "hue-rotate(2turn)",
    expected: ["hue-rotate""180deg"] },
  { start: "hue-rotate(0deg)", end: "hue-rotate("+4*Math.PI+"rad)",
    expected: ["hue-rotate""180deg"] },
  { start: "hue-rotate(0turn)", end: "hue-rotate(800grad)",
    expected: ["hue-rotate""180deg"] },
  { start: "hue-rotate(0grad)", end: "hue-rotate("+4*Math.PI+"rad)",
    expected: ["hue-rotate""180deg"] },
  { start: "hue-rotate(0grad)", end: "hue-rotate(0turn)",
    expected: ["hue-rotate""0deg"] },
  // multiple matching functions, same length
  { start: "contrast(25%) brightness(0.25) blur(25px) sepia(75%)",
    end: "contrast(75%) brightness(0.75) blur(75px) sepia(25%)",
    expected: ["contrast", 0.375, "brightness", 0.375, "blur", 37.5, "sepia", 0.625] },
  { start: "invert(25%) brightness(0.25) blur(25px) invert(50%) brightness(0.5) blur(50px)",
    end: "invert(75%) brightness(0.75) blur(75px)",
    expected: ["invert", 0.375, "brightness", 0.375, "blur", 37.5, "invert", 0.375, "brightness", 0.625, "blur", 37.5] },
  // multiple matching functions, different length
  { start: "contrast(25%) brightness(0.5) blur(50px)",
    end: "contrast(75%)",
    expected: ["contrast", 0.375, "brightness", 0.625, "blur", 37.5] },
  // mismatching filter functions
  { start: "contrast(0%)", end: "blur(10px)",
    expected: ["blur", 10] },
  // not supported interpolations
  { start: "none", end: "url('#b')",
    expected: ["url""\"#b\""] },
  { start: "url('#a')", end: "none",
    expected: ["none"] },
  { start: "url('#a')", end: "url('#b')",
    expected: ["url""\"#b\""] },
  { start: "url('#a')", end: "blur(10px)",
    expected: ["blur", 10] },
  { start: "blur(10px)", end: "url('#a')",
    expected: ["url""\"#a\""] },
  { start: "blur(0px) url('#a')", end: "blur(20px)",
    expected: ["blur", 20] },
  { start: "blur(0px)", end: "blur(20px) url('#a')",
    expected: ["blur", 20, "url""\"#a\""] },
  { start: "contrast(0.25) brightness(0.25) blur(25px)",
    end: "contrast(0.75) url('#a')",
    expected: ["contrast", 0.75, "url""\"#a\""] },
  { start: "contrast(0.25) brightness(0.25) blur(75px)",
    end: "brightness(0.75) contrast(0.75) blur(25px)",
    expected: ["brightness", 0.75, "contrast", 0.75, "blur", 25] },
  { start: "contrast(0.25) brightness(0.25) blur(25px)",
    end: "contrast(0.75) brightness(0.75) contrast(0.75)",
    expected: ["contrast", 0.75, "brightness", 0.75, "contrast", 0.75] },
  // drop-shadow animation
  { start: "none",
    end: "drop-shadow(rgb(0, 0, 0) 4px 4px 0px)",
    expected: ["drop-shadow""rgba(0, 0, 0, 0.25) 1px 1px 0px"] },
  { start: "drop-shadow(rgb(0, 0, 0) 0px 0px 0px)",
    end: "drop-shadow(rgb(0, 0, 0) 4px 4px 0px)",
    expected: ["drop-shadow""rgb(0, 0, 0) 1px 1px 0px"] },
  { start: "drop-shadow(#038000 4px 4px)",
    end: "drop-shadow(8px 8px 8px red)",
    expected: ["drop-shadow""rgb(66, 96, 0) 5px 5px 2px"] },
  { start: "blur(25px) drop-shadow(8px 8px)",
    end: "blur(75px)",
    expected: ["blur", 37.5, "drop-shadow""rgba(0, 0, 0, 0.75) 6px 6px 0px"] },
  { start: "blur(75px)",
    end: "blur(25px) drop-shadow(8px 8px)",
    expected: ["blur", 62.5, "drop-shadow""rgba(0, 0, 0, 0.25) 2px 2px 0px"] },
  { start: "drop-shadow(2px 2px blue)",
    end: "none",
    expected: ["drop-shadow""rgba(0, 0, 255, 0.75) 1.5px 1.5px 0px"] },
];

var prop;
for (prop in supported_properties) {
  // Test that prop is in the property database.
  ok(prop in gCSSProperties, "property " + prop + " in gCSSProperties");

  // Test that the entry has at least one test function.
  ok(supported_properties[prop].length > 0,
     "property " + prop + " must have at least one test function");
}

// Return a consistent sampling of |count| values out of |array|.
function sample_array(array, count) {
  if (count <= 0) {
    ok(false, "unexpected count");
    return [];
  }
  var ratio = array.length / count;
  if (ratio <= 1) {
    return array;
  }
  var result = new Array(count);
  for (let i = 0; i < count; ++i) {
    result[i] = array[Math.floor(i * ratio)];
  }
  return result;
}

// Test that transitions don't do anything (i.e., aren't supported) on
// the properties not in our test list above (and not transition
// properties themselves).
for (prop in gCSSProperties) {
  var prop_info = gCSSProperties[prop];
  if (!(prop in supported_properties) &&
      !skipped_transitionable_properties.includes(prop) &&
      prop_info.type != CSS_TYPE_TRUE_SHORTHAND &&
      prop_info.type != CSS_TYPE_LEGACY_SHORTHAND &&
      !("alias_for" in prop_info) &&
      !prop.match(/^transition-/) &&
      prop != "mask") {

    if ("prerequisites" in prop_info) {
      var prereqs = prop_info.prerequisites;
      for (var prereq in prereqs) {
        div.style.setProperty(prereq, prereqs[prereq], "");
      }
    }

    var all_values = prop_info.initial_values.concat(prop_info.other_values);

    if (all_values.length > 50) {
      // Since we're using an O(N^2) algorithm here, reduce the list of
      // values that we want to test.  (This test is really only testing
      // that somebody didn't make a property animatable without
      // modifying this test.  The odds of somebody doing that without
      // making at least one of the many pairs of values we have left
      // animatable seems pretty low, at least relative to the chance
      // that any pair of the values listed in property_database.js is
      // animatable.)
      //
      // That said, we still try to use all of the start of the list on
      // the assumption that the more basic values are likely to be at
      // the beginning of the list.
      all_values = [].concat(prop_info.initial_values.slice(0,2),
                             sample_array(prop_info.initial_values.slice(2), 6),
                             prop_info.other_values.slice(0, 10),
                             sample_array(prop_info.other_values.slice(10), 40));
    }

    var all_computed = [];
    for (var idx in all_values) {
      let val = all_values[idx];
      div.style.setProperty(prop, val, "");
      all_computed.push(cs.getPropertyValue(prop));
    }
    div.style.removeProperty(prop);

    div.style.setProperty("transition", prop + " 20s linear""");
    for (let i = 0; i < all_values.length; ++i) {
      for (let j = i + 1; j < all_values.length; ++j) {
        div.style.setProperty(prop, all_values[i], "");
        is(cs.getPropertyValue(prop), all_computed[i],
           "transitions not supported for property " + prop +
           " value " + all_values[i]);
        div.style.setProperty(prop, all_values[j], "");
        is(cs.getPropertyValue(prop), all_computed[j],
           "transitions not supported for property " + prop +
           " value " + all_values[j]);
      }
    }

    div.style.removeProperty("transition");
    div.style.removeProperty(prop);
    if ("prerequisites" in prop_info) {
      var prereqs = prop_info.prerequisites;
      for (var prereq in prereqs) {
        div.style.removeProperty(prereq);
      }
    }
  }
}

for (let zoomed of [true, false]) {
  info(`testing all supported properties (zoomed: ${zoomed})`);
  // Do 4-second linear transitions with -1 second transition delay and
  // linear timing function so that we can expect the transition to be
  // one quarter of the way through the value space right after changing
  // the property.
  div.style.setProperty("transition-duration""4s""");
  div.style.setProperty("transition-delay""-1s""");
  div.style.setProperty("transition-timing-function""linear""");
  div.style.setProperty("zoom", zoomed ? "2" : "1");
  for (prop in supported_properties) {
    info(`testing ${prop}`);
    var tinfo = supported_properties[prop];
    var prop_info = gCSSProperties[prop];

    isnot(prop_info.type, CSS_TYPE_TRUE_SHORTHAND,
          prop + " must not be a shorthand");
    if ("prerequisites" in prop_info) {
      var prereqs = prop_info.prerequisites;
      for (var prereq in prereqs) {
        // We don't want the 19px font-size prereq of line-height, since we
        // want to leave it 20px.
        if (prop != "line-height" || prereq != "font-size") {
          div.style.setProperty(prereq, prereqs[prereq], "");
        }
      }
    }

    for (var idx in tinfo) {
      tinfo[idx](prop);
    }

    // Make sure to unset the property and stop transitions on it.
    div.style.setProperty("transition-property""none""");
    div.style.removeProperty(prop);
    cs.getPropertyValue(prop);

    if ("prerequisites" in prop_info) {
      var prereqs = prop_info.prerequisites;
      for (var prereq in prereqs) {
        div.style.removeProperty(prereq);
      }
    }
  }
  div.style.removeProperty("transition");
  div.style.removeProperty("zoom");
}

function get_distance(prop, v1, v2)
{
  return SpecialPowers.DOMWindowUtils
           .computeAnimationDistance(div, prop, v1, v2);
}

function check_distance(prop, start, quarter, end)
{
  var sq = get_distance(prop, start, quarter);
  var se = get_distance(prop, start, end);
  var qe = get_distance(prop, quarter, end);

  ok(Math.abs((sq * 4 - se) / se) < 0.0001, "property '" + prop + "': distance " + sq + " from start '" + start + "' to quarter '" + quarter + "' should be quarter distance " + se + " from start '" + start + "' to end '" + end + "'");
  ok(Math.abs((qe * 4 - se * 3) / se) < 0.0001, "property '" + prop + "': distance " + qe + " from quarter '" + quarter + "' to end '" + end + "' should be three quarters distance " + se + " from start '" + start + "' to end '" + end + "'");
}

function test_length_transition(prop) {
  div.style.setProperty("transition-property""none""");
  div.style.setProperty(prop, "4px""");
  is(cs.getPropertyValue(prop), "4px",
     "length-valued property " + prop + ": computed value before transition");
  div.style.setProperty("transition-property", prop, "");
  div.style.setProperty(prop, "12px""");
  is(cs.getPropertyValue(prop), "6px",
     "length-valued property " + prop + ": interpolation of lengths");
  check_distance(prop, "4px""6px""12px");
}

function test_length_clamped(prop) {
  test_length_clamped_or_unclamped(prop, true);
}

function test_length_unclamped(prop) {
  test_length_clamped_or_unclamped(prop, false);
}

function test_length_clamped_or_unclamped(prop, is_clamped) {
  div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  div.style.setProperty("transition-property""none""");
  div.style.setProperty(prop, "0px""");
  let zero_val = cs.getPropertyValue(prop); // Flushes
  div.style.setProperty("transition-property", prop, "");
  div.style.setProperty(prop, "100px""");
  (is_clamped ? is : isnot)(cs.getPropertyValue(prop), zero_val,
     "length-valued property " + prop + ": clamping of negatives");
  div.style.setProperty("transition-timing-function""linear""");
}

// Test transition to/from the special 'flex-basis: content' keyword.
function test_flex_basis_content_transition(prop) {
  is(prop, "flex-basis""this test function should only be called for 'flex-basis'");

  // Test transition from length to 'content':
  div.style.setProperty("transition-property""none""");
  div.style.setProperty(prop, "8px""");
  is(cs.getPropertyValue(prop), "8px",
     "property " + prop + ": computed value before transition to 'content'");
  div.style.setProperty("transition-property", prop, "");
  div.style.setProperty(prop, "content""");
  is(cs.getPropertyValue(prop), "content",
     "property " + prop + ": transition to 'content' (should be discrete)");

  // Test transition from 'content' to length:
  div.style.setProperty("transition-property""none""");
  div.style.setProperty(prop, "content""");
  is(cs.getPropertyValue(prop), "content",
     "property " + prop + ": computed value before transition from 'content'");
  div.style.setProperty("transition-property", prop, "");
  div.style.setProperty(prop, "6px""");
  is(cs.getPropertyValue(prop), "6px",
     "property " + prop + ": transition from 'content' (should be discrete)");
}

// Test using float values in the range [0, 1] (e.g. opacity)
function test_float_zeroToOne_transition(prop) {
  div.style.setProperty("transition-property""none""");
  div.style.setProperty(prop, "0.3""");
  is(cs.getPropertyValue(prop), "0.3",
     "float-valued property " + prop + ": computed value before transition");
  div.style.setProperty("transition-property", prop, "");
  div.style.setProperty(prop, "0.8""");
  is(cs.getPropertyValue(prop), "0.425",
     "float-valued property " + prop + ": interpolation of floats");
  check_distance(prop, "0.3""0.425""0.8");
}

function test_float_zeroToOne_clamped(prop) {
  test_float_zeroToOne_clamped_or_unclamped(prop, true);
}
function test_float_zeroToOne_unclamped(prop) {
  test_float_zeroToOne_clamped_or_unclamped(prop, false);
}

function test_float_zeroToOne_clamped_or_unclamped(prop, is_clamped) {
  div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  div.style.setProperty("transition-property""none""");
  div.style.setProperty(prop, "0""");
  is(cs.getPropertyValue(prop), "0",
     "float-valued property " + prop + ": flush before clamping test");
  div.style.setProperty("transition-property", prop, "");
  div.style.setProperty(prop, "1""");
  (is_clamped ? is : isnot)(cs.getPropertyValue(prop), "0",
     "float-valued property " + prop + ": clamping of negatives");
  div.style.setProperty("transition-timing-function""linear""");
}

// Test using float values in the range [1, infinity)
function test_float_aboveOne_transition(prop) {
  div.style.setProperty("transition-property""none""");
  div.style.setProperty(prop, "1""");
  is(cs.getPropertyValue(prop), "1",
     "float-valued property " + prop + ": computed value before transition");
  div.style.setProperty("transition-property", prop, "");
  div.style.setProperty(prop, "2.1""");
  is(cs.getPropertyValue(prop), "1.275",
     "float-valued property " + prop + ": interpolation of floats");
  check_distance(prop, "1""1.275""2.1");
}

function test_float_aboveZero_clamped(prop) {
  div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  div.style.setProperty("transition-property""none""");
  div.style.setProperty(prop, "0""");
  is(cs.getPropertyValue(prop), "0",
     "float-valued property " + prop + ": flush before clamping test");
  div.style.setProperty("transition-property", prop, "");
  div.style.setProperty(prop, "5""");
  is(cs.getPropertyValue(prop), "0",
     "float-valued property " + prop + ": clamping of negatives");
  div.style.setProperty("transition-timing-function""linear""");
}

function test_percent_transition(prop) {
  div.style.setProperty("transition-property""none""");
  div.style.setProperty(prop, "25%""");
  var av = cs.getPropertyValue(prop);
  var a = any_unit_to_num(av);
  div.style.setProperty(prop, "75%""");
  var bv = cs.getPropertyValue(prop);
  var b = any_unit_to_num(bv);
  isnot(b, a, "different percentages (" + av + " and " + bv +
              ") should be different for " + prop);
  div.style.setProperty("transition-property", prop, "");
  div.style.setProperty(prop, "25%""");
  var res = cs.getPropertyValue(prop);
  is(any_unit_to_num(res) * 4, 3 * b + a,
     "percent-valued property " + prop + ": interpolation of percents: " +
     res + " should be a quarter of the way between " + bv + " and " + av);
  ok(has_num(res),
     "percent-valued property " + prop + ": percent computes to number");
  check_distance(prop, "25%""37.5%""75%");
}

function test_percent_clamped(prop) {
  test_percent_clamped_or_unclamped(prop, true);
}

function test_percent_unclamped(prop) {
  test_percent_clamped_or_unclamped(prop, false);
}

function test_percent_clamped_or_unclamped(prop, is_clamped) {
  div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  div.style.setProperty("transition-property""none""");
  div.style.setProperty(prop, "0%""");
  var zero_val = cs.getPropertyValue(prop); // flushes too
  div.style.setProperty("transition-property", prop, "");
  div.style.setProperty(prop, "150%""");
  (is_clamped ? is : isnot)(cs.getPropertyValue(prop), zero_val,
     "percent-valued property " + prop + ": clamping of negatives");
  div.style.setProperty("transition-timing-function""linear""");
}

// FIXME: This doesn't deal well with properties for which the resolved value
// is not the used value, like stroke-dashoffset or stroke-width.
function test_length_percent_calc_transition(prop) {
  div.style.setProperty("transition-property""none""");
  div.style.setProperty(prop, "0%""");
  var av = cs.getPropertyValue(prop);
  var a = any_unit_to_num(av);
  div.style.setProperty(prop, "100%""");
  var bv = cs.getPropertyValue(prop);
  var b = any_unit_to_num(bv);
  div.style.setProperty(prop, "100px""");
  var cv = cs.getPropertyValue(prop);
  var c = any_unit_to_num(cv);
  isnot(b, a, "different percentages (" + av + " and " + bv +
              ") should be different for " + prop);

  div.style.setProperty(prop, "50%""");
  var v1v = cs.getPropertyValue(prop);
  is(any_unit_to_num(v1v) * 2, a + b,
     "computed value before transition for " + prop + ": '" +
     v1v + "' should be halfway " +
     "between '" + av + "' + and '" + bv + "'.");
  div.style.setProperty("transition-property", prop, "");
  div.style.setProperty(prop, "200px""");
  var v2v = cs.getPropertyValue(prop);
  is(any_unit_to_num(v2v) * 8, 5*a + 3*b + 4*c,
     "interpolation between length and percent for " + prop + ": '"
     + v2v + "'");

  div.style.setProperty("transition-property""none""");
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=97 H=92 G=94

¤ Dauer der Verarbeitung: 0.50 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge