[Android] Implement 3-way sensor fallback for Device Orientation.
[chromium-blink-merge.git] / ui / file_manager / integration_tests / remote_call.js
blob1eb4a675178208fe923da363468d974cf33d331f
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 'use strict';
7 /**
8  * Class to manipulate the window in the remote extension.
9  *
10  * @param {string} extensionId ID of extension to be manipulated.
11  * @constructor
12  */
13 function RemoteCall(extensionId) {
14   this.extensionId_ = extensionId;
17 /**
18  * Checks whether step by step tests are enabled or not.
19  * @return {Promise<bool>}
20  */
21 RemoteCall.isStepByStepEnabled = function() {
22   return new Promise(function(fulfill) {
23     chrome.commandLinePrivate.hasSwitch(
24         'enable-file-manager-step-by-step-tests', fulfill);
25   });
28 /**
29  * Calls a remote test util in Files.app's extension. See: test_util.js.
30  *
31  * @param {string} func Function name.
32  * @param {?string} appId Target window's App ID or null for functions
33  *     not requiring a window.
34  * @param {Array<*>} args Array of arguments.
35  * @param {function(*)=} opt_callback Callback handling the function's result.
36  * @return {Promise} Promise to be fulfilled with the result of the remote
37  *     utility.
38  */
39 RemoteCall.prototype.callRemoteTestUtil =
40     function(func, appId, args, opt_callback) {
41   return RemoteCall.isStepByStepEnabled().then(function(stepByStep) {
42     if (!stepByStep)
43       return false;
44     return new Promise(function(onFulfilled) {
45       console.info('Executing: ' + func + ' on ' + appId + ' with args: ');
46       console.info(args);
47       console.info('Type step() to continue...');
48       window.step = function() {
49         window.step = null;
50         onFulfilled(stepByStep);
51       };
52     });
53   }).then(function(stepByStep) {
54     return new Promise(function(onFulfilled) {
55       chrome.runtime.sendMessage(
56           this.extensionId_,
57           {
58             func: func,
59             appId: appId,
60             args: args
61           },
62           function(var_args) {
63             if (stepByStep) {
64               console.info('Returned value:');
65               console.info(arguments);
66             }
67             if (opt_callback)
68               opt_callback.apply(null, arguments);
69             onFulfilled(arguments[0]);
70           });
71     }.bind(this));
72   }.bind(this));
75 /**
76  * Waits until a window having the given ID prefix appears.
77  * @param {string} windowIdPrefix ID prefix of the requested window.
78  * @return {Promise} promise Promise to be fulfilled with a found window's ID.
79  */
80 RemoteCall.prototype.waitForWindow = function(windowIdPrefix) {
81   return repeatUntil(function() {
82     return this.callRemoteTestUtil('getWindows', null, []).
83         then(function(windows) {
84       for (var id in windows) {
85         if (id.indexOf(windowIdPrefix) === 0)
86           return id;
87       }
88       return pending('Window with the prefix %s is not found.', windowIdPrefix);
89     });
90   }.bind(this));
93 /**
94  * Closes a window and waits until the window is closed.
95  *
96  * @param {string} windowId ID of the window to close.
97  * @return {Promise} promise Promise to be fulfilled with the result (true:
98  *     success, false: failed).
99  */
100 RemoteCall.prototype.closeWindowAndWait = function(windowId) {
101   // Closes the window.
102   return this.callRemoteTestUtil('closeWindow', null, [windowId]).then(
103       function(result) {
104         // Returns false when the closing is failed.
105         if (!result)
106           return false;
108         return repeatUntil(function() {
109           return this.callRemoteTestUtil('getWindows', null, []).then(
110               function(windows) {
111                 for (var id in windows) {
112                   if (id === windowId) {
113                     // Window is still available. Continues waiting.
114                     return pending('Window with the prefix %s is not found.',
115                                    windowId);
116                   }
117                 }
118                 // Window is not available. Closing is done successfully.
119                 return true;
120               }
121           );
122         }.bind(this));
123       }.bind(this)
124   );
128  * Waits until the window turns to the given size.
129  * @param {string} windowId Target window ID.
130  * @param {number} width Requested width in pixels.
131  * @param {number} height Requested height in pixels.
132  */
133 RemoteCall.prototype.waitForWindowGeometry =
134     function(windowId, width, height) {
135   return repeatUntil(function() {
136     return this.callRemoteTestUtil('getWindows', null, []).
137         then(function(windows) {
138       if (!windows[windowId])
139         return pending('Window %s is not found.', windowId);
140       if (windows[windowId].outerWidth !== width ||
141           windows[windowId].outerHeight !== height) {
142         return pending('Expected window size is %j, but it is %j',
143                        {width: width, height: height},
144                        windows[windowId]);
145       }
146     });
147   }.bind(this));
151  * Waits for the specified element appearing in the DOM.
152  * @param {string} windowId Target window ID.
153  * @param {string} query Query string for the element.
154  * @param {string=} opt_iframeQuery Query string for the iframe containing the
155  *     element.
156  * @return {Promise} Promise to be fulfilled when the element appears.
157  */
158 RemoteCall.prototype.waitForElement =
159     function(windowId, query, opt_iframeQuery) {
160   return repeatUntil(function() {
161     return this.callRemoteTestUtil(
162         'queryAllElements',
163         windowId,
164         [query, opt_iframeQuery]
165     ).then(function(elements) {
166       if (elements.length > 0)
167         return elements[0];
168       else
169         return pending(
170             'Element %s (maybe in iframe %s) is not found.',
171             query,
172             opt_iframeQuery);
173     });
174   }.bind(this));
178  * Waits for the specified element leaving from the DOM.
179  * @param {string} windowId Target window ID.
180  * @param {string} query Query string for the element.
181  * @param {string=} opt_iframeQuery Query string for the iframe containing the
182  *     element.
183  * @return {Promise} Promise to be fulfilled when the element is lost.
184  */
185 RemoteCall.prototype.waitForElementLost =
186     function(windowId, query, opt_iframeQuery) {
187   return repeatUntil(function() {
188     return this.callRemoteTestUtil(
189         'queryAllElements',
190         windowId,
191         [query, opt_iframeQuery]
192     ).then(function(elements) {
193       if (elements.length > 0)
194         return pending('Elements %j is still exists.', elements);
195       return true;
196     });
197   }.bind(this));
201  * Sends a fake key down event.
202  * @param {string} windowId Window ID.
203  * @param {string} query Query for the target element.
204  * @param {string} keyIdentifer Key identifier.
205  * @param {boolean} ctrlKey Control key flag.
206  * @return {Promise} Promise to be fulfilled or rejected depending on the
207  *     result.
208  */
209 RemoteCall.prototype.fakeKeyDown =
210     function(windowId, query, keyIdentifer, ctrlKey) {
211   var resultPromise = this.callRemoteTestUtil(
212       'fakeKeyDown', windowId, [query, keyIdentifer, ctrlKey]);
213   return resultPromise.then(function(result) {
214     if (result)
215       return true;
216     else
217       return Promise.reject('Fail to fake key down.');
218   });
222  * Gets file entries just under the volume.
224  * @param {VolumeManagerCommon.VolumeType} volumeType Volume type.
225  * @param {Array<string>} names File name list.
226  * @return {Promise} Promise to be fulfilled with file entries or rejected
227  *     depending on the result.
228  */
229 RemoteCall.prototype.getFilesUnderVolume = function(volumeType, names) {
230   return this.callRemoteTestUtil(
231       'getFilesUnderVolume', null, [volumeType, names]);
235  * Waits for a single file.
236  * @param {VolumeManagerCommon.VolumeType} volumeType Volume type.
237  * @param {string} name File name.
238  * @return {!Promise} Promise to be fulfilled when the file had found.
239  */
240 RemoteCall.prototype.waitForAFile = function(volumeType, name) {
241   return repeatUntil(function() {
242     return this.getFilesUnderVolume(volumeType, [name])
243         .then(function(urls) {
244           if (urls.length === 1)
245             return true;
246           return pending('"' + name + '" is not found.');
247         });
248   }.bind(this));
252  * Class to manipulate the window in the remote extension.
254  * @param {string} extensionId ID of extension to be manipulated.
255  * @extends {RemoteCall}
256  * @constructor
257  */
258 function RemoteCallFilesApp() {
259   RemoteCall.apply(this, arguments);
262 RemoteCallFilesApp.prototype.__proto__ = RemoteCall.prototype;
265  * Waits for the file list turns to the given contents.
266  * @param {string} windowId Target window ID.
267  * @param {Array<Array<string>>} expected Expected contents of file list.
268  * @param {{orderCheck:boolean=, ignoreLastModifiedTime:boolean=}=} opt_options
269  *     Options of the comparison. If orderCheck is true, it also compares the
270  *     order of files. If ignoreLastModifiedTime is true, it compares the file
271  *     without its last modified time.
272  * @return {Promise} Promise to be fulfilled when the file list turns to the
273  *     given contents.
274  */
275 RemoteCallFilesApp.prototype.waitForFiles =
276     function(windowId, expected, opt_options) {
277   var options = opt_options || {};
278   return repeatUntil(function() {
279     return this.callRemoteTestUtil(
280         'getFileList', windowId, []).then(function(files) {
281       if (!options.orderCheck) {
282         files.sort();
283         expected.sort();
284       }
285       for (var i = 0; i < Math.min(files.length, expected.length); i++) {
286         if (options.ignoreFileSize) {
287           files[i][1] = '';
288           expected[i][1] = '';
289         }
290         if (options.ignoreLastModifiedTime) {
291           files[i][3] = '';
292           expected[i][3] = '';
293         }
294       }
295       if (!chrome.test.checkDeepEq(expected, files)) {
296         return pending('waitForFiles: expected: %j actual %j.',
297                        expected,
298                        files);
299       }
300     });
301   }.bind(this));
305  * Waits until the number of files in the file list is changed from the given
306  * number.
307  * TODO(hirono): Remove the function.
309  * @param {string} windowId Target window ID.
310  * @param {number} lengthBefore Number of items visible before.
311  * @return {Promise} Promise to be fulfilled with the contents of files.
312  */
313 RemoteCallFilesApp.prototype.waitForFileListChange =
314     function(windowId, lengthBefore) {
315   return repeatUntil(function() {
316     return this.callRemoteTestUtil(
317         'getFileList', windowId, []).then(function(files) {
318       files.sort();
319       var notReadyRows = files.filter(function(row) {
320         return row.filter(function(cell) { return cell == '...'; }).length;
321       });
322       if (notReadyRows.length === 0 &&
323           files.length !== lengthBefore &&
324           files.length !== 0) {
325         return files;
326       } else {
327         return pending('The number of file is %d. Not changed.', lengthBefore);
328       }
329     });
330   }.bind(this));
334  * Waits until the given taskId appears in the executed task list.
335  * @param {string} windowId Target window ID.
336  * @param {string} taskId Task ID to watch.
337  * @return {Promise} Promise to be fulfilled when the task appears in the
338  *     executed task list.
339  */
340 RemoteCallFilesApp.prototype.waitUntilTaskExecutes =
341     function(windowId, taskId) {
342   return repeatUntil(function() {
343     return this.callRemoteTestUtil('getExecutedTasks', windowId, []).
344         then(function(executedTasks) {
345           if (executedTasks.indexOf(taskId) === -1)
346             return pending('Executed task is %j', executedTasks);
347         });
348   }.bind(this));
352  * Check if the next tabforcus'd element has the given ID or not.
353  * @param {string} windowId Target window ID.
354  * @param {string} elementId String of 'id' attribute which the next tabfocus'd
355  *     element should have.
356  * @return {Promise} Promise to be fulfilled with the result.
357  */
358 RemoteCallFilesApp.prototype.checkNextTabFocus =
359     function(windowId, elementId) {
360   return remoteCall.callRemoteTestUtil('fakeKeyDown',
361                                        windowId,
362                                        ['body', 'U+0009', false]).then(
363   function(result) {
364     chrome.test.assertTrue(result);
365     return remoteCall.callRemoteTestUtil('getActiveElement',
366                                          windowId,
367                                          []);
368   }).then(function(element) {
369     if (!element || !element.attributes['id'])
370       return false;
372     if (element.attributes['id'] === elementId) {
373       return true;
374     } else {
375       console.error('The ID of the element should be "' + elementId +
376                     '", but "' + element.attributes['id'] + '"');
377       return false;
378     }
379   });
383  * Waits until the current directory is changed.
384  * @param {string} windowId Target window ID.
385  * @param {string} expectedPath Path to be changed to.
386  * @return {Promise} Promise to be fulfilled when the current directory is
387  *     changed to expectedPath.
388  */
389 RemoteCallFilesApp.prototype.waitUntilCurrentDirectoryIsChanged =
390     function(windowId, expectedPath) {
391   return repeatUntil(function () {
392     return this.callRemoteTestUtil('getBreadcrumbPath', windowId, []).then(
393       function(path) {
394         if(path !== expectedPath)
395           return pending('Expected path is %s', expectedPath);
396       });
397   }.bind(this));
401  * Class to manipulate the window in the remote extension.
403  * @param {string} extensionId ID of extension to be manipulated.
404  * @extends {RemoteCall}
405  * @constructor
406  */
407 function RemoteCallGallery() {
408   RemoteCall.apply(this, arguments);
411 RemoteCallGallery.prototype.__proto__ = RemoteCall.prototype;
414  * Waits until the expected image is shown.
416  * @param {document} document Document.
417  * @param {number} width Expected width of the image.
418  * @param {number} height Expected height of the image.
419  * @param {string|null} name Expected name of the image.
420  * @return {Promise} Promsie to be fulfilled when the check is passed.
421  */
422 RemoteCallGallery.prototype.waitForSlideImage =
423     function(windowId, width, height, name) {
424   var expected = {};
425   if (width)
426     expected.width = width;
427   if (height)
428     expected.height = height;
429   if (name)
430     expected.name = name;
432   return repeatUntil(function() {
433     var query = '.gallery[mode="slide"] .content canvas.fullres';
434     return Promise.all([
435         this.waitForElement(windowId, '.filename-spacer input'),
436         this.waitForElement(windowId, query)
437     ]).then(function(args) {
438       var nameBox = args[0];
439       var fullResCanvas = args[1];
440       var actual = {};
441       if (width && fullResCanvas)
442         actual.width = Number(fullResCanvas.attributes.width);
443       if (height && fullResCanvas)
444         actual.height = Number(fullResCanvas.attributes.height);
445       if (name && nameBox)
446         actual.name = nameBox.value;
448       if (!chrome.test.checkDeepEq(expected, actual)) {
449         return pending('Slide mode state, expected is %j, actual is %j.',
450                        expected, actual);
451       }
452       return actual;
453     });
454   }.bind(this));
457 RemoteCallGallery.prototype.changeNameAndWait = function(windowId, newName) {
458   return this.callRemoteTestUtil('changeName', windowId, [newName]
459   ).then(function() {
460     return this.waitForSlideImage(windowId, 0, 0, newName);
461   }.bind(this));
465  * Shorthand for clicking an element.
466  * @param {AppWindow} appWindow Application window.
467  * @param {string} query Query for the element.
468  * @param {Promise} Promise to be fulfilled with the clicked element.
469  */
470 RemoteCallGallery.prototype.waitAndClickElement = function(windowId, query) {
471   return this.waitForElement(windowId, query).then(function(element) {
472     return this.callRemoteTestUtil('fakeMouseClick', windowId, [query])
473     .then(function() { return element; });
474   }.bind(this));
478  * Waits for the "Press Enter" message.
480  * @param {AppWindow} appWindow App window.
481  * @return {Promise} Promise to be fulfilled when the element appears.
482  */
483 RemoteCallGallery.prototype.waitForPressEnterMessage = function(appId) {
484   return this.waitForElement(appId, '.prompt-wrapper .prompt').
485       then(function(element) {
486         chrome.test.assertEq(
487             'Press Enter when done', element.text.trim());
488       });
492  * Shorthand for selecting an image in thumbnail mode.
493  * @param {string} appId App id.
494  * @param {string} name File name to be selected.
495  * @return {!Promise<boolean>} A promise which will be resolved with true if the
496  *     thumbnail has clicked. This method does not guarantee whether the
497  *     thumbnail has actually selected or not.
498  */
499 RemoteCallGallery.prototype.selectImageInThumbnailMode = function(appId, name) {
500   return this.callRemoteTestUtil('fakeMouseClick', appId,
501       ['.thumbnail-view > ul > li[title="' + name + '"] > .selection.frame']);