Rubber-stamped by Brady Eidson.
[webbrowser.git] / LayoutTests / transitions / transition-test-helpers.js
blob6c40ab85dfd4481995bea42e91f411e224b7c570
1 /* This is the helper function to run transition tests:
3 Test page requirements:
4 - The body must contain an empty div with id "result"
5 - Call this function directly from the <script> inside the test page
7 Function parameters:
8 expected [required]: an array of arrays defining a set of CSS properties that must have given values at specific times (see below)
9 callback [optional]: a function to be executed just before the test starts (none by default)
11 Each sub-array must contain these items in this order:
12 - the time in seconds at which to snapshot the CSS property
13 - the id of the element on which to get the CSS property value
14 - the name of the CSS property to get [1]
15 - the expected value for the CSS property
16 - the tolerance to use when comparing the effective CSS property value with its expected value
18 [1] If the CSS property name is "-webkit-transform", expected value must be an array of 1 or more numbers corresponding to the matrix elements,
19 or a string which will be compared directly (useful if the expected value is "none")
20 If the CSS property name is "-webkit-transform.N", expected value must be a number corresponding to the Nth element of the matrix
24 function roundNumber(num, decimalPlaces)
26 return Math.round(num * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces);
29 function isCloseEnough(actual, desired, tolerance)
31 var diff = Math.abs(actual - desired);
32 return diff <= tolerance;
35 function isShadow(property)
37 return (property == '-webkit-box-shadow' || property == 'text-shadow');
40 function getShadowXY(cssValue)
42 var text = cssValue.cssText;
43 // Shadow cssText looks like "rgb(0, 0, 255) 0px -3px 10px 0px"
44 var shadowPositionRegExp = /\)\s*(\d+)px\s*(-?\d+)px/;
45 var result = shadowPositionRegExp.exec(cssValue.cssText);
47 var result = [parseInt(result[1]), parseInt(result[2])];
48 return result;
51 function checkExpectedValue(expected, index)
53 var time = expected[index][0];
54 var elementId = expected[index][1];
55 var property = expected[index][2];
56 var expectedValue = expected[index][3];
57 var tolerance = expected[index][4];
59 var computedValue;
60 var pass = false;
61 var transformRegExp = /^-webkit-transform(\.\d+)?$/;
62 if (transformRegExp.test(property)) {
63 computedValue = window.getComputedStyle(document.getElementById(elementId)).webkitTransform;
64 if (typeof expectedValue == "string")
65 pass = (computedValue == expectedValue);
66 else if (typeof expectedValue == "number") {
67 var m = computedValue.split("(");
68 var m = m[1].split(",");
69 pass = isCloseEnough(parseFloat(m[parseInt(property.substring(18))]), expectedValue, tolerance);
70 } else {
71 var m = computedValue.split("(");
72 var m = m[1].split(",");
73 for (i = 0; i < expectedValue.length; ++i) {
74 pass = isCloseEnough(parseFloat(m[i]), expectedValue[i], tolerance);
75 if (!pass)
76 break;
79 } else if (property == "lineHeight") {
80 computedValue = parseInt(window.getComputedStyle(document.getElementById(elementId)).lineHeight);
81 pass = isCloseEnough(computedValue, expectedValue, tolerance);
82 } else {
83 var computedStyle = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property);
84 if (computedStyle.cssValueType == CSSValue.CSS_VALUE_LIST) {
85 var values = [];
86 for (var i = 0; i < computedStyle.length; ++i) {
87 switch (computedStyle[i].cssValueType) {
88 case CSSValue.CSS_PRIMITIVE_VALUE:
89 values.push(computedStyle[i].getFloatValue(CSSPrimitiveValue.CSS_NUMBER));
90 break;
91 case CSSValue.CSS_CUSTOM:
92 // arbitrarily pick shadow-x and shadow-y
93 if (isShadow) {
94 var shadowXY = getShadowXY(computedStyle[i]);
95 values.push(shadowXY[0]);
96 values.push(shadowXY[1]);
97 } else
98 values.push(computedStyle[i].cssText);
99 break;
102 computedValue = values.join(',');
103 pass = true;
104 for (var i = 0; i < values.length; ++i)
105 pass &= isCloseEnough(values[i], expectedValue[i], tolerance);
106 } else if (computedStyle.cssValueType == CSSValue.CSS_PRIMITIVE_VALUE) {
107 switch (computedStyle.primitiveType) {
108 case CSSPrimitiveValue.CSS_STRING:
109 computedValue = computedStyle.getStringValue();
110 pass = computedValue == expectedValue;
111 break;
112 case CSSPrimitiveValue.CSS_RGBCOLOR:
113 var rgbColor = computedStyle.getRGBColorValue();
114 computedValue = [rgbColor.red.getFloatValue(CSSPrimitiveValue.CSS_NUMBER),
115 rgbColor.green.getFloatValue(CSSPrimitiveValue.CSS_NUMBER),
116 rgbColor.blue.getFloatValue(CSSPrimitiveValue.CSS_NUMBER)]; // alpha is not exposed to JS
117 pass = true;
118 for (var i = 0; i < 3; ++i)
119 pass &= isCloseEnough(computedValue[i], expectedValue[i], tolerance);
120 break;
121 case CSSPrimitiveValue.CSS_RECT:
122 computedValue = computedStyle.getRectValue();
123 pass = computedValue == expectedValue;
124 break;
125 default:
126 computedValue = computedStyle.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
127 pass = isCloseEnough(computedValue, expectedValue, tolerance);
132 if (pass)
133 result += "PASS - \"" + property + "\" property for \"" + elementId + "\" element at " + time + "s saw something close to: " + expectedValue + "<br>";
134 else
135 result += "FAIL - \"" + property + "\" property for \"" + elementId + "\" element at " + time + "s expected: " + expectedValue + " but saw: " + computedValue + "<br>";
138 function endTest()
140 document.getElementById('result').innerHTML = result;
142 if (window.layoutTestController)
143 layoutTestController.notifyDone();
146 function checkExpectedValueCallback(expected, index)
148 return function() { checkExpectedValue(expected, index); };
151 function runTest(expected, usePauseAPI)
153 var maxTime = 0;
154 for (var i = 0; i < expected.length; ++i) {
155 var time = expected[i][0];
156 var elementId = expected[i][1];
157 var property = expected[i][2];
158 if (!property.indexOf("-webkit-transform"))
159 property = "-webkit-transform";
161 // We can only use the transition fast-forward mechanism if DRT implements pauseTransitionAtTimeOnElementWithId()
162 if (hasPauseTransitionAPI && usePauseAPI) {
163 layoutTestController.pauseTransitionAtTimeOnElementWithId(property, time, elementId);
164 checkExpectedValue(expected, i);
165 } else {
166 if (time > maxTime)
167 maxTime = time;
169 window.setTimeout(checkExpectedValueCallback(expected, i), time * 1000);
173 if (maxTime > 0)
174 window.setTimeout(endTest, maxTime * 1000 + 50);
175 else
176 endTest();
179 function waitForAnimationStart(callback, delay)
181 var delayTimeout = delay ? 1000 * delay + 10 : 0;
182 // Why the two setTimeouts? Well, for hardware animations we need to ensure that the hardware animation
183 // has started before we try to pause it, and timers fire before animations get committed in the runloop.
184 window.setTimeout(function() {
185 window.setTimeout(function() {
186 callback();
187 }, 0);
188 }, delayTimeout);
191 function startTest(expected, usePauseAPI, callback)
193 if (callback)
194 callback();
196 waitForAnimationStart(function() {
197 runTest(expected, usePauseAPI);
201 var result = "";
202 var hasPauseTransitionAPI;
204 function runTransitionTest(expected, callback, usePauseAPI, doPixelTest)
206 hasPauseTransitionAPI = ('layoutTestController' in window) && ('pauseTransitionAtTimeOnElementWithId' in layoutTestController);
208 if (window.layoutTestController) {
209 if (!doPixelTest)
210 layoutTestController.dumpAsText();
211 layoutTestController.waitUntilDone();
214 if (!expected)
215 throw("Expected results are missing!");
217 window.addEventListener("load", function() { startTest(expected, usePauseAPI, callback); }, false);