layout/style/test/test_animations.html

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/style/test/test_animations.html	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1547 @@
     1.4 +<!DOCTYPE HTML>
     1.5 +<html>
     1.6 +<!--
     1.7 +https://bugzilla.mozilla.org/show_bug.cgi?id=435442
     1.8 +-->
     1.9 +<!--
    1.10 +
    1.11 + ====== PLEASE KEEP THIS IN SYNC WITH test_animations_omta.html =======
    1.12 +
    1.13 + test_animations_omta.html mimicks the content of this file but with
    1.14 + extra machinery for testing animation values on the compositor thread.
    1.15 +
    1.16 + If you are making changes to this file or to test_animations_omta.html, please
    1.17 + try to keep them consistent where appropriate.
    1.18 +
    1.19 +-->
    1.20 +<head>
    1.21 +  <title>Test for css3-animations (Bug 435442)</title>
    1.22 +  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
    1.23 +  <script type="application/javascript" src="animation_utils.js"></script>
    1.24 +  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
    1.25 +  <style type="text/css">
    1.26 +  @keyframes anim1 {
    1.27 +     0% { margin-left: 0px }
    1.28 +     50% { margin-left: 80px }
    1.29 +     100% { margin-left: 100px }
    1.30 +  }
    1.31 +  @keyframes anim2 {
    1.32 +    from { margin-right: 0 } to { margin-right: 100px }
    1.33 +  }
    1.34 +  @keyframes anim3 {
    1.35 +    from { margin-top: 0 } to { margin-top: 100px }
    1.36 +  }
    1.37 +  @keyframes anim4 {
    1.38 +    from { margin-bottom: 0 } to { margin-bottom: 100px }
    1.39 +  }
    1.40 +  @keyframes anim5 {
    1.41 +    from { margin-left: 0 } to { margin-left: 100px }
    1.42 +  }
    1.43 +
    1.44 +  @keyframes kf1 {
    1.45 +    50% { margin-top: 50px }
    1.46 +    to { margin-top: 150px }
    1.47 +  }
    1.48 +  @keyframes kf2 {
    1.49 +    from { margin-top: 150px }
    1.50 +    50% { margin-top: 50px }
    1.51 +  }
    1.52 +  @keyframes kf3 {
    1.53 +    25% { margin-top: 100px }
    1.54 +  }
    1.55 +  @keyframes kf4 {
    1.56 +    to, from { display: inline; margin-top: 37px }
    1.57 +  }
    1.58 +  @keyframes kf_cascade1 {
    1.59 +    from { padding-top: 50px }
    1.60 +    50%, from { padding-top: 30px }      /* wins: 0% */
    1.61 +    75%, 85%, 50% { padding-top: 20px }  /* wins: 75%, 50% */
    1.62 +    100%, 85% { padding-top: 70px }      /* wins: 100% */
    1.63 +    85.1% { padding-top: 60px }          /* wins: 85.1% */
    1.64 +    85% { padding-top: 30px }            /* wins: 85% */
    1.65 +  }
    1.66 +  @keyframes kf_cascade2 { from, to { margin-top: 100px } }
    1.67 +  @keyframes kf_cascade2 { from, to { margin-left: 200px } }
    1.68 +  @keyframes kf_cascade2 { from, to { margin-left: 300px } }
    1.69 +  @keyframes kf_tf1 {
    1.70 +    0%   { padding-bottom: 20px; animation-timing-function: ease }
    1.71 +    25%  { padding-bottom: 60px; }
    1.72 +    50%  { padding-bottom: 160px; animation-timing-function: steps(5) }
    1.73 +    75%  { padding-bottom: 120px; animation-timing-function: linear }
    1.74 +    100% { padding-bottom: 20px; animation-timing-function: ease-out }
    1.75 +  }
    1.76 +
    1.77 +  @keyframes always_fifty {
    1.78 +    from, to { margin-left: 50px }
    1.79 +  }
    1.80 +
    1.81 +  #withbefore::before, #withafter::after {
    1.82 +    content: "";
    1.83 +    animation: anim2 1s linear alternate 3;
    1.84 +  }
    1.85 +
    1.86 +  @keyframes multiprop {
    1.87 +    0% {
    1.88 +      padding-top: 10px; padding-left: 30px;
    1.89 +      animation-timing-function: ease;
    1.90 +    }
    1.91 +    25% {
    1.92 +      padding-left: 50px;
    1.93 +      animation-timing-function: ease-out;
    1.94 +    }
    1.95 +    50% {
    1.96 +      padding-top: 40px;
    1.97 +    }
    1.98 +    75% {
    1.99 +      padding-top: 80px; padding-left: 60px;
   1.100 +      animation-timing-function: ease-in;
   1.101 +    }
   1.102 +  }
   1.103 +
   1.104 +  @keyframes uaoverride {
   1.105 +    0%, 100% { line-height: 3; margin-top: 20px }
   1.106 +    50% { margin-top: 120px }
   1.107 +  }
   1.108 +
   1.109 +  @keyframes cascade {
   1.110 +    0%, 25%, 100% { top: 0 }
   1.111 +    50%, 75% { top: 100px }
   1.112 +    0%, 75%, 100% { left: 0 }
   1.113 +    25%, 50% { left: 100px }
   1.114 +  }
   1.115 +  @keyframes cascade2 {
   1.116 +    0% { text-indent: 0 }
   1.117 +    25% { text-indent: 30px; animation-timing-function: ease-in } /* beaten by rule below */
   1.118 +    50% { text-indent: 0 }
   1.119 +    25% { text-indent: 50px }
   1.120 +    100% { text-indent: 100px }
   1.121 +  }
   1.122 +
   1.123 +  @keyframes primitives1 {
   1.124 +    from { -moz-transform: rotate(0deg) translateX(0px) scaleX(1)
   1.125 +      translate(0px) scale3d(1, 1, 1); }
   1.126 +    to { -moz-transform: rotate(270deg) translate3d(0px, 0px, 0px) scale(1)
   1.127 +      translateY(0px) scaleY(1); }
   1.128 +  }
   1.129 +
   1.130 +  @keyframes important1 {
   1.131 +    from { margin-top: 50px; }
   1.132 +    50%  { margin-top: 150px !important; } /* ignored */
   1.133 +    to   { margin-top: 100px; }
   1.134 +  }
   1.135 +
   1.136 +  @keyframes important2 {
   1.137 +    from { margin-top: 50px;
   1.138 +           margin-bottom: 100px; }
   1.139 +    to   { margin-top: 150px !important; /* ignored */
   1.140 +           margin-bottom: 50px; }
   1.141 +  }
   1.142 +  </style>
   1.143 +</head>
   1.144 +<body>
   1.145 +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435442">Mozilla Bug 435442</a>
   1.146 +<div id="display"></div>
   1.147 +<pre id="test">
   1.148 +<script type="application/javascript">
   1.149 +"use strict";
   1.150 +
   1.151 +/** Test for css3-animations (Bug 435442) **/
   1.152 +
   1.153 +var e = new AnimationEvent("foo",
   1.154 +                            {
   1.155 +                              bubbles: true,
   1.156 +                              cancelable: true,
   1.157 +                              animationName: "name",
   1.158 +                              elapsedTime: 0.5,
   1.159 +                              pseudoElement: "pseudo"
   1.160 +                            });
   1.161 +is(e.bubbles, true);
   1.162 +is(e.cancelable, true);
   1.163 +is(e.animationName, "name");
   1.164 +is(e.elapsedTime, 0.5);
   1.165 +is(e.pseudoElement, "pseudo");
   1.166 +is(e.isTrusted, false)
   1.167 +
   1.168 +function advance_clock(milliseconds) {
   1.169 +  SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(milliseconds);
   1.170 +}
   1.171 +
   1.172 +var display = document.getElementById("display");
   1.173 +var div = null;
   1.174 +var cs = null;
   1.175 +var events_received = [];
   1.176 +function new_div(style) {
   1.177 +  return new_element("div", style);
   1.178 +}
   1.179 +function new_element(tagname, style) {
   1.180 +  if (div != null || cs != null) {
   1.181 +    ok(false, "test author forgot to call done_div");
   1.182 +  }
   1.183 +  if (typeof(style) != "string") {
   1.184 +    ok(false, "test author forgot to pass argument");
   1.185 +  }
   1.186 +  div = document.createElement(tagname);
   1.187 +  div.setAttribute("style", style);
   1.188 +  display.appendChild(div);
   1.189 +  cs = getComputedStyle(div, "");
   1.190 +}
   1.191 +function listen() {
   1.192 +  events_received = [];
   1.193 +  function listener(event) {
   1.194 +    events_received.push(event);
   1.195 +  }
   1.196 +  div.addEventListener("animationstart", listener, false);
   1.197 +  div.addEventListener("animationiteration", listener, false);
   1.198 +  div.addEventListener("animationend", listener, false);
   1.199 +}
   1.200 +function check_events(events_expected, desc) {
   1.201 +  // This function checks that the list of events_expected matches
   1.202 +  // the received events -- but it only checks the properties that
   1.203 +  // are present on events_expected.
   1.204 +  is(events_received.length, events_expected.length,
   1.205 +     "number of events received for " + desc);
   1.206 +  for (var i = 0,
   1.207 +       i_end = Math.min(events_expected.length, events_received.length);
   1.208 +       i != i_end; ++i) {
   1.209 +    var exp = events_expected[i];
   1.210 +    var rec = events_received[i];
   1.211 +    for (var prop in exp) {
   1.212 +      if (prop == "elapsedTime") {
   1.213 +        // Allow floating point error.
   1.214 +        ok(Math.abs(rec.elapsedTime - exp.elapsedTime) < 0.000002,
   1.215 +           "events[" + i + "]." + prop + " for " + desc +
   1.216 +           " received=" + rec.elapsedTime + " expected=" + exp.elapsedTime);
   1.217 +      } else {
   1.218 +        is(rec[prop], exp[prop], "events[" + i + "]." + prop + " for " + desc);
   1.219 +      }
   1.220 +    }
   1.221 +  }
   1.222 +  for (var i = events_expected.length; i < events_received.length; ++i) {
   1.223 +    ok(false, "unexpected " + events_received[i].type + " event for " + desc);
   1.224 +  }
   1.225 +  events_received = [];
   1.226 +}
   1.227 +function done_div() {
   1.228 +  display.removeChild(div);
   1.229 +  div = null;
   1.230 +  cs = null;
   1.231 +  if (events_received.length) {
   1.232 +    ok(false, "caller should have called check_events");
   1.233 +  }
   1.234 +}
   1.235 +
   1.236 +// take over the refresh driver right from the start.
   1.237 +advance_clock(0);
   1.238 +
   1.239 +/*
   1.240 + * css3-animations:  2. Animations
   1.241 + * http://dev.w3.org/csswg/css3-animations/#animations
   1.242 + */
   1.243 +
   1.244 +// Test that animations don't affect the computed value before the
   1.245 +// start of the animation or after its end.  Test without
   1.246 +// animation-fill-mode, but then repeat the test with all the values of
   1.247 +// animation-fill-mode.
   1.248 +function test_fill_mode(fill_mode, fills_backwards, fills_forwards)
   1.249 +{
   1.250 +  var style = "margin-left: 30px; animation: 10s 3s anim1 linear";
   1.251 +  var desc;
   1.252 +  if (fill_mode.length > 0) {
   1.253 +    style += " " + fill_mode;
   1.254 +    desc = "fill mode " + fill_mode + ": ";
   1.255 +  } else {
   1.256 +    desc = "default fill mode: ";
   1.257 +  }
   1.258 +  new_div(style);
   1.259 +  listen();
   1.260 +  if (fills_backwards)
   1.261 +    is(cs.marginLeft, "0px", desc + "does affect value during delay (0s)");
   1.262 +  else
   1.263 +    is(cs.marginLeft, "30px", desc + "doesn't affect value during delay (0s)");
   1.264 +  advance_clock(2000);
   1.265 +  if (fills_backwards)
   1.266 +    is(cs.marginLeft, "0px", desc + "does affect value during delay (2s)");
   1.267 +  else
   1.268 +    is(cs.marginLeft, "30px", desc + "doesn't affect value during delay (2s)");
   1.269 +  check_events([], "before start in test_fill_mode");
   1.270 +  advance_clock(1000);
   1.271 +  check_events([{ type: 'animationstart', target: div,
   1.272 +                  bubbles: true, cancelable: false,
   1.273 +                  animationName: 'anim1', elapsedTime: 0.0,
   1.274 +                  pseudoElement: "" }],
   1.275 +               "right after start in test_fill_mode");
   1.276 +  if (fills_backwards)
   1.277 +    is(cs.marginLeft, "0px", desc + "affects value at start of animation");
   1.278 +  advance_clock(125);
   1.279 +  is(cs.marginLeft, "2px", desc + "affects value during animation");
   1.280 +  advance_clock(2375);
   1.281 +  is(cs.marginLeft, "40px", desc + "affects value during animation");
   1.282 +  advance_clock(2500);
   1.283 +  is(cs.marginLeft, "80px", desc + "affects value during animation");
   1.284 +  advance_clock(2500);
   1.285 +  is(cs.marginLeft, "90px", desc + "affects value during animation");
   1.286 +  advance_clock(2375);
   1.287 +  is(cs.marginLeft, "99.5px", desc + "affects value during animation");
   1.288 +  check_events([], "before end in test_fill_mode");
   1.289 +  advance_clock(125);
   1.290 +  check_events([{ type: 'animationend', target: div,
   1.291 +                  bubbles: true, cancelable: false,
   1.292 +                  animationName: 'anim1', elapsedTime: 10.0,
   1.293 +                  pseudoElement: "" }],
   1.294 +               "right after end in test_fill_mode");
   1.295 +  if (fills_forwards)
   1.296 +    is(cs.marginLeft, "100px", desc + "affects value at end of animation");
   1.297 +  advance_clock(10);
   1.298 +  if (fills_forwards)
   1.299 +    is(cs.marginLeft, "100px", desc + "does affect value after animation");
   1.300 +  else
   1.301 +    is(cs.marginLeft, "30px", desc + "does not affect value after animation");
   1.302 +  done_div();
   1.303 +}
   1.304 +test_fill_mode("", false, false);
   1.305 +test_fill_mode("none", false, false);
   1.306 +test_fill_mode("forwards", false, true);
   1.307 +test_fill_mode("backwards", true, false);
   1.308 +test_fill_mode("both", true, true);
   1.309 +
   1.310 +// Test that animations continue running when the animation name
   1.311 +// list is changed.
   1.312 +new_div("animation: anim1 linear 10s");
   1.313 +  is(cs.getPropertyValue("margin-top"), "0px",
   1.314 +     "just anim1, margin-top at start");
   1.315 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.316 +     "just anim1, margin-right at start");
   1.317 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.318 +     "just anim1, margin-bottom at start");
   1.319 +  is(cs.getPropertyValue("margin-left"), "0px",
   1.320 +     "just anim1, margin-left at start");
   1.321 +advance_clock(1000);
   1.322 +  is(cs.getPropertyValue("margin-top"), "0px",
   1.323 +     "just anim1, margin-top at 1s");
   1.324 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.325 +     "just anim1, margin-right at 1s");
   1.326 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.327 +     "just anim1, margin-bottom at 1s");
   1.328 +  is(cs.getPropertyValue("margin-left"), "16px",
   1.329 +     "just anim1, margin-left at 1s");
   1.330 +// append anim2
   1.331 +div.style.animation = "anim1 linear 10s, anim2 linear 10s";
   1.332 +  is(cs.getPropertyValue("margin-top"), "0px",
   1.333 +     "anim1 + anim2, margin-top at 1s");
   1.334 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.335 +     "anim1 + anim2, margin-right at 1s");
   1.336 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.337 +     "anim1 + anim2, margin-bottom at 1s");
   1.338 +  is(cs.getPropertyValue("margin-left"), "16px",
   1.339 +     "anim1 + anim2, margin-left at 1s");
   1.340 +advance_clock(1000);
   1.341 +  is(cs.getPropertyValue("margin-top"), "0px",
   1.342 +     "anim1 + anim2, margin-top at 2s");
   1.343 +  is(cs.getPropertyValue("margin-right"), "10px",
   1.344 +     "anim1 + anim2, margin-right at 2s");
   1.345 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.346 +     "anim1 + anim2, margin-bottom at 2s");
   1.347 +  is(cs.getPropertyValue("margin-left"), "32px",
   1.348 +     "anim1 + anim2, margin-left at 2s");
   1.349 +// prepend anim3
   1.350 +div.style.animation = "anim3 linear 10s, anim1 linear 10s, anim2 linear 10s";
   1.351 +  is(cs.getPropertyValue("margin-top"), "0px",
   1.352 +     "anim3 + anim1 + anim2, margin-top at 2s");
   1.353 +  is(cs.getPropertyValue("margin-right"), "10px",
   1.354 +     "anim3 + anim1 + anim2, margin-right at 2s");
   1.355 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.356 +     "anim3 + anim1 + anim2, margin-bottom at 2s");
   1.357 +  is(cs.getPropertyValue("margin-left"), "32px",
   1.358 +     "anim3 + anim1 + anim2, margin-left at 2s");
   1.359 +advance_clock(1000);
   1.360 +  is(cs.getPropertyValue("margin-top"), "10px",
   1.361 +     "anim3 + anim1 + anim2, margin-top at 3s");
   1.362 +  is(cs.getPropertyValue("margin-right"), "20px",
   1.363 +     "anim3 + anim1 + anim2, margin-right at 3s");
   1.364 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.365 +     "anim3 + anim1 + anim2, margin-bottom at 3s");
   1.366 +  is(cs.getPropertyValue("margin-left"), "48px",
   1.367 +     "anim3 + anim1 + anim2, margin-left at 3s");
   1.368 +// remove anim2 from end
   1.369 +div.style.animation = "anim3 linear 10s, anim1 linear 10s";
   1.370 +  is(cs.getPropertyValue("margin-top"), "10px",
   1.371 +     "anim3 + anim1, margin-top at 3s");
   1.372 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.373 +     "anim3 + anim1, margin-right at 3s");
   1.374 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.375 +     "anim3 + anim1, margin-bottom at 3s");
   1.376 +  is(cs.getPropertyValue("margin-left"), "48px",
   1.377 +     "anim3 + anim1, margin-left at 3s");
   1.378 +advance_clock(1000);
   1.379 +  is(cs.getPropertyValue("margin-top"), "20px",
   1.380 +     "anim3 + anim1, margin-top at 4s");
   1.381 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.382 +     "anim3 + anim1, margin-right at 4s");
   1.383 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.384 +     "anim3 + anim1, margin-bottom at 4s");
   1.385 +  is(cs.getPropertyValue("margin-left"), "64px",
   1.386 +     "anim3 + anim1, margin-left at 4s");
   1.387 +// swap anim1 and anim3, change duration of anim3
   1.388 +div.style.animation = "anim1 linear 10s, anim3 linear 5s";
   1.389 +  is(cs.getPropertyValue("margin-top"), "40px",
   1.390 +     "anim1 + anim3, margin-top at 4s");
   1.391 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.392 +     "anim1 + anim3, margin-right at 4s");
   1.393 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.394 +     "anim1 + anim3, margin-bottom at 4s");
   1.395 +  is(cs.getPropertyValue("margin-left"), "64px",
   1.396 +     "anim1 + anim3, margin-left at 4s");
   1.397 +advance_clock(1000);
   1.398 +  is(cs.getPropertyValue("margin-top"), "60px",
   1.399 +     "anim1 + anim3, margin-top at 5s");
   1.400 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.401 +     "anim1 + anim3, margin-right at 5s");
   1.402 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.403 +     "anim1 + anim3, margin-bottom at 5s");
   1.404 +  is(cs.getPropertyValue("margin-left"), "80px",
   1.405 +     "anim1 + anim3, margin-left at 5s");
   1.406 +// list anim1 twice, last duration wins, original start time still applies
   1.407 +div.style.animation = "anim1 linear 10s, anim3 linear 5s, anim1 linear 20s";
   1.408 +  is(cs.getPropertyValue("margin-top"), "60px",
   1.409 +     "anim1 + anim3 + anim1, margin-top at 5s");
   1.410 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.411 +     "anim1 + anim3 + anim1, margin-right at 5s");
   1.412 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.413 +     "anim1 + anim3 + anim1, margin-bottom at 5s");
   1.414 +  is(cs.getPropertyValue("margin-left"), "40px",
   1.415 +     "anim1 + anim3 + anim1, margin-left at 5s");
   1.416 +// drop one of the anim1, and list anim5 as well, which animates
   1.417 +// the same property as anim1
   1.418 +div.style.animation = "anim3 linear 5s, anim1 linear 20s, anim5 linear 10s";
   1.419 +  is(cs.getPropertyValue("margin-top"), "60px",
   1.420 +     "anim3 + anim1 + anim5, margin-top at 5s");
   1.421 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.422 +     "anim3 + anim1 + anim5, margin-right at 5s");
   1.423 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.424 +     "anim3 + anim1 + anim5, margin-bottom at 5s");
   1.425 +  is(cs.getPropertyValue("margin-left"), "0px",
   1.426 +     "anim3 + anim1 + anim5, margin-left at 5s");
   1.427 +advance_clock(1000);
   1.428 +  is(cs.getPropertyValue("margin-top"), "80px",
   1.429 +     "anim3 + anim1 + anim5, margin-top at 6s");
   1.430 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.431 +     "anim3 + anim1 + anim5, margin-right at 6s");
   1.432 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.433 +     "anim3 + anim1 + anim5, margin-bottom at 6s");
   1.434 +  is(cs.getPropertyValue("margin-left"), "10px",
   1.435 +     "anim3 + anim1 + anim5, margin-left at 6s");
   1.436 +// now swap the anim5 and anim1 order
   1.437 +div.style.animation = "anim3 linear 5s, anim5 linear 10s, anim1 linear 20s";
   1.438 +  is(cs.getPropertyValue("margin-top"), "80px",
   1.439 +     "anim3 + anim1 + anim5, margin-top at 6s");
   1.440 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.441 +     "anim3 + anim1 + anim5, margin-right at 6s");
   1.442 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.443 +     "anim3 + anim1 + anim5, margin-bottom at 6s");
   1.444 +  is(cs.getPropertyValue("margin-left"), "48px",
   1.445 +     "anim3 + anim1 + anim5, margin-left at 6s");
   1.446 +advance_clock(1000);
   1.447 +  is(cs.getPropertyValue("margin-top"), "0px",
   1.448 +     "anim3 + anim1 + anim5, margin-top at 7s");
   1.449 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.450 +     "anim3 + anim1 + anim5, margin-right at 7s");
   1.451 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.452 +     "anim3 + anim1 + anim5, margin-bottom at 7s");
   1.453 +  is(cs.getPropertyValue("margin-left"), "56px",
   1.454 +     "anim3 + anim1 + anim5, margin-left at 7s");
   1.455 +// swap anim1 and anim5 back
   1.456 +div.style.animation = "anim3 linear 5s, anim1 linear 20s, anim5 linear 10s";
   1.457 +  is(cs.getPropertyValue("margin-top"), "0px",
   1.458 +     "anim3 + anim1 + anim5, margin-top at 7s");
   1.459 +  is(cs.getPropertyValue("margin-right"), "0px",
   1.460 +     "anim3 + anim1 + anim5, margin-right at 7s");
   1.461 +  is(cs.getPropertyValue("margin-bottom"), "0px",
   1.462 +     "anim3 + anim1 + anim5, margin-bottom at 7s");
   1.463 +  is(cs.getPropertyValue("margin-left"), "20px",
   1.464 +     "anim3 + anim1 + anim5, margin-left at 7s");
   1.465 +advance_clock(100);
   1.466 +  is(cs.getPropertyValue("margin-top"), "0px",
   1.467 +     "anim3 + anim1 + anim5, margin-top at 7.1s");
   1.468 +// Change the animation fill mode on the completed animation.
   1.469 +div.style.animation = "anim3 linear 5s forwards, anim1 linear 20s, anim5 linear 10s";
   1.470 +  is(cs.getPropertyValue("margin-top"), "100px",
   1.471 +     "anim3 + anim1 + anim5, margin-top at 7.1s, with fill mode");
   1.472 +advance_clock(900);
   1.473 +  is(cs.getPropertyValue("margin-top"), "100px",
   1.474 +     "anim3 + anim1 + anim5, margin-top at 8s, with fill mode");
   1.475 +// Change the animation duration on the completed animation, so it is
   1.476 +// no longer completed.
   1.477 +div.style.animation = "anim3 linear 10s, anim1 linear 20s, anim5 linear 10s";
   1.478 +  is(cs.getPropertyValue("margin-top"), "60px",
   1.479 +     "anim3 + anim1 + anim5, margin-top at 8s, with fill mode");
   1.480 +  is(cs.getPropertyValue("margin-left"), "30px",
   1.481 +     "anim3 + anim1 + anim5, margin-left at 8s");
   1.482 +done_div();
   1.483 +
   1.484 +/*
   1.485 + * css3-animations:  3. Keyframes
   1.486 + * http://dev.w3.org/csswg/css3-animations/#keyframes
   1.487 + *
   1.488 + * Also see test_keyframes_rules.html .
   1.489 + */
   1.490 +
   1.491 +// Test the rules on keyframes that lack a 0% or 100% rule:
   1.492 +// (simultaneously, test that reverse animations have their keyframes
   1.493 +// run backwards)
   1.494 +
   1.495 +// 100px at 0%, 50px at 50%, 150px at 100%
   1.496 +new_div("margin-top: 100px; animation: kf1 ease 1s alternate infinite");
   1.497 +is(cs.marginTop, "100px", "no-0% at 0.0s");
   1.498 +advance_clock(100);
   1.499 +is_approx(px_to_num(cs.marginTop), 100 - 50 * gTF.ease(0.2), 0.01,
   1.500 +          "no-0% at 0.1s");
   1.501 +advance_clock(200);
   1.502 +is_approx(px_to_num(cs.marginTop), 100 - 50 * gTF.ease(0.6), 0.01,
   1.503 +          "no-0% at 0.3s");
   1.504 +advance_clock(200);
   1.505 +is(cs.marginTop, "50px", "no-0% at 0.5s");
   1.506 +advance_clock(200);
   1.507 +is_approx(px_to_num(cs.marginTop), 50 + 100 * gTF.ease(0.4), 0.01,
   1.508 +          "no-0% at 0.7s");
   1.509 +advance_clock(200);
   1.510 +is_approx(px_to_num(cs.marginTop), 50 + 100 * gTF.ease(0.8), 0.01,
   1.511 +          "no-0% at 0.9s");
   1.512 +advance_clock(100);
   1.513 +is(cs.marginTop, "150px", "no-0% at 1.0s");
   1.514 +advance_clock(100);
   1.515 +is_approx(px_to_num(cs.marginTop), 50 + 100 * gTF.ease(0.8), 0.01,
   1.516 +          "no-0% at 1.1s");
   1.517 +advance_clock(300);
   1.518 +is_approx(px_to_num(cs.marginTop), 50 + 100 * gTF.ease(0.2), 0.01,
   1.519 +          "no-0% at 1.4s");
   1.520 +advance_clock(300);
   1.521 +is_approx(px_to_num(cs.marginTop), 100 - 50 * gTF.ease(0.6), 0.01,
   1.522 +          "no-0% at 1.7s");
   1.523 +advance_clock(200);
   1.524 +is_approx(px_to_num(cs.marginTop), 100 - 50 * gTF.ease(0.2), 0.01,
   1.525 +          "no-0% at 1.9s");
   1.526 +advance_clock(100);
   1.527 +is(cs.marginTop, "100px", "no-0% at 2.0s");
   1.528 +done_div();
   1.529 +
   1.530 +// 150px at 0%, 50px at 50%, 100px at 100%
   1.531 +new_div("margin-top: 100px; animation: kf2 ease-in 1s alternate infinite");
   1.532 +is(cs.marginTop, "150px", "no-100% at 0.0s");
   1.533 +advance_clock(100);
   1.534 +is_approx(px_to_num(cs.marginTop), 150 - 100 * gTF.ease_in(0.2), 0.01,
   1.535 +          "no-100% at 0.1s");
   1.536 +advance_clock(200);
   1.537 +is_approx(px_to_num(cs.marginTop), 150 - 100 * gTF.ease_in(0.6), 0.01,
   1.538 +          "no-100% at 0.3s");
   1.539 +advance_clock(200);
   1.540 +is(cs.marginTop, "50px", "no-100% at 0.5s");
   1.541 +advance_clock(200);
   1.542 +is_approx(px_to_num(cs.marginTop), 50 + 50 * gTF.ease_in(0.4), 0.01,
   1.543 +          "no-100% at 0.7s");
   1.544 +advance_clock(200);
   1.545 +is_approx(px_to_num(cs.marginTop), 50 + 50 * gTF.ease_in(0.8), 0.01,
   1.546 +          "no-100% at 0.9s");
   1.547 +advance_clock(100);
   1.548 +is(cs.marginTop, "100px", "no-100% at 1.0s");
   1.549 +advance_clock(100);
   1.550 +is_approx(px_to_num(cs.marginTop), 50 + 50 * gTF.ease_in(0.8), 0.01,
   1.551 +          "no-100% at 1.1s");
   1.552 +advance_clock(300);
   1.553 +is_approx(px_to_num(cs.marginTop), 50 + 50 * gTF.ease_in(0.2), 0.01,
   1.554 +          "no-100% at 1.4s");
   1.555 +advance_clock(300);
   1.556 +is_approx(px_to_num(cs.marginTop), 150 - 100 * gTF.ease_in(0.6), 0.01,
   1.557 +          "no-100% at 1.7s");
   1.558 +advance_clock(200);
   1.559 +is_approx(px_to_num(cs.marginTop), 150 - 100 * gTF.ease_in(0.2), 0.01,
   1.560 +          "no-100% at 1.9s");
   1.561 +advance_clock(100);
   1.562 +is(cs.marginTop, "150px", "no-100% at 2.0s");
   1.563 +done_div();
   1.564 +
   1.565 +
   1.566 +// 50px at 0%, 100px at 25%, 50px at 100%
   1.567 +new_div("margin-top: 50px; animation: kf3 ease-out 1s alternate infinite");
   1.568 +is(cs.marginTop, "50px", "no-0%-no-100% at 0.0s");
   1.569 +advance_clock(50);
   1.570 +is_approx(px_to_num(cs.marginTop), 50 + 50 * gTF.ease_out(0.2), 0.01,
   1.571 +          "no-0%-no-100% at 0.05s");
   1.572 +advance_clock(100);
   1.573 +is_approx(px_to_num(cs.marginTop), 50 + 50 * gTF.ease_out(0.6), 0.01,
   1.574 +          "no-0%-no-100% at 0.15s");
   1.575 +advance_clock(100);
   1.576 +is(cs.marginTop, "100px", "no-0%-no-100% at 0.25s");
   1.577 +advance_clock(300);
   1.578 +is_approx(px_to_num(cs.marginTop), 100 - 50 * gTF.ease_out(0.4), 0.01,
   1.579 +          "no-0%-no-100% at 0.55s");
   1.580 +advance_clock(300);
   1.581 +is_approx(px_to_num(cs.marginTop), 100 - 50 * gTF.ease_out(0.8), 0.01,
   1.582 +          "no-0%-no-100% at 0.85s");
   1.583 +advance_clock(150);
   1.584 +is(cs.marginTop, "50px", "no-0%-no-100% at 1.0s");
   1.585 +advance_clock(150);
   1.586 +is_approx(px_to_num(cs.marginTop), 100 - 50 * gTF.ease_out(0.8), 0.01,
   1.587 +          "no-0%-no-100% at 1.15s");
   1.588 +advance_clock(450);
   1.589 +is_approx(px_to_num(cs.marginTop), 100 - 50 * gTF.ease_out(0.2), 0.01,
   1.590 +          "no-0%-no-100% at 1.6s");
   1.591 +advance_clock(250);
   1.592 +is_approx(px_to_num(cs.marginTop), 50 + 50 * gTF.ease_out(0.6), 0.01,
   1.593 +          "no-0%-no-100% at 1.85s");
   1.594 +advance_clock(100);
   1.595 +is_approx(px_to_num(cs.marginTop), 50 + 50 * gTF.ease_out(0.2), 0.01,
   1.596 +          "no-0%-no-100% at 1.95s");
   1.597 +advance_clock(50);
   1.598 +is(cs.marginTop, "50px", "no-0%-no-100% at 2.0s");
   1.599 +done_div();
   1.600 +
   1.601 +// Test that non-animatable properties are ignored.
   1.602 +// Simultaneously, test that the block is still honored, and that
   1.603 +// we still override the value when two consecutive keyframes have
   1.604 +// the same value.
   1.605 +new_div("animation: kf4 ease 10s");
   1.606 +is(cs.display, "block",
   1.607 +   "non-animatable properties should be ignored (linear, 0s)");
   1.608 +is(cs.marginTop, "37px",
   1.609 +   "animatable properties should still apply (linear, 0s)");
   1.610 +advance_clock(1000);
   1.611 +is(cs.display, "block",
   1.612 +   "non-animatable properties should be ignored (linear, 1s)");
   1.613 +is(cs.marginTop, "37px",
   1.614 +   "animatable properties should still apply (linear, 1s)");
   1.615 +done_div();
   1.616 +new_div("animation: kf4 step-start 10s");
   1.617 +is(cs.display, "block",
   1.618 +   "non-animatable properties should be ignored (step-start, 0s)");
   1.619 +is(cs.marginTop, "37px",
   1.620 +   "animatable properties should still apply (step-start, 0s)");
   1.621 +advance_clock(1000);
   1.622 +is(cs.display, "block",
   1.623 +   "non-animatable properties should be ignored (step-start, 1s)");
   1.624 +is(cs.marginTop, "37px",
   1.625 +   "animatable properties should still apply (step-start, 1s)");
   1.626 +done_div();
   1.627 +
   1.628 +// Test cascading of the keyframes within an @keyframes rule.
   1.629 +new_div("animation: kf_cascade1 linear 10s");
   1.630 +//   0%: 30px
   1.631 +//  50%: 20px
   1.632 +//  75%: 20px
   1.633 +//  85%: 30px
   1.634 +//  85.1%: 60px
   1.635 +// 100%: 70px
   1.636 +is(cs.paddingTop, "30px", "kf_cascade1 at 0s");
   1.637 +advance_clock(2500);
   1.638 +is(cs.paddingTop, "25px", "kf_cascade1 at 2.5s");
   1.639 +advance_clock(2500);
   1.640 +is(cs.paddingTop, "20px", "kf_cascade1 at 5s");
   1.641 +advance_clock(2000);
   1.642 +is(cs.paddingTop, "20px", "kf_cascade1 at 7s");
   1.643 +advance_clock(500);
   1.644 +is(cs.paddingTop, "20px", "kf_cascade1 at 7.5s");
   1.645 +advance_clock(500);
   1.646 +is(cs.paddingTop, "25px", "kf_cascade1 at 8s");
   1.647 +advance_clock(500);
   1.648 +is(cs.paddingTop, "30px", "kf_cascade1 at 8.5s");
   1.649 +advance_clock(10);
   1.650 +is(cs.paddingTop, "60px", "kf_cascade1 at 8.51s");
   1.651 +advance_clock(745);
   1.652 +is(cs.paddingTop, "65px", "kf_cascade1 at 9.2505s");
   1.653 +done_div();
   1.654 +
   1.655 +// Test cascading of the @keyframes rules themselves.
   1.656 +new_div("animation: kf_cascade2 linear 10s");
   1.657 +is(cs.marginTop, "0px", "@keyframes rule with margin-top should be ignored");
   1.658 +is(cs.marginLeft, "300px", "last @keyframes rule with margin-left should win");
   1.659 +done_div();
   1.660 +
   1.661 +/*
   1.662 + * css3-animations:  3.1. Timing functions for keyframes
   1.663 + * http://dev.w3.org/csswg/css3-animations/#timing-functions-for-keyframes-
   1.664 + */
   1.665 +new_div("animation: kf_tf1 ease-in 10s alternate infinite");
   1.666 +is(cs.paddingBottom, "20px",
   1.667 +   "keyframe timing functions test at 0s (test needed for flush)");
   1.668 +advance_clock(1000);
   1.669 +is_approx(px_to_num(cs.paddingBottom), 20 + 40 * gTF.ease(0.4), 0.01,
   1.670 +          "keyframe timing functions test at 1s");
   1.671 +advance_clock(1000);
   1.672 +is_approx(px_to_num(cs.paddingBottom), 20 + 40 * gTF.ease(0.8), 0.01,
   1.673 +          "keyframe timing functions test at 2s");
   1.674 +advance_clock(1000);
   1.675 +is_approx(px_to_num(cs.paddingBottom), 60 + 100 * gTF.ease_in(0.2), 0.01,
   1.676 +          "keyframe timing functions test at 3s");
   1.677 +advance_clock(1000);
   1.678 +is_approx(px_to_num(cs.paddingBottom), 60 + 100 * gTF.ease_in(0.6), 0.01,
   1.679 +          "keyframe timing functions test at 4s");
   1.680 +advance_clock(1000);
   1.681 +is(cs.paddingBottom, "160px",
   1.682 +   "keyframe timing functions test at 5s");
   1.683 +advance_clock(1010); // avoid floating point error
   1.684 +is_approx(px_to_num(cs.paddingBottom), 160 - 40 * step_end(5)(0.4), 0.01,
   1.685 +          "keyframe timing functions test at 6s");
   1.686 +advance_clock(1000);
   1.687 +is_approx(px_to_num(cs.paddingBottom), 160 - 40 * step_end(5)(0.8), 0.01,
   1.688 +          "keyframe timing functions test at 7s");
   1.689 +advance_clock(990);
   1.690 +is_approx(px_to_num(cs.paddingBottom), 120 - 100 * gTF.linear(0.2), 0.01,
   1.691 +          "keyframe timing functions test at 8s");
   1.692 +advance_clock(1000);
   1.693 +is_approx(px_to_num(cs.paddingBottom), 120 - 100 * gTF.linear(0.6), 0.01,
   1.694 +          "keyframe timing functions test at 9s");
   1.695 +advance_clock(1000);
   1.696 +is(cs.paddingBottom, "20px",
   1.697 +   "keyframe timing functions test at 10s");
   1.698 +advance_clock(20000);
   1.699 +is(cs.paddingBottom, "20px",
   1.700 +   "keyframe timing functions test at 30s");
   1.701 +advance_clock(1000);
   1.702 +is_approx(px_to_num(cs.paddingBottom), 120 - 100 * gTF.linear(0.6), 0.01,
   1.703 +          "keyframe timing functions test at 31s");
   1.704 +advance_clock(1000);
   1.705 +is_approx(px_to_num(cs.paddingBottom), 120 - 100 * gTF.linear(0.2), 0.01,
   1.706 +          "keyframe timing functions test at 32s");
   1.707 +advance_clock(1000);
   1.708 +is_approx(px_to_num(cs.paddingBottom), 160 - 40 * step_end(5)(0.8), 0.01,
   1.709 +          "keyframe timing functions test at 33s");
   1.710 +advance_clock(1000);
   1.711 +is_approx(px_to_num(cs.paddingBottom), 160 - 40 * step_end(5)(0.4), 0.01,
   1.712 +          "keyframe timing functions test at 34s");
   1.713 +advance_clock(1000);
   1.714 +is(cs.paddingBottom, "160px",
   1.715 +   "keyframe timing functions test at 35s");
   1.716 +advance_clock(1000);
   1.717 +is_approx(px_to_num(cs.paddingBottom), 60 + 100 * gTF.ease_in(0.6), 0.01,
   1.718 +          "keyframe timing functions test at 36s");
   1.719 +advance_clock(1000);
   1.720 +is_approx(px_to_num(cs.paddingBottom), 60 + 100 * gTF.ease_in(0.2), 0.01,
   1.721 +          "keyframe timing functions test at 37s");
   1.722 +advance_clock(1000);
   1.723 +is_approx(px_to_num(cs.paddingBottom), 20 + 40 * gTF.ease(0.8), 0.01,
   1.724 +          "keyframe timing functions test at 38s");
   1.725 +advance_clock(1000);
   1.726 +is_approx(px_to_num(cs.paddingBottom), 20 + 40 * gTF.ease(0.4), 0.01,
   1.727 +          "keyframe timing functions test at 39s");
   1.728 +advance_clock(1000);
   1.729 +is(cs.paddingBottom, "20px",
   1.730 +   "keyframe timing functions test at 40s");
   1.731 +done_div();
   1.732 +
   1.733 +// spot-check the same thing without alternate
   1.734 +new_div("animation: kf_tf1 ease-in 10s infinite");
   1.735 +is(cs.paddingBottom, "20px",
   1.736 +   "keyframe timing functions test at 0s (test needed for flush)");
   1.737 +advance_clock(11000);
   1.738 +is_approx(px_to_num(cs.paddingBottom), 20 + 40 * gTF.ease(0.4), 0.01,
   1.739 +          "keyframe timing functions test at 11s");
   1.740 +advance_clock(3000);
   1.741 +is_approx(px_to_num(cs.paddingBottom), 60 + 100 * gTF.ease_in(0.6), 0.01,
   1.742 +          "keyframe timing functions test at 14s");
   1.743 +advance_clock(2000);
   1.744 +is_approx(px_to_num(cs.paddingBottom), 160 - 40 * step_end(5)(0.4), 0.01,
   1.745 +          "keyframe timing functions test at 16s");
   1.746 +advance_clock(2000);
   1.747 +is_approx(px_to_num(cs.paddingBottom), 120 - 100 * gTF.linear(0.2), 0.01,
   1.748 +          "keyframe timing functions test at 18s");
   1.749 +done_div();
   1.750 +
   1.751 +/*
   1.752 + * css3-animations:  3.2. The 'animation-name' Property
   1.753 + * http://dev.w3.org/csswg/css3-animations/#the-animation-name-property-
   1.754 + */
   1.755 +
   1.756 +// animation-name is reasonably well-tested up in the tests for Section
   1.757 +// 2, particularly the tests that "Test that animations continue running
   1.758 +// when the animation name list is changed."
   1.759 +
   1.760 +// Test that 'animation-name: none' steps the animation, and setting
   1.761 +// it again starts a new one.
   1.762 +
   1.763 +new_div("");
   1.764 +div.style.animation = "anim2 ease-in-out 10s";
   1.765 +is(cs.marginRight, "0px", "after setting animation-name to anim2");
   1.766 +advance_clock(1000);
   1.767 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in_out(0.1), 0.01,
   1.768 +          "before changing animation-name to none");
   1.769 +div.style.animationName = "none";
   1.770 +is(cs.marginRight, "0px", "after changing animation-name to none");
   1.771 +advance_clock(1000);
   1.772 +is(cs.marginRight, "0px", "after changing animation-name to none plus 1s");
   1.773 +div.style.animationName = "anim2";
   1.774 +is(cs.marginRight, "0px", "after changing animation-name to anim2");
   1.775 +advance_clock(1000);
   1.776 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in_out(0.1), 0.01,
   1.777 +          "at 1s in animation when animation-name no longer none again");
   1.778 +div.style.animationName = "none";
   1.779 +is(cs.marginRight, "0px", "after changing animation-name to none");
   1.780 +advance_clock(1000);
   1.781 +is(cs.marginRight, "0px", "after changing animation-name to none plus 1s");
   1.782 +done_div();
   1.783 +
   1.784 +/*
   1.785 + * css3-animations:  3.3. The 'animation-duration' Property
   1.786 + * http://dev.w3.org/csswg/css3-animations/#the-animation-duration-property-
   1.787 + */
   1.788 +
   1.789 +// FIXME: test animation-duration of 0 (quite a bit, including interaction
   1.790 +// with fill-mode, count, and reversing), once I know what the right
   1.791 +// behavior is.
   1.792 +
   1.793 +/*
   1.794 + * css3-animations:  3.4. The 'animation-timing-function' Property
   1.795 + * http://dev.w3.org/csswg/css3-animations/#animation-timing-function_tag
   1.796 + */
   1.797 +
   1.798 +// tested in tests for section 3.1
   1.799 +
   1.800 +/*
   1.801 + * css3-animations:  3.5. The 'animation-iteration-count' Property
   1.802 + * http://dev.w3.org/csswg/css3-animations/#the-animation-iteration-count-property-
   1.803 + */
   1.804 +new_div("animation: anim2 ease-in 10s 0.3 forwards");
   1.805 +is(cs.marginRight, "0px", "animation-iteration-count test 1 at 0s");
   1.806 +advance_clock(2000);
   1.807 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.2), 0.01,
   1.808 +          "animation-iteration-count test 1 at 2s");
   1.809 +advance_clock(900);
   1.810 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.29), 0.01,
   1.811 +          "animation-iteration-count test 1 at 2.9s");
   1.812 +advance_clock(100);
   1.813 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.3), 0.01,
   1.814 +          "animation-iteration-count test 1 at 3s");
   1.815 +advance_clock(100);
   1.816 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.3), 0.01,
   1.817 +          "animation-iteration-count test 1 at 3.1s");
   1.818 +advance_clock(5000);
   1.819 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.3), 0.01,
   1.820 +          "animation-iteration-count test 1 at 8.1s");
   1.821 +done_div();
   1.822 +
   1.823 +new_div("animation: anim2 ease-in 10s 0.3, anim3 ease-out 20s 1.2 alternate forwards, anim4 ease-in-out 5s 1.6 forwards");
   1.824 +is(cs.marginRight, "0px", "animation-iteration-count test 2 at 0s");
   1.825 +is(cs.marginTop, "0px", "animation-iteration-count test 3 at 0s");
   1.826 +is(cs.marginBottom, "0px", "animation-iteration-count test 4 at 0s");
   1.827 +advance_clock(2000);
   1.828 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.2), 0.01,
   1.829 +          "animation-iteration-count test 2 at 2s");
   1.830 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_out(0.1), 0.01,
   1.831 +          "animation-iteration-count test 3 at 2s");
   1.832 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.4), 0.01,
   1.833 +          "animation-iteration-count test 4 at 2s");
   1.834 +advance_clock(900);
   1.835 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.29), 0.01,
   1.836 +          "animation-iteration-count test 2 at 2.9s");
   1.837 +advance_clock(200);
   1.838 +is(cs.marginRight, "0px", "animation-iteration-count test 2 at 3.1s");
   1.839 +advance_clock(1800);
   1.840 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.98), 0.01,
   1.841 +          "animation-iteration-count test 4 at 4.9s");
   1.842 +advance_clock(200);
   1.843 +is(cs.marginRight, "0px", "animation-iteration-count test 2 at 5.1s");
   1.844 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.02), 0.01,
   1.845 +          "animation-iteration-count test 4 at 5.1s");
   1.846 +advance_clock(2800);
   1.847 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.58), 0.01,
   1.848 +          "animation-iteration-count test 4 at 7.9s");
   1.849 +advance_clock(100);
   1.850 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.6), 0.01,
   1.851 +          "animation-iteration-count test 4 at 8s");
   1.852 +advance_clock(100);
   1.853 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.6), 0.01,
   1.854 +          "animation-iteration-count test 4 at 8.1s");
   1.855 +advance_clock(11700);
   1.856 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_out(0.99), 0.01,
   1.857 +          "animation-iteration-count test 3 at 19.8s");
   1.858 +advance_clock(200);
   1.859 +is(cs.marginTop, "100px", "animation-iteration-count test 3 at 20s");
   1.860 +advance_clock(200);
   1.861 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_out(0.99), 0.01,
   1.862 +          "animation-iteration-count test 3 at 20.2s");
   1.863 +advance_clock(3600);
   1.864 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_out(0.81), 0.01,
   1.865 +          "animation-iteration-count test 3 at 23.8s");
   1.866 +advance_clock(200);
   1.867 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_out(0.8), 0.01,
   1.868 +          "animation-iteration-count test 3 at 24s");
   1.869 +advance_clock(200);
   1.870 +is(cs.marginRight, "0px", "animation-iteration-count test 2 at 25s");
   1.871 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_out(0.8), 0.01,
   1.872 +          "animation-iteration-count test 3 at 25s");
   1.873 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.6), 0.01,
   1.874 +          "animation-iteration-count test 4 at 25s");
   1.875 +done_div();
   1.876 +
   1.877 +/*
   1.878 + * css3-animations:  3.6. The 'animation-direction' Property
   1.879 + * http://dev.w3.org/csswg/css3-animations/#the-animation-direction-property-
   1.880 + */
   1.881 +
   1.882 +// Tested in tests for sections 3.1 and 3.5.
   1.883 +
   1.884 +new_div("animation: anim2 ease-in 10s infinite");
   1.885 +div.style.animationDirection = "normal";
   1.886 +is(cs.marginRight, "0px", "animation-direction test 1 (normal) at 0s");
   1.887 +div.style.animationDirection = "reverse";
   1.888 +is(cs.marginRight, "100px", "animation-direction test 1 (reverse) at 0s");
   1.889 +div.style.animationDirection = "alternate";
   1.890 +is(cs.marginRight, "0px", "animation-direction test 1 (alternate) at 0s");
   1.891 +div.style.animationDirection = "alternate-reverse";
   1.892 +is(cs.marginRight, "100px", "animation-direction test 1 (alternate-reverse) at 0s");
   1.893 +advance_clock(2000);
   1.894 +div.style.animationDirection = "normal";
   1.895 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.2), 0.01,
   1.896 +          "animation-direction test 1 (normal) at 2s");
   1.897 +div.style.animationDirection = "reverse";
   1.898 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.8), 0.01,
   1.899 +          "animation-direction test 1 (reverse) at 2s");
   1.900 +div.style.animationDirection = "alternate";
   1.901 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.2), 0.01,
   1.902 +          "animation-direction test 1 (alternate) at 2s");
   1.903 +div.style.animationDirection = "alternate-reverse";
   1.904 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.8), 0.01,
   1.905 +          "animation-direction test 1 (alternate-reverse) at 2s");
   1.906 +advance_clock(5000);
   1.907 +div.style.animationDirection = "normal";
   1.908 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.7), 0.01,
   1.909 +          "animation-direction test 1 (normal) at 7s");
   1.910 +div.style.animationDirection = "reverse";
   1.911 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.3), 0.01,
   1.912 +          "animation-direction test 1 (reverse) at 7s");
   1.913 +div.style.animationDirection = "alternate";
   1.914 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.7), 0.01,
   1.915 +          "animation-direction test 1 (alternate) at 7s");
   1.916 +div.style.animationDirection = "alternate-reverse";
   1.917 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.3), 0.01,
   1.918 +          "animation-direction test 1 (alternate-reverse) at 7s");
   1.919 +advance_clock(5000);
   1.920 +div.style.animationDirection = "normal";
   1.921 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.2), 0.01,
   1.922 +          "animation-direction test 1 (normal) at 12s");
   1.923 +div.style.animationDirection = "reverse";
   1.924 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.8), 0.01,
   1.925 +          "animation-direction test 1 (reverse) at 12s");
   1.926 +div.style.animationDirection = "alternate";
   1.927 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.8), 0.01,
   1.928 +          "animation-direction test 1 (alternate) at 12s");
   1.929 +div.style.animationDirection = "alternate-reverse";
   1.930 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.2), 0.01,
   1.931 +          "animation-direction test 1 (alternate-reverse) at 12s");
   1.932 +advance_clock(10000);
   1.933 +div.style.animationDirection = "normal";
   1.934 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.2), 0.01,
   1.935 +          "animation-direction test 1 (normal) at 22s");
   1.936 +div.style.animationDirection = "reverse";
   1.937 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.8), 0.01,
   1.938 +          "animation-direction test 1 (reverse) at 22s");
   1.939 +div.style.animationDirection = "alternate";
   1.940 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.2), 0.01,
   1.941 +          "animation-direction test 1 (alternate) at 22s");
   1.942 +div.style.animationDirection = "alternate-reverse";
   1.943 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.8), 0.01,
   1.944 +          "animation-direction test 1 (alternate-reverse) at 22s");
   1.945 +advance_clock(30000);
   1.946 +div.style.animationDirection = "normal";
   1.947 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.2), 0.01,
   1.948 +          "animation-direction test 1 (normal) at 52s");
   1.949 +div.style.animationDirection = "reverse";
   1.950 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.8), 0.01,
   1.951 +          "animation-direction test 1 (reverse) at 52s");
   1.952 +div.style.animationDirection = "alternate";
   1.953 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.8), 0.01,
   1.954 +          "animation-direction test 1 (alternate) at 52s");
   1.955 +div.style.animationDirection = "alternate-reverse";
   1.956 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.2), 0.01,
   1.957 +          "animation-direction test 1 (alternate-reverse) at 52s");
   1.958 +done_div();
   1.959 +
   1.960 +/*
   1.961 + * css3-animations:  3.7. The 'animation-play-state' Property
   1.962 + * http://dev.w3.org/csswg/css3-animations/#the-animation-play-state-property-
   1.963 + */
   1.964 +
   1.965 +// simple test with just one animation
   1.966 +new_div("");
   1.967 +div.style.animationTimingFunction = "ease";
   1.968 +div.style.animationName = "anim1";
   1.969 +div.style.animationDuration = "1s";
   1.970 +div.style.animationDirection = "alternate";
   1.971 +div.style.animationIterationCount = "2";
   1.972 +is(cs.marginLeft, "0px", "animation-play-state test 1, at 0s");
   1.973 +advance_clock(250);
   1.974 +is_approx(px_to_num(cs.marginLeft), 80 * gTF.ease(0.5), 0.01,
   1.975 +          "animation-play-state test 1 at 250ms");
   1.976 +div.style.animationPlayState = "paused";
   1.977 +is_approx(px_to_num(cs.marginLeft), 80 * gTF.ease(0.5), 0.01,
   1.978 +          "animation-play-state test 1 at 250ms");
   1.979 +advance_clock(250);
   1.980 +is_approx(px_to_num(cs.marginLeft), 80 * gTF.ease(0.5), 0.01,
   1.981 +          "animation-play-state test 1 still at 500ms");
   1.982 +div.style.animationPlayState = "running";
   1.983 +is_approx(px_to_num(cs.marginLeft), 80 * gTF.ease(0.5), 0.01,
   1.984 +          "animation-play-state test 1 still at 500ms");
   1.985 +advance_clock(500);
   1.986 +is_approx(px_to_num(cs.marginLeft), 80 + 20 * gTF.ease(0.5), 0.01,
   1.987 +          "animation-play-state test 1 at 1000ms");
   1.988 +advance_clock(250);
   1.989 +is(cs.marginLeft, "100px", "animation-play-state test 1 at 1250ms");
   1.990 +advance_clock(250);
   1.991 +is_approx(px_to_num(cs.marginLeft), 80 + 20 * gTF.ease(0.5), 0.01,
   1.992 +          "animation-play-state test 1 at 1500ms");
   1.993 +div.style.animationPlayState = "paused";
   1.994 +is_approx(px_to_num(cs.marginLeft), 80 + 20 * gTF.ease(0.5), 0.01,
   1.995 +          "animation-play-state test 1 at 1500ms");
   1.996 +advance_clock(2000);
   1.997 +is_approx(px_to_num(cs.marginLeft), 80 + 20 * gTF.ease(0.5), 0.01,
   1.998 +          "animation-play-state test 1 at 3500ms");
   1.999 +advance_clock(500);
  1.1000 +is_approx(px_to_num(cs.marginLeft), 80 + 20 * gTF.ease(0.5), 0.01,
  1.1001 +          "animation-play-state test 1 at 4000ms");
  1.1002 +div.style.animationPlayState = "";
  1.1003 +is_approx(px_to_num(cs.marginLeft), 80 + 20 * gTF.ease(0.5), 0.01,
  1.1004 +          "animation-play-state test 1 at 4000ms");
  1.1005 +advance_clock(500);
  1.1006 +is_approx(px_to_num(cs.marginLeft), 80 * gTF.ease(0.5), 0.01,
  1.1007 +          "animation-play-state test 1 at 4500ms");
  1.1008 +advance_clock(250);
  1.1009 +is(cs.marginLeft, "0px", "animation-play-state test 1, at 4750ms");
  1.1010 +advance_clock(250);
  1.1011 +is(cs.marginLeft, "0px", "animation-play-state test 1, at 5000ms");
  1.1012 +done_div();
  1.1013 +
  1.1014 +// more complicated test with multiple animations (and different directions
  1.1015 +// and iteration counts)
  1.1016 +new_div("");
  1.1017 +div.style.animationTimingFunction = "ease-out, ease-in, ease-in-out";
  1.1018 +div.style.animationName = "anim2, anim3, anim4";
  1.1019 +div.style.animationDuration = "1s, 2s, 1s";
  1.1020 +div.style.animationDirection = "alternate, normal, normal";
  1.1021 +div.style.animationIterationCount = "4, 2, infinite";
  1.1022 +is(cs.marginRight, "0px", "animation-play-state test 2, at 0s");
  1.1023 +is(cs.marginTop, "0px", "animation-play-state test 3, at 0s");
  1.1024 +is(cs.marginBottom, "0px", "animation-play-state test 4, at 0s");
  1.1025 +advance_clock(250);
  1.1026 +div.style.animationPlayState = "paused, running"; // pause 1 and 3
  1.1027 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.25), 0.01,
  1.1028 +          "animation-play-state test 2 at 250ms");
  1.1029 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.125), 0.01,
  1.1030 +          "animation-play-state test 3 at 250ms");
  1.1031 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.25), 0.01,
  1.1032 +          "animation-play-state test 4 at 250ms");
  1.1033 +advance_clock(250);
  1.1034 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.25), 0.01,
  1.1035 +          "animation-play-state test 2 at 500ms");
  1.1036 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.25), 0.01,
  1.1037 +          "animation-play-state test 3 at 500ms");
  1.1038 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.25), 0.01,
  1.1039 +          "animation-play-state test 4 at 500ms");
  1.1040 +div.style.animationPlayState = "paused, running, running"; // unpause 3
  1.1041 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.25), 0.01,
  1.1042 +          "animation-play-state test 2 at 500ms");
  1.1043 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.25), 0.01,
  1.1044 +          "animation-play-state test 3 at 500ms");
  1.1045 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.25), 0.01,
  1.1046 +          "animation-play-state test 4 at 500ms");
  1.1047 +advance_clock(250);
  1.1048 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.25), 0.01,
  1.1049 +          "animation-play-state test 2 at 750ms");
  1.1050 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.375), 0.01,
  1.1051 +          "animation-play-state test 3 at 750ms");
  1.1052 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.5), 0.01,
  1.1053 +          "animation-play-state test 4 at 750ms");
  1.1054 +div.style.animationPlayState = "running, paused"; // unpause 1, pause 2
  1.1055 +advance_clock(0); // notify refresh observers
  1.1056 +advance_clock(250);
  1.1057 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.5), 0.01,
  1.1058 +          "animation-play-state test 2 at 1000ms");
  1.1059 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.375), 0.01,
  1.1060 +          "animation-play-state test 3 at 1000ms");
  1.1061 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.75), 0.01,
  1.1062 +          "animation-play-state test 4 at 1000ms");
  1.1063 +div.style.animationPlayState = "paused"; // pause all
  1.1064 +advance_clock(0); // notify refresh observers
  1.1065 +advance_clock(3000);
  1.1066 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.5), 0.01,
  1.1067 +          "animation-play-state test 2 at 4000ms");
  1.1068 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.375), 0.01,
  1.1069 +          "animation-play-state test 3 at 4000ms");
  1.1070 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.75), 0.01,
  1.1071 +          "animation-play-state test 4 at 4000ms");
  1.1072 +div.style.animationPlayState = "running, paused"; // pause 2
  1.1073 +advance_clock(0); // notify refresh observers
  1.1074 +advance_clock(850);
  1.1075 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.65), 0.01,
  1.1076 +          "animation-play-state test 2 at 4850ms");
  1.1077 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.375), 0.01,
  1.1078 +          "animation-play-state test 3 at 4850ms");
  1.1079 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.6), 0.01,
  1.1080 +          "animation-play-state test 4 at 4850ms");
  1.1081 +advance_clock(300);
  1.1082 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.35), 0.01,
  1.1083 +          "animation-play-state test 2 at 5150ms");
  1.1084 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.375), 0.01,
  1.1085 +          "animation-play-state test 3 at 5150ms");
  1.1086 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.9), 0.01,
  1.1087 +          "animation-play-state test 4 at 5150ms");
  1.1088 +advance_clock(2300);
  1.1089 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.05), 0.01,
  1.1090 +          "animation-play-state test 2 at 7450ms");
  1.1091 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.375), 0.01,
  1.1092 +          "animation-play-state test 3 at 7450ms");
  1.1093 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.2), 0.01,
  1.1094 +          "animation-play-state test 4 at 7450ms");
  1.1095 +advance_clock(100);
  1.1096 +is(cs.marginRight, "0px", "animation-play-state test 2 at 7550ms");
  1.1097 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.375), 0.01,
  1.1098 +          "animation-play-state test 3 at 7550ms");
  1.1099 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.3), 0.01,
  1.1100 +          "animation-play-state test 4 at 7550ms");
  1.1101 +div.style.animationPlayState = "running"; // unpause 2
  1.1102 +advance_clock(0); // notify refresh observers
  1.1103 +advance_clock(1000);
  1.1104 +is(cs.marginRight, "0px", "animation-play-state test 2 at 7550ms");
  1.1105 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.875), 0.01,
  1.1106 +          "animation-play-state test 3 at 7550ms");
  1.1107 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.3), 0.01,
  1.1108 +          "animation-play-state test 4 at 7550ms");
  1.1109 +advance_clock(500);
  1.1110 +is(cs.marginRight, "0px", "animation-play-state test 2 at 8050ms");
  1.1111 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.125), 0.01,
  1.1112 +          "animation-play-state test 3 at 8050ms");
  1.1113 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.8), 0.01,
  1.1114 +          "animation-play-state test 4 at 8050ms");
  1.1115 +advance_clock(1000);
  1.1116 +is(cs.marginRight, "0px", "animation-play-state test 2 at 9050ms");
  1.1117 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.625), 0.01,
  1.1118 +          "animation-play-state test 3 at 9050ms");
  1.1119 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.8), 0.01,
  1.1120 +          "animation-play-state test 4 at 9050ms");
  1.1121 +advance_clock(500);
  1.1122 +is(cs.marginRight, "0px", "animation-play-state test 2 at 9550ms");
  1.1123 +is_approx(px_to_num(cs.marginTop), 100 * gTF.ease_in(0.875), 0.01,
  1.1124 +          "animation-play-state test 3 at 9550ms");
  1.1125 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.3), 0.01,
  1.1126 +          "animation-play-state test 4 at 9550ms");
  1.1127 +advance_clock(500);
  1.1128 +is(cs.marginRight, "0px", "animation-play-state test 2 at 10050ms");
  1.1129 +is(cs.marginTop, "0px", "animation-play-state test 3 at 10050ms");
  1.1130 +is_approx(px_to_num(cs.marginBottom), 100 * gTF.ease_in_out(0.8), 0.01,
  1.1131 +          "animation-play-state test 4 at 10050ms");
  1.1132 +done_div();
  1.1133 +
  1.1134 +/*
  1.1135 + * css3-animations:  3.8. The 'animation-delay' Property
  1.1136 + * http://dev.w3.org/csswg/css3-animations/#the-animation-delay-property-
  1.1137 + */
  1.1138 +
  1.1139 +// test positive delay
  1.1140 +new_div("animation: anim2 1s 0.5s ease-out");
  1.1141 +is(cs.marginRight, "0px", "positive delay test at 0ms");
  1.1142 +advance_clock(400);
  1.1143 +is(cs.marginRight, "0px", "positive delay test at 400ms");
  1.1144 +advance_clock(100);
  1.1145 +is(cs.marginRight, "0px", "positive delay test at 500ms");
  1.1146 +advance_clock(100);
  1.1147 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.1), 0.01,
  1.1148 +          "positive delay test at 500ms");
  1.1149 +done_div();
  1.1150 +
  1.1151 +// test dynamic changes to delay (i.e., that we preserve the start time
  1.1152 +// that's before the delay)
  1.1153 +new_div("animation: anim2 1s 0.5s ease-out both");
  1.1154 +is(cs.marginRight, "0px", "dynamic delay delay test at 0ms");
  1.1155 +advance_clock(400);
  1.1156 +is(cs.marginRight, "0px", "dynamic delay delay test at 400ms (1)");
  1.1157 +div.style.animationDelay = "0.2s";
  1.1158 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.2), 0.01,
  1.1159 +          "dynamic delay delay test at 400ms (2)");
  1.1160 +div.style.animationDelay = "0.6s";
  1.1161 +advance_clock(0);
  1.1162 +advance_clock(200);
  1.1163 +is(cs.marginRight, "0px", "dynamic delay delay test at 600ms");
  1.1164 +advance_clock(200);
  1.1165 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.2), 0.01,
  1.1166 +          "dynamic delay delay test at 800ms");
  1.1167 +advance_clock(1000);
  1.1168 +is(cs.marginRight, "100px", "dynamic delay delay test at 1800ms (1)");
  1.1169 +div.style.animationDelay = "1.5s";
  1.1170 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.3), 0.01,
  1.1171 +          "dynamic delay delay test at 1800ms (2)");
  1.1172 +div.style.animationDelay = "2s";
  1.1173 +is(cs.marginRight, "0px", "dynamic delay delay test at 1800ms (3)");
  1.1174 +done_div();
  1.1175 +
  1.1176 +// test delay and play-state interaction
  1.1177 +new_div("animation: anim2 1s 0.5s ease-out");
  1.1178 +is(cs.marginRight, "0px", "delay and play-state delay test at 0ms");
  1.1179 +advance_clock(400);
  1.1180 +is(cs.marginRight, "0px", "delay and play-state delay test at 400ms");
  1.1181 +div.style.animationPlayState = "paused";
  1.1182 +advance_clock(0);
  1.1183 +advance_clock(100);
  1.1184 +is(cs.marginRight, "0px", "delay and play-state delay test at 500ms");
  1.1185 +advance_clock(500);
  1.1186 +is(cs.marginRight, "0px", "delay and play-state delay test at 1000ms");
  1.1187 +div.style.animationPlayState = "running";
  1.1188 +advance_clock(0);
  1.1189 +advance_clock(100);
  1.1190 +is(cs.marginRight, "0px", "delay and play-state delay test at 1100ms");
  1.1191 +advance_clock(100);
  1.1192 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.1), 0.01,
  1.1193 +          "delay and play-state delay test at 1200ms");
  1.1194 +div.style.animationPlayState = "paused";
  1.1195 +advance_clock(0);
  1.1196 +advance_clock(100);
  1.1197 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_out(0.1), 0.01,
  1.1198 +          "delay and play-state delay test at 1300ms");
  1.1199 +done_div();
  1.1200 +
  1.1201 +// test negative delay and implicit starting values
  1.1202 +new_div("margin-top: 1000px");
  1.1203 +advance_clock(300);
  1.1204 +div.style.marginTop = "100px";
  1.1205 +div.style.animation = "kf1 1s -0.1s ease-in";
  1.1206 +is_approx(px_to_num(cs.marginTop), 100 - 50 * gTF.ease_in(0.2), 0.01,
  1.1207 +          "delay and implicit starting values test");
  1.1208 +done_div();
  1.1209 +
  1.1210 +// test large negative delay that causes the animation to start
  1.1211 +// in the fourth iteration
  1.1212 +new_div("animation: anim2 1s -3.6s ease-in 5 alternate forwards");
  1.1213 +listen(); // rely on no flush having happened yet
  1.1214 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.4), 0.01,
  1.1215 +          "large negative delay test at 0ms");
  1.1216 +check_events([{ type: 'animationstart', target: div,
  1.1217 +                animationName: 'anim2', elapsedTime: 3.6,
  1.1218 +                pseudoElement: "" }],
  1.1219 +             "right after start in large negative delay test");
  1.1220 +advance_clock(380);
  1.1221 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.02), 0.01,
  1.1222 +          "large negative delay test at 380ms");
  1.1223 +check_events([]);
  1.1224 +advance_clock(20);
  1.1225 +is(cs.marginRight, "0px", "large negative delay test at 400ms");
  1.1226 +check_events([{ type: 'animationiteration', target: div,
  1.1227 +                animationName: 'anim2', elapsedTime: 4.0,
  1.1228 +                pseudoElement: "" }],
  1.1229 +             "right after start in large negative delay test");
  1.1230 +advance_clock(800);
  1.1231 +is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.8), 0.01,
  1.1232 +          "large negative delay test at 1200ms");
  1.1233 +check_events([]);
  1.1234 +advance_clock(200);
  1.1235 +is(cs.marginRight, "100px", "large negative delay test at 1400ms");
  1.1236 +check_events([{ type: 'animationend', target: div,
  1.1237 +                animationName: 'anim2', elapsedTime: 5.0,
  1.1238 +                pseudoElement: "" }],
  1.1239 +             "right after start in large negative delay test");
  1.1240 +done_div();
  1.1241 +
  1.1242 +/*
  1.1243 + * css3-animations:  3.9. The 'animation-fill-mode' Property
  1.1244 + * http://dev.w3.org/csswg/css3-animations/#the-animation-fill-mode-property-
  1.1245 + */
  1.1246 +
  1.1247 +// animation-fill-mode is tested in the tests for section (2).
  1.1248 +
  1.1249 +/*
  1.1250 + * css3-animations:  3.10. The 'animation' Shorthand Property
  1.1251 + * http://dev.w3.org/csswg/css3-animations/#the-animation-shorthand-property-
  1.1252 + */
  1.1253 +
  1.1254 +// shorthand vs. longhand is adequately tested by the
  1.1255 +// property_database.js-based tests.
  1.1256 +
  1.1257 +/**
  1.1258 + * Basic tests of animations on pseudo-elements
  1.1259 + */
  1.1260 +new_div("");
  1.1261 +listen();
  1.1262 +div.id = "withbefore";
  1.1263 +var cs_before = getComputedStyle(div, ":before");
  1.1264 +is(cs_before.marginRight, "0px", ":before test at 0ms");
  1.1265 +advance_clock(400);
  1.1266 +is(cs_before.marginRight, "40px", ":before test at 400ms");
  1.1267 +advance_clock(800);
  1.1268 +is(cs_before.marginRight, "80px", ":before test at 1200ms");
  1.1269 +is(cs.marginRight, "0px", ":before animation should not affect element");
  1.1270 +advance_clock(800);
  1.1271 +is(cs_before.marginRight, "0px", ":before test at 2000ms");
  1.1272 +advance_clock(300);
  1.1273 +is(cs_before.marginRight, "30px", ":before test at 2300ms");
  1.1274 +advance_clock(700);
  1.1275 +check_events([ { type: "animationstart", animationName: "anim2", elapsedTime: 0, pseudoElement: "::before" },
  1.1276 +               { type: "animationiteration", animationName: "anim2", elapsedTime: 1.2, pseudoElement: "::before" },
  1.1277 +               { type: "animationiteration", animationName: "anim2", elapsedTime: 2, pseudoElement: "::before" },
  1.1278 +               { type: "animationend", animationName: "anim2", elapsedTime: 3, pseudoElement: "::before" }]);
  1.1279 +done_div();
  1.1280 +
  1.1281 +new_div("");
  1.1282 +listen();
  1.1283 +div.id = "withafter";
  1.1284 +var cs_after = getComputedStyle(div, ":after");
  1.1285 +is(cs_after.marginRight, "0px", ":after test at 0ms");
  1.1286 +advance_clock(400);
  1.1287 +is(cs_after.marginRight, "40px", ":after test at 400ms");
  1.1288 +advance_clock(800);
  1.1289 +is(cs_after.marginRight, "80px", ":after test at 1200ms");
  1.1290 +is(cs.marginRight, "0px", ":after animation should not affect element");
  1.1291 +advance_clock(800);
  1.1292 +is(cs_after.marginRight, "0px", ":after test at 2000ms");
  1.1293 +advance_clock(300);
  1.1294 +is(cs_after.marginRight, "30px", ":after test at 2300ms");
  1.1295 +advance_clock(700);
  1.1296 +check_events([ { type: "animationstart", animationName: "anim2", elapsedTime: 0, pseudoElement: "::after" },
  1.1297 +               { type: "animationiteration", animationName: "anim2", elapsedTime: 1.2, pseudoElement: "::after" },
  1.1298 +               { type: "animationiteration", animationName: "anim2", elapsedTime: 2, pseudoElement: "::after" },
  1.1299 +               { type: "animationend", animationName: "anim2", elapsedTime: 3, pseudoElement: "::after" }]);
  1.1300 +done_div();
  1.1301 +
  1.1302 +/**
  1.1303 + * Test handling of properties that are present in only some of the
  1.1304 + * keyframes.
  1.1305 + */
  1.1306 +new_div("animation: multiprop 1s ease-in-out alternate infinite");
  1.1307 +is(cs.paddingTop, "10px", "multiprop top at 0ms");
  1.1308 +is(cs.paddingLeft, "30px", "multiprop top at 0ms");
  1.1309 +advance_clock(100);
  1.1310 +is_approx(px_to_num(cs.paddingTop), 10 + 30 * gTF.ease(0.2), 0.01,
  1.1311 +          "multiprop top at 100ms");
  1.1312 +is_approx(px_to_num(cs.paddingLeft), 30 + 20 * gTF.ease(0.4), 0.01,
  1.1313 +          "multiprop left at 100ms");
  1.1314 +advance_clock(200);
  1.1315 +is_approx(px_to_num(cs.paddingTop), 10 + 30 * gTF.ease(0.6), 0.01,
  1.1316 +          "multiprop top at 300ms");
  1.1317 +is_approx(px_to_num(cs.paddingLeft), 50 + 10 * gTF.ease_out(0.1), 0.01,
  1.1318 +          "multiprop left at 300ms");
  1.1319 +advance_clock(300);
  1.1320 +is_approx(px_to_num(cs.paddingTop), 40 + 40 * gTF.ease_in_out(0.4), 0.01,
  1.1321 +          "multiprop top at 600ms");
  1.1322 +is_approx(px_to_num(cs.paddingLeft), 50 + 10 * gTF.ease_out(0.7), 0.01,
  1.1323 +          "multiprop left at 600ms");
  1.1324 +advance_clock(200);
  1.1325 +is_approx(px_to_num(cs.paddingTop), 80 - 80 * gTF.ease_in(0.2), 0.01,
  1.1326 +          "multiprop top at 800ms");
  1.1327 +is_approx(px_to_num(cs.paddingLeft), 60 - 60 * gTF.ease_in(0.2), 0.01,
  1.1328 +          "multiprop left at 800ms");
  1.1329 +advance_clock(400);
  1.1330 +is_approx(px_to_num(cs.paddingTop), 80 - 80 * gTF.ease_in(0.2), 0.01,
  1.1331 +          "multiprop top at 1200ms");
  1.1332 +is_approx(px_to_num(cs.paddingLeft), 60 - 60 * gTF.ease_in(0.2), 0.01,
  1.1333 +          "multiprop left at 1200ms");
  1.1334 +advance_clock(200);
  1.1335 +is_approx(px_to_num(cs.paddingTop), 40 + 40 * gTF.ease_in_out(0.4), 0.01,
  1.1336 +          "multiprop top at 1400ms");
  1.1337 +is_approx(px_to_num(cs.paddingLeft), 50 + 10 * gTF.ease_out(0.7), 0.01,
  1.1338 +          "multiprop left at 1400ms");
  1.1339 +advance_clock(300);
  1.1340 +is_approx(px_to_num(cs.paddingTop), 10 + 30 * gTF.ease(0.6), 0.01,
  1.1341 +          "multiprop top at 1700ms");
  1.1342 +is_approx(px_to_num(cs.paddingLeft), 50 + 10 * gTF.ease_out(0.1), 0.01,
  1.1343 +          "multiprop left at 1700ms");
  1.1344 +advance_clock(200);
  1.1345 +is_approx(px_to_num(cs.paddingTop), 10 + 30 * gTF.ease(0.2), 0.01,
  1.1346 +          "multiprop top at 1900ms");
  1.1347 +is_approx(px_to_num(cs.paddingLeft), 30 + 20 * gTF.ease(0.4), 0.01,
  1.1348 +          "multiprop left at 1900ms");
  1.1349 +done_div();
  1.1350 +
  1.1351 +// Test for https://bugzilla.mozilla.org/show_bug.cgi?id=651456 -- make
  1.1352 +// sure that refreshing of animations doesn't break when we get two
  1.1353 +// refreshes with the same timestamp.
  1.1354 +new_div("animation: anim2 1s linear");
  1.1355 +is(cs.marginRight, "0px", "bug 651456 at 0ms");
  1.1356 +advance_clock(100);
  1.1357 +is(cs.marginRight, "10px", "bug 651456 at 100ms (1)");
  1.1358 +advance_clock(0); // still forces a refresh
  1.1359 +is(cs.marginRight, "10px", "bug 651456 at 100ms (2)");
  1.1360 +advance_clock(100);
  1.1361 +is(cs.marginRight, "20px", "bug 651456 at 200ms");
  1.1362 +done_div();
  1.1363 +
  1.1364 +// Test that UA !important rules override animations.
  1.1365 +// This test depends on forms.css having a rule
  1.1366 +//   select { line-height: !important }
  1.1367 +// If that rule changes, we should rewrite it to depend on a different rule.
  1.1368 +new_element("select", "");
  1.1369 +var default_line_height = cs.lineHeight;
  1.1370 +done_div();
  1.1371 +new_element("select", "animation: uaoverride 2s linear infinite");
  1.1372 +is(cs.lineHeight, default_line_height,
  1.1373 +   "animations should not override UA !important at 0ms");
  1.1374 +is(cs.marginTop, "20px",
  1.1375 +   "rest of animation should still work when UA !important present at 0ms");
  1.1376 +advance_clock(200);
  1.1377 +is(cs.lineHeight, default_line_height,
  1.1378 +   "animations should not override UA !important at 200ms");
  1.1379 +is(cs.marginTop, "40px",
  1.1380 +   "rest of animation should still work when UA !important present at 200ms");
  1.1381 +done_div();
  1.1382 +
  1.1383 +// Test that author !important rules override animations, but
  1.1384 +// that animations override regular author rules.
  1.1385 +new_div("animation: always_fifty 1s linear infinite; margin-left: 200px");
  1.1386 +is(cs.marginLeft, "50px", "animations override regular author rules");
  1.1387 +done_div();
  1.1388 +new_div("animation: always_fifty 1s linear infinite; margin-left: 200px ! important;");
  1.1389 +is(cs.marginLeft, "200px", "important author rules override animations");
  1.1390 +done_div();
  1.1391 +
  1.1392 +// Test interaction of animations and restyling (Bug 686656).
  1.1393 +// This test depends on kf3 getting its 0% and 100% values from the
  1.1394 +// rules below it in the cascade; we're checking that the animation
  1.1395 +// isn't rebuilt when the restyles happen.
  1.1396 +new_div("animation: kf3 1s linear forwards");
  1.1397 +is(cs.marginTop, "0px", "bug 686656 test 1 at 0ms");
  1.1398 +advance_clock(250);
  1.1399 +display.style.color = "blue";
  1.1400 +is(cs.marginTop, "100px", "bug 686656 test 1 at 250ms");
  1.1401 +advance_clock(375);
  1.1402 +is(cs.marginTop, "50px", "bug 686656 test 1 at 625ms");
  1.1403 +advance_clock(375);
  1.1404 +is(cs.marginTop, "0px", "bug 686656 test 1 at 1000ms");
  1.1405 +done_div();
  1.1406 +display.style.color = "";
  1.1407 +
  1.1408 +// Test interaction of animations and restyling (Bug 686656),
  1.1409 +// with reframing.
  1.1410 +// This test depends on kf3 getting its 0% and 100% values from the
  1.1411 +// rules below it in the cascade; we're checking that the animation
  1.1412 +// isn't rebuilt when the restyles happen.
  1.1413 +new_div("animation: kf3 1s linear forwards");
  1.1414 +is(cs.marginTop, "0px", "bug 686656 test 2 at 0ms");
  1.1415 +advance_clock(250);
  1.1416 +display.style.overflow = "scroll";
  1.1417 +is(cs.marginTop, "100px", "bug 686656 test 2 at 250ms");
  1.1418 +advance_clock(375);
  1.1419 +is(cs.marginTop, "50px", "bug 686656 test 2 at 625ms");
  1.1420 +advance_clock(375);
  1.1421 +is(cs.marginTop, "0px", "bug 686656 test 2 at 1000ms");
  1.1422 +done_div();
  1.1423 +display.style.overflow = "";
  1.1424 +
  1.1425 +// Test that cascading between keyframes rules is per-property rather
  1.1426 +// than per-rule (bug ), and that the timing function isn't taken from a
  1.1427 +// rule that's skipped.  (Bug 738003)
  1.1428 +new_div("animation: cascade 1s linear forwards; position: relative");
  1.1429 +is(cs.top, "0px", "cascade test (top) at 0ms");
  1.1430 +is(cs.left, "0px", "cascade test (top) at 0ms");
  1.1431 +advance_clock(125);
  1.1432 +is(cs.top, "0px", "cascade test (top) at 125ms");
  1.1433 +is(cs.left, "50px", "cascade test (top) at 125ms");
  1.1434 +advance_clock(125);
  1.1435 +is(cs.top, "0px", "cascade test (top) at 250ms");
  1.1436 +is(cs.left, "100px", "cascade test (top) at 250ms");
  1.1437 +advance_clock(125);
  1.1438 +is(cs.top, "50px", "cascade test (top) at 375ms");
  1.1439 +is(cs.left, "100px", "cascade test (top) at 375ms");
  1.1440 +advance_clock(125);
  1.1441 +is(cs.top, "100px", "cascade test (top) at 500ms");
  1.1442 +is(cs.left, "100px", "cascade test (top) at 500ms");
  1.1443 +advance_clock(125);
  1.1444 +is(cs.top, "100px", "cascade test (top) at 625ms");
  1.1445 +is(cs.left, "50px", "cascade test (top) at 625ms");
  1.1446 +advance_clock(125);
  1.1447 +is(cs.top, "100px", "cascade test (top) at 750ms");
  1.1448 +is(cs.left, "0px", "cascade test (top) at 750ms");
  1.1449 +advance_clock(125);
  1.1450 +is(cs.top, "50px", "cascade test (top) at 875ms");
  1.1451 +is(cs.left, "0px", "cascade test (top) at 875ms");
  1.1452 +advance_clock(125);
  1.1453 +is(cs.top, "0px", "cascade test (top) at 1000ms");
  1.1454 +is(cs.left, "0px", "cascade test (top) at 1000ms");
  1.1455 +done_div();
  1.1456 +
  1.1457 +new_div("animation: cascade2 8s linear forwards");
  1.1458 +is(cs.textIndent, "0px", "cascade2 test at 0s");
  1.1459 +advance_clock(1000);
  1.1460 +is(cs.textIndent, "25px", "cascade2 test at 1s");
  1.1461 +advance_clock(1000);
  1.1462 +is(cs.textIndent, "50px", "cascade2 test at 2s");
  1.1463 +advance_clock(1000);
  1.1464 +is(cs.textIndent, "25px", "cascade2 test at 3s");
  1.1465 +advance_clock(1000);
  1.1466 +is(cs.textIndent, "0px", "cascade2 test at 4s");
  1.1467 +advance_clock(3000);
  1.1468 +is(cs.textIndent, "75px", "cascade2 test at 7s");
  1.1469 +advance_clock(1000);
  1.1470 +is(cs.textIndent, "100px", "cascade2 test at 8s");
  1.1471 +done_div();
  1.1472 +
  1.1473 +new_div("-moz-animation: primitives1 2s linear forwards");
  1.1474 +is(cs.getPropertyValue("-moz-transform"), "matrix(1, 0, 0, 1, 0, 0)",
  1.1475 +    "primitives1 at 0s");
  1.1476 +advance_clock(1000);
  1.1477 +is(cs.getPropertyValue("-moz-transform"),
  1.1478 +   "matrix(-0.707107, 0.707107, -0.707107, -0.707107, 0, 0)",
  1.1479 +   "primitives1 at 1s");
  1.1480 +advance_clock(1000);
  1.1481 +is(cs.getPropertyValue("-moz-transform"), "matrix(0, -1, 1, 0, 0, 0)",
  1.1482 +    "primitives1 at 0s");
  1.1483 +done_div();
  1.1484 +
  1.1485 +new_div("animation: important1 1s linear forwards");
  1.1486 +is(cs.marginTop, "50px", "important1 test at 0s");
  1.1487 +advance_clock(500);
  1.1488 +is(cs.marginTop, "75px", "important1 test at 0.5s");
  1.1489 +advance_clock(500);
  1.1490 +is(cs.marginTop, "100px", "important1 test at 1s");
  1.1491 +done_div();
  1.1492 +
  1.1493 +new_div("animation: important2 1s linear forwards");
  1.1494 +is(cs.marginTop, "50px", "important2 (margin-top) test at 0s");
  1.1495 +is(cs.marginBottom, "100px", "important2 (margin-bottom) test at 0s");
  1.1496 +advance_clock(1000);
  1.1497 +is(cs.marginTop, "0px", "important2 (margin-top) test at 1s");
  1.1498 +is(cs.marginBottom, "50px", "important2 (margin-bottom) test at 1s");
  1.1499 +done_div();
  1.1500 +
  1.1501 +// Test that it's the length of the 'animation-name' list that's used to
  1.1502 +// start animations.
  1.1503 +// note: anim2 animates margin-right from 0 to 100px
  1.1504 +// note: anim3 animates margin-top from 0 to 100px
  1.1505 +new_div("animation-name: anim2, anim3; animation-duration: 1s; animation-timing-function: linear; animation-delay: -250ms, -250ms, -750ms, -500ms;");
  1.1506 +is(cs.marginRight, "25px", "animation-name list length is the length that matters");
  1.1507 +is(cs.marginTop, "25px", "animation-name list length is the length that matters");
  1.1508 +done_div();
  1.1509 +new_div("animation-name: anim2, anim3, anim2; animation-duration: 1s; animation-timing-function: linear; animation-delay: -250ms, -250ms, -750ms, -500ms;");
  1.1510 +is(cs.marginRight, "75px", "animation-name list length is the length that matters, and the last occurrence of a name wins");
  1.1511 +is(cs.marginTop, "25px", "animation-name list length is the length that matters");
  1.1512 +done_div();
  1.1513 +
  1.1514 +var dyn_sheet_elt = document.createElement("style");
  1.1515 +document.head.appendChild(dyn_sheet_elt);
  1.1516 +var dyn_sheet = dyn_sheet_elt.sheet;
  1.1517 +dyn_sheet.insertRule("@keyframes dyn1 { from { margin-left: 0 } 50% { margin-left: 50px } to { margin-left: 100px } }", 0);
  1.1518 +dyn_sheet.insertRule("@keyframes dyn2 { from { margin-left: 100px } to { margin-left: 200px } }", 1);
  1.1519 +var dyn1 = dyn_sheet.cssRules[0];
  1.1520 +var dyn2 = dyn_sheet.cssRules[1];
  1.1521 +new_div("animation: dyn1 1s linear");
  1.1522 +is(cs.marginLeft, "0px", "dynamic rule change test, initial state");
  1.1523 +advance_clock(250);
  1.1524 +is(cs.marginLeft, "25px", "dynamic rule change test, 250ms");
  1.1525 +dyn2.name = "dyn1";
  1.1526 +is(cs.marginLeft, "125px", "dynamic rule change test, change in @keyframes name applies");
  1.1527 +dyn2.appendRule("50% { margin-left: 0px }");
  1.1528 +is(cs.marginLeft, "50px", "dynamic rule change test, @keyframes appendRule");
  1.1529 +var dyn2_kf1 = dyn2.cssRules[0]; // currently 0% { margin-left: 100px }
  1.1530 +dyn2_kf1.style.marginLeft = "-100px";
  1.1531 +// FIXME: Bug 978833 (keyframe rules used as nsIStyleRule but doesn't follow immutability contract)
  1.1532 +todo_is(cs.marginLeft, "-50px", "dynamic rule change test, keyframe style set");
  1.1533 +dyn2.name = "dyn2";
  1.1534 +is(cs.marginLeft, "25px", "dynamic rule change test, change in @keyframes name applies (second time)");
  1.1535 +var dyn1_kf2 = dyn1.cssRules[1]; // currently 50% { margin-left: 50px }
  1.1536 +dyn1_kf2.keyText = "25%";
  1.1537 +is(cs.marginLeft, "50px", "dynamic rule change test, change in keyframe keyText");
  1.1538 +dyn1.deleteRule("25%");
  1.1539 +is(cs.marginLeft, "25px", "dynamic rule change test, @keyframes deleteRule");
  1.1540 +done_div();
  1.1541 +dyn_sheet_elt.parentNode.removeChild(dyn_sheet_elt);
  1.1542 +dyn_sheet_elt = null;
  1.1543 +dyn_sheet = null;
  1.1544 +
  1.1545 +SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
  1.1546 +
  1.1547 +</script>
  1.1548 +</pre>
  1.1549 +</body>
  1.1550 +</html>

mercurial