|
1 <!DOCTYPE HTML> |
|
2 <html> |
|
3 <!-- |
|
4 https://bugzilla.mozilla.org/show_bug.cgi?id=435441 |
|
5 --> |
|
6 <head> |
|
7 <title>Test for Bug 435441</title> |
|
8 <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
|
9 <script type="text/javascript" src="property_database.js"></script> |
|
10 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> |
|
11 <style type="text/css"> |
|
12 |
|
13 #display > p { margin-top: 0; margin-bottom: 0; } |
|
14 |
|
15 </style> |
|
16 </head> |
|
17 <body> |
|
18 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435441">Mozilla Bug 435441</a> |
|
19 |
|
20 <!-- |
|
21 fixed-height container so percentage heights compute to different |
|
22 (i.e., nonzero) values |
|
23 fixed-width container so that percentages for margin-top and |
|
24 margin-bottom are all relative to the same size container (rather than |
|
25 one that depends on whether we're tall enough to need a scrollbar) |
|
26 |
|
27 Use a 20px font size and line-height so that percentage line-height |
|
28 and vertical-align doesn't accumulate rounding error. |
|
29 --> |
|
30 <div style="height: 50px; width: 300px; font-size: 20px; line-height: 20px"> |
|
31 |
|
32 <div id="display"> |
|
33 </div> |
|
34 |
|
35 <div id="transformTest" style="height:100px; width:200px; background-color:blue;"> |
|
36 </div> |
|
37 |
|
38 </div> |
|
39 <pre id="test"> |
|
40 <script type="application/javascript"> |
|
41 |
|
42 /** Test for Bug 435441 **/ |
|
43 |
|
44 SimpleTest.requestLongerTimeout(2); |
|
45 SimpleTest.waitForExplicitFinish(); |
|
46 |
|
47 function has_num(str) |
|
48 { |
|
49 return !!String(str).match(/^([\d.]+)/); |
|
50 } |
|
51 |
|
52 function any_unit_to_num(str) |
|
53 { |
|
54 return Number(String(str).match(/^([\d.]+)/)[1]); |
|
55 } |
|
56 |
|
57 var FUNC_NEGATIVE = "cubic-bezier(0.25, -2, 0.75, 1)"; |
|
58 var FUNC_OVERONE = "cubic-bezier(0.25, 0, 0.75, 3)"; |
|
59 |
|
60 var supported_properties = { |
|
61 "border-bottom-left-radius": [ test_radius_transition ], |
|
62 "border-bottom-right-radius": [ test_radius_transition ], |
|
63 "border-top-left-radius": [ test_radius_transition ], |
|
64 "border-top-right-radius": [ test_radius_transition ], |
|
65 "-moz-box-flex": [ test_float_zeroToOne_transition, |
|
66 test_float_aboveOne_transition, |
|
67 test_float_zeroToOne_clamped ], |
|
68 "box-shadow": [ test_shadow_transition ], |
|
69 "-moz-column-count": [ test_pos_integer_or_auto_transition, |
|
70 test_integer_at_least_one_clamping ], |
|
71 "-moz-column-gap": [ test_length_transition, |
|
72 test_length_clamped ], |
|
73 "-moz-column-rule-color": [ test_color_transition, |
|
74 test_border_color_transition ], |
|
75 "-moz-column-rule-width": [ test_length_transition, |
|
76 test_length_clamped ], |
|
77 "-moz-column-width": [ test_length_transition, |
|
78 test_length_clamped ], |
|
79 "-moz-image-region": [ test_rect_transition ], |
|
80 "-moz-outline-radius-bottomleft": [ test_radius_transition ], |
|
81 "-moz-outline-radius-bottomright": [ test_radius_transition ], |
|
82 "-moz-outline-radius-topleft": [ test_radius_transition ], |
|
83 "-moz-outline-radius-topright": [ test_radius_transition ], |
|
84 "-moz-text-decoration-color": [ test_color_transition, |
|
85 test_border_color_transition ], |
|
86 "background-color": [ test_color_transition ], |
|
87 "background-position": [ test_background_position_transition, |
|
88 // FIXME: We don't currently test clamping, |
|
89 // since background-position uses calc() as |
|
90 // an intermediate form. |
|
91 /* test_length_percent_pair_unclamped */ ], |
|
92 "background-size": [ test_background_size_transition, |
|
93 // FIXME: We don't currently test clamping, |
|
94 // since background-size uses calc() as an |
|
95 // intermediate form. |
|
96 /* test_length_percent_pair_clamped */ ], |
|
97 "border-bottom-color": [ test_color_transition, |
|
98 test_border_color_transition ], |
|
99 "border-bottom-width": [ test_length_transition, |
|
100 test_length_clamped ], |
|
101 "border-left-color": [ test_color_transition, |
|
102 test_border_color_transition ], |
|
103 "border-left-width": [ test_length_transition, |
|
104 test_length_clamped ], |
|
105 "border-right-color": [ test_color_transition, |
|
106 test_border_color_transition ], |
|
107 "border-right-width": [ test_length_transition, |
|
108 test_length_clamped ], |
|
109 "border-spacing": [ test_length_pair_transition, |
|
110 test_length_pair_transition_clamped ], |
|
111 "border-top-color": [ test_color_transition, |
|
112 test_border_color_transition ], |
|
113 "border-top-width": [ test_length_transition, |
|
114 test_length_clamped ], |
|
115 "bottom": [ test_length_transition, test_percent_transition, |
|
116 test_length_percent_calc_transition, |
|
117 test_length_unclamped, test_percent_unclamped ], |
|
118 "clip": [ test_rect_transition ], |
|
119 "color": [ test_color_transition ], |
|
120 "fill": [ test_color_transition ], |
|
121 "fill-opacity" : [ test_float_zeroToOne_transition, |
|
122 // opacity is clamped in computed style |
|
123 // (not parsing/interpolation) |
|
124 test_float_zeroToOne_clamped ], |
|
125 "filter" : [ test_filter_transition ], |
|
126 "flex-basis": [ test_length_transition, test_percent_transition, |
|
127 test_length_clamped, test_percent_clamped ], |
|
128 "flex-grow": [ test_float_zeroToOne_transition, |
|
129 test_float_aboveOne_transition ], |
|
130 "flex-shrink": [ test_float_zeroToOne_transition, |
|
131 test_float_aboveOne_transition ], |
|
132 "flood-color": [ test_color_transition ], |
|
133 "flood-opacity" : [ test_float_zeroToOne_transition, |
|
134 // opacity is clamped in computed style |
|
135 // (not parsing/interpolation) |
|
136 test_float_zeroToOne_clamped ], |
|
137 "font-size": [ test_length_transition, test_percent_transition, |
|
138 test_length_percent_calc_transition, |
|
139 test_length_clamped, test_percent_clamped ], |
|
140 "font-size-adjust": [ test_float_zeroToOne_transition, |
|
141 test_float_aboveOne_transition, |
|
142 /* FIXME: font-size-adjust treats zero specially */ |
|
143 /* test_float_zeroToOne_clamped */ ], |
|
144 "font-stretch": [ test_font_stretch ], |
|
145 "font-weight": [ test_font_weight ], |
|
146 "height": [ test_length_transition, test_percent_transition, |
|
147 test_length_percent_calc_transition, |
|
148 test_length_clamped, test_percent_clamped ], |
|
149 "left": [ test_length_transition, test_percent_transition, |
|
150 test_length_percent_calc_transition, |
|
151 test_length_unclamped, test_percent_unclamped ], |
|
152 "letter-spacing": [ test_length_transition, test_length_unclamped ], |
|
153 "lighting-color": [ test_color_transition ], |
|
154 // NOTE: when calc() is supported on 'line-height', we should add |
|
155 // test_length_percent_calc_transition. |
|
156 "line-height": [ test_length_transition, test_percent_transition, |
|
157 test_length_clamped, test_percent_clamped ], |
|
158 "margin-bottom": [ test_length_transition, test_percent_transition, |
|
159 test_length_percent_calc_transition, |
|
160 test_length_unclamped, test_percent_unclamped ], |
|
161 "margin-left": [ test_length_transition, test_percent_transition, |
|
162 test_length_percent_calc_transition, |
|
163 test_length_unclamped, test_percent_unclamped ], |
|
164 "margin-right": [ test_length_transition, test_percent_transition, |
|
165 test_length_percent_calc_transition, |
|
166 test_length_unclamped, test_percent_unclamped ], |
|
167 "margin-top": [ test_length_transition, test_percent_transition, |
|
168 test_length_percent_calc_transition, |
|
169 test_length_unclamped, test_percent_unclamped ], |
|
170 "marker-offset": [ test_length_transition, |
|
171 test_length_unclamped ], |
|
172 "max-height": [ test_length_transition, test_percent_transition, |
|
173 test_length_percent_calc_transition, |
|
174 test_length_clamped, test_percent_clamped ], |
|
175 "max-width": [ test_length_transition, test_percent_transition, |
|
176 test_length_percent_calc_transition, |
|
177 test_length_clamped, test_percent_clamped ], |
|
178 "min-height": [ test_length_transition, test_percent_transition, |
|
179 test_length_percent_calc_transition, |
|
180 test_length_clamped, test_percent_clamped ], |
|
181 "min-width": [ test_length_transition, test_percent_transition, |
|
182 test_length_percent_calc_transition, |
|
183 test_length_clamped, test_percent_clamped ], |
|
184 "opacity" : [ test_float_zeroToOne_transition, |
|
185 // opacity is clamped in computed style |
|
186 // (not parsing/interpolation) |
|
187 test_float_zeroToOne_clamped ], |
|
188 "order": [ test_integer_transition ], |
|
189 "outline-color": [ test_color_transition ], |
|
190 "outline-offset": [ test_length_transition, test_length_unclamped ], |
|
191 "outline-width": [ test_length_transition, test_length_clamped ], |
|
192 "padding-bottom": [ test_length_transition, test_percent_transition, |
|
193 test_length_percent_calc_transition, |
|
194 test_length_clamped, test_percent_clamped ], |
|
195 "padding-left": [ test_length_transition, test_percent_transition, |
|
196 test_length_percent_calc_transition, |
|
197 test_length_clamped, test_percent_clamped ], |
|
198 "padding-right": [ test_length_transition, test_percent_transition, |
|
199 test_length_percent_calc_transition, |
|
200 test_length_clamped, test_percent_clamped ], |
|
201 "padding-top": [ test_length_transition, test_percent_transition, |
|
202 test_length_percent_calc_transition, |
|
203 test_length_clamped, test_percent_clamped ], |
|
204 "perspective": [ test_length_transition ], |
|
205 "perspective-origin": [ test_length_pair_transition, |
|
206 test_length_percent_pair_transition, |
|
207 test_length_percent_pair_unclamped ], |
|
208 "right": [ test_length_transition, test_percent_transition, |
|
209 test_length_percent_calc_transition, |
|
210 test_length_unclamped, test_percent_unclamped ], |
|
211 "stop-color": [ test_color_transition ], |
|
212 "stop-opacity" : [ test_float_zeroToOne_transition, |
|
213 // opacity is clamped in computed style |
|
214 // (not parsing/interpolation) |
|
215 test_float_zeroToOne_clamped ], |
|
216 "stroke": [ test_color_transition ], |
|
217 "stroke-dasharray": [ test_dasharray_transition ], |
|
218 // NOTE: when calc() is supported on 'stroke-dashoffset', we should |
|
219 // add test_length_percent_calc_transition. |
|
220 "stroke-dashoffset": [ test_length_transition, test_percent_transition, |
|
221 test_length_unclamped, test_percent_unclamped ], |
|
222 "stroke-miterlimit": [ test_float_aboveOne_transition, |
|
223 test_float_aboveOne_clamped ], |
|
224 "stroke-opacity" : [ test_float_zeroToOne_transition, |
|
225 // opacity is clamped in computed style |
|
226 // (not parsing/interpolation) |
|
227 test_float_zeroToOne_clamped ], |
|
228 // NOTE: when calc() is supported on 'stroke-width', we should add |
|
229 // test_length_percent_calc_transition. |
|
230 "stroke-width": [ test_length_transition, test_percent_transition, |
|
231 test_length_clamped, test_percent_clamped ], |
|
232 "text-indent": [ test_length_transition, test_percent_transition, |
|
233 test_length_percent_calc_transition, |
|
234 test_length_unclamped, test_percent_unclamped ], |
|
235 "text-shadow": [ test_shadow_transition ], |
|
236 "top": [ test_length_transition, test_percent_transition, |
|
237 test_length_percent_calc_transition, |
|
238 test_length_unclamped, test_percent_unclamped ], |
|
239 "transform": [ test_transform_transition ], |
|
240 "transform-origin": [ test_length_pair_transition, |
|
241 test_length_percent_pair_transition, |
|
242 test_length_percent_pair_unclamped ], |
|
243 "vertical-align": [ test_length_transition, test_percent_transition, |
|
244 test_length_percent_calc_transition, |
|
245 test_length_unclamped, test_percent_unclamped ], |
|
246 "visibility": [ test_visibility_transition ], |
|
247 "width": [ test_length_transition, test_percent_transition, |
|
248 test_length_percent_calc_transition, |
|
249 test_length_clamped, test_percent_clamped ], |
|
250 "word-spacing": [ test_length_transition, test_length_unclamped ], |
|
251 "z-index": [ test_integer_transition, test_pos_integer_or_auto_transition ], |
|
252 }; |
|
253 |
|
254 var div = document.getElementById("display"); |
|
255 var OMTAdiv = document.getElementById("transformTest"); |
|
256 var cs = getComputedStyle(div, ""); |
|
257 var OMTACs = getComputedStyle(OMTAdiv, ""); |
|
258 var winUtils = SpecialPowers.getDOMWindowUtils(window); |
|
259 |
|
260 function computeMatrix(v) { |
|
261 div.style.setProperty("transform", v, ""); |
|
262 var result = cs.getPropertyValue("transform"); |
|
263 div.style.removeProperty("transform"); |
|
264 return result; |
|
265 } |
|
266 var c_rot_15 = computeMatrix("rotate(15deg)"); |
|
267 is(c_rot_15.substring(0,6), "matrix", "should compute to matrix value"); |
|
268 var c_rot_60 = computeMatrix("rotate(60deg)"); |
|
269 is(c_rot_60.substring(0,6), "matrix", "should compute to matrix value"); |
|
270 |
|
271 var transformTestIndex = 0; |
|
272 var transformTests = [ |
|
273 // rotate |
|
274 { start: 'none', end: 'rotate(60deg)', |
|
275 expected_uncomputed: 'rotate(15deg)', |
|
276 expected: c_rot_15 }, |
|
277 { start: 'rotate(0)', end: 'rotate(60deg)', |
|
278 expected_uncomputed: 'rotate(15deg)', |
|
279 expected: c_rot_15 }, |
|
280 { start: 'rotate(0deg)', end: 'rotate(60deg)', |
|
281 expected_uncomputed: 'rotate(15deg)', |
|
282 expected: c_rot_15 }, |
|
283 { start: 'none', end: c_rot_60, |
|
284 expected: c_rot_15 }, |
|
285 { start: 'none', end: 'rotate(360deg)', |
|
286 expected_uncomputed: 'rotate(90deg)', |
|
287 expected: computeMatrix('rotate(90deg)') }, |
|
288 { start: 'none', end: 'rotatez(360deg)', |
|
289 expected_uncomputed: 'rotate(90deg)', |
|
290 expected: computeMatrix('rotate(90deg)') }, |
|
291 { start: 'none', end: 'rotate(720deg)', |
|
292 expected_uncomputed: 'rotate(180deg)', |
|
293 expected: computeMatrix('rotate(180deg)') }, |
|
294 { start: 'none', end: 'rotate(720deg)', |
|
295 expected_uncomputed: 'rotatez(180deg)', |
|
296 expected: computeMatrix('rotate(180deg)') }, |
|
297 { start: 'none', end: 'rotate(1080deg)', |
|
298 expected_uncomputed: 'rotate(270deg)', |
|
299 expected: computeMatrix('rotate(270deg)') }, |
|
300 { start: 'none', end: 'rotate(1080deg)', |
|
301 expected_uncomputed: 'rotate(270deg)', |
|
302 expected: computeMatrix('rotatez(270deg)') }, |
|
303 { start: 'none', end: 'rotate(1440deg)', |
|
304 expected_uncomputed: 'rotate(360deg)', |
|
305 expected: computeMatrix('scale(1)'), |
|
306 round_error_ok: true }, |
|
307 { start: 'none', end: 'rotatey(60deg)', |
|
308 expected_uncomputed: 'rotatey(15deg)', |
|
309 expected: computeMatrix('rotatey(15deg)') }, |
|
310 { start: 'none', end: 'rotatey(720deg)', |
|
311 expected_uncomputed: 'rotatey(180deg)', |
|
312 expected: computeMatrix('rotatey(180deg)') }, |
|
313 { start: 'none', end: 'rotatex(60deg)', |
|
314 expected_uncomputed: 'rotatex(15deg)', |
|
315 expected: computeMatrix('rotatex(15deg)') }, |
|
316 { start: 'none', end: 'rotatex(720deg)', |
|
317 expected_uncomputed: 'rotatex(180deg)', |
|
318 expected: computeMatrix('rotatex(180deg)') }, |
|
319 |
|
320 // translate |
|
321 { start: 'translate(20px)', end: 'none', |
|
322 expected_uncomputed: 'translate(15px)', |
|
323 expected: 'matrix(1, 0, 0, 1, 15, 0)' }, |
|
324 { start: 'translate(20px, 12px)', end: 'none', |
|
325 expected_uncomputed: 'translate(15px, 9px)', |
|
326 expected: 'matrix(1, 0, 0, 1, 15, 9)' }, |
|
327 { start: 'translateX(-20px)', end: 'none', |
|
328 expected_uncomputed: 'translateX(-15px)', |
|
329 expected: 'matrix(1, 0, 0, 1, -15, 0)' }, |
|
330 { start: 'translateY(-40px)', end: 'none', |
|
331 expected_uncomputed: 'translateY(-30px)', |
|
332 expected: 'matrix(1, 0, 0, 1, 0, -30)' }, |
|
333 { start: 'translateZ(40px)', end: 'none', |
|
334 expected_uncomputed: 'translateZ(30px)', |
|
335 expected: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 30, 1)' }, |
|
336 { start: 'none', end: 'translate3D(40px, 60px, -40px)', |
|
337 expected_uncomputed: 'translate3D(10px, 15px, -10px)', |
|
338 expected: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10, 15, -10, 1)' }, |
|
339 // percentages are relative to 300px (width) and 50px (height) |
|
340 // per the prerequisites in property_database.js |
|
341 { start: 'translate(20%)', end: 'none', |
|
342 expected_uncomputed: 'translate(15%)', |
|
343 expected: 'matrix(1, 0, 0, 1, 45, 0)', |
|
344 round_error_ok: true }, |
|
345 { start: 'translate(20%, 12%)', end: 'none', |
|
346 expected_uncomputed: 'translate(15%, 9%)', |
|
347 expected: 'matrix(1, 0, 0, 1, 45, 4.5)', |
|
348 round_error_ok: true }, |
|
349 { start: 'translateX(-20%)', end: 'none', |
|
350 expected_uncomputed: 'translateX(-15%)', |
|
351 expected: 'matrix(1, 0, 0, 1, -45, 0)', |
|
352 round_error_ok: true }, |
|
353 { start: 'translateY(-40%)', end: 'none', |
|
354 expected_uncomputed: 'translateY(-30%)', |
|
355 expected: 'matrix(1, 0, 0, 1, 0, -15)', |
|
356 round_error_ok: true, |
|
357 big_omta_round_error: true }, |
|
358 { start: 'none', end: 'rotate(90deg) translate(20%, 20%) rotate(-90deg)', |
|
359 expected_uncomputed: 'rotate(22.5deg) translate(5%, 5%) rotate(-22.5deg)', |
|
360 round_error_ok: true }, |
|
361 { start: 'none', end: 'rotate(-90deg) translate(20%, 20%) rotate(90deg)', |
|
362 expected_uncomputed: 'rotate(-22.5deg) translate(5%, 5%) rotate(22.5deg)', |
|
363 round_error_ok: true }, |
|
364 // test percent translation using matrix decomposition |
|
365 { start: 'rotate(45deg) rotate(-45deg)', |
|
366 end: 'rotate(90deg) translate(20%, 20%) rotate(-90deg)', |
|
367 expected: 'matrix(1, 0, 0, 1, -2.5, 15)', |
|
368 round_error_ok: true }, |
|
369 { start: 'rotate(45deg) rotate(-45deg)', |
|
370 end: 'rotate(-90deg) translate(20%, 20%) rotate(90deg)', |
|
371 expected: 'matrix(1, 0, 0, 1, 2.5, -15)', |
|
372 round_error_ok: true }, |
|
373 // test calc() in translate |
|
374 // Note that font-size: is 20px, and that percentages are relative |
|
375 // to 300px (width) and 50px (height) per the prerequisites in |
|
376 // property_database.js |
|
377 { start: 'translateX(20%)', /* 60px */ |
|
378 end: 'translateX(calc(10% + 1em))', /* 30px + 20px = 50px */ |
|
379 expected_uncomputed: 'translateX(calc(17.5% + 0.25em))', |
|
380 expected: 'matrix(1, 0, 0, 1, 57.5, 0)', |
|
381 big_omta_round_error: true }, |
|
382 { start: 'translate(calc(0.75 * 3em + 1.5 * 10%), calc(0.5 * 5em + 0.5 * 8%))', /* 90px, 52px */ |
|
383 end: 'rotate(90deg) translateY(20%) rotate(90deg) translateY(calc(10% + 0.5em)) rotate(180deg)', /* -10px, -15px */ |
|
384 expected: 'matrix(1, 0, 0, 1, 65, 35.25)', |
|
385 big_omta_round_error: true }, |
|
386 |
|
387 // scale |
|
388 { start: 'scale(2)', end: 'none', |
|
389 expected_uncomputed: 'scale(1.75)', |
|
390 expected: 'matrix(1.75, 0, 0, 1.75, 0, 0)' }, |
|
391 { start: 'none', end: 'scale(0.4)', |
|
392 expected_uncomputed: 'scale(0.85)', |
|
393 expected: 'matrix(0.85, 0, 0, 0.85, 0, 0)', |
|
394 round_error_ok: true }, |
|
395 { start: 'scale(2)', end: 'scale(-2)', |
|
396 expected_uncomputed: 'scale(1)', |
|
397 expected: 'matrix(1, 0, 0, 1, 0, 0)' }, |
|
398 { start: 'scale(2)', end: 'scale(-6)', |
|
399 expected_uncomputed: 'scale(0)', |
|
400 expected: 'matrix(0, 0, 0, 0, 0, 0)' }, |
|
401 { start: 'scale(2, 0.4)', end: 'none', |
|
402 expected_uncomputed: 'scale(1.75, 0.55)', |
|
403 expected: 'matrix(1.75, 0, 0, 0.55, 0, 0)', |
|
404 round_error_ok: true }, |
|
405 { start: 'scaleX(3)', end: 'none', |
|
406 expected_uncomputed: 'scaleX(2.5)', |
|
407 expected: 'matrix(2.5, 0, 0, 1, 0, 0)' }, |
|
408 { start: 'scaleY(5)', end: 'none', |
|
409 expected_uncomputed: 'scaleY(4)', |
|
410 expected: 'matrix(1, 0, 0, 4, 0, 0)' }, |
|
411 { start: 'scaleZ(5)', end: 'none', |
|
412 expected_uncomputed: 'scaleZ(4)', |
|
413 expected: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1)' }, |
|
414 { start: 'none', end: 'scale3D(5, 5, 5)', |
|
415 expected_uncomputed: 'scale3D(2, 2, 2)', |
|
416 expected: 'matrix3d(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1)' }, |
|
417 |
|
418 // skew |
|
419 { start: 'skewX(45deg)', end: 'none', |
|
420 expected_uncomputed: 'skewX(33.75deg)' }, |
|
421 { start: 'skewY(45deg)', end: 'none', |
|
422 expected_uncomputed: 'skewY(33.75deg)' }, |
|
423 { start: 'skew(45deg)', end: 'none', |
|
424 expected_uncomputed: 'skew(33.75deg)' }, |
|
425 { start: 'skew(45deg, 45deg)', end: 'none', |
|
426 expected_uncomputed: 'skew(33.75deg, 33.75deg)' }, |
|
427 { start: 'skewX(45deg)', end: 'skewX(-45deg)', |
|
428 expected_uncomputed: 'skewX(22.5deg)' }, |
|
429 { start: 'skewX(0)', end: 'skewX(-45deg)', |
|
430 expected_uncomputed: 'skewX(-11.25deg)' }, |
|
431 { start: 'skewY(45deg)', end: 'skewY(-45deg)', |
|
432 expected_uncomputed: 'skewY(22.5deg)' }, |
|
433 |
|
434 // matrix : skewX |
|
435 { start: 'matrix(1, 0, 3, 1, 0, 0)', end: 'none', |
|
436 expected: 'matrix(1, 0, ' + 3 * 0.75 + ', 1, 0, 0)', |
|
437 round_error_ok: true }, |
|
438 { start: 'skewX(0)', end: 'skewX(-45deg) translate(0)', |
|
439 expected: 'matrix(1, 0, -0.25, 1, 0, 0)', |
|
440 round_error_ok: true }, |
|
441 // matrix : rotate |
|
442 { start: 'rotate(-30deg)', end: 'matrix(0, 1, -1, 0, 0, 0)', |
|
443 expected: 'matrix(1, 0, 0, 1, 0, 0)', |
|
444 round_error_ok: true }, |
|
445 { start: 'rotate(-30deg) translateX(0)', |
|
446 end: 'translateX(0) rotate(-90deg)', |
|
447 expected: computeMatrix('rotate(-45deg)'), |
|
448 round_error_ok: true }, |
|
449 // matrix decomposition of skewY |
|
450 { start: 'skewY(60deg)', end: 'skewY(-60deg) translateX(0)', |
|
451 /* rotate(30deg) skewX(60deg)/2 scale(2, 0.5) */ |
|
452 expected: computeMatrix('rotate(30deg) skewX(' + Math.atan(Math.tan(Math.PI * 60/180) / 2) + 'rad) scale(2, 0.5)'), |
|
453 round_error_ok: true }, |
|
454 |
|
455 // matrix decomposition |
|
456 |
|
457 // Four pairs of the same matrix expressed different ways. |
|
458 { start: 'matrix(-1, 0, 0, -1, 0, 0)', /* rotate(180deg) */ |
|
459 end: 'matrix(1, 0, 0, 1, 0, 0)', |
|
460 expected: computeMatrix('rotate(135deg)') }, |
|
461 { start: 'scale(-1)', end: 'none', |
|
462 expected_uncomputed: 'scale(-0.5)', |
|
463 expected: 'matrix(-0.5, 0, 0, -0.5, 0, 0)' }, |
|
464 { start: 'rotate(180deg)', end: 'none', |
|
465 expected_uncomputed: 'rotate(135deg)' }, |
|
466 { start: 'rotate(-180deg)', end: 'none', |
|
467 expected_uncomputed: 'rotate(-135deg)', |
|
468 expected: computeMatrix('rotate(225deg)') }, |
|
469 |
|
470 // matrix followed by scale |
|
471 { start: 'matrix(2, 0, 0, 2, 10, 20) scale(2)', |
|
472 end: 'none', |
|
473 expected: 'matrix(3.0625, 0, 0, 3.0625, 7.5, 15)' }, |
|
474 |
|
475 // ... and a bunch of similar possibilities. The spec isn't settled |
|
476 // here; there are multiple options. See: |
|
477 // http://lists.w3.org/Archives/Public/www-style/2010Jun/0602.html |
|
478 { start: 'matrix(-1, 0, 0, 1, 0, 0)', /* scaleX(-1) */ |
|
479 end: 'matrix(1, 0, 0, 1, 0, 0)', |
|
480 expected: computeMatrix('scaleX(-0.5)') }, |
|
481 |
|
482 { start: 'matrix(1, 0, 0, -1, 0, 0)', /* rotate(-180deg) scaleX(-1) */ |
|
483 end: 'matrix(1, 0, 0, 1, 0, 0)', |
|
484 expected: computeMatrix('rotate(-135deg) scaleX(-0.5)') }, |
|
485 |
|
486 { start: 'matrix(0, 1, 1, 0, 0, 0)', /* rotate(-90deg) scaleX(-1) */ |
|
487 end: 'matrix(1, 0, 0, 1, 0, 0)', |
|
488 expected: computeMatrix('rotate(-67.5deg) scaleX(-0.5)') }, |
|
489 |
|
490 { start: 'matrix(0, -1, 1, 0, 0, 0)', /* rotate(-90deg) */ |
|
491 end: 'matrix(1, 0, 0, 1, 0, 0)', |
|
492 expected: computeMatrix('rotate(-67.5deg)') }, |
|
493 |
|
494 { start: 'matrix(0, 1, -1, 0, 0, 0)', /* rotate(90deg) */ |
|
495 end: 'matrix(1, 0, 0, 1, 0, 0)', |
|
496 expected: computeMatrix('rotate(67.5deg)') }, |
|
497 |
|
498 { start: 'matrix(0, -1, -1, 0, 0, 0)', /* rotate(90deg) scaleX(-1) */ |
|
499 end: 'matrix(1, 0, 0, 1, 0, 0)', |
|
500 expected: computeMatrix('rotate(67.5deg) scaleX(-0.5)') }, |
|
501 |
|
502 // Similar decomposition tests, but with skewX. I checked visually |
|
503 // that the sign of the skew was correct by checking visually that |
|
504 // the animations in |
|
505 // http://dbaron.org/css/test/2010/transition-negative-determinant |
|
506 // don't flip when they finish, and then wrote tests corresponding |
|
507 // to the current code's behavior. |
|
508 // ... start with four with positive determinants |
|
509 { start: 'none', |
|
510 end: 'matrix(1, 0, 1.5, 1, 0, 0)', |
|
511 /* skewX(atan(1.5)) */ |
|
512 expected: 'matrix(1, 0, ' + 1.5 * 0.25 + ', 1, 0, 0)', |
|
513 round_error_ok: true }, |
|
514 { start: 'none', |
|
515 end: 'matrix(-1, 0, 2, -1, 0, 0)', |
|
516 /* rotate(180deg) skewX(atan(-2)) */ |
|
517 expected: computeMatrix('rotate(45deg) matrix(1, 0, ' + -2 * 0.25 + ', 1, 0, 0)'), |
|
518 round_error_ok: true }, |
|
519 { start: 'none', |
|
520 end: 'matrix(0, -1, 1, -3, 0, 0)', |
|
521 /* rotate(-90deg) skewX(atan(3)) */ |
|
522 expected: computeMatrix('rotate(-22.5deg) matrix(1, 0, ' + 3 * 0.25 + ', 1, 0, 0)'), |
|
523 round_error_ok: true }, |
|
524 { start: 'none', |
|
525 end: 'matrix(0, 1, -1, 4, 0, 0)', |
|
526 /* rotate(90deg) skewX(atan(4)) */ |
|
527 expected: computeMatrix('rotate(22.5deg) matrix(1, 0, ' + 4 * 0.25 + ', 1, 0, 0)'), |
|
528 round_error_ok: true }, |
|
529 // and then four with negative determinants |
|
530 { start: 'none', |
|
531 end: 'matrix(1, 0, 1, -1, 0, 0)', |
|
532 /* rotate(-180deg) skewX(atan(-1)) scaleX(-1) */ |
|
533 expected: computeMatrix('rotate(-45deg) matrix(1, 0, ' + -1 * 0.25 + ', 1, 0, 0) scaleX(0.5)'), |
|
534 round_error_ok: true }, |
|
535 { start: 'none', |
|
536 end: 'matrix(-1, 0, -1, 1, 0, 0)', |
|
537 /* skewX(atan(-1)) scaleX(-1) */ |
|
538 expected: computeMatrix('matrix(1, 0, ' + -1 * 0.25 + ', 1, 0, 0) scaleX(0.5)') }, |
|
539 { start: 'none', |
|
540 end: 'matrix(0, 1, 1, -2, 0, 0)', |
|
541 /* rotate(-90deg) skewX(atan(2)) scaleX(-1) */ |
|
542 expected: computeMatrix('rotate(-22.5deg) matrix(1, 0, ' + 2 * 0.25 + ', 1, 0, 0) scaleX(0.5)'), |
|
543 round_error_ok: true }, |
|
544 { start: 'none', |
|
545 end: 'matrix(0, -1, -1, 0.5, 0, 0)', |
|
546 /* rotate(90deg) skewX(atan(0.5)) scaleX(-1) */ |
|
547 expected: computeMatrix('rotate(22.5deg) matrix(1, 0, ' + 0.5 * 0.25 + ', 1, 0, 0) scaleX(0.5)'), |
|
548 round_error_ok: true }, |
|
549 |
|
550 // lists vs. matrix decomposition |
|
551 { start: 'translate(10px) skewY(45deg)', |
|
552 end: 'translate(30px) skewY(-45deg)', |
|
553 expected_uncomputed: 'translate(15px) skewY(22.5deg)' }, |
|
554 { start: 'skewY(45deg) rotate(90deg)', |
|
555 end: 'skewY(-45deg) rotate(90deg)', |
|
556 expected_uncomputed: 'skewY(22.5deg) rotate(90deg)' }, |
|
557 { start: 'skewY(45deg) rotate(90deg) translate(0)', |
|
558 end: 'skewY(-45deg) rotate(90deg)', |
|
559 expected: 'matrix(0, 1, -1, -0.5, 0, 0)', |
|
560 round_error_ok: true }, |
|
561 { start: 'skewX(45deg) rotate(90deg)', |
|
562 end: 'skewX(-45deg) rotate(90deg)', |
|
563 expected_uncomputed: 'skewX(22.5deg) rotate(90deg)' }, |
|
564 { start: 'skewX(-60deg) rotate(90deg) translate(0)', |
|
565 end: 'skewX(60deg) rotate(90deg)', |
|
566 expected: computeMatrix('rotate(120deg) skewX(' + Math.atan(Math.tan(Math.PI * 60/180) / 2) + 'rad) scale(2, 0.5)'), |
|
567 round_error_ok: true }, |
|
568 ]; |
|
569 |
|
570 var filterTests = [ |
|
571 { start: "none", end: "none", |
|
572 expected: ["none"] }, |
|
573 // function from none (number/length) |
|
574 { start: "none", end: "brightness(0.5)", |
|
575 expected: ["brightness", 0.875] }, |
|
576 { start: "none", end: "contrast(0.5)", |
|
577 expected: ["contrast", 0.875] }, |
|
578 { start: "none", end: "grayscale(0.5)", |
|
579 expected: ["grayscale", 0.125] }, |
|
580 { start: "none", end: "invert(0.5)", |
|
581 expected: ["invert", 0.125] }, |
|
582 { start: "none", end: "opacity(0.5)", |
|
583 expected: ["opacity", 0.875] }, |
|
584 { start: "none", end: "saturate(0.5)", |
|
585 expected: ["saturate", 0.875] }, |
|
586 { start: "none", end: "sepia(0.5)", |
|
587 expected: ["sepia", 0.125] }, |
|
588 { start: "none", end: "blur(50px)", |
|
589 expected: ["blur", 12.5] }, |
|
590 // function to none (number/length) |
|
591 { start: "brightness(0.5)", end: "none", |
|
592 expected: ["brightness", 0.625] }, |
|
593 { start: "contrast(0.5)", end: "none", |
|
594 expected: ["contrast", 0.625] }, |
|
595 { start: "grayscale(0.5)", end: "none", |
|
596 expected: ["grayscale", 0.375] }, |
|
597 { start: "invert(0.5)", end: "none", |
|
598 expected: ["invert", 0.375] }, |
|
599 { start: "opacity(0.5)", end: "none", |
|
600 expected: ["opacity", 0.625] }, |
|
601 { start: "saturate(0.5)", end: "none", |
|
602 expected: ["saturate", 0.625] }, |
|
603 { start: "sepia(0.5)", end: "none", |
|
604 expected: ["sepia", 0.375] }, |
|
605 { start: "blur(50px)", end: "none", |
|
606 expected: ["blur", 37.5] }, |
|
607 // function to same function (number/length) |
|
608 { start: "brightness(0.25)", end: "brightness(0.75)", |
|
609 expected: ["brightness", 0.375] }, |
|
610 { start: "contrast(0.25)", end: "contrast(0.75)", |
|
611 expected: ["contrast", 0.375] }, |
|
612 { start: "grayscale(0.25)", end: "grayscale(0.75)", |
|
613 expected: ["grayscale", 0.375] }, |
|
614 { start: "invert(0.25)", end: "invert(0.75)", |
|
615 expected: ["invert", 0.375] }, |
|
616 { start: "opacity(0.25)", end: "opacity(0.75)", |
|
617 expected: ["opacity", 0.375] }, |
|
618 { start: "saturate(0.25)", end: "saturate(0.75)", |
|
619 expected: ["saturate", 0.375] }, |
|
620 { start: "sepia(0.25)", end: "sepia(0.75)", |
|
621 expected: ["sepia", 0.375] }, |
|
622 { start: "blur(25px)", end: "blur(75px)", |
|
623 expected: ["blur", 37.5] }, |
|
624 // function to same function (percent) |
|
625 { start: "brightness(25%)", end: "brightness(75%)", |
|
626 expected: ["brightness", 0.375] }, |
|
627 { start: "contrast(25%)", end: "contrast(75%)", |
|
628 expected: ["contrast", 0.375] }, |
|
629 { start: "grayscale(25%)", end: "grayscale(75%)", |
|
630 expected: ["grayscale", 0.375] }, |
|
631 { start: "invert(25%)", end: "invert(75%)", |
|
632 expected: ["invert", 0.375] }, |
|
633 { start: "opacity(25%)", end: "opacity(75%)", |
|
634 expected: ["opacity", 0.375] }, |
|
635 { start: "saturate(25%)", end: "saturate(75%)", |
|
636 expected: ["saturate", 0.375] }, |
|
637 { start: "sepia(25%)", end: "sepia(75%)", |
|
638 expected: ["sepia", 0.375] }, |
|
639 // function to same function (percent, number/length) |
|
640 { start: "brightness(0.25)", end: "brightness(75%)", |
|
641 expected: ["brightness", 0.375] }, |
|
642 { start: "contrast(25%)", end: "contrast(0.75)", |
|
643 expected: ["contrast", 0.375] }, |
|
644 // hue-rotate with different angle values |
|
645 { start: "hue-rotate(0deg)", end: "hue-rotate(720deg)", |
|
646 expected: ["hue-rotate", Math.PI.toFixed(5)] }, |
|
647 { start: "hue-rotate(0rad)", end: "hue-rotate("+4*Math.PI+"rad)", |
|
648 expected: ["hue-rotate", Math.PI.toFixed(5)] }, |
|
649 { start: "hue-rotate(0grad)", end: "hue-rotate(800grad)", |
|
650 expected: ["hue-rotate", Math.PI.toFixed(5)] }, |
|
651 { start: "hue-rotate(0turn)", end: "hue-rotate(2turn)", |
|
652 expected: ["hue-rotate", Math.PI.toFixed(5)] }, |
|
653 { start: "hue-rotate(0deg)", end: "hue-rotate("+4*Math.PI+"rad)", |
|
654 expected: ["hue-rotate", Math.PI.toFixed(5)] }, |
|
655 { start: "hue-rotate(0turn)", end: "hue-rotate(800grad)", |
|
656 expected: ["hue-rotate", Math.PI.toFixed(5)] }, |
|
657 { start: "hue-rotate(0grad)", end: "hue-rotate("+4*Math.PI+"rad)", |
|
658 expected: ["hue-rotate", Math.PI.toFixed(5)] }, |
|
659 { start: "hue-rotate(0grad)", end: "hue-rotate(0turn)", |
|
660 expected: ["hue-rotate", 0] }, |
|
661 // multiple matching functions, same length |
|
662 { start: "contrast(25%) brightness(0.25) blur(25px) sepia(75%)", |
|
663 end: "contrast(75%) brightness(0.75) blur(75px) sepia(25%)", |
|
664 expected: ["contrast", 0.375, "brightness", 0.375, "blur", 37.5, "sepia", 0.625] }, |
|
665 { start: "invert(25%) brightness(0.25) blur(25px) invert(50%) brightness(0.5) blur(50px)", |
|
666 end: "invert(75%) brightness(0.75) blur(75px)", |
|
667 expected: ["invert", 0.375, "brightness", 0.375, "blur", 37.5, "invert", 0.375, "brightness", 0.625, "blur", 37.5] }, |
|
668 // multiple matching functions, different length |
|
669 { start: "contrast(25%) brightness(0.5) blur(50px)", |
|
670 end: "contrast(75%)", |
|
671 expected: ["contrast", 0.375, "brightness", 0.625, "blur", 37.5] }, |
|
672 // mismatching filter functions |
|
673 { start: "contrast(0%)", end: "blur(10px)", |
|
674 expected: ["blur", 10] }, |
|
675 // not supported interpolations |
|
676 { start: "none", end: "url('#b')", |
|
677 expected: ["url", "\""+document.URL+"#b\""] }, |
|
678 { start: "url('#a')", end: "none", |
|
679 expected: ["none"] }, |
|
680 { start: "url('#a')", end: "url('#b')", |
|
681 expected: ["url", "\""+document.URL+"#b\""] }, |
|
682 { start: "url('#a')", end: "blur(10px)", |
|
683 expected: ["blur", 10] }, |
|
684 { start: "blur(10px)", end: "url('#a')", |
|
685 expected: ["url", "\""+document.URL+"#a\""] }, |
|
686 { start: "blur(0px) url('#a')", end: "blur(20px)", |
|
687 expected: ["blur", 20] }, |
|
688 { start: "blur(0px)", end: "blur(20px) url('#a')", |
|
689 expected: ["blur", 20, "url", "\""+document.URL+"#a\""] }, |
|
690 { start: "contrast(0.25) brightness(0.25) blur(25px)", |
|
691 end: "contrast(0.75) url('#a')", |
|
692 expected: ["contrast", 0.75, "url", "\""+document.URL+"#a\""] }, |
|
693 { start: "contrast(0.25) brightness(0.25) blur(75px)", |
|
694 end: "brightness(0.75) contrast(0.75) blur(25px)", |
|
695 expected: ["brightness", 0.75, "contrast", 0.75, "blur", 25] }, |
|
696 { start: "contrast(0.25) brightness(0.25) blur(25px)", |
|
697 end: "contrast(0.75) brightness(0.75) contrast(0.75)", |
|
698 expected: ["contrast", 0.75, "brightness", 0.75, "contrast", 0.75] }, |
|
699 // drop-shadow animation |
|
700 { start: "none", |
|
701 end: "drop-shadow(rgb(0, 0, 0) 4px 4px 0px)", |
|
702 expected: ["drop-shadow", "rgba(0, 0, 0, 0.25) 1px 1px 0px"] }, |
|
703 { start: "drop-shadow(rgb(0, 0, 0) 0px 0px 0px)", |
|
704 end: "drop-shadow(rgb(0, 0, 0) 4px 4px 0px)", |
|
705 expected: ["drop-shadow", "rgb(0, 0, 0) 1px 1px 0px"] }, |
|
706 { start: "drop-shadow(#038000 4px 4px)", |
|
707 end: "drop-shadow(8px 8px 8px red)", |
|
708 expected: ["drop-shadow", "rgb(66, 96, 0) 5px 5px 2px"] }, |
|
709 { start: "blur(25px) drop-shadow(8px 8px)", |
|
710 end: "blur(75px)", |
|
711 expected: ["blur", 37.5, "drop-shadow", "rgb(0, 0, 0) 6px 6px 0px"] }, |
|
712 { start: "blur(75px)", |
|
713 end: "blur(25px) drop-shadow(8px 8px)", |
|
714 expected: ["blur", 62.5, "drop-shadow", "rgb(0, 0, 0) 2px 2px 0px"] }, |
|
715 { start: "drop-shadow(2px 2px blue)", |
|
716 end: "none", |
|
717 expected: ["drop-shadow", "rgba(0, 0, 255, 0.75) 1.5px 1.5px 0px"] }, |
|
718 ]; |
|
719 |
|
720 var prop; |
|
721 for (prop in supported_properties) { |
|
722 // Test that prop is in the property database. |
|
723 ok(prop in gCSSProperties, "property " + prop + " in gCSSProperties"); |
|
724 |
|
725 // Test that the entry has at least one test function. |
|
726 ok(supported_properties[prop].length > 0, |
|
727 "property " + prop + " must have at least one test function"); |
|
728 } |
|
729 |
|
730 // Return a consistent sampling of |count| values out of |array|. |
|
731 function sample_array(array, count) { |
|
732 if (count <= 0) { |
|
733 ok(false, "unexpected count"); |
|
734 return []; |
|
735 } |
|
736 var ratio = array.length / count; |
|
737 if (ratio <= 1) { |
|
738 return array; |
|
739 } |
|
740 var result = new Array(count); |
|
741 for (var i = 0; i < count; ++i) { |
|
742 result[i] = array[Math.floor(i * ratio)]; |
|
743 } |
|
744 return result; |
|
745 } |
|
746 |
|
747 // Test that transitions don't do anything (i.e., aren't supported) on |
|
748 // the properties not in our test list above (and not transition |
|
749 // properties themselves). |
|
750 for (prop in gCSSProperties) { |
|
751 var info = gCSSProperties[prop]; |
|
752 if (!(prop in supported_properties) && |
|
753 info.type != CSS_TYPE_TRUE_SHORTHAND && |
|
754 !("alias_for" in info) && |
|
755 !prop.match(/^transition-/) && |
|
756 // FIXME (Bug 119078): THIS SHOULD REALLY NOT BE NEEDED! |
|
757 prop != "-moz-binding") { |
|
758 |
|
759 if ("prerequisites" in info) { |
|
760 var prereqs = info.prerequisites; |
|
761 for (var prereq in prereqs) { |
|
762 div.style.setProperty(prereq, prereqs[prereq], ""); |
|
763 } |
|
764 } |
|
765 |
|
766 var all_values = info.initial_values.concat(info.other_values); |
|
767 |
|
768 if (all_values.length > 50) { |
|
769 // Since we're using an O(N^2) algorithm here, reduce the list of |
|
770 // values that we want to test. (This test is really only testing |
|
771 // that somebody didn't make a property animatable without |
|
772 // modifying this test. The odds of somebody doing that without |
|
773 // making at least one of the many pairs of values we have left |
|
774 // animatable seems pretty low, at least relative to the chance |
|
775 // that any pair of the values listed in property_database.js is |
|
776 // animatable.) |
|
777 // |
|
778 // That said, we still try to use all of the start of the list on |
|
779 // the assumption that the more basic values are likely to be at |
|
780 // the beginning of the list. |
|
781 all_values = [].concat(info.initial_values.slice(0,2), |
|
782 sample_array(info.initial_values.slice(2), 6), |
|
783 info.other_values.slice(0, 10), |
|
784 sample_array(info.other_values.slice(10), 40)); |
|
785 } |
|
786 |
|
787 var all_computed = []; |
|
788 for (var idx in all_values) { |
|
789 var val = all_values[idx]; |
|
790 div.style.setProperty(prop, val, ""); |
|
791 all_computed.push(cs.getPropertyValue(prop)); |
|
792 } |
|
793 div.style.removeProperty(prop); |
|
794 |
|
795 div.style.setProperty("transition", prop + " 20s linear", ""); |
|
796 for (var i = 0; i < all_values.length; ++i) { |
|
797 for (var j = i + 1; j < all_values.length; ++j) { |
|
798 div.style.setProperty(prop, all_values[i], ""); |
|
799 is(cs.getPropertyValue(prop), all_computed[i], |
|
800 "transitions not supported for property " + prop + |
|
801 " value " + all_values[i]); |
|
802 div.style.setProperty(prop, all_values[j], ""); |
|
803 is(cs.getPropertyValue(prop), all_computed[j], |
|
804 "transitions not supported for property " + prop + |
|
805 " value " + all_values[j]); |
|
806 } |
|
807 } |
|
808 |
|
809 div.style.removeProperty("transition"); |
|
810 div.style.removeProperty(prop); |
|
811 if ("prerequisites" in info) { |
|
812 var prereqs = info.prerequisites; |
|
813 for (var prereq in prereqs) { |
|
814 div.style.removeProperty(prereq); |
|
815 } |
|
816 } |
|
817 } |
|
818 } |
|
819 |
|
820 // Do 4-second linear transitions with -1 second transition delay and |
|
821 // linear timing function so that we can expect the transition to be |
|
822 // one quarter of the way through the value space right after changing |
|
823 // the property. |
|
824 div.style.setProperty("transition-duration", "4s", ""); |
|
825 div.style.setProperty("transition-delay", "-1s", ""); |
|
826 div.style.setProperty("transition-timing-function", "linear", ""); |
|
827 for (prop in supported_properties) { |
|
828 var tinfo = supported_properties[prop]; |
|
829 var info = gCSSProperties[prop]; |
|
830 |
|
831 isnot(info.type, CSS_TYPE_TRUE_SHORTHAND, |
|
832 prop + " must not be a shorthand"); |
|
833 if ("prerequisites" in info) { |
|
834 var prereqs = info.prerequisites; |
|
835 for (var prereq in prereqs) { |
|
836 // We don't want the 19px font-size prereq of line-height, since we |
|
837 // want to leave it 20px. |
|
838 if (prop != "line-height" || prereq != "font-size") { |
|
839 div.style.setProperty(prereq, prereqs[prereq], ""); |
|
840 } |
|
841 } |
|
842 } |
|
843 |
|
844 for (var idx in tinfo) { |
|
845 tinfo[idx](prop); |
|
846 } |
|
847 |
|
848 // Make sure to unset the property and stop transitions on it. |
|
849 div.style.setProperty("transition-property", "none", ""); |
|
850 div.style.removeProperty(prop); |
|
851 cs.getPropertyValue(prop); |
|
852 |
|
853 if ("prerequisites" in info) { |
|
854 var prereqs = info.prerequisites; |
|
855 for (var prereq in prereqs) { |
|
856 div.style.removeProperty(prereq); |
|
857 } |
|
858 } |
|
859 } |
|
860 div.style.removeProperty("transition"); |
|
861 |
|
862 function get_distance(prop, v1, v2) |
|
863 { |
|
864 return SpecialPowers.DOMWindowUtils |
|
865 .computeAnimationDistance(div, prop, v1, v2); |
|
866 } |
|
867 |
|
868 function check_distance(prop, start, quarter, end) |
|
869 { |
|
870 var sq = get_distance(prop, start, quarter); |
|
871 var se = get_distance(prop, start, end); |
|
872 var qe = get_distance(prop, quarter, end); |
|
873 |
|
874 ok(Math.abs((sq * 4 - se) / se) < 0.0001, "property '" + prop + "': distance " + sq + " from start '" + start + "' to quarter '" + quarter + "' should be quarter distance " + se + " from start '" + start + "' to end '" + end + "'"); |
|
875 ok(Math.abs((qe * 4 - se * 3) / se) < 0.0001, "property '" + prop + "': distance " + qe + " from quarter '" + quarter + "' to end '" + end + "' should be three quarters distance " + se + " from start '" + start + "' to end '" + end + "'"); |
|
876 } |
|
877 |
|
878 function test_length_transition(prop) { |
|
879 div.style.setProperty("transition-property", "none", ""); |
|
880 div.style.setProperty(prop, "4px", ""); |
|
881 is(cs.getPropertyValue(prop), "4px", |
|
882 "length-valued property " + prop + ": computed value before transition"); |
|
883 div.style.setProperty("transition-property", prop, ""); |
|
884 div.style.setProperty(prop, "12px", ""); |
|
885 is(cs.getPropertyValue(prop), "6px", |
|
886 "length-valued property " + prop + ": interpolation of lengths"); |
|
887 check_distance(prop, "4px", "6px", "12px"); |
|
888 } |
|
889 |
|
890 function test_length_clamped(prop) { |
|
891 test_length_clamped_or_unclamped(prop, true); |
|
892 } |
|
893 |
|
894 function test_length_unclamped(prop) { |
|
895 test_length_clamped_or_unclamped(prop, false); |
|
896 } |
|
897 |
|
898 function test_length_clamped_or_unclamped(prop, is_clamped) { |
|
899 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
900 div.style.setProperty("transition-property", "none", ""); |
|
901 div.style.setProperty(prop, "0px", ""); |
|
902 is(cs.getPropertyValue(prop), "0px", |
|
903 "length-valued property " + prop + ": flush before clamping test"); |
|
904 div.style.setProperty("transition-property", prop, ""); |
|
905 div.style.setProperty(prop, "100px", ""); |
|
906 (is_clamped ? is : isnot)(cs.getPropertyValue(prop), "0px", |
|
907 "length-valued property " + prop + ": clamping of negatives"); |
|
908 div.style.setProperty("transition-timing-function", "linear", ""); |
|
909 } |
|
910 |
|
911 // Test using float values in the range [0, 1] (e.g. opacity) |
|
912 function test_float_zeroToOne_transition(prop) { |
|
913 div.style.setProperty("transition-property", "none", ""); |
|
914 div.style.setProperty(prop, "0.3", ""); |
|
915 is(cs.getPropertyValue(prop), "0.3", |
|
916 "float-valued property " + prop + ": computed value before transition"); |
|
917 div.style.setProperty("transition-property", prop, ""); |
|
918 div.style.setProperty(prop, "0.8", ""); |
|
919 is(cs.getPropertyValue(prop), "0.425", |
|
920 "float-valued property " + prop + ": interpolation of floats"); |
|
921 check_distance(prop, "0.3", "0.425", "0.8"); |
|
922 } |
|
923 |
|
924 function test_float_zeroToOne_clamped(prop) { |
|
925 test_float_zeroToOne_clamped_or_unclamped(prop, true); |
|
926 } |
|
927 function test_float_zeroToOne_unclamped(prop) { |
|
928 test_float_zeroToOne_clamped_or_unclamped(prop, false); |
|
929 } |
|
930 |
|
931 function test_float_zeroToOne_clamped_or_unclamped(prop, is_clamped) { |
|
932 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
933 div.style.setProperty("transition-property", "none", ""); |
|
934 div.style.setProperty(prop, "0", ""); |
|
935 is(cs.getPropertyValue(prop), "0", |
|
936 "float-valued property " + prop + ": flush before clamping test"); |
|
937 div.style.setProperty("transition-property", prop, ""); |
|
938 div.style.setProperty(prop, "1", ""); |
|
939 (is_clamped ? is : isnot)(cs.getPropertyValue(prop), "0", |
|
940 "float-valued property " + prop + ": clamping of negatives"); |
|
941 div.style.setProperty("transition-timing-function", "linear", ""); |
|
942 } |
|
943 |
|
944 // Test using float values in the range [1, infinity) (e.g. stroke-miterlimit) |
|
945 function test_float_aboveOne_transition(prop) { |
|
946 div.style.setProperty("transition-property", "none", ""); |
|
947 div.style.setProperty(prop, "1", ""); |
|
948 is(cs.getPropertyValue(prop), "1", |
|
949 "float-valued property " + prop + ": computed value before transition"); |
|
950 div.style.setProperty("transition-property", prop, ""); |
|
951 div.style.setProperty(prop, "2.1", ""); |
|
952 is(cs.getPropertyValue(prop), "1.275", |
|
953 "float-valued property " + prop + ": interpolation of floats"); |
|
954 check_distance(prop, "1", "1.275", "2.1"); |
|
955 } |
|
956 |
|
957 function test_float_aboveOne_clamped(prop) { |
|
958 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
959 div.style.setProperty("transition-property", "none", ""); |
|
960 div.style.setProperty(prop, "1", ""); |
|
961 is(cs.getPropertyValue(prop), "1", |
|
962 "float-valued property " + prop + ": flush before clamping test"); |
|
963 div.style.setProperty("transition-property", prop, ""); |
|
964 div.style.setProperty(prop, "5", ""); |
|
965 is(cs.getPropertyValue(prop), "1", |
|
966 "float-valued property " + prop + ": clamping of negatives"); |
|
967 div.style.setProperty("transition-timing-function", "linear", ""); |
|
968 } |
|
969 |
|
970 function test_percent_transition(prop) { |
|
971 div.style.setProperty("transition-property", "none", ""); |
|
972 div.style.setProperty(prop, "25%", ""); |
|
973 var av = cs.getPropertyValue(prop); |
|
974 var a = any_unit_to_num(av); |
|
975 div.style.setProperty(prop, "75%", ""); |
|
976 var bv = cs.getPropertyValue(prop); |
|
977 var b = any_unit_to_num(bv); |
|
978 isnot(b, a, "different percentages (" + av + " and " + bv + |
|
979 ") should be different for " + prop); |
|
980 div.style.setProperty("transition-property", prop, ""); |
|
981 div.style.setProperty(prop, "25%", ""); |
|
982 var res = cs.getPropertyValue(prop); |
|
983 is(any_unit_to_num(res) * 4, 3 * b + a, |
|
984 "percent-valued property " + prop + ": interpolation of percents: " + |
|
985 res + " should be a quarter of the way between " + bv + " and " + av); |
|
986 ok(has_num(res), |
|
987 "percent-valued property " + prop + ": percent computes to number"); |
|
988 check_distance(prop, "25%", "37.5%", "75%"); |
|
989 } |
|
990 |
|
991 function test_percent_clamped(prop) { |
|
992 test_percent_clamped_or_unclamped(prop, true); |
|
993 } |
|
994 |
|
995 function test_percent_unclamped(prop) { |
|
996 test_percent_clamped_or_unclamped(prop, false); |
|
997 } |
|
998 |
|
999 function test_percent_clamped_or_unclamped(prop, is_clamped) { |
|
1000 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1001 div.style.setProperty("transition-property", "none", ""); |
|
1002 div.style.setProperty(prop, "0%", ""); |
|
1003 var zero_val = cs.getPropertyValue(prop); // flushes too |
|
1004 div.style.setProperty("transition-property", prop, ""); |
|
1005 div.style.setProperty(prop, "150%", ""); |
|
1006 (is_clamped ? is : isnot)(cs.getPropertyValue(prop), zero_val, |
|
1007 "percent-valued property " + prop + ": clamping of negatives"); |
|
1008 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1009 } |
|
1010 |
|
1011 function test_length_percent_calc_transition(prop) { |
|
1012 div.style.setProperty("transition-property", "none", ""); |
|
1013 div.style.setProperty(prop, "0%", ""); |
|
1014 var av = cs.getPropertyValue(prop); |
|
1015 var a = any_unit_to_num(av); |
|
1016 div.style.setProperty(prop, "100%", ""); |
|
1017 var bv = cs.getPropertyValue(prop); |
|
1018 var b = any_unit_to_num(bv); |
|
1019 div.style.setProperty(prop, "100px", ""); |
|
1020 var cv = cs.getPropertyValue(prop); |
|
1021 var c = any_unit_to_num(cv); |
|
1022 isnot(b, a, "different percentages (" + av + " and " + bv + |
|
1023 ") should be different for " + prop); |
|
1024 |
|
1025 div.style.setProperty(prop, "50%", ""); |
|
1026 var v1v = cs.getPropertyValue(prop); |
|
1027 is(any_unit_to_num(v1v) * 2, a + b, |
|
1028 "computed value before transition for " + prop + ": '" + |
|
1029 v1v + "' should be halfway " + |
|
1030 "between '" + av + "' + and '" + bv + "'."); |
|
1031 div.style.setProperty("transition-property", prop, ""); |
|
1032 div.style.setProperty(prop, "200px", ""); |
|
1033 var v2v = cs.getPropertyValue(prop); |
|
1034 is(any_unit_to_num(v2v) * 8, 5*a + 3*b + 4*c, |
|
1035 "interpolation between length and percent for " + prop + ": '" |
|
1036 + v2v + "'"); |
|
1037 |
|
1038 div.style.setProperty("transition-property", "none", ""); |
|
1039 div.style.setProperty(prop, "calc(25% + 100px)", ""); |
|
1040 v1v = cs.getPropertyValue(prop); |
|
1041 is(any_unit_to_num(v1v) * 4, b + 4*c, |
|
1042 "computed value before transition for " + prop + ": '" + v1v + "'"); |
|
1043 div.style.setProperty("transition-property", prop, ""); |
|
1044 div.style.setProperty(prop, "75%", ""); |
|
1045 v2v = cs.getPropertyValue(prop); |
|
1046 is(any_unit_to_num(v2v) * 8, 5*a + 3*b + 6*c, |
|
1047 "interpolation between calc() and percent for " + prop + ": '" + |
|
1048 v2v + "'"); |
|
1049 |
|
1050 div.style.setProperty("transition-property", "none", ""); |
|
1051 div.style.setProperty(prop, "150px", ""); |
|
1052 v1v = cs.getPropertyValue(prop); |
|
1053 is(any_unit_to_num(v1v) * 2, c * 3, |
|
1054 "computed value before transition for " + prop + ": '" + v1v + "'"); |
|
1055 div.style.setProperty("transition-property", prop, ""); |
|
1056 div.style.setProperty(prop, "calc(50% + 50px)", ""); |
|
1057 v2v = cs.getPropertyValue(prop); |
|
1058 is(any_unit_to_num(v2v) * 8, 7 * a + b + 10*c, |
|
1059 "interpolation between length and calc() for " + prop + ": '" + |
|
1060 v2v + "'"); |
|
1061 |
|
1062 check_distance(prop, "50%", "calc(37.5% + 50px)", "200px"); |
|
1063 check_distance(prop, "calc(25% + 100px)", "calc(37.5% + 75px)", |
|
1064 "75%"); |
|
1065 check_distance(prop, "150px", "calc(125px + 12.5%)", |
|
1066 "calc(50% + 50px)"); |
|
1067 } |
|
1068 |
|
1069 function test_color_transition(prop) { |
|
1070 div.style.setProperty("transition-property", "none", ""); |
|
1071 div.style.setProperty(prop, "rgb(255, 28, 0)", ""); |
|
1072 is(cs.getPropertyValue(prop), "rgb(255, 28, 0)", |
|
1073 "color-valued property " + prop + ": computed value before transition"); |
|
1074 div.style.setProperty("transition-property", prop, ""); |
|
1075 div.style.setProperty(prop, "rgb(75, 84, 128)", ""); |
|
1076 is(cs.getPropertyValue(prop), "rgb(210, 42, 32)", |
|
1077 "color-valued property " + prop + ": interpolation of colors"); |
|
1078 |
|
1079 div.style.setProperty("transition-property", "none", ""); |
|
1080 div.style.setProperty(prop, "rgb(128, 64, 0)", ""); |
|
1081 (prop == "color" ? div.parentNode : div).style. |
|
1082 setProperty("color", "rgb(0, 0, 128)", ""); |
|
1083 is(cs.getPropertyValue(prop), "rgb(128, 64, 0)", |
|
1084 "color-valued property " + prop + ": computed value before transition"); |
|
1085 div.style.setProperty("transition-property", prop, ""); |
|
1086 div.style.setProperty(prop, "currentColor", ""); |
|
1087 is(cs.getPropertyValue(prop), "rgb(96, 48, 32)", |
|
1088 "color-valued property " + prop + ": interpolation of currentColor"); |
|
1089 |
|
1090 check_distance(prop, "rgb(255, 28, 0)", "rgb(210, 42, 32)", |
|
1091 "rgb(75, 84, 128)"); |
|
1092 check_distance(prop, "rgb(128, 64, 0)", "rgb(96, 48, 32)", "currentColor"); |
|
1093 |
|
1094 (prop == "color" ? div.parentNode : div).style.removeProperty("color"); |
|
1095 |
|
1096 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1097 div.style.setProperty("transition-property", "none", ""); |
|
1098 div.style.setProperty(prop, "rgb(0, 255, 0)", ""); |
|
1099 var vals = cs.getPropertyValue(prop).match(/rgb\(([^, ]*), ([^, ]*), ([^, ]*)\)/); |
|
1100 is(vals.length, 4, |
|
1101 "color-valued property " + prop + ": flush before clamping test (length)"); |
|
1102 is(vals[1], "0", |
|
1103 "color-valued property " + prop + ": flush before clamping test (red)"); |
|
1104 is(vals[2], "255", |
|
1105 "color-valued property " + prop + ": flush before clamping test (green)"); |
|
1106 is(vals[3], "0", |
|
1107 "color-valued property " + prop + ": flush before clamping test (blue)"); |
|
1108 div.style.setProperty("transition-property", prop, ""); |
|
1109 div.style.setProperty(prop, "rgb(255, 0, 128)", ""); |
|
1110 // FIXME: Once we support non-sRGB colors, these tests will need fixing. |
|
1111 vals = cs.getPropertyValue(prop).match(/rgb\(([^, ]*), ([^, ]*), ([^, ]*)\)/); |
|
1112 is(vals.length, 4, |
|
1113 "color-valued property " + prop + ": clamping of negatives (length)"); |
|
1114 is(vals[1], "0", |
|
1115 "color-valued property " + prop + ": clamping of negatives (red)"); |
|
1116 is(vals[2], "255", |
|
1117 "color-valued property " + prop + ": clamping of above-range (green)"); |
|
1118 is(vals[3], "0", |
|
1119 "color-valued property " + prop + ": clamping of negatives (blue)"); |
|
1120 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1121 } |
|
1122 |
|
1123 function test_border_color_transition(prop) { |
|
1124 div.style.setProperty("transition-property", "none", ""); |
|
1125 div.style.setProperty(prop, "rgb(128, 64, 0)", ""); |
|
1126 div.style.setProperty("color", "rgb(0, 0, 128)", ""); |
|
1127 is(cs.getPropertyValue(prop), "rgb(128, 64, 0)", |
|
1128 "color-valued property " + prop + ": computed value before transition"); |
|
1129 div.style.setProperty("transition-property", prop, ""); |
|
1130 div.style.removeProperty(prop); |
|
1131 is(cs.getPropertyValue(prop), "rgb(96, 48, 32)", |
|
1132 "color-valued property " + prop + ": interpolation of initial value"); |
|
1133 |
|
1134 check_distance(prop, "rgb(128, 64, 0)", "rgb(96, 48, 32)", "initial"); |
|
1135 |
|
1136 div.style.removeProperty("color"); |
|
1137 } |
|
1138 |
|
1139 function filter_function_list_equals(computedValStr, expectedList) |
|
1140 { |
|
1141 // Check simple case "none" |
|
1142 if (computedValStr == "none" && computedValStr == expectedList[0]) { |
|
1143 return true; |
|
1144 } |
|
1145 |
|
1146 // The regular expression does not filter out the last parenthesis. |
|
1147 // Remove last character for now. |
|
1148 is(computedValStr.substring(computedValStr.length - 1, computedValStr.length), |
|
1149 ')', "Check if last character is close-paren"); |
|
1150 computedValStr = computedValStr.substring(0, computedValStr.length - 1); |
|
1151 |
|
1152 var reg = /\)*\s*(blur|brightness|contrast|grayscale|hue\-rotate|invert|opacity|saturate|sepia|drop\-shadow|url)\(/ |
|
1153 var matches = computedValStr.split(reg); |
|
1154 // First item must be empty. All other items are of functionName, functionValue. |
|
1155 if (!matches || matches.shift() != "") { |
|
1156 ok(false, "computed style of 'filter' isn't in the format we expect"); |
|
1157 return false; |
|
1158 } |
|
1159 |
|
1160 // Odd items are the function name, even items the function value. |
|
1161 if (!matches.length || matches.length % 2 || |
|
1162 expectedList.length != matches.length) { |
|
1163 ok(false, "computed style of 'filter' isn't in the format we expect"); |
|
1164 return false; |
|
1165 } |
|
1166 for (var i = 0; i < matches.length; i += 2) { |
|
1167 var functionName = matches[i]; |
|
1168 var functionValue = matches[i+1]; |
|
1169 var expected = expectedList[i+1] |
|
1170 var tolerance = 0; |
|
1171 // Check if we have the expected function. |
|
1172 if (functionName != expectedList[i]) { |
|
1173 return false; |
|
1174 } |
|
1175 if (functionName == "blur") { |
|
1176 // Last two characters must be "px". |
|
1177 if (functionValue.search("px") != functionValue.length - 2) { |
|
1178 return false; |
|
1179 } |
|
1180 functionValue = functionValue.substring(0, functionValue.length - 2); |
|
1181 } else if (functionName == "hue-rotate") { |
|
1182 // Last two characters must be "rad". |
|
1183 if (functionValue.search("rad") != functionValue.length - 3) { |
|
1184 return false; |
|
1185 } |
|
1186 tolerance = 0.001; |
|
1187 functionValue = functionValue.substring(0, functionValue.length - 3); |
|
1188 } else if (functionName == "drop-shadow" || functionName == "url") { |
|
1189 if (functionValue != expected) { |
|
1190 return false; |
|
1191 } |
|
1192 continue; |
|
1193 } |
|
1194 // Check if string is not a number or difference is not in tolerance level. |
|
1195 if (isNaN(functionValue) || |
|
1196 Math.abs(parseFloat(functionValue) - expected) > tolerance) { |
|
1197 return false; |
|
1198 } |
|
1199 } |
|
1200 return true; |
|
1201 } |
|
1202 |
|
1203 function test_filter_transition(prop) { |
|
1204 if (!SpecialPowers.getBoolPref("layout.css.filters.enabled")) { |
|
1205 return; |
|
1206 } |
|
1207 for (var i in filterTests) { |
|
1208 var test = filterTests[i]; |
|
1209 div.style.setProperty("transition-property", "none", ""); |
|
1210 div.style.setProperty(prop, test.start, ""); |
|
1211 cs.getPropertyValue(prop); |
|
1212 div.style.setProperty("transition-property", prop, ""); |
|
1213 div.style.setProperty(prop, test.end, ""); |
|
1214 var actual = cs.getPropertyValue(prop); |
|
1215 ok(filter_function_list_equals(actual, test.expected), |
|
1216 "Filter property is " + actual + " expected values of " + |
|
1217 test.expected); |
|
1218 } |
|
1219 } |
|
1220 |
|
1221 function test_shadow_transition(prop) { |
|
1222 var spreadStr = (prop == "box-shadow") ? " 0px" : ""; |
|
1223 |
|
1224 div.style.setProperty("transition-property", "none", ""); |
|
1225 div.style.setProperty(prop, "none", ""); |
|
1226 is(cs.getPropertyValue(prop), "none", |
|
1227 "shadow-valued property " + prop + ": computed value before transition"); |
|
1228 div.style.setProperty("transition-property", prop, ""); |
|
1229 div.style.setProperty(prop, "4px 8px 3px red", ""); |
|
1230 is(cs.getPropertyValue(prop), "rgba(255, 0, 0, 0.25) 1px 2px 0.75px" + spreadStr, |
|
1231 "shadow-valued property " + prop + ": interpolation of shadows"); |
|
1232 check_distance(prop, "none", "rgba(255, 0, 0, 0.25) 1px 2px 0.75px", |
|
1233 "4px 8px 3px red"); |
|
1234 |
|
1235 div.style.setProperty("transition-property", "none", ""); |
|
1236 div.style.setProperty(prop, "#038000 4px 4px, 2px 2px blue", ""); |
|
1237 is(cs.getPropertyValue(prop), "rgb(3, 128, 0) 4px 4px 0px" + spreadStr + ", rgb(0, 0, 255) 2px 2px 0px" + spreadStr, |
|
1238 "shadow-valued property " + prop + ": computed value before transition"); |
|
1239 div.style.setProperty("transition-property", prop, ""); |
|
1240 div.style.setProperty(prop, "8px 8px 8px red", ""); |
|
1241 is(cs.getPropertyValue(prop), "rgb(66, 96, 0) 5px 5px 2px" + spreadStr + ", rgba(0, 0, 255, 0.75) 1.5px 1.5px 0px" + spreadStr, |
|
1242 "shadow-valued property " + prop + ": interpolation of shadows"); |
|
1243 check_distance(prop, "#038000 4px 4px, 2px 2px blue", |
|
1244 "rgb(66, 96, 0) 5px 5px 2px, rgba(0, 0, 255, 0.75) 1.5px 1.5px 0px", |
|
1245 "8px 8px 8px red"); |
|
1246 |
|
1247 if (prop == "box-shadow") { |
|
1248 div.style.setProperty(prop, "8px 8px 8px red inset", ""); |
|
1249 is(cs.getPropertyValue(prop), "rgb(255, 0, 0) 8px 8px 8px 0px inset", |
|
1250 "shadow-valued property " + prop + ": non-interpolable cases"); |
|
1251 div.style.setProperty(prop, "8px 8px 8px 8px red inset", ""); |
|
1252 is(cs.getPropertyValue(prop), "rgb(255, 0, 0) 8px 8px 8px 2px inset", |
|
1253 "shadow-valued property " + prop + ": interpolation of spread"); |
|
1254 // Leave in same state whether in the |if| or not. |
|
1255 div.style.setProperty(prop, "8px 8px 8px red", ""); |
|
1256 is(cs.getPropertyValue(prop), "rgb(255, 0, 0) 8px 8px 8px 0px", |
|
1257 "shadow-valued property " + prop + ": non-interpolable cases"); |
|
1258 check_distance(prop, "8px 8px 8px red inset", |
|
1259 "rgb(255, 0, 0) 8px 8px 8px 2px inset", |
|
1260 "8px 8px 8px 8px red inset"); |
|
1261 } |
|
1262 |
|
1263 var defaultColor = cs.getPropertyValue("color") + " "; |
|
1264 div.style.setProperty(prop, "2px 2px 2px", ""); |
|
1265 is(cs.getPropertyValue(prop), defaultColor + "2px 2px 2px" + spreadStr, |
|
1266 "shadow-valued property " + prop + ": non-interpolable cases"); |
|
1267 div.style.setProperty(prop, "6px 14px 10px", ""); |
|
1268 is(cs.getPropertyValue(prop), defaultColor + "3px 5px 4px" + spreadStr, |
|
1269 "shadow-valued property " + prop + ": interpolation without color"); |
|
1270 check_distance(prop, "2px 2px 2px", "3px 5px 4px", "6px 14px 10px"); |
|
1271 |
|
1272 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1273 div.style.setProperty("transition-property", "none", ""); |
|
1274 div.style.setProperty(prop, "0px 0px 0px black", ""); |
|
1275 is(cs.getPropertyValue(prop), "rgb(0, 0, 0) 0px 0px 0px" + spreadStr, |
|
1276 "shadow-valued property " + prop + ": flush before clamping test"); |
|
1277 div.style.setProperty("transition-property", prop, ""); |
|
1278 div.style.setProperty(prop, "10px 10px 10px black", ""); |
|
1279 var vals = cs.getPropertyValue(prop).split(" "); |
|
1280 is(vals.length, 6 + (prop == "box-shadow"), "unexpected number of values"); |
|
1281 is(vals.slice(0, 3).join(" "), "rgb(0, 0, 0)", |
|
1282 "shadow-valued property " + prop + " (color): clamping of negatives"); |
|
1283 isnot(vals[3], "0px", |
|
1284 "shadow-valued property " + prop + " (x): clamping of negatives"); |
|
1285 isnot(vals[4], "0px", |
|
1286 "shadow-valued property " + prop + " (y): clamping of negatives"); |
|
1287 is(vals[5], "0px", |
|
1288 "shadow-valued property " + prop + " (radius): clamping of negatives"); |
|
1289 if (prop == "box-shadow") { |
|
1290 div.style.setProperty("transition-property", "none", ""); |
|
1291 div.style.setProperty(prop, "0px 0px 0px 0px black", ""); |
|
1292 is(cs.getPropertyValue(prop), "rgb(0, 0, 0) 0px 0px 0px 0px", |
|
1293 "shadow-valued property " + prop + ": flush before clamping test"); |
|
1294 div.style.setProperty("transition-property", prop, ""); |
|
1295 div.style.setProperty(prop, "10px 10px 10px 10px black", ""); |
|
1296 var vals = cs.getPropertyValue(prop).split(" "); |
|
1297 is(vals.length, 7, "unexpected number of values"); |
|
1298 is(vals.slice(0, 3).join(" "), "rgb(0, 0, 0)", |
|
1299 "shadow-valued property " + prop + " (color): clamping of negatives"); |
|
1300 isnot(vals[3], "0px", |
|
1301 "shadow-valued property " + prop + " (x): clamping of negatives"); |
|
1302 isnot(vals[4], "0px", |
|
1303 "shadow-valued property " + prop + " (y): clamping of negatives"); |
|
1304 is(vals[5], "0px", |
|
1305 "shadow-valued property " + prop + " (radius): clamping of negatives"); |
|
1306 isnot(vals[6], "0px", |
|
1307 "shadow-valued property " + prop + " (spread): clamping of negatives"); |
|
1308 } |
|
1309 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1310 } |
|
1311 |
|
1312 function test_dasharray_transition(prop) { |
|
1313 div.style.setProperty("transition-property", "none", ""); |
|
1314 div.style.setProperty(prop, "3", ""); |
|
1315 is(cs.getPropertyValue(prop), "3", |
|
1316 "dasharray-valued property " + prop + |
|
1317 ": computed value before transition"); |
|
1318 div.style.setProperty("transition-property", prop, ""); |
|
1319 div.style.setProperty(prop, "15px", ""); |
|
1320 is(cs.getPropertyValue(prop), "6", |
|
1321 "dasharray-valued property " + prop + ": interpolation of dasharray"); |
|
1322 check_distance(prop, "3", "6", "15px"); |
|
1323 div.style.setProperty(prop, "none", ""); |
|
1324 is(cs.getPropertyValue(prop), "none", |
|
1325 "dasharray-valued property " + prop + ": non-interpolability of none"); |
|
1326 div.style.setProperty(prop, "6,8px,4,4", ""); |
|
1327 is(cs.getPropertyValue(prop), "6, 8px, 4, 4", |
|
1328 "dasharray-valued property " + prop + |
|
1329 ": computed value before transition"); |
|
1330 div.style.setProperty(prop, "14, 12,16,16px", ""); |
|
1331 is(cs.getPropertyValue(prop), "8, 9, 7, 7", |
|
1332 "dasharray-valued property " + prop + ": interpolation of dasharray"); |
|
1333 check_distance(prop, "6,8px,4,4", "8,9,7,7", "14, 12,16,16px"); |
|
1334 div.style.setProperty(prop, "none", ""); |
|
1335 is(cs.getPropertyValue(prop), "none", |
|
1336 "dasharray-valued property " + prop + ": non-interpolability of none"); |
|
1337 div.style.setProperty(prop, "8,16,4", ""); |
|
1338 is(cs.getPropertyValue(prop), "8, 16, 4", |
|
1339 "dasharray-valued property " + prop + |
|
1340 ": computed value before transition"); |
|
1341 div.style.setProperty(prop, "4,8,12,16", ""); |
|
1342 is(cs.getPropertyValue(prop), "7, 14, 6, 10, 13, 5, 9, 16, 4, 8, 15, 7", |
|
1343 "dasharray-valued property " + prop + ": interpolation of dasharray"); |
|
1344 check_distance(prop, "8,16,4", "7, 14, 6, 10, 13, 5, 9, 16, 4, 8, 15, 7", |
|
1345 "4,8,12,16"); |
|
1346 div.style.setProperty(prop, "2,50%,6,10", ""); |
|
1347 is(cs.getPropertyValue(prop), "2, 50%, 6, 10", |
|
1348 "dasharray-valued property " + prop + ": non-interpolability of mixed units"); |
|
1349 div.style.setProperty(prop, "6,30%,2,2", ""); |
|
1350 is(cs.getPropertyValue(prop), "3, 45%, 5, 8", |
|
1351 "dasharray-valued property " + prop + ": interpolation of dasharray"); |
|
1352 check_distance(prop, "2,50%,6,10", "3, 45%, 5, 8", "6,30%,2,2"); |
|
1353 |
|
1354 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1355 div.style.setProperty("transition-property", "none", ""); |
|
1356 div.style.setProperty(prop, "0,0%", ""); |
|
1357 is(cs.getPropertyValue(prop), "0, 0%", |
|
1358 "dasharray-valued property " + prop + ": flush before clamping test"); |
|
1359 div.style.setProperty("transition-property", prop, ""); |
|
1360 div.style.setProperty(prop, "5, 25%", ""); |
|
1361 is(cs.getPropertyValue(prop), "0, 0%", |
|
1362 "dasharray-valued property " + prop + ": clamping of negatives"); |
|
1363 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1364 } |
|
1365 |
|
1366 function test_radius_transition(prop) { |
|
1367 div.style.setProperty("transition-property", "none", ""); |
|
1368 |
|
1369 // FIXME: Test a square for now, since we haven't updated to the spec |
|
1370 // for vertical components being relative to the height. |
|
1371 // Note: We use powers of two here so the floating-point math comes out |
|
1372 // nicely. |
|
1373 div.style.setProperty("width", "256px", ""); |
|
1374 div.style.setProperty("height", "256px", ""); |
|
1375 div.style.setProperty("border", "none", ""); |
|
1376 div.style.setProperty("padding", "0", ""); |
|
1377 |
|
1378 div.style.setProperty(prop, "3px", ""); |
|
1379 is(cs.getPropertyValue(prop), "3px", |
|
1380 "radius-valued property " + prop + |
|
1381 ": computed value before transition"); |
|
1382 div.style.setProperty("transition-property", prop, ""); |
|
1383 div.style.setProperty(prop, "15px", ""); |
|
1384 is(cs.getPropertyValue(prop), "6px", |
|
1385 "radius-valued property " + prop + ": interpolation of radius"); |
|
1386 check_distance(prop, "3px", "6px", "15px"); |
|
1387 div.style.setProperty("transition-property", "none", ""); |
|
1388 div.style.setProperty(prop, "12.5%", ""); |
|
1389 is(cs.getPropertyValue(prop), "32px", |
|
1390 "radius-valued property " + prop + ": computed value before transition"); |
|
1391 div.style.setProperty("transition-property", prop, ""); |
|
1392 div.style.setProperty(prop, "25%", ""); |
|
1393 is(cs.getPropertyValue(prop), "40px", |
|
1394 "radius-valued property " + prop + ": interpolation of radius"); |
|
1395 check_distance(prop, "12.5%", "15.625%", "25%"); |
|
1396 div.style.setProperty("transition-property", "none", ""); |
|
1397 div.style.setProperty(prop, "3px 8px", ""); |
|
1398 is(cs.getPropertyValue(prop), "3px 8px", |
|
1399 "radius-valued property " + prop + ": computed value before transition"); |
|
1400 div.style.setProperty("transition-property", prop, ""); |
|
1401 div.style.setProperty(prop, "15px 12px", ""); |
|
1402 is(cs.getPropertyValue(prop), "6px 9px", |
|
1403 "radius-valued property " + prop + ": interpolation of radius"); |
|
1404 check_distance(prop, "3px 8px", "6px 9px", "15px 12px"); |
|
1405 div.style.setProperty("transition-property", "none", ""); |
|
1406 div.style.setProperty(prop, "12.5% 6.25%", ""); |
|
1407 is(cs.getPropertyValue(prop), "32px 16px", |
|
1408 "radius-valued property " + prop + ": computed value before transition"); |
|
1409 div.style.setProperty("transition-property", prop, ""); |
|
1410 div.style.setProperty(prop, "25%", ""); |
|
1411 is(cs.getPropertyValue(prop), "40px 28px", |
|
1412 "radius-valued property " + prop + ": interpolation of radius"); |
|
1413 check_distance(prop, "12.5% 6.25%", "15.625% 10.9375%", "25%"); |
|
1414 div.style.setProperty("transition-property", "none", ""); |
|
1415 div.style.setProperty(prop, "6.25% 12.5%", ""); |
|
1416 is(cs.getPropertyValue(prop), "16px 32px", |
|
1417 "radius-valued property " + prop + ": computed value before transition"); |
|
1418 div.style.setProperty("transition-property", prop, ""); |
|
1419 div.style.setProperty(prop, "64px 16px", ""); |
|
1420 is(cs.getPropertyValue(prop), "28px", |
|
1421 "radius-valued property " + prop + ": interpolation of radius with mixed units"); |
|
1422 check_distance(prop, "6.25% 12.5%", |
|
1423 "calc(4.6875% + 16px) calc(9.375% + 4px)", |
|
1424 "64px 16px"); |
|
1425 |
|
1426 div.style.setProperty("transition-property", "none", ""); |
|
1427 div.style.setProperty(prop, "calc(5px) 10px", ""); |
|
1428 is(cs.getPropertyValue(prop), "5px 10px", |
|
1429 "radius-valued property " + prop + ": computed value before transition"); |
|
1430 div.style.setProperty("transition-property", prop, ""); |
|
1431 div.style.setProperty(prop, "calc(25px) calc(50px)", ""); |
|
1432 is(cs.getPropertyValue(prop), "10px 20px", |
|
1433 "radius-valued property " + prop + ": interpolation of radius with calc() units"); |
|
1434 |
|
1435 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1436 div.style.setProperty("transition-property", "none", ""); |
|
1437 div.style.setProperty(prop, "0px 0px", ""); |
|
1438 is(cs.getPropertyValue(prop), "0px", |
|
1439 "radius-valued property " + prop + ": flush before clamping test"); |
|
1440 div.style.setProperty("transition-property", prop, ""); |
|
1441 div.style.setProperty(prop, "10px 20px", ""); |
|
1442 is(cs.getPropertyValue(prop), "0px", |
|
1443 "radius-valued property " + prop + ": clamping of negatives"); |
|
1444 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1445 |
|
1446 test_length_percent_calc_transition(prop); |
|
1447 |
|
1448 div.style.removeProperty("width"); |
|
1449 div.style.removeProperty("height"); |
|
1450 div.style.removeProperty("border"); |
|
1451 div.style.removeProperty("padding"); |
|
1452 } |
|
1453 |
|
1454 function test_integer_transition(prop) { |
|
1455 div.style.setProperty("transition-property", "none", ""); |
|
1456 div.style.setProperty(prop, "4", ""); |
|
1457 is(cs.getPropertyValue(prop), "4", |
|
1458 "integer-valued property " + prop + ": computed value before transition"); |
|
1459 div.style.setProperty("transition-property", prop, ""); |
|
1460 div.style.setProperty(prop, "-14", ""); |
|
1461 is(cs.getPropertyValue(prop), "-1", |
|
1462 "integer-valued property " + prop + ": interpolation of integers"); |
|
1463 check_distance(prop, "6", "1", "-14"); |
|
1464 |
|
1465 div.style.setProperty("transition-property", "none", ""); |
|
1466 div.style.setProperty(prop, "-4", ""); |
|
1467 is(cs.getPropertyValue(prop), "-4", |
|
1468 "integer-valued property " + prop + ": computed value before transition"); |
|
1469 div.style.setProperty("transition-property", prop, ""); |
|
1470 div.style.setProperty(prop, "8", ""); |
|
1471 is(cs.getPropertyValue(prop), "-1", |
|
1472 "integer-valued property " + prop + ": interpolation of integers"); |
|
1473 check_distance(prop, "-4", "-1", "8"); |
|
1474 |
|
1475 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1476 div.style.setProperty("transition-property", "none", ""); |
|
1477 div.style.setProperty(prop, "0", ""); |
|
1478 is(cs.getPropertyValue(prop), "0", |
|
1479 "integer-valued property " + prop + ": flush before clamping test"); |
|
1480 div.style.setProperty("transition-property", prop, ""); |
|
1481 div.style.setProperty(prop, "100", ""); |
|
1482 isnot(cs.getPropertyValue(prop), "0", |
|
1483 "integer-valued property " + prop + ": clamping of negatives"); |
|
1484 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1485 } |
|
1486 |
|
1487 function test_font_stretch(prop) { |
|
1488 is(prop, "font-stretch", "only designed for one property"); |
|
1489 |
|
1490 div.style.setProperty("transition-property", "none", ""); |
|
1491 div.style.setProperty(prop, "normal", ""); |
|
1492 is(cs.getPropertyValue(prop), "normal", |
|
1493 "font-stretch property " + prop + ": computed value before transition"); |
|
1494 div.style.setProperty("transition-property", prop, ""); |
|
1495 div.style.setProperty(prop, "ultra-expanded", ""); |
|
1496 is(cs.getPropertyValue(prop), "semi-expanded", |
|
1497 "font-stretch property " + prop + ": interpolation of font-stretches"); |
|
1498 check_distance(prop, "normal", "semi-expanded", "ultra-expanded"); |
|
1499 div.style.setProperty("transition-property", "none", ""); |
|
1500 div.style.setProperty(prop, "expanded", ""); |
|
1501 is(cs.getPropertyValue(prop), "expanded", |
|
1502 "font-stretch property " + prop + ": computed value before transition"); |
|
1503 div.style.setProperty("transition-property", prop, ""); |
|
1504 div.style.setProperty(prop, "extra-condensed", ""); |
|
1505 is(cs.getPropertyValue(prop), "normal", |
|
1506 "font-stretch property " + prop + ": interpolation of font-stretches"); |
|
1507 check_distance(prop, "expanded", "semi-expanded", "condensed"); |
|
1508 |
|
1509 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1510 div.style.setProperty("transition-property", "none", ""); |
|
1511 div.style.setProperty(prop, "ultra-condensed", ""); |
|
1512 is(cs.getPropertyValue(prop), "ultra-condensed", |
|
1513 "font-stretch property " + prop + ": flush before clamping test"); |
|
1514 div.style.setProperty("transition-property", prop, ""); |
|
1515 div.style.setProperty(prop, "ultra-expanded", ""); |
|
1516 is(cs.getPropertyValue(prop), "ultra-condensed", |
|
1517 "font-stretch property " + prop + ": clamping of values"); |
|
1518 div.style.setProperty("transition-property", "none", ""); |
|
1519 div.style.setProperty(prop, "ultra-expanded", ""); |
|
1520 is(cs.getPropertyValue(prop), "ultra-expanded", |
|
1521 "font-stretch property " + prop + ": flush before clamping test"); |
|
1522 div.style.setProperty("transition-property", prop, ""); |
|
1523 div.style.setProperty(prop, "ultra-condensed", ""); |
|
1524 is(cs.getPropertyValue(prop), "ultra-expanded", |
|
1525 "font-stretch property " + prop + ": clamping of values"); |
|
1526 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1527 } |
|
1528 |
|
1529 function test_font_weight(prop) { |
|
1530 is(prop, "font-weight", "only designed for one property"); |
|
1531 |
|
1532 div.style.setProperty("transition-property", "none", ""); |
|
1533 div.style.setProperty(prop, "normal", ""); |
|
1534 is(cs.getPropertyValue(prop), "400", |
|
1535 "font-weight property " + prop + ": computed value before transition"); |
|
1536 div.style.setProperty("transition-property", prop, ""); |
|
1537 div.style.setProperty(prop, "900", ""); |
|
1538 is(cs.getPropertyValue(prop), "500", |
|
1539 "font-weight property " + prop + ": interpolation of font-weights"); |
|
1540 check_distance(prop, "400", "500", "800"); |
|
1541 |
|
1542 div.style.setProperty("transition-property", "none", ""); |
|
1543 div.style.setProperty(prop, "900", ""); |
|
1544 is(cs.getPropertyValue(prop), "900", |
|
1545 "font-weight property " + prop + ": computed value before transition"); |
|
1546 div.style.setProperty("transition-property", prop, ""); |
|
1547 div.style.setProperty(prop, "100", ""); |
|
1548 is(cs.getPropertyValue(prop), "700", |
|
1549 "font-weight property " + prop + ": interpolation of font-weights"); |
|
1550 check_distance(prop, "900", "700", "100"); |
|
1551 |
|
1552 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1553 div.style.setProperty("transition-property", "none", ""); |
|
1554 div.style.setProperty(prop, "100", ""); |
|
1555 is(cs.getPropertyValue(prop), "100", |
|
1556 "font-weight property " + prop + ": flush before clamping test"); |
|
1557 div.style.setProperty("transition-property", prop, ""); |
|
1558 div.style.setProperty(prop, "900", ""); |
|
1559 is(cs.getPropertyValue(prop), "100", |
|
1560 "font-weight property " + prop + ": clamping of values"); |
|
1561 div.style.setProperty("transition-property", "none", ""); |
|
1562 div.style.setProperty(prop, "900", ""); |
|
1563 is(cs.getPropertyValue(prop), "900", |
|
1564 "font-weight property " + prop + ": flush before clamping test"); |
|
1565 div.style.setProperty("transition-property", prop, ""); |
|
1566 div.style.setProperty(prop, "100", ""); |
|
1567 is(cs.getPropertyValue(prop), "900", |
|
1568 "font-weight property " + prop + ": clamping of values"); |
|
1569 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1570 } |
|
1571 |
|
1572 function test_pos_integer_or_auto_transition(prop) { |
|
1573 div.style.setProperty("transition-property", "none", ""); |
|
1574 div.style.setProperty(prop, "4", ""); |
|
1575 is(cs.getPropertyValue(prop), "4", |
|
1576 "integer-valued property " + prop + ": computed value before transition"); |
|
1577 div.style.setProperty("transition-property", prop, ""); |
|
1578 div.style.setProperty(prop, "11", ""); |
|
1579 is(cs.getPropertyValue(prop), "5", |
|
1580 "integer-valued property " + prop + ": interpolation of integers"); |
|
1581 check_distance(prop, "4", "6", "12"); |
|
1582 div.style.setProperty(prop, "auto", ""); |
|
1583 is(cs.getPropertyValue(prop), "auto", |
|
1584 "integer-valued property " + prop + ": auto not interpolable"); |
|
1585 div.style.setProperty(prop, "8", ""); |
|
1586 is(cs.getPropertyValue(prop), "8", |
|
1587 "integer-valued property " + prop + ": computed value before transition"); |
|
1588 div.style.setProperty(prop, "4", ""); |
|
1589 is(cs.getPropertyValue(prop), "7", |
|
1590 "integer-valued property " + prop + ": interpolation of integers"); |
|
1591 check_distance(prop, "8", "7", "4"); |
|
1592 } |
|
1593 |
|
1594 function test_integer_at_least_one_clamping(prop) { |
|
1595 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1596 div.style.setProperty("transition-property", "none", ""); |
|
1597 div.style.setProperty(prop, "1", ""); |
|
1598 is(cs.getPropertyValue(prop), "1", |
|
1599 "integer-valued property " + prop + ": flush before clamping test"); |
|
1600 div.style.setProperty("transition-property", prop, ""); |
|
1601 div.style.setProperty(prop, "5", ""); |
|
1602 is(cs.getPropertyValue(prop), "1", |
|
1603 "integer-valued property " + prop + ": clamping of negatives"); |
|
1604 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1605 } |
|
1606 |
|
1607 function test_length_pair_transition(prop) { |
|
1608 div.style.setProperty("transition-property", "none", ""); |
|
1609 div.style.setProperty(prop, "4px 6px", ""); |
|
1610 is(cs.getPropertyValue(prop), "4px 6px", |
|
1611 "length-valued property " + prop + ": computed value before transition"); |
|
1612 div.style.setProperty("transition-property", prop, ""); |
|
1613 div.style.setProperty(prop, "12px 10px", ""); |
|
1614 is(cs.getPropertyValue(prop), "6px 7px", |
|
1615 "length-valued property " + prop + ": interpolation of lengths"); |
|
1616 check_distance(prop, "4px 6px", "6px 7px", "12px 10px"); |
|
1617 } |
|
1618 |
|
1619 function test_length_pair_transition_clamped(prop) { |
|
1620 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1621 div.style.setProperty("transition-property", "none", ""); |
|
1622 div.style.setProperty(prop, "0px 0px", ""); |
|
1623 is(cs.getPropertyValue(prop), "0px 0px", |
|
1624 "length-valued property " + prop + ": flush before clamping test"); |
|
1625 div.style.setProperty("transition-property", prop, ""); |
|
1626 div.style.setProperty(prop, "30px 50px", ""); |
|
1627 is(cs.getPropertyValue(prop), "0px 0px", |
|
1628 "length-valued property " + prop + ": clamping of negatives"); |
|
1629 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1630 } |
|
1631 |
|
1632 function test_length_percent_pair_transition(prop) { |
|
1633 div.style.setProperty("transition-property", "none", ""); |
|
1634 div.style.setProperty(prop, "4px 50%", ""); |
|
1635 is(cs.getPropertyValue(prop), "4px 5px", |
|
1636 "length-valued property " + prop + ": computed value before transition"); |
|
1637 div.style.setProperty("transition-property", prop, ""); |
|
1638 div.style.setProperty(prop, "12px 70%", ""); |
|
1639 is(cs.getPropertyValue(prop), "6px 5.5px", |
|
1640 "length-valued property " + prop + ": interpolation of lengths"); |
|
1641 check_distance(prop, "4px 50%", "6px 55%", "12px 70%"); |
|
1642 } |
|
1643 |
|
1644 function test_length_percent_pair_clamped(prop) { |
|
1645 test_length_percent_pair_clamped_or_unclamped(prop, true); |
|
1646 } |
|
1647 |
|
1648 function test_length_percent_pair_unclamped(prop) { |
|
1649 test_length_percent_pair_clamped_or_unclamped(prop, false); |
|
1650 } |
|
1651 |
|
1652 function test_length_percent_pair_clamped_or_unclamped(prop, is_clamped) { |
|
1653 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1654 div.style.setProperty("transition-property", "none", ""); |
|
1655 div.style.setProperty(prop, "0px 0%", ""); |
|
1656 is(cs.getPropertyValue(prop), "0px 0px", |
|
1657 "length+percent-valued property " + prop + ": flush before clamping test"); |
|
1658 div.style.setProperty("transition-property", prop, ""); |
|
1659 div.style.setProperty(prop, "30px 25%", ""); |
|
1660 (is_clamped ? is : isnot)(cs.getPropertyValue(prop), "0px 0px", |
|
1661 "length+percent-valued property " + prop + ": clamping of negatives"); |
|
1662 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1663 } |
|
1664 |
|
1665 function test_rect_transition(prop) { |
|
1666 div.style.setProperty("transition-property", "none", ""); |
|
1667 div.style.setProperty(prop, "rect(4px, 16px, 12px, 6px)", ""); |
|
1668 is(cs.getPropertyValue(prop), "rect(4px, 16px, 12px, 6px)", |
|
1669 "rect-valued property " + prop + ": computed value before transition"); |
|
1670 div.style.setProperty("transition-property", prop, ""); |
|
1671 div.style.setProperty(prop, "rect(0px, 4px, 4px, 2px)", ""); |
|
1672 is(cs.getPropertyValue(prop), "rect(3px, 13px, 10px, 5px)", |
|
1673 "rect-valued property " + prop + ": interpolation of rects"); |
|
1674 check_distance(prop, "rect(4px, 16px, 12px, 6px)", |
|
1675 "rect(3px, 13px, 10px, 5px)", |
|
1676 "rect(0px, 4px, 4px, 2px)"); |
|
1677 if (prop == "clip") { |
|
1678 div.style.setProperty(prop, "rect(0px, 6px, 4px, auto)", ""); |
|
1679 is(cs.getPropertyValue(prop), "rect(0px, 6px, 4px, auto)", |
|
1680 "rect-valued property " + prop + ": can't interpolate auto components"); |
|
1681 div.style.setProperty(prop, "rect(0px, 6px, 4px, 2px)", ""); |
|
1682 } |
|
1683 div.style.setProperty(prop, "auto", ""); |
|
1684 is(cs.getPropertyValue(prop), "auto", |
|
1685 "rect-valued property " + prop + ": can't interpolate auto components"); |
|
1686 |
|
1687 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1688 div.style.setProperty("transition-property", "none", ""); |
|
1689 div.style.setProperty(prop, "rect(-10px, 30px, 0px, 0px)", ""); |
|
1690 var vals = cs.getPropertyValue(prop).match(/rect\(([^, ]*), ([^, ]*), ([^, ]*), ([^, ]*)\)/); |
|
1691 is(vals.length, 5, |
|
1692 "rect-valued property " + prop + ": flush before clamping test (length)"); |
|
1693 is(vals[1], "-10px", |
|
1694 "rect-valued property " + prop + ": flush before clamping test (top)"); |
|
1695 is(vals[2], "30px", |
|
1696 "rect-valued property " + prop + ": flush before clamping test (right)"); |
|
1697 is(vals[3], "0px", |
|
1698 "rect-valued property " + prop + ": flush before clamping test (bottom)"); |
|
1699 is(vals[4], "0px", |
|
1700 "rect-valued property " + prop + ": flush before clamping test (left)"); |
|
1701 div.style.setProperty("transition-property", prop, ""); |
|
1702 div.style.setProperty(prop, "rect(0px, 40px, 10px, 10px)", ""); |
|
1703 vals = cs.getPropertyValue(prop).match(/rect\(([^, ]*), ([^, ]*), ([^, ]*), ([^, ]*)\)/); |
|
1704 is(vals.length, 5, |
|
1705 "rect-valued property " + prop + ": clamping of negatives (length)"); |
|
1706 isnot(vals[1], "-10px", |
|
1707 "rect-valued property " + prop + ": clamping of negatives (top)"); |
|
1708 isnot(vals[2], "30px", |
|
1709 "rect-valued property " + prop + ": clamping of negatives (right)"); |
|
1710 isnot(vals[3], "0px", |
|
1711 "rect-valued property " + prop + ": clamping of negatives (bottom)"); |
|
1712 isnot(vals[4], "0px", |
|
1713 "rect-valued property " + prop + ": clamping of negatives (left)"); |
|
1714 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1715 } |
|
1716 |
|
1717 function test_visibility_transition(prop) { |
|
1718 function do_test(from_value, to_value, interp_value) { |
|
1719 div.style.setProperty("transition-property", "none", ""); |
|
1720 div.style.setProperty(prop, from_value, ""); |
|
1721 is(cs.getPropertyValue(prop), from_value, |
|
1722 "visibility property " + prop + ": computed value before transition"); |
|
1723 div.style.setProperty("transition-property", prop, ""); |
|
1724 div.style.setProperty(prop, to_value, ""); |
|
1725 is(cs.getPropertyValue(prop), interp_value, |
|
1726 "visibility property " + prop + ": interpolation of visibility"); |
|
1727 } |
|
1728 |
|
1729 do_test("visible", "hidden", "visible"); |
|
1730 do_test("hidden", "visible", "visible"); |
|
1731 do_test("hidden", "collapse", "collapse"); /* not interpolable */ |
|
1732 do_test("collapse", "hidden", "hidden"); /* not interpolable */ |
|
1733 do_test("visible", "collapse", "visible"); |
|
1734 do_test("collapse", "visible", "visible"); |
|
1735 |
|
1736 isnot(get_distance(prop, "visible", "hidden"), 0, |
|
1737 "distance between visible and hidden should not be zero"); |
|
1738 isnot(get_distance(prop, "visible", "collapse"), 0, |
|
1739 "distance between visible and collapse should not be zero"); |
|
1740 is(get_distance(prop, "visible", "visible"), 0, |
|
1741 "distance between visible and visible should not be zero"); |
|
1742 is(get_distance(prop, "hidden", "hidden"), 0, |
|
1743 "distance between hidden and hidden should not be zero"); |
|
1744 is(get_distance(prop, "collapse", "collapse"), 0, |
|
1745 "distance between collapse and collapse should not be zero"); |
|
1746 |
|
1747 div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, ""); |
|
1748 function do_negative_test(from_value, to_value, interpolable) { |
|
1749 div.style.setProperty("transition-property", "none", ""); |
|
1750 div.style.setProperty(prop, from_value, ""); |
|
1751 is(cs.getPropertyValue(prop), from_value, |
|
1752 "visibility property " + prop + ": flush before clamping test"); |
|
1753 div.style.setProperty("transition-property", prop, ""); |
|
1754 div.style.setProperty(prop, to_value, ""); |
|
1755 is(cs.getPropertyValue(prop), interpolable ? from_value : to_value, |
|
1756 "visibility property " + prop + ": clamping of negatives"); |
|
1757 } |
|
1758 do_negative_test("visible", "hidden", true); |
|
1759 do_negative_test("hidden", "visible", true); |
|
1760 do_negative_test("hidden", "collapse", false); |
|
1761 do_negative_test("collapse", "hidden", false); |
|
1762 do_negative_test("visible", "collapse", true); |
|
1763 do_negative_test("collapse", "visible", true); |
|
1764 |
|
1765 div.style.setProperty("transition-delay", "-3s", ""); |
|
1766 div.style.setProperty("transition-timing-function", FUNC_OVERONE, ""); |
|
1767 |
|
1768 function do_overone_test(from_value, to_value) { |
|
1769 div.style.setProperty("transition-property", "none", ""); |
|
1770 div.style.setProperty(prop, from_value, ""); |
|
1771 is(cs.getPropertyValue(prop), from_value, |
|
1772 "visibility property " + prop + ": flush before clamping test"); |
|
1773 div.style.setProperty("transition-property", prop, ""); |
|
1774 div.style.setProperty(prop, to_value, ""); |
|
1775 is(cs.getPropertyValue(prop), to_value, |
|
1776 "visibility property " + prop + ": clamping of over-ones"); |
|
1777 } |
|
1778 do_overone_test("visible", "hidden"); |
|
1779 do_overone_test("hidden", "visible"); |
|
1780 do_overone_test("hidden", "collapse"); |
|
1781 do_overone_test("collapse", "hidden"); |
|
1782 do_overone_test("visible", "collapse"); |
|
1783 do_overone_test("collapse", "visible"); |
|
1784 |
|
1785 div.style.setProperty("transition-delay", "-1s", ""); |
|
1786 div.style.setProperty("transition-timing-function", "linear", ""); |
|
1787 } |
|
1788 |
|
1789 function test_background_size_transition(prop) { |
|
1790 div.style.setProperty("transition-property", "none", ""); |
|
1791 div.style.setProperty(prop, "50% 80%", ""); |
|
1792 is(cs.getPropertyValue(prop), "50% 80%", |
|
1793 "property " + prop + ": computed value before transition"); |
|
1794 div.style.setProperty("transition-property", prop, ""); |
|
1795 div.style.setProperty(prop, "100% 100%", ""); |
|
1796 is(cs.getPropertyValue(prop), "62.5% 85%", |
|
1797 "property " + prop + ": interpolation of percents"); |
|
1798 check_distance(prop, "50% 80%", "62.5% 85%", "100% 100%"); |
|
1799 div.style.setProperty(prop, "contain", ""); |
|
1800 is(cs.getPropertyValue(prop), "contain", |
|
1801 "property " + prop + ": can't interpolate 'contain'"); |
|
1802 test_background_position_size_common(prop); |
|
1803 } |
|
1804 |
|
1805 function test_background_position_transition(prop) { |
|
1806 div.style.setProperty("transition-property", "none", ""); |
|
1807 div.style.setProperty(prop, "center 80%", ""); |
|
1808 is(cs.getPropertyValue(prop), "50% 80%", |
|
1809 "property " + prop + ": computed value before transition"); |
|
1810 div.style.setProperty("transition-property", prop, ""); |
|
1811 div.style.setProperty(prop, "bottom right", ""); |
|
1812 is(cs.getPropertyValue(prop), "62.5% 85%", |
|
1813 "property " + prop + ": interpolation of percents"); |
|
1814 check_distance(prop, "center 80%", "62.5% 85%", "bottom right"); |
|
1815 test_background_position_size_common(prop); |
|
1816 } |
|
1817 |
|
1818 function test_background_position_size_common(prop) { |
|
1819 div.style.setProperty("transition-property", "none", ""); |
|
1820 div.style.setProperty(prop, "40% 0%", ""); |
|
1821 is(cs.getPropertyValue(prop), "40% 0%", |
|
1822 "property " + prop + ": computed value before transition"); |
|
1823 div.style.setProperty("transition-property", prop, ""); |
|
1824 div.style.setProperty(prop, "0% 0%", ""); |
|
1825 is(cs.getPropertyValue(prop), "30% 0%", |
|
1826 "property " + prop + ": interpolation of percentages"); |
|
1827 check_distance(prop, "40% 0%", "30% 0%", "0% 0%"); |
|
1828 |
|
1829 div.style.setProperty("transition-property", "none", ""); |
|
1830 div.style.setProperty(prop, "0% 40%", ""); |
|
1831 is(cs.getPropertyValue(prop), "0% 40%", |
|
1832 "property " + prop + ": computed value before transition"); |
|
1833 div.style.setProperty("transition-property", prop, ""); |
|
1834 div.style.setProperty(prop, "0% 0%", ""); |
|
1835 is(cs.getPropertyValue(prop), "0% 30%", |
|
1836 "property " + prop + ": interpolation of percentages"); |
|
1837 check_distance(prop, "0% 40%", "0% 30%", "0% 0%"); |
|
1838 |
|
1839 div.style.setProperty("transition-property", "none", ""); |
|
1840 div.style.setProperty(prop, "10px 40px", ""); |
|
1841 is(cs.getPropertyValue(prop), "10px 40px", |
|
1842 "property " + prop + ": computed value before transition"); |
|
1843 div.style.setProperty("transition-property", prop, ""); |
|
1844 div.style.setProperty(prop, "50px 0", ""); |
|
1845 is(cs.getPropertyValue(prop), "20px 30px", |
|
1846 "property " + prop + ": interpolation of lengths"); |
|
1847 check_distance(prop, "10px 40px", "20px 30px", "50px 0"); |
|
1848 div.style.setProperty(prop, "10px 40px, 50px 50px, 30px 20px", ""); |
|
1849 is(cs.getPropertyValue(prop), "10px 40px, 50px 50px, 30px 20px", |
|
1850 "property " + prop + ": computed value before transition"); |
|
1851 div.style.setProperty(prop, "50px 20px, 70px 50px, 30px 40px", ""); |
|
1852 is(cs.getPropertyValue(prop), "20px 35px, 55px 50px, 30px 25px", |
|
1853 "property " + prop + ": interpolation of lists of lengths"); |
|
1854 check_distance(prop, "10px 40px, 50px 50px, 30px 20px", |
|
1855 "20px 35px, 55px 50px, 30px 25px", |
|
1856 "50px 20px, 70px 50px, 30px 40px"); |
|
1857 div.style.setProperty(prop, "10px 40%, 50% 50px, 30% 20%, 5px 10px", ""); |
|
1858 is(cs.getPropertyValue(prop), "10px 40%, 50% 50px, 30% 20%, 5px 10px", |
|
1859 "property " + prop + ": computed value before transition"); |
|
1860 div.style.setProperty(prop, "50px 20%, 70% 50px, 30% 40%, 25px 50px", ""); |
|
1861 is(cs.getPropertyValue(prop), "20px 35%, 55% 50px, 30% 25%, 10px 20px", |
|
1862 "property " + prop + ": interpolation of lists of lengths and percents"); |
|
1863 check_distance(prop, "10px 40%, 50% 50px, 30% 20%, 5px 10px", |
|
1864 "20px 35%, 55% 50px, 30% 25%, 10px 20px", |
|
1865 "50px 20%, 70% 50px, 30% 40%, 25px 50px"); |
|
1866 div.style.setProperty(prop, "20% 40%, 8px 12px", ""); |
|
1867 is(cs.getPropertyValue(prop), "20% 40%, 8px 12px", |
|
1868 "property " + prop + ": computed value before transition"); |
|
1869 div.style.setProperty(prop, "12px 20px, 40% 16%", ""); |
|
1870 is(cs.getPropertyValue(prop), "calc(3px + 15%) calc(5px + 30%), calc(6px + 10%) calc(9px + 4%)", |
|
1871 "property " + prop + ": interpolation that computes to calc()"); |
|
1872 check_distance(prop, "20% 40%, 8px 12px", |
|
1873 "calc(3px + 15%) calc(5px + 30%), calc(6px + 10%) calc(9px + 4%)", |
|
1874 "12px 20px, 40% 16%"); |
|
1875 div.style.setProperty(prop, "calc(20% + 40px) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)", ""); |
|
1876 is(cs.getPropertyValue(prop), "calc(40px + 20%) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)", |
|
1877 "property " + prop + ": computed value before transition"); |
|
1878 div.style.setProperty(prop, "12px 20%, calc(20%) calc(16px + 60%), calc(8px + 20%) calc(40px + 16%)", ""); |
|
1879 is(cs.getPropertyValue(prop), "calc(33px + 15%) calc(30px + 35%), calc(6px + 5%) calc(4px + 24%), calc(17px + 14%) calc(28px + 10%)", |
|
1880 "property " + prop + ": interpolation that computes to calc()"); |
|
1881 check_distance(prop, "calc(20% + 40px) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)", |
|
1882 "calc(33px + 15%) calc(30px + 35%), calc(6px + 5%) calc(4px + 24%), calc(17px + 14%) calc(28px + 10%)", |
|
1883 "12px 20%, calc(20%) calc(16px + 60%), calc(8px + 20%) calc(40px + 16%)"); |
|
1884 } |
|
1885 |
|
1886 function test_transform_transition(prop) { |
|
1887 is(prop, "transform", "Unexpected transform property! Test needs to be fixed"); |
|
1888 var matrix_re = /^matrix\(([^,]*), ([^,]*), ([^,]*), ([^,]*), ([^,]*), ([^,]*)\)$/; |
|
1889 for (var i in transformTests) { |
|
1890 var test = transformTests[i]; |
|
1891 if (!("expected" in test)) { |
|
1892 var v = test.expected_uncomputed; |
|
1893 if (v.match(matrix_re) && !test.force_compute) { |
|
1894 test.expected = v; |
|
1895 } else { |
|
1896 test.expected = computeMatrix(v); |
|
1897 } |
|
1898 } |
|
1899 } |
|
1900 |
|
1901 for (var i in transformTests) { |
|
1902 var test = transformTests[i]; |
|
1903 div.style.setProperty("transition-property", "none", ""); |
|
1904 div.style.setProperty(prop, test.start, ""); |
|
1905 cs.getPropertyValue(prop); |
|
1906 div.style.setProperty("transition-property", prop, ""); |
|
1907 div.style.setProperty(prop, test.end, ""); |
|
1908 var actual = cs.getPropertyValue(prop); |
|
1909 if (!test.round_error_ok || actual == test.expected) { |
|
1910 // In most cases, we'll get an exact match, but in some cases |
|
1911 // there can be a small amount of rounding error. |
|
1912 is(actual, test.expected, |
|
1913 "interpolation of transitions: " + test.start + " to " + test.end); |
|
1914 } else { |
|
1915 function s(mat) { |
|
1916 return mat.match(matrix_re).slice(1,7); |
|
1917 } |
|
1918 var pass = true; |
|
1919 var actual_split = s(actual); |
|
1920 var expected_split = s(test.expected); |
|
1921 for (var i = 0; i < 6; ++i) { |
|
1922 // Allow differences of 1 at the sixth decimal place, and allow |
|
1923 // a drop extra for floating point error from the subtraction. |
|
1924 if (Math.abs(Number(actual_split[i]) - Number(expected_split[i])) > |
|
1925 0.0000011) { |
|
1926 pass = false; |
|
1927 } |
|
1928 } |
|
1929 ok(pass, |
|
1930 "interpolation of transitions: " + test.start + " to " + test.end + |
|
1931 ": " + actual + " should approximately equal " + test.expected); |
|
1932 } |
|
1933 } |
|
1934 |
|
1935 // FIXME: should perhaps test that no clamping occurs |
|
1936 |
|
1937 // These tests check the computed value 2/3 of the way through the transition |
|
1938 OMTAdiv.style.setProperty("transition-duration", "300s", ""); |
|
1939 OMTAdiv.style.setProperty("transition-timing-function", "linear", ""); |
|
1940 window.requestAnimationFrame(nextAsyncTransformTest); |
|
1941 } |
|
1942 |
|
1943 function nextAsyncTransformTest() |
|
1944 { |
|
1945 var test = transformTests[transformTestIndex]; |
|
1946 |
|
1947 if (transformTestIndex >= transformTests.length) { |
|
1948 window.requestAnimationFrame(asyncOpacityTest); |
|
1949 return; |
|
1950 } |
|
1951 |
|
1952 OMTAdiv.style.setProperty("transition-property", "none", ""); |
|
1953 OMTAdiv.style.setProperty("transform", test.start, ""); |
|
1954 OMTACs.getPropertyValue("transform"); |
|
1955 OMTAdiv.style.setProperty("transition-property", "transform", ""); |
|
1956 OMTAdiv.style.setProperty("transform", test.end, ""); |
|
1957 OMTACs.getPropertyValue("transform"); |
|
1958 |
|
1959 window.requestAnimationFrame(checkAsyncTransformTest); |
|
1960 } |
|
1961 |
|
1962 function checkAsyncTransformTest() { |
|
1963 function s(matrix) { |
|
1964 return matrix.replace(/^\w*\(/, '').replace(')','').split(/\s*,\s*/); |
|
1965 } |
|
1966 winUtils.advanceTimeAndRefresh(200000); |
|
1967 var test = transformTests[transformTestIndex]; |
|
1968 var async_transform = winUtils.getOMTAOrComputedStyle(OMTAdiv, "transform"); |
|
1969 var computed_transform = OMTACs.getPropertyValue("transform"); |
|
1970 var async_split = s(async_transform); |
|
1971 var cs_split = s(computed_transform); |
|
1972 var pass = true; |
|
1973 for (var j = 0; j < 16; ++j) { |
|
1974 var epsilon = test.big_omta_round_error ? 0.1 : 0.0001; |
|
1975 if (Math.abs(Number(async_split[j]) - Number(cs_split[j])) > epsilon) { |
|
1976 pass = false; |
|
1977 } |
|
1978 } |
|
1979 ok(pass, |
|
1980 "interpolation of transitions: " + test.start + " to " + test.end + |
|
1981 ": OMTA - " + async_transform + ", computed style - " + computed_transform); |
|
1982 transformTestIndex++; |
|
1983 winUtils.restoreNormalRefresh(); |
|
1984 window.requestAnimationFrame(nextAsyncTransformTest); |
|
1985 } |
|
1986 |
|
1987 function asyncOpacityTest() { |
|
1988 OMTAdiv.style.setProperty("transition-property", "none", ""); |
|
1989 OMTAdiv.style.setProperty("opacity", 0, ""); |
|
1990 OMTACs.getPropertyValue("opacity"); |
|
1991 OMTAdiv.style.setProperty("transition-property", "opacity", ""); |
|
1992 OMTAdiv.style.setProperty("opacity", 1, ""); |
|
1993 OMTACs.getPropertyValue("opacity"); |
|
1994 |
|
1995 window.requestAnimationFrame(checkAsyncOpacityTest); |
|
1996 } |
|
1997 |
|
1998 function checkAsyncOpacityTest() { |
|
1999 winUtils.advanceTimeAndRefresh(200000); |
|
2000 var async_opacity = winUtils.getOMTAOrComputedStyle(OMTAdiv, "opacity"); |
|
2001 var computed_opacity = OMTACs.getPropertyValue("opacity"); |
|
2002 is(async_opacity, computed_opacity, |
|
2003 "Async animated opacity should match computed opacity"); |
|
2004 winUtils.restoreNormalRefresh(); |
|
2005 OMTAdiv.style.removeProperty("transition"); |
|
2006 SimpleTest.finish(); |
|
2007 } |
|
2008 |
|
2009 </script> |
|
2010 </pre> |
|
2011 </body> |
|
2012 </html> |