widget/tests/window_wheeltransaction.xul

branch
TOR_BUG_9701
changeset 10
ac0c01689b40
equal deleted inserted replaced
-1:000000000000 0:d7cee55e364e
1 <?xml version="1.0"?>
2 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
3 <window title="Wheel scroll tests"
4 width="600" height="600"
5 onload="onload();"
6 onunload="onunload();"
7 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
8
9 <script type="application/javascript"
10 src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js" />
11
12 <body xmlns="http://www.w3.org/1999/xhtml">
13 <style type="text/css">
14 #rootview {
15 overflow: auto;
16 width: 400px;
17 height: 400px;
18 border: 1px solid;
19 }
20 #container {
21 overflow: auto;
22 width: 600px;
23 height: 600px;
24 }
25 #rootview pre {
26 margin: 20px 0 20px 20px;
27 padding: 0;
28 overflow: auto;
29 display: block;
30 width: 100px;
31 height: 100.5px;
32 font-size: 16px;
33 }
34 </style>
35 <div id="rootview" onscroll="onScrollView(event);">
36 <div id="container">
37 <pre id="subview1" onscroll="onScrollView(event);">
38 Text. Text. Text. Text. Text. Text. Text. Text. Text. Text. Text.
39 Text. Text. Text. Text. Text. Text. Text. Text. Text. Text. Text.
40 Text. Text. Text. Text. Text. Text. Text. Text. Text. Text. Text.
41 Text. Text. Text. Text. Text. Text. Text. Text. Text. Text. Text.
42 Text. Text. Text. Text. Text. Text. Text. Text. Text. Text. Text.
43 Text. Text. Text. Text. Text. Text. Text. Text. Text. Text. Text.
44 Text. Text. Text. Text. Text. Text. Text. Text. Text. Text. Text.
45 Text. Text. Text. Text. Text. Text. Text. Text. Text. Text. Text.
46 Text. Text. Text. Text. Text. Text. Text. Text. Text. Text. Text.
47 Text. Text. Text. Text. Text. Text. Text. Text. Text. Text. Text.
48 </pre>
49 <pre id="subview2" onscroll="onScrollView(event);">
50 Text.
51 Text.
52 Text.
53 Text.
54 Text.
55 Text.
56 Text.
57 Text.
58 Text.
59 Text.
60 </pre>
61 <pre id="subview3" onscroll="onScrollView(event);">
62 Text. Text. Text. Text. Text. Text. Text. Text. Text. Text. Text.
63 </pre>
64 </div>
65 </div>
66 <div id="content" style="display: none">
67 </div>
68 <pre id="test">
69 </pre>
70 </body>
71
72 <script class="testbody" type="application/javascript">
73 <![CDATA[
74
75 function ok(aCondition, aMessage)
76 {
77 window.opener.wrappedJSObject.SimpleTest.ok(aCondition, aMessage);
78 }
79
80 function is(aLeft, aRight, aMessage)
81 {
82 window.opener.wrappedJSObject.SimpleTest.is(aLeft, aRight, aMessage);
83 }
84
85 function isnot(aLeft, aRight, aMessage)
86 {
87 window.opener.wrappedJSObject.SimpleTest.isnot(aLeft, aRight, aMessage);
88 }
89
90 var gCurrentTestListStatus = { nextListIndex: 0 };
91 var gCurrentTest;
92
93 const kListenEvent_None = 0;
94 const kListenEvent_OnScroll = 1;
95 const kListenEvent_OnScrollFailed = 2;
96 const kListenEvent_OnTransactionTimeout = 4;
97 const kListenEvent_All = kListenEvent_OnScroll |
98 kListenEvent_OnScrollFailed |
99 kListenEvent_OnTransactionTimeout;
100 var gLitesnEvents = kListenEvent_None;
101
102 /**
103 * At unexpected transaction timeout, we need to stop *all* timers. But it is
104 * difficult and it can be create more complex testing code. So, we should use
105 * only one timer at one time. For that, we must store the timer id to this
106 * variable. And the functions which may be called via a timer must clear the
107 * current timer by |_clearTimer| function.
108 */
109 var gTimer;
110
111 var gPrefSvc = Components.classes["@mozilla.org/preferences-service;1"].
112 getService(Components.interfaces.nsIPrefBranch);
113 const kPrefSmoothScroll = "general.smoothScroll";
114 const kPrefNameTimeout = "mousewheel.transaction.timeout";
115 const kPrefNameIgnoreMoveDelay = "mousewheel.transaction.ignoremovedelay";
116
117 const kDefaultTimeout = gPrefSvc.getIntPref(kPrefNameTimeout);
118 const kDefaultIgnoreMoveDelay = gPrefSvc.getIntPref(kPrefNameIgnoreMoveDelay);
119
120 gPrefSvc.setBoolPref(kPrefSmoothScroll, false);
121
122 var gTimeout, gIgnoreMoveDelay;
123 var gEnoughForTimeout, gEnoughForIgnoreMoveDelay;
124
125 function setTimeoutPrefs(aTimeout, aIgnoreMoveDelay)
126 {
127 gPrefSvc.setIntPref(kPrefNameTimeout, aTimeout);
128 gPrefSvc.setIntPref(kPrefNameIgnoreMoveDelay, aIgnoreMoveDelay);
129 gTimeout = aTimeout;
130 gIgnoreMoveDelay = aIgnoreMoveDelay;
131 gEnoughForTimeout = gTimeout * 2;
132 gEnoughForIgnoreMoveDelay = gIgnoreMoveDelay * 1.2;
133 }
134
135 function resetTimeoutPrefs()
136 {
137 if (gTimeout == kDefaultTimeout)
138 return;
139 setTimeoutPrefs(kDefaultTimeout, kDefaultIgnoreMoveDelay);
140 initTestList();
141 }
142
143 function growUpTimeoutPrefs()
144 {
145 if (gTimeout != kDefaultTimeout)
146 return;
147 setTimeoutPrefs(5000, 1000);
148 initTestList();
149 }
150
151 // setting enough time for testing.
152 gPrefSvc.setIntPref(kPrefNameTimeout, gTimeout);
153 gPrefSvc.setIntPref(kPrefNameIgnoreMoveDelay, gIgnoreMoveDelay);
154
155 var gRootView = document.getElementById("rootview");
156 var gSubView1 = document.getElementById("subview1");
157 var gSubView2 = document.getElementById("subview2");
158 var gSubView3 = document.getElementById("subview3");
159
160 gRootView.addEventListener("MozMouseScrollFailed", onMouseScrollFailed, false);
161 gRootView.addEventListener("MozMouseScrollTransactionTimeout",
162 onTransactionTimeout, false);
163
164 function finish()
165 {
166 window.close();
167 }
168
169 function onload()
170 {
171 runNextTestList();
172 }
173
174 function onunload()
175 {
176 resetTimeoutPrefs();
177 gPrefSvc.clearUserPref(kPrefSmoothScroll);
178 disableNonTestMouseEvents(false);
179 window.opener.wrappedJSObject.SimpleTest.finish();
180 }
181
182 const kSubView1Offset = { x: 20, y: 20 };
183 const kSubView2Offset = { x: 20, y: 20 + 100 + 20 };
184 const kSubView3Offset = { x: 20, y: 20 + (100 + 20) * 2 };
185
186 function _getSubViewTestPtForV(aPt)
187 {
188 return { x: aPt.x + 10, y: aPt.y + 10 };
189 }
190
191 const kPtInRootViewForV = { x: kSubView1Offset.x + 10,
192 y: kSubView1Offset.y - 10 };
193 const kPtInSubView1ForV = _getSubViewTestPtForV(kSubView1Offset);
194 const kPtInSubView2ForV = _getSubViewTestPtForV(kSubView2Offset);
195 const kPtInSubView3ForV = _getSubViewTestPtForV(kSubView3Offset);
196
197 function _convertTestPtForH(aPt)
198 {
199 return { x: aPt.y, y: aPt.x };
200 }
201
202 const kPtInRootViewForH = _convertTestPtForH(kPtInRootViewForV);
203 const kPtInSubView1ForH = _convertTestPtForH(kPtInSubView1ForV);
204 const kPtInSubView2ForH = _convertTestPtForH(kPtInSubView2ForV);
205 const kPtInSubView3ForH = _convertTestPtForH(kPtInSubView3ForV);
206
207 /**
208 * Define the tests here:
209 * Scrolls are processed async always. Therefore, we need to call all tests
210 * by timer. gTestLists is array of testing lists. In other words, an item
211 * of gTestList is a group of one or more testing. Each items has following
212 * properties:
213 *
214 * - retryWhenTransactionTimeout
215 * The testing of wheel transaction might be fialed randomly by
216 * timeout. Then, automatically the failed test list will be retested
217 * automatically only this number of times.
218 *
219 * - steps
220 * This property is array of testing. Each steps must have following
221 * properties at least.
222 *
223 * - func
224 * This property means function which will be called via
225 * |setTimeout|. The function cannot have params. If you need
226 * some additional parameters, you can specify some original
227 * properties for the test function. If you do so, you should
228 * document it in the testing function.
229 * - delay
230 * This property means delay time until the function to be called.
231 * I.e., the value used for the second param of |setTimeout|.
232 *
233 * And also you need one more property when you call a testing function.
234 *
235 * - description
236 * This property is description of the test. This is used for
237 * logging.
238 *
239 * At testing, you can access to current step via |gCurrentTest|.
240 */
241
242 var gTestLists;
243 function initTestList()
244 {
245 gTestLists = [
246 /**************************************************************************
247 * Continuous scrolling test for |gRootView|
248 * |gRootView| has both scrollbars and it has three children which are
249 * |gSubView1|, |gSubView2| and |gSubView3|. They have scrollbars. If
250 * the current transaction targets |gRootView|, other children should not
251 * be scrolled even if the wheel events are fired on them.
252 **************************************************************************/
253 { retryWhenTransactionTimeout: 5,
254 steps: [
255 // Vertical case
256 { func: initElements, delay: 0, forVertical: true,
257 description: "initElements" },
258 { func: clearWheelTransaction, delay: 0,
259 description: "clearWheelTransaction" },
260 // Vertical wheel events should scroll |gRootView| even if the position
261 // of wheel events in a child view which has scrollbar.
262 { func: testContinuousScroll, delay: 0, offset: kPtInRootViewForV,
263 isForward: true, isVertical: true, expectedView: gRootView,
264 description: "Continuous scrolling test for root view (vertical/forward)" },
265 { func: testContinuousScroll, delay: 0, offset: kPtInRootViewForV,
266 isForward: false, isVertical: true, expectedView: gRootView,
267 description: "Continuous scrolling test for root view (vertical/backward)" }
268 ]
269 },
270
271
272 { retryWhenTransactionTimeout: 5,
273 steps: [
274 // Horizontal case
275 { func: initElements, delay: 0, forVertical: false,
276 description: "initElements" },
277 { func: clearWheelTransaction, delay: 0,
278 description: "clearWheelTransaction" },
279 // Horizontal wheel events should scroll |gRootView| even if the
280 // position of wheel events in a child view which has scrollbar.
281 { func: testContinuousScroll, delay: 0, offset: kPtInRootViewForH,
282 isForward: true, isVertical: false, expectedView: gRootView,
283 description: "Continuous scrolling test for root view (horizontal/forward)" },
284 { func: testContinuousScroll, delay: 0, offset: kPtInRootViewForH,
285 isForward: false, isVertical: false, expectedView: gRootView,
286 description: "Continuous scrolling test for root view (horizontal/backward)" }
287 ]
288 },
289
290
291 /**************************************************************************
292 * Continuous scrolling test for |gSubView1|
293 * |gSubView1| has both scrollbars.
294 **************************************************************************/
295 { retryWhenTransactionTimeout: 5,
296 steps: [
297 // Vertical case
298 { func: initElements, delay: 0, forVertical: true,
299 description: "initElements" },
300 { func: clearWheelTransaction, delay: 0,
301 description: "clearWheelTransaction" },
302 // Vertical wheel events should scroll |gSubView1|.
303 { func: testContinuousScroll, delay: 0, offset: kPtInSubView1ForV,
304 isForward: true, isVertical: true, expectedView: gSubView1,
305 description: "Continuous scrolling test for sub view 1 (vertical/forward)" },
306 { func: testContinuousScroll, delay: 0, offset: kPtInSubView1ForV,
307 isForward: false, isVertical: true, expectedView: gSubView1,
308 description: "Continuous scrolling test for sub view 1 (vertical/backward)" }
309 ]
310 },
311
312
313 { retryWhenTransactionTimeout: 5,
314 steps: [
315 // Horizontal case
316 { func: initElements, delay: 0, forVertical: false,
317 description: "initElements" },
318 { func: clearWheelTransaction, delay: 0,
319 description: "clearWheelTransaction" },
320 // Horitontal wheel events should scroll |gSubView1|.
321 { func: testContinuousScroll, delay: 0, offset: kPtInSubView1ForH,
322 isForward: true, isVertical: false, expectedView: gSubView1,
323 description: "Continuous scrolling test for sub view 1 (horizontal/forward)" },
324 { func: testContinuousScroll, delay: 0, offset: kPtInSubView1ForH,
325 isForward: false, isVertical: false, expectedView: gSubView1,
326 description: "Continuous scrolling test for sub view 1 (horizontal/backward)" }
327 ]
328 },
329
330
331 /**************************************************************************
332 * Continuous scrolling test for |gSubView2|
333 * |gSubView2| has only vertical scrollbar.
334 **************************************************************************/
335 { retryWhenTransactionTimeout: 5,
336 steps: [
337 // Vertical case
338 { func: initElements, delay: 0, forVertical: true,
339 description: "initElements" },
340 { func: clearWheelTransaction, delay: 0,
341 description: "clearWheelTransaction" },
342 // Vertical wheel events should scroll |gSubView2|.
343 { func: testContinuousScroll, delay: 0, offset: kPtInSubView2ForV,
344 isForward: true, isVertical: true, expectedView: gSubView2,
345 description: "Continuous scrolling test for sub view 2 (vertical/forward)" },
346 { func: testContinuousScroll, delay: 0, offset: kPtInSubView2ForV,
347 isForward: false, isVertical: true, expectedView: gSubView2,
348 description: "Continuous scrolling test for sub view 2 (vertical/backward)" }
349 ]
350 },
351
352
353 { retryWhenTransactionTimeout: 5,
354 steps: [
355 // Horizontal case
356 { func: initElements, delay: 0, forVertical: false,
357 description: "initElements" },
358 { func: clearWheelTransaction, delay: 0,
359 description: "clearWheelTransaction" },
360 // Horizontal wheel events should scroll its nearest scrollable ancestor
361 // view, i.e., it is |gRootView|.
362 { func: testContinuousScroll, delay: 0, offset: kPtInSubView2ForH,
363 isForward: true, isVertical: false, expectedView: gRootView,
364 description: "Continuous scrolling test for sub view 2 (horizontal/forward)" },
365 { func: testContinuousScroll, delay: 0, offset: kPtInSubView2ForH,
366 isForward: false, isVertical: false, expectedView: gRootView,
367 description: "Continuous scrolling test for sub view 2 (horizontal/backward)" }
368 ]
369 },
370
371
372 /**************************************************************************
373 * Continuous scrolling test for |gSubView3|
374 * |gSubView3| has only horizontal scrollbar.
375 **************************************************************************/
376 { retryWhenTransactionTimeout: 5,
377 steps: [
378 // Vertical case
379 { func: initElements, delay: 0, forVertical: true,
380 description: "initElements" },
381 { func: clearWheelTransaction, delay: 0,
382 description: "clearWheelTransaction" },
383 // Vertical wheel events should scroll its nearest scrollable ancestor
384 // view, i.e., it is |gRootView|.
385 { func: testContinuousScroll, delay: 0, offset: kPtInSubView3ForV,
386 isForward: true, isVertical: true, expectedView: gRootView,
387 description: "Continuous scrolling test for sub view 3 (vertical/forward)" },
388 { func: testContinuousScroll, delay: 0, offset: kPtInSubView3ForV,
389 isForward: false, isVertical: true, expectedView: gRootView,
390 description: "Continuous scrolling test for sub view 3 (vertical/backward)" }
391 ]
392 },
393
394
395 { retryWhenTransactionTimeout: 5,
396 steps: [
397 // Horizontal case
398 { func: initElements, delay: 0, forVertical: false,
399 description: "initElements" },
400 { func: clearWheelTransaction, delay: 0,
401 description: "clearWheelTransaction" },
402 // Horitontal wheel events should scroll |gSubView3|.
403 { func: testContinuousScroll, delay: 0, offset: kPtInSubView3ForH,
404 isForward: true, isVertical: false, expectedView: gSubView3,
405 description: "Continuous scrolling test for sub view 3 (horizontal/forward)" },
406 { func: testContinuousScroll, delay: 0, offset: kPtInSubView3ForH,
407 isForward: false, isVertical: false, expectedView: gSubView3,
408 description: "Continuous scrolling test for sub view 3 (horizontal/backward)" }
409 ]
410 },
411
412
413 /**************************************************************************
414 * Don't reset transaction by a different direction wheel event
415 * Even if a wheel event doesn't same direction as last wheel event, the
416 * current transaction should not be reset.
417 **************************************************************************/
418 { retryWhenTransactionTimeout: 5,
419 steps: [
420 // Vertical -> Horizontal
421 { func: initElements, delay: 0, forVertical: true,
422 description: "initElements" },
423 { func: clearWheelTransaction, delay: 0,
424 description: "clearWheelTransaction" },
425 // Create a transaction which targets |gRootView| by a vertical wheel
426 // event.
427 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForV,
428 isForward: true, isVertical: true, expectedView: gRootView,
429 description: "Don't reset transaction by a different direction wheel event (1-1)" },
430 // Scroll back to top-most for easy cursor position specifying.
431 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForV,
432 isForward: false, isVertical: true, expectedView: gRootView,
433 description: "Don't reset transaction by a different direction wheel event (1-2)" },
434 // Send a horizontal wheel event over |gSubView1| but |gRootView| should
435 // be scrolled.
436 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
437 isForward: true, isVertical: false, expectedView: gRootView,
438 canFailRandomly: { possibleView: gSubView1 },
439 description: "Don't reset transaction by a different direction wheel event (1-3)" }
440 ]
441 },
442
443
444 { retryWhenTransactionTimeout: 5,
445 steps: [
446 // Horizontal -> Vertical
447 { func: initElements, delay: 0, forVertical: false,
448 description: "initElements" },
449 { func: clearWheelTransaction, delay: 0,
450 description: "clearWheelTransaction" },
451 // Create a transaction which targets |gRootView| by a horizontal wheel
452 // event.
453 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForH,
454 isForward: true, isVertical: false, expectedView: gRootView,
455 description: "Don't reset transaction by a different direction wheel event (2-1)" },
456 // Scroll back to left-most for easy cursor position specifying.
457 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForH,
458 isForward: false, isVertical: false, expectedView: gRootView,
459 description: "Don't reset transaction by a different direction wheel event (2-2)" },
460 // Send a vertical wheel event over |gSubView1| but |gRootView| should
461 // be scrolled.
462 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForH,
463 isForward: true, isVertical: true, expectedView: gRootView,
464 canFailRandomly: { possibleView: gSubView1 },
465 description: "Don't reset transaction by a different direction wheel event (2-3)" }
466 ]
467 },
468
469
470 /**************************************************************************
471 * Don't reset transaction even if a wheel event cannot scroll
472 * Even if a wheel event cannot scroll to specified direction in the
473 * current target view, the transaction should not be reset. E.g., there
474 * are some devices which can scroll obliquely. If so, probably, users
475 * cannot input only intended direction.
476 **************************************************************************/
477 { retryWhenTransactionTimeout: 5,
478 steps: [
479 // A view only has vertical scrollbar case.
480 { func: initElements, delay: 0, forVertical: true,
481 description: "initElements" },
482 { func: clearWheelTransaction, delay: 0,
483 description: "clearWheelTransaction" },
484 // Create a transaction which targets |gSubView2|.
485 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView2ForV,
486 isForward: true, isVertical: true, expectedView: gSubView2,
487 description: "Don't reset transaction even if a wheel event cannot scroll (1-1)" },
488 // |gSubView2| doesn't have horizontal scrollbar but should not scroll
489 // any views.
490 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView2ForV,
491 isForward: true, isVertical: false, expectedView: null,
492 description: "Don't reset transaction even if a wheel event cannot scroll (1-2)" }
493 ]
494 },
495
496
497 { retryWhenTransactionTimeout: 5,
498 steps: [
499 // A view only has horizontal scrollbar case.
500 { func: initElements, delay: 0, forVertical: true,
501 description: "initElements" },
502 { func: clearWheelTransaction, delay: 0,
503 description: "clearWheelTransaction" },
504 // Create a transaction which targets |gSubView3|.
505 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView3ForV,
506 isForward: true, isVertical: false, expectedView: gSubView3,
507 description: "Don't reset transaction even if a wheel event cannot scroll (2-1)" },
508 // |gSubView3| doesn't have vertical scrollbar but should not scroll any
509 // views.
510 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView3ForV,
511 isForward: true, isVertical: true, expectedView: null,
512 description: "Don't reset transaction even if a wheel event cannot scroll (2-2)" }
513 ]
514 },
515
516
517 /**************************************************************************
518 * Reset transaction by mouse down/mouse up events
519 * Mouse down and mouse up events should cause resetting the current
520 * transaction.
521 **************************************************************************/
522 { retryWhenTransactionTimeout: 5,
523 steps: [
524 // Vertical case
525 { func: initElements, delay: 0, forVertical: true,
526 description: "initElements" },
527 { func: clearWheelTransaction, delay: 0,
528 description: "clearWheelTransaction" },
529 // Create a transaction which targets |gRootView|.
530 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForV,
531 isForward: true, isVertical: true, expectedView: gRootView,
532 description: "Reset transaction by mouse down/mouse up events (v-1)" },
533 // Scroll back to top-most for easy cursor position specifying.
534 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForV,
535 isForward: false, isVertical: true, expectedView: gRootView,
536 description: "Reset transaction by mouse down/mouse up events (v-2)" },
537 // Send mouse button events which should reset the current transaction.
538 // So, the next wheel event should scroll |gSubView1|.
539 { func: sendMouseButtonEvents, delay: 0,
540 description: "sendMouseButtonEvents" },
541 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
542 isForward: true, isVertical: true, expectedView: gSubView1,
543 description: "Reset transaction by mouse down/mouse up events (v-3)" }
544 ]
545 },
546
547
548 { retryWhenTransactionTimeout: 5,
549 steps: [
550 // Horizontal case
551 { func: initElements, delay: 0, forVertical: false,
552 description: "initElements" },
553 { func: clearWheelTransaction, delay: 0,
554 description: "clearWheelTransaction" },
555 // Create a transaction which targets |gRootView|.
556 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForH,
557 isForward: true, isVertical: false, expectedView: gRootView,
558 description: "Reset transaction by mouse down/mouse up events (h-1)" },
559 // Scroll back to left-most for easy cursor position specifying.
560 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForH,
561 isForward: false, isVertical: false, expectedView: gRootView,
562 description: "Reset transaction by mouse down/mouse up events (h-2)" },
563 // Send mouse button events which should reset the current transaction.
564 // So, the next wheel event should scroll |gSubView1|.
565 { func: sendMouseButtonEvents, delay: 0,
566 description: "sendMouseButtonEvents" },
567 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForH,
568 isForward: true, isVertical: false, expectedView: gSubView1,
569 description: "Reset transaction by mouse down/mouse up events (h-3)" }
570 ]
571 },
572
573
574 /**************************************************************************
575 * Reset transaction by a key event
576 * A key event should cause resetting the current transaction.
577 **************************************************************************/
578 { retryWhenTransactionTimeout: 5,
579 steps: [
580 // Vertical case
581 { func: initElements, delay: 0, forVertical: true,
582 description: "initElements" },
583 { func: clearWheelTransaction, delay: 0,
584 description: "clearWheelTransaction" },
585 // Create a transaction which targets |gRootView|.
586 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForV,
587 isForward: true, isVertical: true, expectedView: gRootView,
588 description: "Reset transaction by a key event (v-1)" },
589 // Scroll back to top-most for easy cursor position specifying.
590 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForV,
591 isForward: false, isVertical: true, expectedView: gRootView,
592 description: "Reset transaction by a key event (v-2)" },
593 // Send a key event which should reset the current transaction. So, the
594 // next wheel event should scroll |gSubView1|.
595 { func: sendKeyEvents, delay: 0, key: "a",
596 description: "sendKeyEvents" },
597 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
598 isForward: true, isVertical: true, expectedView: gSubView1,
599 description: "Reset transaction by a key event (v-3)" }
600 ]
601 },
602
603
604 { retryWhenTransactionTimeout: 5,
605 steps: [
606 // Horizontal case
607 { func: initElements, delay: 0, forVertical: false,
608 description: "initElements" },
609 { func: clearWheelTransaction, delay: 0,
610 description: "clearWheelTransaction" },
611 // Create a transaction which targets |gRootView|.
612 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForH,
613 isForward: true, isVertical: false, expectedView: gRootView,
614 description: "Reset transaction by a key event (h-1)" },
615 // Scroll back to left-most for easy cursor position specifying.
616 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForH,
617 isForward: false, isVertical: false, expectedView: gRootView,
618 description: "Reset transaction by a key event (h-2)" },
619 // Send a key event which should reset the current transaction. So, the
620 // next wheel event should scroll |gSubView1|.
621 { func: sendKeyEvents, delay: 0, key: "a",
622 description: "sendKeyEvents" },
623 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForH,
624 isForward: true, isVertical: false, expectedView: gSubView1,
625 description: "Reset transaction by a key event (h-3)" }
626 ]
627 },
628
629
630 /**************************************************************************
631 * Reset transaction by a mouse move event
632 * A mouse move event can cause reseting the current transaction even if
633 * mouse cursor is inside the target view of current transaction. Only
634 * when a wheel event is fired after |gIgnoreMoveDelay| milliseconds since
635 * the first mouse move event from last wheel event, the transaction
636 * should be reset.
637 **************************************************************************/
638 { retryWhenTransactionTimeout: 5,
639 steps: [
640 // Vertical case
641 { func: initElements, delay: 0, forVertical: true,
642 description: "initElements" },
643 { func: clearWheelTransaction, delay: 0,
644 description: "clearWheelTransaction" },
645 // Create a transaction which targets |gRootView|.
646 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForV,
647 isForward: true, isVertical: true, expectedView: gRootView,
648 description: "Reset transaction by a mouse move event (v-1)" },
649 // Scroll back to top-most for easy cursor position specifying.
650 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForV,
651 isForward: false, isVertical: true, expectedView: gRootView,
652 description: "Reset transaction by a mouse move event (v-2)" },
653 // Send a mouse move event immediately after last wheel event, then,
654 // current transaction should be kept.
655 { func: sendMouseMoveEvent, delay: 0, offset: kPtInSubView1ForV,
656 description: "sendMouseMoveEvent" },
657 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
658 isForward: true, isVertical: true, expectedView: gRootView,
659 canFailRandomly: { possibleView: gSubView1 },
660 description: "Reset transaction by a mouse move event (v-3)" },
661 // Scroll back to top-most for easy cursor position specifying.
662 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
663 isForward: false, isVertical: true, expectedView: gRootView,
664 canFailRandomly: { possibleView: gSubView1 },
665 description: "Reset transaction by a mouse move event (v-4)" },
666 // Send a mouse move event after |gIgnoreMoveDelay| milliseconds since
667 // last wheel event, then, current transaction should be kept.
668 { func: sendMouseMoveEvent, delay: gEnoughForIgnoreMoveDelay,
669 offset: kPtInSubView1ForV,
670 description: "sendMouseMoveEvent" },
671 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
672 isForward: true, isVertical: true, expectedView: gRootView,
673 canFailRandomly: { possibleView: gSubView1 },
674 description: "Reset transaction by a mouse move event (v-5)" },
675 // Scroll back to top-most for easy cursor position specifying.
676 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
677 isForward: false, isVertical: true, expectedView: gRootView,
678 canFailRandomly: { possibleView: gSubView1 },
679 description: "Reset transaction by a mouse move event (v-6)" },
680 // Send a wheel event after |gIgnoreMoveDelay| milliseconds since last
681 // mouse move event but it is fired immediately after the last wheel
682 // event, then, current transaction should be kept.
683 { func: sendMouseMoveEvent, delay: 0, offset: kPtInSubView1ForV,
684 description: "sendMouseMoveEvent" },
685 { func: testOneTimeScroll, delay: gEnoughForIgnoreMoveDelay,
686 offset: kPtInSubView1ForV,
687 isForward: true, isVertical: true, expectedView: gRootView,
688 canFailRandomly: { possibleView: gSubView1 },
689 description: "Reset transaction by a mouse move event (v-7)" },
690 // Scroll back to top-most for easy cursor position specifying.
691 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
692 isForward: false, isVertical: true, expectedView: gRootView,
693 canFailRandomly: { possibleView: gSubView1 },
694 description: "Reset transaction by a mouse move event (v-8)" },
695 // Send a wheel event after |gIgnoreMoveDelay| milliseconds have passed
696 // since last mouse move event which is fired after |gIgnoreMoveDelay|
697 // milliseconds since last wheel event, then, current transaction should
698 // be reset.
699 { func: sendMouseMoveEvent, delay: gEnoughForIgnoreMoveDelay,
700 offset: kPtInSubView1ForV,
701 description: "sendMouseMoveEvent" },
702 { func: testOneTimeScroll, delay: gEnoughForIgnoreMoveDelay,
703 offset: kPtInSubView1ForV,
704 isForward: true, isVertical: true, expectedView: gSubView1,
705 canFailRandomly: { possibleView: gRootView },
706 description: "Reset transaction by a mouse move event (v-9)" }
707 ]
708 },
709
710
711 { retryWhenTransactionTimeout: 5,
712 steps: [
713 // Horizontal case
714 { func: initElements, delay: 0, forVertical: false,
715 description: "initElements" },
716 { func: clearWheelTransaction, delay: 0,
717 description: "clearWheelTransaction" },
718 // Create a transaction which targets |gRootView|.
719 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForH,
720 isForward: true, isVertical: false, expectedView: gRootView,
721 canFailRandomly: { possibleView: gSubView1 },
722 description: "Reset transaction by a mouse move event (h-1)" },
723 // Scroll back to top-most for easy cursor position specifying.
724 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForH,
725 isForward: false, isVertical: false, expectedView: gRootView,
726 canFailRandomly: { possibleView: gSubView1 },
727 description: "Reset transaction by a mouse move event (h-2)" },
728 // Send a mouse move event immediately after last wheel event, then,
729 // current transaction should be kept.
730 { func: sendMouseMoveEvent, delay: 0, offset: kPtInSubView1ForH,
731 description: "sendMouseMoveEvent" },
732 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForH,
733 isForward: true, isVertical: false, expectedView: gRootView,
734 canFailRandomly: { possibleView: gSubView1 },
735 description: "Reset transaction by a mouse move event (h-3)" },
736 // Scroll back to top-most for easy cursor position specifying.
737 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForH,
738 isForward: false, isVertical: false, expectedView: gRootView,
739 canFailRandomly: { possibleView: gSubView1 },
740 description: "Reset transaction by a mouse move event (h-4)" },
741 // Send a mouse move event after |gIgnoreMoveDelay| milliseconds since
742 // last wheel event, then, current transaction should be kept.
743 { func: sendMouseMoveEvent, delay: gEnoughForIgnoreMoveDelay,
744 offset: kPtInSubView1ForH,
745 description: "sendMouseMoveEvent" },
746 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForH,
747 isForward: true, isVertical: false, expectedView: gRootView,
748 canFailRandomly: { possibleView: gSubView1 },
749 description: "Reset transaction by a mouse move event (h-5)" },
750 // Scroll back to top-most for easy cursor position specifying.
751 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForH,
752 isForward: false, isVertical: false, expectedView: gRootView,
753 canFailRandomly: { possibleView: gSubView1 },
754 description: "Reset transaction by a mouse move event (h-6)" },
755 // Send a wheel event after |gIgnoreMoveDelay| milliseconds since last
756 // mouse move event but it is fired immediately after the last wheel
757 // event, then, current transaction should be kept.
758 { func: sendMouseMoveEvent, delay: 0, offset: kPtInSubView1ForH,
759 description: "sendMouseMoveEvent" },
760 { func: testOneTimeScroll, delay: gEnoughForIgnoreMoveDelay,
761 offset: kPtInSubView1ForH,
762 isForward: true, isVertical: false, expectedView: gRootView,
763 canFailRandomly: { possibleView: gSubView1 },
764 description: "Reset transaction by a mouse move event (h-7)" },
765 // Scroll back to top-most for easy cursor position specifying.
766 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForH,
767 isForward: false, isVertical: false, expectedView: gRootView,
768 canFailRandomly: { possibleView: gSubView1 },
769 description: "Reset transaction by a mouse move event (h-8)" },
770 // Send a wheel event after |gIgnoreMoveDelay| milliseconds have passed
771 // since last mouse move event which is fired after |gIgnoreMoveDelay|
772 // milliseconds since last wheel event, then, current transaction should
773 // be reset.
774 { func: sendMouseMoveEvent, delay: gEnoughForIgnoreMoveDelay,
775 offset: kPtInSubView1ForH,
776 description: "sendMouseMoveEvent" },
777 { func: testOneTimeScroll, delay: gEnoughForIgnoreMoveDelay,
778 offset: kPtInSubView1ForH,
779 isForward: true, isVertical: false, expectedView: gSubView1,
780 canFailRandomly: { possibleView: gRootView },
781 description: "Reset transaction by a mouse move event (h-9)" }
782 ]
783 },
784
785
786 /**************************************************************************
787 * Reset transaction by a mouse move event on outside of view
788 * When mouse cursor is moved to outside of the current target view, the
789 * transaction should be reset immediately.
790 **************************************************************************/
791 { retryWhenTransactionTimeout: 5,
792 steps: [
793 // Vertical case
794 { func: initElements, delay: 0, forVertical: true,
795 description: "initElements" },
796 { func: clearWheelTransaction, delay: 0,
797 description: "clearWheelTransaction" },
798 // Create a transaction which targets |gSubView1|.
799 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
800 isForward: true, isVertical: true, expectedView: gSubView1,
801 description: "Reset transaction by a mouse move event on outside of view (v-1)" },
802 // Send mouse move event over |gRootView|.
803 { func: sendMouseMoveEvent, delay: 0, offset: kPtInRootViewForV,
804 description: "sendMouseMoveEvent" },
805 // Send Wheel event over |gRootView| which should be scrolled.
806 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForV,
807 isForward: true, isVertical: true, expectedView: gRootView,
808 description: "Reset transaction by a mouse move event on outside of view (v-2)" }
809 ]
810 },
811
812
813 { retryWhenTransactionTimeout: 5,
814 steps: [
815 // Horizontal case
816 { func: initElements, delay: 0, forVertical: false,
817 description: "initElements" },
818 { func: clearWheelTransaction, delay: 0,
819 description: "clearWheelTransaction" },
820 // Create a transaction which targets |gSubView1|.
821 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForH,
822 isForward: true, isVertical: true, expectedView: gSubView1,
823 description: "Reset transaction by a mouse move event on outside of view (h-1)" },
824 // Send mouse move event over |gRootView|.
825 { func: sendMouseMoveEvent, delay: 0, offset: kPtInRootViewForH,
826 description: "sendMouseMoveEvent" },
827 // Send Wheel event over |gRootView| which should be scrolled.
828 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForH,
829 isForward: true, isVertical: true, expectedView: gRootView,
830 description: "Reset transaction by a mouse move event on outside of view (h-2)" }
831 ]
832 },
833
834
835 /**************************************************************************
836 * Timeout test
837 * A view should not be scrolled during another to be transaction for
838 * another view scrolling. However, a wheel event which is sent after
839 * timeout, a view which is under the mouse cursor should be scrolled.
840 **************************************************************************/
841 { retryWhenTransactionTimeout: 5,
842 steps: [
843 // Vertical case
844 { func: initElements, delay: 0, forVertical: true,
845 description: "initElements" },
846 { func: clearWheelTransaction, delay: 0,
847 description: "clearWheelTransaction" },
848 // First, create a transaction which should target the |gRootView|.
849 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForV,
850 isForward: true, isVertical: true, expectedView: gRootView,
851 description: "Timeout test (v-1)" },
852 // Scroll back to top-most for easy cursor position specifying.
853 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForV,
854 isForward: false, isVertical: true, expectedView: gRootView,
855 description: "Timeout test (v-2)" },
856 // A wheel event over |gSubView1| should not scroll it during current
857 // transaction.
858 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
859 isForward: true, isVertical: true, expectedView: gRootView,
860 canFailRandomly: { possibleView: gSubView1 },
861 description: "Timeout test (v-3)" },
862 // Scroll back to top-most again.
863 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
864 isForward: false, isVertical: true, expectedView: gRootView,
865 canFailRandomly: { possibleView: gSubView1 },
866 description: "Timeout test (v-4)" },
867 // A wheel event over |gSubView1| after timeout should scroll
868 // |gSubView1|.
869 { func: testOneTimeScroll, delay: gEnoughForTimeout,
870 offset: kPtInSubView1ForV,
871 isForward: true, isVertical: true, expectedView: gSubView1,
872 isTimeoutTesting: true,
873 description: "Timeout test (v-5)" }
874 ]
875 },
876
877
878 { retryWhenTransactionTimeout: 5,
879 steps: [
880 // Horizontal case
881 { func: initElements, delay: 0, forVertical: false,
882 description: "initElements" },
883 { func: clearWheelTransaction, delay: 0,
884 description: "clearWheelTransaction" },
885 // First, create a transaction which should target the |gRootView|.
886 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForH,
887 isForward: true, isVertical: false, expectedView: gRootView,
888 description: "Timeout test (h-1)" },
889 // Scroll back to left-most for easy cursor position specifying.
890 { func: testOneTimeScroll, delay: 0, offset: kPtInRootViewForH,
891 isForward: false, isVertical: false, expectedView: gRootView,
892 description: "Timeout test (h-2)" },
893 // A wheel event over |gSubView1| should not scroll it during current
894 // transaction.
895 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForH,
896 isForward: true, isVertical: false, expectedView: gRootView,
897 canFailRandomly: { possibleView: gSubView1 },
898 description: "Timeout test (h-3)" },
899 // Scroll back to left-most again.
900 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForH,
901 isForward: false, isVertical: false, expectedView: gRootView,
902 canFailRandomly: { possibleView: gSubView1 },
903 description: "Timeout test (h-4)" },
904 // A wheel event over |gSubView1| after timeout should scroll
905 // |gSubView1|.
906 { func: testOneTimeScroll, delay: gEnoughForTimeout,
907 offset: kPtInSubView1ForH,
908 isForward: true, isVertical: false, expectedView: gSubView1,
909 isTimeoutTesting: true,
910 description: "Timeout test (h-5)" }
911 ]
912 },
913
914
915 /**************************************************************************
916 * Timeout test even with many wheel events
917 * This tests whether timeout is occurred event if wheel events are sent.
918 * The transaction should not be updated by non-scrollable wheel events.
919 **************************************************************************/
920 { retryWhenTransactionTimeout: 5,
921 steps: [
922 // Vertical case
923 { func: initElements, delay: 0, forVertical: true,
924 description: "initElements" },
925 { func: clearWheelTransaction, delay: 0,
926 description: "clearWheelTransaction" },
927 // Scroll |gSubView1| to bottom-most.
928 { func: testContinuousScroll, delay: 0, offset: kPtInSubView1ForV,
929 isForward: true, isVertical: true, expectedView: gSubView1,
930 description: "Timeout test even with many wheel events (v-1)" },
931 // Don't scroll any views before timeout.
932 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
933 isForward: true, isVertical: true, expectedView: null,
934 canFailRandomly: { possibleView: gRootView },
935 description: "Timeout test even with many wheel events (v-2)" },
936 // Recreate a transaction which is scrolling |gRootView| after time out.
937 { func: testRestartScroll, delay: 0, offset: kPtInSubView1ForV,
938 isForward: true, isVertical: true, expectedView: gRootView,
939 description: "Timeout test even with many wheel events (v-3)" }
940 ]
941 },
942
943
944 { retryWhenTransactionTimeout: 5,
945 steps: [
946 // Horizontal case
947 { func: initElements, delay: 0, forVertical: false,
948 description: "initElements" },
949 { func: clearWheelTransaction, delay: 0,
950 description: "clearWheelTransaction" },
951 // Scroll |gSubView1| to right-most.
952 { func: testContinuousScroll, delay: 0, offset: kPtInSubView1ForH,
953 isForward: true, isVertical: false, expectedView: gSubView1,
954 description: "Timeout test even with many wheel events (h-1)" },
955 // Don't scroll any views before timeout.
956 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForH,
957 isForward: true, isVertical: false, expectedView: null,
958 canFailRandomly: { possibleView: gRootView },
959 description: "Timeout test even with many wheel events (h-2)" },
960 // Recreate a transaction which is scrolling |gRootView| after time out.
961 { func: testRestartScroll, delay: 0, offset: kPtInSubView1ForH,
962 isForward: true, isVertical: false, expectedView: gRootView,
963 description: "Timeout test even with many wheel events (h-3)" }
964 ]
965 },
966
967
968 /**************************************************************************
969 * Very large scrolling wheel event
970 * If the delta value is larger than the scrolling page size, it should be
971 * scrolled only one page instead of the delta value.
972 **************************************************************************/
973 { retryWhenTransactionTimeout: 5,
974 steps: [
975 { func: initElements, delay: 0, forVertical: true,
976 description: "initElements" },
977 { func: clearWheelTransaction, delay: 0,
978 description: "clearWheelTransaction" },
979 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
980 isForward: true, isVertical: true, expectedView: gSubView1,
981 delta: 5000,
982 description: "Very large delta scrolling (v-1)" },
983 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
984 isForward: true, isVertical: true, expectedView: gSubView1,
985 delta: 5000,
986 description: "Very large delta scrolling (v-2)" },
987 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
988 isForward: true, isVertical: false, expectedView: gSubView1,
989 delta: 5000,
990 description: "Very large delta scrolling (h-1)" },
991 { func: testOneTimeScroll, delay: 0, offset: kPtInSubView1ForV,
992 isForward: true, isVertical: false, expectedView: gSubView1,
993 delta: 5000,
994 description: "Very large delta scrolling (h-2)" }
995 ]
996 }
997 ];
998 }
999
1000 /******************************************************************************
1001 * Actions for preparing tests
1002 ******************************************************************************/
1003
1004 function initElements()
1005 {
1006 _clearTimer();
1007
1008 function resetScrollPosition(aElement)
1009 {
1010 aElement.scrollTop = 0;
1011 aElement.scrollLeft = 0;
1012 }
1013
1014 function initInRootView(aElement, aPt)
1015 {
1016 aElement.offset =
1017 gCurrentTest.forVertical ? aPt : { x: aPt.y, y: aPt.x };
1018 }
1019
1020 const kDisplay = gCurrentTest.forVertical ? "block" : "inline-block";
1021 gSubView1.style.display = kDisplay;
1022 gSubView2.style.display = kDisplay;
1023 gSubView3.style.display = kDisplay;
1024
1025 resetScrollPosition(gRootView);
1026 resetScrollPosition(gSubView1);
1027 resetScrollPosition(gSubView2);
1028 resetScrollPosition(gSubView3);
1029
1030 runNextTestStep();
1031 }
1032
1033 function clearWheelTransaction()
1034 {
1035 _clearTimer();
1036 _clearTransaction();
1037 runNextTestStep();
1038 }
1039
1040 function sendKeyEvents()
1041 {
1042 _clearTimer();
1043 synthesizeKey(gCurrentTest.key, {}, window);
1044 runNextTestStep();
1045 }
1046
1047 function sendMouseButtonEvents()
1048 {
1049 _clearTimer();
1050 synthesizeMouse(gRootView, -1, -1, { type:"mousedown" }, window);
1051 synthesizeMouse(gRootView, -1, -1, { type:"mouseup" }, window);
1052 runNextTestStep();
1053 }
1054
1055 function sendMouseMoveEvent()
1056 {
1057 _clearTimer();
1058 _fireMouseMoveEvent(gCurrentTest.offset);
1059 runNextTestStep();
1060 }
1061
1062 /******************************************************************************
1063 * Utilities for testing functions
1064 ******************************************************************************/
1065
1066 function _clearTransaction()
1067 {
1068 synthesizeMouse(gRootView, -1, -1, { type:"mousedown" }, window);
1069 synthesizeMouse(gRootView, -1, -1, { type:"mouseup" }, window);
1070 }
1071
1072 function _saveScrollPositions()
1073 {
1074 function save(aElement)
1075 {
1076 aElement.prevTop = aElement.scrollTop;
1077 aElement.prevLeft = aElement.scrollLeft;
1078 }
1079 save(gRootView);
1080 save(gSubView1);
1081 save(gSubView2);
1082 save(gSubView3);
1083 }
1084
1085 function _fireMouseMoveEvent(aOffset)
1086 {
1087 synthesizeMouse(gRootView, aOffset.x, aOffset.y, { type:"mousemove" }, window);
1088 }
1089
1090 function _fireWheelScrollEvent(aOffset, aIsVertical, aForward, aDelta)
1091 {
1092 var event = { deltaMode: WheelEvent.DOM_DELTA_LINE };
1093 if (aIsVertical) {
1094 event.deltaY = aForward ? aDelta : -aDelta;
1095 } else {
1096 event.deltaX = aForward ? aDelta : -aDelta;
1097 }
1098 synthesizeWheel(gRootView, aOffset.x, aOffset.y, event, window);
1099 }
1100
1101 function _canScroll(aElement, aIsVertical, aForward)
1102 {
1103 if (aIsVertical) {
1104 if (!aForward)
1105 return aElement.scrollTop > 0;
1106 return aElement.scrollHeight > aElement.scrollTop + aElement.clientHeight;
1107 }
1108 if (!aForward)
1109 return aElement.scrollLeft > 0;
1110 return aElement.scrollWidth > aElement.scrollLeft + aElement.clientWidth;
1111 }
1112
1113 const kNotScrolled = 0;
1114 const kScrolledToTop = 1;
1115 const kScrolledToBottom = 2;
1116 const kScrolledToLeft = 4;
1117 const kScrolledToRight = 8;
1118
1119 const kScrolledVertical = kScrolledToTop | kScrolledToBottom;
1120 const kScrolledHorizontal = kScrolledToLeft | kScrolledToRight;
1121
1122 function _getScrolledState(aElement)
1123 {
1124 var ret = kNotScrolled;
1125 if (aElement.scrollTop != aElement.prevTop) {
1126 ret |= aElement.scrollTop < aElement.prevTop ? kScrolledToTop :
1127 kScrolledToBottom;
1128 }
1129 if (aElement.scrollLeft != aElement.prevLeft) {
1130 ret |= aElement.scrollLeft < aElement.prevLeft ? kScrolledToLeft :
1131 kScrolledToRight;
1132 }
1133 return ret;
1134 }
1135
1136 function _getExpectedScrolledState()
1137 {
1138 return gCurrentTest.isVertical ?
1139 gCurrentTest.isForward ? kScrolledToBottom : kScrolledToTop :
1140 gCurrentTest.isForward ? kScrolledToRight : kScrolledToLeft;
1141 }
1142
1143 function _getScrolledStateText(aScrolledState)
1144 {
1145 if (aScrolledState == kNotScrolled)
1146 return "Not scrolled";
1147
1148 var s = "scrolled to ";
1149 if (aScrolledState & kScrolledVertical) {
1150 s += aScrolledState & kScrolledToTop ? "backward" : "forward";
1151 s += " (vertical)"
1152 if (aScrolledState & kScrolledHorizontal)
1153 s += " and to ";
1154 }
1155 if (aScrolledState & kScrolledHorizontal) {
1156 s += aScrolledState & kScrolledToLeft ? "backward" : "forward";
1157 s += " (horizontal)"
1158 }
1159 return s;
1160 }
1161
1162 function _getCurrentTestList()
1163 {
1164 return gTestLists[gCurrentTestListStatus.nextListIndex - 1];
1165 }
1166
1167 function _clearTimer()
1168 {
1169 clearTimeout(gTimer);
1170 gTimer = 0;
1171 }
1172
1173 /******************************************************************************
1174 * Testing functions
1175 ******************************************************************************/
1176
1177 /**
1178 * Note that testing functions must set following variables:
1179 *
1180 * gCurrentTest.repeatTest: See comment in |continueTest|.
1181 * gCurrentTest.autoRepeatDelay: See comment in |continueTest|.
1182 * gListenScrollEvent: When this is not true, the event handlers ignores the
1183 * events.
1184 */
1185
1186 function testContinuousScroll()
1187 {
1188 /**
1189 * Testing continuous scrolling. This function synthesizes a wheel event. If
1190 * the test was success, this function will be recalled automatically.
1191 * And when a generating wheel event cannot scroll the expected view, this
1192 * function fires the wheel event only one time.
1193 *
1194 * @param gCurrentTest.offset
1195 * The cursor position of firing wheel event. The values are offset
1196 * from |gRootView|.
1197 * @param gCurrentTest.isVertical
1198 * Whether the wheel event is for virtical scrolling or horizontal.
1199 * @param gCurrentTest.isForward
1200 * Whether the wheel event is to forward or to backward.
1201 * @param gCurrentTest.expectedView
1202 * The expected view which will be scrolled by wheel event. This
1203 * value must not be null.
1204 */
1205
1206 _clearTimer();
1207 _saveScrollPositions();
1208 if (!gCurrentTest.expectedView) {
1209 runNextTestStep();
1210 return;
1211 }
1212
1213 gLitesnEvents = kListenEvent_All;
1214 gCurrentTest.repeatTest = true;
1215 gCurrentTest.autoRepeatDelay = 0;
1216
1217 if (!_canScroll(gCurrentTest.expectedView,
1218 gCurrentTest.isVertical, gCurrentTest.isForward)) {
1219 gCurrentTest.expectedView = null;
1220 }
1221 var delta = gCurrentTest.delta ? gCurrentTest.delta : 4;
1222 _fireWheelScrollEvent(gCurrentTest.offset,
1223 gCurrentTest.isVertical, gCurrentTest.isForward, delta);
1224 }
1225
1226 function testOneTimeScroll()
1227 {
1228 /**
1229 * Testing one wheel event. |runNextTestStep| will be called immediately
1230 * after this function by |onScrollView| or |onTimeout|.
1231 *
1232 * @param gCurrentTest.offset
1233 * The cursor position of firing wheel event. The values are offset
1234 * from |gRootView|.
1235 * @param gCurrentTest.isVertical
1236 * Whether the wheel event is for virtical scrolling or horizontal.
1237 * @param gCurrentTest.isForward
1238 * Whether the wheel event is to forward or to backward.
1239 * @param gCurrentTest.expectedView
1240 * The expected view which will be scrolled by wheel event. This
1241 * value can be null. It means any views should not be scrolled.
1242 */
1243
1244 _clearTimer();
1245 _saveScrollPositions();
1246
1247 gLitesnEvents = kListenEvent_All;
1248 gCurrentTest.repeatTest = false;
1249 gCurrentTest.autoRepeatDelay = 0;
1250
1251 var delta = gCurrentTest.delta ? gCurrentTest.delta : 4;
1252 _fireWheelScrollEvent(gCurrentTest.offset,
1253 gCurrentTest.isVertical, gCurrentTest.isForward, delta);
1254 }
1255
1256 function testRestartScroll()
1257 {
1258 /**
1259 * Testing restart to scroll in expected view after timeout from the current
1260 * transaction. This function recall this itself until to success this test
1261 * or timeout from this test.
1262 *
1263 * @param gCurrentTest.offset
1264 * The cursor position of firing wheel event. The values are offset
1265 * from |gRootView|.
1266 * @param gCurrentTest.isVertical
1267 * Whether the wheel event is for virtical scrolling or horizontal.
1268 * @param gCurrentTest.isForward
1269 * Whether the wheel event is to forward or to backward.
1270 * @param gCurrentTest.expectedView
1271 * The expected view which will be scrolled by wheel event. This
1272 * value must not be null.
1273 */
1274
1275 _clearTimer();
1276 _saveScrollPositions();
1277
1278 if (!gCurrentTest.wasTransactionTimeout) {
1279 gCurrentTest.repeatTest = true;
1280 gCurrentTest.autoRepeatDelay = gTimeout / 3;
1281 gLitesnEvents = kListenEvent_All;
1282 gCurrentTest.isTimeoutTesting = true;
1283 if (gCurrentTest.expectedView) {
1284 gCurrentTest.expectedViewAfterTimeout = gCurrentTest.expectedView;
1285 gCurrentTest.expectedView = null;
1286 }
1287 } else {
1288 gCurrentTest.repeatTest = false;
1289 gCurrentTest.autoRepeatDelay = 0;
1290 gLitesnEvents = kListenEvent_All;
1291 gCurrentTest.isTimeoutTesting = false;
1292 gCurrentTest.expectedView = gCurrentTest.expectedViewAfterTimeout;
1293 }
1294
1295 var delta = gCurrentTest.delta ? gCurrentTest.delta : 4;
1296 _fireWheelScrollEvent(gCurrentTest.offset,
1297 gCurrentTest.isVertical, gCurrentTest.isForward, delta);
1298 }
1299
1300 /******************************************************************************
1301 * Event handlers
1302 ******************************************************************************/
1303
1304 function onScrollView(aEvent)
1305 {
1306 /**
1307 * Scroll event handler of |gRootView|, |gSubView1|, |gSubView2| and
1308 * |gSubView3|. If testing is failed, this function cancels all left tests.
1309 * For checking the event is expected, the event firer must call
1310 * |_saveScrollPositions|.
1311 *
1312 * @param gCurrentTest.expectedView
1313 * The expected view which should be scrolled by the wheel event.
1314 * This value can be null. It means any views should not be
1315 * scrolled.
1316 * @param gCurrentTest.isVertical
1317 * The expected view should be scrolled vertical or horizontal.
1318 * @param gCurrentTest.isForward
1319 * The expected view should be scrolled to forward or backward.
1320 * @param gCurrentTest.canFailRandomly
1321 * If this is not undefined, this test can fail by unexpected view
1322 * scrolling which is caused by unexpected timeout. If this is
1323 * defined, |gCurrentTest.possibleView| must be set. If the view is
1324 * same as the event target, the failure can be random. At this
1325 * time, we should retry the current test list.
1326 */
1327
1328 if (!(gLitesnEvents & kListenEvent_OnScroll))
1329 return;
1330
1331 // Now testing a timeout, but a view is scrolled before timeout.
1332 if (gCurrentTest.isTimeoutTesting && !gCurrentTest.wasTransactionTimeout) {
1333 is(aEvent.target.id, "",
1334 "The view scrolled before timeout (the expected view after timeout is " +
1335 gCurrentTest.expectedView ? gCurrentTest.expectedView.id : "null" +
1336 "): " + gCurrentTest.description);
1337 runNextTestList();
1338 return;
1339 }
1340
1341 // Check whether the scrolled event should be fired or not.
1342 if (!gCurrentTest.expectedView) {
1343 is(aEvent.target.id, "",
1344 "no views should be scrolled (" +
1345 _getScrolledStateText(_getScrolledState(aEvent.target)) + "): " +
1346 gCurrentTest.description);
1347 runNextTestList();
1348 return;
1349 }
1350
1351 // Check whether the scrolled view is expected or not.
1352 if (aEvent.target != gCurrentTest.expectedView) {
1353 // If current test can fail randomly and the possible view is same as the
1354 // event target, this failure may be caused by unexpected timeout.
1355 // At this time, we should retry the current tests with slower settings.
1356 if (gCurrentTest.canFailRandomly &&
1357 gCurrentTest.canFailRandomly.possibleView == aEvent.target &&
1358 gCurrentTestListStatus.retryWhenTransactionTimeout > 0) {
1359 gCurrentTestListStatus.retryWhenTransactionTimeout--;
1360 retryCurrentTestList();
1361 return;
1362 }
1363 is(aEvent.target.id, gCurrentTest.expectedView.id,
1364 "wrong view was scrolled: " + gCurrentTest.description);
1365 runNextTestList();
1366 return;
1367 }
1368
1369 // Check whether the scrolling direction is expected or not.
1370 var expectedState = _getExpectedScrolledState();
1371 var currentState = _getScrolledState(aEvent.target);
1372 if (expectedState != currentState) {
1373 is(_getScrolledStateText(currentState),
1374 _getScrolledStateText(expectedState),
1375 "scrolled to wrong direction: " + gCurrentTest.description);
1376 runNextTestList();
1377 return;
1378 }
1379
1380 ok(true, "passed: " + gCurrentTest.description);
1381 continueTest();
1382 }
1383
1384 function onMouseScrollFailed()
1385 {
1386 /**
1387 * Scroll failed event handler. If testing is failed, this function cancels
1388 * all remains of current test-list, and go to next test-list.
1389 *
1390 * NOTE: This event is fired immediately after |_fireWheelScrollEvent|.
1391 *
1392 * @param gCurrentTest.expectedView
1393 * The expected view which should be scrolled by the wheel event.
1394 * This value can be null. It means any views should not be
1395 * scrolled. When this is not null, this event means the test may
1396 * be failed.
1397 */
1398
1399 if (!(gLitesnEvents & kListenEvent_OnScrollFailed))
1400 return;
1401
1402 ok(!gCurrentTest.expectedView,
1403 "failed to scroll on current target: " + gCurrentTest.description);
1404 if (gCurrentTest.expectedView) {
1405 runNextTestList();
1406 return;
1407 }
1408
1409 continueTest();
1410 }
1411
1412 function onTransactionTimeout()
1413 {
1414 /**
1415 * Scroll transaction timeout event handler. If the timeout is unexpected,
1416 * i.e., |gCurrentTest.isTimeoutTesting| is not true, this function retry
1417 * the current test-list. However, if the current test-list failed by timeout
1418 * |gCurrentTestListStatus.retryWhenTransactionTimeout| times already, marking
1419 * to failed the current test-list, and go to next test-list.
1420 *
1421 * @param gCurrentTest.expectedView
1422 * The expected view which should be scrolled by the wheel event.
1423 * This value can be null. It means any views should not be
1424 * scrolled. When this is not null, this event means the testing may
1425 * be failed.
1426 * @param gCurrentTest.isTimeoutTesting
1427 * If this value is true, the current testing have waited this
1428 * event. Otherwise, the testing may be failed.
1429 * @param gCurrentTestListStatus.retryWhenTransactionTimeout
1430 * If |gCurrentTest.isTimeoutTesting| is not true but this event is
1431 * fired, the failure may be randomly. Then, this event handler
1432 * retry to test the current test-list until this cound will be zero.
1433 */
1434
1435 if (!gCurrentTest.isTimeoutTesting &&
1436 gCurrentTestListStatus.retryWhenTransactionTimeout > 0) {
1437 gCurrentTestListStatus.retryWhenTransactionTimeout--;
1438 // retry current test list
1439 retryCurrentTestList();
1440 return;
1441 }
1442
1443 gCurrentTest.wasTransactionTimeout = true;
1444
1445 if (!(gLitesnEvents & kListenEvent_OnTransactionTimeout))
1446 return;
1447
1448 ok(gCurrentTest.isTimeoutTesting,
1449 "transaction timeout: " + gCurrentTest.description);
1450 if (!gCurrentTest.isTimeoutTesting) {
1451 runNextTestList();
1452 return;
1453 }
1454
1455 continueTest();
1456 }
1457
1458 /******************************************************************************
1459 * Main function for this tests
1460 ******************************************************************************/
1461
1462 function runNextTestStep()
1463 {
1464 // When this is first time or the current test list is finised, load next
1465 // test-list.
1466 _clearTimer();
1467 if (!gCurrentTest)
1468 runNextTestList();
1469 else
1470 runTestStepAt(gCurrentTestListStatus.nextStepIndex);
1471 }
1472
1473 function runNextTestList()
1474 {
1475 _clearTimer();
1476
1477 gLitesnEvents = kListenEvent_None;
1478 _clearTransaction();
1479 resetTimeoutPrefs();
1480 if (gCurrentTestListStatus.nextListIndex >= gTestLists.length) {
1481 finish();
1482 return;
1483 }
1484
1485 gCurrentTestListStatus.nextListIndex++;
1486 gCurrentTestListStatus.retryWhenTransactionTimeout =
1487 _getCurrentTestList().retryWhenTransactionTimeout;
1488 runTestStepAt(0);
1489 }
1490
1491 function runTestStepAt(aStepIndex)
1492 {
1493 _clearTimer();
1494
1495 disableNonTestMouseEvents(true);
1496
1497 // load a step of testing.
1498 gCurrentTestListStatus.nextStepIndex = aStepIndex;
1499 gCurrentTest =
1500 _getCurrentTestList().steps[gCurrentTestListStatus.nextStepIndex++];
1501 if (gCurrentTest) {
1502 gCurrentTest.wasTransactionTimeout = false;
1503 gTimer = setTimeout(gCurrentTest.func, gCurrentTest.delay);
1504 } else {
1505 // If current test-list doesn't have more testing, go to next test-list
1506 // after cleaning up the current transaction.
1507 _clearTransaction();
1508 runNextTestList();
1509 }
1510 }
1511
1512 function retryCurrentTestList()
1513 {
1514 _clearTimer();
1515
1516 gLitesnEvents = kListenEvent_None;
1517 _clearTransaction();
1518 ok(true, "WARNING: retry current test-list...");
1519 growUpTimeoutPrefs(); // retry the test with longer timeout settings.
1520 runTestStepAt(0);
1521 }
1522
1523 function continueTest()
1524 {
1525 /**
1526 * This function is called from an event handler when a test succeeded.
1527 *
1528 * @param gCurrentTest.repeatTest
1529 * When this is true, onScrollView calls |gCurrentTest.func|. So,
1530 * same test can repeat. Otherwise, this calls |runNextTestStep|.
1531 * @param gCurrentTest.autoRepeatDelay
1532 * The delay value in milliseconds, this is used to call
1533 * |gCurrentTest.func| via |setTimeout|.
1534 */
1535
1536 _clearTimer();
1537 gLitesnEvents = kListenEvent_OnTransactionTimeout;
1538
1539 // We should call each functions via setTimeout. Because sometimes this test
1540 // is broken by stack overflow.
1541 if (gCurrentTest.repeatTest) {
1542 gTimer = setTimeout(gCurrentTest.func, gCurrentTest.autoRepeatDelay);
1543 } else {
1544 gTimer = setTimeout(runNextTestStep, 0);
1545 }
1546 }
1547
1548 ]]>
1549 </script>
1550
1551 </window>

mercurial