Commit 9d7b91ec authored by Sasha Morrissey's avatar Sasha Morrissey Committed by Commit Bot

Check for canRename capability when renaming files in the Files App

Also added integration tests, and moved existing delete tests to be in
one file specific to testing context menu items (context_menu.js).

Test: browser_test --gtest-filter="ContextMenu/FilesApp*"
Bug: 719959
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: I5c8d2e71697ecdc273f8d41d9b919b5be12b1519
Reviewed-on: https://chromium-review.googlesource.com/1068769Reviewed-by: default avatarLuciano Pacheco <lucmult@chromium.org>
Commit-Queue: Sasha Morrissey <sashab@chromium.org>
Cr-Commit-Position: refs/heads/master@{#566648}
parent 2fac1e71
...@@ -197,17 +197,24 @@ WRAPPED_INSTANTIATE_TEST_CASE_P( ...@@ -197,17 +197,24 @@ WRAPPED_INSTANTIATE_TEST_CASE_P(
TestCase("renameNewFolderDownloads"), TestCase("renameNewFolderDownloads"),
TestCase("renameNewFolderDrive"))); TestCase("renameNewFolderDrive")));
WRAPPED_INSTANTIATE_TEST_CASE_P(
ContextMenu, /* context_menu.js */
FilesAppBrowserTest,
::testing::Values(TestCase("checkDeleteEnabledForReadWriteFile"),
TestCase("checkDeleteDisabledForReadOnlyDocument"),
TestCase("checkDeleteDisabledForReadOnlyFile"),
TestCase("checkDeleteDisabledForReadOnlyFolder"),
TestCase("checkRenameEnabledForReadWriteFile"),
TestCase("checkRenameDisabledForReadOnlyDocument"),
TestCase("checkRenameDisabledForReadOnlyFile"),
TestCase("checkRenameDisabledForReadOnlyFolder")));
WRAPPED_INSTANTIATE_TEST_CASE_P( WRAPPED_INSTANTIATE_TEST_CASE_P(
Delete, /* delete.js */ Delete, /* delete.js */
FilesAppBrowserTest, FilesAppBrowserTest,
::testing::Values( ::testing::Values(TestCase("deleteMenuItemNoEntrySelected"),
TestCase("deleteMenuItemNoEntrySelected"), TestCase("deleteEntryWithToolbar").InGuestMode(),
TestCase("deleteEntryWithToolbar").InGuestMode(), TestCase("deleteEntryWithToolbar")));
TestCase("deleteEntryWithToolbar"),
TestCase("deleteContextMenuItemDisabledForReadOnlyDocument"),
TestCase("deleteContextMenuItemDisabledForReadOnlyFile"),
TestCase("deleteContextMenuItemDisabledForReadOnlyFolder"),
TestCase("deleteContextMenuItemEnabledForReadWriteFile")));
WRAPPED_INSTANTIATE_TEST_CASE_P(QuickView, /* quick_view.js */ WRAPPED_INSTANTIATE_TEST_CASE_P(QuickView, /* quick_view.js */
FilesAppBrowserTest, FilesAppBrowserTest,
......
...@@ -1176,8 +1176,12 @@ CommandHandler.COMMANDS_['rename'] = /** @type {Command} */ ({ ...@@ -1176,8 +1176,12 @@ CommandHandler.COMMANDS_['rename'] = /** @type {Command} */ ({
CommandUtil.getParentEntry(renameTarget, fileManager.directoryModel); CommandUtil.getParentEntry(renameTarget, fileManager.directoryModel);
var locationInfo = parentEntry ? var locationInfo = parentEntry ?
fileManager.volumeManager.getLocationInfo(parentEntry) : null; fileManager.volumeManager.getLocationInfo(parentEntry) : null;
const volumeIsNotReadOnly = !!locationInfo && !locationInfo.isReadOnly;
// Check if canRename is true or undefined, but not false.
var metadata = fileManager.metadataModel_.getCache(entries, ['canRename']);
const canRenameAllItems = metadata.every(item => item.canRename !== false);
event.canExecute = event.canExecute =
entries.length === 1 && !!locationInfo && !locationInfo.isReadOnly; entries.length === 1 && volumeIsNotReadOnly && canRenameAllItems;
event.command.setHidden(false); event.command.setHidden(false);
} }
}); });
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* Tests that check the context menu displays the right options (enabled and
* disabled) for different types of files.
*
* The names passed to the tests are file names to select. They are generated
* from COMPLEX_DRIVE_ENTRY_SET (see setupAndWaitUntilReady).
*
* TODO(sashab): Generate the entries used in these tests at runtime, by
* creating entries with pre-set combinations of permissions and ensuring the
* outcome is always as expected.
*/
/**
* Tests that the specified menu item is in |expectedEnabledState| when the
* entry at |path| is selected.
*
* @param {string} commandId ID of the command in the context menu to check.
* @param {string} path Path to the file to open the context menu for.
* @param {boolean} expectedEnabledState True if the command should be enabled
* in the context menu, false if not.
*/
function checkContextMenu(commandId, path, expectedEnabledState) {
let appId;
StepsRunner.run([
// Set up Files App.
function() {
setupAndWaitUntilReady(
null, RootPath.DRIVE, this.next, BASIC_LOCAL_ENTRY_SET,
COMPLEX_DRIVE_ENTRY_SET);
},
// Select the file.
function(results) {
appId = results.windowId;
remoteCall.callRemoteTestUtil('selectFile', appId, [path], this.next);
},
// Wait for the file to be selected.
function(result) {
chrome.test.assertTrue(!!result);
remoteCall.waitForElement(appId, '.table-row[selected]').then(this.next);
},
// Right-click on the file.
function() {
remoteCall.callRemoteTestUtil(
'fakeMouseRightClick', appId, ['.table-row[selected]'], this.next);
},
// Wait for the context menu to appear.
function(result) {
chrome.test.assertTrue(!!result);
remoteCall.waitForElement(appId, '#file-context-menu:not([hidden])')
.then(this.next);
},
// Wait for the command option to appear.
function() {
let query;
if (expectedEnabledState) {
query = `[command="#${commandId}"]:not([hidden]):not([disabled])`;
} else {
query = `[command="#${commandId}"][disabled]:not([hidden])`;
}
remoteCall.waitForElement(appId, query).then(this.next);
},
// Check for Javascript errors.
function() {
checkIfNoErrorsOccured(this.next);
}
]);
}
/**
* Tests that the Delete menu item is enabled if a read-write entry is selected.
*/
testcase.checkDeleteEnabledForReadWriteFile = function() {
checkContextMenu('delete', 'hello.txt', true);
};
/**
* Tests that the Delete menu item is disabled if a read-only document is
* selected.
*/
testcase.checkDeleteDisabledForReadOnlyDocument = function() {
checkContextMenu('delete', 'Read-Only Doc.gdoc', false);
};
/**
* Tests that the Delete menu item is disabled if a read-only file is selected.
*/
testcase.checkDeleteDisabledForReadOnlyFile = function() {
checkContextMenu('delete', 'Read-Only File.jpg', false);
};
/**
* Tests that the Delete menu item is disabled if a read-only folder is
* selected.
*/
testcase.checkDeleteDisabledForReadOnlyFolder = function() {
checkContextMenu('delete', 'Read-Only Folder', false);
};
/**
* Tests that the Rename menu item is enabled if a read-write entry is selected.
*/
testcase.checkRenameEnabledForReadWriteFile = function() {
checkContextMenu('rename', 'hello.txt', true);
};
/**
* Tests that the Rename menu item is disabled if a read-only document is
* selected.
*/
testcase.checkRenameDisabledForReadOnlyDocument = function() {
checkContextMenu('rename', 'Read-Only Doc.gdoc', false);
};
/**
* Tests that the Rename menu item is disabled if a read-only file is selected.
*/
testcase.checkRenameDisabledForReadOnlyFile = function() {
checkContextMenu('rename', 'Read-Only File.jpg', false);
};
/**
* Tests that the Rename menu item is disabled if a read-only folder is
* selected.
*/
testcase.checkRenameDisabledForReadOnlyFolder = function() {
checkContextMenu('rename', 'Read-Only Folder', false);
};
...@@ -83,88 +83,3 @@ testcase.deleteEntryWithToolbar = function() { ...@@ -83,88 +83,3 @@ testcase.deleteEntryWithToolbar = function() {
}); });
})); }));
}; };
/**
* Tests that the Delete menu item is in |deleteEnabledState| when the entry
* at |path| is selected.
*
* @param {string} path Path to the file to try and delete.
* @param {boolean} deleteEnabledState True if the delete command should be
* enabled in the context menu, false if not.
*/
function deleteContextMenu(path, deleteEnabledState) {
var appId;
StepsRunner.run([
// Set up Files App.
function() {
setupAndWaitUntilReady(
null, RootPath.DRIVE, this.next, BASIC_LOCAL_ENTRY_SET,
COMPLEX_DRIVE_ENTRY_SET);
},
// Select the read-only file.
function(results) {
appId = results.windowId;
remoteCall.callRemoteTestUtil('selectFile', appId, [path], this.next);
},
// Wait for the file to be selected.
function(result) {
chrome.test.assertTrue(!!result);
remoteCall.waitForElement(appId, '.table-row[selected]').then(this.next);
},
// Right-click on the file.
function() {
remoteCall.callRemoteTestUtil(
'fakeMouseRightClick', appId, ['.table-row[selected]'], this.next);
},
// Wait for the context menu to appear.
function(result) {
chrome.test.assertTrue(!!result);
remoteCall.waitForElement(appId, '#file-context-menu:not([hidden])')
.then(this.next);
},
// Wait for the "Delete" option to appear.
function() {
var query;
if (deleteEnabledState) {
query = '[command="#delete"]:not([hidden]):not([disabled])';
} else {
query = '[command="#delete"][disabled]:not([hidden])';
}
remoteCall.waitForElement(appId, query).then(this.next);
},
// Check for Javascript errors.
function() {
checkIfNoErrorsOccured(this.next);
}
]);
}
/**
* Tests that the Delete menu item is disabled if a read-only document is
* selected.
*/
testcase.deleteContextMenuItemDisabledForReadOnlyDocument = function() {
deleteContextMenu('Read-Only Doc.gdoc', false);
};
/**
* Tests that the Delete menu item is disabled if a read-only file is selected.
*/
testcase.deleteContextMenuItemDisabledForReadOnlyFile = function() {
deleteContextMenu('Read-Only File.jpg', false);
};
/**
* Tests that the Delete menu item is disabled if a read-only folder is
* selected.
*/
testcase.deleteContextMenuItemDisabledForReadOnlyFolder = function() {
deleteContextMenu('Read-Only Folder', false);
};
/**
* Tests that the Delete menu item is enabled if a read-write entry is selected.
*/
testcase.deleteContextMenuItemEnabledForReadWriteFile = function() {
deleteContextMenu('hello.txt', true);
};
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
"remote_call.js", "remote_call.js",
"file_manager/background.js", "file_manager/background.js",
"file_manager/test_util_unittest.js", "file_manager/test_util_unittest.js",
"file_manager/context_menu.js",
"file_manager/copy_between_windows.js", "file_manager/copy_between_windows.js",
"file_manager/create_new_folder.js", "file_manager/create_new_folder.js",
"file_manager/delete.js", "file_manager/delete.js",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment