1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/style/test/test_transitions.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,783 @@ 1.4 +<!DOCTYPE HTML> 1.5 +<html> 1.6 +<!-- 1.7 +https://bugzilla.mozilla.org/show_bug.cgi?id=435441 1.8 +--> 1.9 +<head> 1.10 + <title>Test for Bug 435441</title> 1.11 + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> 1.12 + <script type="application/javascript" src="animation_utils.js"></script> 1.13 + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 1.14 + <style type="text/css"> 1.15 + 1.16 + #display p { margin-top: 0; margin-bottom: 0; } 1.17 + #display .before, #display .after { 1.18 + width: -moz-fit-content; border: 1px solid black; 1.19 + } 1.20 + #display .before::before, #display .after::after { 1.21 + display: block; 1.22 + width: 0; 1.23 + text-indent: 0; 1.24 + } 1.25 + #display .before.started::before, #display .after.started::after { 1.26 + width: 100px; 1.27 + text-indent: 100px; 1.28 + transition: 8s width ease-in-out, 8s text-indent ease-in-out; 1.29 + } 1.30 + #display .before::before { 1.31 + content: "Before"; 1.32 + } 1.33 + #display .after::after { 1.34 + content: "After"; 1.35 + } 1.36 + 1.37 + </style> 1.38 +</head> 1.39 +<body> 1.40 +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435441">Mozilla Bug 435441</a> 1.41 +<div id="display"> 1.42 + 1.43 +</div> 1.44 +<pre id="test"> 1.45 +<script type="application/javascript"> 1.46 + 1.47 +/** Test for Bug 435441 **/ 1.48 + 1.49 +// Run tests simultaneously so we don't have to take up too much time. 1.50 +SimpleTest.waitForExplicitFinish(); 1.51 +var gTestsRunning = 0; 1.52 +function TestStarted() { ++gTestsRunning; } 1.53 +function TestFinished() { if (--gTestsRunning == 0) SimpleTest.finish(); } 1.54 + 1.55 +// An array of arrays of functions to be called at the outer index number 1.56 +// of seconds after the present. 1.57 +var gFutureCalls = []; 1.58 + 1.59 +function add_future_call(index, func) 1.60 +{ 1.61 + if (!(index in gFutureCalls)) { 1.62 + gFutureCalls[index] = []; 1.63 + } 1.64 + gFutureCalls[index].push(func); 1.65 + TestStarted(); 1.66 +} 1.67 +var gStartTime1, gStartTime2; 1.68 +var gCurrentTime; 1.69 +var gSetupComplete = false; 1.70 + 1.71 +function process_future_calls(index) 1.72 +{ 1.73 + var calls = gFutureCalls[index]; 1.74 + if (!calls) 1.75 + return; 1.76 + gCurrentTime = Date.now(); 1.77 + for (var i = 0; i < calls.length; ++i) { 1.78 + calls[i](); 1.79 + TestFinished(); 1.80 + } 1.81 +} 1.82 + 1.83 +var timingFunctions = { 1.84 + // a map from the value of 'transition-timing-function' to an array of 1.85 + // the portions this function yields at 0 (always 0), 1/4, 1/2, and 1.86 + // 3/4 and all (always 1) of the way through the time of the 1.87 + // transition. Each portion is represented as a value and an 1.88 + // acceptable error tolerance (based on a time error of 1%) for that 1.89 + // value. 1.90 + 1.91 + // ease 1.92 + "ease": bezier(0.25, 0.1, 0.25, 1), 1.93 + "cubic-bezier(0.25, 0.1, 0.25, 1.0)": bezier(0.25, 0.1, 0.25, 1), 1.94 + 1.95 + // linear and various synonyms for it 1.96 + "linear": function(x) { return x; }, 1.97 + "cubic-bezier(0.0, 0.0, 1.0, 1.0)": function(x) { return x; }, 1.98 + "cubic-bezier(0, 0, 1, 1)": function(x) { return x; }, 1.99 + "cubic-bezier(0, 0, 0, 0.0)": function(x) { return x; }, 1.100 + "cubic-bezier(1.0, 1, 0, 0)": function(x) { return x; }, 1.101 + 1.102 + // ease-in 1.103 + "ease-in": bezier(0.42, 0, 1, 1), 1.104 + "cubic-bezier(0.42, 0, 1.0, 1.0)": bezier(0.42, 0, 1, 1), 1.105 + 1.106 + // ease-out 1.107 + "ease-out": bezier(0, 0, 0.58, 1), 1.108 + "cubic-bezier(0, 0, 0.58, 1.0)": bezier(0, 0, 0.58, 1), 1.109 + 1.110 + // ease-in-out 1.111 + "ease-in-out": bezier(0.42, 0, 0.58, 1), 1.112 + "cubic-bezier(0.42, 0, 0.58, 1.0)": bezier(0.42, 0, 0.58, 1), 1.113 + 1.114 + // other cubic-bezier values 1.115 + "cubic-bezier(0.4, 0.1, 0.7, 0.95)": bezier(0.4, 0.1, 0.7, 0.95), 1.116 + "cubic-bezier(1, 0, 0, 1)": bezier(1, 0, 0, 1), 1.117 + "cubic-bezier(0, 1, 1, 0)": bezier(0, 1, 1, 0), 1.118 + 1.119 +}; 1.120 + 1.121 +var div = document.getElementById("display"); 1.122 + 1.123 +// Set up all the elements on which we are going to start transitions. 1.124 + 1.125 +// We have two reference elements to check the expected timing range. 1.126 +// They both have 8s linear transitions from 0 to 1000px. 1.127 +function make_reference_p() { 1.128 + var p = document.createElement("p"); 1.129 + p.appendChild(document.createTextNode("reference")); 1.130 + p.style.textIndent = "0px"; 1.131 + p.style.transition = "8s text-indent linear"; 1.132 + div.appendChild(p); 1.133 + return p; 1.134 +} 1.135 +var earlyref = make_reference_p(); 1.136 +var earlyrefcs = getComputedStyle(earlyref, ""); 1.137 + 1.138 +// Test all timing functions using a set of 8-second transitions, which 1.139 +// we check at times 0, 2s, 4s, 6s, and 8s. 1.140 +var tftests = []; 1.141 +for (var tf in timingFunctions) { 1.142 + var p = document.createElement("p"); 1.143 + var t = document.createTextNode("transition-timing-function: " + tf); 1.144 + p.appendChild(t); 1.145 + p.style.textIndent = "0px"; 1.146 + p.style.transition = "8s text-indent linear"; 1.147 + p.style.transitionTimingFunction = tf; 1.148 + div.appendChild(p); 1.149 + is(getComputedStyle(p, "").textIndent, "0px", 1.150 + "should be zero before changing value"); 1.151 + tftests.push([ p, tf ]); 1.152 +} 1.153 + 1.154 +// Check that the timing function continues even when we restyle in the 1.155 +// middle. 1.156 +var interrupt_tests = []; 1.157 +for (var restyleParent of [true, false]) { 1.158 + for (var itime = 2; itime < 8; itime += 2) { 1.159 + var p = document.createElement("p"); 1.160 + var t = document.createTextNode("interrupt on " + 1.161 + (restyleParent ? "parent" : "node itself") + 1.162 + " at " + itime + "s"); 1.163 + p.appendChild(t); 1.164 + p.style.textIndent = "0px"; 1.165 + p.style.transition = "8s text-indent cubic-bezier(0, 1, 1, 0)"; 1.166 + if (restyleParent) { 1.167 + var d = document.createElement("div"); 1.168 + d.appendChild(p); 1.169 + div.appendChild(d); 1.170 + } else { 1.171 + div.appendChild(p); 1.172 + } 1.173 + is(getComputedStyle(p, "").textIndent, "0px", 1.174 + "should be zero before changing value"); 1.175 + setTimeout("interrupt_tests[" + interrupt_tests.length + "]" + 1.176 + "[0]" + (restyleParent ? ".parentNode" : "") + 1.177 + ".style.color = 'blue';" + 1.178 + "check_interrupt_tests()", itime*1000); 1.179 + interrupt_tests.push([ p, itime ]); 1.180 + } 1.181 +} 1.182 + 1.183 +// Test transition-delay values of -4s through 4s on a 4s transition 1.184 +// with 'ease-out' timing function. 1.185 +var delay_tests = {}; 1.186 +for (var d = -4; d <= 4; ++d) { 1.187 + var p = document.createElement("p"); 1.188 + var delay = d + "s"; 1.189 + var t = document.createTextNode("transition-delay: " + delay); 1.190 + p.appendChild(t); 1.191 + p.style.marginLeft = "0px"; 1.192 + p.style.transition = "4s margin-left ease-out " + delay; 1.193 + div.appendChild(p); 1.194 + is(getComputedStyle(p, "").marginLeft, "0px", 1.195 + "should be zero before changing value"); 1.196 + delay_tests[d] = p; 1.197 +} 1.198 + 1.199 +// Test transition-delay values of -4s through 4s on a 4s transition 1.200 +// with duration of zero. 1.201 +var delay_zero_tests = {}; 1.202 +for (var d = -4; d <= 4; ++d) { 1.203 + var p = document.createElement("p"); 1.204 + var delay = d + "s"; 1.205 + var t = document.createTextNode("transition-delay: " + delay); 1.206 + p.appendChild(t); 1.207 + p.style.marginLeft = "0px"; 1.208 + p.style.transition = "0s margin-left linear " + delay; 1.209 + div.appendChild(p); 1.210 + is(getComputedStyle(p, "").marginLeft, "0px", 1.211 + "should be zero before changing value"); 1.212 + delay_zero_tests[d] = p; 1.213 +} 1.214 + 1.215 +// Test that changing the value on an already-running transition to the 1.216 +// value it currently happens to have resets the transition. 1.217 +function make_reset_test(transition, description) 1.218 +{ 1.219 + var p = document.createElement("p"); 1.220 + var t = document.createTextNode(description); 1.221 + p.appendChild(t); 1.222 + p.style.marginLeft = "0px"; 1.223 + p.style.transition = transition; 1.224 + div.appendChild(p); 1.225 + is(getComputedStyle(p, "").marginLeft, "0px", 1.226 + "should be zero before changing value"); 1.227 + return p; 1.228 +} 1.229 +var reset_test = make_reset_test("4s margin-left ease-out 4s", "transition-delay reset to starting point"); 1.230 +var reset_test_reference = make_reset_test("4s margin-left linear -3s", "reference for previous test (reset test)"); 1.231 + 1.232 +// Test that transitions on descendants do not trigger when the 1.233 +// inherited value is itself transitioning. In other words, when 1.234 +// ancestor and descendant both have a transition for the same property, 1.235 +// and the descendant inherits the property from the ancestor, the 1.236 +// descendant's transition is ignored (as part of the idea of not 1.237 +// starting transitions on changes that result from animation). 1.238 +// See http://lists.w3.org/Archives/Public/www-style/2009Jun/0121.html 1.239 +// and http://lists.w3.org/Archives/Public/www-style/2009Jul/0050.html 1.240 +var descendant_tests = [ 1.241 + { parent_transition: "", 1.242 + child_transition: "4s text-indent" }, 1.243 + { parent_transition: "4s text-indent", 1.244 + child_transition: "" }, 1.245 + { parent_transition: "4s text-indent", 1.246 + child_transition: "16s text-indent" }, 1.247 + { parent_transition: "4s text-indent", 1.248 + child_transition: "1s text-indent" }, 1.249 + { parent_transition: "8s letter-spacing", 1.250 + child_transition: "4s text-indent" }, 1.251 + { parent_transition: "4s text-indent", 1.252 + child_transition: "8s letter-spacing" }, 1.253 + { parent_transition: "4s text-indent", 1.254 + child_transition: "8s all" }, 1.255 + { parent_transition: "8s text-indent", 1.256 + child_transition: "4s all" }, 1.257 + // examples with positive and negative delay 1.258 + { parent_transition: "4s text-indent 1s", 1.259 + child_transition: "8s text-indent" }, 1.260 + { parent_transition: "4s text-indent -1s", 1.261 + child_transition: "8s text-indent" } 1.262 +]; 1.263 + 1.264 +for (var i in descendant_tests) { 1.265 + var test = descendant_tests[i]; 1.266 + test.parentNode = document.createElement("div"); 1.267 + test.childNode = document.createElement("p"); 1.268 + test.parentNode.appendChild(test.childNode); 1.269 + test.childNode.appendChild(document.createTextNode( 1.270 + "parent with \"" + test.parent_transition + "\" and " + 1.271 + "child with \"" + test.child_transition + "\"")); 1.272 + test.parentNode.style.transition = test.parent_transition; 1.273 + test.childNode.style.transition = test.child_transition; 1.274 + test.parentNode.style.textIndent = "50px"; // transition from 50 to 150 1.275 + test.parentNode.style.letterSpacing = "10px"; // transition from 10 to 5 1.276 + div.appendChild(test.parentNode); 1.277 + var parentCS = getComputedStyle(test.parentNode, ""); 1.278 + var childCS = getComputedStyle(test.childNode, ""); 1.279 + is(parentCS.textIndent, "50px", 1.280 + "parent text-indent should be 50px before changing"); 1.281 + is(parentCS.letterSpacing, "10px", 1.282 + "parent letter-spacing should be 10px before changing"); 1.283 + is(childCS.textIndent, "50px", 1.284 + "child text-indent should be 50px before changing"); 1.285 + is(childCS.letterSpacing, "10px", 1.286 + "child letter-spacing should be 10px before changing"); 1.287 + test.childCS = childCS; 1.288 +} 1.289 + 1.290 +// For all of these transitions, the transition for margin-left should 1.291 +// have a duration of 8s, and the default timing function (ease) and 1.292 +// delay (0). 1.293 +// This is because we're implementing the proposal in 1.294 +// http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html 1.295 +var number_tests = [ 1.296 + { style: "transition: 4s margin, 8s margin-left" }, 1.297 + { style: "transition: 4s margin-left, 8s margin" }, 1.298 + { style: "transition-property: margin-left; " + 1.299 + "transition-duration: 8s, 2s" }, 1.300 + { style: "transition-property: margin-left, margin-left; " + 1.301 + "transition-duration: 2s, 8s" }, 1.302 + { style: "transition-property: margin-left, margin-left, margin-left; " + 1.303 + "transition-duration: 8s, 2s" }, 1.304 + { style: "transition-property: margin-left; " + 1.305 + "transition-duration: 8s, 16s" }, 1.306 + { style: "transition-property: margin-left, margin-left; " + 1.307 + "transition-duration: 16s, 8s" }, 1.308 + { style: "transition-property: margin-left, margin-left, margin-left; " + 1.309 + "transition-duration: 8s, 16s" }, 1.310 + { style: "transition-property: text-indent,word-spacing,margin-left; " + 1.311 + "transition-duration: 8s; " + 1.312 + "transition-delay: 0, 8s" }, 1.313 + { style: "transition-property: text-indent,word-spacing,margin-left; " + 1.314 + "transition-duration: 8s, 16s; " + 1.315 + "transition-delay: 8s, 8s, 0, 8s, 8s, 8s" }, 1.316 +]; 1.317 + 1.318 +for (var i in number_tests) { 1.319 + var test = number_tests[i]; 1.320 + var p = document.createElement("p"); 1.321 + p.setAttribute("style", test.style); 1.322 + var t = document.createTextNode(test.style); 1.323 + p.appendChild(t); 1.324 + p.style.marginLeft = "100px"; 1.325 + div.appendChild(p); 1.326 + is(getComputedStyle(p, "").marginLeft, "100px", 1.327 + "should be 100px before changing value"); 1.328 + test.node = p; 1.329 +} 1.330 + 1.331 +// Test transitions that are also from-display:none, to-display:none, and 1.332 +// display:none throughout. 1.333 +var from_none_test, to_none_test, always_none_test; 1.334 +function make_display_test(initially_none, text) 1.335 +{ 1.336 + var p = document.createElement("p"); 1.337 + p.appendChild(document.createTextNode(text)); 1.338 + p.style.textIndent = "0px"; 1.339 + p.style.transition = "8s text-indent ease-in-out"; 1.340 + if (initially_none) 1.341 + p.style.display = "none"; 1.342 + div.appendChild(p); 1.343 + return p; 1.344 +} 1.345 +from_none_test = make_display_test(true, "transition from display:none"); 1.346 +to_none_test = make_display_test(false, "transition to display:none"); 1.347 +always_none_test = make_display_test(true, "transition always display:none"); 1.348 +var display_tests = [ from_none_test, to_none_test, always_none_test ]; 1.349 + 1.350 +// Test transitions on pseudo-elements 1.351 +var before_test, after_test; 1.352 +function make_pseudo_elem_test(pseudo) 1.353 +{ 1.354 + var p = document.createElement("p"); 1.355 + p.className = pseudo; 1.356 + div.appendChild(p); 1.357 + return {"pseudo": pseudo, element: p}; 1.358 +} 1.359 +before_test = make_pseudo_elem_test("before"); 1.360 +after_test = make_pseudo_elem_test("after"); 1.361 +var pseudo_element_tests = [ before_test, after_test ]; 1.362 + 1.363 +// FIXME (Bug 522599): Test a transition that reverses partway through. 1.364 + 1.365 +var lateref = make_reference_p(); 1.366 +var laterefcs = getComputedStyle(lateref, ""); 1.367 + 1.368 +// flush style changes 1.369 +var x = getComputedStyle(div, "").color; 1.370 + 1.371 +// Start our timer as close as possible to when we start the first 1.372 +// transition. 1.373 +// Do not use setInterval because once it gets off in time, it stays off. 1.374 +for (var i = 1; i <= 8; ++i) { 1.375 + setTimeout(process_future_calls, i * 1000, i); 1.376 +} 1.377 +gStartTime1 = Date.now(); // set before any transitions have started 1.378 + 1.379 +// Start all the transitions. 1.380 +earlyref.style.textIndent = "1000px"; 1.381 +for (var test in tftests) { 1.382 + var p = tftests[test][0]; 1.383 + p.style.textIndent = "100px"; 1.384 +} 1.385 +for (var test in interrupt_tests) { 1.386 + var p = interrupt_tests[test][0]; 1.387 + p.style.textIndent = "100px"; 1.388 +} 1.389 +for (var d in delay_tests) { 1.390 + var p = delay_tests[d]; 1.391 + p.style.marginLeft = "100px"; 1.392 +} 1.393 +for (var d in delay_zero_tests) { 1.394 + var p = delay_zero_tests[d]; 1.395 + p.style.marginLeft = "100px"; 1.396 +} 1.397 +reset_test.style.marginLeft = "100px"; 1.398 +reset_test_reference.style.marginLeft = "100px"; 1.399 +for (var i in descendant_tests) { 1.400 + var test = descendant_tests[i]; 1.401 + test.parentNode.style.textIndent = "150px"; 1.402 + test.parentNode.style.letterSpacing = "5px"; 1.403 +} 1.404 +for (var i in number_tests) { 1.405 + var test = number_tests[i]; 1.406 + test.node.style.marginLeft = "50px"; 1.407 +} 1.408 +from_none_test.style.textIndent = "100px"; 1.409 +from_none_test.style.display = ""; 1.410 +to_none_test.style.textIndent = "100px"; 1.411 +to_none_test.style.display = "none"; 1.412 +always_none_test.style.textIndent = "100px"; 1.413 +for (var i in pseudo_element_tests) { 1.414 + var test = pseudo_element_tests[i]; 1.415 + test.element.classList.add("started"); 1.416 +} 1.417 +lateref.style.textIndent = "1000px"; 1.418 + 1.419 +// flush style changes 1.420 +x = getComputedStyle(div, "").color; 1.421 + 1.422 +gStartTime2 = Date.now(); // set after all transitions have started 1.423 +gCurrentTime = gStartTime2; 1.424 + 1.425 +/** 1.426 + * Assert that a transition whose timing function yields the bezier 1.427 + * |func|, running from |start_time| to |end_time| (both in seconds 1.428 + * relative to when the transitions were started) should have produced 1.429 + * computed value |cval| given that the transition was from 1.430 + * |start_value| to |end_value| (both numbers in CSS pixels). 1.431 + */ 1.432 +function check_transition_value(func, start_time, end_time, 1.433 + start_value, end_value, cval, desc, 1.434 + xfail) 1.435 +{ 1.436 + /** 1.437 + * Compute the value at a given time |elapsed|, by normalizing the 1.438 + * input to the timing function using start_time and end_time and 1.439 + * then turning the output into a value using start_value and 1.440 + * end_value. 1.441 + * 1.442 + * The |error_direction| argument should be either -1, 0, or 1, 1.443 + * suggesting adding on a little bit of error, to allow for the 1.444 + * cubic-bezier calculation being an approximation. The amount of 1.445 + * error is proportional to the slope of the timing function, since 1.446 + * the error is added to the *input* of the timing function (after 1.447 + * normalization to 0-1 based on start_time and end_time). 1.448 + */ 1.449 + function value_at(elapsed, error_direction) { 1.450 + var time_portion = (elapsed - start_time) / (end_time - start_time); 1.451 + if (time_portion < 0) 1.452 + time_portion = 0; 1.453 + else if (time_portion > 1) 1.454 + time_portion = 1; 1.455 + // Assume a small error since bezier computation can be off slightly. 1.456 + // (This test's computation is probably more accurate than Mozilla's.) 1.457 + var value_portion = func(time_portion + error_direction * 0.0005); 1.458 + if (value_portion < 0) 1.459 + value_portion = 0; 1.460 + else if (value_portion > 1) 1.461 + value_portion = 1; 1.462 + var value = (1 - value_portion) * start_value + value_portion * end_value; 1.463 + if (start_value > end_value) 1.464 + error_direction = -error_direction; 1.465 + // Computed values get rounded to 1/60th of a pixel. 1.466 + return value + error_direction * 0.02; 1.467 + } 1.468 + 1.469 + var time_range; // in seconds 1.470 + var uns_range; // |range| before being sorted (so errors give it 1.471 + // in the original order 1.472 + if (!gSetupComplete) { 1.473 + // No timers involved 1.474 + time_range = [0, 0]; 1.475 + if (start_time < 0) { 1.476 + uns_range = [ value_at(0, -1), value_at(0, 1) ]; 1.477 + } else { 1.478 + var val = value_at(0, 0); 1.479 + uns_range = [val, val]; 1.480 + } 1.481 + } else { 1.482 + time_range = [ px_to_num(earlyrefcs.textIndent) / 125, 1.483 + px_to_num(laterefcs.textIndent) / 125 ]; 1.484 + // seconds 1.485 + uns_range = [ value_at(time_range[0], -1), 1.486 + value_at(time_range[1], 1) ]; 1.487 + } 1.488 + var range = uns_range.concat(). /* concat to clone array */ 1.489 + sort(function compareNumbers(a,b) { return a - b; }); 1.490 + var actual = px_to_num(cval); 1.491 + 1.492 + var fn = ok; 1.493 + if (xfail && xfail(range)) 1.494 + fn = todo; 1.495 + 1.496 + fn(range[0] <= actual && actual <= range[1], 1.497 + desc + ": computed value " + cval + " should be between " + 1.498 + uns_range[0].toFixed(6) + "px and " + uns_range[1].toFixed(6) + 1.499 + "px at time between " + time_range[0] + "s and " + time_range[1] + "s."); 1.500 +} 1.501 + 1.502 +function check_ref_range() 1.503 +{ 1.504 + // This is the only test where we compare the progress of the 1.505 + // transitions to an actual time; we need considerable tolerance at 1.506 + // the low end (we are using half a second). 1.507 + var expected_range = [ (gCurrentTime - gStartTime2 - 40) / 8, 1.508 + (Date.now() - gStartTime1 + 20) / 8 ]; 1.509 + if (expected_range[0] > 1000) { 1.510 + expected_range[0] = 1000; 1.511 + } 1.512 + if (expected_range[1] > 1000) { 1.513 + expected_range[1] = 1000; 1.514 + } 1.515 + function check(desc, value) { 1.516 + // The timing on the unit test VMs is not reliable, so make this 1.517 + // test report PASS when it succeeds and TODO when it fails. 1.518 + var passed = expected_range[0] <= value && value <= expected_range[1]; 1.519 + (passed ? ok : todo)(passed, 1.520 + desc + ": computed value " + value + "px should be between " + 1.521 + expected_range[0].toFixed(6) + "px and " + 1.522 + expected_range[1].toFixed(6) + "px at time between " + 1.523 + expected_range[0]/125 + "s and " + expected_range[1]/125 + "s."); 1.524 + } 1.525 + check("early reference", px_to_num(earlyrefcs.textIndent)); 1.526 + check("late reference", px_to_num(laterefcs.textIndent)); 1.527 +} 1.528 + 1.529 +for (var i = 1; i <= 8; ++i) { 1.530 + add_future_call(i, check_ref_range); 1.531 +} 1.532 + 1.533 +function check_tf_test() 1.534 +{ 1.535 + for (var test in tftests) { 1.536 + var p = tftests[test][0]; 1.537 + var tf = tftests[test][1]; 1.538 + 1.539 + check_transition_value(timingFunctions[tf], 0, 8, 0, 100, 1.540 + getComputedStyle(p, "").textIndent, 1.541 + "timing function test for timing function " + tf); 1.542 + 1.543 + } 1.544 + 1.545 + check_interrupt_tests(); 1.546 +} 1.547 + 1.548 +check_tf_test(); 1.549 +add_future_call(2, check_tf_test); 1.550 +add_future_call(4, check_tf_test); 1.551 +add_future_call(6, check_tf_test); 1.552 +add_future_call(8, check_tf_test); 1.553 + 1.554 +function check_interrupt_tests() 1.555 +{ 1.556 + for (var test in interrupt_tests) { 1.557 + var p = interrupt_tests[test][0]; 1.558 + var itime = interrupt_tests[test][1]; 1.559 + 1.560 + check_transition_value(timingFunctions["cubic-bezier(0, 1, 1, 0)"], 1.561 + 0, 8, 0, 100, 1.562 + getComputedStyle(p, "").textIndent, 1.563 + "interrupt " + 1.564 + (p.parentNode == div ? "" : "on parent ") + 1.565 + "test for time " + itime + "s"); 1.566 + } 1.567 +} 1.568 + 1.569 +// check_interrupt_tests is called from check_tf_test and from 1.570 +// where we reset the interrupts 1.571 + 1.572 +function check_delay_test(time) 1.573 +{ 1.574 + var tf = timingFunctions["ease-out"]; 1.575 + for (var d in delay_tests) { 1.576 + var p = delay_tests[d]; 1.577 + 1.578 + check_transition_value(tf, Number(d), Number(d) + 4, 0, 100, 1.579 + getComputedStyle(p, "").marginLeft, 1.580 + "delay test for delay " + d + "s"); 1.581 + } 1.582 +} 1.583 + 1.584 +check_delay_test(0); 1.585 +for (var i = 1; i <= 8; ++i) { 1.586 + add_future_call(i, check_delay_test); 1.587 +} 1.588 + 1.589 +function check_delay_zero_test(time) 1.590 +{ 1.591 + for (var d in delay_zero_tests) { 1.592 + var p = delay_zero_tests[d]; 1.593 + 1.594 + time_range = [ px_to_num(earlyrefcs.textIndent) / 125, 1.595 + px_to_num(laterefcs.textIndent) / 125 ]; 1.596 + var m = getComputedStyle(p, "").marginLeft; 1.597 + var desc = "delay_zero test for delay " + d + "s"; 1.598 + if (time_range[0] < d && time_range[1] < d) { 1.599 + is(m, "0px", desc); 1.600 + } else if ((time_range[0] > d && time_range[1] > d) || 1.601 + (d == 0 && time == 0)) { 1.602 + is(m, "100px", desc); 1.603 + } 1.604 + } 1.605 +} 1.606 + 1.607 +check_delay_zero_test(0); 1.608 +for (var i = 1; i <= 8; ++i) { 1.609 + add_future_call(i, check_delay_zero_test); 1.610 +} 1.611 + 1.612 +function reset_reset_test(time) 1.613 +{ 1.614 + reset_test.style.marginLeft = "0px"; 1.615 +} 1.616 +function check_reset_test(time) 1.617 +{ 1.618 + is(getComputedStyle(reset_test, "").marginLeft, "0px", 1.619 + "reset test value at time " + time + "s."); 1.620 +} 1.621 +check_reset_test(0); 1.622 +// reset the reset test right now so we don't have to worry about clock skew 1.623 +// To make sure that this is valid, check that a pretty-much-identical test is 1.624 +// already transitioning. 1.625 +is(getComputedStyle(reset_test_reference, "").marginLeft, "75px", 1.626 + "reset test reference value"); 1.627 +reset_reset_test(); 1.628 +check_reset_test(0); 1.629 +for (var i = 1; i <= 8; ++i) { 1.630 + (function(j) { 1.631 + add_future_call(j, function() { check_reset_test(j); }); 1.632 + })(i); 1.633 +} 1.634 + 1.635 +check_descendant_tests(); 1.636 +add_future_call(2, check_descendant_tests); 1.637 +add_future_call(6, check_descendant_tests); 1.638 + 1.639 +function check_descendant_tests() { 1.640 + // text-indent: transition from 50px to 150px 1.641 + // letter-spacing: transition from 10px to 5px 1.642 + var values = {}; 1.643 + values["text-indent"] = [ 50, 150 ]; 1.644 + values["letter-spacing"] = [ 10, 5 ]; 1.645 + var tf = timingFunctions["ease"]; 1.646 + 1.647 + for (var i in descendant_tests) { 1.648 + var test = descendant_tests[i]; 1.649 + 1.650 + /* ti=text-indent, ls=letter-spacing */ 1.651 + var child_ti_duration = 0; 1.652 + var child_ls_duration = 0; 1.653 + var child_ti_delay = 0; 1.654 + var child_ls_delay = 0; 1.655 + 1.656 + if (test.parent_transition != "") { 1.657 + var props = test.parent_transition.split(" "); 1.658 + var duration = parseInt(props[0]); 1.659 + var delay = (props.length > 2) ? parseInt(props[2]) : 0; 1.660 + var property = props[1]; 1.661 + if (property == "text-indent") { 1.662 + child_ti_duration = duration; 1.663 + child_ti_delay = delay; 1.664 + } else if (property == "letter-spacing") { 1.665 + child_ls_duration = duration; 1.666 + child_ls_delay = delay; 1.667 + } else { 1.668 + ok(false, "fix this test (unexpected transition-property " + 1.669 + property + " on parent)"); 1.670 + } 1.671 + } 1.672 + 1.673 + if (test.child_transition != "") { 1.674 + var props = test.child_transition.split(" "); 1.675 + var duration = parseInt(props[0]); 1.676 + var delay = (props.length > 2) ? parseInt(props[2]) : 0; 1.677 + var property = props[1]; 1.678 + if (property != "text-indent" && property != "letter-spacing" && 1.679 + property != "all") { 1.680 + ok(false, "fix this test (unexpected transition-property " + 1.681 + property + " on child)"); 1.682 + } 1.683 + 1.684 + if (property != "letter-spacing" && child_ti_duration == 0) { 1.685 + child_ti_duration = duration; 1.686 + child_ti_delay = delay; 1.687 + } 1.688 + if (property != "text-indent" && child_ls_duration == 0) { 1.689 + child_ls_duration = duration; 1.690 + child_ls_delay = delay; 1.691 + } 1.692 + } 1.693 + 1.694 + var time_portions = { 1.695 + "text-indent": 1.696 + { duration: child_ti_duration, delay: child_ti_delay }, 1.697 + "letter-spacing": 1.698 + { duration: child_ls_duration, delay: child_ls_delay }, 1.699 + }; 1.700 + 1.701 + for (var prop in {"text-indent": true, "letter-spacing": true}) { 1.702 + var time_portion = time_portions[prop]; 1.703 + 1.704 + if (time_portion.duration == 0) { 1.705 + time_portion.duration = 0.01; 1.706 + time_portion.delay = -1; 1.707 + } 1.708 + 1.709 + check_transition_value(tf, time_portion.delay, 1.710 + time_portion.delay + time_portion.duration, 1.711 + values[prop][0], values[prop][1], 1.712 + test.childCS.getPropertyValue(prop), 1.713 + "descendant test, property " + prop); 1.714 + } 1.715 + } 1.716 +} 1.717 + 1.718 +function check_number_tests() 1.719 +{ 1.720 + var tf = timingFunctions["ease"]; 1.721 + for (var d in number_tests) { 1.722 + var test = number_tests[d]; 1.723 + var p = test.node; 1.724 + 1.725 + check_transition_value(tf, 0, 8, 100, 50, 1.726 + getComputedStyle(p, "").marginLeft, 1.727 + "number of transitions test for style " + 1.728 + test.style); 1.729 + } 1.730 +} 1.731 + 1.732 +check_number_tests(0); 1.733 +add_future_call(2, check_number_tests); 1.734 +add_future_call(4, check_number_tests); 1.735 +add_future_call(6, check_number_tests); 1.736 +add_future_call(8, check_number_tests); 1.737 + 1.738 +function check_display_tests(time) 1.739 +{ 1.740 + var tf = timingFunctions["ease-in-out"]; 1.741 + for (var i in display_tests) { 1.742 + var p = display_tests[i]; 1.743 + 1.744 + check_transition_value(tf, 0, 8, 0, 100, 1.745 + getComputedStyle(p, "").textIndent, 1.746 + "display test for test with " + 1.747 + p.childNodes[0].data, 1.748 + // TODO: Making transitions work on 'display:none' elements is 1.749 + // still not implemented. 1.750 + function(range) { return p != to_none_test && 1.751 + range[1] < 100 }); 1.752 + } 1.753 +} 1.754 + 1.755 +check_display_tests(0); 1.756 +add_future_call(2, function() { check_display_tests(2); }); 1.757 +add_future_call(4, function() { check_display_tests(4); }); 1.758 +add_future_call(6, function() { check_display_tests(6); }); 1.759 +add_future_call(8, function() { check_display_tests(8); }); 1.760 + 1.761 +function check_pseudo_element_tests(time) 1.762 +{ 1.763 + var tf = timingFunctions["ease-in-out"]; 1.764 + for (var i in pseudo_element_tests) { 1.765 + var test = pseudo_element_tests[i]; 1.766 + 1.767 + check_transition_value(tf, 0, 8, 0, 100, 1.768 + getComputedStyle(test.element, "").width, 1.769 + "::"+test.pseudo+" test"); 1.770 + check_transition_value(tf, 0, 8, 0, 100, 1.771 + getComputedStyle(test.element, 1.772 + "::"+test.pseudo).textIndent, 1.773 + "::"+test.pseudo+" indent test"); 1.774 + } 1.775 +} 1.776 +check_pseudo_element_tests(0); 1.777 +add_future_call(2, function() { check_pseudo_element_tests(2); }); 1.778 +add_future_call(4, function() { check_pseudo_element_tests(4); }); 1.779 +add_future_call(6, function() { check_pseudo_element_tests(6); }); 1.780 +add_future_call(8, function() { check_pseudo_element_tests(8); }); 1.781 + 1.782 +gSetupComplete = true; 1.783 +</script> 1.784 +</pre> 1.785 +</body> 1.786 +</html>