Adding Test Fixture for initial test cases for the App Remoting Test Driver. Also...
[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.
10 * @param {string} extensionId ID of extension to be manipulated.
11 * @constructor
13 function RemoteCall(extensionId) {
14 this.extensionId_ = extensionId;
17 /**
18 * Checks whether step by step tests are enabled or not.
19 * @return {Promise<bool>}
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.
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.
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);
52 });
53 }).then(function(stepByStep) {
54 return new Promise(function(onFulfilled) {
55 chrome.runtime.sendMessage(
56 this.extensionId_,
58 func: func,
59 appId: appId,
60 args: args
62 function(var_args) {
63 if (stepByStep) {
64 console.info('Returned value:');
65 console.info(arguments);
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.
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;
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.
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).
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);
118 // Window is not available. Closing is done successfully.
119 return true;
122 }.bind(this));
123 }.bind(this)
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.
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]);
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.
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);
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.
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;
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.
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.');
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.
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
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.
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();
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] = '';
273 if (options.ignoreLastModifiedTime) {
274 files[i][3] = '';
275 expected[i][3] = '';
278 if (!chrome.test.checkDeepEq(expected, files)) {
279 return pending('waitForFiles: expected: %j actual %j.',
280 expected,
281 files);
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.
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;
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);
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.
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);
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.
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;
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.
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);
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
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.
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);
435 return actual;
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.
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.
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());