layout/style/test/test_transitions_per_property.html

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 <!DOCTYPE HTML>
     2 <html>
     3 <!--
     4 https://bugzilla.mozilla.org/show_bug.cgi?id=435441
     5 -->
     6 <head>
     7   <title>Test for Bug 435441</title>
     8   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
     9   <script type="text/javascript" src="property_database.js"></script>
    10   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
    11   <style type="text/css">
    13   #display > p { margin-top: 0; margin-bottom: 0; }
    15   </style>
    16 </head>
    17 <body>
    18 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435441">Mozilla Bug 435441</a>
    20 <!--
    21   fixed-height container so percentage heights compute to different
    22   (i.e., nonzero) values
    23   fixed-width container so that percentages for margin-top and
    24   margin-bottom are all relative to the same size container (rather than
    25   one that depends on whether we're tall enough to need a scrollbar)
    27   Use a 20px font size and line-height so that percentage line-height
    28   and vertical-align doesn't accumulate rounding error.
    29   -->
    30 <div style="height: 50px; width: 300px; font-size: 20px; line-height: 20px">
    32 <div id="display">
    33 </div>
    35 <div id="transformTest" style="height:100px; width:200px; background-color:blue;">
    36 </div>
    38 </div>
    39 <pre id="test">
    40 <script type="application/javascript">
    42 /** Test for Bug 435441 **/
    44 SimpleTest.requestLongerTimeout(2);
    45 SimpleTest.waitForExplicitFinish();
    47 function has_num(str)
    48 {
    49     return !!String(str).match(/^([\d.]+)/);
    50 }
    52 function any_unit_to_num(str)
    53 {
    54     return Number(String(str).match(/^([\d.]+)/)[1]);
    55 }
    57 var FUNC_NEGATIVE = "cubic-bezier(0.25, -2, 0.75, 1)";
    58 var FUNC_OVERONE = "cubic-bezier(0.25, 0, 0.75, 3)";
    60 var supported_properties = {
    61     "border-bottom-left-radius": [ test_radius_transition ],
    62     "border-bottom-right-radius": [ test_radius_transition ],
    63     "border-top-left-radius": [ test_radius_transition ],
    64     "border-top-right-radius": [ test_radius_transition ],
    65     "-moz-box-flex": [ test_float_zeroToOne_transition,
    66                        test_float_aboveOne_transition,
    67                        test_float_zeroToOne_clamped ],
    68     "box-shadow": [ test_shadow_transition ],
    69     "-moz-column-count": [ test_pos_integer_or_auto_transition,
    70                            test_integer_at_least_one_clamping ],
    71     "-moz-column-gap": [ test_length_transition,
    72                          test_length_clamped ],
    73     "-moz-column-rule-color": [ test_color_transition,
    74                                 test_border_color_transition ],
    75     "-moz-column-rule-width": [ test_length_transition,
    76                                 test_length_clamped ],
    77     "-moz-column-width": [ test_length_transition,
    78                            test_length_clamped ],
    79     "-moz-image-region": [ test_rect_transition ],
    80     "-moz-outline-radius-bottomleft": [ test_radius_transition ],
    81     "-moz-outline-radius-bottomright": [ test_radius_transition ],
    82     "-moz-outline-radius-topleft": [ test_radius_transition ],
    83     "-moz-outline-radius-topright": [ test_radius_transition ],
    84     "-moz-text-decoration-color": [ test_color_transition,
    85                                     test_border_color_transition ],
    86     "background-color": [ test_color_transition ],
    87     "background-position": [ test_background_position_transition,
    88                              // FIXME: We don't currently test clamping,
    89                              // since background-position uses calc() as
    90                              // an intermediate form.
    91                              /* test_length_percent_pair_unclamped */ ],
    92     "background-size": [ test_background_size_transition,
    93                          // FIXME: We don't currently test clamping,
    94                          // since background-size uses calc() as an
    95                          // intermediate form.
    96                          /* test_length_percent_pair_clamped */ ],
    97     "border-bottom-color": [ test_color_transition,
    98                              test_border_color_transition ],
    99     "border-bottom-width": [ test_length_transition,
   100                              test_length_clamped ],
   101     "border-left-color": [ test_color_transition,
   102                            test_border_color_transition ],
   103     "border-left-width": [ test_length_transition,
   104                            test_length_clamped ],
   105     "border-right-color": [ test_color_transition,
   106                             test_border_color_transition ],
   107     "border-right-width": [ test_length_transition,
   108                             test_length_clamped ],
   109     "border-spacing": [ test_length_pair_transition,
   110                         test_length_pair_transition_clamped ],
   111     "border-top-color": [ test_color_transition,
   112                           test_border_color_transition ],
   113     "border-top-width": [ test_length_transition,
   114                            test_length_clamped ],
   115     "bottom": [ test_length_transition, test_percent_transition,
   116                 test_length_percent_calc_transition,
   117                 test_length_unclamped, test_percent_unclamped ],
   118     "clip": [ test_rect_transition ],
   119     "color": [ test_color_transition ],
   120     "fill": [ test_color_transition ],
   121     "fill-opacity" : [ test_float_zeroToOne_transition,
   122                        // opacity is clamped in computed style
   123                        // (not parsing/interpolation)
   124                        test_float_zeroToOne_clamped ],
   125     "filter" : [ test_filter_transition ],
   126     "flex-basis": [ test_length_transition, test_percent_transition,
   127                     test_length_clamped, test_percent_clamped ],
   128     "flex-grow": [ test_float_zeroToOne_transition,
   129                    test_float_aboveOne_transition ],
   130     "flex-shrink": [ test_float_zeroToOne_transition,
   131                      test_float_aboveOne_transition ],
   132     "flood-color": [ test_color_transition ],
   133     "flood-opacity" : [ test_float_zeroToOne_transition,
   134                         // opacity is clamped in computed style
   135                         // (not parsing/interpolation)
   136                         test_float_zeroToOne_clamped ],
   137     "font-size": [ test_length_transition, test_percent_transition,
   138                    test_length_percent_calc_transition,
   139                    test_length_clamped, test_percent_clamped ],
   140     "font-size-adjust": [ test_float_zeroToOne_transition,
   141                           test_float_aboveOne_transition,
   142                           /* FIXME: font-size-adjust treats zero specially */
   143                           /* test_float_zeroToOne_clamped */ ],
   144     "font-stretch": [ test_font_stretch ],
   145     "font-weight": [ test_font_weight ],
   146     "height": [ test_length_transition, test_percent_transition,
   147                 test_length_percent_calc_transition,
   148                 test_length_clamped, test_percent_clamped ],
   149     "left": [ test_length_transition, test_percent_transition,
   150               test_length_percent_calc_transition,
   151               test_length_unclamped, test_percent_unclamped ],
   152     "letter-spacing": [ test_length_transition, test_length_unclamped ],
   153     "lighting-color": [ test_color_transition ],
   154     // NOTE: when calc() is supported on 'line-height', we should add
   155     // test_length_percent_calc_transition.
   156     "line-height": [ test_length_transition, test_percent_transition,
   157                      test_length_clamped, test_percent_clamped ],
   158     "margin-bottom": [ test_length_transition, test_percent_transition,
   159                        test_length_percent_calc_transition,
   160                        test_length_unclamped, test_percent_unclamped ],
   161     "margin-left": [ test_length_transition, test_percent_transition,
   162                      test_length_percent_calc_transition,
   163                      test_length_unclamped, test_percent_unclamped ],
   164     "margin-right": [ test_length_transition, test_percent_transition,
   165                       test_length_percent_calc_transition,
   166                       test_length_unclamped, test_percent_unclamped ],
   167     "margin-top": [ test_length_transition, test_percent_transition,
   168                     test_length_percent_calc_transition,
   169                     test_length_unclamped, test_percent_unclamped ],
   170     "marker-offset": [ test_length_transition,
   171                        test_length_unclamped ],
   172     "max-height": [ test_length_transition, test_percent_transition,
   173                     test_length_percent_calc_transition,
   174                     test_length_clamped, test_percent_clamped ],
   175     "max-width": [ test_length_transition, test_percent_transition,
   176                    test_length_percent_calc_transition,
   177                    test_length_clamped, test_percent_clamped ],
   178     "min-height": [ test_length_transition, test_percent_transition,
   179                     test_length_percent_calc_transition,
   180                     test_length_clamped, test_percent_clamped ],
   181     "min-width": [ test_length_transition, test_percent_transition,
   182                    test_length_percent_calc_transition,
   183                    test_length_clamped, test_percent_clamped ],
   184     "opacity" : [ test_float_zeroToOne_transition,
   185                   // opacity is clamped in computed style
   186                   // (not parsing/interpolation)
   187                   test_float_zeroToOne_clamped ],
   188     "order": [ test_integer_transition ],
   189     "outline-color": [ test_color_transition ],
   190     "outline-offset": [ test_length_transition, test_length_unclamped ],
   191     "outline-width": [ test_length_transition, test_length_clamped ],
   192     "padding-bottom": [ test_length_transition, test_percent_transition,
   193                         test_length_percent_calc_transition,
   194                         test_length_clamped, test_percent_clamped ],
   195     "padding-left": [ test_length_transition, test_percent_transition,
   196                       test_length_percent_calc_transition,
   197                       test_length_clamped, test_percent_clamped ],
   198     "padding-right": [ test_length_transition, test_percent_transition,
   199                        test_length_percent_calc_transition,
   200                        test_length_clamped, test_percent_clamped ],
   201     "padding-top": [ test_length_transition, test_percent_transition,
   202                      test_length_percent_calc_transition,
   203                      test_length_clamped, test_percent_clamped ],
   204     "perspective": [ test_length_transition ],
   205     "perspective-origin": [ test_length_pair_transition,
   206                             test_length_percent_pair_transition,
   207                             test_length_percent_pair_unclamped ],
   208     "right": [ test_length_transition, test_percent_transition,
   209                test_length_percent_calc_transition,
   210                test_length_unclamped, test_percent_unclamped ],
   211     "stop-color": [ test_color_transition ],
   212     "stop-opacity" : [ test_float_zeroToOne_transition,
   213                        // opacity is clamped in computed style
   214                        // (not parsing/interpolation)
   215                        test_float_zeroToOne_clamped ],
   216     "stroke": [ test_color_transition ],
   217     "stroke-dasharray": [ test_dasharray_transition ],
   218     // NOTE: when calc() is supported on 'stroke-dashoffset', we should
   219     // add test_length_percent_calc_transition.
   220     "stroke-dashoffset": [ test_length_transition, test_percent_transition,
   221                            test_length_unclamped, test_percent_unclamped ],
   222     "stroke-miterlimit": [ test_float_aboveOne_transition,
   223                            test_float_aboveOne_clamped ],
   224     "stroke-opacity" : [ test_float_zeroToOne_transition,
   225                          // opacity is clamped in computed style
   226                          // (not parsing/interpolation)
   227                          test_float_zeroToOne_clamped ],
   228     // NOTE: when calc() is supported on 'stroke-width', we should add
   229     // test_length_percent_calc_transition.
   230     "stroke-width": [ test_length_transition, test_percent_transition,
   231                       test_length_clamped, test_percent_clamped ],
   232     "text-indent": [ test_length_transition, test_percent_transition,
   233                      test_length_percent_calc_transition,
   234                      test_length_unclamped, test_percent_unclamped ],
   235     "text-shadow": [ test_shadow_transition ],
   236     "top": [ test_length_transition, test_percent_transition,
   237              test_length_percent_calc_transition,
   238              test_length_unclamped, test_percent_unclamped ],
   239     "transform": [ test_transform_transition ],
   240     "transform-origin": [ test_length_pair_transition,
   241                           test_length_percent_pair_transition,
   242                           test_length_percent_pair_unclamped ],
   243     "vertical-align": [ test_length_transition, test_percent_transition,
   244                         test_length_percent_calc_transition,
   245                         test_length_unclamped, test_percent_unclamped ],
   246     "visibility": [ test_visibility_transition ],
   247     "width": [ test_length_transition, test_percent_transition,
   248                test_length_percent_calc_transition,
   249                test_length_clamped, test_percent_clamped ],
   250     "word-spacing": [ test_length_transition, test_length_unclamped ],
   251     "z-index": [ test_integer_transition, test_pos_integer_or_auto_transition ],
   252 };
   254 var div = document.getElementById("display");
   255 var OMTAdiv = document.getElementById("transformTest");
   256 var cs = getComputedStyle(div, "");
   257 var OMTACs = getComputedStyle(OMTAdiv, "");
   258 var winUtils = SpecialPowers.getDOMWindowUtils(window);
   260 function computeMatrix(v) {
   261   div.style.setProperty("transform", v, "");
   262   var result = cs.getPropertyValue("transform");
   263   div.style.removeProperty("transform");
   264   return result;
   265 }
   266 var c_rot_15 = computeMatrix("rotate(15deg)");
   267 is(c_rot_15.substring(0,6), "matrix", "should compute to matrix value");
   268 var c_rot_60 = computeMatrix("rotate(60deg)");
   269 is(c_rot_60.substring(0,6), "matrix", "should compute to matrix value");
   271 var transformTestIndex = 0;
   272 var transformTests = [
   273   // rotate
   274   { start: 'none', end: 'rotate(60deg)',
   275     expected_uncomputed: 'rotate(15deg)',
   276     expected: c_rot_15 },
   277   { start: 'rotate(0)', end: 'rotate(60deg)',
   278     expected_uncomputed: 'rotate(15deg)',
   279     expected: c_rot_15 },
   280   { start: 'rotate(0deg)', end: 'rotate(60deg)',
   281     expected_uncomputed: 'rotate(15deg)',
   282     expected: c_rot_15 },
   283   { start: 'none', end: c_rot_60,
   284     expected: c_rot_15 },
   285   { start: 'none', end: 'rotate(360deg)',
   286     expected_uncomputed: 'rotate(90deg)',
   287     expected: computeMatrix('rotate(90deg)') },
   288   { start: 'none', end: 'rotatez(360deg)',
   289     expected_uncomputed: 'rotate(90deg)',
   290     expected: computeMatrix('rotate(90deg)') },
   291   { start: 'none', end: 'rotate(720deg)',
   292     expected_uncomputed: 'rotate(180deg)',
   293     expected: computeMatrix('rotate(180deg)') },
   294   { start: 'none', end: 'rotate(720deg)',
   295     expected_uncomputed: 'rotatez(180deg)',
   296     expected: computeMatrix('rotate(180deg)') },
   297   { start: 'none', end: 'rotate(1080deg)',
   298     expected_uncomputed: 'rotate(270deg)',
   299     expected: computeMatrix('rotate(270deg)') },
   300   { start: 'none', end: 'rotate(1080deg)',
   301     expected_uncomputed: 'rotate(270deg)',
   302     expected: computeMatrix('rotatez(270deg)') },
   303   { start: 'none', end: 'rotate(1440deg)',
   304     expected_uncomputed: 'rotate(360deg)',
   305     expected: computeMatrix('scale(1)'),
   306     round_error_ok: true },
   307   { start: 'none', end: 'rotatey(60deg)',
   308     expected_uncomputed: 'rotatey(15deg)',
   309     expected: computeMatrix('rotatey(15deg)') },
   310   { start: 'none', end: 'rotatey(720deg)',
   311     expected_uncomputed: 'rotatey(180deg)',
   312     expected: computeMatrix('rotatey(180deg)') },
   313   { start: 'none', end: 'rotatex(60deg)',
   314     expected_uncomputed: 'rotatex(15deg)',
   315     expected: computeMatrix('rotatex(15deg)') },
   316   { start: 'none', end: 'rotatex(720deg)',
   317     expected_uncomputed: 'rotatex(180deg)',
   318     expected: computeMatrix('rotatex(180deg)') },
   320   // translate
   321   { start: 'translate(20px)', end: 'none',
   322     expected_uncomputed: 'translate(15px)',
   323     expected: 'matrix(1, 0, 0, 1, 15, 0)' },
   324   { start: 'translate(20px, 12px)', end: 'none',
   325     expected_uncomputed: 'translate(15px, 9px)',
   326     expected: 'matrix(1, 0, 0, 1, 15, 9)' },
   327   { start: 'translateX(-20px)', end: 'none',
   328     expected_uncomputed: 'translateX(-15px)',
   329     expected: 'matrix(1, 0, 0, 1, -15, 0)' },
   330   { start: 'translateY(-40px)', end: 'none',
   331     expected_uncomputed: 'translateY(-30px)',
   332     expected: 'matrix(1, 0, 0, 1, 0, -30)' },
   333   { start: 'translateZ(40px)', end: 'none',
   334     expected_uncomputed: 'translateZ(30px)',
   335     expected: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 30, 1)' },
   336   { start: 'none', end: 'translate3D(40px, 60px, -40px)',
   337     expected_uncomputed: 'translate3D(10px, 15px, -10px)',
   338     expected: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10, 15, -10, 1)' },
   339   // percentages are relative to 300px (width) and 50px (height)
   340   // per the prerequisites in property_database.js
   341   { start: 'translate(20%)', end: 'none',
   342     expected_uncomputed: 'translate(15%)',
   343     expected: 'matrix(1, 0, 0, 1, 45, 0)',
   344     round_error_ok: true },
   345   { start: 'translate(20%, 12%)', end: 'none',
   346     expected_uncomputed: 'translate(15%, 9%)',
   347     expected: 'matrix(1, 0, 0, 1, 45, 4.5)',
   348     round_error_ok: true },
   349   { start: 'translateX(-20%)', end: 'none',
   350     expected_uncomputed: 'translateX(-15%)',
   351     expected: 'matrix(1, 0, 0, 1, -45, 0)',
   352     round_error_ok: true },
   353   { start: 'translateY(-40%)', end: 'none',
   354     expected_uncomputed: 'translateY(-30%)',
   355     expected: 'matrix(1, 0, 0, 1, 0, -15)',
   356     round_error_ok: true,
   357     big_omta_round_error: true },
   358   { start: 'none', end: 'rotate(90deg) translate(20%, 20%) rotate(-90deg)',
   359     expected_uncomputed: 'rotate(22.5deg) translate(5%, 5%) rotate(-22.5deg)',
   360     round_error_ok: true },
   361   { start: 'none', end: 'rotate(-90deg) translate(20%, 20%) rotate(90deg)',
   362     expected_uncomputed: 'rotate(-22.5deg) translate(5%, 5%) rotate(22.5deg)',
   363     round_error_ok: true },
   364   // test percent translation using matrix decomposition
   365   { start: 'rotate(45deg) rotate(-45deg)',
   366     end: 'rotate(90deg) translate(20%, 20%) rotate(-90deg)',
   367     expected: 'matrix(1, 0, 0, 1, -2.5, 15)',
   368     round_error_ok: true },
   369   { start: 'rotate(45deg) rotate(-45deg)',
   370     end: 'rotate(-90deg) translate(20%, 20%) rotate(90deg)',
   371     expected: 'matrix(1, 0, 0, 1, 2.5, -15)',
   372     round_error_ok: true },
   373   // test calc() in translate
   374   // Note that font-size: is 20px, and that percentages are relative
   375   // to 300px (width) and 50px (height) per the prerequisites in
   376   // property_database.js
   377   { start: 'translateX(20%)', /* 60px */
   378     end: 'translateX(calc(10% + 1em))', /* 30px + 20px = 50px */
   379     expected_uncomputed: 'translateX(calc(17.5% + 0.25em))',
   380     expected: 'matrix(1, 0, 0, 1, 57.5, 0)',
   381     big_omta_round_error: true },
   382   { start: 'translate(calc(0.75 * 3em + 1.5 * 10%), calc(0.5 * 5em + 0.5 * 8%))', /* 90px, 52px */
   383     end: 'rotate(90deg) translateY(20%) rotate(90deg) translateY(calc(10% + 0.5em)) rotate(180deg)', /* -10px, -15px */
   384     expected: 'matrix(1, 0, 0, 1, 65, 35.25)',
   385     big_omta_round_error: true },
   387   // scale
   388   { start: 'scale(2)', end: 'none',
   389     expected_uncomputed: 'scale(1.75)',
   390     expected: 'matrix(1.75, 0, 0, 1.75, 0, 0)' },
   391   { start: 'none', end: 'scale(0.4)',
   392     expected_uncomputed: 'scale(0.85)',
   393     expected: 'matrix(0.85, 0, 0, 0.85, 0, 0)',
   394     round_error_ok: true },
   395   { start: 'scale(2)', end: 'scale(-2)',
   396     expected_uncomputed: 'scale(1)',
   397     expected: 'matrix(1, 0, 0, 1, 0, 0)' },
   398   { start: 'scale(2)', end: 'scale(-6)',
   399     expected_uncomputed: 'scale(0)',
   400     expected: 'matrix(0, 0, 0, 0, 0, 0)' },
   401   { start: 'scale(2, 0.4)', end: 'none',
   402     expected_uncomputed: 'scale(1.75, 0.55)',
   403     expected: 'matrix(1.75, 0, 0, 0.55, 0, 0)',
   404     round_error_ok: true },
   405   { start: 'scaleX(3)', end: 'none',
   406     expected_uncomputed: 'scaleX(2.5)',
   407     expected: 'matrix(2.5, 0, 0, 1, 0, 0)' },
   408   { start: 'scaleY(5)', end: 'none',
   409     expected_uncomputed: 'scaleY(4)',
   410     expected: 'matrix(1, 0, 0, 4, 0, 0)' },
   411   { start: 'scaleZ(5)', end: 'none',
   412     expected_uncomputed: 'scaleZ(4)',
   413     expected: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1)' },
   414   { start: 'none', end: 'scale3D(5, 5, 5)',
   415     expected_uncomputed: 'scale3D(2, 2, 2)',
   416     expected: 'matrix3d(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1)' },
   418   // skew
   419   { start: 'skewX(45deg)', end: 'none',
   420     expected_uncomputed: 'skewX(33.75deg)' },
   421   { start: 'skewY(45deg)', end: 'none',
   422     expected_uncomputed: 'skewY(33.75deg)' },
   423   { start: 'skew(45deg)', end: 'none',
   424     expected_uncomputed: 'skew(33.75deg)' },
   425   { start: 'skew(45deg, 45deg)', end: 'none',
   426     expected_uncomputed: 'skew(33.75deg, 33.75deg)' },
   427   { start: 'skewX(45deg)', end: 'skewX(-45deg)',
   428     expected_uncomputed: 'skewX(22.5deg)' },
   429   { start: 'skewX(0)', end: 'skewX(-45deg)',
   430     expected_uncomputed: 'skewX(-11.25deg)' },
   431   { start: 'skewY(45deg)', end: 'skewY(-45deg)',
   432     expected_uncomputed: 'skewY(22.5deg)' },
   434   // matrix : skewX
   435   { start: 'matrix(1, 0, 3, 1, 0, 0)', end: 'none',
   436     expected: 'matrix(1, 0, ' + 3 * 0.75 + ', 1, 0, 0)',
   437     round_error_ok: true },
   438   { start: 'skewX(0)', end: 'skewX(-45deg) translate(0)',
   439     expected: 'matrix(1, 0, -0.25, 1, 0, 0)',
   440     round_error_ok: true },
   441   // matrix : rotate
   442   { start: 'rotate(-30deg)', end: 'matrix(0, 1, -1, 0, 0, 0)',
   443     expected: 'matrix(1, 0, 0, 1, 0, 0)',
   444     round_error_ok: true },
   445   { start: 'rotate(-30deg) translateX(0)',
   446     end: 'translateX(0) rotate(-90deg)',
   447     expected: computeMatrix('rotate(-45deg)'),
   448     round_error_ok: true },
   449   // matrix decomposition of skewY
   450   { start: 'skewY(60deg)', end: 'skewY(-60deg) translateX(0)',
   451     /* rotate(30deg) skewX(60deg)/2 scale(2, 0.5) */
   452     expected: computeMatrix('rotate(30deg) skewX(' + Math.atan(Math.tan(Math.PI * 60/180) / 2) + 'rad) scale(2, 0.5)'),
   453     round_error_ok: true },
   455   // matrix decomposition
   457   // Four pairs of the same matrix expressed different ways.
   458   { start: 'matrix(-1, 0, 0, -1, 0, 0)', /* rotate(180deg) */
   459     end: 'matrix(1, 0, 0, 1, 0, 0)',
   460     expected: computeMatrix('rotate(135deg)') },
   461   { start: 'scale(-1)', end: 'none',
   462     expected_uncomputed: 'scale(-0.5)',
   463     expected: 'matrix(-0.5, 0, 0, -0.5, 0, 0)' },
   464   { start: 'rotate(180deg)', end: 'none',
   465     expected_uncomputed: 'rotate(135deg)' },
   466   { start: 'rotate(-180deg)', end: 'none',
   467     expected_uncomputed: 'rotate(-135deg)',
   468     expected: computeMatrix('rotate(225deg)') },
   470   // matrix followed by scale
   471   { start: 'matrix(2, 0, 0, 2, 10, 20) scale(2)',
   472     end: 'none',
   473     expected: 'matrix(3.0625, 0, 0, 3.0625, 7.5, 15)' },
   475   // ... and a bunch of similar possibilities.  The spec isn't settled
   476   // here; there are multiple options.  See:
   477   // http://lists.w3.org/Archives/Public/www-style/2010Jun/0602.html
   478   { start: 'matrix(-1, 0, 0, 1, 0, 0)', /* scaleX(-1) */
   479     end: 'matrix(1, 0, 0, 1, 0, 0)',
   480     expected: computeMatrix('scaleX(-0.5)') },
   482   { start: 'matrix(1, 0, 0, -1, 0, 0)', /* rotate(-180deg) scaleX(-1) */
   483     end: 'matrix(1, 0, 0, 1, 0, 0)',
   484     expected: computeMatrix('rotate(-135deg) scaleX(-0.5)') },
   486   { start: 'matrix(0, 1, 1, 0, 0, 0)', /* rotate(-90deg) scaleX(-1) */
   487     end: 'matrix(1, 0, 0, 1, 0, 0)',
   488     expected: computeMatrix('rotate(-67.5deg) scaleX(-0.5)') },
   490   { start: 'matrix(0, -1, 1, 0, 0, 0)', /* rotate(-90deg) */
   491     end: 'matrix(1, 0, 0, 1, 0, 0)',
   492     expected: computeMatrix('rotate(-67.5deg)') },
   494   { start: 'matrix(0, 1, -1, 0, 0, 0)', /* rotate(90deg) */
   495     end: 'matrix(1, 0, 0, 1, 0, 0)',
   496     expected: computeMatrix('rotate(67.5deg)') },
   498   { start: 'matrix(0, -1, -1, 0, 0, 0)', /* rotate(90deg) scaleX(-1) */
   499     end: 'matrix(1, 0, 0, 1, 0, 0)',
   500     expected: computeMatrix('rotate(67.5deg) scaleX(-0.5)') },
   502   // Similar decomposition tests, but with skewX.  I checked visually
   503   // that the sign of the skew was correct by checking visually that
   504   // the animations in
   505   // http://dbaron.org/css/test/2010/transition-negative-determinant
   506   // don't flip when they finish, and then wrote tests corresponding
   507   // to the current code's behavior.
   508   // ... start with four with positive determinants
   509   { start: 'none',
   510     end: 'matrix(1, 0, 1.5, 1, 0, 0)',
   511     /* skewX(atan(1.5)) */
   512     expected: 'matrix(1, 0, ' + 1.5 * 0.25 + ', 1, 0, 0)',
   513     round_error_ok: true },
   514   { start: 'none',
   515     end: 'matrix(-1, 0, 2, -1, 0, 0)',
   516             /* rotate(180deg) skewX(atan(-2)) */
   517     expected: computeMatrix('rotate(45deg) matrix(1, 0, ' + -2 * 0.25 + ', 1, 0, 0)'),
   518     round_error_ok: true },
   519   { start: 'none',
   520     end: 'matrix(0, -1, 1, -3, 0, 0)',
   521             /* rotate(-90deg) skewX(atan(3)) */
   522     expected: computeMatrix('rotate(-22.5deg) matrix(1, 0, ' + 3 * 0.25 + ', 1, 0, 0)'),
   523     round_error_ok: true },
   524   { start: 'none',
   525     end: 'matrix(0, 1, -1, 4, 0, 0)',
   526             /* rotate(90deg) skewX(atan(4)) */
   527     expected: computeMatrix('rotate(22.5deg) matrix(1, 0, ' + 4 * 0.25 + ', 1, 0, 0)'),
   528     round_error_ok: true },
   529   // and then four with negative determinants
   530   { start: 'none',
   531     end: 'matrix(1, 0, 1, -1, 0, 0)',
   532             /* rotate(-180deg) skewX(atan(-1)) scaleX(-1) */
   533     expected: computeMatrix('rotate(-45deg) matrix(1, 0, ' + -1 * 0.25 + ', 1, 0, 0) scaleX(0.5)'),
   534     round_error_ok: true },
   535   { start: 'none',
   536     end: 'matrix(-1, 0, -1, 1, 0, 0)',
   537             /* skewX(atan(-1)) scaleX(-1) */
   538     expected: computeMatrix('matrix(1, 0, ' + -1 * 0.25 + ', 1, 0, 0) scaleX(0.5)') },
   539   { start: 'none',
   540     end: 'matrix(0, 1, 1, -2, 0, 0)',
   541             /* rotate(-90deg) skewX(atan(2)) scaleX(-1) */
   542     expected: computeMatrix('rotate(-22.5deg) matrix(1, 0, ' + 2 * 0.25 + ', 1, 0, 0) scaleX(0.5)'),
   543     round_error_ok: true },
   544   { start: 'none',
   545     end: 'matrix(0, -1, -1, 0.5, 0, 0)',
   546             /* rotate(90deg) skewX(atan(0.5)) scaleX(-1) */
   547     expected: computeMatrix('rotate(22.5deg) matrix(1, 0, ' + 0.5 * 0.25 + ', 1, 0, 0) scaleX(0.5)'),
   548     round_error_ok: true },
   550   // lists vs. matrix decomposition
   551   { start: 'translate(10px) skewY(45deg)',
   552     end: 'translate(30px) skewY(-45deg)',
   553     expected_uncomputed: 'translate(15px) skewY(22.5deg)' },
   554   { start: 'skewY(45deg) rotate(90deg)',
   555     end: 'skewY(-45deg) rotate(90deg)',
   556     expected_uncomputed: 'skewY(22.5deg) rotate(90deg)' },
   557   { start: 'skewY(45deg) rotate(90deg) translate(0)',
   558     end: 'skewY(-45deg) rotate(90deg)',
   559     expected: 'matrix(0, 1, -1, -0.5, 0, 0)',
   560     round_error_ok: true },
   561   { start: 'skewX(45deg) rotate(90deg)',
   562     end: 'skewX(-45deg) rotate(90deg)',
   563     expected_uncomputed: 'skewX(22.5deg) rotate(90deg)' },
   564   { start: 'skewX(-60deg) rotate(90deg) translate(0)',
   565     end: 'skewX(60deg) rotate(90deg)',
   566     expected: computeMatrix('rotate(120deg) skewX(' + Math.atan(Math.tan(Math.PI * 60/180) / 2) + 'rad) scale(2, 0.5)'),
   567     round_error_ok: true },
   568 ];
   570 var filterTests = [
   571   { start: "none", end: "none",
   572     expected: ["none"] },
   573   // function from none (number/length)
   574   { start: "none", end: "brightness(0.5)",
   575     expected: ["brightness", 0.875] },
   576   { start: "none", end: "contrast(0.5)",
   577     expected: ["contrast", 0.875] },
   578   { start: "none", end: "grayscale(0.5)",
   579     expected: ["grayscale", 0.125] },
   580   { start: "none", end: "invert(0.5)",
   581     expected: ["invert", 0.125] },
   582   { start: "none", end: "opacity(0.5)",
   583     expected: ["opacity", 0.875] },
   584   { start: "none", end: "saturate(0.5)",
   585     expected: ["saturate", 0.875] },
   586   { start: "none", end: "sepia(0.5)",
   587     expected: ["sepia", 0.125] },
   588   { start: "none", end: "blur(50px)",
   589     expected: ["blur", 12.5] },
   590   // function to none (number/length)
   591   { start: "brightness(0.5)", end: "none",
   592     expected: ["brightness", 0.625] },
   593   { start: "contrast(0.5)", end: "none",
   594     expected: ["contrast", 0.625] },
   595   { start: "grayscale(0.5)", end: "none",
   596     expected: ["grayscale", 0.375] },
   597   { start: "invert(0.5)", end: "none",
   598     expected: ["invert", 0.375] },
   599   { start: "opacity(0.5)", end: "none",
   600     expected: ["opacity", 0.625] },
   601   { start: "saturate(0.5)", end: "none",
   602     expected: ["saturate", 0.625] },
   603   { start: "sepia(0.5)", end: "none",
   604     expected: ["sepia", 0.375] },
   605   { start: "blur(50px)", end: "none",
   606     expected: ["blur", 37.5] },
   607   // function to same function (number/length)
   608   { start: "brightness(0.25)", end: "brightness(0.75)",
   609     expected: ["brightness", 0.375] },
   610   { start: "contrast(0.25)", end: "contrast(0.75)",
   611     expected: ["contrast", 0.375] },
   612   { start: "grayscale(0.25)", end: "grayscale(0.75)",
   613     expected: ["grayscale", 0.375] },
   614   { start: "invert(0.25)", end: "invert(0.75)",
   615     expected: ["invert", 0.375] },
   616   { start: "opacity(0.25)", end: "opacity(0.75)",
   617     expected: ["opacity", 0.375] },
   618   { start: "saturate(0.25)", end: "saturate(0.75)",
   619     expected: ["saturate", 0.375] },
   620   { start: "sepia(0.25)", end: "sepia(0.75)",
   621     expected: ["sepia", 0.375] },
   622   { start: "blur(25px)", end: "blur(75px)",
   623     expected: ["blur", 37.5] },
   624   // function to same function (percent)
   625   { start: "brightness(25%)", end: "brightness(75%)",
   626     expected: ["brightness", 0.375] },
   627   { start: "contrast(25%)", end: "contrast(75%)",
   628     expected: ["contrast", 0.375] },
   629   { start: "grayscale(25%)", end: "grayscale(75%)",
   630     expected: ["grayscale", 0.375] },
   631   { start: "invert(25%)", end: "invert(75%)",
   632     expected: ["invert", 0.375] },
   633   { start: "opacity(25%)", end: "opacity(75%)",
   634     expected: ["opacity", 0.375] },
   635   { start: "saturate(25%)", end: "saturate(75%)",
   636     expected: ["saturate", 0.375] },
   637   { start: "sepia(25%)", end: "sepia(75%)",
   638     expected: ["sepia", 0.375] },
   639   // function to same function (percent, number/length)
   640   { start: "brightness(0.25)", end: "brightness(75%)",
   641     expected: ["brightness", 0.375] },
   642   { start: "contrast(25%)", end: "contrast(0.75)",
   643     expected: ["contrast", 0.375] },
   644   // hue-rotate with different angle values
   645   { start: "hue-rotate(0deg)", end: "hue-rotate(720deg)",
   646     expected: ["hue-rotate", Math.PI.toFixed(5)] },
   647   { start: "hue-rotate(0rad)", end: "hue-rotate("+4*Math.PI+"rad)",
   648     expected: ["hue-rotate", Math.PI.toFixed(5)] },
   649   { start: "hue-rotate(0grad)", end: "hue-rotate(800grad)",
   650     expected: ["hue-rotate", Math.PI.toFixed(5)] },
   651   { start: "hue-rotate(0turn)", end: "hue-rotate(2turn)",
   652     expected: ["hue-rotate", Math.PI.toFixed(5)] },
   653   { start: "hue-rotate(0deg)", end: "hue-rotate("+4*Math.PI+"rad)",
   654     expected: ["hue-rotate", Math.PI.toFixed(5)] },
   655   { start: "hue-rotate(0turn)", end: "hue-rotate(800grad)",
   656     expected: ["hue-rotate", Math.PI.toFixed(5)] },
   657   { start: "hue-rotate(0grad)", end: "hue-rotate("+4*Math.PI+"rad)",
   658     expected: ["hue-rotate", Math.PI.toFixed(5)] },
   659   { start: "hue-rotate(0grad)", end: "hue-rotate(0turn)",
   660     expected: ["hue-rotate", 0] },
   661   // multiple matching functions, same length
   662   { start: "contrast(25%) brightness(0.25) blur(25px) sepia(75%)",
   663     end: "contrast(75%) brightness(0.75) blur(75px) sepia(25%)",
   664     expected: ["contrast", 0.375, "brightness", 0.375, "blur", 37.5, "sepia", 0.625] },
   665   { start: "invert(25%) brightness(0.25) blur(25px) invert(50%) brightness(0.5) blur(50px)",
   666     end: "invert(75%) brightness(0.75) blur(75px)",
   667     expected: ["invert", 0.375, "brightness", 0.375, "blur", 37.5, "invert", 0.375, "brightness", 0.625, "blur", 37.5] },
   668   // multiple matching functions, different length
   669   { start: "contrast(25%) brightness(0.5) blur(50px)",
   670     end: "contrast(75%)",
   671     expected: ["contrast", 0.375, "brightness", 0.625, "blur", 37.5] },
   672   // mismatching filter functions
   673   { start: "contrast(0%)", end: "blur(10px)",
   674     expected: ["blur", 10] },
   675   // not supported interpolations
   676   { start: "none", end: "url('#b')",
   677     expected: ["url", "\""+document.URL+"#b\""] },
   678   { start: "url('#a')", end: "none",
   679     expected: ["none"] },
   680   { start: "url('#a')", end: "url('#b')",
   681     expected: ["url", "\""+document.URL+"#b\""] },
   682   { start: "url('#a')", end: "blur(10px)",
   683     expected: ["blur", 10] },
   684   { start: "blur(10px)", end: "url('#a')",
   685     expected: ["url", "\""+document.URL+"#a\""] },
   686   { start: "blur(0px) url('#a')", end: "blur(20px)",
   687     expected: ["blur", 20] },
   688   { start: "blur(0px)", end: "blur(20px) url('#a')",
   689     expected: ["blur", 20, "url", "\""+document.URL+"#a\""] },
   690   { start: "contrast(0.25) brightness(0.25) blur(25px)",
   691     end: "contrast(0.75) url('#a')",
   692     expected: ["contrast", 0.75, "url", "\""+document.URL+"#a\""] },
   693   { start: "contrast(0.25) brightness(0.25) blur(75px)",
   694     end: "brightness(0.75) contrast(0.75) blur(25px)",
   695     expected: ["brightness", 0.75, "contrast", 0.75, "blur", 25] },
   696   { start: "contrast(0.25) brightness(0.25) blur(25px)",
   697     end: "contrast(0.75) brightness(0.75) contrast(0.75)",
   698     expected: ["contrast", 0.75, "brightness", 0.75, "contrast", 0.75] },
   699   // drop-shadow animation
   700   { start: "none",
   701     end: "drop-shadow(rgb(0, 0, 0) 4px 4px 0px)",
   702     expected: ["drop-shadow", "rgba(0, 0, 0, 0.25) 1px 1px 0px"] },
   703   { start: "drop-shadow(rgb(0, 0, 0) 0px 0px 0px)",
   704     end: "drop-shadow(rgb(0, 0, 0) 4px 4px 0px)",
   705     expected: ["drop-shadow", "rgb(0, 0, 0) 1px 1px 0px"] },
   706   { start: "drop-shadow(#038000 4px 4px)",
   707     end: "drop-shadow(8px 8px 8px red)",
   708     expected: ["drop-shadow", "rgb(66, 96, 0) 5px 5px 2px"] },
   709   { start: "blur(25px) drop-shadow(8px 8px)",
   710     end: "blur(75px)",
   711     expected: ["blur", 37.5, "drop-shadow", "rgb(0, 0, 0) 6px 6px 0px"] },
   712   { start: "blur(75px)",
   713     end: "blur(25px) drop-shadow(8px 8px)",
   714     expected: ["blur", 62.5, "drop-shadow", "rgb(0, 0, 0) 2px 2px 0px"] },
   715   { start: "drop-shadow(2px 2px blue)",
   716     end: "none",
   717     expected: ["drop-shadow", "rgba(0, 0, 255, 0.75) 1.5px 1.5px 0px"] },
   718 ];
   720 var prop;
   721 for (prop in supported_properties) {
   722   // Test that prop is in the property database.
   723   ok(prop in gCSSProperties, "property " + prop + " in gCSSProperties");
   725   // Test that the entry has at least one test function.
   726   ok(supported_properties[prop].length > 0,
   727      "property " + prop + " must have at least one test function");
   728 }
   730 // Return a consistent sampling of |count| values out of |array|.
   731 function sample_array(array, count) {
   732   if (count <= 0) {
   733     ok(false, "unexpected count");
   734     return [];
   735   }
   736   var ratio = array.length / count;
   737   if (ratio <= 1) {
   738     return array;
   739   }
   740   var result = new Array(count);
   741   for (var i = 0; i < count; ++i) {
   742     result[i] = array[Math.floor(i * ratio)];
   743   }
   744   return result;
   745 }
   747 // Test that transitions don't do anything (i.e., aren't supported) on
   748 // the properties not in our test list above (and not transition
   749 // properties themselves).
   750 for (prop in gCSSProperties) {
   751   var info = gCSSProperties[prop];
   752   if (!(prop in supported_properties) &&
   753       info.type != CSS_TYPE_TRUE_SHORTHAND &&
   754       !("alias_for" in info) &&
   755       !prop.match(/^transition-/) &&
   756       // FIXME (Bug 119078): THIS SHOULD REALLY NOT BE NEEDED!
   757       prop != "-moz-binding") {
   759     if ("prerequisites" in info) {
   760       var prereqs = info.prerequisites;
   761       for (var prereq in prereqs) {
   762         div.style.setProperty(prereq, prereqs[prereq], "");
   763       }
   764     }
   766     var all_values = info.initial_values.concat(info.other_values);
   768     if (all_values.length > 50) {
   769       // Since we're using an O(N^2) algorithm here, reduce the list of
   770       // values that we want to test.  (This test is really only testing
   771       // that somebody didn't make a property animatable without
   772       // modifying this test.  The odds of somebody doing that without
   773       // making at least one of the many pairs of values we have left
   774       // animatable seems pretty low, at least relative to the chance
   775       // that any pair of the values listed in property_database.js is
   776       // animatable.)
   777       //
   778       // That said, we still try to use all of the start of the list on
   779       // the assumption that the more basic values are likely to be at
   780       // the beginning of the list.
   781       all_values = [].concat(info.initial_values.slice(0,2),
   782                              sample_array(info.initial_values.slice(2), 6),
   783                              info.other_values.slice(0, 10),
   784                              sample_array(info.other_values.slice(10), 40));
   785     }
   787     var all_computed = [];
   788     for (var idx in all_values) {
   789       var val = all_values[idx];
   790       div.style.setProperty(prop, val, "");
   791       all_computed.push(cs.getPropertyValue(prop));
   792     }
   793     div.style.removeProperty(prop);
   795     div.style.setProperty("transition", prop + " 20s linear", "");
   796     for (var i = 0; i < all_values.length; ++i) {
   797       for (var j = i + 1; j < all_values.length; ++j) {
   798         div.style.setProperty(prop, all_values[i], "");
   799         is(cs.getPropertyValue(prop), all_computed[i],
   800            "transitions not supported for property " + prop +
   801            " value " + all_values[i]);
   802         div.style.setProperty(prop, all_values[j], "");
   803         is(cs.getPropertyValue(prop), all_computed[j],
   804            "transitions not supported for property " + prop +
   805            " value " + all_values[j]);
   806       }
   807     }
   809     div.style.removeProperty("transition");
   810     div.style.removeProperty(prop);
   811     if ("prerequisites" in info) {
   812       var prereqs = info.prerequisites;
   813       for (var prereq in prereqs) {
   814         div.style.removeProperty(prereq);
   815       }
   816     }
   817   }
   818 }
   820 // Do 4-second linear transitions with -1 second transition delay and
   821 // linear timing function so that we can expect the transition to be
   822 // one quarter of the way through the value space right after changing
   823 // the property.
   824 div.style.setProperty("transition-duration", "4s", "");
   825 div.style.setProperty("transition-delay", "-1s", "");
   826 div.style.setProperty("transition-timing-function", "linear", "");
   827 for (prop in supported_properties) {
   828   var tinfo = supported_properties[prop];
   829   var info = gCSSProperties[prop];
   831   isnot(info.type, CSS_TYPE_TRUE_SHORTHAND,
   832         prop + " must not be a shorthand");
   833   if ("prerequisites" in info) {
   834     var prereqs = info.prerequisites;
   835     for (var prereq in prereqs) {
   836       // We don't want the 19px font-size prereq of line-height, since we
   837       // want to leave it 20px.
   838       if (prop != "line-height" || prereq != "font-size") {
   839         div.style.setProperty(prereq, prereqs[prereq], "");
   840       }
   841     }
   842   }
   844   for (var idx in tinfo) {
   845     tinfo[idx](prop);
   846   }
   848   // Make sure to unset the property and stop transitions on it.
   849   div.style.setProperty("transition-property", "none", "");
   850   div.style.removeProperty(prop);
   851   cs.getPropertyValue(prop);
   853   if ("prerequisites" in info) {
   854     var prereqs = info.prerequisites;
   855     for (var prereq in prereqs) {
   856       div.style.removeProperty(prereq);
   857     }
   858   }
   859 }
   860 div.style.removeProperty("transition");
   862 function get_distance(prop, v1, v2)
   863 {
   864   return SpecialPowers.DOMWindowUtils
   865            .computeAnimationDistance(div, prop, v1, v2);
   866 }
   868 function check_distance(prop, start, quarter, end)
   869 {
   870   var sq = get_distance(prop, start, quarter);
   871   var se = get_distance(prop, start, end);
   872   var qe = get_distance(prop, quarter, end);
   874   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 + "'");
   875   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 + "'");
   876 }
   878 function test_length_transition(prop) {
   879   div.style.setProperty("transition-property", "none", "");
   880   div.style.setProperty(prop, "4px", "");
   881   is(cs.getPropertyValue(prop), "4px",
   882      "length-valued property " + prop + ": computed value before transition");
   883   div.style.setProperty("transition-property", prop, "");
   884   div.style.setProperty(prop, "12px", "");
   885   is(cs.getPropertyValue(prop), "6px",
   886      "length-valued property " + prop + ": interpolation of lengths");
   887   check_distance(prop, "4px", "6px", "12px");
   888 }
   890 function test_length_clamped(prop) {
   891   test_length_clamped_or_unclamped(prop, true);
   892 }
   894 function test_length_unclamped(prop) {
   895   test_length_clamped_or_unclamped(prop, false);
   896 }
   898 function test_length_clamped_or_unclamped(prop, is_clamped) {
   899   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
   900   div.style.setProperty("transition-property", "none", "");
   901   div.style.setProperty(prop, "0px", "");
   902   is(cs.getPropertyValue(prop), "0px",
   903      "length-valued property " + prop + ": flush before clamping test");
   904   div.style.setProperty("transition-property", prop, "");
   905   div.style.setProperty(prop, "100px", "");
   906   (is_clamped ? is : isnot)(cs.getPropertyValue(prop), "0px",
   907      "length-valued property " + prop + ": clamping of negatives");
   908   div.style.setProperty("transition-timing-function", "linear", "");
   909 }
   911 // Test using float values in the range [0, 1] (e.g. opacity)
   912 function test_float_zeroToOne_transition(prop) {
   913   div.style.setProperty("transition-property", "none", "");
   914   div.style.setProperty(prop, "0.3", "");
   915   is(cs.getPropertyValue(prop), "0.3",
   916      "float-valued property " + prop + ": computed value before transition");
   917   div.style.setProperty("transition-property", prop, "");
   918   div.style.setProperty(prop, "0.8", "");
   919   is(cs.getPropertyValue(prop), "0.425",
   920      "float-valued property " + prop + ": interpolation of floats");
   921   check_distance(prop, "0.3", "0.425", "0.8");
   922 }
   924 function test_float_zeroToOne_clamped(prop) {
   925   test_float_zeroToOne_clamped_or_unclamped(prop, true);
   926 }
   927 function test_float_zeroToOne_unclamped(prop) {
   928   test_float_zeroToOne_clamped_or_unclamped(prop, false);
   929 }
   931 function test_float_zeroToOne_clamped_or_unclamped(prop, is_clamped) {
   932   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
   933   div.style.setProperty("transition-property", "none", "");
   934   div.style.setProperty(prop, "0", "");
   935   is(cs.getPropertyValue(prop), "0",
   936      "float-valued property " + prop + ": flush before clamping test");
   937   div.style.setProperty("transition-property", prop, "");
   938   div.style.setProperty(prop, "1", "");
   939   (is_clamped ? is : isnot)(cs.getPropertyValue(prop), "0",
   940      "float-valued property " + prop + ": clamping of negatives");
   941   div.style.setProperty("transition-timing-function", "linear", "");
   942 }
   944 // Test using float values in the range [1, infinity) (e.g. stroke-miterlimit)
   945 function test_float_aboveOne_transition(prop) {
   946   div.style.setProperty("transition-property", "none", "");
   947   div.style.setProperty(prop, "1", "");
   948   is(cs.getPropertyValue(prop), "1",
   949      "float-valued property " + prop + ": computed value before transition");
   950   div.style.setProperty("transition-property", prop, "");
   951   div.style.setProperty(prop, "2.1", "");
   952   is(cs.getPropertyValue(prop), "1.275",
   953      "float-valued property " + prop + ": interpolation of floats");
   954   check_distance(prop, "1", "1.275", "2.1");
   955 }
   957 function test_float_aboveOne_clamped(prop) {
   958   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
   959   div.style.setProperty("transition-property", "none", "");
   960   div.style.setProperty(prop, "1", "");
   961   is(cs.getPropertyValue(prop), "1",
   962      "float-valued property " + prop + ": flush before clamping test");
   963   div.style.setProperty("transition-property", prop, "");
   964   div.style.setProperty(prop, "5", "");
   965   is(cs.getPropertyValue(prop), "1",
   966      "float-valued property " + prop + ": clamping of negatives");
   967   div.style.setProperty("transition-timing-function", "linear", "");
   968 }
   970 function test_percent_transition(prop) {
   971   div.style.setProperty("transition-property", "none", "");
   972   div.style.setProperty(prop, "25%", "");
   973   var av = cs.getPropertyValue(prop);
   974   var a = any_unit_to_num(av);
   975   div.style.setProperty(prop, "75%", "");
   976   var bv = cs.getPropertyValue(prop);
   977   var b = any_unit_to_num(bv);
   978   isnot(b, a, "different percentages (" + av + " and " + bv +
   979               ") should be different for " + prop);
   980   div.style.setProperty("transition-property", prop, "");
   981   div.style.setProperty(prop, "25%", "");
   982   var res = cs.getPropertyValue(prop);
   983   is(any_unit_to_num(res) * 4, 3 * b + a,
   984      "percent-valued property " + prop + ": interpolation of percents: " +
   985      res + " should be a quarter of the way between " + bv + " and " + av);
   986   ok(has_num(res),
   987      "percent-valued property " + prop + ": percent computes to number");
   988   check_distance(prop, "25%", "37.5%", "75%");
   989 }
   991 function test_percent_clamped(prop) {
   992   test_percent_clamped_or_unclamped(prop, true);
   993 }
   995 function test_percent_unclamped(prop) {
   996   test_percent_clamped_or_unclamped(prop, false);
   997 }
   999 function test_percent_clamped_or_unclamped(prop, is_clamped) {
  1000   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1001   div.style.setProperty("transition-property", "none", "");
  1002   div.style.setProperty(prop, "0%", "");
  1003   var zero_val = cs.getPropertyValue(prop); // flushes too
  1004   div.style.setProperty("transition-property", prop, "");
  1005   div.style.setProperty(prop, "150%", "");
  1006   (is_clamped ? is : isnot)(cs.getPropertyValue(prop), zero_val,
  1007      "percent-valued property " + prop + ": clamping of negatives");
  1008   div.style.setProperty("transition-timing-function", "linear", "");
  1011 function test_length_percent_calc_transition(prop) {
  1012   div.style.setProperty("transition-property", "none", "");
  1013   div.style.setProperty(prop, "0%", "");
  1014   var av = cs.getPropertyValue(prop);
  1015   var a = any_unit_to_num(av);
  1016   div.style.setProperty(prop, "100%", "");
  1017   var bv = cs.getPropertyValue(prop);
  1018   var b = any_unit_to_num(bv);
  1019   div.style.setProperty(prop, "100px", "");
  1020   var cv = cs.getPropertyValue(prop);
  1021   var c = any_unit_to_num(cv);
  1022   isnot(b, a, "different percentages (" + av + " and " + bv +
  1023               ") should be different for " + prop);
  1025   div.style.setProperty(prop, "50%", "");
  1026   var v1v = cs.getPropertyValue(prop);
  1027   is(any_unit_to_num(v1v) * 2, a + b,
  1028      "computed value before transition for " + prop + ": '" +
  1029      v1v + "' should be halfway " +
  1030      "between '" + av + "' + and '" + bv + "'.");
  1031   div.style.setProperty("transition-property", prop, "");
  1032   div.style.setProperty(prop, "200px", "");
  1033   var v2v = cs.getPropertyValue(prop);
  1034   is(any_unit_to_num(v2v) * 8, 5*a + 3*b + 4*c,
  1035      "interpolation between length and percent for " + prop + ": '"
  1036      + v2v + "'");
  1038   div.style.setProperty("transition-property", "none", "");
  1039   div.style.setProperty(prop, "calc(25% + 100px)", "");
  1040   v1v = cs.getPropertyValue(prop);
  1041   is(any_unit_to_num(v1v) * 4, b + 4*c,
  1042      "computed value before transition for " + prop + ": '" + v1v + "'");
  1043   div.style.setProperty("transition-property", prop, "");
  1044   div.style.setProperty(prop, "75%", "");
  1045   v2v = cs.getPropertyValue(prop);
  1046   is(any_unit_to_num(v2v) * 8, 5*a + 3*b + 6*c,
  1047      "interpolation between calc() and percent for " + prop + ": '" +
  1048      v2v + "'");
  1050   div.style.setProperty("transition-property", "none", "");
  1051   div.style.setProperty(prop, "150px", "");
  1052   v1v = cs.getPropertyValue(prop);
  1053   is(any_unit_to_num(v1v) * 2, c * 3,
  1054      "computed value before transition for " + prop + ": '" + v1v + "'");
  1055   div.style.setProperty("transition-property", prop, "");
  1056   div.style.setProperty(prop, "calc(50% + 50px)", "");
  1057   v2v = cs.getPropertyValue(prop);
  1058   is(any_unit_to_num(v2v) * 8, 7 * a + b + 10*c,
  1059      "interpolation between length and calc() for " + prop + ": '" +
  1060      v2v + "'");
  1062   check_distance(prop, "50%", "calc(37.5% + 50px)", "200px");
  1063   check_distance(prop, "calc(25% + 100px)", "calc(37.5% + 75px)",
  1064                        "75%");
  1065   check_distance(prop, "150px", "calc(125px + 12.5%)",
  1066                        "calc(50% + 50px)");
  1069 function test_color_transition(prop) {
  1070   div.style.setProperty("transition-property", "none", "");
  1071   div.style.setProperty(prop, "rgb(255, 28, 0)", "");
  1072   is(cs.getPropertyValue(prop), "rgb(255, 28, 0)",
  1073      "color-valued property " + prop + ": computed value before transition");
  1074   div.style.setProperty("transition-property", prop, "");
  1075   div.style.setProperty(prop, "rgb(75, 84, 128)", "");
  1076   is(cs.getPropertyValue(prop), "rgb(210, 42, 32)",
  1077      "color-valued property " + prop + ": interpolation of colors");
  1079   div.style.setProperty("transition-property", "none", "");
  1080   div.style.setProperty(prop, "rgb(128, 64, 0)", "");
  1081   (prop == "color" ? div.parentNode : div).style.
  1082     setProperty("color", "rgb(0, 0, 128)", "");
  1083   is(cs.getPropertyValue(prop), "rgb(128, 64, 0)",
  1084      "color-valued property " + prop + ": computed value before transition");
  1085   div.style.setProperty("transition-property", prop, "");
  1086   div.style.setProperty(prop, "currentColor", "");
  1087   is(cs.getPropertyValue(prop), "rgb(96, 48, 32)",
  1088      "color-valued property " + prop + ": interpolation of currentColor");
  1090   check_distance(prop, "rgb(255, 28, 0)", "rgb(210, 42, 32)",
  1091                        "rgb(75, 84, 128)");
  1092   check_distance(prop, "rgb(128, 64, 0)", "rgb(96, 48, 32)", "currentColor");
  1094   (prop == "color" ? div.parentNode : div).style.removeProperty("color");
  1096   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1097   div.style.setProperty("transition-property", "none", "");
  1098   div.style.setProperty(prop, "rgb(0, 255, 0)", "");
  1099   var vals = cs.getPropertyValue(prop).match(/rgb\(([^, ]*), ([^, ]*), ([^, ]*)\)/);
  1100   is(vals.length, 4,
  1101      "color-valued property " + prop + ": flush before clamping test (length)");
  1102   is(vals[1], "0",
  1103      "color-valued property " + prop + ": flush before clamping test (red)");
  1104   is(vals[2], "255",
  1105      "color-valued property " + prop + ": flush before clamping test (green)");
  1106   is(vals[3], "0",
  1107      "color-valued property " + prop + ": flush before clamping test (blue)");
  1108   div.style.setProperty("transition-property", prop, "");
  1109   div.style.setProperty(prop, "rgb(255, 0, 128)", "");
  1110   // FIXME: Once we support non-sRGB colors, these tests will need fixing.
  1111   vals = cs.getPropertyValue(prop).match(/rgb\(([^, ]*), ([^, ]*), ([^, ]*)\)/);
  1112   is(vals.length, 4,
  1113      "color-valued property " + prop + ": clamping of negatives (length)");
  1114   is(vals[1], "0",
  1115      "color-valued property " + prop + ": clamping of negatives (red)");
  1116   is(vals[2], "255",
  1117      "color-valued property " + prop + ": clamping of above-range (green)");
  1118   is(vals[3], "0",
  1119      "color-valued property " + prop + ": clamping of negatives (blue)");
  1120   div.style.setProperty("transition-timing-function", "linear", "");
  1123 function test_border_color_transition(prop) {
  1124   div.style.setProperty("transition-property", "none", "");
  1125   div.style.setProperty(prop, "rgb(128, 64, 0)", "");
  1126   div.style.setProperty("color", "rgb(0, 0, 128)", "");
  1127   is(cs.getPropertyValue(prop), "rgb(128, 64, 0)",
  1128      "color-valued property " + prop + ": computed value before transition");
  1129   div.style.setProperty("transition-property", prop, "");
  1130   div.style.removeProperty(prop);
  1131   is(cs.getPropertyValue(prop), "rgb(96, 48, 32)",
  1132      "color-valued property " + prop + ": interpolation of initial value");
  1134   check_distance(prop, "rgb(128, 64, 0)", "rgb(96, 48, 32)", "initial");
  1136   div.style.removeProperty("color");
  1139 function filter_function_list_equals(computedValStr, expectedList)
  1141   // Check simple case "none"
  1142   if (computedValStr == "none" && computedValStr == expectedList[0]) {
  1143     return true;
  1146   // The regular expression does not filter out the last parenthesis.
  1147   // Remove last character for now.
  1148   is(computedValStr.substring(computedValStr.length - 1, computedValStr.length),
  1149                               ')', "Check if last character is close-paren");
  1150   computedValStr = computedValStr.substring(0, computedValStr.length - 1);
  1152   var reg = /\)*\s*(blur|brightness|contrast|grayscale|hue\-rotate|invert|opacity|saturate|sepia|drop\-shadow|url)\(/
  1153   var matches = computedValStr.split(reg);
  1154   // First item must be empty. All other items are of functionName, functionValue.
  1155   if (!matches || matches.shift() != "") {
  1156     ok(false, "computed style of 'filter' isn't in the format we expect");
  1157     return false;
  1160   // Odd items are the function name, even items the function value.
  1161   if (!matches.length || matches.length % 2 ||
  1162       expectedList.length != matches.length) {
  1163     ok(false, "computed style of 'filter' isn't in the format we expect");
  1164     return false;
  1166   for (var i = 0; i < matches.length; i += 2) {
  1167     var functionName = matches[i];
  1168     var functionValue = matches[i+1];
  1169     var expected = expectedList[i+1]
  1170     var tolerance = 0;
  1171     // Check if we have the expected function.
  1172     if (functionName != expectedList[i]) {
  1173       return false;
  1175     if (functionName == "blur") {
  1176       // Last two characters must be "px".
  1177       if (functionValue.search("px") != functionValue.length - 2) {
  1178         return false;
  1180       functionValue = functionValue.substring(0, functionValue.length - 2);
  1181     } else if (functionName == "hue-rotate") {
  1182       // Last two characters must be "rad".
  1183       if (functionValue.search("rad") != functionValue.length - 3) {
  1184         return false;
  1186       tolerance = 0.001;
  1187       functionValue = functionValue.substring(0, functionValue.length - 3);
  1188     } else if (functionName == "drop-shadow" || functionName == "url") {
  1189       if (functionValue != expected) {
  1190         return false;
  1192       continue;
  1194     // Check if string is not a number or difference is not in tolerance level.
  1195     if (isNaN(functionValue) ||
  1196       Math.abs(parseFloat(functionValue) - expected) > tolerance) {
  1197       return false;
  1200   return true;
  1203 function test_filter_transition(prop) {
  1204   if (!SpecialPowers.getBoolPref("layout.css.filters.enabled")) {
  1205     return;
  1207   for (var i in filterTests) {
  1208     var test = filterTests[i];
  1209     div.style.setProperty("transition-property", "none", "");
  1210     div.style.setProperty(prop, test.start, "");
  1211     cs.getPropertyValue(prop);
  1212     div.style.setProperty("transition-property", prop, "");
  1213     div.style.setProperty(prop, test.end, "");
  1214     var actual = cs.getPropertyValue(prop);
  1215     ok(filter_function_list_equals(actual, test.expected),
  1216                                    "Filter property is " + actual + " expected values of " +
  1217                                    test.expected);
  1221 function test_shadow_transition(prop) {
  1222   var spreadStr = (prop == "box-shadow") ? " 0px" : "";
  1224   div.style.setProperty("transition-property", "none", "");
  1225   div.style.setProperty(prop, "none", "");
  1226   is(cs.getPropertyValue(prop), "none",
  1227      "shadow-valued property " + prop + ": computed value before transition");
  1228   div.style.setProperty("transition-property", prop, "");
  1229   div.style.setProperty(prop, "4px 8px 3px red", "");
  1230   is(cs.getPropertyValue(prop), "rgba(255, 0, 0, 0.25) 1px 2px 0.75px" + spreadStr,
  1231      "shadow-valued property " + prop + ": interpolation of shadows");
  1232   check_distance(prop, "none", "rgba(255, 0, 0, 0.25) 1px 2px 0.75px",
  1233                        "4px 8px 3px red");
  1235   div.style.setProperty("transition-property", "none", "");
  1236   div.style.setProperty(prop, "#038000 4px 4px, 2px 2px blue", "");
  1237   is(cs.getPropertyValue(prop), "rgb(3, 128, 0) 4px 4px 0px" + spreadStr + ", rgb(0, 0, 255) 2px 2px 0px" + spreadStr,
  1238      "shadow-valued property " + prop + ": computed value before transition");
  1239   div.style.setProperty("transition-property", prop, "");
  1240   div.style.setProperty(prop, "8px 8px 8px red", "");
  1241   is(cs.getPropertyValue(prop), "rgb(66, 96, 0) 5px 5px 2px" + spreadStr + ", rgba(0, 0, 255, 0.75) 1.5px 1.5px 0px" + spreadStr,
  1242      "shadow-valued property " + prop + ": interpolation of shadows");
  1243   check_distance(prop, "#038000 4px 4px, 2px 2px blue",
  1244                        "rgb(66, 96, 0) 5px 5px 2px, rgba(0, 0, 255, 0.75) 1.5px 1.5px 0px",
  1245                        "8px 8px 8px red");
  1247   if (prop == "box-shadow") {
  1248     div.style.setProperty(prop, "8px 8px 8px red inset", "");
  1249     is(cs.getPropertyValue(prop), "rgb(255, 0, 0) 8px 8px 8px 0px inset",
  1250        "shadow-valued property " + prop + ": non-interpolable cases");
  1251     div.style.setProperty(prop, "8px 8px 8px 8px red inset", "");
  1252     is(cs.getPropertyValue(prop), "rgb(255, 0, 0) 8px 8px 8px 2px inset",
  1253        "shadow-valued property " + prop + ": interpolation of spread");
  1254     // Leave in same state whether in the |if| or not.
  1255     div.style.setProperty(prop, "8px 8px 8px red", "");
  1256     is(cs.getPropertyValue(prop), "rgb(255, 0, 0) 8px 8px 8px 0px",
  1257        "shadow-valued property " + prop + ": non-interpolable cases");
  1258     check_distance(prop, "8px 8px 8px red inset",
  1259                          "rgb(255, 0, 0) 8px 8px 8px 2px inset",
  1260                          "8px 8px 8px 8px red inset");
  1263   var defaultColor = cs.getPropertyValue("color") + " ";
  1264   div.style.setProperty(prop, "2px 2px 2px", "");
  1265   is(cs.getPropertyValue(prop), defaultColor + "2px 2px 2px" + spreadStr,
  1266      "shadow-valued property " + prop + ": non-interpolable cases");
  1267   div.style.setProperty(prop, "6px 14px 10px", "");
  1268   is(cs.getPropertyValue(prop), defaultColor + "3px 5px 4px" + spreadStr,
  1269      "shadow-valued property " + prop + ": interpolation without color");
  1270   check_distance(prop, "2px 2px 2px", "3px 5px 4px", "6px 14px 10px");
  1272   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1273   div.style.setProperty("transition-property", "none", "");
  1274   div.style.setProperty(prop, "0px 0px 0px black", "");
  1275   is(cs.getPropertyValue(prop), "rgb(0, 0, 0) 0px 0px 0px" + spreadStr,
  1276      "shadow-valued property " + prop + ": flush before clamping test");
  1277   div.style.setProperty("transition-property", prop, "");
  1278   div.style.setProperty(prop, "10px 10px 10px black", "");
  1279   var vals = cs.getPropertyValue(prop).split(" ");
  1280   is(vals.length, 6 + (prop == "box-shadow"), "unexpected number of values");
  1281   is(vals.slice(0, 3).join(" "), "rgb(0, 0, 0)",
  1282      "shadow-valued property " + prop + " (color): clamping of negatives");
  1283   isnot(vals[3], "0px",
  1284         "shadow-valued property " + prop + " (x): clamping of negatives");
  1285   isnot(vals[4], "0px",
  1286         "shadow-valued property " + prop + " (y): clamping of negatives");
  1287   is(vals[5], "0px",
  1288      "shadow-valued property " + prop + " (radius): clamping of negatives");
  1289   if (prop == "box-shadow") {
  1290     div.style.setProperty("transition-property", "none", "");
  1291     div.style.setProperty(prop, "0px 0px 0px 0px black", "");
  1292     is(cs.getPropertyValue(prop), "rgb(0, 0, 0) 0px 0px 0px 0px",
  1293        "shadow-valued property " + prop + ": flush before clamping test");
  1294     div.style.setProperty("transition-property", prop, "");
  1295     div.style.setProperty(prop, "10px 10px 10px 10px black", "");
  1296     var vals = cs.getPropertyValue(prop).split(" ");
  1297     is(vals.length, 7, "unexpected number of values");
  1298     is(vals.slice(0, 3).join(" "), "rgb(0, 0, 0)",
  1299        "shadow-valued property " + prop + " (color): clamping of negatives");
  1300     isnot(vals[3], "0px",
  1301           "shadow-valued property " + prop + " (x): clamping of negatives");
  1302     isnot(vals[4], "0px",
  1303           "shadow-valued property " + prop + " (y): clamping of negatives");
  1304     is(vals[5], "0px",
  1305        "shadow-valued property " + prop + " (radius): clamping of negatives");
  1306     isnot(vals[6], "0px",
  1307           "shadow-valued property " + prop + " (spread): clamping of negatives");
  1309   div.style.setProperty("transition-timing-function", "linear", "");
  1312 function test_dasharray_transition(prop) {
  1313   div.style.setProperty("transition-property", "none", "");
  1314   div.style.setProperty(prop, "3", "");
  1315   is(cs.getPropertyValue(prop), "3",
  1316      "dasharray-valued property " + prop +
  1317      ": computed value before transition");
  1318   div.style.setProperty("transition-property", prop, "");
  1319   div.style.setProperty(prop, "15px", "");
  1320   is(cs.getPropertyValue(prop), "6",
  1321      "dasharray-valued property " + prop + ": interpolation of dasharray");
  1322   check_distance(prop, "3", "6", "15px");
  1323   div.style.setProperty(prop, "none", "");
  1324   is(cs.getPropertyValue(prop), "none",
  1325      "dasharray-valued property " + prop + ": non-interpolability of none");
  1326   div.style.setProperty(prop, "6,8px,4,4", "");
  1327   is(cs.getPropertyValue(prop), "6, 8px, 4, 4",
  1328      "dasharray-valued property " + prop +
  1329      ": computed value before transition");
  1330   div.style.setProperty(prop, "14, 12,16,16px", "");
  1331   is(cs.getPropertyValue(prop), "8, 9, 7, 7",
  1332      "dasharray-valued property " + prop + ": interpolation of dasharray");
  1333   check_distance(prop, "6,8px,4,4", "8,9,7,7", "14, 12,16,16px");
  1334   div.style.setProperty(prop, "none", "");
  1335   is(cs.getPropertyValue(prop), "none",
  1336      "dasharray-valued property " + prop + ": non-interpolability of none");
  1337   div.style.setProperty(prop, "8,16,4", "");
  1338   is(cs.getPropertyValue(prop), "8, 16, 4",
  1339      "dasharray-valued property " + prop +
  1340      ": computed value before transition");
  1341   div.style.setProperty(prop, "4,8,12,16", "");
  1342   is(cs.getPropertyValue(prop), "7, 14, 6, 10, 13, 5, 9, 16, 4, 8, 15, 7",
  1343      "dasharray-valued property " + prop + ": interpolation of dasharray");
  1344   check_distance(prop, "8,16,4", "7, 14, 6, 10, 13, 5, 9, 16, 4, 8, 15, 7",
  1345                        "4,8,12,16");
  1346   div.style.setProperty(prop, "2,50%,6,10", "");
  1347   is(cs.getPropertyValue(prop), "2, 50%, 6, 10",
  1348      "dasharray-valued property " + prop + ": non-interpolability of mixed units");
  1349   div.style.setProperty(prop, "6,30%,2,2", "");
  1350   is(cs.getPropertyValue(prop), "3, 45%, 5, 8",
  1351      "dasharray-valued property " + prop + ": interpolation of dasharray");
  1352   check_distance(prop, "2,50%,6,10", "3, 45%, 5, 8", "6,30%,2,2");
  1354   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1355   div.style.setProperty("transition-property", "none", "");
  1356   div.style.setProperty(prop, "0,0%", "");
  1357   is(cs.getPropertyValue(prop), "0, 0%",
  1358      "dasharray-valued property " + prop + ": flush before clamping test");
  1359   div.style.setProperty("transition-property", prop, "");
  1360   div.style.setProperty(prop, "5, 25%", "");
  1361   is(cs.getPropertyValue(prop), "0, 0%",
  1362      "dasharray-valued property " + prop + ": clamping of negatives");
  1363   div.style.setProperty("transition-timing-function", "linear", "");
  1366 function test_radius_transition(prop) {
  1367   div.style.setProperty("transition-property", "none", "");
  1369   // FIXME: Test a square for now, since we haven't updated to the spec
  1370   // for vertical components being relative to the height.
  1371   // Note: We use powers of two here so the floating-point math comes out
  1372   // nicely.
  1373   div.style.setProperty("width", "256px", "");
  1374   div.style.setProperty("height", "256px", "");
  1375   div.style.setProperty("border", "none", "");
  1376   div.style.setProperty("padding", "0", "");
  1378   div.style.setProperty(prop, "3px", "");
  1379   is(cs.getPropertyValue(prop), "3px",
  1380      "radius-valued property " + prop +
  1381      ": computed value before transition");
  1382   div.style.setProperty("transition-property", prop, "");
  1383   div.style.setProperty(prop, "15px", "");
  1384   is(cs.getPropertyValue(prop), "6px",
  1385      "radius-valued property " + prop + ": interpolation of radius");
  1386   check_distance(prop, "3px", "6px", "15px");
  1387   div.style.setProperty("transition-property", "none", "");
  1388   div.style.setProperty(prop, "12.5%", "");
  1389   is(cs.getPropertyValue(prop), "32px",
  1390      "radius-valued property " + prop + ": computed value before transition");
  1391   div.style.setProperty("transition-property", prop, "");
  1392   div.style.setProperty(prop, "25%", "");
  1393   is(cs.getPropertyValue(prop), "40px",
  1394      "radius-valued property " + prop + ": interpolation of radius");
  1395   check_distance(prop, "12.5%", "15.625%", "25%");
  1396   div.style.setProperty("transition-property", "none", "");
  1397   div.style.setProperty(prop, "3px 8px", "");
  1398   is(cs.getPropertyValue(prop), "3px 8px",
  1399      "radius-valued property " + prop + ": computed value before transition");
  1400   div.style.setProperty("transition-property", prop, "");
  1401   div.style.setProperty(prop, "15px 12px", "");
  1402   is(cs.getPropertyValue(prop), "6px 9px",
  1403      "radius-valued property " + prop + ": interpolation of radius");
  1404   check_distance(prop, "3px 8px", "6px 9px", "15px 12px");
  1405   div.style.setProperty("transition-property", "none", "");
  1406   div.style.setProperty(prop, "12.5% 6.25%", "");
  1407   is(cs.getPropertyValue(prop), "32px 16px",
  1408      "radius-valued property " + prop + ": computed value before transition");
  1409   div.style.setProperty("transition-property", prop, "");
  1410   div.style.setProperty(prop, "25%", "");
  1411   is(cs.getPropertyValue(prop), "40px 28px",
  1412      "radius-valued property " + prop + ": interpolation of radius");
  1413   check_distance(prop, "12.5% 6.25%", "15.625% 10.9375%", "25%");
  1414   div.style.setProperty("transition-property", "none", "");
  1415   div.style.setProperty(prop, "6.25% 12.5%", "");
  1416   is(cs.getPropertyValue(prop), "16px 32px",
  1417      "radius-valued property " + prop + ": computed value before transition");
  1418   div.style.setProperty("transition-property", prop, "");
  1419   div.style.setProperty(prop, "64px 16px", "");
  1420   is(cs.getPropertyValue(prop), "28px",
  1421      "radius-valued property " + prop + ": interpolation of radius with mixed units");
  1422   check_distance(prop, "6.25% 12.5%",
  1423                  "calc(4.6875% + 16px) calc(9.375% + 4px)",
  1424                  "64px 16px");
  1426   div.style.setProperty("transition-property", "none", "");
  1427   div.style.setProperty(prop, "calc(5px) 10px", "");
  1428   is(cs.getPropertyValue(prop), "5px 10px",
  1429      "radius-valued property " + prop + ": computed value before transition");
  1430   div.style.setProperty("transition-property", prop, "");
  1431   div.style.setProperty(prop, "calc(25px) calc(50px)", "");
  1432   is(cs.getPropertyValue(prop), "10px 20px",
  1433      "radius-valued property " + prop + ": interpolation of radius with calc() units");
  1435   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1436   div.style.setProperty("transition-property", "none", "");
  1437   div.style.setProperty(prop, "0px 0px", "");
  1438   is(cs.getPropertyValue(prop), "0px",
  1439      "radius-valued property " + prop + ": flush before clamping test");
  1440   div.style.setProperty("transition-property", prop, "");
  1441   div.style.setProperty(prop, "10px 20px", "");
  1442   is(cs.getPropertyValue(prop), "0px",
  1443      "radius-valued property " + prop + ": clamping of negatives");
  1444   div.style.setProperty("transition-timing-function", "linear", "");
  1446   test_length_percent_calc_transition(prop);
  1448   div.style.removeProperty("width");
  1449   div.style.removeProperty("height");
  1450   div.style.removeProperty("border");
  1451   div.style.removeProperty("padding");
  1454 function test_integer_transition(prop) {
  1455   div.style.setProperty("transition-property", "none", "");
  1456   div.style.setProperty(prop, "4", "");
  1457   is(cs.getPropertyValue(prop), "4",
  1458      "integer-valued property " + prop + ": computed value before transition");
  1459   div.style.setProperty("transition-property", prop, "");
  1460   div.style.setProperty(prop, "-14", "");
  1461   is(cs.getPropertyValue(prop), "-1",
  1462      "integer-valued property " + prop + ": interpolation of integers");
  1463   check_distance(prop, "6", "1", "-14");
  1465   div.style.setProperty("transition-property", "none", "");
  1466   div.style.setProperty(prop, "-4", "");
  1467   is(cs.getPropertyValue(prop), "-4",
  1468      "integer-valued property " + prop + ": computed value before transition");
  1469   div.style.setProperty("transition-property", prop, "");
  1470   div.style.setProperty(prop, "8", "");
  1471   is(cs.getPropertyValue(prop), "-1",
  1472      "integer-valued property " + prop + ": interpolation of integers");
  1473   check_distance(prop, "-4", "-1", "8");
  1475   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1476   div.style.setProperty("transition-property", "none", "");
  1477   div.style.setProperty(prop, "0", "");
  1478   is(cs.getPropertyValue(prop), "0",
  1479      "integer-valued property " + prop + ": flush before clamping test");
  1480   div.style.setProperty("transition-property", prop, "");
  1481   div.style.setProperty(prop, "100", "");
  1482   isnot(cs.getPropertyValue(prop), "0",
  1483         "integer-valued property " + prop + ": clamping of negatives");
  1484   div.style.setProperty("transition-timing-function", "linear", "");
  1487 function test_font_stretch(prop) {
  1488   is(prop, "font-stretch", "only designed for one property");
  1490   div.style.setProperty("transition-property", "none", "");
  1491   div.style.setProperty(prop, "normal", "");
  1492   is(cs.getPropertyValue(prop), "normal",
  1493      "font-stretch property " + prop + ": computed value before transition");
  1494   div.style.setProperty("transition-property", prop, "");
  1495   div.style.setProperty(prop, "ultra-expanded", "");
  1496   is(cs.getPropertyValue(prop), "semi-expanded",
  1497      "font-stretch property " + prop + ": interpolation of font-stretches");
  1498   check_distance(prop, "normal", "semi-expanded", "ultra-expanded");
  1499   div.style.setProperty("transition-property", "none", "");
  1500   div.style.setProperty(prop, "expanded", "");
  1501   is(cs.getPropertyValue(prop), "expanded",
  1502      "font-stretch property " + prop + ": computed value before transition");
  1503   div.style.setProperty("transition-property", prop, "");
  1504   div.style.setProperty(prop, "extra-condensed", "");
  1505   is(cs.getPropertyValue(prop), "normal",
  1506      "font-stretch property " + prop + ": interpolation of font-stretches");
  1507   check_distance(prop, "expanded", "semi-expanded", "condensed");
  1509   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1510   div.style.setProperty("transition-property", "none", "");
  1511   div.style.setProperty(prop, "ultra-condensed", "");
  1512   is(cs.getPropertyValue(prop), "ultra-condensed",
  1513      "font-stretch property " + prop + ": flush before clamping test");
  1514   div.style.setProperty("transition-property", prop, "");
  1515   div.style.setProperty(prop, "ultra-expanded", "");
  1516   is(cs.getPropertyValue(prop), "ultra-condensed",
  1517      "font-stretch property " + prop + ": clamping of values");
  1518   div.style.setProperty("transition-property", "none", "");
  1519   div.style.setProperty(prop, "ultra-expanded", "");
  1520   is(cs.getPropertyValue(prop), "ultra-expanded",
  1521      "font-stretch property " + prop + ": flush before clamping test");
  1522   div.style.setProperty("transition-property", prop, "");
  1523   div.style.setProperty(prop, "ultra-condensed", "");
  1524   is(cs.getPropertyValue(prop), "ultra-expanded",
  1525      "font-stretch property " + prop + ": clamping of values");
  1526   div.style.setProperty("transition-timing-function", "linear", "");
  1529 function test_font_weight(prop) {
  1530   is(prop, "font-weight", "only designed for one property");
  1532   div.style.setProperty("transition-property", "none", "");
  1533   div.style.setProperty(prop, "normal", "");
  1534   is(cs.getPropertyValue(prop), "400",
  1535      "font-weight property " + prop + ": computed value before transition");
  1536   div.style.setProperty("transition-property", prop, "");
  1537   div.style.setProperty(prop, "900", "");
  1538   is(cs.getPropertyValue(prop), "500",
  1539      "font-weight property " + prop + ": interpolation of font-weights");
  1540   check_distance(prop, "400", "500", "800");
  1542   div.style.setProperty("transition-property", "none", "");
  1543   div.style.setProperty(prop, "900", "");
  1544   is(cs.getPropertyValue(prop), "900",
  1545      "font-weight property " + prop + ": computed value before transition");
  1546   div.style.setProperty("transition-property", prop, "");
  1547   div.style.setProperty(prop, "100", "");
  1548   is(cs.getPropertyValue(prop), "700",
  1549      "font-weight property " + prop + ": interpolation of font-weights");
  1550   check_distance(prop, "900", "700", "100");
  1552   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1553   div.style.setProperty("transition-property", "none", "");
  1554   div.style.setProperty(prop, "100", "");
  1555   is(cs.getPropertyValue(prop), "100",
  1556      "font-weight property " + prop + ": flush before clamping test");
  1557   div.style.setProperty("transition-property", prop, "");
  1558   div.style.setProperty(prop, "900", "");
  1559   is(cs.getPropertyValue(prop), "100",
  1560      "font-weight property " + prop + ": clamping of values");
  1561   div.style.setProperty("transition-property", "none", "");
  1562   div.style.setProperty(prop, "900", "");
  1563   is(cs.getPropertyValue(prop), "900",
  1564      "font-weight property " + prop + ": flush before clamping test");
  1565   div.style.setProperty("transition-property", prop, "");
  1566   div.style.setProperty(prop, "100", "");
  1567   is(cs.getPropertyValue(prop), "900",
  1568      "font-weight property " + prop + ": clamping of values");
  1569   div.style.setProperty("transition-timing-function", "linear", "");
  1572 function test_pos_integer_or_auto_transition(prop) {
  1573   div.style.setProperty("transition-property", "none", "");
  1574   div.style.setProperty(prop, "4", "");
  1575   is(cs.getPropertyValue(prop), "4",
  1576      "integer-valued property " + prop + ": computed value before transition");
  1577   div.style.setProperty("transition-property", prop, "");
  1578   div.style.setProperty(prop, "11", "");
  1579   is(cs.getPropertyValue(prop), "5",
  1580      "integer-valued property " + prop + ": interpolation of integers");
  1581   check_distance(prop, "4", "6", "12");
  1582   div.style.setProperty(prop, "auto", "");
  1583   is(cs.getPropertyValue(prop), "auto",
  1584      "integer-valued property " + prop + ": auto not interpolable");
  1585   div.style.setProperty(prop, "8", "");
  1586   is(cs.getPropertyValue(prop), "8",
  1587      "integer-valued property " + prop + ": computed value before transition");
  1588   div.style.setProperty(prop, "4", "");
  1589   is(cs.getPropertyValue(prop), "7",
  1590      "integer-valued property " + prop + ": interpolation of integers");
  1591   check_distance(prop, "8", "7", "4");
  1594 function test_integer_at_least_one_clamping(prop) {
  1595   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1596   div.style.setProperty("transition-property", "none", "");
  1597   div.style.setProperty(prop, "1", "");
  1598   is(cs.getPropertyValue(prop), "1",
  1599      "integer-valued property " + prop + ": flush before clamping test");
  1600   div.style.setProperty("transition-property", prop, "");
  1601   div.style.setProperty(prop, "5", "");
  1602   is(cs.getPropertyValue(prop), "1",
  1603      "integer-valued property " + prop + ": clamping of negatives");
  1604   div.style.setProperty("transition-timing-function", "linear", "");
  1607 function test_length_pair_transition(prop) {
  1608   div.style.setProperty("transition-property", "none", "");
  1609   div.style.setProperty(prop, "4px 6px", "");
  1610   is(cs.getPropertyValue(prop), "4px 6px",
  1611      "length-valued property " + prop + ": computed value before transition");
  1612   div.style.setProperty("transition-property", prop, "");
  1613   div.style.setProperty(prop, "12px 10px", "");
  1614   is(cs.getPropertyValue(prop), "6px 7px",
  1615      "length-valued property " + prop + ": interpolation of lengths");
  1616   check_distance(prop, "4px 6px", "6px 7px", "12px 10px");
  1619 function test_length_pair_transition_clamped(prop) {
  1620   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1621   div.style.setProperty("transition-property", "none", "");
  1622   div.style.setProperty(prop, "0px 0px", "");
  1623   is(cs.getPropertyValue(prop), "0px 0px",
  1624      "length-valued property " + prop + ": flush before clamping test");
  1625   div.style.setProperty("transition-property", prop, "");
  1626   div.style.setProperty(prop, "30px 50px", "");
  1627   is(cs.getPropertyValue(prop), "0px 0px",
  1628      "length-valued property " + prop + ": clamping of negatives");
  1629   div.style.setProperty("transition-timing-function", "linear", "");
  1632 function test_length_percent_pair_transition(prop) {
  1633   div.style.setProperty("transition-property", "none", "");
  1634   div.style.setProperty(prop, "4px 50%", "");
  1635   is(cs.getPropertyValue(prop), "4px 5px",
  1636      "length-valued property " + prop + ": computed value before transition");
  1637   div.style.setProperty("transition-property", prop, "");
  1638   div.style.setProperty(prop, "12px 70%", "");
  1639   is(cs.getPropertyValue(prop), "6px 5.5px",
  1640      "length-valued property " + prop + ": interpolation of lengths");
  1641   check_distance(prop, "4px 50%", "6px 55%", "12px 70%");
  1644 function test_length_percent_pair_clamped(prop) {
  1645   test_length_percent_pair_clamped_or_unclamped(prop, true);
  1648 function test_length_percent_pair_unclamped(prop) {
  1649   test_length_percent_pair_clamped_or_unclamped(prop, false);
  1652 function test_length_percent_pair_clamped_or_unclamped(prop, is_clamped) {
  1653   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1654   div.style.setProperty("transition-property", "none", "");
  1655   div.style.setProperty(prop, "0px 0%", "");
  1656   is(cs.getPropertyValue(prop), "0px 0px",
  1657      "length+percent-valued property " + prop + ": flush before clamping test");
  1658   div.style.setProperty("transition-property", prop, "");
  1659   div.style.setProperty(prop, "30px 25%", "");
  1660   (is_clamped ? is : isnot)(cs.getPropertyValue(prop), "0px 0px",
  1661      "length+percent-valued property " + prop + ": clamping of negatives");
  1662   div.style.setProperty("transition-timing-function", "linear", "");
  1665 function test_rect_transition(prop) {
  1666   div.style.setProperty("transition-property", "none", "");
  1667   div.style.setProperty(prop, "rect(4px, 16px, 12px, 6px)", "");
  1668   is(cs.getPropertyValue(prop), "rect(4px, 16px, 12px, 6px)",
  1669      "rect-valued property " + prop + ": computed value before transition");
  1670   div.style.setProperty("transition-property", prop, "");
  1671   div.style.setProperty(prop, "rect(0px, 4px, 4px, 2px)", "");
  1672   is(cs.getPropertyValue(prop), "rect(3px, 13px, 10px, 5px)",
  1673      "rect-valued property " + prop + ": interpolation of rects");
  1674   check_distance(prop, "rect(4px, 16px, 12px, 6px)",
  1675                        "rect(3px, 13px, 10px, 5px)",
  1676                        "rect(0px, 4px, 4px, 2px)");
  1677   if (prop == "clip") {
  1678     div.style.setProperty(prop, "rect(0px, 6px, 4px, auto)", "");
  1679     is(cs.getPropertyValue(prop), "rect(0px, 6px, 4px, auto)",
  1680        "rect-valued property " + prop + ": can't interpolate auto components");
  1681     div.style.setProperty(prop, "rect(0px, 6px, 4px, 2px)", "");
  1683   div.style.setProperty(prop, "auto", "");
  1684   is(cs.getPropertyValue(prop), "auto",
  1685      "rect-valued property " + prop + ": can't interpolate auto components");
  1687   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1688   div.style.setProperty("transition-property", "none", "");
  1689   div.style.setProperty(prop, "rect(-10px, 30px, 0px, 0px)", "");
  1690   var vals = cs.getPropertyValue(prop).match(/rect\(([^, ]*), ([^, ]*), ([^, ]*), ([^, ]*)\)/);
  1691   is(vals.length, 5,
  1692      "rect-valued property " + prop + ": flush before clamping test (length)");
  1693   is(vals[1], "-10px",
  1694      "rect-valued property " + prop + ": flush before clamping test (top)");
  1695   is(vals[2], "30px",
  1696      "rect-valued property " + prop + ": flush before clamping test (right)");
  1697   is(vals[3], "0px",
  1698      "rect-valued property " + prop + ": flush before clamping test (bottom)");
  1699   is(vals[4], "0px",
  1700      "rect-valued property " + prop + ": flush before clamping test (left)");
  1701   div.style.setProperty("transition-property", prop, "");
  1702   div.style.setProperty(prop, "rect(0px, 40px, 10px, 10px)", "");
  1703   vals = cs.getPropertyValue(prop).match(/rect\(([^, ]*), ([^, ]*), ([^, ]*), ([^, ]*)\)/);
  1704   is(vals.length, 5,
  1705      "rect-valued property " + prop + ": clamping of negatives (length)");
  1706   isnot(vals[1], "-10px",
  1707      "rect-valued property " + prop + ": clamping of negatives (top)");
  1708   isnot(vals[2], "30px",
  1709      "rect-valued property " + prop + ": clamping of negatives (right)");
  1710   isnot(vals[3], "0px",
  1711      "rect-valued property " + prop + ": clamping of negatives (bottom)");
  1712   isnot(vals[4], "0px",
  1713      "rect-valued property " + prop + ": clamping of negatives (left)");
  1714   div.style.setProperty("transition-timing-function", "linear", "");
  1717 function test_visibility_transition(prop) {
  1718   function do_test(from_value, to_value, interp_value) {
  1719     div.style.setProperty("transition-property", "none", "");
  1720     div.style.setProperty(prop, from_value, "");
  1721     is(cs.getPropertyValue(prop), from_value,
  1722        "visibility property " + prop + ": computed value before transition");
  1723     div.style.setProperty("transition-property", prop, "");
  1724     div.style.setProperty(prop, to_value, "");
  1725     is(cs.getPropertyValue(prop), interp_value,
  1726        "visibility property " + prop + ": interpolation of visibility");
  1729   do_test("visible", "hidden", "visible");
  1730   do_test("hidden", "visible", "visible");
  1731   do_test("hidden", "collapse", "collapse"); /* not interpolable */
  1732   do_test("collapse", "hidden", "hidden"); /* not interpolable */
  1733   do_test("visible", "collapse", "visible");
  1734   do_test("collapse", "visible", "visible");
  1736   isnot(get_distance(prop, "visible", "hidden"), 0,
  1737         "distance between visible and hidden should not be zero");
  1738   isnot(get_distance(prop, "visible", "collapse"), 0,
  1739         "distance between visible and collapse should not be zero");
  1740   is(get_distance(prop, "visible", "visible"), 0,
  1741      "distance between visible and visible should not be zero");
  1742   is(get_distance(prop, "hidden", "hidden"), 0,
  1743      "distance between hidden and hidden should not be zero");
  1744   is(get_distance(prop, "collapse", "collapse"), 0,
  1745      "distance between collapse and collapse should not be zero");
  1747   div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
  1748   function do_negative_test(from_value, to_value, interpolable) {
  1749     div.style.setProperty("transition-property", "none", "");
  1750     div.style.setProperty(prop, from_value, "");
  1751     is(cs.getPropertyValue(prop), from_value,
  1752        "visibility property " + prop + ": flush before clamping test");
  1753     div.style.setProperty("transition-property", prop, "");
  1754     div.style.setProperty(prop, to_value, "");
  1755     is(cs.getPropertyValue(prop), interpolable ? from_value : to_value,
  1756        "visibility property " + prop + ": clamping of negatives");
  1758   do_negative_test("visible", "hidden", true);
  1759   do_negative_test("hidden", "visible", true);
  1760   do_negative_test("hidden", "collapse", false);
  1761   do_negative_test("collapse", "hidden", false);
  1762   do_negative_test("visible", "collapse", true);
  1763   do_negative_test("collapse", "visible", true);
  1765   div.style.setProperty("transition-delay", "-3s", "");
  1766   div.style.setProperty("transition-timing-function", FUNC_OVERONE, "");
  1768   function do_overone_test(from_value, to_value) {
  1769     div.style.setProperty("transition-property", "none", "");
  1770     div.style.setProperty(prop, from_value, "");
  1771     is(cs.getPropertyValue(prop), from_value,
  1772        "visibility property " + prop + ": flush before clamping test");
  1773     div.style.setProperty("transition-property", prop, "");
  1774     div.style.setProperty(prop, to_value, "");
  1775     is(cs.getPropertyValue(prop), to_value,
  1776        "visibility property " + prop + ": clamping of over-ones");
  1778   do_overone_test("visible", "hidden");
  1779   do_overone_test("hidden", "visible");
  1780   do_overone_test("hidden", "collapse");
  1781   do_overone_test("collapse", "hidden");
  1782   do_overone_test("visible", "collapse");
  1783   do_overone_test("collapse", "visible");
  1785   div.style.setProperty("transition-delay", "-1s", "");
  1786   div.style.setProperty("transition-timing-function", "linear", "");
  1789 function test_background_size_transition(prop) {
  1790   div.style.setProperty("transition-property", "none", "");
  1791   div.style.setProperty(prop, "50% 80%", "");
  1792   is(cs.getPropertyValue(prop), "50% 80%",
  1793      "property " + prop + ": computed value before transition");
  1794   div.style.setProperty("transition-property", prop, "");
  1795   div.style.setProperty(prop, "100% 100%", "");
  1796   is(cs.getPropertyValue(prop), "62.5% 85%",
  1797      "property " + prop + ": interpolation of percents");
  1798   check_distance(prop, "50% 80%", "62.5% 85%", "100% 100%");
  1799   div.style.setProperty(prop, "contain", "");
  1800   is(cs.getPropertyValue(prop), "contain",
  1801      "property " + prop + ": can't interpolate 'contain'");
  1802   test_background_position_size_common(prop);
  1805 function test_background_position_transition(prop) {
  1806   div.style.setProperty("transition-property", "none", "");
  1807   div.style.setProperty(prop, "center 80%", "");
  1808   is(cs.getPropertyValue(prop), "50% 80%",
  1809      "property " + prop + ": computed value before transition");
  1810   div.style.setProperty("transition-property", prop, "");
  1811   div.style.setProperty(prop, "bottom right", "");
  1812   is(cs.getPropertyValue(prop), "62.5% 85%",
  1813      "property " + prop + ": interpolation of percents");
  1814   check_distance(prop, "center 80%", "62.5% 85%", "bottom right");
  1815   test_background_position_size_common(prop);
  1818 function test_background_position_size_common(prop) {
  1819   div.style.setProperty("transition-property", "none", "");
  1820   div.style.setProperty(prop, "40% 0%", "");
  1821   is(cs.getPropertyValue(prop), "40% 0%",
  1822      "property " + prop + ": computed value before transition");
  1823   div.style.setProperty("transition-property", prop, "");
  1824   div.style.setProperty(prop, "0% 0%", "");
  1825   is(cs.getPropertyValue(prop), "30% 0%",
  1826      "property " + prop + ": interpolation of percentages");
  1827   check_distance(prop, "40% 0%", "30% 0%", "0% 0%");
  1829   div.style.setProperty("transition-property", "none", "");
  1830   div.style.setProperty(prop, "0% 40%", "");
  1831   is(cs.getPropertyValue(prop), "0% 40%",
  1832      "property " + prop + ": computed value before transition");
  1833   div.style.setProperty("transition-property", prop, "");
  1834   div.style.setProperty(prop, "0% 0%", "");
  1835   is(cs.getPropertyValue(prop), "0% 30%",
  1836      "property " + prop + ": interpolation of percentages");
  1837   check_distance(prop, "0% 40%", "0% 30%", "0% 0%");
  1839   div.style.setProperty("transition-property", "none", "");
  1840   div.style.setProperty(prop, "10px 40px", "");
  1841   is(cs.getPropertyValue(prop), "10px 40px",
  1842      "property " + prop + ": computed value before transition");
  1843   div.style.setProperty("transition-property", prop, "");
  1844   div.style.setProperty(prop, "50px 0", "");
  1845   is(cs.getPropertyValue(prop), "20px 30px",
  1846      "property " + prop + ": interpolation of lengths");
  1847   check_distance(prop, "10px 40px", "20px 30px", "50px 0");
  1848   div.style.setProperty(prop, "10px 40px, 50px 50px, 30px 20px", "");
  1849   is(cs.getPropertyValue(prop), "10px 40px, 50px 50px, 30px 20px",
  1850      "property " + prop + ": computed value before transition");
  1851   div.style.setProperty(prop, "50px 20px, 70px 50px, 30px 40px", "");
  1852   is(cs.getPropertyValue(prop), "20px 35px, 55px 50px, 30px 25px",
  1853      "property " + prop + ": interpolation of lists of lengths");
  1854   check_distance(prop, "10px 40px, 50px 50px, 30px 20px",
  1855                        "20px 35px, 55px 50px, 30px 25px",
  1856                        "50px 20px, 70px 50px, 30px 40px");
  1857   div.style.setProperty(prop, "10px 40%, 50% 50px, 30% 20%, 5px 10px", "");
  1858   is(cs.getPropertyValue(prop), "10px 40%, 50% 50px, 30% 20%, 5px 10px",
  1859      "property " + prop + ": computed value before transition");
  1860   div.style.setProperty(prop, "50px 20%, 70% 50px, 30% 40%, 25px 50px", "");
  1861   is(cs.getPropertyValue(prop), "20px 35%, 55% 50px, 30% 25%, 10px 20px",
  1862      "property " + prop + ": interpolation of lists of lengths and percents");
  1863   check_distance(prop, "10px 40%, 50% 50px, 30% 20%, 5px 10px",
  1864                        "20px 35%, 55% 50px, 30% 25%, 10px 20px",
  1865                        "50px 20%, 70% 50px, 30% 40%, 25px 50px");
  1866   div.style.setProperty(prop, "20% 40%, 8px 12px", "");
  1867   is(cs.getPropertyValue(prop), "20% 40%, 8px 12px",
  1868      "property " + prop + ": computed value before transition");
  1869   div.style.setProperty(prop, "12px 20px, 40% 16%", "");
  1870   is(cs.getPropertyValue(prop), "calc(3px + 15%) calc(5px + 30%), calc(6px + 10%) calc(9px + 4%)",
  1871      "property " + prop + ": interpolation that computes to calc()");
  1872   check_distance(prop, "20% 40%, 8px 12px",
  1873                        "calc(3px + 15%) calc(5px + 30%), calc(6px + 10%) calc(9px + 4%)",
  1874                        "12px 20px, 40% 16%");
  1875   div.style.setProperty(prop, "calc(20% + 40px) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)", "");
  1876   is(cs.getPropertyValue(prop), "calc(40px + 20%) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)",
  1877      "property " + prop + ": computed value before transition");
  1878   div.style.setProperty(prop, "12px 20%, calc(20%) calc(16px + 60%), calc(8px + 20%) calc(40px + 16%)", "");
  1879   is(cs.getPropertyValue(prop), "calc(33px + 15%) calc(30px + 35%), calc(6px + 5%) calc(4px + 24%), calc(17px + 14%) calc(28px + 10%)",
  1880      "property " + prop + ": interpolation that computes to calc()");
  1881   check_distance(prop, "calc(20% + 40px) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)",
  1882                        "calc(33px + 15%) calc(30px + 35%), calc(6px + 5%) calc(4px + 24%), calc(17px + 14%) calc(28px + 10%)",
  1883                        "12px 20%, calc(20%) calc(16px + 60%), calc(8px + 20%) calc(40px + 16%)");
  1886 function test_transform_transition(prop) {
  1887   is(prop, "transform", "Unexpected transform property!  Test needs to be fixed");
  1888   var matrix_re = /^matrix\(([^,]*), ([^,]*), ([^,]*), ([^,]*), ([^,]*), ([^,]*)\)$/;
  1889   for (var i in transformTests) {
  1890     var test = transformTests[i];
  1891     if (!("expected" in test)) {
  1892       var v = test.expected_uncomputed;
  1893       if (v.match(matrix_re) && !test.force_compute) {
  1894         test.expected = v;
  1895       } else {
  1896         test.expected = computeMatrix(v);
  1901   for (var i in transformTests) {
  1902     var test = transformTests[i];
  1903     div.style.setProperty("transition-property", "none", "");
  1904     div.style.setProperty(prop, test.start, "");
  1905     cs.getPropertyValue(prop);
  1906     div.style.setProperty("transition-property", prop, "");
  1907     div.style.setProperty(prop, test.end, "");
  1908     var actual = cs.getPropertyValue(prop);
  1909     if (!test.round_error_ok || actual == test.expected) {
  1910       // In most cases, we'll get an exact match, but in some cases
  1911       // there can be a small amount of rounding error.
  1912       is(actual, test.expected,
  1913          "interpolation of transitions: " + test.start + " to " + test.end);
  1914     } else {
  1915       function s(mat) {
  1916         return mat.match(matrix_re).slice(1,7);
  1918       var pass = true;
  1919       var actual_split = s(actual);
  1920       var expected_split = s(test.expected);
  1921       for (var i = 0; i < 6; ++i) {
  1922         // Allow differences of 1 at the sixth decimal place, and allow
  1923         // a drop extra for floating point error from the subtraction.
  1924         if (Math.abs(Number(actual_split[i]) - Number(expected_split[i])) >
  1925               0.0000011) {
  1926           pass = false;
  1929       ok(pass,
  1930          "interpolation of transitions: " + test.start + " to " + test.end +
  1931          ": " + actual + " should approximately equal " + test.expected);
  1935   // FIXME: should perhaps test that no clamping occurs
  1937   // These tests check the computed value 2/3 of the way through the transition
  1938   OMTAdiv.style.setProperty("transition-duration", "300s", "");
  1939   OMTAdiv.style.setProperty("transition-timing-function", "linear", "");
  1940   window.requestAnimationFrame(nextAsyncTransformTest);
  1943 function nextAsyncTransformTest()
  1945   var test = transformTests[transformTestIndex];
  1947   if (transformTestIndex >= transformTests.length) {
  1948     window.requestAnimationFrame(asyncOpacityTest);
  1949     return;
  1952   OMTAdiv.style.setProperty("transition-property", "none", "");
  1953   OMTAdiv.style.setProperty("transform", test.start, "");
  1954   OMTACs.getPropertyValue("transform");
  1955   OMTAdiv.style.setProperty("transition-property", "transform", "");
  1956   OMTAdiv.style.setProperty("transform", test.end, "");
  1957   OMTACs.getPropertyValue("transform");
  1959   window.requestAnimationFrame(checkAsyncTransformTest);
  1962 function checkAsyncTransformTest() {
  1963   function s(matrix) {
  1964     return matrix.replace(/^\w*\(/, '').replace(')','').split(/\s*,\s*/);
  1966   winUtils.advanceTimeAndRefresh(200000);
  1967   var test = transformTests[transformTestIndex];
  1968   var async_transform = winUtils.getOMTAOrComputedStyle(OMTAdiv, "transform");
  1969   var computed_transform = OMTACs.getPropertyValue("transform");
  1970   var async_split = s(async_transform);
  1971   var cs_split = s(computed_transform);
  1972   var pass = true;
  1973   for (var j = 0; j < 16; ++j) {
  1974     var epsilon = test.big_omta_round_error ? 0.1 : 0.0001;
  1975     if (Math.abs(Number(async_split[j]) - Number(cs_split[j])) > epsilon) {
  1976       pass = false;
  1979   ok(pass,
  1980      "interpolation of transitions: " + test.start + " to " + test.end +
  1981      ": OMTA - " + async_transform + ", computed style - " + computed_transform);
  1982   transformTestIndex++;
  1983   winUtils.restoreNormalRefresh();
  1984   window.requestAnimationFrame(nextAsyncTransformTest);
  1987 function asyncOpacityTest() {
  1988   OMTAdiv.style.setProperty("transition-property", "none", "");
  1989   OMTAdiv.style.setProperty("opacity", 0, "");
  1990   OMTACs.getPropertyValue("opacity");
  1991   OMTAdiv.style.setProperty("transition-property", "opacity", "");
  1992   OMTAdiv.style.setProperty("opacity", 1, "");
  1993   OMTACs.getPropertyValue("opacity");
  1995   window.requestAnimationFrame(checkAsyncOpacityTest);
  1998 function checkAsyncOpacityTest() {
  1999   winUtils.advanceTimeAndRefresh(200000);
  2000   var async_opacity = winUtils.getOMTAOrComputedStyle(OMTAdiv, "opacity");
  2001   var computed_opacity = OMTACs.getPropertyValue("opacity");
  2002   is(async_opacity, computed_opacity,
  2003      "Async animated opacity should match computed opacity");
  2004   winUtils.restoreNormalRefresh();
  2005   OMTAdiv.style.removeProperty("transition");
  2006   SimpleTest.finish();
  2009 </script>
  2010 </pre>
  2011 </body>
  2012 </html>

mercurial