diff --git a/tests/acceptance/bootstrap/SpacesContext.php b/tests/acceptance/bootstrap/SpacesContext.php index eb85d53a146..a8b0da7de76 100644 --- a/tests/acceptance/bootstrap/SpacesContext.php +++ b/tests/acceptance/bootstrap/SpacesContext.php @@ -2039,6 +2039,60 @@ public function userCopiesMovesFileIntoInsideSpaceUsingFileId(string $user, stri } } + /** + * @Given /^user "([^"]*)" has (copied|moved|renamed) file "([^"]*)" into "([^"]*)" inside space "([^"]*)" using file-id "([^"]*)"$/ + * + * @param string $user + * @param string $actionType + * @param string $sourceFile + * @param string $destinationFile + * @param string $spaceName + * @param string $fileId + * + * @throws GuzzleException + * @return void + */ + public function userHasCopiedOrMovedFileInsideSpaceUsingFileId( + string $user, + string $actionType, + string $sourceFile, + string $destinationFile, + string $spaceName, + string $fileId + ): void { + // split the source when there are sub-folders + $sourceFile = \trim($sourceFile, "/"); + $sourceFile = \explode("/", $sourceFile); + $sourceFile = \end($sourceFile); + $destinationFile = \trim($destinationFile, "/"); + if ($actionType === 'copied' || $actionType === 'moved') { + $fileDestination = $this->escapePath($destinationFile) . '/' . $this->escapePath($sourceFile); + } else { + $fileDestination = $destinationFile; + } + + $baseUrl = $this->featureContext->getBaseUrl(); + $sourceDavPath = WebdavHelper::getDavPath($this->featureContext->getDavPathVersion()); + if ($spaceName === 'Shares') { + $sharesPath = $this->featureContext->getSharesMountPath($user, $fileDestination); + $davPath = WebDavHelper::getDavPath($this->featureContext->getDavPathVersion()); + $headers['Destination'] = "$baseUrl/$davPath/$sharesPath"; + } else { + $headers['Destination'] = $this->destinationHeaderValueWithSpaceName($user, $fileDestination, $spaceName, $fileId); + } + $fullUrl = "$baseUrl/$sourceDavPath/$fileId"; + if ($actionType === 'copied') { + $response = $this->copyFilesAndFoldersRequest($user, $fullUrl, $headers); + } else { + $response = $this->moveFilesAndFoldersRequest($user, $fullUrl, $headers); + } + Assert::assertEquals( + 201, + $response->getStatusCode(), + "Expected response status code should be 201" + ); + } + /** * @When /^user "([^"]*)" tries to move (?:file|folder) "([^"]*)" of space "([^"]*)" to (space|folder) "([^"]*)" using its id in destination path$/ * @When /^user "([^"]*)" moves (?:file|folder) "([^"]*)" of space "([^"]*)" to (folder) "([^"]*)" using its id in destination path$/ diff --git a/tests/acceptance/bootstrap/WebDav.php b/tests/acceptance/bootstrap/WebDav.php index 4d4c9463ccc..225cf218d88 100644 --- a/tests/acceptance/bootstrap/WebDav.php +++ b/tests/acceptance/bootstrap/WebDav.php @@ -2673,6 +2673,31 @@ public function userDeletesFileFromSpaceUsingFileIdPath(string $user, string $fi $this->pushToLastStatusCodesArrays(); } + /** + * @Given user :user has updated a file with content :content using file-id :fileId + * + * @param string $user + * @param string $content + * @param string $fileId + * + * @return void + */ + public function userHasUpdatedAFileWithContentUsingFileId(string $user, string $content, string $fileId): void { + $baseUrl = $this->getBaseUrl(); + $sourceDavPath = WebdavHelper::getDavPath($this->getDavPathVersion()); + $fullUrl = "$baseUrl/$sourceDavPath/$fileId"; + $response = HttpRequestHelper::sendRequest( + $fullUrl, + $this->getStepLineRef(), + 'PUT', + $user, + $this->getPasswordForUser($user), + null, + $content + ); + $this->theHTTPStatusCodeShouldBe('204', '', $response); + } + /** * @Given /^user "([^"]*)" has deleted (?:file|folder|entity) "([^"]*)"$/ * diff --git a/tests/acceptance/features/apiActivities/activitiesByFileId.feature b/tests/acceptance/features/apiActivities/activitiesByFileId.feature new file mode 100644 index 00000000000..944f1f97a4f --- /dev/null +++ b/tests/acceptance/features/apiActivities/activitiesByFileId.feature @@ -0,0 +1,455 @@ +Feature: check activities + As a user + I want to check who made which changes to files using file-id + So that I can track modifications + + Background: + Given user "Alice" has been created with default attributes and without skeleton files + And using spaces DAV path + + + Scenario: check copy activity + Given user "Alice" has uploaded file with content "ownCloud test text file" to "textfile.txt" + And we save it into "FILEID" + And user "Alice" has created folder "newFolder" + And user "Alice" has copied file "textfile.txt" into "newFolder" inside space "Personal" using file-id "<>" + When user "Alice" lists the activities of folder "newFolder" from space "Personal" using the Graph API + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": ["value"], + "properties": { + "value": { + "type": "array", + "minItems": 2, + "maxItems": 2, + "uniqueItems": true, + "items": { + "oneOf": [ + { + "type": "object", + "required": ["id","template","times"], + "properties": { + "template": { + "type": "object", + "required": ["message","variables"], + "properties": { + "message": { + "const": "{user} added {resource} to {folder}" + } + } + } + } + }, + { + "type": "object", + "required": ["id","template","times"], + "properties": { + "id": { + "type": "string", + "pattern": "^%user_id_pattern%$" + }, + "template": { + "type": "object", + "required": ["message","variables"], + "properties": { + "message": { + "const": "{user} added {resource} to {folder}" + }, + "variables": { + "type": "object", + "required": ["folder", "resource", "user"], + "properties": { + "folder": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "const": "newFolder" + } + } + }, + "resource": { + "type": "object", + "required": ["id","name"], + "properties": { + "id": { + "type": "string", + "pattern": "^%file_id_pattern%$" + }, + "name": { + "const": "textfile.txt" + } + } + }, + "user": { + "type": "object", + "required": ["id","displayName"], + "properties": { + "id": { + "type": "string", + "pattern": "%user_id_pattern%" + }, + "displayName": { + "const": "Alice Hansen" + } + } + } + } + } + } + }, + "times": { + "type": "object", + "required": ["recordedTime"], + "properties": { + "recordedTime": { + "type": "string", + "format": "date-time" + } + } + } + } + } + ] + } + } + } + } + """ + + + Scenario: check edit activity + Given user "Alice" has uploaded file with content "ownCloud test text file" to "textfile.txt" + And we save it into "FILEID" + And user "Alice" has updated a file with content "updated content" using file-id "<>" + When user "Alice" lists the activities of file "textfile.txt" from space "Personal" using the Graph API + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": ["value"], + "properties": { + "value": { + "type": "array", + "minItems": 2, + "maxItems": 2, + "uniqueItems": true, + "items": { + "oneOf": [ + { + "type": "object", + "required": ["id", "template", "times"], + "properties": { + "template": { + "type": "object", + "required": ["message", "variables"], + "properties": { + "message": { + "const": "{user} added {resource} to {folder}" + } + } + } + } + }, + { + "type": "object", + "required": ["id", "template", "times"], + "properties": { + "template": { + "type": "object", + "required": ["message", "variables"], + "properties": { + "message": { + "const": "{user} updated {resource} in {folder}" + }, + "variables": { + "type": "object", + "required": ["folder", "resource", "user"], + "properties": { + "folder": { + "type": "object", + "required": ["name"], + "properties": { + "id": { + "type": "string", + "pattern": "%user_id_pattern%" + }, + "name": { + "const": "Alice Hansen" + } + } + }, + "resource": { + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { + "type": "string", + "pattern": "%file_id_pattern%" + }, + "name": { + "const": "textfile.txt" + } + } + }, + "user": { + "type": "object", + "required": ["id","displayName"], + "properties": { + "id": { + "type": "string", + "pattern": "%user_id_pattern%" + }, + "displayName": { + "const": "Alice Hansen" + } + } + } + } + } + } + }, + "times": { + "type": "object", + "required": ["recordedTime"] + } + } + } + ] + } + } + } + } + """ + + @issue-9744 + Scenario: check rename activity + Given user "Alice" has uploaded file with content "ownCloud test text file" to "textfile.txt" + And we save it into "FILEID" + And user "Alice" has renamed file "textfile.txt" into "renamed.txt" inside space "Personal" using file-id "<>" + When user "Alice" lists the activities of file "renamed.txt" from space "Personal" using the Graph API + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": ["value"], + "properties": { + "value": { + "type": "array", + "minItems": 2, + "maxItems": 2, + "uniqueItems": true, + "items": { + "oneOf": [ + { + "type": "object", + "required": ["id", "template", "times"], + "properties": { + "template": { + "type": "object", + "required": ["message", "variables"], + "properties": { + "message": { + "const": "{user} added {resource} to {folder}" + } + } + } + } + }, + { + "type": "object", + "required": ["id", "template", "times"], + "properties": { + "id": { + "type": "string", + "pattern": "^%user_id_pattern%$" + }, + "template": { + "type": "object", + "required": ["message", "variables"], + "properties": { + "message": { + "const": "{user} renamed {oldResource} to {resource}" + }, + "variables": { + "type": "object", + "required": ["oldResource", "resource", "user"], + "properties": { + "oldResource": { + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { + "const": "" + }, + "name": { + "const": "textfile.txt" + } + } + }, + "resource": { + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { + "type": "string", + "pattern": "^%file_id_pattern%$" + }, + "name": { + "const": "renamed.txt" + } + } + }, + "user": { + "type": "object", + "required": ["id", "displayName"], + "properties": { + "id": { + "type": "string", + "pattern": "^%user_id_pattern%$" + }, + "displayName": { + "const": "Alice Hansen" + } + } + } + } + } + } + }, + "times": { + "type": "object", + "required": ["recordedTime"], + "properties": { + "recordedTime": { + "type": "string", + "format": "date-time" + } + } + } + } + } + ] + } + } + } + } + """ + + + Scenario: check move activity + Given user "Alice" has uploaded file with content "ownCloud test text file" to "textfile.txt" + And we save it into "FILEID" + And user "Alice" has created folder "New Folder" + And user "Alice" has moved file "textfile.txt" into "New Folder" inside space "Personal" using file-id "<>" + When user "Alice" lists the activities of file "New Folder/textfile.txt" from space "Personal" using the Graph API + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": ["value"], + "properties": { + "value": { + "type": "array", + "minItems": 2, + "maxItems": 2, + "uniqueItems": true, + "items": { + "oneOf": [ + { + "type": "object", + "required": ["id","template","times"], + "properties": { + "template": { + "type": "object", + "required": ["message","variables"], + "properties": { + "message": { + "const": "{user} added {resource} to {folder}" + } + } + } + } + }, + { + "type": "object", + "required": ["id","template","times"], + "properties": { + "id": { + "type": "string", + "pattern": "^%user_id_pattern%$" + }, + "template": { + "type": "object", + "required": ["message","variables"], + "properties": { + "message": { + "const": "{user} moved {resource} to {folder}" + }, + "variables": { + "type": "object", + "required": ["folder", "resource", "user"], + "properties": { + "folder": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "const": "New Folder" + } + } + }, + "resource": { + "type": "object", + "required": ["id","name"], + "properties": { + "id": { + "type": "string", + "pattern": "^%file_id_pattern%$" + }, + "name": { + "const": "textfile.txt" + } + } + }, + "user": { + "type": "object", + "required": ["id","displayName"], + "properties": { + "id": { + "type": "string", + "pattern": "%user_id_pattern%" + }, + "displayName": { + "const": "Alice Hansen" + } + } + } + } + } + } + }, + "times": { + "type": "object", + "required": ["recordedTime"], + "properties": { + "recordedTime": { + "type": "string", + "format": "date-time" + } + } + } + } + } + ] + } + } + } + } + """