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.

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

mercurial