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
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])];
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];
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
);
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
);
79 } else if (property
== "lineHeight") {
80 computedValue
= parseInt(window
.getComputedStyle(document
.getElementById(elementId
)).lineHeight
);
81 pass
= isCloseEnough(computedValue
, expectedValue
, tolerance
);
83 var computedStyle
= window
.getComputedStyle(document
.getElementById(elementId
)).getPropertyCSSValue(property
);
84 if (computedStyle
.cssValueType
== CSSValue
.CSS_VALUE_LIST
) {
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
));
91 case CSSValue
.CSS_CUSTOM
:
92 // arbitrarily pick shadow-x and shadow-y
94 var shadowXY
= getShadowXY(computedStyle
[i
]);
95 values
.push(shadowXY
[0]);
96 values
.push(shadowXY
[1]);
98 values
.push(computedStyle
[i
].cssText
);
102 computedValue
= values
.join(',');
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
;
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
118 for (var i
= 0; i
< 3; ++i
)
119 pass
&= isCloseEnough(computedValue
[i
], expectedValue
[i
], tolerance
);
121 case CSSPrimitiveValue
.CSS_RECT
:
122 computedValue
= computedStyle
.getRectValue();
123 pass
= computedValue
== expectedValue
;
126 computedValue
= computedStyle
.getFloatValue(CSSPrimitiveValue
.CSS_NUMBER
);
127 pass
= isCloseEnough(computedValue
, expectedValue
, tolerance
);
133 result
+= "PASS - \"" + property
+ "\" property for \"" + elementId
+ "\" element at " + time
+ "s saw something close to: " + expectedValue
+ "<br>";
135 result
+= "FAIL - \"" + property
+ "\" property for \"" + elementId
+ "\" element at " + time
+ "s expected: " + expectedValue
+ " but saw: " + computedValue
+ "<br>";
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
)
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
);
169 window
.setTimeout(checkExpectedValueCallback(expected
, i
), time
* 1000);
174 window
.setTimeout(endTest
, maxTime
* 1000 + 50);
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() {
191 function startTest(expected
, usePauseAPI
, callback
)
196 waitForAnimationStart(function() {
197 runTest(expected
, usePauseAPI
);
202 var hasPauseTransitionAPI
;
204 function runTransitionTest(expected
, callback
, usePauseAPI
, doPixelTest
)
206 hasPauseTransitionAPI
= ('layoutTestController' in window
) && ('pauseTransitionAtTimeOnElementWithId' in layoutTestController
);
208 if (window
.layoutTestController
) {
210 layoutTestController
.dumpAsText();
211 layoutTestController
.waitUntilDone();
215 throw("Expected results are missing!");
217 window
.addEventListener("load", function() { startTest(expected
, usePauseAPI
, callback
); }, false);