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.
8 * Sends a test message.
9 * @param {Object} message Message to be sent. It is converted into JSON string
11 * @return {Promise} Promise to be fulfilled with a returned value.
13 function sendTestMessage(message) {
14 return new Promise(function(fulfill) {
15 chrome.test.sendMessage(JSON.stringify(message), fulfill);
20 * Returns promise to be fulfilled after the given milliseconds.
21 * @param {number} time Time in milliseconds.
24 return new Promise(function(callback) {
25 setTimeout(callback, time);
30 * Interval milliseconds between checks of repeatUntil.
34 var REPEAT_UNTIL_INTERVAL = 200;
37 * Interval milliseconds between log output of repeatUntil.
41 var LOG_INTERVAL = 3000;
44 * Returns a pending marker. See also the repeatUntil function.
45 * @param {string} message Pending reason including %s, %d, or %j markers. %j
46 * format an object as JSON.
47 * @param {Array.<*>} var_args Values to be assigined to %x markers.
48 * @return {Object} Object which returns true for the expression: obj instanceof
51 function pending(message, var_args) {
54 var formattedMessage = message.replace(/%[sdj]/g, function(pattern) {
55 var arg = args[index++];
57 case '%s': return String(arg);
58 case '%d': return Number(arg);
59 case '%j': return JSON.stringify(arg);
60 default: return pattern;
63 var pendingMarker = Object.create(pending.prototype);
64 pendingMarker.message = formattedMessage;
69 * Waits until the checkFunction returns a value but a pending marker.
70 * @param {function():*} checkFunction Function to check a condition. It can
71 * return a pending marker created by a pending function.
72 * @return {Promise} Promise to be fulfilled with the return value of
73 * checkFunction when the checkFunction reutrns a value but a pending
76 function repeatUntil(checkFunction) {
77 var logTime = Date.now() + LOG_INTERVAL;
78 var step = function() {
79 return Promise.resolve(checkFunction()).then(function(result) {
80 if (result instanceof pending) {
81 if (Date.now() > logTime) {
82 logTime += LOG_INTERVAL;
84 return wait(REPEAT_UNTIL_INTERVAL).then(step);
94 * Adds the givin entries to the target volume(s).
95 * @param {Array.<string>} volumeNames Names of target volumes.
96 * @param {Array.<TestEntryInfo>} entries List of entries to be added.
97 * @param {function(boolean)=} opt_callback Callback function to be passed the
98 * result of function. The argument is true on success.
99 * @return {Promise} Promise to be fulfilled when the entries are added.
101 function addEntries(volumeNames, entries, opt_callback) {
102 if (volumeNames.length == 0) {
106 var volumeResultPromises = volumeNames.map(function(volume) {
107 return sendTestMessage({
113 var resultPromise = Promise.all(volumeResultPromises);
115 resultPromise.then(opt_callback.bind(null, true),
116 opt_callback.bind(null, false));
118 return resultPromise;
125 var EntryType = Object.freeze({
127 DIRECTORY: 'directory'
134 var SharedOption = Object.freeze({
142 var RootPath = Object.seal({
143 DOWNLOADS: '/must-be-filled-in-test-setup',
144 DRIVE: '/must-be-filled-in-test-setup',
148 * File system entry information for tests.
150 * @param {EntryType} type Entry type.
151 * @param {string} sourceFileName Source file name that provides file contents.
152 * @param {string} targetName Name of entry on the test file system.
153 * @param {string} mimeType Mime type.
154 * @param {SharedOption} sharedOption Shared option.
155 * @param {string} lastModifiedTime Last modified time as a text to be shown in
156 * the last modified column.
157 * @param {string} nameText File name to be shown in the name column.
158 * @param {string} sizeText Size text to be shown in the size column.
159 * @param {string} typeText Type name to be shown in the type column.
162 function TestEntryInfo(type,
172 this.sourceFileName = sourceFileName || '';
173 this.targetPath = targetPath;
174 this.mimeType = mimeType || '';
175 this.sharedOption = sharedOption;
176 this.lastModifiedTime = lastModifiedTime;
177 this.nameText = nameText;
178 this.sizeText = sizeText;
179 this.typeText = typeText;
183 TestEntryInfo.getExpectedRows = function(entries) {
184 return entries.map(function(entry) { return entry.getExpectedRow(); });
188 * Obtains a expected row contents of the file in the file list.
190 TestEntryInfo.prototype.getExpectedRow = function() {
191 return [this.nameText, this.sizeText, this.typeText, this.lastModifiedTime];
195 * Filesystem entries used by the test cases.
196 * @type {Object.<string, TestEntryInfo>}
200 hello: new TestEntryInfo(
201 EntryType.FILE, 'text.txt', 'hello.txt',
202 'text/plain', SharedOption.NONE, 'Sep 4, 1998, 12:34 PM',
203 'hello.txt', '51 bytes', 'Plain text'),
205 world: new TestEntryInfo(
206 EntryType.FILE, 'video.ogv', 'world.ogv',
207 'text/plain', SharedOption.NONE, 'Jul 4, 2012, 10:35 AM',
208 'world.ogv', '59 KB', 'OGG video'),
210 unsupported: new TestEntryInfo(
211 EntryType.FILE, 'random.bin', 'unsupported.foo',
212 'application/x-foo', SharedOption.NONE, 'Jul 4, 2012, 10:36 AM',
213 'unsupported.foo', '8 KB', 'FOO file'),
215 desktop: new TestEntryInfo(
216 EntryType.FILE, 'image.png', 'My Desktop Background.png',
217 'image/png', SharedOption.NONE, 'Jan 18, 2038, 1:02 AM',
218 'My Desktop Background.png', '272 bytes', 'PNG image'),
220 image2: new TestEntryInfo(
221 EntryType.FILE, 'image2.png', 'image2.png',
222 'image/png', SharedOption.NONE, 'Jan 18, 2038, 1:02 AM',
223 'image2.png', '4 KB', 'PNG image'),
225 image3: new TestEntryInfo(
226 EntryType.FILE, 'image3.jpg', 'image3.jpg',
227 'image/jpg', SharedOption.NONE, 'Jan 18, 2038, 1:02 AM',
228 'image3.jpg', '272 bytes', 'JPEG image'),
230 beautiful: new TestEntryInfo(
231 EntryType.FILE, 'music.ogg', 'Beautiful Song.ogg',
232 'text/plain', SharedOption.NONE, 'Nov 12, 2086, 12:00 PM',
233 'Beautiful Song.ogg', '14 KB', 'OGG audio'),
235 photos: new TestEntryInfo(
236 EntryType.DIRECTORY, null, 'photos',
237 null, SharedOption.NONE, 'Jan 1, 1980, 11:59 PM',
238 'photos', '--', 'Folder'),
240 testDocument: new TestEntryInfo(
241 EntryType.FILE, null, 'Test Document',
242 'application/vnd.google-apps.document',
243 SharedOption.NONE, 'Apr 10, 2013, 4:20 PM',
244 'Test Document.gdoc', '--', 'Google document'),
246 testSharedDocument: new TestEntryInfo(
247 EntryType.FILE, null, 'Test Shared Document',
248 'application/vnd.google-apps.document',
249 SharedOption.SHARED, 'Mar 20, 2013, 10:40 PM',
250 'Test Shared Document.gdoc', '--', 'Google document'),
252 newlyAdded: new TestEntryInfo(
253 EntryType.FILE, 'music.ogg', 'newly added file.ogg',
254 'audio/ogg', SharedOption.NONE, 'Sep 4, 1998, 12:00 AM',
255 'newly added file.ogg', '14 KB', 'OGG audio'),
257 directoryA: new TestEntryInfo(
258 EntryType.DIRECTORY, null, 'A',
259 null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
260 'A', '--', 'Folder'),
262 directoryB: new TestEntryInfo(
263 EntryType.DIRECTORY, null, 'A/B',
264 null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
265 'B', '--', 'Folder'),
267 directoryC: new TestEntryInfo(
268 EntryType.DIRECTORY, null, 'A/B/C',
269 null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
270 'C', '--', 'Folder'),
272 directoryD: new TestEntryInfo(
273 EntryType.DIRECTORY, null, 'D',
274 null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
275 'D', '--', 'Folder'),
277 directoryE: new TestEntryInfo(
278 EntryType.DIRECTORY, null, 'D/E',
279 null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
280 'E', '--', 'Folder'),
282 directoryF: new TestEntryInfo(
283 EntryType.DIRECTORY, null, 'D/E/F',
284 null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
285 'F', '--', 'Folder'),
287 zipArchive: new TestEntryInfo(
288 EntryType.FILE, 'archive.zip', 'archive.zip',
289 'application/x-zip', SharedOption.NONE, 'Jan 1, 2014, 1:00 AM',
290 'archive.zip', '533 bytes', 'Zip archive')