[Android] Implement 3-way sensor fallback for Device Orientation.
[chromium-blink-merge.git] / ui / file_manager / integration_tests / test_util.js
blob2db86ff9fc5e814299d0b020836f0dd6fdced7a7
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  * Sends a test message.
9  * @param {Object} message Message to be sent. It is converted into JSON string
10  *     before sending.
11  * @return {Promise} Promise to be fulfilled with a returned value.
12  */
13 function sendTestMessage(message) {
14   return new Promise(function(fulfill) {
15     chrome.test.sendMessage(JSON.stringify(message), fulfill);
16   });
19 /**
20  * Returns promise to be fulfilled after the given milliseconds.
21  * @param {number} time Time in milliseconds.
22  */
23 function wait(time) {
24   return new Promise(function(callback) {
25     setTimeout(callback, time);
26   });
29 /**
30  * Verifies if there are no Javascript errors in any of the app windows.
31  * @param {function()} Completion callback.
32  */
33 function checkIfNoErrorsOccuredOnApp(app, callback) {
34   var countPromise = app.callRemoteTestUtil('getErrorCount', null, []);
35   countPromise.then(function(count) {
36     chrome.test.assertEq(0, count, 'The error count is not 0.');
37     callback();
38   });
41 /**
42  * Adds check of chrome.test to the end of the given promise.
43  * @param {Promise} promise Promise.
44  */
45 function testPromiseAndApps(promise, apps) {
46   promise.then(function() {
47     return Promise.all(
48         apps.map(function(app) {
49           return new Promise(checkIfNoErrorsOccuredOnApp.bind(null, app));
50         }));
51   }).then(chrome.test.callbackPass(function() {
52     // The callbacPass is necessary to avoid prematurely finishing tests.
53     // Don't put chrome.test.succeed() here to avoid doubled success log.
54   }), function(error) {
55     chrome.test.fail(error.stack || error);
56   });
59 /**
60  * Interval milliseconds between checks of repeatUntil.
61  * @type {number}
62  * @const
63  */
64 var REPEAT_UNTIL_INTERVAL = 200;
66 /**
67  * Interval milliseconds between log output of repeatUntil.
68  * @type {number}
69  * @const
70  */
71 var LOG_INTERVAL = 3000;
73 /**
74  * Returns a pending marker. See also the repeatUntil function.
75  * @param {string} message Pending reason including %s, %d, or %j markers. %j
76  *     format an object as JSON.
77  * @param {Array<*>} var_args Values to be assigined to %x markers.
78  * @return {Object} Object which returns true for the expression: obj instanceof
79  *     pending.
80  */
81 function pending(message, var_args) {
82   var index = 1;
83   var args = arguments;
84   var formattedMessage = message.replace(/%[sdj]/g, function(pattern) {
85     var arg = args[index++];
86     switch(pattern) {
87       case '%s': return String(arg);
88       case '%d': return Number(arg);
89       case '%j': return JSON.stringify(arg);
90       default: return pattern;
91     }
92   });
93   var pendingMarker = Object.create(pending.prototype);
94   pendingMarker.message = formattedMessage;
95   return pendingMarker;
98 /**
99  * Waits until the checkFunction returns a value but a pending marker.
100  * @param {function():*} checkFunction Function to check a condition. It can
101  *     return a pending marker created by a pending function.
102  * @return {Promise} Promise to be fulfilled with the return value of
103  *     checkFunction when the checkFunction reutrns a value but a pending
104  *     marker.
105  */
106 function repeatUntil(checkFunction) {
107   var logTime = Date.now() + LOG_INTERVAL;
108   var step = function() {
109     return Promise.resolve(checkFunction()).then(function(result) {
110       if (result instanceof pending) {
111         if (Date.now() > logTime) {
112           console.warn(result.message);
113           logTime += LOG_INTERVAL;
114         }
115         return wait(REPEAT_UNTIL_INTERVAL).then(step);
116       } else {
117         return result;
118       }
119     });
120   };
121   return step();
125  * Adds the givin entries to the target volume(s).
126  * @param {Array<string>} volumeNames Names of target volumes.
127  * @param {Array<TestEntryInfo>} entries List of entries to be added.
128  * @param {function(boolean)=} opt_callback Callback function to be passed the
129  *     result of function. The argument is true on success.
130  * @return {Promise} Promise to be fulfilled when the entries are added.
131  */
132 function addEntries(volumeNames, entries, opt_callback) {
133   if (volumeNames.length == 0) {
134     callback(true);
135     return;
136   }
137   var volumeResultPromises = volumeNames.map(function(volume) {
138     return sendTestMessage({
139       name: 'addEntries',
140       volume: volume,
141       entries: entries
142     });
143   });
144   var resultPromise = Promise.all(volumeResultPromises);
145   if (opt_callback) {
146     resultPromise.then(opt_callback.bind(null, true),
147                        opt_callback.bind(null, false));
148   }
149   return resultPromise;
153  * @enum {string}
154  * @const
155  */
156 var EntryType = Object.freeze({
157   FILE: 'file',
158   DIRECTORY: 'directory'
162  * @enum {string}
163  * @const
164  */
165 var SharedOption = Object.freeze({
166   NONE: 'none',
167   SHARED: 'shared'
171  * @enum {string}
172  */
173 var RootPath = Object.seal({
174   DOWNLOADS: '/must-be-filled-in-test-setup',
175   DRIVE: '/must-be-filled-in-test-setup',
179  * File system entry information for tests.
181  * @param {EntryType} type Entry type.
182  * @param {string} sourceFileName Source file name that provides file contents.
183  * @param {string} targetName Name of entry on the test file system.
184  * @param {string} mimeType Mime type.
185  * @param {SharedOption} sharedOption Shared option.
186  * @param {string} lastModifiedTime Last modified time as a text to be shown in
187  *     the last modified column.
188  * @param {string} nameText File name to be shown in the name column.
189  * @param {string} sizeText Size text to be shown in the size column.
190  * @param {string} typeText Type name to be shown in the type column.
191  * @constructor
192  */
193 function TestEntryInfo(type,
194                        sourceFileName,
195                        targetPath,
196                        mimeType,
197                        sharedOption,
198                        lastModifiedTime,
199                        nameText,
200                        sizeText,
201                        typeText) {
202   this.type = type;
203   this.sourceFileName = sourceFileName || '';
204   this.targetPath = targetPath;
205   this.mimeType = mimeType || '';
206   this.sharedOption = sharedOption;
207   this.lastModifiedTime = lastModifiedTime;
208   this.nameText = nameText;
209   this.sizeText = sizeText;
210   this.typeText = typeText;
211   Object.freeze(this);
214 TestEntryInfo.getExpectedRows = function(entries) {
215   return entries.map(function(entry) { return entry.getExpectedRow(); });
219  * Obtains a expected row contents of the file in the file list.
220  */
221 TestEntryInfo.prototype.getExpectedRow = function() {
222   return [this.nameText, this.sizeText, this.typeText, this.lastModifiedTime];
226  * Filesystem entries used by the test cases.
227  * @type {Object<TestEntryInfo>}
228  * @const
229  */
230 var ENTRIES = {
231   hello: new TestEntryInfo(
232       EntryType.FILE, 'text.txt', 'hello.txt',
233       'text/plain', SharedOption.NONE, 'Sep 4, 1998, 12:34 PM',
234       'hello.txt', '51 bytes', 'Plain text'),
236   world: new TestEntryInfo(
237       EntryType.FILE, 'video.ogv', 'world.ogv',
238       'video/ogg', SharedOption.NONE, 'Jul 4, 2012, 10:35 AM',
239       'world.ogv', '59 KB', 'OGG video'),
241   unsupported: new TestEntryInfo(
242       EntryType.FILE, 'random.bin', 'unsupported.foo',
243       'application/x-foo', SharedOption.NONE, 'Jul 4, 2012, 10:36 AM',
244       'unsupported.foo', '8 KB', 'FOO file'),
246   desktop: new TestEntryInfo(
247       EntryType.FILE, 'image.png', 'My Desktop Background.png',
248       'image/png', SharedOption.NONE, 'Jan 18, 2038, 1:02 AM',
249       'My Desktop Background.png', '272 bytes', 'PNG image'),
251   // An image file without an extension, to confirm that file type detection
252   // using mime types works fine.
253   image2: new TestEntryInfo(
254       EntryType.FILE, 'image2.png', 'image2',
255       'image/png', SharedOption.NONE, 'Jan 18, 2038, 1:02 AM',
256       'image2', '4 KB', 'PNG image'),
258   image3: new TestEntryInfo(
259       EntryType.FILE, 'image3.jpg', 'image3.jpg',
260       'image/jpeg', SharedOption.NONE, 'Jan 18, 2038, 1:02 AM',
261       'image3.jpg', '3 KB', 'JPEG image'),
263   // An ogg file without a mime type, to confirm that file type detection using
264   // file extensions works fine.
265   beautiful: new TestEntryInfo(
266       EntryType.FILE, 'music.ogg', 'Beautiful Song.ogg',
267       null, SharedOption.NONE, 'Nov 12, 2086, 12:00 PM',
268       'Beautiful Song.ogg', '14 KB', 'OGG audio'),
270   photos: new TestEntryInfo(
271       EntryType.DIRECTORY, null, 'photos',
272       null, SharedOption.NONE, 'Jan 1, 1980, 11:59 PM',
273       'photos', '--', 'Folder'),
275   testDocument: new TestEntryInfo(
276       EntryType.FILE, null, 'Test Document',
277       'application/vnd.google-apps.document',
278       SharedOption.NONE, 'Apr 10, 2013, 4:20 PM',
279       'Test Document.gdoc', '--', 'Google document'),
281   testSharedDocument: new TestEntryInfo(
282       EntryType.FILE, null, 'Test Shared Document',
283       'application/vnd.google-apps.document',
284       SharedOption.SHARED, 'Mar 20, 2013, 10:40 PM',
285       'Test Shared Document.gdoc', '--', 'Google document'),
287   newlyAdded: new TestEntryInfo(
288       EntryType.FILE, 'music.ogg', 'newly added file.ogg',
289       'audio/ogg', SharedOption.NONE, 'Sep 4, 1998, 12:00 AM',
290       'newly added file.ogg', '14 KB', 'OGG audio'),
292   directoryA: new TestEntryInfo(
293       EntryType.DIRECTORY, null, 'A',
294       null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
295       'A', '--', 'Folder'),
297   directoryB: new TestEntryInfo(
298       EntryType.DIRECTORY, null, 'A/B',
299       null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
300       'B', '--', 'Folder'),
302   directoryC: new TestEntryInfo(
303       EntryType.DIRECTORY, null, 'A/B/C',
304       null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
305       'C', '--', 'Folder'),
307   directoryD: new TestEntryInfo(
308       EntryType.DIRECTORY, null, 'D',
309       null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
310       'D', '--', 'Folder'),
312   directoryE: new TestEntryInfo(
313       EntryType.DIRECTORY, null, 'D/E',
314       null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
315       'E', '--', 'Folder'),
317   directoryF: new TestEntryInfo(
318       EntryType.DIRECTORY, null, 'D/E/F',
319       null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
320       'F', '--', 'Folder'),
322   zipArchive: new TestEntryInfo(
323       EntryType.FILE, 'archive.zip', 'archive.zip',
324       'application/x-zip', SharedOption.NONE, 'Jan 1, 2014, 1:00 AM',
325       'archive.zip', '533 bytes', 'Zip archive')