Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / remoting / webapp / browser_test / bump_scroll_browser_test.js
bloba20cd3671555d3c1b956c697235f0e186d3edf34
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 /**
6  * @fileoverview
7  * @suppress {checkTypes}
8  * Browser test for the scenario below:
9  * 1. Enter full-screen mode
10  * 2. Move the mouse to each edge; verify that the desktop bump-scrolls.
11  */
13 'use strict';
15 /** @constructor */
16 browserTest.FakeDesktopViewport = function() {
17   /** @private */
18   this.pluginPosition_ = {
19     top: 0,
20     left: 0
21   };
22   /** @private */
23   this.bumpScroller_ = new base.EventSourceImpl();
24   this.bumpScroller_.defineEvents(Object.keys(remoting.BumpScroller.Events));
27 /**
28  * @param {number} top
29  * @param {number} left
30  * @return {void} nothing.
31  */
32 browserTest.FakeDesktopViewport.prototype.setPluginPositionForTesting =
33     function(top, left) {
34   this.pluginPosition_ = {
35     top: top,
36     left: left
37   };
40 /**
41  * @return {{top: number, left:number}} The top-left corner of the plugin.
42  */
43 browserTest.FakeDesktopViewport.prototype.getPluginPositionForTesting =
44     function() {
45   return this.pluginPosition_;
48 /** @return {base.EventSource} */
49 browserTest.FakeDesktopViewport.prototype.getBumpScrollerForTesting =
50     function() {
51   return this.bumpScroller_;
54 /** @suppress {reportUnknownTypes} */
55 browserTest.FakeDesktopViewport.prototype.raiseEvent =
56     function() {
57   return this.bumpScroller_.raiseEvent.apply(this.bumpScroller_, arguments);
60 /** @return {remoting.DesktopViewport} */
61 function getViewportForTesting() {
62   var desktopApp = /** @type {remoting.DesktopRemoting} */ (remoting.app);
63   var view = desktopApp.getConnectedViewForTesting();
64   if (view) {
65     return view.getViewportForTesting();
66   }
67   return null;
70 /** @constructor */
71 browserTest.Bump_Scroll = function() {
72   // To avoid dependencies on the actual host desktop size, we simulate a
73   // desktop larger or smaller than the client window. The exact value is
74   // arbitrary, but must be positive.
75   /** @type {number} */
76   this.kHostDesktopSizeDelta = 10;
79 /**
80  * @param {{pin:string}} data
81  */
82 browserTest.Bump_Scroll.prototype.run = function(data) {
83   browserTest.expect(typeof data.pin == 'string');
85   if (!base.isAppsV2()) {
86     browserTest.fail(
87         'Bump-scroll requires full-screen, which can only be activated ' +
88         'programmatically in apps v2.');
89   }
91   var mockConnection = new remoting.MockConnection();
93   function onPluginCreated(/** remoting.MockClientPlugin */ plugin) {
94     plugin.mock$useDefaultBehavior(remoting.MockClientPlugin.AuthMethod.PIN);
95   }
96   mockConnection.pluginFactory().mock$setPluginCreated(onPluginCreated);
99   function cleanup() {
100     mockConnection.restore();
101     browserTest.disconnect();
102   }
104   this.testVerifyScroll().then(function() {
105     return browserTest.connectMe2Me();
106   }).then(function() {
107     return browserTest.enterPIN(data.pin);
108   }).then(
109     this.noScrollWindowed.bind(this)
110   ).then(
111     this.activateFullscreen.bind(this)
112   ).then(
113     this.noScrollSmaller.bind(this)
114     // The order of these operations is important. Because the plugin starts
115     // scrolled to the top-left, it needs to be scrolled right and down first.
116   ).then(
117     this.scrollDirection.bind(this, 1.0, 0.5)  // Right edge
118   ).then(
119     this.scrollDirection.bind(this, 0.5, 1.0)  // Bottom edge
120   ).then(
121     this.scrollDirection.bind(this, 0.0, 0.5)  // Left edge
122   ).then(
123     this.scrollDirection.bind(this, 0.5, 0.0)  // Top edge
124   ).then(
125     function(value) {
126       cleanup();
127       return browserTest.pass();
128     },
129     function(error) {
130       cleanup();
131       return browserTest.fail(error);
132     }
133   );
137  * @return {Promise}
138  */
139 browserTest.Bump_Scroll.prototype.noScrollWindowed = function() {
140   var viewport = getViewportForTesting();
141   viewport.setPluginSizeForBumpScrollTesting(
142       window.innerWidth + this.kHostDesktopSizeDelta,
143       window.innerHeight + this.kHostDesktopSizeDelta);
144   this.moveMouseTo(0, 0);
145   return this.verifyNoScroll();
149  * @return {Promise}
150  */
151 browserTest.Bump_Scroll.prototype.noScrollSmaller = function() {
152   var viewport = getViewportForTesting();
153   viewport.setPluginSizeForBumpScrollTesting(
154       window.innerWidth - this.kHostDesktopSizeDelta,
155       window.innerHeight - this.kHostDesktopSizeDelta);
156   this.moveMouseTo(0, 0);
157   return this.verifyNoScroll();
161  * @param {number} widthFraction
162  * @param {number} heightFraction
163  * @return {Promise}
164  */
165 browserTest.Bump_Scroll.prototype.scrollDirection =
166     function(widthFraction, heightFraction) {
167   var viewport = getViewportForTesting();
168   viewport.setPluginSizeForBumpScrollTesting(
169       screen.width + this.kHostDesktopSizeDelta,
170       screen.height + this.kHostDesktopSizeDelta);
171   /** @type {number} */
172   var expectedTop = heightFraction === 0.0 ? 0 :
173                     heightFraction == 1.0 ? -this.kHostDesktopSizeDelta :
174                     undefined;
175   /** @type {number} */
176   var expectedLeft = widthFraction === 0.0 ? 0 :
177                      widthFraction === 1.0 ? -this.kHostDesktopSizeDelta :
178                      undefined;
179   var result = this.verifyScroll(expectedTop, expectedLeft);
180   this.moveMouseTo(widthFraction * screen.width,
181                    heightFraction * screen.height);
182   return result;
186  * @return {Promise}
187  */
188 browserTest.Bump_Scroll.prototype.activateFullscreen = function() {
189   return new Promise(function(fulfill, reject) {
190     remoting.fullscreen.activate(true, function() {
191       // The onFullscreen callback is invoked before the window has
192       // resized, so defer fulfilling the promise so that innerWidth
193       // and innerHeight are correct.
194       base.Promise.sleep(1000).then(fulfill);
195     });
196     base.Promise.sleep(5000).then(function(){
197       reject('Timed out waiting for full-screen');
198     });
199   });
203  * @param {number} x
204  * @param {number} y
205  */
206 browserTest.Bump_Scroll.prototype.moveMouseTo = function(x, y) {
207   var e = {
208     bubbles: true,
209     cancelable: false,
210     view: window,
211     detail: 0,
212     screenX: x,
213     screenY: y,
214     clientX: x,
215     clientY: y,
216     ctrlKey: false,
217     altKey: false,
218     shiftKey: false,
219     metaKey: false,
220     button: 0,
221     relatedTarget: undefined
222   };
223   var event = document.createEvent('MouseEvents');
224   event.initMouseEvent('mousemove',
225                        e.bubbles, e.cancelable, e.view, e.detail,
226                        e.screenX, e.screenY, e.clientX, e.clientY,
227                        e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
228                        e.button, document.documentElement);
229   document.documentElement.dispatchEvent(event);
233  * verifyScroll() is complicated enough to warrant a test.
234  * @return {Promise}
235  */
236 browserTest.Bump_Scroll.prototype.testVerifyScroll = function() {
237   var STARTED = remoting.BumpScroller.Events.bumpScrollStarted;
238   var STOPPED = remoting.BumpScroller.Events.bumpScrollStopped;
239   var fakeViewport = new browserTest.FakeDesktopViewport;
240   var that = this;
242   // No events raised (e.g. windowed mode).
243   var result = this.verifyNoScroll(fakeViewport)
245   .then(function() {
246     // Start and end events raised, but no scrolling (e.g. full-screen mode
247     // with host desktop <= window size).
248     fakeViewport = new browserTest.FakeDesktopViewport;
249     var result = that.verifyNoScroll(fakeViewport);
250     fakeViewport.raiseEvent(STARTED, {});
251     fakeViewport.raiseEvent(STOPPED, {});
252     return result;
254   }).then(function() {
255     // Start and end events raised, with incorrect scrolling.
256     fakeViewport = new browserTest.FakeDesktopViewport;
257     var result = base.Promise.negate(
258         that.verifyScroll(2, 2, fakeViewport));
259     fakeViewport.raiseEvent(STARTED, {});
260     fakeViewport.setPluginPositionForTesting(1, 1);
261     fakeViewport.raiseEvent(STOPPED, {});
262     return result;
264   }).then(function() {
265     // Start event raised, but not end event.
266     fakeViewport = new browserTest.FakeDesktopViewport;
267     var result = base.Promise.negate(
268         that.verifyScroll(2, 2, fakeViewport));
269     fakeViewport.raiseEvent(STARTED, {});
270     fakeViewport.setPluginPositionForTesting(2, 2);
271     return result;
273   }).then(function() {
274     // Start and end events raised, with correct scrolling.
275     fakeViewport = new browserTest.FakeDesktopViewport;
276     var result = that.verifyScroll(2, 2, fakeViewport);
277     fakeViewport.raiseEvent(STARTED, {});
278     fakeViewport.setPluginPositionForTesting(2, 2);
279     fakeViewport.raiseEvent(STOPPED, {});
280     return result;
281   });
283   return result;
287  * Verify that a bump scroll operation takes place and that the top-left corner
288  * of the plugin is as expected when it completes.
289  * @param {number|undefined} expectedTop The expected vertical position of the
290  *    plugin, or undefined if it is not expected to change.
291  * @param {number|undefined} expectedLeft The expected horizontal position of
292  *    the plugin, or undefined if it is not expected to change.
293  * @param {browserTest.FakeDesktopViewport=} opt_desktopViewport
294  *     DesktopViewport fake, for testing.
295  * @return {Promise}
296  */
297 browserTest.Bump_Scroll.prototype.verifyScroll =
298     function (expectedTop, expectedLeft, opt_desktopViewport) {
299   var desktopViewport = opt_desktopViewport || getViewportForTesting();
300   console.assert(desktopViewport != null, '|desktopViewport| is null.');
301   var STARTED = remoting.BumpScroller.Events.bumpScrollStarted;
302   var STOPPED = remoting.BumpScroller.Events.bumpScrollStopped;
304   var initialPosition = desktopViewport.getPluginPositionForTesting();
305   var initialTop = initialPosition.top;
306   var initialLeft = initialPosition.left;
308   /** @return {Promise} */
309   var verifyPluginPosition = function() {
310     var position = desktopViewport.getPluginPositionForTesting();
311     if (expectedLeft === undefined) {
312       expectedLeft = initialLeft;
313     }
314     if (expectedTop === undefined) {
315       expectedTop = initialTop;
316     }
317     if (position.top != expectedTop || position.left != expectedLeft) {
318       return Promise.reject(
319           new Error('No or incorrect scroll detected: (' +
320                     position.left + ',' + position.top + ' instead of ' +
321                     expectedLeft + ',' + expectedTop + ')'));
322     } else {
323       return Promise.resolve();
324     }
325   };
327   var bumpScroller = desktopViewport.getBumpScrollerForTesting();
328   var started = browserTest.expectEvent(bumpScroller, STARTED, 1000);
329   var stopped = browserTest.expectEvent(bumpScroller, STOPPED, 5000);
330   return started.then(function() {
331     return stopped;
332   }, function() {
333     // If no started event is raised, the test might still pass if it asserted
334     // no scrolling.
335     if (expectedTop === undefined && expectedLeft === undefined) {
336       return Promise.resolve();
337     } else {
338       return Promise.reject(
339           new Error('Scroll expected but no start event fired.'));
340     }
341   }).then(function() {
342     return verifyPluginPosition();
343   });
347  * @param {browserTest.FakeDesktopViewport=} opt_desktopViewport
348  *     DesktopViewport fake, for testing.
350  * @return {Promise<boolean>} A promise that resolves to true if no scrolling
351  *   occurs within a timeout.
352  */
353 browserTest.Bump_Scroll.prototype.verifyNoScroll =
354     function(opt_desktopViewport) {
355   var desktopViewport = opt_desktopViewport || getViewportForTesting();
356   var bumpScroller = desktopViewport.getBumpScrollerForTesting();
357   if (!bumpScroller) {
358     Promise.resolve(true);
359   }
360   return this.verifyScroll(undefined, undefined, desktopViewport);