widget/tests/window_wheeltransaction.xul

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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;
    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>
    72 <script class="testbody" type="application/javascript">
    73 <![CDATA[
    75 function ok(aCondition, aMessage)
    76 {
    77   window.opener.wrappedJSObject.SimpleTest.ok(aCondition, aMessage);
    78 }
    80 function is(aLeft, aRight, aMessage)
    81 {
    82   window.opener.wrappedJSObject.SimpleTest.is(aLeft, aRight, aMessage);
    83 }
    85 function isnot(aLeft, aRight, aMessage)
    86 {
    87   window.opener.wrappedJSObject.SimpleTest.isnot(aLeft, aRight, aMessage);
    88 }
    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;
   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;
   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)
   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 }
   135 function resetTimeoutPrefs()
   136 {
   137   if (gTimeout == kDefaultTimeout)
   138     return;
   139   setTimeoutPrefs(kDefaultTimeout, kDefaultIgnoreMoveDelay);
   140   initTestList();
   141 }
   143 function growUpTimeoutPrefs()
   144 {
   145   if (gTimeout != kDefaultTimeout)
   146     return;
   147   setTimeoutPrefs(5000, 1000);
   148   initTestList();
   149 }
   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()
   165 {
   166   window.close();
   167 }
   169 function onload()
   170 {
   171   runNextTestList();
   172 }
   174 function onunload()
   175 {
   176   resetTimeoutPrefs();
   177   gPrefSvc.clearUserPref(kPrefSmoothScroll);
   178   disableNonTestMouseEvents(false);
   179   window.opener.wrappedJSObject.SimpleTest.finish();
   180 }
   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)
   187 {
   188   return { x: aPt.x + 10, y: aPt.y + 10 };
   189 }
   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)
   198 {
   199   return { x: aPt.y, y: aPt.x };
   200 }
   202 const kPtInRootViewForH = _convertTestPtForH(kPtInRootViewForV);
   203 const kPtInSubView1ForH = _convertTestPtForH(kPtInSubView1ForV);
   204 const kPtInSubView2ForH = _convertTestPtForH(kPtInSubView2ForV);
   205 const kPtInSubView3ForH = _convertTestPtForH(kPtInSubView3ForV);
   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  */
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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     },
   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 }
  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  ******************************************************************************/
  1177 /**
  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.
  1184  */
  1186 function testContinuousScroll()
  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.
  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    */
  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()
  1228   /**
  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.
  1242    */
  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()
  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.
  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    */
  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)
  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|.
  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    */
  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()
  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.
  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.
  1397    */
  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()
  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.
  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    */
  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()
  1525   /**
  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|.
  1534    */
  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);
  1548 ]]>
  1549 </script>
  1551 </window>

mercurial