diff --git a/tests/acceptance/features/apiEmailNotification/notification.feature b/tests/acceptance/features/apiEmailNotification/notification.feature new file mode 100644 index 00000000000..b97fd66a467 --- /dev/null +++ b/tests/acceptance/features/apiEmailNotification/notification.feature @@ -0,0 +1,241 @@ +@api +Feature: Notification + As a user + I want to be notified of actions + So that I can stay updated about the information + + Background: + Given these users have been created with default attributes and without skeleton files: + | username | + | Alice | + | Brian | + | Carol | + And user "Alice" has uploaded file with content "other data" to "/textfile1.txt" + And user "Alice" has created folder "my_data" + + Scenario Outline: user gets a notification of resource sharing + And user "Alice" has shared entry "" with user "Brian" + When user "Brian" lists all notifications + Then the HTTP status code should be "200" + And the JSON response should contain a notification message with the subject "Resource shared" and the message-details should match + """ + { + "type": "object", + "required": [ + "app", + "datetime", + "message", + "messageRich", + "messageRichParameters", + "notification_id", + "object_id", + "object_type", + "subject", + "subjectRich", + "user" + ], + "properties": { + "app": { + "type": "string", + "enum": ["userlog"] + }, + "message": { + "type": "string", + "enum": ["Alice Hansen shared with you"] + }, + "messageRich": { + "type": "string", + "enum": ["{user} shared {resource} with you"] + }, + "messageRichParameters": { + "type": "object", + "required": [ + "resource", + "user" + ], + "properties": { + "resource": { + "type": "object", + "required": [ + "id", + "name" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\\$[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}![a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + }, + "name": { + "type": "string", + "enum": [""] + } + } + }, + "user": { + "type": "object", + "required": [ + "displayname", + "id", + "name" + ], + "properties": { + "displayname": { + "type": "string", + "enum": ["Alice Hansen"] + }, + "id": { + "type": "string", + "enim": ["%user_id%"] + }, + "name": { + "type": "string", + "enum": ["Alice"] + } + } + } + } + }, + "notification_id": { + "type": "string" + }, + "object_id": { + "type": "string" + }, + "object_type": { + "type": "string", + "enum": ["share"] + }, + "subject": { + "type": "string", + "enum": ["Resource shared"] + }, + "subjectRich": { + "type": "string", + "enum": ["Resource shared"] + }, + "user": { + "type": "string", + "enum": ["Alice"] + } + } + } + """ + Examples: + | resource | + | textfile1.txt | + | my_data | + + + Scenario Outline: user gets a notification of unsharing resource + And user "Alice" has shared entry "" with user "Brian" + And user "Brian" has accepted share "/" offered by user "Alice" + And user "Alice" has unshared folder "" for "Brian" + When user "Brian" lists all notifications + Then the HTTP status code should be "200" + And the JSON response should contain a notification message with the subject "Resource unshared" and the message-details should match + """ + { + "type": "object", + "required": [ + "app", + "datetime", + "message", + "messageRich", + "messageRichParameters", + "notification_id", + "object_id", + "object_type", + "subject", + "subjectRich", + "user" + ], + "properties": { + "app": { + "type": "string", + "enum": ["userlog"] + }, + "message": { + "type": "string", + "enum": ["Alice Hansen unshared with you"] + }, + "messageRich": { + "type": "string", + "enum": ["{user} unshared {resource} with you"] + }, + "messageRichParameters": { + "type": "object", + "required": [ + "resource", + "user" + ], + "properties": { + "resource": { + "type": "object", + "required": [ + "id", + "name" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\\$[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}![a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + }, + "name": { + "type": "string", + "enum": [""] + } + } + }, + "user": { + "type": "object", + "required": [ + "displayname", + "id", + "name" + ], + "properties": { + "displayname": { + "type": "string", + "enum": ["Alice Hansen"] + }, + "id": { + "type": "string", + "enim": ["%user_id%"] + }, + "name": { + "type": "string", + "enum": ["Alice"] + } + } + } + } + }, + "notification_id": { + "type": "string" + }, + "object_id": { + "type": "string" + }, + "object_type": { + "type": "string", + "enum": ["share"] + }, + "subject": { + "type": "string", + "enum": ["Resource unshared"] + }, + "subjectRich": { + "type": "string", + "enum": ["Resource unshared"] + }, + "user": { + "type": "string", + "enum": ["Alice"] + } + } + } + """ + Examples: + | resource | + | textfile1.txt | + | my_data | diff --git a/tests/acceptance/features/bootstrap/Sharing.php b/tests/acceptance/features/bootstrap/Sharing.php index d4db525f70c..ac8c30af16a 100644 --- a/tests/acceptance/features/bootstrap/Sharing.php +++ b/tests/acceptance/features/bootstrap/Sharing.php @@ -3023,13 +3023,13 @@ public function userRemovesAllSharesFromTheFileNamed(string $user, string $fileN public function userHasRemovedAllSharesFromTheFileNamed(string $user, string $fileName):void { $user = $this->getActualUsername($user); $this->removeAllSharesFromResource($user, $fileName); - $dataResponded = $this->getShares($user, $fileName); + $response = $this->getShares($user, $fileName); Assert::assertEquals( 0, - \count($dataResponded), + \count($response), __METHOD__ . " Expected all shares to be removed from '$fileName' but got '" - . \count($dataResponded) + . \count($response) . "' shares still present" ); } @@ -3055,7 +3055,7 @@ public function getShares(string $user, string $path):SimpleXMLElement { $user, $this->getPasswordForUser($user), "GET", - $this->getSharesEndpointPath("?path=$path"), + $this->getSharesEndpointPath($path), $this->getStepLineRef(), [], $this->ocsApiVersion @@ -3075,7 +3075,7 @@ public function getShares(string $user, string $path):SimpleXMLElement { */ public function checkPublicShares(string $user, string $path, ?TableNode $TableNode):void { $user = $this->getActualUsername($user); - $dataResponded = $this->getShares($user, $path); + $response = $this->getShares($user, "?path=$path"); $this->verifyTableNodeColumns($TableNode, ['path', 'permissions', 'name']); if ($TableNode instanceof TableNode) { @@ -3083,7 +3083,7 @@ public function checkPublicShares(string $user, string $path, ?TableNode $TableN foreach ($elementRows as $expectedElementsArray) { $nameFound = false; - foreach ($dataResponded as $elementResponded) { + foreach ($response as $elementResponded) { if ((string) $elementResponded->name[0] === $expectedElementsArray['name']) { Assert::assertEquals( $expectedElementsArray['path'], @@ -3126,14 +3126,14 @@ public function checkPublicShares(string $user, string $path, ?TableNode $TableN public function checkPublicSharesAreEmpty(string $user, string $entry, string $path):void { $user = $this->getActualUsername($user); $this->asFileOrFolderShouldExist($user, $entry, $path); - $dataResponded = $this->getShares($user, $path); + $response = $this->getShares($user, "?path=$path"); //It shouldn't have public shares Assert::assertEquals( 0, - \count($dataResponded), + \count($response), __METHOD__ . " As '$user', '$path' was expected to have no shares, but got '" - . \count($dataResponded) + . \count($response) . "' shares present" ); } @@ -3146,8 +3146,8 @@ public function checkPublicSharesAreEmpty(string $user, string $entry, string $p * @return string|null */ public function getPublicShareIDByName(string $user, string $path, string $name):?string { - $dataResponded = $this->getShares($user, $path); - foreach ($dataResponded as $elementResponded) { + $response = $this->getShares($user, "?path=$path"); + foreach ($response as $elementResponded) { if ((string) $elementResponded->name[0] === $name) { return (string) $elementResponded->id[0]; } @@ -3236,9 +3236,9 @@ public function userReactsToShareOfferedBy(string $user, string $action, string $user = $this->getActualUsername($user); $offeredBy = $this->getActualUsername($offeredBy); - $dataResponded = $this->getAllSharesSharedWithUser($user); + $response = $this->getAllSharesSharedWithUser($user); $shareId = null; - foreach ($dataResponded as $shareElement) { + foreach ($response as $shareElement) { // SharingHelper::SHARE_STATES has the mapping between the words for share states // like "accepted", "pending",... and the integer constants 0, 1,... that are in // the "state" field of the share data. @@ -3479,6 +3479,47 @@ public function assertNoSharesOfUserAreInState(string $user, string $state):void ); } + /** + * @Given /^user "([^"]*)" has unshared folder "([^"]*)" for "([^"]*)"$/ + * + * @param string $sharer + * @param string $path + * @param string $sharee + * + * @return void + * @throws JsonException + */ + public function userHasUnsharedFolderFor(string $sharer, string $path, string $sharee): void { + $sharer = $this->getActualUsername($sharer); + $sharee = $this->getActualUsername($sharee); + + $path = "?path=$path&share_types=0"; + $response = $this->getShares($sharer, $path); + $shareId = null; + foreach ($response as $shareElement) { + if ((string)$shareElement->share_with[0] === $sharee) { + $shareId = (string) $shareElement->id; + break; + } + } + Assert::assertNotNull( + $shareId, + __METHOD__ . " could not find share, offered by $sharer to $sharee" + ); + + $this->ocsContext->userSendsHTTPMethodToOcsApiEndpointWithBody( + $sharer, + 'DELETE', + '/apps/files_sharing/api/v' . $this->sharingApiVersion . '/shares/' . $shareId + ); + + $this->ocsContext->assertOCSResponseIndicatesSuccess( + 'The ocs share response does not indicate success.', + ); + $this->emptyLastHTTPStatusCodesArray(); + $this->emptyLastOCSStatusCodesArray(); + } + /** * @Then the sharing API should report that no shares are shared with user :user * diff --git a/tests/acceptance/features/bootstrap/WebDav.php b/tests/acceptance/features/bootstrap/WebDav.php index 49c3a0ad6f5..d44663511a9 100644 --- a/tests/acceptance/features/bootstrap/WebDav.php +++ b/tests/acceptance/features/bootstrap/WebDav.php @@ -3437,19 +3437,6 @@ public function theUserDeletesFile(string $file):void { $this->userDeletesFile($this->getCurrentUser(), $file); } - /** - * @Given /^the user has (deleted|unshared) (file|folder) "([^"]*)"$/ - * - * @param string $deletedOrUnshared - * @param string $fileOrFolder - * @param string $file - * - * @return void - */ - public function theUserHasDeletedFile(string $deletedOrUnshared, string $fileOrFolder, string $file):void { - $this->userHasDeletedFile($this->getCurrentUser(), $deletedOrUnshared, $fileOrFolder, $file); - } - /** * @When /^user "([^"]*)" (?:deletes|unshares) these (?:files|folders|entries) without delays using the WebDAV API$/ *