Merge pull request #12701 from nextcloud/stable14-12632-add-acceptance-tests-for-sharing-files-and-folders-with-another-user
[stable14] Add acceptance tests for sharing files and folders with another user
This commit is contained in:
commit
e1739e3da9
18
.drone.yml
18
.drone.yml
|
@ -678,6 +678,20 @@ pipeline:
|
||||||
when:
|
when:
|
||||||
matrix:
|
matrix:
|
||||||
TESTS-ACCEPTANCE: app-files
|
TESTS-ACCEPTANCE: app-files
|
||||||
|
acceptance-app-files-sharing:
|
||||||
|
image: nextcloudci/acceptance-php7.1:acceptance-php7.1-2
|
||||||
|
commands:
|
||||||
|
- tests/acceptance/run-local.sh --timeout-multiplier 10 --nextcloud-server-domain acceptance-app-files-sharing --selenium-server selenium:4444 allow-git-repository-modifications features/app-files-sharing.feature
|
||||||
|
when:
|
||||||
|
matrix:
|
||||||
|
TESTS-ACCEPTANCE: app-files-sharing
|
||||||
|
acceptance-app-files-sharing-link:
|
||||||
|
image: nextcloudci/acceptance-php7.1:acceptance-php7.1-2
|
||||||
|
commands:
|
||||||
|
- tests/acceptance/run-local.sh --timeout-multiplier 10 --nextcloud-server-domain acceptance-app-files-sharing-link --selenium-server selenium:4444 allow-git-repository-modifications features/app-files-sharing-link.feature
|
||||||
|
when:
|
||||||
|
matrix:
|
||||||
|
TESTS-ACCEPTANCE: app-files-sharing-link
|
||||||
acceptance-app-files-tags:
|
acceptance-app-files-tags:
|
||||||
image: nextcloudci/acceptance-php7.1:acceptance-php7.1-2
|
image: nextcloudci/acceptance-php7.1:acceptance-php7.1-2
|
||||||
commands:
|
commands:
|
||||||
|
@ -928,6 +942,10 @@ matrix:
|
||||||
TESTS-ACCEPTANCE: app-comments
|
TESTS-ACCEPTANCE: app-comments
|
||||||
- TESTS: acceptance
|
- TESTS: acceptance
|
||||||
TESTS-ACCEPTANCE: app-files
|
TESTS-ACCEPTANCE: app-files
|
||||||
|
- TESTS: acceptance
|
||||||
|
TESTS-ACCEPTANCE: app-files-sharing
|
||||||
|
- TESTS: acceptance
|
||||||
|
TESTS-ACCEPTANCE: app-files-sharing-link
|
||||||
- TESTS: acceptance
|
- TESTS: acceptance
|
||||||
TESTS-ACCEPTANCE: app-files-tags
|
TESTS-ACCEPTANCE: app-files-tags
|
||||||
- TESTS: acceptance
|
- TESTS: acceptance
|
||||||
|
|
|
@ -16,9 +16,10 @@ default:
|
||||||
- FeatureContext
|
- FeatureContext
|
||||||
- FileListContext
|
- FileListContext
|
||||||
- FilesAppContext
|
- FilesAppContext
|
||||||
- FilesSharingAppContext
|
- FilesAppSharingContext
|
||||||
- LoginPageContext
|
- LoginPageContext
|
||||||
- NotificationContext
|
- NotificationContext
|
||||||
|
- PublicShareContext
|
||||||
- SettingsContext
|
- SettingsContext
|
||||||
- SettingsMenuContext
|
- SettingsMenuContext
|
||||||
- ThemingAppContext
|
- ThemingAppContext
|
||||||
|
@ -42,9 +43,10 @@ default:
|
||||||
- FeatureContext
|
- FeatureContext
|
||||||
- FileListContext
|
- FileListContext
|
||||||
- FilesAppContext
|
- FilesAppContext
|
||||||
- FilesSharingAppContext
|
- FilesAppSharingContext
|
||||||
- LoginPageContext
|
- LoginPageContext
|
||||||
- NotificationContext
|
- NotificationContext
|
||||||
|
- PublicShareContext
|
||||||
- SettingsContext
|
- SettingsContext
|
||||||
- SettingsMenuContext
|
- SettingsMenuContext
|
||||||
- ThemingAppContext
|
- ThemingAppContext
|
||||||
|
@ -63,6 +65,9 @@ default:
|
||||||
Jane:
|
Jane:
|
||||||
selenium2:
|
selenium2:
|
||||||
wd_host: %selenium.server%
|
wd_host: %selenium.server%
|
||||||
|
Jim:
|
||||||
|
selenium2:
|
||||||
|
wd_host: %selenium.server%
|
||||||
Rubeus:
|
Rubeus:
|
||||||
# Rubeus uses a browser that has CSS grid support.
|
# Rubeus uses a browser that has CSS grid support.
|
||||||
selenium2:
|
selenium2:
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
Feature: app-files-sharing-link
|
||||||
|
|
||||||
|
Scenario: open the menu in a public shared link
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in
|
||||||
|
And I share the link for "welcome.txt"
|
||||||
|
And I write down the shared link
|
||||||
|
When I act as Jane
|
||||||
|
And I visit the shared link I wrote down
|
||||||
|
And I see that the current page is the shared link I wrote down
|
||||||
|
And I open the Share menu
|
||||||
|
Then I see that the Share menu is shown
|
||||||
|
|
||||||
|
Scenario: creation is not possible by default in a public shared folder
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in
|
||||||
|
And I create a new folder named "Shared folder"
|
||||||
|
# To share the link the "Share" inline action has to be clicked but, as the
|
||||||
|
# details view is opened automatically when the folder is created, clicking
|
||||||
|
# on the inline action could fail if it is covered by the details view due
|
||||||
|
# to its opening animation. Instead of ensuring that the animations of the
|
||||||
|
# contents and the details view have both finished it is easier to close the
|
||||||
|
# details view and wait until it is closed before continuing.
|
||||||
|
And I close the details view
|
||||||
|
And I see that the details view is closed
|
||||||
|
And I share the link for "Shared folder"
|
||||||
|
And I write down the shared link
|
||||||
|
When I act as Jane
|
||||||
|
And I visit the shared link I wrote down
|
||||||
|
And I see that the current page is the shared link I wrote down
|
||||||
|
And I see that the file list is eventually loaded
|
||||||
|
Then I see that it is not possible to create new files
|
||||||
|
|
||||||
|
Scenario: create folder in a public editable shared folder
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in
|
||||||
|
And I create a new folder named "Editable shared folder"
|
||||||
|
# To share the link the "Share" inline action has to be clicked but, as the
|
||||||
|
# details view is opened automatically when the folder is created, clicking
|
||||||
|
# on the inline action could fail if it is covered by the details view due
|
||||||
|
# to its opening animation. Instead of ensuring that the animations of the
|
||||||
|
# contents and the details view have both finished it is easier to close the
|
||||||
|
# details view and wait until it is closed before continuing.
|
||||||
|
And I close the details view
|
||||||
|
And I see that the details view is closed
|
||||||
|
And I share the link for "Editable shared folder"
|
||||||
|
And I set the shared link as editable
|
||||||
|
And I write down the shared link
|
||||||
|
When I act as Jane
|
||||||
|
And I visit the shared link I wrote down
|
||||||
|
And I see that the current page is the shared link I wrote down
|
||||||
|
And I create a new folder named "Subfolder"
|
||||||
|
Then I see that the file list contains a file named "Subfolder"
|
||||||
|
|
||||||
|
Scenario: owner sees folder created in the public page of an editable shared folder
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in
|
||||||
|
And I create a new folder named "Editable shared folder"
|
||||||
|
# To share the link the "Share" inline action has to be clicked but, as the
|
||||||
|
# details view is opened automatically when the folder is created, clicking
|
||||||
|
# on the inline action could fail if it is covered by the details view due
|
||||||
|
# to its opening animation. Instead of ensuring that the animations of the
|
||||||
|
# contents and the details view have both finished it is easier to close the
|
||||||
|
# details view and wait until it is closed before continuing.
|
||||||
|
And I close the details view
|
||||||
|
And I see that the details view is closed
|
||||||
|
And I share the link for "Editable shared folder"
|
||||||
|
And I set the shared link as editable
|
||||||
|
And I write down the shared link
|
||||||
|
And I act as Jane
|
||||||
|
And I visit the shared link I wrote down
|
||||||
|
And I see that the current page is the shared link I wrote down
|
||||||
|
And I create a new folder named "Subfolder"
|
||||||
|
And I see that the file list contains a file named "Subfolder"
|
||||||
|
When I act as John
|
||||||
|
And I enter in the folder named "Editable shared folder"
|
||||||
|
Then I see that the file list contains a file named "Subfolder"
|
||||||
|
|
||||||
|
Scenario: set a password to a shared link
|
||||||
|
Given I am logged in
|
||||||
|
And I share the link for "welcome.txt"
|
||||||
|
When I protect the shared link with the password "abcdef"
|
||||||
|
Then I see that the working icon for password protect is shown
|
||||||
|
And I see that the working icon for password protect is eventually not shown
|
||||||
|
|
||||||
|
Scenario: access a shared link protected by password with a valid password
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in
|
||||||
|
And I share the link for "welcome.txt" protected by the password "abcdef"
|
||||||
|
And I write down the shared link
|
||||||
|
When I act as Jane
|
||||||
|
And I visit the shared link I wrote down
|
||||||
|
And I see that the current page is the Authenticate page for the shared link I wrote down
|
||||||
|
And I authenticate with password "abcdef"
|
||||||
|
Then I see that the current page is the shared link I wrote down
|
||||||
|
And I see that the shared file preview shows the text "Welcome to your Nextcloud account!"
|
||||||
|
|
||||||
|
Scenario: access a shared link protected by password with an invalid password
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in
|
||||||
|
And I share the link for "welcome.txt" protected by the password "abcdef"
|
||||||
|
And I write down the shared link
|
||||||
|
When I act as Jane
|
||||||
|
And I visit the shared link I wrote down
|
||||||
|
And I authenticate with password "fedcba"
|
||||||
|
Then I see that the current page is the Authenticate page for the shared link I wrote down
|
||||||
|
And I see that a wrong password for the shared file message is shown
|
||||||
|
|
||||||
|
Scenario: access a direct download shared link protected by password with a valid password
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in
|
||||||
|
And I share the link for "welcome.txt" protected by the password "abcdef"
|
||||||
|
And I write down the shared link
|
||||||
|
When I act as Jane
|
||||||
|
And I visit the direct download shared link I wrote down
|
||||||
|
And I see that the current page is the Authenticate page for the direct download shared link I wrote down
|
||||||
|
And I authenticate with password "abcdef"
|
||||||
|
# download starts no page redirection
|
||||||
|
And I see that the current page is the Authenticate page for the direct download shared link I wrote down
|
|
@ -0,0 +1,269 @@
|
||||||
|
Feature: app-files-sharing
|
||||||
|
|
||||||
|
Scenario: share a file with another user
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in as the admin
|
||||||
|
And I act as Jane
|
||||||
|
And I am logged in
|
||||||
|
And I act as John
|
||||||
|
And I rename "welcome.txt" to "farewell.txt"
|
||||||
|
And I see that the file list contains a file named "farewell.txt"
|
||||||
|
When I share "farewell.txt" with "user0"
|
||||||
|
And I see that the file is shared with "user0"
|
||||||
|
And I act as Jane
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
Then I see that the file list contains a file named "farewell.txt"
|
||||||
|
And I open the details view for "farewell.txt"
|
||||||
|
And I see that the details view is open
|
||||||
|
And I open the "Sharing" tab in the details view
|
||||||
|
And I see that the "Sharing" tab in the details view is eventually loaded
|
||||||
|
And I see that the file is shared with me by "admin"
|
||||||
|
|
||||||
|
Scenario: share a file with another user who already has a file with that name
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in as the admin
|
||||||
|
And I act as Jane
|
||||||
|
And I am logged in
|
||||||
|
And I act as John
|
||||||
|
When I share "welcome.txt" with "user0"
|
||||||
|
And I see that the file is shared with "user0"
|
||||||
|
And I act as Jane
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
Then I see that the file list contains a file named "welcome (2).txt"
|
||||||
|
And I open the details view for "welcome (2).txt"
|
||||||
|
And I see that the details view is open
|
||||||
|
And I open the "Sharing" tab in the details view
|
||||||
|
And I see that the "Sharing" tab in the details view is eventually loaded
|
||||||
|
And I see that the file is shared with me by "admin"
|
||||||
|
|
||||||
|
Scenario: share a skeleton file with another user before first login
|
||||||
|
# If a file is shared with a user before her first login the skeleton would
|
||||||
|
# not have been created, so if the shared file has the same name as one from
|
||||||
|
# the skeleton the shared file will take its place and the skeleton file
|
||||||
|
# will not be added.
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in as the admin
|
||||||
|
When I share "welcome.txt" with "user0"
|
||||||
|
And I see that the file is shared with "user0"
|
||||||
|
And I act as Jane
|
||||||
|
And I am logged in
|
||||||
|
Then I see that the file list contains a file named "welcome.txt"
|
||||||
|
And I open the details view for "welcome.txt"
|
||||||
|
And I see that the details view is open
|
||||||
|
And I open the "Sharing" tab in the details view
|
||||||
|
And I see that the "Sharing" tab in the details view is eventually loaded
|
||||||
|
And I see that the file is shared with me by "admin"
|
||||||
|
|
||||||
|
Scenario: reshare a file with another user
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in as the admin
|
||||||
|
And I act as Jane
|
||||||
|
And I am logged in
|
||||||
|
And I act as Jim
|
||||||
|
And I am logged in as "user1"
|
||||||
|
And I act as John
|
||||||
|
And I rename "welcome.txt" to "farewell.txt"
|
||||||
|
And I see that the file list contains a file named "farewell.txt"
|
||||||
|
And I share "farewell.txt" with "user0"
|
||||||
|
And I see that the file is shared with "user0"
|
||||||
|
And I act as Jane
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
When I share "farewell.txt" with "user1"
|
||||||
|
And I see that the file is shared with "user1"
|
||||||
|
And I act as Jim
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
Then I see that the file list contains a file named "farewell.txt"
|
||||||
|
And I open the details view for "farewell.txt"
|
||||||
|
And I see that the details view is open
|
||||||
|
And I open the "Sharing" tab in the details view
|
||||||
|
And I see that the "Sharing" tab in the details view is eventually loaded
|
||||||
|
And I see that the file is shared with me by "user0"
|
||||||
|
|
||||||
|
Scenario: owner sees reshares with other users
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in as the admin
|
||||||
|
And I act as Jane
|
||||||
|
And I am logged in
|
||||||
|
And I act as John
|
||||||
|
And I rename "welcome.txt" to "farewell.txt"
|
||||||
|
And I see that the file list contains a file named "farewell.txt"
|
||||||
|
And I share "farewell.txt" with "user0"
|
||||||
|
And I see that the file is shared with "user0"
|
||||||
|
And I act as Jane
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
And I share "farewell.txt" with "user1"
|
||||||
|
And I see that the file is shared with "user1"
|
||||||
|
When I act as John
|
||||||
|
# The Files app is open again to reload the file list and the shares
|
||||||
|
And I open the Files app
|
||||||
|
And I open the details view for "farewell.txt"
|
||||||
|
And I see that the details view is open
|
||||||
|
And I open the "Sharing" tab in the details view
|
||||||
|
And I see that the "Sharing" tab in the details view is eventually loaded
|
||||||
|
Then I see that the file is shared with "user0"
|
||||||
|
And I see that the file is shared with "user1"
|
||||||
|
|
||||||
|
Scenario: share an empty folder with another user
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in as the admin
|
||||||
|
And I act as Jane
|
||||||
|
And I am logged in
|
||||||
|
And I act as John
|
||||||
|
And I create a new folder named "Shared folder"
|
||||||
|
And I see that the file list contains a file named "Shared folder"
|
||||||
|
When I share "Shared folder" with "user0"
|
||||||
|
And I see that the file is shared with "user0"
|
||||||
|
And I act as Jane
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
Then I see that the file list contains a file named "Shared folder"
|
||||||
|
And I open the details view for "Shared folder"
|
||||||
|
And I see that the details view is open
|
||||||
|
And I open the "Sharing" tab in the details view
|
||||||
|
And I see that the "Sharing" tab in the details view is eventually loaded
|
||||||
|
And I see that the file is shared with me by "admin"
|
||||||
|
|
||||||
|
Scenario: sharee sees a folder created by the owner in a shared folder
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in as the admin
|
||||||
|
And I act as Jane
|
||||||
|
And I am logged in
|
||||||
|
And I act as John
|
||||||
|
And I create a new folder named "Shared folder"
|
||||||
|
And I see that the file list contains a file named "Shared folder"
|
||||||
|
And I share "Shared folder" with "user0"
|
||||||
|
And I see that the file is shared with "user0"
|
||||||
|
And I enter in the folder named "Shared folder"
|
||||||
|
And I create a new folder named "Subfolder"
|
||||||
|
And I see that the file list contains a file named "Subfolder"
|
||||||
|
When I act as Jane
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
And I enter in the folder named "Shared folder"
|
||||||
|
Then I see that the file list contains a file named "Subfolder"
|
||||||
|
|
||||||
|
Scenario: owner sees a folder created by the sharee in a shared folder
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in as the admin
|
||||||
|
And I act as Jane
|
||||||
|
And I am logged in
|
||||||
|
And I act as John
|
||||||
|
And I create a new folder named "Shared folder"
|
||||||
|
And I see that the file list contains a file named "Shared folder"
|
||||||
|
And I share "Shared folder" with "user0"
|
||||||
|
And I see that the file is shared with "user0"
|
||||||
|
And I act as Jane
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
And I enter in the folder named "Shared folder"
|
||||||
|
And I create a new folder named "Subfolder"
|
||||||
|
And I see that the file list contains a file named "Subfolder"
|
||||||
|
When I act as John
|
||||||
|
And I enter in the folder named "Shared folder"
|
||||||
|
Then I see that the file list contains a file named "Subfolder"
|
||||||
|
|
||||||
|
Scenario: resharee sees a folder created by the owner in a shared folder
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in as the admin
|
||||||
|
And I act as Jane
|
||||||
|
And I am logged in
|
||||||
|
And I act as Jim
|
||||||
|
And I am logged in as "user1"
|
||||||
|
And I act as John
|
||||||
|
And I create a new folder named "Shared folder"
|
||||||
|
And I see that the file list contains a file named "Shared folder"
|
||||||
|
And I share "Shared folder" with "user0"
|
||||||
|
And I see that the file is shared with "user0"
|
||||||
|
And I act as Jane
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
And I share "Shared folder" with "user1"
|
||||||
|
And I act as John
|
||||||
|
And I enter in the folder named "Shared folder"
|
||||||
|
And I create a new folder named "Subfolder"
|
||||||
|
And I see that the file list contains a file named "Subfolder"
|
||||||
|
When I act as Jim
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
And I enter in the folder named "Shared folder"
|
||||||
|
Then I see that the file list contains a file named "Subfolder"
|
||||||
|
|
||||||
|
Scenario: owner sees a folder created by the resharee in a shared folder
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in as the admin
|
||||||
|
And I act as Jane
|
||||||
|
And I am logged in
|
||||||
|
And I act as Jim
|
||||||
|
And I am logged in as "user1"
|
||||||
|
And I act as John
|
||||||
|
And I create a new folder named "Shared folder"
|
||||||
|
And I see that the file list contains a file named "Shared folder"
|
||||||
|
And I share "Shared folder" with "user0"
|
||||||
|
And I see that the file is shared with "user0"
|
||||||
|
And I act as Jane
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
And I share "Shared folder" with "user1"
|
||||||
|
And I act as Jim
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
And I enter in the folder named "Shared folder"
|
||||||
|
And I create a new folder named "Subfolder"
|
||||||
|
And I see that the file list contains a file named "Subfolder"
|
||||||
|
When I act as John
|
||||||
|
And I enter in the folder named "Shared folder"
|
||||||
|
Then I see that the file list contains a file named "Subfolder"
|
||||||
|
|
||||||
|
Scenario: sharee can not reshare a folder if the sharer disables it
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in as the admin
|
||||||
|
And I act as Jane
|
||||||
|
And I am logged in
|
||||||
|
And I act as John
|
||||||
|
And I create a new folder named "Shared folder"
|
||||||
|
And I see that the file list contains a file named "Shared folder"
|
||||||
|
And I share "Shared folder" with "user0"
|
||||||
|
And I see that the file is shared with "user0"
|
||||||
|
And I set the share with "user0" as not reshareable
|
||||||
|
And I see that "user0" can not reshare the share
|
||||||
|
When I act as Jane
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
Then I see that the file list contains a file named "Shared folder"
|
||||||
|
And I open the details view for "Shared folder"
|
||||||
|
And I see that the details view is open
|
||||||
|
And I open the "Sharing" tab in the details view
|
||||||
|
And I see that the "Sharing" tab in the details view is eventually loaded
|
||||||
|
And I see that the file is shared with me by "admin"
|
||||||
|
And I see that resharing the file is not allowed
|
||||||
|
|
||||||
|
Scenario: sharee can not reshare a subfolder if the sharer disables it for the parent folder
|
||||||
|
Given I act as John
|
||||||
|
And I am logged in as the admin
|
||||||
|
And I act as Jane
|
||||||
|
And I am logged in
|
||||||
|
And I act as John
|
||||||
|
And I create a new folder named "Shared folder"
|
||||||
|
And I see that the file list contains a file named "Shared folder"
|
||||||
|
And I share "Shared folder" with "user0"
|
||||||
|
And I see that the file is shared with "user0"
|
||||||
|
And I set the share with "user0" as not reshareable
|
||||||
|
And I see that "user0" can not reshare the share
|
||||||
|
And I enter in the folder named "Shared folder"
|
||||||
|
And I create a new folder named "Subfolder"
|
||||||
|
And I see that the file list contains a file named "Subfolder"
|
||||||
|
When I act as Jane
|
||||||
|
# The Files app is open again to reload the file list
|
||||||
|
And I open the Files app
|
||||||
|
And I enter in the folder named "Shared folder"
|
||||||
|
Then I see that the file list contains a file named "Subfolder"
|
||||||
|
And I open the details view for "Subfolder"
|
||||||
|
And I see that the details view is open
|
||||||
|
And I open the "Sharing" tab in the details view
|
||||||
|
And I see that the "Sharing" tab in the details view is eventually loaded
|
||||||
|
And I see that resharing the file is not allowed
|
|
@ -147,124 +147,6 @@ Feature: app-files
|
||||||
Then I see that the file list contains a file named "farewell.txt"
|
Then I see that the file list contains a file named "farewell.txt"
|
||||||
And I see that the file name shown in the details view is "farewell.txt"
|
And I see that the file name shown in the details view is "farewell.txt"
|
||||||
|
|
||||||
Scenario: open the menu in a public shared link
|
|
||||||
Given I act as John
|
|
||||||
And I am logged in
|
|
||||||
And I share the link for "welcome.txt"
|
|
||||||
And I write down the shared link
|
|
||||||
When I act as Jane
|
|
||||||
And I visit the shared link I wrote down
|
|
||||||
And I see that the current page is the shared link I wrote down
|
|
||||||
And I open the Share menu
|
|
||||||
Then I see that the Share menu is shown
|
|
||||||
|
|
||||||
Scenario: creation is not possible by default in a public shared folder
|
|
||||||
Given I act as John
|
|
||||||
And I am logged in
|
|
||||||
And I create a new folder named "Shared folder"
|
|
||||||
# To share the link the "Share" inline action has to be clicked but, as the
|
|
||||||
# details view is opened automatically when the folder is created, clicking
|
|
||||||
# on the inline action could fail if it is covered by the details view due
|
|
||||||
# to its opening animation. Instead of ensuring that the animations of the
|
|
||||||
# contents and the details view have both finished it is easier to close the
|
|
||||||
# details view and wait until it is closed before continuing.
|
|
||||||
And I close the details view
|
|
||||||
And I see that the details view is closed
|
|
||||||
And I share the link for "Shared folder"
|
|
||||||
And I write down the shared link
|
|
||||||
When I act as Jane
|
|
||||||
And I visit the shared link I wrote down
|
|
||||||
And I see that the current page is the shared link I wrote down
|
|
||||||
And I see that the file list is eventually loaded
|
|
||||||
Then I see that it is not possible to create new files
|
|
||||||
|
|
||||||
Scenario: create folder in a public editable shared folder
|
|
||||||
Given I act as John
|
|
||||||
And I am logged in
|
|
||||||
And I create a new folder named "Editable shared folder"
|
|
||||||
# To share the link the "Share" inline action has to be clicked but, as the
|
|
||||||
# details view is opened automatically when the folder is created, clicking
|
|
||||||
# on the inline action could fail if it is covered by the details view due
|
|
||||||
# to its opening animation. Instead of ensuring that the animations of the
|
|
||||||
# contents and the details view have both finished it is easier to close the
|
|
||||||
# details view and wait until it is closed before continuing.
|
|
||||||
And I close the details view
|
|
||||||
And I see that the details view is closed
|
|
||||||
And I share the link for "Editable shared folder"
|
|
||||||
And I set the shared link as editable
|
|
||||||
And I write down the shared link
|
|
||||||
When I act as Jane
|
|
||||||
And I visit the shared link I wrote down
|
|
||||||
And I see that the current page is the shared link I wrote down
|
|
||||||
And I create a new folder named "Subfolder"
|
|
||||||
Then I see that the file list contains a file named "Subfolder"
|
|
||||||
|
|
||||||
Scenario: owner sees folder created in the public page of an editable shared folder
|
|
||||||
Given I act as John
|
|
||||||
And I am logged in
|
|
||||||
And I create a new folder named "Editable shared folder"
|
|
||||||
# To share the link the "Share" inline action has to be clicked but, as the
|
|
||||||
# details view is opened automatically when the folder is created, clicking
|
|
||||||
# on the inline action could fail if it is covered by the details view due
|
|
||||||
# to its opening animation. Instead of ensuring that the animations of the
|
|
||||||
# contents and the details view have both finished it is easier to close the
|
|
||||||
# details view and wait until it is closed before continuing.
|
|
||||||
And I close the details view
|
|
||||||
And I see that the details view is closed
|
|
||||||
And I share the link for "Editable shared folder"
|
|
||||||
And I set the shared link as editable
|
|
||||||
And I write down the shared link
|
|
||||||
And I act as Jane
|
|
||||||
And I visit the shared link I wrote down
|
|
||||||
And I see that the current page is the shared link I wrote down
|
|
||||||
And I create a new folder named "Subfolder"
|
|
||||||
And I see that the file list contains a file named "Subfolder"
|
|
||||||
When I act as John
|
|
||||||
And I enter in the folder named "Editable shared folder"
|
|
||||||
Then I see that the file list contains a file named "Subfolder"
|
|
||||||
|
|
||||||
Scenario: set a password to a shared link
|
|
||||||
Given I am logged in
|
|
||||||
And I share the link for "welcome.txt"
|
|
||||||
When I protect the shared link with the password "abcdef"
|
|
||||||
Then I see that the working icon for password protect is shown
|
|
||||||
And I see that the working icon for password protect is eventually not shown
|
|
||||||
|
|
||||||
Scenario: access a shared link protected by password with a valid password
|
|
||||||
Given I act as John
|
|
||||||
And I am logged in
|
|
||||||
And I share the link for "welcome.txt" protected by the password "abcdef"
|
|
||||||
And I write down the shared link
|
|
||||||
When I act as Jane
|
|
||||||
And I visit the shared link I wrote down
|
|
||||||
And I see that the current page is the Authenticate page for the shared link I wrote down
|
|
||||||
And I authenticate with password "abcdef"
|
|
||||||
Then I see that the current page is the shared link I wrote down
|
|
||||||
And I see that the shared file preview shows the text "Welcome to your Nextcloud account!"
|
|
||||||
|
|
||||||
Scenario: access a shared link protected by password with an invalid password
|
|
||||||
Given I act as John
|
|
||||||
And I am logged in
|
|
||||||
And I share the link for "welcome.txt" protected by the password "abcdef"
|
|
||||||
And I write down the shared link
|
|
||||||
When I act as Jane
|
|
||||||
And I visit the shared link I wrote down
|
|
||||||
And I authenticate with password "fedcba"
|
|
||||||
Then I see that the current page is the Authenticate page for the shared link I wrote down
|
|
||||||
And I see that a wrong password for the shared file message is shown
|
|
||||||
|
|
||||||
Scenario: access a direct download shared link protected by password with a valid password
|
|
||||||
Given I act as John
|
|
||||||
And I am logged in
|
|
||||||
And I share the link for "welcome.txt" protected by the password "abcdef"
|
|
||||||
And I write down the shared link
|
|
||||||
When I act as Jane
|
|
||||||
And I visit the direct download shared link I wrote down
|
|
||||||
And I see that the current page is the Authenticate page for the direct download shared link I wrote down
|
|
||||||
And I authenticate with password "abcdef"
|
|
||||||
# download starts no page redirection
|
|
||||||
And I see that the current page is the Authenticate page for the direct download shared link I wrote down
|
|
||||||
|
|
||||||
Scenario: marking a file as favorite causes the file list to be sorted again
|
Scenario: marking a file as favorite causes the file list to be sorted again
|
||||||
Given I am logged in
|
Given I am logged in
|
||||||
And I create a new folder named "A name alphabetically lower than welcome.txt"
|
And I create a new folder named "A name alphabetically lower than welcome.txt"
|
||||||
|
|
|
@ -42,6 +42,23 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
||||||
"Deleted files" => "trashbin" ];
|
"Deleted files" => "trashbin" ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
private static function appMenu() {
|
||||||
|
return Locator::forThe()->id("appmenu")->
|
||||||
|
describedAs("App menu in header");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function filesItemInAppMenu() {
|
||||||
|
return Locator::forThe()->xpath("/li[@data-id = 'files']")->
|
||||||
|
descendantOf(self::appMenu())->
|
||||||
|
describedAs("Files item in app menu in header");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Locator
|
* @return Locator
|
||||||
*/
|
*/
|
||||||
|
@ -212,91 +229,10 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Locator
|
* @Given I open the Files app
|
||||||
*/
|
*/
|
||||||
public static function shareLinkRow() {
|
public function iOpenTheFilesApp() {
|
||||||
return Locator::forThe()->id("shareLink")->
|
$this->actor->find(self::filesItemInAppMenu(), 10)->click();
|
||||||
descendantOf(self::detailsView())->
|
|
||||||
describedAs("Share link row in the details view in Files app");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Locator
|
|
||||||
*/
|
|
||||||
public static function shareLinkCheckbox() {
|
|
||||||
// forThe()->checkbox("Enable") can not be used here; that would return
|
|
||||||
// the checkbox itself, but the element that the user interacts with is
|
|
||||||
// the label.
|
|
||||||
return Locator::forThe()->xpath("//label[normalize-space() = 'Enable']")->
|
|
||||||
descendantOf(self::shareLinkRow())->
|
|
||||||
describedAs("Share link checkbox in the details view in Files app");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Locator
|
|
||||||
*/
|
|
||||||
public static function shareLinkMenuButton() {
|
|
||||||
return Locator::forThe()->css(".share-menu > .icon")->
|
|
||||||
descendantOf(self::shareLinkRow())->
|
|
||||||
describedAs("Share link menu button in the details view in Files app");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Locator
|
|
||||||
*/
|
|
||||||
public static function shareLinkMenu() {
|
|
||||||
return Locator::forThe()->css(".share-menu > .menu")->
|
|
||||||
descendantOf(self::shareLinkRow())->
|
|
||||||
describedAs("Share link menu in the details view in Files app");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Locator
|
|
||||||
*/
|
|
||||||
public static function copyUrlMenuItem() {
|
|
||||||
return Locator::forThe()->xpath("//a[normalize-space() = 'Copy URL']")->
|
|
||||||
descendantOf(self::shareLinkMenu())->
|
|
||||||
describedAs("Copy URL menu item in the share link menu in the details view in Files app");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Locator
|
|
||||||
*/
|
|
||||||
public static function allowUploadAndEditingRadioButton() {
|
|
||||||
// forThe()->radio("Allow upload and editing") can not be used here;
|
|
||||||
// that would return the radio button itself, but the element that the
|
|
||||||
// user interacts with is the label.
|
|
||||||
return Locator::forThe()->xpath("//label[normalize-space() = 'Allow upload and editing']")->
|
|
||||||
descendantOf(self::shareLinkMenu())->
|
|
||||||
describedAs("Allow upload and editing radio button in the details view in Files app");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Locator
|
|
||||||
*/
|
|
||||||
public static function passwordProtectCheckbox() {
|
|
||||||
// forThe()->checkbox("Password protect") can not be used here; that
|
|
||||||
// would return the checkbox itself, but the element that the user
|
|
||||||
// interacts with is the label.
|
|
||||||
return Locator::forThe()->xpath("//label[normalize-space() = 'Password protect']")->
|
|
||||||
descendantOf(self::shareLinkMenu())->
|
|
||||||
describedAs("Password protect checkbox in the details view in Files app");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Locator
|
|
||||||
*/
|
|
||||||
public static function passwordProtectField() {
|
|
||||||
return Locator::forThe()->css(".linkPassText")->descendantOf(self::shareLinkMenu())->
|
|
||||||
describedAs("Password protect field in the details view in Files app");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Locator
|
|
||||||
*/
|
|
||||||
public static function passwordProtectWorkingIcon() {
|
|
||||||
return Locator::forThe()->css(".linkPassMenu .icon-loading-small")->descendantOf(self::shareLinkMenu())->
|
|
||||||
describedAs("Password protect working icon in the details view in Files app");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -320,29 +256,6 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
||||||
$this->actor->find(self::tabHeaderInDetailsViewNamed($tabName), 10)->click();
|
$this->actor->find(self::tabHeaderInDetailsViewNamed($tabName), 10)->click();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @Given I share the link for :fileName
|
|
||||||
*/
|
|
||||||
public function iShareTheLinkFor($fileName) {
|
|
||||||
$this->actor->find(FileListContext::shareActionForFile(self::currentSectionMainView(), $fileName), 10)->click();
|
|
||||||
|
|
||||||
$this->actor->find(self::shareLinkCheckbox(), 5)->click();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Given I write down the shared link
|
|
||||||
*/
|
|
||||||
public function iWriteDownTheSharedLink() {
|
|
||||||
$this->showShareLinkMenuIfNeeded();
|
|
||||||
|
|
||||||
$this->actor->find(self::copyUrlMenuItem(), 2)->click();
|
|
||||||
|
|
||||||
// Clicking on the menu item copies the link to the clipboard, but it is
|
|
||||||
// not possible to access that value from the acceptance tests. Due to
|
|
||||||
// this the value of the attribute that holds the URL is used instead.
|
|
||||||
$this->actor->getSharedNotebook()["shared link"] = $this->actor->find(self::copyUrlMenuItem(), 2)->getWrappedElement()->getAttribute("data-clipboard-text");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @When I mark the file as favorite in the details view
|
* @When I mark the file as favorite in the details view
|
||||||
*/
|
*/
|
||||||
|
@ -379,26 +292,6 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
||||||
$this->actor->find(self::itemInDropdownForTag($tag), 10)->click();
|
$this->actor->find(self::itemInDropdownForTag($tag), 10)->click();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @When I set the shared link as editable
|
|
||||||
*/
|
|
||||||
public function iSetTheSharedLinkAsEditable() {
|
|
||||||
$this->showShareLinkMenuIfNeeded();
|
|
||||||
|
|
||||||
$this->actor->find(self::allowUploadAndEditingRadioButton(), 2)->click();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @When I protect the shared link with the password :password
|
|
||||||
*/
|
|
||||||
public function iProtectTheSharedLinkWithThePassword($password) {
|
|
||||||
$this->showShareLinkMenuIfNeeded();
|
|
||||||
|
|
||||||
$this->actor->find(self::passwordProtectCheckbox(), 2)->click();
|
|
||||||
|
|
||||||
$this->actor->find(self::passwordProtectField(), 2)->setValue($password . "\r");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Then I see that the current page is the Files app
|
* @Then I see that the current page is the Files app
|
||||||
*/
|
*/
|
||||||
|
@ -520,47 +413,4 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
||||||
PHPUnit_Framework_Assert::fail("The $tabName tab in the details view has not been loaded after $timeout seconds");
|
PHPUnit_Framework_Assert::fail("The $tabName tab in the details view has not been loaded after $timeout seconds");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @Then I see that the working icon for password protect is shown
|
|
||||||
*/
|
|
||||||
public function iSeeThatTheWorkingIconForPasswordProtectIsShown() {
|
|
||||||
PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::passwordProtectWorkingIcon(), 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Then I see that the working icon for password protect is eventually not shown
|
|
||||||
*/
|
|
||||||
public function iSeeThatTheWorkingIconForPasswordProtectIsEventuallyNotShown() {
|
|
||||||
if (!WaitFor::elementToBeEventuallyNotShown(
|
|
||||||
$this->actor,
|
|
||||||
self::passwordProtectWorkingIcon(),
|
|
||||||
$timeout = 10 * $this->actor->getFindTimeoutMultiplier())) {
|
|
||||||
PHPUnit_Framework_Assert::fail("The working icon for password protect is still shown after $timeout seconds");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Given I share the link for :fileName protected by the password :password
|
|
||||||
*/
|
|
||||||
public function iShareTheLinkForProtectedByThePassword($fileName, $password) {
|
|
||||||
$this->iShareTheLinkFor($fileName);
|
|
||||||
$this->iProtectTheSharedLinkWithThePassword($password);
|
|
||||||
$this->iSeeThatTheWorkingIconForPasswordProtectIsShown();
|
|
||||||
$this->iSeeThatTheWorkingIconForPasswordProtectIsEventuallyNotShown();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function showShareLinkMenuIfNeeded() {
|
|
||||||
// In some cases the share menu is hidden after clicking on an action of
|
|
||||||
// the menu. Therefore, if the menu is visible, wait a little just in
|
|
||||||
// case it is in the process of being hidden due to a previous action,
|
|
||||||
// in which case it is shown again.
|
|
||||||
if (WaitFor::elementToBeEventuallyNotShown(
|
|
||||||
$this->actor,
|
|
||||||
self::shareLinkMenu(),
|
|
||||||
$timeout = 2 * $this->actor->getFindTimeoutMultiplier())) {
|
|
||||||
$this->actor->find(self::shareLinkMenuButton(), 10)->click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,358 @@
|
||||||
|
<?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 FilesAppSharingContext implements Context, ActorAwareInterface {
|
||||||
|
|
||||||
|
use ActorAware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function sharedByLabel() {
|
||||||
|
return Locator::forThe()->css(".reshare")->
|
||||||
|
descendantOf(FilesAppContext::detailsView())->
|
||||||
|
describedAs("Shared by label in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function shareWithInput() {
|
||||||
|
return Locator::forThe()->css(".shareWithField")->
|
||||||
|
descendantOf(FilesAppContext::detailsView())->
|
||||||
|
describedAs("Share with input in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function shareeList() {
|
||||||
|
return Locator::forThe()->css(".shareeListView")->
|
||||||
|
descendantOf(FilesAppContext::detailsView())->
|
||||||
|
describedAs("Sharee list in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function sharedWithRow($sharedWithName) {
|
||||||
|
// "username" class is used for any type of share, not only for shares
|
||||||
|
// with users.
|
||||||
|
return Locator::forThe()->xpath("//span[contains(concat(' ', normalize-space(@class), ' '), ' username ') and normalize-space() = '$sharedWithName']/ancestor::li")->
|
||||||
|
descendantOf(self::shareeList())->
|
||||||
|
describedAs("Shared with $sharedWithName row in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function shareWithMenuButton($sharedWithName) {
|
||||||
|
return Locator::forThe()->css(".share-menu > .icon")->
|
||||||
|
descendantOf(self::sharedWithRow($sharedWithName))->
|
||||||
|
describedAs("Share with $sharedWithName menu button in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function shareWithMenu($sharedWithName) {
|
||||||
|
return Locator::forThe()->css(".share-menu > .menu")->
|
||||||
|
descendantOf(self::sharedWithRow($sharedWithName))->
|
||||||
|
describedAs("Share with $sharedWithName menu in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function canReshareCheckbox($sharedWithName) {
|
||||||
|
// forThe()->checkbox("Can reshare") can not be used here; that would
|
||||||
|
// return the checkbox itself, but the element that the user interacts
|
||||||
|
// with is the label.
|
||||||
|
return Locator::forThe()->xpath("//label[normalize-space() = 'Can reshare']")->
|
||||||
|
descendantOf(self::shareWithMenu($sharedWithName))->
|
||||||
|
describedAs("Can reshare checkbox in the share with $sharedWithName menu in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function canReshareCheckboxInput($sharedWithName) {
|
||||||
|
return Locator::forThe()->checkbox("Can reshare")->
|
||||||
|
descendantOf(self::shareWithMenu($sharedWithName))->
|
||||||
|
describedAs("Can reshare checkbox input in the share with $sharedWithName menu in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function shareLinkRow() {
|
||||||
|
return Locator::forThe()->id("shareLink")->
|
||||||
|
descendantOf(FilesAppContext::detailsView())->
|
||||||
|
describedAs("Share link row in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function shareLinkCheckbox() {
|
||||||
|
// forThe()->checkbox("Enable") can not be used here; that would return
|
||||||
|
// the checkbox itself, but the element that the user interacts with is
|
||||||
|
// the label.
|
||||||
|
return Locator::forThe()->xpath("//label[normalize-space() = 'Enable']")->
|
||||||
|
descendantOf(self::shareLinkRow())->
|
||||||
|
describedAs("Share link checkbox in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function shareLinkMenuButton() {
|
||||||
|
return Locator::forThe()->css(".share-menu > .icon")->
|
||||||
|
descendantOf(self::shareLinkRow())->
|
||||||
|
describedAs("Share link menu button in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function shareLinkMenu() {
|
||||||
|
return Locator::forThe()->css(".share-menu > .menu")->
|
||||||
|
descendantOf(self::shareLinkRow())->
|
||||||
|
describedAs("Share link menu in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function copyUrlMenuItem() {
|
||||||
|
return Locator::forThe()->xpath("//a[normalize-space() = 'Copy URL']")->
|
||||||
|
descendantOf(self::shareLinkMenu())->
|
||||||
|
describedAs("Copy URL menu item in the share link menu in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function allowUploadAndEditingRadioButton() {
|
||||||
|
// forThe()->radio("Allow upload and editing") can not be used here;
|
||||||
|
// that would return the radio button itself, but the element that the
|
||||||
|
// user interacts with is the label.
|
||||||
|
return Locator::forThe()->xpath("//label[normalize-space() = 'Allow upload and editing']")->
|
||||||
|
descendantOf(self::shareLinkMenu())->
|
||||||
|
describedAs("Allow upload and editing radio button in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function passwordProtectCheckbox() {
|
||||||
|
// forThe()->checkbox("Password protect") can not be used here; that
|
||||||
|
// would return the checkbox itself, but the element that the user
|
||||||
|
// interacts with is the label.
|
||||||
|
return Locator::forThe()->xpath("//label[normalize-space() = 'Password protect']")->
|
||||||
|
descendantOf(self::shareLinkMenu())->
|
||||||
|
describedAs("Password protect checkbox in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function passwordProtectField() {
|
||||||
|
return Locator::forThe()->css(".linkPassText")->descendantOf(self::shareLinkMenu())->
|
||||||
|
describedAs("Password protect field in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Locator
|
||||||
|
*/
|
||||||
|
public static function passwordProtectWorkingIcon() {
|
||||||
|
return Locator::forThe()->css(".linkPassMenu .icon-loading-small")->descendantOf(self::shareLinkMenu())->
|
||||||
|
describedAs("Password protect working icon in the details view in Files app");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Given I share the link for :fileName
|
||||||
|
*/
|
||||||
|
public function iShareTheLinkFor($fileName) {
|
||||||
|
$this->actor->find(FileListContext::shareActionForFile(FilesAppContext::currentSectionMainView(), $fileName), 10)->click();
|
||||||
|
|
||||||
|
$this->actor->find(self::shareLinkCheckbox(), 5)->click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Given I share :fileName with :shareWithName
|
||||||
|
*/
|
||||||
|
public function iShareWith($fileName, $shareWithName) {
|
||||||
|
$this->actor->find(FileListContext::shareActionForFile(FilesAppContext::currentSectionMainView(), $fileName), 10)->click();
|
||||||
|
|
||||||
|
$this->actor->find(self::shareWithInput(), 5)->setValue($shareWithName . "\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Given I write down the shared link
|
||||||
|
*/
|
||||||
|
public function iWriteDownTheSharedLink() {
|
||||||
|
$this->showShareLinkMenuIfNeeded();
|
||||||
|
|
||||||
|
$this->actor->find(self::copyUrlMenuItem(), 2)->click();
|
||||||
|
|
||||||
|
// Clicking on the menu item copies the link to the clipboard, but it is
|
||||||
|
// not possible to access that value from the acceptance tests. Due to
|
||||||
|
// this the value of the attribute that holds the URL is used instead.
|
||||||
|
$this->actor->getSharedNotebook()["shared link"] = $this->actor->find(self::copyUrlMenuItem(), 2)->getWrappedElement()->getAttribute("data-clipboard-text");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @When I set the shared link as editable
|
||||||
|
*/
|
||||||
|
public function iSetTheSharedLinkAsEditable() {
|
||||||
|
$this->showShareLinkMenuIfNeeded();
|
||||||
|
|
||||||
|
$this->actor->find(self::allowUploadAndEditingRadioButton(), 2)->click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @When I protect the shared link with the password :password
|
||||||
|
*/
|
||||||
|
public function iProtectTheSharedLinkWithThePassword($password) {
|
||||||
|
$this->showShareLinkMenuIfNeeded();
|
||||||
|
|
||||||
|
$this->actor->find(self::passwordProtectCheckbox(), 2)->click();
|
||||||
|
|
||||||
|
$this->actor->find(self::passwordProtectField(), 2)->setValue($password . "\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @When I set the share with :shareWithName as not reshareable
|
||||||
|
*/
|
||||||
|
public function iSetTheShareWithAsNotReshareable($shareWithName) {
|
||||||
|
$this->showShareWithMenuIfNeeded($shareWithName);
|
||||||
|
|
||||||
|
$this->iSeeThatCanReshareTheShare($shareWithName);
|
||||||
|
|
||||||
|
$this->actor->find(self::canReshareCheckbox($shareWithName), 2)->click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Then I see that the file is shared with me by :sharedByName
|
||||||
|
*/
|
||||||
|
public function iSeeThatTheFileIsSharedWithMeBy($sharedByName) {
|
||||||
|
PHPUnit_Framework_Assert::assertEquals(
|
||||||
|
$this->actor->find(self::sharedByLabel(), 10)->getText(), "Shared with you by $sharedByName");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Then I see that the file is shared with :sharedWithName
|
||||||
|
*/
|
||||||
|
public function iSeeThatTheFileIsSharedWith($sharedWithName) {
|
||||||
|
PHPUnit_Framework_Assert::assertTrue(
|
||||||
|
$this->actor->find(self::sharedWithRow($sharedWithName), 10)->isVisible());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Then I see that resharing the file is not allowed
|
||||||
|
*/
|
||||||
|
public function iSeeThatResharingTheFileIsNotAllowed() {
|
||||||
|
PHPUnit_Framework_Assert::assertEquals(
|
||||||
|
$this->actor->find(self::shareWithInput(), 10)->getWrappedElement()->getAttribute("disabled"), "disabled");
|
||||||
|
PHPUnit_Framework_Assert::assertEquals(
|
||||||
|
$this->actor->find(self::shareWithInput(), 10)->getWrappedElement()->getAttribute("placeholder"), "Resharing is not allowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Then I see that :sharedWithName can reshare the share
|
||||||
|
*/
|
||||||
|
public function iSeeThatCanReshareTheShare($sharedWithName) {
|
||||||
|
$this->showShareWithMenuIfNeeded($sharedWithName);
|
||||||
|
|
||||||
|
PHPUnit_Framework_Assert::assertTrue(
|
||||||
|
$this->actor->find(self::canReshareCheckboxInput($sharedWithName), 10)->isChecked());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Then I see that :sharedWithName can not reshare the share
|
||||||
|
*/
|
||||||
|
public function iSeeThatCanNotReshareTheShare($sharedWithName) {
|
||||||
|
$this->showShareWithMenuIfNeeded($sharedWithName);
|
||||||
|
|
||||||
|
PHPUnit_Framework_Assert::assertFalse(
|
||||||
|
$this->actor->find(self::canReshareCheckboxInput($sharedWithName), 10)->isChecked());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Then I see that the working icon for password protect is shown
|
||||||
|
*/
|
||||||
|
public function iSeeThatTheWorkingIconForPasswordProtectIsShown() {
|
||||||
|
PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::passwordProtectWorkingIcon(), 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Then I see that the working icon for password protect is eventually not shown
|
||||||
|
*/
|
||||||
|
public function iSeeThatTheWorkingIconForPasswordProtectIsEventuallyNotShown() {
|
||||||
|
if (!WaitFor::elementToBeEventuallyNotShown(
|
||||||
|
$this->actor,
|
||||||
|
self::passwordProtectWorkingIcon(),
|
||||||
|
$timeout = 10 * $this->actor->getFindTimeoutMultiplier())) {
|
||||||
|
PHPUnit_Framework_Assert::fail("The working icon for password protect is still shown after $timeout seconds");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Given I share the link for :fileName protected by the password :password
|
||||||
|
*/
|
||||||
|
public function iShareTheLinkForProtectedByThePassword($fileName, $password) {
|
||||||
|
$this->iShareTheLinkFor($fileName);
|
||||||
|
$this->iProtectTheSharedLinkWithThePassword($password);
|
||||||
|
$this->iSeeThatTheWorkingIconForPasswordProtectIsShown();
|
||||||
|
$this->iSeeThatTheWorkingIconForPasswordProtectIsEventuallyNotShown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function showShareLinkMenuIfNeeded() {
|
||||||
|
// In some cases the share menu is hidden after clicking on an action of
|
||||||
|
// the menu. Therefore, if the menu is visible, wait a little just in
|
||||||
|
// case it is in the process of being hidden due to a previous action,
|
||||||
|
// in which case it is shown again.
|
||||||
|
if (WaitFor::elementToBeEventuallyNotShown(
|
||||||
|
$this->actor,
|
||||||
|
self::shareLinkMenu(),
|
||||||
|
$timeout = 2 * $this->actor->getFindTimeoutMultiplier())) {
|
||||||
|
$this->actor->find(self::shareLinkMenuButton(), 10)->click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function showShareWithMenuIfNeeded($shareWithName) {
|
||||||
|
// In some cases the share menu is hidden after clicking on an action of
|
||||||
|
// the menu. Therefore, if the menu is visible, wait a little just in
|
||||||
|
// case it is in the process of being hidden due to a previous action,
|
||||||
|
// in which case it is shown again.
|
||||||
|
if (WaitFor::elementToBeEventuallyNotShown(
|
||||||
|
$this->actor,
|
||||||
|
self::shareWithMenu($shareWithName),
|
||||||
|
$timeout = 2 * $this->actor->getFindTimeoutMultiplier())) {
|
||||||
|
$this->actor->find(self::shareWithMenuButton($shareWithName), 10)->click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -131,6 +131,15 @@ class LoginPageContext implements Context, ActorAwareInterface {
|
||||||
$this->filesAppContext->iSeeThatTheCurrentPageIsTheFilesApp();
|
$this->filesAppContext->iSeeThatTheCurrentPageIsTheFilesApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Given I am logged in as :userName
|
||||||
|
*/
|
||||||
|
public function iAmLoggedInAs($userName) {
|
||||||
|
$this->featureContext->iVisitTheHomePage();
|
||||||
|
$this->iLogInWithUserAndPassword($userName, "123456acb");
|
||||||
|
$this->filesAppContext->iSeeThatTheCurrentPageIsTheFilesApp();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Given I am logged in as the admin
|
* @Given I am logged in as the admin
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
use Behat\Behat\Context\Context;
|
use Behat\Behat\Context\Context;
|
||||||
|
|
||||||
class FilesSharingAppContext implements Context, ActorAwareInterface {
|
class PublicShareContext implements Context, ActorAwareInterface {
|
||||||
|
|
||||||
use ActorAware;
|
use ActorAware;
|
||||||
use FileListAncestorSetter;
|
use FileListAncestorSetter;
|
|
@ -35,6 +35,7 @@ fi
|
||||||
php occ maintenance:install --admin-pass=admin
|
php occ maintenance:install --admin-pass=admin
|
||||||
|
|
||||||
OC_PASS=123456acb php occ user:add --password-from-env user0
|
OC_PASS=123456acb php occ user:add --password-from-env user0
|
||||||
|
OC_PASS=123456acb php occ user:add --password-from-env user1
|
||||||
OC_PASS=123456acb php occ user:add --password-from-env disabledUser
|
OC_PASS=123456acb php occ user:add --password-from-env disabledUser
|
||||||
php occ user:disable disabledUser
|
php occ user:disable disabledUser
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue