blob: 4b257856c2a4239919b814658399a0501f8aa977 [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {RemoteCall} from './remote_call.js';
/**
* Sends a command to the controlling test harness, namely and usually, the
* chrome FileManagerBrowserTest harness: it expects the command to contain
* the 'name' of the command, and any required or optional arguments of the
* command, e.g.,
*
* await sendTestMessage({
* name: 'addEntries', // command with volume and entries arguments
* volume: volume,
* entries: entries
* });
*
* @param {Object} command Test command to send. The object is converted to
* a JSON string prior to sending.
* @return {Promise} Promise to be fulfilled with the value returned by the
* chrome.test.sendMessage callback.
*/
export function sendTestMessage(command) {
if (typeof command.name === 'string') {
return new Promise(function(fulfill) {
chrome.test.sendMessage(JSON.stringify(command), fulfill);
});
} else {
const error = 'sendTestMessage requires a command.name <string>';
throw new Error(error);
}
}
/**
* Wait (aka pause, or sleep) for the given time in milliseconds.
* @param {number} time Time in milliseconds.
* @return {Promise} Promise that will resolve after Time in milliseconds
* has elapsed.
*/
export function wait(time) {
return new Promise(function(resolve) {
setTimeout(resolve, time);
});
}
/**
* Verifies if there are no Javascript errors in the given app window by
* asserting the count returned by the app.getErrorCount remote call.
* @param {!RemoteCall} app RemoteCall interface to the app window.
* @param {function()=} callback Completion callback.
* @return {Promise} Promise to be fulfilled on completion.
*/
export async function checkIfNoErrorsOccuredOnApp(app, callback) {
const count = await app.callRemoteTestUtil('getErrorCount', null, []);
chrome.test.assertEq(0, count, 'The error count is not 0.');
if (callback) {
callback();
}
}
/**
* Adds check of chrome.test to the end of the given promise.
* @param {Promise} promise Promise to add the check to.
* @param {Array<!RemoteCall>} apps An array of RemoteCall interfaces.
*/
export async function testPromiseAndApps(promise, apps) {
const finished = chrome.test.callbackPass(function() {
// The callbackPass is necessary to avoid prematurely finishing tests.
// Don't use chrome.test.succeed() here to avoid doubled success log.
});
try {
await promise;
await Promise.all(apps.map(app => checkIfNoErrorsOccuredOnApp(app)));
} catch (error) {
chrome.test.fail(error.stack || error);
return;
}
finished();
}
/**
* Interval milliseconds between checks of repeatUntil.
* @type {number}
* @const
*/
export const REPEAT_UNTIL_INTERVAL = 200;
/**
* Interval milliseconds between log output of repeatUntil.
* @type {number}
* @const
*/
export const LOG_INTERVAL = 3000;
/**
* Returns caller's file, function and line/column number from the call stack.
* @return {string} String with the caller's file name and line/column number,
* as returned by exception stack trace. Example "at /a_file.js:1:1".
*/
export function getCaller() {
const error = new Error('For extracting error.stack');
const ignoreStackLines = 3;
const lines = error.stack.split('\n');
if (ignoreStackLines < lines.length) {
const caller = lines[ignoreStackLines];
// Strip 'chrome-extension://oobinhbdbiehknkpbpejbbpdbkdjmoco' prefix.
return caller.replace(/(chrome-extension:\/\/\w*)/gi, '').trim();
}
return '';
}
/**
* Returns a pending marker. See also the repeatUntil function.
* @param {string} caller name of test function that originated the operation,
* it's the return of getCaller() function.
* @param {string} message Pending reason including %s, %d, or %j markers. %j
* format an object as JSON.
* @param {...*} var_args Values to be assigined to %x markers.
* @return {Object} Object which returns true for the expression: obj instanceof
* pending.
*/
export function pending(caller, message, var_args) {
// |index| is used to ignore caller and message arguments subsisting markers
// (%s, %d and %j) within message with the remaining |arguments|.
let index = 2;
const args = arguments;
message = String(message);
const formattedMessage = message.replace(/%[sdj]/g, function(pattern) {
const arg = args[index++];
switch (pattern) {
case '%s':
return String(arg);
case '%d':
return Number(arg);
case '%j':
return JSON.stringify(arg);
default:
return pattern;
}
});
const pendingMarker = Object.create(pending.prototype);
pendingMarker.message = caller + ': ' + formattedMessage;
return pendingMarker;
}
/**
* Waits until the checkFunction returns a value but a pending marker.
* @param {function():*} checkFunction Function to check a condition. It can
* return a pending marker created by a pending function.
* @return {!Promise} Promise to be fulfilled with the return value of
* checkFunction when the checkFunction reutrns a value but a pending
* marker.
*/
export async function repeatUntil(checkFunction) {
let logTime = Date.now() + LOG_INTERVAL;
while (true) {
const result = await checkFunction();
if (!(result instanceof pending)) {
return result;
}
if (Date.now() > logTime) {
console.warn(result.message);
logTime += LOG_INTERVAL;
}
await wait(REPEAT_UNTIL_INTERVAL);
}
}
/**
* Sends the test |command| to the browser test harness and awaits a 'string'
* result. Calls |callback| with that result.
* @param {Object} command Test command to send. Refer to sendTestMessage()
* above for the expected format of a test |command| object.
* @param {function(string)} callback Completion callback.
* @param {Object=} opt_debug If truthy, log the result.
*/
export async function sendBrowserTestCommand(command, callback, opt_debug) {
const caller = getCaller();
if (typeof command.name !== 'string') {
chrome.test.fail('Invalid test command: ' + JSON.stringify(command));
}
const result = await repeatUntil(async () => {
const tryAgain = pending(caller, 'Sent BrowserTest ' + command.name);
try {
const result = await sendTestMessage(command);
if (typeof result !== 'string') {
return tryAgain;
}
return result;
} catch (error) {
console.log(error.stack || error);
return tryAgain;
}
});
if (opt_debug) {
console.log('BrowserTest ' + command.name + ': ' + result);
}
callback(result);
}
/**
* Get all the browser windows.
* @param {number} expectedInitialCount The number of windows expected before
* opening a new one.
* @return {Object} Object returned from chrome.windows.getAll().
*/
export async function getBrowserWindows(expectedInitialCount = 0) {
const caller = getCaller();
return repeatUntil(async () => {
const result = await new Promise(function(fulfill) {
chrome.windows.getAll({'populate': true}, fulfill);
});
if (result.length === expectedInitialCount) {
return pending(caller, 'getBrowserWindows ' + result.length);
}
return result;
});
}
/**
* Adds the given entries to the target volume(s).
* @param {Array<string>} volumeNames Names of target volumes.
* @param {Array<TestEntryInfo>} entries List of entries to be added.
* @param {function(boolean)=} opt_callback Callback function to be passed the
* result of function. The argument is true on success.
* @return {Promise} Promise to be fulfilled when the entries are added.
*/
export async function addEntries(volumeNames, entries, opt_callback) {
if (volumeNames.length == 0) {
opt_callback && opt_callback(true);
return;
}
const volumeResultPromises = volumeNames.map(function(volume) {
return sendTestMessage({
name: 'addEntries',
volume: volume,
entries: entries,
});
});
if (!opt_callback) {
return volumeResultPromises;
}
try {
await Promise.all(volumeResultPromises);
} catch (error) {
opt_callback(false);
throw error;
}
opt_callback(true);
}
/**
* @enum {string}
* @const
*/
export const EntryType = {
FILE: 'file',
DIRECTORY: 'directory',
LINK: 'link',
SHARED_DRIVE: 'team_drive',
COMPUTER: 'Computer',
};
Object.freeze(EntryType);
/**
* Enumeration that determines the shared status of entries.
* @enum {string}
* @const
*/
export const SharedOption = {
// Not shared.
NONE: 'none',
// Shared but not visible in the 'Shared with me' view.
SHARED: 'shared',
// Shared and appears in the 'Shared With Me' view.
SHARED_WITH_ME: 'sharedWithMe',
// Not directly shared, but belongs to a folder that is shared with me.
// Entries marked as indirectly shared do not have the 'shared' metadata
// field, and thus cannot be located via search for shared items.
INDIRECTLY_SHARED_WITH_ME: 'indirectlySharedWithMe',
};
Object.freeze(SharedOption);
/**
* @typedef {{
* downloads: string,
* drive: string,
* android_files: string,
* }}
*
*/
export let getRootPathsResult;
/**
* @typedef {{
* DOWNLOADS: string,
* DRIVE: string,
* ANDROID_FILES: string,
* }}
*/
export const RootPath = {
DOWNLOADS: '/must-be-filled-in-test-setup',
DRIVE: '/must-be-filled-in-test-setup',
ANDROID_FILES: '/must-be-filled-in-test-setup',
};
Object.seal(RootPath);
/**
* The capabilities (permissions) for the Test Entry. Structure should match
* TestEntryCapabilities in file_manager_browsertest_base.cc. All capabilities
* default to true if not specified.
*
* @typedef {{
* canCopy: (boolean|undefined),
* canDelete: (boolean|undefined),
* canRename: (boolean|undefined),
* canAddChildren: (boolean|undefined),
* canShare: (boolean|undefined),
* }}
*/
export let TestEntryCapabilities;
/**
* The folder features for the test entry. Structure should match
* TestEntryFolderFeature in file_manager_browsertest_base.cc. All features
* default to false is not specified.
*
* @typedef {{
* isMachineRoot: (boolean|undefined),
* isArbitrarySyncFolder: (boolean|undefined),
* isExternalMedia: (boolean|undefined),
* }}
*/
export let TestEntryFolderFeature;
/**
* Parameters to creat a Test Entry in the file manager. Structure should match
* TestEntryInfo in file_manager_browsertest_base.cc.
*
* Field details:
*
* sourceFileName: Source file name that provides file contents (file location
* relative to /chrome/test/data/chromeos/file_manager/).
*
* targetPath: Name of entry on the test file system. Used to determine the
* actual name of the file.
*
* teamDriveName: Name of the team drive this entry is in. Defaults to a blank
* string (no team drive). Team Drive names must be unique.
*
* computerName: Name of the computer this entry is in. Defaults to a blank
* string (no computer). Computer names must be unique.
*
* lastModifiedTime: Last modified time as a text to be shown in the last
* modified column.
*
* nameText: File name to be shown in the name column.
*
* sizeText: Size text to be shown in the size column.
*
* typeText: Type name to be shown in the type column.
*
* capabilities: Capabilities of this file. Defaults to all capabilities
* available (read-write access).
*
* folderFeature: Folder features of this file. Defaults to all features
* disabled.
*
* pinned: Drive pinned status of this file. Defaults to false.
*
* availableOffline: Whether the file is available offline. Defaults to false.
*
* alternateUrl: File's Drive alternate URL. Defaults to an empty string.
*
* @typedef {{
* type: EntryType,
* sourceFileName: (string|undefined),
* targetPath: (string|undefined),
* teamDriveName: (string|undefined),
* computerName: (string|undefined),
* mimeType: (string|undefined),
* sharedOption: (SharedOption|undefined),
* lastModifiedTime: (string|undefined),
* nameText: (string|undefined),
* sizeText: (string|undefined),
* typeText: (string|undefined),
* capabilities: (TestEntryCapabilities|undefined),
* folderFeature: (TestEntryFolderFeature|undefined),
* pinned: (boolean|undefined),
* availableOffline: (boolean|undefined),
* alternateUrl: (string|undefined),
* }}
*/
export let TestEntryInfoOptions;
/**
* File system entry information for tests. Structure should match TestEntryInfo
* in file_manager_browsertest_base.cc
* TODO(sashab): Remove this, rename TestEntryInfoOptions to TestEntryInfo and
* set the defaults in the record definition above.
*/
export class TestEntryInfo {
/**
* @param {TestEntryInfoOptions} options Parameters to create the
* TestEntryInfo.
*/
constructor(options) {
this.type = options.type;
this.sourceFileName = options.sourceFileName || '';
this.thumbnailFileName = options.thumbnailFileName || '';
this.targetPath = options.targetPath;
this.teamDriveName = options.teamDriveName || '';
this.computerName = options.computerName || '';
this.mimeType = options.mimeType || '';
this.sharedOption = options.sharedOption || SharedOption.NONE;
this.lastModifiedTime = options.lastModifiedTime;
this.nameText = options.nameText || '';
this.sizeText = options.sizeText || '';
this.typeText = options.typeText || '';
this.capabilities = options.capabilities;
this.folderFeature = options.folderFeature;
this.pinned = !!options.pinned;
this.availableOffline = !!options.availableOffline;
this.alternateUrl = options.alternateUrl || '';
Object.freeze(this);
}
/**
* Obtains the expected row contents for each file.
* @param {!Array<!TestEntryInfo>} entries
* @return {!Array<!Array<string>>}
*/
static getExpectedRows(entries) {
return entries.map(function(entry) {
return entry.getExpectedRow();
});
}
/**
* Obtains a expected row contents of the file in the file list.
* @return {!Array<string>}
*/
getExpectedRow() {
return [this.nameText, this.sizeText, this.typeText, this.lastModifiedTime];
}
/**
* Returns a new entry with modified attributes specified in the
* `newOptions` object.
* @param {!Object} newOptions The options to be modified.
* @returns {!TestEntryInfo}
*/
cloneWith(newOptions) {
return new TestEntryInfo(/** @type {TestEntryInfoOptions} */ (
Object.assign({}, this, newOptions)));
}
/**
* Clone the existing TestEntryInfo object to a new TestEntryInfo object but
* with modified lastModifiedTime field. This is especially useful for
* constructing TestEntryInfo for Recents view.
*
* @param {string} newDate the new modified date time
* @return {!TestEntryInfo}
*/
cloneWithModifiedDate(newDate) {
return this.cloneWith({lastModifiedTime: newDate});
}
/**
* Clone the existing TestEntryInfo object to a new TestEntryInfo object but
* with modified targetPath field. This is especially useful for testing
* rename functionality.
*
* @param {string} newName the new modified name
* @return {!TestEntryInfo}
*/
cloneWithNewName(newName) {
return this.cloneWith({
targetPath: newName,
nameText: newName,
});
}
}
/**
* Filesystem entries used by the test cases.
* TODO(sashab): Rename 'nameText', 'sizeText' and 'typeText' to
* 'expectedNameText', 'expectedSizeText' and 'expectedTypeText' to reflect that
* they are the expected values for those columns in the file manager.
*
* @type {!Object<string, TestEntryInfo>}
* @const
*/
export const ENTRIES = {
hello: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'hello.txt',
mimeType: 'text/plain',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'hello.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
}),
world: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'video.ogv',
thumbnailFileName: 'image.png',
targetPath: 'world.ogv',
mimeType: 'video/ogg',
lastModifiedTime: 'Jul 4, 2012, 10:35 AM',
nameText: 'world.ogv',
sizeText: '59 KB',
typeText: 'OGG video',
}),
webm: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'world.webm',
targetPath: 'world.webm',
mimeType: 'video/webm',
lastModifiedTime: 'Jul 4, 2012, 10:35 AM',
nameText: 'world.webm',
sizeText: '17 KB',
typeText: 'WebM video',
}),
video: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'video_long.ogv',
targetPath: 'video_long.ogv',
mimeType: 'video/ogg',
lastModifiedTime: 'Jan 14, 2019, 16:01 PM',
nameText: 'video_long.ogv',
sizeText: '166 KB',
typeText: 'OGG video',
}),
subtitle: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'video.vtt',
targetPath: 'world.vtt',
mimeType: 'text/vtt',
lastModifiedTime: 'Feb 7, 2019, 15:03 PM',
nameText: 'world.vtt',
sizeText: '46 bytes',
typeText: 'VTT text',
}),
unsupported: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'random.bin',
targetPath: 'unsupported.foo',
mimeType: 'application/x-foo',
lastModifiedTime: 'Jul 4, 2012, 10:36 AM',
nameText: 'unsupported.foo',
sizeText: '8 KB',
typeText: 'FOO file',
}),
desktop: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'image.png',
thumbnailFileName: 'image.png',
targetPath: 'My Desktop Background.png',
mimeType: 'image/png',
lastModifiedTime: 'Jan 18, 2038, 1:02 AM',
nameText: 'My Desktop Background.png',
sizeText: '272 bytes',
typeText: 'PNG image',
}),
image2: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'image2.png',
// No file extension.
targetPath: 'image2',
mimeType: 'image/png',
lastModifiedTime: 'Jan 18, 2038, 1:02 AM',
nameText: 'image2',
sizeText: '4 KB',
typeText: 'PNG image',
}),
image3: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'image3.jpg',
targetPath: 'image3.jpg',
mimeType: 'image/jpeg',
lastModifiedTime: 'Jan 18, 2038, 1:02 AM',
nameText: 'image3.jpg',
sizeText: '3 KB',
typeText: 'JPEG image',
}),
smallJpeg: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'small.jpg',
targetPath: 'small.jpg',
mimeType: 'image/jpeg',
lastModifiedTime: 'Jan 18, 2038, 1:02 AM',
nameText: 'small.jpg',
sizeText: '1 KB',
typeText: 'JPEG image',
}),
// Used to differentiate between .jpg and .jpeg handling.
sampleJpeg: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'small.jpg',
targetPath: 'sample.jpeg',
mimeType: 'image/jpeg',
lastModifiedTime: 'Jan 18, 2038, 1:02 AM',
nameText: 'sample.jpeg',
sizeText: '1 KB',
typeText: 'JPEG image',
}),
brokenJpeg: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'broken.jpg',
targetPath: 'broken.jpg',
mimeType: 'image/jpeg',
lastModifiedTime: 'Jan 18, 2038, 1:02 AM',
nameText: 'broken.jpg',
sizeText: '1 byte',
typeText: 'JPEG image',
}),
exifImage: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'exif.jpg',
// No mime type.
targetPath: 'exif.jpg',
lastModifiedTime: 'Jan 18, 2038, 1:02 AM',
nameText: 'exif.jpg',
sizeText: '31 KB',
typeText: 'JPEG image',
}),
webpImage: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'image.webp',
// No mime type.
targetPath: 'image.webp',
lastModifiedTime: 'Jan 19, 2021, 1:10 PM',
nameText: 'image.webp',
sizeText: '5 KB',
typeText: 'WebP image',
}),
rawImage: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'raw.orf',
// No mime type.
targetPath: 'raw.orf',
lastModifiedTime: 'May 20, 2019, 10:10 AM',
nameText: 'raw.orf',
sizeText: '214 KB',
typeText: 'ORF image',
}),
nefImage: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'raw.nef',
// No mime type.
targetPath: 'raw.nef',
lastModifiedTime: 'May 9, 2015, 11:16 PM',
nameText: 'raw.nef',
sizeText: '92 KB',
typeText: 'NEF image',
}),
beautiful: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'music.ogg',
// No mime type.
targetPath: 'Beautiful Song.ogg',
lastModifiedTime: 'Nov 12, 2086, 12:00 PM',
nameText: 'Beautiful Song.ogg',
sizeText: '14 KB',
typeText: 'OGG audio',
}),
movFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'video.mov',
targetPath: 'mac.mov',
lastModifiedTime: 'Jul 4, 2012, 10:35 AM',
nameText: 'mac.mov',
sizeText: '875 bytes',
typeText: 'QuickTime video',
}),
docxFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.docx',
targetPath: 'word.docx',
mimeType: 'application/vnd.openxmlformats-officedocument' +
'.wordprocessingml.document',
lastModifiedTime: 'Jul 4, 2038, 10:35 AM',
nameText: 'word.docx',
sizeText: '9 KB',
typeText: 'Word document',
}),
photos: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'photos',
lastModifiedTime: 'Jan 1, 1980, 11:59 PM',
nameText: 'photos',
sizeText: '--',
typeText: 'Folder',
}),
testCSEDocument: new TestEntryInfo({
type: EntryType.FILE,
targetPath: 'Test Encrypted Document',
mimeType: 'application/vnd.google-gsuite.encrypted; ' +
'content="application/vnd.google-apps.document"',
lastModifiedTime: 'Apr 10, 2013, 4:20 PM',
nameText: 'Test Encrypted Document.gdoc',
sizeText: '--',
typeText: 'Google document',
}),
testCSEFile: new TestEntryInfo({
type: EntryType.FILE,
targetPath: 'test-encrypted.txt',
mimeType: 'application/vnd.google-gsuite.encrypted; content="text/plain"',
lastModifiedTime: 'Apr 10, 2013, 4:20 PM',
nameText: 'test-encrypted.txt',
sizeText: '--',
typeText: 'Plain text',
availableOffline: true,
}),
testDocument: new TestEntryInfo({
type: EntryType.FILE,
targetPath: 'Test Document',
mimeType: 'application/vnd.google-apps.document',
lastModifiedTime: 'Apr 10, 2013, 4:20 PM',
nameText: 'Test Document.gdoc',
sizeText: '--',
typeText: 'Google document',
}),
testSharedDocument: new TestEntryInfo({
type: EntryType.FILE,
targetPath: 'Test Shared Document',
mimeType: 'application/vnd.google-apps.document',
sharedOption: SharedOption.SHARED,
lastModifiedTime: 'Mar 20, 2013, 10:40 PM',
nameText: 'Test Shared Document.gdoc',
sizeText: '--',
typeText: 'Google document',
}),
testSharedFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'test.txt',
mimeType: 'text/plain',
sharedOption: SharedOption.SHARED,
lastModifiedTime: 'Mar 20, 2012, 11:40 PM',
nameText: 'test.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
pinned: true,
}),
sharedDirectory: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'Shared',
sharedOption: SharedOption.SHARED,
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'Shared',
sizeText: '--',
typeText: 'Folder',
}),
sharedDirectoryFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'Shared/file.txt',
mimeType: 'text/plain',
sharedOption: SharedOption.SHARED,
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'file.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
}),
newlyAdded: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'music.ogg',
targetPath: 'newly added file.ogg',
mimeType: 'audio/ogg',
lastModifiedTime: 'Sep 4, 1998, 12:00 AM',
nameText: 'newly added file.ogg',
sizeText: '14 KB',
typeText: 'OGG audio',
}),
tallText: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'tall.txt',
targetPath: 'tall.txt',
mimeType: 'text/plain',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'tall.txt',
sizeText: '546 bytes',
typeText: 'Plain text',
}),
plainText: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'plaintext',
// No mime type, no file extension.
targetPath: 'plaintext',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'plaintext',
sizeText: '32 bytes',
typeText: 'Plain text',
}),
utf8Text: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'utf8.txt',
targetPath: 'utf8.txt',
mimeType: 'text/plain',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'utf8.txt',
sizeText: '191 bytes',
typeText: 'Plain text',
}),
mHtml: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'page.mhtml',
targetPath: 'page.mhtml',
mimeType: 'multipart/related',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'page.mhtml',
sizeText: '421 bytes',
typeText: 'HTML document',
}),
tallHtml: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'tall.html',
targetPath: 'tall.html',
mimeType: 'text/html',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'tall.html',
sizeText: '589 bytes',
typeText: 'HTML document',
}),
tallPdf: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'tall.pdf',
targetPath: 'tall.pdf',
mimeType: 'application/pdf',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'tall.pdf',
sizeText: '15 KB',
typeText: 'PDF document',
}),
popupPdf: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'popup.pdf',
targetPath: 'popup.pdf',
mimeType: 'application/pdf',
lastModifiedTime: 'Jul 4, 2000, 10:42 AM',
nameText: 'popup.pdf',
sizeText: '538 bytes',
typeText: 'PDF document',
}),
imgPdf: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'img.pdf',
targetPath: 'imgpdf',
mimeType: 'application/pdf',
lastModifiedTime: 'Jul 4, 2012, 10:35 AM',
nameText: 'imgpdf',
sizeText: '1608 bytes',
typeText: 'PDF document',
}),
smallDocx: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.docx',
targetPath: 'text.docx',
mimeType: 'application/vnd.openxmlformats-officedocument' +
'.wordprocessingml.document',
lastModifiedTime: 'Jan 4, 2019, 10:57 AM',
nameText: 'text.docx',
sizeText: '8.7 KB',
typeText: 'Office document',
alternateUrl: 'https://drive.google.com/open?id=smalldocxid&usp=drive_fs',
}),
smallDocxHosted: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.docx',
targetPath: 'synced.docx',
mimeType: 'application/vnd.openxmlformats-officedocument' +
'.wordprocessingml.document',
lastModifiedTime: 'Jan 4, 2019, 10:57 AM',
nameText: 'synced.docx',
sizeText: '8.7 KB',
typeText: 'Office document',
alternateUrl: 'https://docs.google.com/document/d/smalldocxid' +
'?rtpof=true&usp=drive_fs',
}),
smallDocxPinned: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.docx',
targetPath: 'pinned.docx',
mimeType: 'application/vnd.openxmlformats-officedocument' +
'.wordprocessingml.document',
lastModifiedTime: 'Jan 4, 2019, 10:57 AM',
nameText: 'pinned.docx',
sizeText: '8.7 KB',
typeText: 'Office document',
pinned: true,
alternateUrl: 'https://docs.google.com/document/d/pinneddocxid' +
'?rtpof=true&usp=drive_fs',
}),
smallXlsxPinned: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'sheet.xlsx',
targetPath: 'pinned.xlsx',
mimeType: 'application/vnd.openxmlformats-officedocument' +
'.spreadsheetml.sheet',
lastModifiedTime: 'Jan 10, 2020, 11:58 PM',
nameText: 'pinned.xlsx',
sizeText: '5.7 KB',
typeText: 'Office spreadsheet',
pinned: true,
alternateUrl: 'https://docs.google.com/document/d/pinnedxlsxid' +
'?rtpof=true&usp=drive_fs',
}),
smallPptxPinned: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'presentation.pptx',
targetPath: 'pinned.pptx',
mimeType: 'application/vnd.openxmlformats-officedocument' +
'.presentationml.presentation',
lastModifiedTime: 'Jan 14, 2020, 10:15 AM',
nameText: 'pinned.pptx',
sizeText: '35.2 KB',
typeText: 'Office document',
pinned: true,
alternateUrl: 'https://docs.google.com/document/d/pinnedpptxid' +
'?rtpof=true&usp=drive_fs',
}),
pinned: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'pinned.txt',
mimeType: 'text/plain',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'pinned.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
pinned: true,
}),
directoryA: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'A',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'A',
sizeText: '--',
typeText: 'Folder',
}),
directoryB: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'A/B',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'B',
sizeText: '--',
typeText: 'Folder',
}),
directoryC: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'A/B/C',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'C',
sizeText: '--',
typeText: 'Folder',
}),
directoryD: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'D',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'D',
sizeText: '--',
typeText: 'Folder',
}),
directoryE: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'D/E',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'E',
sizeText: '--',
typeText: 'Folder',
}),
directoryF: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'D/E/F',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'F',
sizeText: '--',
typeText: 'Folder',
}),
dotTrash: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: '.Trash',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: '.Trash',
sizeText: '--',
typeText: 'Folder',
}),
deeplyBurriedSmallJpeg: new TestEntryInfo({
type: EntryType.FILE,
targetPath: 'A/B/C/deep.jpg',
sourceFileName: 'small.jpg',
mimeType: 'image/jpeg',
lastModifiedTime: 'Jan 18, 2038, 1:02 AM',
nameText: 'deep.jpg',
sizeText: '886 bytes',
typeText: 'JPEG image',
}),
linkGtoB: new TestEntryInfo({
type: EntryType.LINK,
targetPath: 'G',
sourceFileName: 'A/B',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'G',
sizeText: '--',
typeText: 'Folder',
}),
linkHtoFile: new TestEntryInfo({
type: EntryType.LINK,
targetPath: 'H.jpg',
sourceFileName: 'A/B/C/deep.jpg',
mimeType: 'image/jpeg',
lastModifiedTime: 'Jan 18, 2038, 1:02 AM',
nameText: 'H.jpg',
sizeText: '886 bytes',
typeText: 'JPEG image',
}),
linkTtoTransitiveDirectory: new TestEntryInfo({
type: EntryType.LINK,
targetPath: 'T',
sourceFileName: 'G/C',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'T',
sizeText: '--',
typeText: 'Folder',
}),
zipArchive: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'archive.zip',
targetPath: 'archive.zip',
mimeType: 'application/x-zip',
lastModifiedTime: 'Jan 1, 2014, 1:00 AM',
nameText: 'archive.zip',
sizeText: '743 bytes',
typeText: 'ZIP archive',
}),
zipSJISArchive: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'sjis.zip',
targetPath: 'sjis.zip',
mimeType: 'application/x-zip',
lastModifiedTime: 'Apr 6, 2022, 1:00 AM',
nameText: 'sjis.zip',
sizeText: '479 bytes',
typeText: 'ZIP archive',
}),
zipExtArchive: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'tera.zip',
targetPath: 'tera.zip',
mimeType: 'application/x-zip',
lastModifiedTime: 'Apr 6, 2022, 1:00 AM',
nameText: 'tera.zip',
sizeText: '250 bytes',
typeText: 'ZIP archive',
}),
debPackage: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'package.deb',
targetPath: 'package.deb',
mimeType: 'application/vnd.debian.binary-package',
lastModifiedTime: 'Jan 1, 2014, 1:00 AM',
nameText: 'package.deb',
sizeText: '724 bytes',
typeText: 'DEB file',
}),
tiniFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'archive.tar.gz',
targetPath: 'test.tini',
mimeType: 'application/gzip',
lastModifiedTime: 'Jan 1, 2014, 1:00 AM',
nameText: 'test.tini',
sizeText: '439 bytes',
typeText: 'Crostini image file',
}),
hiddenFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: '.hiddenfile.txt',
mimeType: 'text/plain',
lastModifiedTime: 'Sep 30, 2014, 3:30 PM',
nameText: '.hiddenfile.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
}),
// Team-drive entries.
teamDriveA: new TestEntryInfo({
type: EntryType.SHARED_DRIVE,
teamDriveName: 'Team Drive A',
capabilities: {
canCopy: true,
canDelete: true,
canRename: true,
canAddChildren: true,
canShare: true,
},
}),
teamDriveAFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'teamDriveAFile.txt',
mimeType: 'text/plain',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'teamDriveAFile.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
teamDriveName: 'Team Drive A',
capabilities: {
canCopy: true,
canDelete: true,
canRename: true,
canAddChildren: false,
canShare: true,
},
}),
teamDriveADirectory: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'teamDriveADirectory',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'teamDriveADirectory',
sizeText: '--',
typeText: 'Folder',
teamDriveName: 'Team Drive A',
capabilities: {
canCopy: true,
canDelete: true,
canRename: true,
canAddChildren: true,
canShare: false,
},
}),
teamDriveAHostedFile: new TestEntryInfo({
type: EntryType.FILE,
targetPath: 'teamDriveAHostedDoc',
mimeType: 'application/vnd.google-apps.document',
lastModifiedTime: 'Apr 10, 2013, 4:20 PM',
nameText: 'teamDriveAHostedDoc.gdoc',
sizeText: '--',
typeText: 'Google document',
teamDriveName: 'Team Drive A',
}),
teamDriveB: new TestEntryInfo({
type: EntryType.SHARED_DRIVE,
teamDriveName: 'Team Drive B',
capabilities: {
canCopy: true,
canDelete: false,
canRename: false,
canAddChildren: false,
canShare: true,
},
}),
teamDriveBFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'teamDriveBFile.txt',
mimeType: 'text/plain',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'teamDriveBFile.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
teamDriveName: 'Team Drive B',
capabilities: {
canCopy: true,
canDelete: false,
canRename: false,
canAddChildren: false,
canShare: true,
},
}),
teamDriveBDirectory: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'teamDriveBDirectory',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'teamDriveBDirectory',
sizeText: '--',
typeText: 'Folder',
teamDriveName: 'Team Drive B',
capabilities: {
canCopy: true,
canDelete: false,
canRename: false,
canAddChildren: false,
canShare: true,
},
}),
// Computer entries.
computerA: new TestEntryInfo({
type: EntryType.COMPUTER,
computerName: 'Computer A',
folderFeature: {
isMachineRoot: true,
},
}),
computerAFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'computerAFile.txt',
mimeType: 'text/plain',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'computerAFile.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
computerName: 'Computer A',
capabilities: {
canCopy: true,
canDelete: true,
canRename: true,
canAddChildren: false,
canShare: true,
},
}),
computerAdirectoryA: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'A',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
computerName: 'Computer A',
nameText: 'A',
sizeText: '--',
typeText: 'Folder',
}),
// Read-only and write-restricted entries.
// TODO(sashab): Generate all combinations of capabilities inside the test, to
// ensure maximum coverage.
// A folder that can't be renamed or deleted or have children added, but can
// be copied and shared.
readOnlyFolder: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'Read-Only Folder',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'Read-Only Folder',
sizeText: '--',
typeText: 'Folder',
capabilities: {
canCopy: true,
canAddChildren: false,
canRename: false,
canDelete: false,
canShare: true,
},
}),
// A google doc file that can't be renamed or deleted, but can be copied and
// shared.
readOnlyDocument: new TestEntryInfo({
type: EntryType.FILE,
targetPath: 'Read-Only Doc',
mimeType: 'application/vnd.google-apps.document',
lastModifiedTime: 'Mar 20, 2013, 10:40 PM',
nameText: 'Read-Only Doc.gdoc',
sizeText: '--',
typeText: 'Google document',
capabilities: {
canCopy: true,
canAddChildren: false,
canRename: false,
canDelete: false,
canShare: true,
},
}),
// A google doc file that can't be renamed, deleted, copied or shared.
readOnlyStrictDocument: new TestEntryInfo({
type: EntryType.FILE,
targetPath: 'Read-Only (Strict) Doc',
mimeType: 'application/vnd.google-apps.document',
lastModifiedTime: 'Mar 20, 2013, 10:40 PM',
nameText: 'Read-Only (Strict) Doc.gdoc',
sizeText: '--',
typeText: 'Google document',
capabilities: {
canCopy: false,
canAddChildren: false,
canRename: false,
canDelete: false,
canShare: false,
},
}),
// A regular file that can't be renamed or deleted, but can be copied and
// shared.
readOnlyFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'image4.jpg',
targetPath: 'Read-Only File.jpg',
mimeType: 'image/jpeg',
lastModifiedTime: 'Jan 18, 2038, 1:02 AM',
nameText: 'Read-Only File.jpg',
sizeText: '9 KB',
typeText: 'JPEG image',
capabilities: {
canCopy: true,
canAddChildren: false,
canRename: false,
canDelete: false,
canShare: true,
},
}),
// A ZIP file that can't be renamed or deleted, but can be copied and
// shared.
readOnlyZipFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'archive.zip',
targetPath: 'archive.zip',
mimeType: 'application/x-zip',
lastModifiedTime: 'Jan 1, 2014, 1:00 AM',
nameText: 'archive.zip',
sharedOption: SharedOption.SHARED,
sizeText: '743 bytes',
typeText: 'ZIP archive',
capabilities: {
canCopy: true,
canAddChildren: false,
canRename: false,
canDelete: false,
canShare: true,
},
}),
// A regular file that can't be renamed, but can be deleted.
deletableFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'Deletable File.txt',
mimeType: 'text/plain',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'Deletable File.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
capabilities: {
canCopy: true,
canAddChildren: false,
canRename: false,
canDelete: true,
},
}),
// A regular file that can't be deleted, but can be renamed.
renamableFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'Renamable File.txt',
mimeType: 'text/plain',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'Renamable File.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
capabilities: {
canCopy: true,
canAddChildren: false,
canRename: true,
canDelete: false,
},
}),
// Default Android directories.
directoryDocuments: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'Documents',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'Documents',
sizeText: '--',
typeText: 'Folder',
capabilities: {
canCopy: false,
canAddChildren: true,
canRename: false,
canDelete: false,
canShare: true,
},
}),
directoryMovies: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'Movies',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'Movies',
sizeText: '--',
typeText: 'Folder',
capabilities: {
canCopy: false,
canAddChildren: true,
canRename: false,
canDelete: false,
canShare: true,
},
}),
directoryMusic: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'Music',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'Music',
sizeText: '--',
typeText: 'Folder',
capabilities: {
canCopy: false,
canAddChildren: true,
canRename: false,
canDelete: false,
canShare: true,
},
}),
directoryPictures: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'Pictures',
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'Pictures',
sizeText: '--',
typeText: 'Folder',
capabilities: {
canCopy: false,
canAddChildren: true,
canRename: false,
canDelete: false,
canShare: true,
},
}),
// Android test files.
documentsText: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'Documents/android.txt',
mimeType: 'text/plain',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'android.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
}),
moviesVideo: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'world.webm',
targetPath: 'Movies/android.webm',
mimeType: 'video/webm',
lastModifiedTime: 'Jul 4, 2012, 10:35 AM',
nameText: 'android.webm',
sizeText: '17 KB',
typeText: 'WebM video',
}),
musicAudio: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'music.ogg',
targetPath: 'Music/android.ogg',
mimeType: 'audio/ogg',
lastModifiedTime: 'Sep 4, 1998, 12:00 AM',
nameText: 'android.ogg',
sizeText: '14 KB',
typeText: 'OGG audio',
}),
picturesImage: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'image3.jpg',
targetPath: 'Pictures/android.jpg',
mimeType: 'image/jpeg',
lastModifiedTime: 'Jan 18, 2012, 1:02 AM',
nameText: 'android.jpg',
sizeText: '3 KB',
typeText: 'JPEG image',
}),
neverSync: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'never-sync.txt',
mimeType: 'text/plain',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'never-sync.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
}),
sharedWithMeDirectory: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'Shared Directory',
sharedOption: SharedOption.SHARED_WITH_ME,
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'Shared Directory',
sizeText: '--',
typeText: 'Folder',
}),
sharedWithMeDirectoryFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'Shared Directory/file.txt',
mimeType: 'text/plain',
sharedOption: SharedOption.INDIRECTLY_SHARED_WITH_ME,
lastModifiedTime: 'Jan 1, 2000, 1:00 AM',
nameText: 'file.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
}),
crdownload: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'hello.crdownload',
mimeType: 'application/octet-stream',
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
nameText: 'hello.crdownload',
sizeText: '51 bytes',
typeText: 'CRDOWNLOAD file',
}),
pluginVm: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: 'PvmDefault',
lastModifiedTime: 'Jan 1, 1980, 11:59 PM',
nameText: 'Windows Files',
sizeText: '--',
typeText: 'Folder',
}),
invalidLastModifiedDate: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'text.txt',
targetPath: 'invalidLastModifiedDate.txt',
mimeType: 'text/plain',
nameText: 'invalidLastModifiedDate.txt',
sizeText: '51 bytes',
typeText: 'Plain text',
}),
trashRootDirectory: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: '.Trash',
lastModifiedTime: 'Jan 1, 1980, 11:59 PM',
nameText: '.Trash',
sizeText: '--',
typeText: 'Folder',
}),
trashInfoDirectory: new TestEntryInfo({
type: EntryType.DIRECTORY,
targetPath: '.Trash/info',
lastModifiedTime: 'Jan 1, 1980, 11:59 PM',
nameText: 'info',
sizeText: '--',
typeText: 'Folder',
}),
oldTrashInfoFile: new TestEntryInfo({
type: EntryType.FILE,
sourceFileName: 'old_file.trashinfo',
targetPath: '.Trash/info/hello.txt.trashinfo',
lastModifiedTime: 'Jan 1, 1980, 11:59 PM',
mimeType: 'text/plan',
nameText: 'hello.txt.trashinfo',
sizeText: '64 bytes',
typeText: 'TRASHINFO',
}),
};
/**
* Creates a test file, which can be inside folders, however parent folders
* have to be created by the caller using |createTestFolder|.
* @param {string} path File path to be created,
* @return {TestEntryInfo}
*/
export function createTestFile(path) {
const name = path.split('/').pop();
return new TestEntryInfo({
targetPath: path,
nameText: name,
type: EntryType.FILE,
lastModifiedTime: 'Sep 4, 1998, 12:34 PM',
sizeText: '51 bytes',
typeText: 'Plain text',
sourceFileName: 'text.txt',
mimeType: 'text/plain',
});
}
/**
* Returns the count for |value| for the histogram |name|.
* @param {string} name The histogram to be queried.
* @param {number} value The value within that histogram to query.
* @return {!Promise<number>} A promise fulfilled with the count.
*/
export async function getHistogramCount(name, value) {
const result = await sendTestMessage({
'name': 'getHistogramCount',
'histogramName': name,
'value': value,
});
return /** @type {number} */ (JSON.parse(result));
}
/**
* Returns the sum for for the histogram |name|.
* @param {string} name The histogram to be queried.
* @return {!Promise<number>} A promise fulfilled with the sum.
*/
export async function getHistogramSum(name) {
const result = await sendTestMessage({
'name': 'getHistogramSum',
'histogramName': name,
});
return /** @type {number} */ (parseInt(JSON.parse(result), 10));
}
/**
* Checks the expected total count for the histogram |name|.
* @param {string} name The histogram to be queried.
* @param {number} count The expected sample count.
*/
export async function expectHistogramTotalCount(name, count) {
await sendTestMessage({
'name': 'expectHistogramTotalCount',
'histogramName': name,
'count': count,
});
}
/**
* Returns the count for the user action |name|.
* @param {string} name The user action to be queried.
* @return {!Promise<number>} A promise fulfilled with the count.
*/
export async function getUserActionCount(name) {
const result = await sendTestMessage({
'name': 'getUserActionCount',
'userActionName': name,
});
return /** @type {number} */ (JSON.parse(result));
}
/**
* Returns a date time string with diff days. This can be used as the
* lastModifiedTime field of TestEntryInfo object, which is useful to construct
* a recent file.
* @param {number} diffDays how many days in diff
* @return {string}
*/
export function getDateWithDayDiff(diffDays) {
const nowDate = new Date();
nowDate.setDate(nowDate.getDate() - diffDays);
// Format: "May 2, 2021, 11:25 AM"
return formatDate(nowDate);
}
/**
* Formats the date to be able to compare to Files app date.
*/
export function formatDate(date) {
return sanitizeDate(date.toLocaleString('default', {
month: 'short',
day: 'numeric',
year: 'numeric',
hour12: true,
hour: 'numeric',
minute: 'numeric',
}));
}
/**
* Sanitizes the formatted date. Replaces unusual space with normal space.
* @param {string} strDate the date already in the string format.
* @return {string}
*/
export function sanitizeDate(strDate) {
return strDate.replace('\u202f', ' ');
}