From ed1a4671c8877df3764e5d6e971eee080fb49b07 Mon Sep 17 00:00:00 2001 From: amrita Date: Thu, 18 May 2023 09:43:01 +0545 Subject: [PATCH 1/2] Add api tests for notification --- .drone.star | 4 +- tests/acceptance/config/behat.yml | 4 +- .../emailNotification.feature | 0 .../apiNotification/notification.feature | 242 ++++++++++++++++++ .../acceptance/features/bootstrap/Sharing.php | 67 ++++- 5 files changed, 300 insertions(+), 17 deletions(-) rename tests/acceptance/features/{apiEmailNotification => apiNotification}/emailNotification.feature (100%) create mode 100644 tests/acceptance/features/apiNotification/notification.feature diff --git a/.drone.star b/.drone.star index abcf7d67d69..41ec2b3ba04 100644 --- a/.drone.star +++ b/.drone.star @@ -117,9 +117,9 @@ config = { "skip": False, "earlyFail": True, }, - "apiEmailNotification": { + "apiNotification": { "suites": [ - "apiEmailNotification", + "apiNotification", ], "skip": False, "earlyFail": True, diff --git a/tests/acceptance/config/behat.yml b/tests/acceptance/config/behat.yml index 874db10c58b..74d2e8fda5e 100644 --- a/tests/acceptance/config/behat.yml +++ b/tests/acceptance/config/behat.yml @@ -170,9 +170,9 @@ default: - GraphContext: - OcisConfigContext: - apiEmailNotification: + apiNotification: paths: - - '%paths.base%/../features/apiEmailNotification' + - '%paths.base%/../features/apiNotification' context: *common_ldap_suite_context contexts: - NotificationContext: diff --git a/tests/acceptance/features/apiEmailNotification/emailNotification.feature b/tests/acceptance/features/apiNotification/emailNotification.feature similarity index 100% rename from tests/acceptance/features/apiEmailNotification/emailNotification.feature rename to tests/acceptance/features/apiNotification/emailNotification.feature diff --git a/tests/acceptance/features/apiNotification/notification.feature b/tests/acceptance/features/apiNotification/notification.feature new file mode 100644 index 00000000000..f15bd30f8ed --- /dev/null +++ b/tests/acceptance/features/apiNotification/notification.feature @@ -0,0 +1,242 @@ +@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 + Given 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 + Given 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 * From 93df6ed3366492a9e186841959b038d3012eaa16 Mon Sep 17 00:00:00 2001 From: amrita Date: Mon, 22 May 2023 10:11:10 +0545 Subject: [PATCH 2/2] Address review --- docs/ocis/development/testing.md | 2 +- .../features/apiNotification/notification.feature | 4 ++-- tests/acceptance/features/bootstrap/Sharing.php | 15 +++++++-------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/docs/ocis/development/testing.md b/docs/ocis/development/testing.md index ee4063d247b..3e966009595 100644 --- a/docs/ocis/development/testing.md +++ b/docs/ocis/development/testing.md @@ -352,7 +352,7 @@ TEST_OCIS=true \ TEST_SERVER_URL="https://localhost:9200" \ EMAIL_HOST="localhost" \ EMAIL_PORT=9000 \ -BEHAT_FEATURE="tests/acceptance/features/apiEmailNotification/emailNotification.feature" \ +BEHAT_FEATURE="tests/acceptance/features/apiNotification/emailNotification.feature" \ make test-acceptance-api ``` diff --git a/tests/acceptance/features/apiNotification/notification.feature b/tests/acceptance/features/apiNotification/notification.feature index f15bd30f8ed..a0a364df324 100644 --- a/tests/acceptance/features/apiNotification/notification.feature +++ b/tests/acceptance/features/apiNotification/notification.feature @@ -1,7 +1,7 @@ @api Feature: Notification As a user - I want to be notified of actions + I want to be notified of various events So that I can stay updated about the information Background: @@ -130,7 +130,7 @@ Feature: Notification Scenario Outline: user gets a notification of unsharing resource Given 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" + And user "Alice" has unshared entity "" shared to "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 diff --git a/tests/acceptance/features/bootstrap/Sharing.php b/tests/acceptance/features/bootstrap/Sharing.php index ac8c30af16a..013099414fc 100644 --- a/tests/acceptance/features/bootstrap/Sharing.php +++ b/tests/acceptance/features/bootstrap/Sharing.php @@ -3055,7 +3055,7 @@ public function getShares(string $user, string $path):SimpleXMLElement { $user, $this->getPasswordForUser($user), "GET", - $this->getSharesEndpointPath($path), + $this->getSharesEndpointPath("?path=$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); - $response = $this->getShares($user, "?path=$path"); + $response = $this->getShares($user, $path); $this->verifyTableNodeColumns($TableNode, ['path', 'permissions', 'name']); if ($TableNode instanceof TableNode) { @@ -3126,7 +3126,7 @@ 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); - $response = $this->getShares($user, "?path=$path"); + $response = $this->getShares($user, $path); //It shouldn't have public shares Assert::assertEquals( 0, @@ -3146,7 +3146,7 @@ public function checkPublicSharesAreEmpty(string $user, string $entry, string $p * @return string|null */ public function getPublicShareIDByName(string $user, string $path, string $name):?string { - $response = $this->getShares($user, "?path=$path"); + $response = $this->getShares($user, $path); foreach ($response as $elementResponded) { if ((string) $elementResponded->name[0] === $name) { return (string) $elementResponded->id[0]; @@ -3480,7 +3480,7 @@ public function assertNoSharesOfUserAreInState(string $user, string $state):void } /** - * @Given /^user "([^"]*)" has unshared folder "([^"]*)" for "([^"]*)"$/ + * @Given /^user "([^"]*)" has unshared (?:folder|file|entity) "([^"]*)" shared to "([^"]*)"$/ * * @param string $sharer * @param string $path @@ -3489,12 +3489,11 @@ public function assertNoSharesOfUserAreInState(string $user, string $state):void * @return void * @throws JsonException */ - public function userHasUnsharedFolderFor(string $sharer, string $path, string $sharee): void { + public function userHasUnsharedResourceSharedTo(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); + $response = $this->getShares($sharer, "$path&share_types=0"); $shareId = null; foreach ($response as $shareElement) { if ((string)$shareElement->share_with[0] === $sharee) {