Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / ui / file_manager / integration_tests / remote_call.js
blob1f7dd0b6b07f7edc0d04fca9d4c9d54c571d99e8
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  * Class to manipulate the window in the remote extension.
237  * @param {string} extensionId ID of extension to be manipulated.
238  * @extends {RemoteCall}
239  * @constructor
240  */
241 function RemoteCallFilesApp() {
242   RemoteCall.apply(this, arguments);
245 RemoteCallFilesApp.prototype.__proto__ = RemoteCall.prototype;
248  * Waits for the file list turns to the given contents.
249  * @param {string} windowId Target window ID.
250  * @param {Array.<Array.<string>>} expected Expected contents of file list.
251  * @param {{orderCheck:boolean=, ignoreLastModifiedTime:boolean=}=} opt_options
252  *     Options of the comparison. If orderCheck is true, it also compares the
253  *     order of files. If ignoreLastModifiedTime is true, it compares the file
254  *     without its last modified time.
255  * @return {Promise} Promise to be fulfilled when the file list turns to the
256  *     given contents.
257  */
258 RemoteCallFilesApp.prototype.waitForFiles =
259     function(windowId, expected, opt_options) {
260   var options = opt_options || {};
261   return repeatUntil(function() {
262     return this.callRemoteTestUtil(
263         'getFileList', windowId, []).then(function(files) {
264       if (!options.orderCheck) {
265         files.sort();
266         expected.sort();
267       }
268       for (var i = 0; i < Math.min(files.length, expected.length); i++) {
269         if (options.ignoreFileSize) {
270           files[i][1] = '';
271           expected[i][1] = '';
272         }
273         if (options.ignoreLastModifiedTime) {
274           files[i][3] = '';
275           expected[i][3] = '';
276         }
277       }
278       if (!chrome.test.checkDeepEq(expected, files)) {
279         return pending('waitForFiles: expected: %j actual %j.',
280                        expected,
281                        files);
282       }
283     });
284   }.bind(this));
288  * Waits until the number of files in the file list is changed from the given
289  * number.
290  * TODO(hirono): Remove the function.
292  * @param {string} windowId Target window ID.
293  * @param {number} lengthBefore Number of items visible before.
294  * @return {Promise} Promise to be fulfilled with the contents of files.
295  */
296 RemoteCallFilesApp.prototype.waitForFileListChange =
297     function(windowId, lengthBefore) {
298   return repeatUntil(function() {
299     return this.callRemoteTestUtil(
300         'getFileList', windowId, []).then(function(files) {
301       files.sort();
302       var notReadyRows = files.filter(function(row) {
303         return row.filter(function(cell) { return cell == '...'; }).length;
304       });
305       if (notReadyRows.length === 0 &&
306           files.length !== lengthBefore &&
307           files.length !== 0) {
308         return files;
309       } else {
310         return pending('The number of file is %d. Not changed.', lengthBefore);
311       }
312     });
313   }.bind(this));
317  * Waits until the given taskId appears in the executed task list.
318  * @param {string} windowId Target window ID.
319  * @param {string} taskId Task ID to watch.
320  * @return {Promise} Promise to be fulfilled when the task appears in the
321  *     executed task list.
322  */
323 RemoteCallFilesApp.prototype.waitUntilTaskExecutes =
324     function(windowId, taskId) {
325   return repeatUntil(function() {
326     return this.callRemoteTestUtil('getExecutedTasks', windowId, []).
327         then(function(executedTasks) {
328           if (executedTasks.indexOf(taskId) === -1)
329             return pending('Executed task is %j', executedTasks);
330         });
331   }.bind(this));
335  * Check if the next tabforcus'd element has the given ID or not.
336  * @param {string} windowId Target window ID.
337  * @param {string} elementId String of 'id' attribute which the next tabfocus'd
338  *     element should have.
339  * @return {Promise} Promise to be fulfilled with the result.
340  */
341 RemoteCallFilesApp.prototype.checkNextTabFocus =
342     function(windowId, elementId) {
343   return remoteCall.callRemoteTestUtil('fakeKeyDown',
344                                        windowId,
345                                        ['body', 'U+0009', false]).then(
346   function(result) {
347     chrome.test.assertTrue(result);
348     return remoteCall.callRemoteTestUtil('getActiveElement',
349                                          windowId,
350                                          []);
351   }).then(function(element) {
352     if (!element || !element.attributes['id'])
353       return false;
355     if (element.attributes['id'] === elementId) {
356       return true;
357     } else {
358       console.error('The ID of the element should be "' + elementId +
359                     '", but "' + element.attributes['id'] + '"');
360       return false;
361     }
362   });
366  * Waits until the current directory is changed.
367  * @param {string} windowId Target window ID.
368  * @param {string} expectedPath Path to be changed to.
369  * @return {Promise} Promise to be fulfilled when the current directory is
370  *     changed to expectedPath.
371  */
372 RemoteCallFilesApp.prototype.waitUntilCurrentDirectoryIsChanged =
373     function(windowId, expectedPath) {
374   return repeatUntil(function () {
375     return this.callRemoteTestUtil('getBreadcrumbPath', windowId, []).then(
376       function(path) {
377         if(path !== expectedPath)
378           return pending('Expected path is %s', expectedPath);
379       });
380   }.bind(this));
384  * Class to manipulate the window in the remote extension.
386  * @param {string} extensionId ID of extension to be manipulated.
387  * @extends {RemoteCall}
388  * @constructor
389  */
390 function RemoteCallGallery() {
391   RemoteCall.apply(this, arguments);
394 RemoteCallGallery.prototype.__proto__ = RemoteCall.prototype;
397  * Waits until the expected image is shown.
399  * @param {document} document Document.
400  * @param {number} width Expected width of the image.
401  * @param {number} height Expected height of the image.
402  * @param {string|null} name Expected name of the image.
403  * @return {Promise} Promsie to be fulfilled when the check is passed.
404  */
405 RemoteCallGallery.prototype.waitForSlideImage =
406     function(windowId, width, height, name) {
407   var expected = {};
408   if (width)
409     expected.width = width;
410   if (height)
411     expected.height = height;
412   if (name)
413     expected.name = name;
415   return repeatUntil(function() {
416     var query = '.gallery[mode="slide"] .content canvas.fullres';
417     return Promise.all([
418         this.waitForElement(windowId, '.namebox'),
419         this.waitForElement(windowId, query)
420     ]).then(function(args) {
421       var nameBox = args[0];
422       var fullResCanvas = args[1];
423       var actual = {};
424       if (width && fullResCanvas)
425         actual.width = Number(fullResCanvas.attributes.width);
426       if (height && fullResCanvas)
427         actual.height = Number(fullResCanvas.attributes.height);
428       if (name && nameBox)
429         actual.name = nameBox.value;
431       if (!chrome.test.checkDeepEq(expected, actual)) {
432         return pending('Slide mode state, expected is %j, actual is %j.',
433                        expected, actual);
434       }
435       return actual;
436     });
437   }.bind(this));
440 RemoteCallGallery.prototype.changeNameAndWait = function(windowId, newName) {
441   return this.callRemoteTestUtil('changeName', windowId, [newName]
442   ).then(function() {
443     return this.waitForSlideImage(windowId, 0, 0, newName);
444   }.bind(this));
448  * Shorthand for clicking an element.
449  * @param {AppWindow} appWindow Application window.
450  * @param {string} query Query for the element.
451  * @param {Promise} Promise to be fulfilled with the clicked element.
452  */
453 RemoteCallGallery.prototype.waitAndClickElement = function(windowId, query) {
454   return this.waitForElement(windowId, query).then(function(element) {
455     return this.callRemoteTestUtil('fakeMouseClick', windowId, [query])
456     .then(function() { return element; });
457   }.bind(this));
461  * Waits for the "Press Enter" message.
463  * @param {AppWindow} appWindow App window.
464  * @return {Promise} Promise to be fulfilled when the element appears.
465  */
466 RemoteCallGallery.prototype.waitForPressEnterMessage = function(appId) {
467   return this.waitForElement(appId, '.prompt-wrapper .prompt').
468       then(function(element) {
469         chrome.test.assertEq(
470             'Press Enter when done', element.text.trim());
471       });