layout/style/test/test_transitions.html

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     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="application/javascript" src="animation_utils.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; }
    14   #display .before, #display .after {
    15     width: -moz-fit-content; border: 1px solid black;
    16   }
    17   #display .before::before, #display .after::after {
    18     display: block;
    19     width: 0;
    20     text-indent: 0;
    21   }
    22   #display .before.started::before, #display .after.started::after {
    23     width: 100px;
    24     text-indent: 100px;
    25     transition: 8s width ease-in-out, 8s text-indent ease-in-out;
    26   }
    27   #display .before::before {
    28     content: "Before";
    29   }
    30   #display .after::after {
    31     content: "After";
    32   }
    34   </style>
    35 </head>
    36 <body>
    37 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435441">Mozilla Bug 435441</a>
    38 <div id="display">
    40 </div>
    41 <pre id="test">
    42 <script type="application/javascript">
    44 /** Test for Bug 435441 **/
    46 // Run tests simultaneously so we don't have to take up too much time.
    47 SimpleTest.waitForExplicitFinish();
    48 var gTestsRunning = 0;
    49 function TestStarted() { ++gTestsRunning; }
    50 function TestFinished() { if (--gTestsRunning == 0) SimpleTest.finish(); }
    52 // An array of arrays of functions to be called at the outer index number
    53 // of seconds after the present.
    54 var gFutureCalls = [];
    56 function add_future_call(index, func)
    57 {
    58     if (!(index in gFutureCalls)) {
    59         gFutureCalls[index] = [];
    60     }
    61     gFutureCalls[index].push(func);
    62     TestStarted();
    63 }
    64 var gStartTime1, gStartTime2;
    65 var gCurrentTime;
    66 var gSetupComplete = false;
    68 function process_future_calls(index)
    69 {
    70     var calls = gFutureCalls[index];
    71     if (!calls)
    72         return;
    73     gCurrentTime = Date.now();
    74     for (var i = 0; i < calls.length; ++i) {
    75         calls[i]();
    76         TestFinished();
    77     }
    78 }
    80 var timingFunctions = {
    81   // a map from the value of 'transition-timing-function' to an array of
    82   // the portions this function yields at 0 (always 0), 1/4, 1/2, and
    83   // 3/4 and all (always 1) of the way through the time of the
    84   // transition.  Each portion is represented as a value and an
    85   // acceptable error tolerance (based on a time error of 1%) for that
    86   // value.
    88   // ease
    89   "ease": bezier(0.25, 0.1, 0.25, 1),
    90   "cubic-bezier(0.25, 0.1, 0.25, 1.0)": bezier(0.25, 0.1, 0.25, 1),
    92   // linear and various synonyms for it
    93   "linear": function(x) { return x; },
    94   "cubic-bezier(0.0, 0.0, 1.0, 1.0)": function(x) { return x; },
    95   "cubic-bezier(0, 0, 1, 1)": function(x) { return x; },
    96   "cubic-bezier(0, 0, 0, 0.0)": function(x) { return x; },
    97   "cubic-bezier(1.0, 1, 0, 0)": function(x) { return x; },
    99   // ease-in
   100   "ease-in": bezier(0.42, 0, 1, 1),
   101   "cubic-bezier(0.42, 0, 1.0, 1.0)": bezier(0.42, 0, 1, 1),
   103   // ease-out
   104   "ease-out": bezier(0, 0, 0.58, 1),
   105   "cubic-bezier(0, 0, 0.58, 1.0)": bezier(0, 0, 0.58, 1),
   107   // ease-in-out
   108   "ease-in-out": bezier(0.42, 0, 0.58, 1),
   109   "cubic-bezier(0.42, 0, 0.58, 1.0)": bezier(0.42, 0, 0.58, 1),
   111   // other cubic-bezier values
   112   "cubic-bezier(0.4, 0.1, 0.7, 0.95)": bezier(0.4, 0.1, 0.7, 0.95),
   113   "cubic-bezier(1, 0, 0, 1)": bezier(1, 0, 0, 1),
   114   "cubic-bezier(0, 1, 1, 0)": bezier(0, 1, 1, 0),
   116 };
   118 var div = document.getElementById("display");
   120 // Set up all the elements on which we are going to start transitions.
   122 // We have two reference elements to check the expected timing range.
   123 // They both have 8s linear transitions from 0 to 1000px.
   124 function make_reference_p() {
   125     var p = document.createElement("p");
   126     p.appendChild(document.createTextNode("reference"));
   127     p.style.textIndent = "0px";
   128     p.style.transition = "8s text-indent linear";
   129     div.appendChild(p);
   130     return p;
   131 }
   132 var earlyref = make_reference_p();
   133 var earlyrefcs = getComputedStyle(earlyref, "");
   135 // Test all timing functions using a set of 8-second transitions, which
   136 // we check at times 0, 2s, 4s, 6s, and 8s.
   137 var tftests = [];
   138 for (var tf in timingFunctions) {
   139     var p = document.createElement("p");
   140     var t = document.createTextNode("transition-timing-function: " + tf);
   141     p.appendChild(t);
   142     p.style.textIndent = "0px";
   143     p.style.transition = "8s text-indent linear";
   144     p.style.transitionTimingFunction = tf;
   145     div.appendChild(p);
   146     is(getComputedStyle(p, "").textIndent, "0px",
   147        "should be zero before changing value");
   148     tftests.push([ p, tf ]);
   149 }
   151 // Check that the timing function continues even when we restyle in the
   152 // middle.
   153 var interrupt_tests = [];
   154 for (var restyleParent of [true, false]) {
   155     for (var itime = 2; itime < 8; itime += 2) {
   156         var p = document.createElement("p");
   157         var t = document.createTextNode("interrupt on " +
   158                                         (restyleParent ? "parent" : "node itself") +
   159                                         " at " + itime + "s");
   160         p.appendChild(t);
   161         p.style.textIndent = "0px";
   162         p.style.transition = "8s text-indent cubic-bezier(0, 1, 1, 0)";
   163         if (restyleParent) {
   164           var d = document.createElement("div");
   165           d.appendChild(p);
   166           div.appendChild(d);
   167         } else {
   168           div.appendChild(p);
   169         }
   170         is(getComputedStyle(p, "").textIndent, "0px",
   171            "should be zero before changing value");
   172         setTimeout("interrupt_tests[" + interrupt_tests.length + "]" +
   173                    "[0]" + (restyleParent ? ".parentNode" : "") +
   174                    ".style.color = 'blue';" +
   175                    "check_interrupt_tests()", itime*1000);
   176         interrupt_tests.push([ p, itime ]);
   177     }
   178 }
   180 // Test transition-delay values of -4s through 4s on a 4s transition
   181 // with 'ease-out' timing function.
   182 var delay_tests = {};
   183 for (var d = -4; d <= 4; ++d) {
   184     var p = document.createElement("p");
   185     var delay = d + "s";
   186     var t = document.createTextNode("transition-delay: " + delay);
   187     p.appendChild(t);
   188     p.style.marginLeft = "0px";
   189     p.style.transition = "4s margin-left ease-out " + delay;
   190     div.appendChild(p);
   191     is(getComputedStyle(p, "").marginLeft, "0px",
   192        "should be zero before changing value");
   193     delay_tests[d] = p;
   194 }
   196 // Test transition-delay values of -4s through 4s on a 4s transition
   197 // with duration of zero.
   198 var delay_zero_tests = {};
   199 for (var d = -4; d <= 4; ++d) {
   200     var p = document.createElement("p");
   201     var delay = d + "s";
   202     var t = document.createTextNode("transition-delay: " + delay);
   203     p.appendChild(t);
   204     p.style.marginLeft = "0px";
   205     p.style.transition = "0s margin-left linear " + delay;
   206     div.appendChild(p);
   207     is(getComputedStyle(p, "").marginLeft, "0px",
   208        "should be zero before changing value");
   209     delay_zero_tests[d] = p;
   210 }
   212 // Test that changing the value on an already-running transition to the
   213 // value it currently happens to have resets the transition.
   214 function make_reset_test(transition, description)
   215 {
   216     var p = document.createElement("p");
   217     var t = document.createTextNode(description);
   218     p.appendChild(t);
   219     p.style.marginLeft = "0px";
   220     p.style.transition = transition;
   221     div.appendChild(p);
   222     is(getComputedStyle(p, "").marginLeft, "0px",
   223        "should be zero before changing value");
   224     return p;
   225 }
   226 var reset_test = make_reset_test("4s margin-left ease-out 4s", "transition-delay reset to starting point");
   227 var reset_test_reference = make_reset_test("4s margin-left linear -3s", "reference for previous test (reset test)");
   229 // Test that transitions on descendants do not trigger when the
   230 // inherited value is itself transitioning.  In other words, when
   231 // ancestor and descendant both have a transition for the same property,
   232 // and the descendant inherits the property from the ancestor, the
   233 // descendant's transition is ignored (as part of the idea of not
   234 // starting transitions on changes that result from animation).
   235 // See http://lists.w3.org/Archives/Public/www-style/2009Jun/0121.html
   236 // and http://lists.w3.org/Archives/Public/www-style/2009Jul/0050.html
   237 var descendant_tests = [
   238     { parent_transition: "",
   239       child_transition: "4s text-indent" },
   240     { parent_transition: "4s text-indent",
   241       child_transition: "" },
   242     { parent_transition: "4s text-indent",
   243       child_transition: "16s text-indent" },
   244     { parent_transition: "4s text-indent",
   245       child_transition: "1s text-indent" },
   246     { parent_transition: "8s letter-spacing",
   247       child_transition: "4s text-indent" },
   248     { parent_transition: "4s text-indent",
   249       child_transition: "8s letter-spacing" },
   250     { parent_transition: "4s text-indent",
   251       child_transition: "8s all" },
   252     { parent_transition: "8s text-indent",
   253       child_transition: "4s all" },
   254     // examples with positive and negative delay
   255     { parent_transition: "4s text-indent 1s",
   256       child_transition: "8s text-indent" },
   257     { parent_transition: "4s text-indent -1s",
   258       child_transition: "8s text-indent" }
   259 ];
   261 for (var i in descendant_tests) {
   262     var test = descendant_tests[i];
   263     test.parentNode = document.createElement("div");
   264     test.childNode = document.createElement("p");
   265     test.parentNode.appendChild(test.childNode);
   266     test.childNode.appendChild(document.createTextNode(
   267         "parent with \"" + test.parent_transition + "\" and " +
   268         "child with \"" + test.child_transition + "\""));
   269     test.parentNode.style.transition = test.parent_transition;
   270     test.childNode.style.transition = test.child_transition;
   271     test.parentNode.style.textIndent = "50px"; // transition from 50 to 150
   272     test.parentNode.style.letterSpacing = "10px"; // transition from 10 to 5
   273     div.appendChild(test.parentNode);
   274     var parentCS = getComputedStyle(test.parentNode, "");
   275     var childCS = getComputedStyle(test.childNode, "");
   276     is(parentCS.textIndent, "50px",
   277        "parent text-indent should be 50px before changing");
   278     is(parentCS.letterSpacing, "10px",
   279        "parent letter-spacing should be 10px before changing");
   280     is(childCS.textIndent, "50px",
   281        "child text-indent should be 50px before changing");
   282     is(childCS.letterSpacing, "10px",
   283        "child letter-spacing should be 10px before changing");
   284     test.childCS = childCS;
   285 }
   287 // For all of these transitions, the transition for margin-left should
   288 // have a duration of 8s, and the default timing function (ease) and
   289 // delay (0).
   290 // This is because we're implementing the proposal in
   291 // http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html
   292 var number_tests = [
   293   { style: "transition: 4s margin, 8s margin-left" },
   294   { style: "transition: 4s margin-left, 8s margin" },
   295   { style: "transition-property: margin-left; " +
   296              "transition-duration: 8s, 2s" },
   297   { style: "transition-property: margin-left, margin-left; " + 
   298              "transition-duration: 2s, 8s" },
   299   { style: "transition-property: margin-left, margin-left, margin-left; " +
   300              "transition-duration: 8s, 2s" },
   301   { style: "transition-property: margin-left; " +
   302              "transition-duration: 8s, 16s" },
   303   { style: "transition-property: margin-left, margin-left; " + 
   304              "transition-duration: 16s, 8s" },
   305   { style: "transition-property: margin-left, margin-left, margin-left; " +
   306              "transition-duration: 8s, 16s" },
   307   { style: "transition-property: text-indent,word-spacing,margin-left; " +
   308              "transition-duration: 8s; " +
   309              "transition-delay: 0, 8s" },
   310   { style: "transition-property: text-indent,word-spacing,margin-left; " +
   311              "transition-duration: 8s, 16s; " +
   312              "transition-delay: 8s, 8s, 0, 8s, 8s, 8s" },
   313 ];
   315 for (var i in number_tests) {
   316     var test = number_tests[i];
   317     var p = document.createElement("p");
   318     p.setAttribute("style", test.style);
   319     var t = document.createTextNode(test.style);
   320     p.appendChild(t);
   321     p.style.marginLeft = "100px";
   322     div.appendChild(p);
   323     is(getComputedStyle(p, "").marginLeft, "100px",
   324        "should be 100px before changing value");
   325     test.node = p;
   326 }
   328 // Test transitions that are also from-display:none, to-display:none, and
   329 // display:none throughout.
   330 var from_none_test, to_none_test, always_none_test;
   331 function make_display_test(initially_none, text)
   332 {
   333     var p = document.createElement("p");
   334     p.appendChild(document.createTextNode(text));
   335     p.style.textIndent = "0px";
   336     p.style.transition = "8s text-indent ease-in-out";
   337     if (initially_none)
   338         p.style.display = "none";
   339     div.appendChild(p);
   340     return p;
   341 }
   342 from_none_test   = make_display_test(true,  "transition from display:none");
   343 to_none_test     = make_display_test(false, "transition to display:none");
   344 always_none_test = make_display_test(true,  "transition always display:none");
   345 var display_tests = [ from_none_test, to_none_test, always_none_test ];
   347 // Test transitions on pseudo-elements
   348 var before_test, after_test;
   349 function make_pseudo_elem_test(pseudo)
   350 {
   351     var p = document.createElement("p");
   352     p.className = pseudo;
   353     div.appendChild(p);
   354     return {"pseudo": pseudo, element: p};
   355 }
   356 before_test = make_pseudo_elem_test("before");
   357 after_test = make_pseudo_elem_test("after");
   358 var pseudo_element_tests = [ before_test, after_test ];
   360 // FIXME (Bug 522599): Test a transition that reverses partway through.
   362 var lateref = make_reference_p();
   363 var laterefcs = getComputedStyle(lateref, "");
   365 // flush style changes
   366 var x = getComputedStyle(div, "").color;
   368 // Start our timer as close as possible to when we start the first
   369 // transition.
   370 // Do not use setInterval because once it gets off in time, it stays off.
   371 for (var i = 1; i <= 8; ++i) {
   372     setTimeout(process_future_calls, i * 1000, i);
   373 }
   374 gStartTime1 = Date.now(); // set before any transitions have started
   376 // Start all the transitions.
   377 earlyref.style.textIndent = "1000px";
   378 for (var test in tftests) {
   379     var p = tftests[test][0];
   380     p.style.textIndent = "100px";
   381 }
   382 for (var test in interrupt_tests) {
   383     var p = interrupt_tests[test][0];
   384     p.style.textIndent = "100px";
   385 }
   386 for (var d in delay_tests) {
   387     var p = delay_tests[d];
   388     p.style.marginLeft = "100px";
   389 }
   390 for (var d in delay_zero_tests) {
   391     var p = delay_zero_tests[d];
   392     p.style.marginLeft = "100px";
   393 }
   394 reset_test.style.marginLeft = "100px";
   395 reset_test_reference.style.marginLeft = "100px";
   396 for (var i in descendant_tests) {
   397     var test = descendant_tests[i];
   398     test.parentNode.style.textIndent = "150px";
   399     test.parentNode.style.letterSpacing = "5px";
   400 }
   401 for (var i in number_tests) {
   402     var test = number_tests[i];
   403     test.node.style.marginLeft = "50px";
   404 }
   405 from_none_test.style.textIndent = "100px";
   406 from_none_test.style.display = "";
   407 to_none_test.style.textIndent = "100px";
   408 to_none_test.style.display = "none";
   409 always_none_test.style.textIndent = "100px";
   410 for (var i in pseudo_element_tests) {
   411     var test = pseudo_element_tests[i];
   412     test.element.classList.add("started");
   413 }
   414 lateref.style.textIndent = "1000px";
   416 // flush style changes
   417 x = getComputedStyle(div, "").color;
   419 gStartTime2 = Date.now(); // set after all transitions have started
   420 gCurrentTime = gStartTime2;
   422 /**
   423  * Assert that a transition whose timing function yields the bezier
   424  * |func|, running from |start_time| to |end_time| (both in seconds
   425  * relative to when the transitions were started) should have produced
   426  * computed value |cval| given that the transition was from
   427  * |start_value| to |end_value| (both numbers in CSS pixels).
   428  */
   429 function check_transition_value(func, start_time, end_time,
   430                                 start_value, end_value, cval, desc,
   431                                 xfail)
   432 {
   433     /**
   434      * Compute the value at a given time |elapsed|, by normalizing the
   435      * input to the timing function using start_time and end_time and
   436      * then turning the output into a value using start_value and
   437      * end_value.
   438      *
   439      * The |error_direction| argument should be either -1, 0, or 1,
   440      * suggesting adding on a little bit of error, to allow for the
   441      * cubic-bezier calculation being an approximation.  The amount of
   442      * error is proportional to the slope of the timing function, since
   443      * the error is added to the *input* of the timing function (after
   444      * normalization to 0-1 based on start_time and end_time).
   445      */
   446     function value_at(elapsed, error_direction) {
   447         var time_portion = (elapsed - start_time) / (end_time - start_time);
   448         if (time_portion < 0)
   449             time_portion = 0;
   450         else if (time_portion > 1)
   451             time_portion = 1;
   452         // Assume a small error since bezier computation can be off slightly.
   453         // (This test's computation is probably more accurate than Mozilla's.)
   454         var value_portion = func(time_portion + error_direction * 0.0005);
   455         if (value_portion < 0)
   456             value_portion = 0;
   457         else if (value_portion > 1)
   458             value_portion = 1;
   459         var value = (1 - value_portion) * start_value + value_portion * end_value;
   460         if (start_value > end_value)
   461             error_direction = -error_direction;
   462         // Computed values get rounded to 1/60th of a pixel.
   463         return value + error_direction * 0.02;
   464     }
   466     var time_range; // in seconds
   467     var uns_range; // |range| before being sorted (so errors give it
   468                    // in the original order
   469     if (!gSetupComplete) {
   470         // No timers involved
   471         time_range = [0, 0];
   472         if (start_time < 0) {
   473             uns_range = [ value_at(0, -1), value_at(0, 1) ];
   474         } else {
   475             var val = value_at(0, 0);
   476             uns_range = [val, val];
   477         }
   478     } else {
   479         time_range = [ px_to_num(earlyrefcs.textIndent) / 125,
   480                        px_to_num(laterefcs.textIndent) / 125 ];
   481         // seconds
   482         uns_range = [ value_at(time_range[0], -1),
   483                       value_at(time_range[1], 1) ];
   484     }
   485     var range = uns_range.concat(). /* concat to clone array */
   486                   sort(function compareNumbers(a,b) { return a - b; });
   487     var actual = px_to_num(cval);
   489     var fn = ok;
   490     if (xfail && xfail(range))
   491       fn = todo;
   493     fn(range[0] <= actual && actual <= range[1],
   494        desc + ": computed value " + cval + " should be between " +
   495        uns_range[0].toFixed(6) + "px and " + uns_range[1].toFixed(6) +
   496        "px at time between " + time_range[0] + "s and " + time_range[1] + "s.");
   497 }
   499 function check_ref_range()
   500 {
   501     // This is the only test where we compare the progress of the
   502     // transitions to an actual time; we need considerable tolerance at
   503     // the low end (we are using half a second).
   504     var expected_range = [ (gCurrentTime - gStartTime2 - 40) / 8,
   505                            (Date.now() - gStartTime1 + 20) / 8 ];
   506     if (expected_range[0] > 1000) {
   507         expected_range[0] = 1000;
   508     }
   509     if (expected_range[1] > 1000) {
   510         expected_range[1] = 1000;
   511     }
   512     function check(desc, value) {
   513         // The timing on the unit test VMs is not reliable, so make this
   514         // test report PASS when it succeeds and TODO when it fails.
   515         var passed = expected_range[0] <= value && value <= expected_range[1];
   516         (passed ? ok : todo)(passed,
   517            desc + ": computed value " + value + "px should be between " +
   518            expected_range[0].toFixed(6) + "px and " +
   519            expected_range[1].toFixed(6) + "px at time between " +
   520            expected_range[0]/125 + "s and " + expected_range[1]/125 + "s.");
   521     }
   522     check("early reference", px_to_num(earlyrefcs.textIndent));
   523     check("late reference", px_to_num(laterefcs.textIndent));
   524 }
   526 for (var i = 1; i <= 8; ++i) {
   527     add_future_call(i, check_ref_range);
   528 }
   530 function check_tf_test()
   531 {
   532     for (var test in tftests) {
   533         var p = tftests[test][0];
   534         var tf = tftests[test][1];
   536         check_transition_value(timingFunctions[tf], 0, 8, 0, 100,
   537                                getComputedStyle(p, "").textIndent,
   538                                "timing function test for timing function " + tf);
   540     }
   542     check_interrupt_tests();
   543 }
   545 check_tf_test();
   546 add_future_call(2, check_tf_test);
   547 add_future_call(4, check_tf_test);
   548 add_future_call(6, check_tf_test);
   549 add_future_call(8, check_tf_test);
   551 function check_interrupt_tests()
   552 {
   553     for (var test in interrupt_tests) {
   554         var p = interrupt_tests[test][0];
   555         var itime = interrupt_tests[test][1];
   557         check_transition_value(timingFunctions["cubic-bezier(0, 1, 1, 0)"],
   558                                0, 8, 0, 100,
   559                                getComputedStyle(p, "").textIndent,
   560                                "interrupt " +
   561                                (p.parentNode == div ? "" : "on parent ") +
   562                                "test for time " + itime + "s");
   563     }
   564 }
   566 // check_interrupt_tests is called from check_tf_test and from
   567 // where we reset the interrupts
   569 function check_delay_test(time)
   570 {
   571     var tf = timingFunctions["ease-out"];
   572     for (var d in delay_tests) {
   573         var p = delay_tests[d];
   575         check_transition_value(tf, Number(d), Number(d) + 4, 0, 100,
   576                                getComputedStyle(p, "").marginLeft,
   577                                "delay test for delay " + d + "s");
   578     }
   579 }
   581 check_delay_test(0);
   582 for (var i = 1; i <= 8; ++i) {
   583     add_future_call(i, check_delay_test);
   584 }
   586 function check_delay_zero_test(time)
   587 {
   588     for (var d in delay_zero_tests) {
   589         var p = delay_zero_tests[d];
   591         time_range = [ px_to_num(earlyrefcs.textIndent) / 125,
   592                        px_to_num(laterefcs.textIndent) / 125 ];
   593         var m = getComputedStyle(p, "").marginLeft;
   594         var desc = "delay_zero test for delay " + d + "s";
   595         if (time_range[0] < d && time_range[1] < d) {
   596             is(m, "0px", desc);
   597         } else if ((time_range[0] > d && time_range[1] > d) ||
   598                    (d == 0 && time == 0)) {
   599             is(m, "100px", desc);
   600         }
   601     }
   602 }
   604 check_delay_zero_test(0);
   605 for (var i = 1; i <= 8; ++i) {
   606     add_future_call(i, check_delay_zero_test);
   607 }
   609 function reset_reset_test(time)
   610 {
   611     reset_test.style.marginLeft = "0px";
   612 }
   613 function check_reset_test(time)
   614 {
   615     is(getComputedStyle(reset_test, "").marginLeft, "0px",
   616        "reset test value at time " + time + "s.");
   617 }
   618 check_reset_test(0);
   619 // reset the reset test right now so we don't have to worry about clock skew
   620 // To make sure that this is valid, check that a pretty-much-identical test is
   621 // already transitioning.
   622 is(getComputedStyle(reset_test_reference, "").marginLeft, "75px",
   623    "reset test reference value");
   624 reset_reset_test();
   625 check_reset_test(0);
   626 for (var i = 1; i <= 8; ++i) {
   627     (function(j) {
   628         add_future_call(j, function() { check_reset_test(j); });
   629     })(i);
   630 }
   632 check_descendant_tests();
   633 add_future_call(2, check_descendant_tests);
   634 add_future_call(6, check_descendant_tests);
   636 function check_descendant_tests() {
   637     // text-indent: transition from 50px to 150px
   638     // letter-spacing: transition from 10px to 5px
   639     var values = {};
   640     values["text-indent"] = [ 50, 150 ];
   641     values["letter-spacing"] = [ 10, 5 ];
   642     var tf = timingFunctions["ease"];
   644     for (var i in descendant_tests) {
   645         var test = descendant_tests[i];
   647         /* ti=text-indent, ls=letter-spacing */
   648         var child_ti_duration = 0;
   649         var child_ls_duration = 0;
   650         var child_ti_delay = 0;
   651         var child_ls_delay = 0;
   653         if (test.parent_transition != "") {
   654             var props = test.parent_transition.split(" ");
   655             var duration = parseInt(props[0]);
   656             var delay = (props.length > 2) ? parseInt(props[2]) : 0;
   657             var property = props[1];
   658             if (property == "text-indent") {
   659                 child_ti_duration = duration;
   660                 child_ti_delay = delay;
   661             } else if (property == "letter-spacing") {
   662                 child_ls_duration = duration;
   663                 child_ls_delay = delay;
   664             } else {
   665                 ok(false, "fix this test (unexpected transition-property " +
   666                           property + " on parent)");
   667             }
   668         }
   670         if (test.child_transition != "") {
   671             var props = test.child_transition.split(" ");
   672             var duration = parseInt(props[0]);
   673             var delay = (props.length > 2) ? parseInt(props[2]) : 0;
   674             var property = props[1];
   675             if (property != "text-indent" && property != "letter-spacing" &&
   676                 property != "all") {
   677                 ok(false, "fix this test (unexpected transition-property " +
   678                           property + " on child)");
   679             }
   681             if (property != "letter-spacing" && child_ti_duration == 0) {
   682                 child_ti_duration = duration;
   683                 child_ti_delay = delay;
   684             }
   685             if (property != "text-indent" && child_ls_duration == 0) {
   686                 child_ls_duration = duration;
   687                 child_ls_delay = delay;
   688             }
   689         }
   691         var time_portions = {
   692           "text-indent":
   693             { duration: child_ti_duration, delay: child_ti_delay },
   694           "letter-spacing":
   695             { duration: child_ls_duration, delay: child_ls_delay },
   696         };
   698         for (var prop in {"text-indent": true, "letter-spacing": true}) {
   699             var time_portion = time_portions[prop];
   701             if (time_portion.duration == 0) {
   702                 time_portion.duration = 0.01;
   703                 time_portion.delay = -1;
   704             }
   706             check_transition_value(tf, time_portion.delay,
   707                                    time_portion.delay + time_portion.duration,
   708                                    values[prop][0], values[prop][1],
   709                                    test.childCS.getPropertyValue(prop),
   710                                    "descendant test, property " + prop);
   711         }
   712     }
   713 }
   715 function check_number_tests()
   716 {
   717     var tf = timingFunctions["ease"];
   718     for (var d in number_tests) {
   719         var test = number_tests[d];
   720         var p = test.node;
   722         check_transition_value(tf, 0, 8, 100, 50,
   723                                getComputedStyle(p, "").marginLeft,
   724                                "number of transitions test for style " +
   725                                  test.style);
   726     }
   727 }
   729 check_number_tests(0);
   730 add_future_call(2, check_number_tests);
   731 add_future_call(4, check_number_tests);
   732 add_future_call(6, check_number_tests);
   733 add_future_call(8, check_number_tests);
   735 function check_display_tests(time)
   736 {
   737     var tf = timingFunctions["ease-in-out"];
   738     for (var i in display_tests) {
   739         var p = display_tests[i];
   741         check_transition_value(tf, 0, 8, 0, 100,
   742                                getComputedStyle(p, "").textIndent,
   743                                "display test for test with " +
   744                                  p.childNodes[0].data,
   745         // TODO: Making transitions work on 'display:none' elements is
   746         // still not implemented.
   747                                function(range) { return p != to_none_test &&
   748                                                  range[1] < 100 });
   749     }
   750 }
   752 check_display_tests(0);
   753 add_future_call(2, function() { check_display_tests(2); });
   754 add_future_call(4, function() { check_display_tests(4); });
   755 add_future_call(6, function() { check_display_tests(6); });
   756 add_future_call(8, function() { check_display_tests(8); });
   758 function check_pseudo_element_tests(time)
   759 {
   760     var tf = timingFunctions["ease-in-out"];
   761     for (var i in pseudo_element_tests) {
   762         var test = pseudo_element_tests[i];
   764         check_transition_value(tf, 0, 8, 0, 100,
   765                                getComputedStyle(test.element, "").width,
   766                                "::"+test.pseudo+" test");
   767         check_transition_value(tf, 0, 8, 0, 100,
   768                                getComputedStyle(test.element,
   769                                                 "::"+test.pseudo).textIndent,
   770                                "::"+test.pseudo+" indent test");
   771     }
   772 }
   773 check_pseudo_element_tests(0);
   774 add_future_call(2, function() { check_pseudo_element_tests(2); });
   775 add_future_call(4, function() { check_pseudo_element_tests(4); });
   776 add_future_call(6, function() { check_pseudo_element_tests(6); });
   777 add_future_call(8, function() { check_pseudo_element_tests(8); });
   779 gSetupComplete = true;
   780 </script>
   781 </pre>
   782 </body>
   783 </html>

mercurial