Bumping manifests a=b2g-bump
[gecko.git] / widget / tests / window_wheeltransaction.xul
blob264b5e13d3f54ad809bf314d4632cdbecc4a688d
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">
9 <script type="application/javascript"
10 src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js" />
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;
20 #container {
21 overflow: auto;
22 width: 600px;
23 height: 600px;
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;
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>
72 <script class="testbody" type="application/javascript">
73 <![CDATA[
75 function ok(aCondition, aMessage)
77 window.opener.wrappedJSObject.SimpleTest.ok(aCondition, aMessage);
80 function is(aLeft, aRight, aMessage)
82 window.opener.wrappedJSObject.SimpleTest.is(aLeft, aRight, aMessage);
85 function isnot(aLeft, aRight, aMessage)
87 window.opener.wrappedJSObject.SimpleTest.isnot(aLeft, aRight, aMessage);
90 var gCurrentTestListStatus = { nextListIndex: 0 };
91 var gCurrentTest;
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;
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.
109 var gTimer;
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";
117 const kDefaultTimeout = gPrefSvc.getIntPref(kPrefNameTimeout);
118 const kDefaultIgnoreMoveDelay = gPrefSvc.getIntPref(kPrefNameIgnoreMoveDelay);
120 gPrefSvc.setBoolPref(kPrefSmoothScroll, false);
122 var gTimeout, gIgnoreMoveDelay;
123 var gEnoughForTimeout, gEnoughForIgnoreMoveDelay;
125 function setTimeoutPrefs(aTimeout, aIgnoreMoveDelay)
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;
135 function resetTimeoutPrefs()
137 if (gTimeout == kDefaultTimeout)
138 return;
139 setTimeoutPrefs(kDefaultTimeout, kDefaultIgnoreMoveDelay);
140 initTestList();
143 function growUpTimeoutPrefs()
145 if (gTimeout != kDefaultTimeout)
146 return;
147 setTimeoutPrefs(5000, 1000);
148 initTestList();
151 // setting enough time for testing.
152 gPrefSvc.setIntPref(kPrefNameTimeout, gTimeout);
153 gPrefSvc.setIntPref(kPrefNameIgnoreMoveDelay, gIgnoreMoveDelay);
155 var gRootView = document.getElementById("rootview");
156 var gSubView1 = document.getElementById("subview1");
157 var gSubView2 = document.getElementById("subview2");
158 var gSubView3 = document.getElementById("subview3");
160 gRootView.addEventListener("MozMouseScrollFailed", onMouseScrollFailed, false);
161 gRootView.addEventListener("MozMouseScrollTransactionTimeout",
162 onTransactionTimeout, false);
164 function finish()
166 window.close();
169 function onload()
171 runNextTestList();
174 function onunload()
176 resetTimeoutPrefs();
177 gPrefSvc.clearUserPref(kPrefSmoothScroll);
178 disableNonTestMouseEvents(false);
179 window.opener.wrappedJSObject.SimpleTest.finish();
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 };
186 function _getSubViewTestPtForV(aPt)
188 return { x: aPt.x + 10, y: aPt.y + 10 };
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);
197 function _convertTestPtForH(aPt)
199 return { x: aPt.y, y: aPt.x };
202 const kPtInRootViewForH = _convertTestPtForH(kPtInRootViewForV);
203 const kPtInSubView1ForH = _convertTestPtForH(kPtInSubView1ForV);
204 const kPtInSubView2ForH = _convertTestPtForH(kPtInSubView2ForV);
205 const kPtInSubView3ForH = _convertTestPtForH(kPtInSubView3ForV);
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:
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.
219 * - steps
220 * This property is array of testing. Each steps must have following
221 * properties at least.
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|.
233 * And also you need one more property when you call a testing function.
235 * - description
236 * This property is description of the test. This is used for
237 * logging.
239 * At testing, you can access to current step via |gCurrentTest|.
242 var gTestLists;
243 function initTestList()
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
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)" }
1000 /******************************************************************************
1001 * Actions for preparing tests
1002 ******************************************************************************/
1004 function initElements()
1006 _clearTimer();
1008 function resetScrollPosition(aElement)
1010 aElement.scrollTop = 0;
1011 aElement.scrollLeft = 0;
1014 function initInRootView(aElement, aPt)
1016 aElement.offset =
1017 gCurrentTest.forVertical ? aPt : { x: aPt.y, y: aPt.x };
1020 const kDisplay = gCurrentTest.forVertical ? "block" : "inline-block";
1021 gSubView1.style.display = kDisplay;
1022 gSubView2.style.display = kDisplay;
1023 gSubView3.style.display = kDisplay;
1025 resetScrollPosition(gRootView);
1026 resetScrollPosition(gSubView1);
1027 resetScrollPosition(gSubView2);
1028 resetScrollPosition(gSubView3);
1030 runNextTestStep();
1033 function clearWheelTransaction()
1035 _clearTimer();
1036 _clearTransaction();
1037 runNextTestStep();
1040 function sendKeyEvents()
1042 _clearTimer();
1043 synthesizeKey(gCurrentTest.key, {}, window);
1044 runNextTestStep();
1047 function sendMouseButtonEvents()
1049 _clearTimer();
1050 synthesizeMouse(gRootView, -1, -1, { type:"mousedown" }, window);
1051 synthesizeMouse(gRootView, -1, -1, { type:"mouseup" }, window);
1052 runNextTestStep();
1055 function sendMouseMoveEvent()
1057 _clearTimer();
1058 _fireMouseMoveEvent(gCurrentTest.offset);
1059 runNextTestStep();
1062 /******************************************************************************
1063 * Utilities for testing functions
1064 ******************************************************************************/
1066 function _clearTransaction()
1068 synthesizeMouse(gRootView, -1, -1, { type:"mousedown" }, window);
1069 synthesizeMouse(gRootView, -1, -1, { type:"mouseup" }, window);
1072 function _saveScrollPositions()
1074 function save(aElement)
1076 aElement.prevTop = aElement.scrollTop;
1077 aElement.prevLeft = aElement.scrollLeft;
1079 save(gRootView);
1080 save(gSubView1);
1081 save(gSubView2);
1082 save(gSubView3);
1085 function _fireMouseMoveEvent(aOffset)
1087 synthesizeMouse(gRootView, aOffset.x, aOffset.y, { type:"mousemove" }, window);
1090 function _fireWheelScrollEvent(aOffset, aIsVertical, aForward, aDelta)
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;
1098 synthesizeWheel(gRootView, aOffset.x, aOffset.y, event, window);
1101 function _canScroll(aElement, aIsVertical, aForward)
1103 if (aIsVertical) {
1104 if (!aForward)
1105 return aElement.scrollTop > 0;
1106 return aElement.scrollHeight > aElement.scrollTop + aElement.clientHeight;
1108 if (!aForward)
1109 return aElement.scrollLeft > 0;
1110 return aElement.scrollWidth > aElement.scrollLeft + aElement.clientWidth;
1113 const kNotScrolled = 0;
1114 const kScrolledToTop = 1;
1115 const kScrolledToBottom = 2;
1116 const kScrolledToLeft = 4;
1117 const kScrolledToRight = 8;
1119 const kScrolledVertical = kScrolledToTop | kScrolledToBottom;
1120 const kScrolledHorizontal = kScrolledToLeft | kScrolledToRight;
1122 function _getScrolledState(aElement)
1124 var ret = kNotScrolled;
1125 if (aElement.scrollTop != aElement.prevTop) {
1126 ret |= aElement.scrollTop < aElement.prevTop ? kScrolledToTop :
1127 kScrolledToBottom;
1129 if (aElement.scrollLeft != aElement.prevLeft) {
1130 ret |= aElement.scrollLeft < aElement.prevLeft ? kScrolledToLeft :
1131 kScrolledToRight;
1133 return ret;
1136 function _getExpectedScrolledState()
1138 return gCurrentTest.isVertical ?
1139 gCurrentTest.isForward ? kScrolledToBottom : kScrolledToTop :
1140 gCurrentTest.isForward ? kScrolledToRight : kScrolledToLeft;
1143 function _getScrolledStateText(aScrolledState)
1145 if (aScrolledState == kNotScrolled)
1146 return "Not scrolled";
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 ";
1155 if (aScrolledState & kScrolledHorizontal) {
1156 s += aScrolledState & kScrolledToLeft ? "backward" : "forward";
1157 s += " (horizontal)"
1159 return s;
1162 function _getCurrentTestList()
1164 return gTestLists[gCurrentTestListStatus.nextListIndex - 1];
1167 function _clearTimer()
1169 clearTimeout(gTimer);
1170 gTimer = 0;
1173 /******************************************************************************
1174 * Testing functions
1175 ******************************************************************************/
1178 * Note that testing functions must set following variables:
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.
1186 function testContinuousScroll()
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.
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.
1206 _clearTimer();
1207 _saveScrollPositions();
1208 if (!gCurrentTest.expectedView) {
1209 runNextTestStep();
1210 return;
1213 gLitesnEvents = kListenEvent_All;
1214 gCurrentTest.repeatTest = true;
1215 gCurrentTest.autoRepeatDelay = 0;
1217 if (!_canScroll(gCurrentTest.expectedView,
1218 gCurrentTest.isVertical, gCurrentTest.isForward)) {
1219 gCurrentTest.expectedView = null;
1221 var delta = gCurrentTest.delta ? gCurrentTest.delta : 4;
1222 _fireWheelScrollEvent(gCurrentTest.offset,
1223 gCurrentTest.isVertical, gCurrentTest.isForward, delta);
1226 function testOneTimeScroll()
1229 * Testing one wheel event. |runNextTestStep| will be called immediately
1230 * after this function by |onScrollView| or |onTimeout|.
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.
1244 _clearTimer();
1245 _saveScrollPositions();
1247 gLitesnEvents = kListenEvent_All;
1248 gCurrentTest.repeatTest = false;
1249 gCurrentTest.autoRepeatDelay = 0;
1251 var delta = gCurrentTest.delta ? gCurrentTest.delta : 4;
1252 _fireWheelScrollEvent(gCurrentTest.offset,
1253 gCurrentTest.isVertical, gCurrentTest.isForward, delta);
1256 function testRestartScroll()
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.
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.
1275 _clearTimer();
1276 _saveScrollPositions();
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;
1287 } else {
1288 gCurrentTest.repeatTest = false;
1289 gCurrentTest.autoRepeatDelay = 0;
1290 gLitesnEvents = kListenEvent_All;
1291 gCurrentTest.isTimeoutTesting = false;
1292 gCurrentTest.expectedView = gCurrentTest.expectedViewAfterTimeout;
1295 var delta = gCurrentTest.delta ? gCurrentTest.delta : 4;
1296 _fireWheelScrollEvent(gCurrentTest.offset,
1297 gCurrentTest.isVertical, gCurrentTest.isForward, delta);
1300 /******************************************************************************
1301 * Event handlers
1302 ******************************************************************************/
1304 function onScrollView(aEvent)
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|.
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.
1328 if (!(gLitesnEvents & kListenEvent_OnScroll))
1329 return;
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;
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;
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;
1363 is(aEvent.target.id, gCurrentTest.expectedView.id,
1364 "wrong view was scrolled: " + gCurrentTest.description);
1365 runNextTestList();
1366 return;
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;
1380 ok(true, "passed: " + gCurrentTest.description);
1381 continueTest();
1384 function onMouseScrollFailed()
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.
1390 * NOTE: This event is fired immediately after |_fireWheelScrollEvent|.
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.
1399 if (!(gLitesnEvents & kListenEvent_OnScrollFailed))
1400 return;
1402 ok(!gCurrentTest.expectedView,
1403 "failed to scroll on current target: " + gCurrentTest.description);
1404 if (gCurrentTest.expectedView) {
1405 runNextTestList();
1406 return;
1409 continueTest();
1412 function onTransactionTimeout()
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.
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.
1435 if (!gCurrentTest.isTimeoutTesting &&
1436 gCurrentTestListStatus.retryWhenTransactionTimeout > 0) {
1437 gCurrentTestListStatus.retryWhenTransactionTimeout--;
1438 // retry current test list
1439 retryCurrentTestList();
1440 return;
1443 gCurrentTest.wasTransactionTimeout = true;
1445 if (!(gLitesnEvents & kListenEvent_OnTransactionTimeout))
1446 return;
1448 ok(gCurrentTest.isTimeoutTesting,
1449 "transaction timeout: " + gCurrentTest.description);
1450 if (!gCurrentTest.isTimeoutTesting) {
1451 runNextTestList();
1452 return;
1455 continueTest();
1458 /******************************************************************************
1459 * Main function for this tests
1460 ******************************************************************************/
1462 function runNextTestStep()
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);
1473 function runNextTestList()
1475 _clearTimer();
1477 gLitesnEvents = kListenEvent_None;
1478 _clearTransaction();
1479 resetTimeoutPrefs();
1480 if (gCurrentTestListStatus.nextListIndex >= gTestLists.length) {
1481 finish();
1482 return;
1485 gCurrentTestListStatus.nextListIndex++;
1486 gCurrentTestListStatus.retryWhenTransactionTimeout =
1487 _getCurrentTestList().retryWhenTransactionTimeout;
1488 runTestStepAt(0);
1491 function runTestStepAt(aStepIndex)
1493 _clearTimer();
1495 disableNonTestMouseEvents(true);
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();
1512 function retryCurrentTestList()
1514 _clearTimer();
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);
1523 function continueTest()
1526 * This function is called from an event handler when a test succeeded.
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|.
1536 _clearTimer();
1537 gLitesnEvents = kListenEvent_OnTransactionTimeout;
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);
1549 </script>
1551 </window>