Merge pull request #13217 from nextcloud/add-acceptance-tests-for-moving-and-copying-files
Add acceptance tests for moving and copying files
This commit is contained in:
commit
ae25fd2389
4 changed files with 337 additions and 0 deletions
|
@ -15,6 +15,7 @@ default:
|
|||
- DialogContext
|
||||
- FeatureContext
|
||||
- FileListContext
|
||||
- FilePickerContext
|
||||
- FilesAppContext
|
||||
- FilesAppSharingContext
|
||||
- LoginPageContext
|
||||
|
@ -43,6 +44,7 @@ default:
|
|||
- DialogContext
|
||||
- FeatureContext
|
||||
- FileListContext
|
||||
- FilePickerContext
|
||||
- FilesAppContext
|
||||
- FilesAppSharingContext
|
||||
- LoginPageContext
|
||||
|
|
|
@ -140,6 +140,101 @@ Feature: app-files
|
|||
Then I see that the current section is "Deleted files"
|
||||
Then I see that the file list contains a file named "welcome.txt"
|
||||
|
||||
Scenario: move a file to another folder
|
||||
Given I am logged in
|
||||
And I create a new folder named "Destination"
|
||||
When I start the move or copy operation for "welcome.txt"
|
||||
And I select "Destination" in the file picker
|
||||
And I move to the last selected folder in the file picker
|
||||
Then I see that the file list does not contain a file named "welcome.txt"
|
||||
And I enter in the folder named "Destination"
|
||||
And I see that the file list contains a file named "welcome.txt"
|
||||
|
||||
Scenario: move a selection to another folder
|
||||
Given I am logged in
|
||||
And I create a new folder named "Folder"
|
||||
And I create a new folder named "Not selected folder"
|
||||
And I create a new folder named "Destination"
|
||||
When I select "welcome.txt"
|
||||
And I select "Folder"
|
||||
And I start the move or copy operation for the selected files
|
||||
And I select "Destination" in the file picker
|
||||
And I move to the last selected folder in the file picker
|
||||
Then I see that the file list does not contain a file named "welcome.txt"
|
||||
And I see that the file list does not contain a file named "Folder"
|
||||
And I see that the file list contains a file named "Not selected folder"
|
||||
And I enter in the folder named "Destination"
|
||||
And I see that the file list contains a file named "welcome.txt"
|
||||
And I see that the file list contains a file named "Folder"
|
||||
And I see that the file list does not contain a file named "Not selected folder"
|
||||
|
||||
Scenario: copy a file to another folder
|
||||
Given I am logged in
|
||||
And I create a new folder named "Destination"
|
||||
When I start the move or copy operation for "welcome.txt"
|
||||
And I select "Destination" in the file picker
|
||||
And I copy to the last selected folder in the file picker
|
||||
Then I enter in the folder named "Destination"
|
||||
# The file will appear in the destination once the copy operation finishes
|
||||
And I see that the file list contains a file named "welcome.txt"
|
||||
# The Files app is open again to reload the file list in the root folder
|
||||
And I open the Files app
|
||||
And I see that the file list contains a file named "welcome.txt"
|
||||
|
||||
Scenario: copy a selection to another folder
|
||||
Given I am logged in
|
||||
And I create a new folder named "Folder"
|
||||
And I create a new folder named "Not selected folder"
|
||||
And I create a new folder named "Destination"
|
||||
When I select "welcome.txt"
|
||||
And I select "Folder"
|
||||
And I start the move or copy operation for the selected files
|
||||
And I select "Destination" in the file picker
|
||||
And I copy to the last selected folder in the file picker
|
||||
Then I enter in the folder named "Destination"
|
||||
# The files will appear in the destination once the copy operation finishes
|
||||
And I see that the file list contains a file named "welcome.txt"
|
||||
And I see that the file list contains a file named "Folder"
|
||||
And I see that the file list does not contain a file named "Not selected folder"
|
||||
# The Files app is open again to reload the file list in the root folder
|
||||
And I open the Files app
|
||||
And I see that the file list contains a file named "welcome.txt"
|
||||
And I see that the file list contains a file named "Folder"
|
||||
And I see that the file list contains a file named "Not selected folder"
|
||||
|
||||
Scenario: copy a file in its same folder
|
||||
Given I am logged in
|
||||
When I start the move or copy operation for "welcome.txt"
|
||||
# No folder was explicitly selected, so the last selected folder is the
|
||||
# current folder.
|
||||
And I copy to the last selected folder in the file picker
|
||||
Then I see that the file list contains a file named "welcome.txt"
|
||||
And I see that the file list contains a file named "welcome (copy).txt"
|
||||
|
||||
Scenario: copy a file twice in its same folder
|
||||
Given I am logged in
|
||||
And I start the move or copy operation for "welcome.txt"
|
||||
# No folder was explicitly selected, so the last selected folder is the
|
||||
# current folder.
|
||||
And I copy to the last selected folder in the file picker
|
||||
When I start the move or copy operation for "welcome.txt"
|
||||
And I copy to the last selected folder in the file picker
|
||||
Then I see that the file list contains a file named "welcome.txt"
|
||||
And I see that the file list contains a file named "welcome (copy).txt"
|
||||
And I see that the file list contains a file named "welcome (copy 2).txt"
|
||||
|
||||
Scenario: copy a copy of a file in its same folder
|
||||
Given I am logged in
|
||||
And I start the move or copy operation for "welcome.txt"
|
||||
# No folder was explicitly selected, so the last selected folder is the
|
||||
# current folder.
|
||||
And I copy to the last selected folder in the file picker
|
||||
When I start the move or copy operation for "welcome (copy).txt"
|
||||
And I copy to the last selected folder in the file picker
|
||||
Then I see that the file list contains a file named "welcome.txt"
|
||||
And I see that the file list contains a file named "welcome (copy).txt"
|
||||
And I see that the file list contains a file named "welcome (copy 2).txt"
|
||||
|
||||
Scenario: rename a file with the details view open
|
||||
Given I am logged in
|
||||
And I open the details view for "welcome.txt"
|
||||
|
|
|
@ -130,6 +130,48 @@ class FileListContext implements Context, ActorAwareInterface {
|
|||
describedAs("Name input in create new folder menu item in file list");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function fileListHeader($fileListAncestor) {
|
||||
return Locator::forThe()->css("thead")->
|
||||
descendantOf($fileListAncestor)->
|
||||
describedAs("Header in file list");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function selectedFilesActionsMenuButton($fileListAncestor) {
|
||||
return Locator::forThe()->css(".actions-selected")->
|
||||
descendantOf(self::fileListHeader($fileListAncestor))->
|
||||
describedAs("Selected files actions menu button in file list");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function selectedFilesActionsMenu() {
|
||||
return Locator::forThe()->css(".filesSelectMenu")->
|
||||
describedAs("Selected files actions menu in file list");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
private static function selectedFilesActionsMenuItemFor($itemText) {
|
||||
return Locator::forThe()->xpath("//a[normalize-space() = '$itemText']")->
|
||||
descendantOf(self::selectedFilesActionsMenu())->
|
||||
describedAs($itemText . " item in selected files actions menu in file list");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function moveOrCopySelectedFilesMenuItem() {
|
||||
return self::selectedFilesActionsMenuItemFor("Move or copy");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
|
@ -148,6 +190,26 @@ class FileListContext implements Context, ActorAwareInterface {
|
|||
describedAs("Row for file $fileName1 preceding $fileName2 in file list");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function selectionCheckboxForFile($fileListAncestor, $fileName) {
|
||||
// Note that the element that the user interacts with is the label, not
|
||||
// the checbox itself.
|
||||
return Locator::forThe()->css(".selection label")->
|
||||
descendantOf(self::rowForFile($fileListAncestor, $fileName))->
|
||||
describedAs("Selection checkbox for file $fileName in file list");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function selectionCheckboxInputForFile($fileListAncestor, $fileName) {
|
||||
return Locator::forThe()->css(".selection input[type=checkbox]")->
|
||||
descendantOf(self::rowForFile($fileListAncestor, $fileName))->
|
||||
describedAs("Selection checkbox input for file $fileName in file list");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
|
@ -265,6 +327,13 @@ class FileListContext implements Context, ActorAwareInterface {
|
|||
return self::fileActionsMenuItemFor("Rename");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function moveOrCopyMenuItem() {
|
||||
return self::fileActionsMenuItemFor("Move or copy");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
|
@ -296,6 +365,24 @@ class FileListContext implements Context, ActorAwareInterface {
|
|||
$this->actor->find(self::mainLinkForFile($this->fileListAncestor, $folderName), 10)->click();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given I select :fileName
|
||||
*/
|
||||
public function iSelect($fileName) {
|
||||
$this->iSeeThatIsNotSelected($fileName);
|
||||
|
||||
$this->actor->find(self::selectionCheckboxForFile($this->fileListAncestor, $fileName), 10)->click();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given I start the move or copy operation for the selected files
|
||||
*/
|
||||
public function iStartTheMoveOrCopyOperationForTheSelectedFiles() {
|
||||
$this->actor->find(self::selectedFilesActionsMenuButton($this->fileListAncestor), 10)->click();
|
||||
|
||||
$this->actor->find(self::moveOrCopySelectedFilesMenuItem(), 2)->click();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given I open the details view for :fileName
|
||||
*/
|
||||
|
@ -325,6 +412,15 @@ class FileListContext implements Context, ActorAwareInterface {
|
|||
$this->actor->find(self::renameInputForFile($this->fileListAncestor, $fileName1), 10)->setValue($fileName2 . "\r");
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given I start the move or copy operation for :fileName
|
||||
*/
|
||||
public function iStartTheMoveOrCopyOperationFor($fileName) {
|
||||
$this->actor->find(self::fileActionsMenuButtonForFile($this->fileListAncestor, $fileName), 10)->click();
|
||||
|
||||
$this->actor->find(self::moveOrCopyMenuItem(), 2)->click();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given I mark :fileName as favorite
|
||||
*/
|
||||
|
@ -410,6 +506,18 @@ class FileListContext implements Context, ActorAwareInterface {
|
|||
PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::rowForFile($this->fileListAncestor, $fileName), 10));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I see that the file list does not contain a file named :fileName
|
||||
*/
|
||||
public function iSeeThatTheFileListDoesNotContainAFileNamed($fileName) {
|
||||
if (!WaitFor::elementToBeEventuallyNotShown(
|
||||
$this->actor,
|
||||
self::rowForFile($this->fileListAncestor, $fileName),
|
||||
$timeout = 10 * $this->actor->getFindTimeoutMultiplier())) {
|
||||
PHPUnit_Framework_Assert::fail("The file list still contains a file named $fileName after $timeout seconds");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I see that :fileName1 precedes :fileName2 in the file list
|
||||
*/
|
||||
|
@ -417,6 +525,13 @@ class FileListContext implements Context, ActorAwareInterface {
|
|||
PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::rowForFilePreceding($this->fileListAncestor, $fileName1, $fileName2), 10));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I see that :fileName is not selected
|
||||
*/
|
||||
public function iSeeThatIsNotSelected($fileName) {
|
||||
PHPUnit_Framework_Assert::assertFalse($this->actor->find(self::selectionCheckboxInputForFile($this->fileListAncestor, $fileName), 10)->isChecked());
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I see that :fileName is marked as favorite
|
||||
*/
|
||||
|
|
125
tests/acceptance/features/bootstrap/FilePickerContext.php
Normal file
125
tests/acceptance/features/bootstrap/FilePickerContext.php
Normal file
|
@ -0,0 +1,125 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* @copyright Copyright (c) 2018, Daniel Calviño Sánchez (danxuliu@gmail.com)
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
|
||||
class FilePickerContext implements Context, ActorAwareInterface {
|
||||
|
||||
use ActorAware;
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function dialog() {
|
||||
return Locator::forThe()->css(".oc-dialog")->
|
||||
describedAs("File picker dialog");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function fileListContainer() {
|
||||
return Locator::forThe()->css("#oc-dialog-filepicker-content")->
|
||||
descendantOf(self::dialog())->
|
||||
describedAs("File list container in the file picker dialog");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function rowForFile($fileName) {
|
||||
return Locator::forThe()->xpath("//*[@id = 'picker-filestable']//*[contains(concat(' ', normalize-space(@class), ' '), ' filename ') and normalize-space() = '$fileName']/ancestor::tr")->
|
||||
descendantOf(self::fileListContainer())->
|
||||
describedAs("Row for file $fileName in the file picker dialog");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function buttonRow() {
|
||||
return Locator::forThe()->css(".oc-dialog-buttonrow")->
|
||||
descendantOf(self::dialog())->
|
||||
describedAs("Button row in the file picker dialog");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
private static function buttonFor($buttonText) {
|
||||
// "Copy" and "Move" buttons text is set to "Copy to XXX" and "Move to
|
||||
// XXX" when a folder is selected.
|
||||
return Locator::forThe()->xpath("//button[starts-with(normalize-space(), '$buttonText')]")->
|
||||
descendantOf(self::buttonRow())->
|
||||
describedAs($buttonText . " button in the file picker dialog");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function copyButton() {
|
||||
return self::buttonFor("Copy");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function moveButton() {
|
||||
return self::buttonFor("Move");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function chooseButton() {
|
||||
return self::buttonFor("Choose");
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I select :fileName in the file picker
|
||||
*/
|
||||
public function iSelectInTheFilePicker($fileName) {
|
||||
$this->actor->find(self::rowForFile($fileName), 10)->click();
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I copy to the last selected folder in the file picker
|
||||
*/
|
||||
public function iCopyToTheLastSelectedFolderInTheFilePicker() {
|
||||
$this->actor->find(self::copyButton(), 10)->click();
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I move to the last selected folder in the file picker
|
||||
*/
|
||||
public function iMoveToTheLastSelectedFolderInTheFilePicker() {
|
||||
$this->actor->find(self::moveButton(), 10)->click();
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I choose the last selected file in the file picker
|
||||
*/
|
||||
public function iChooseTheLastSelectedFileInTheFilePicker() {
|
||||
$this->actor->find(self::chooseButton(), 10)->click();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue