diff --git a/.github/workflows/integration-sqlite.yml b/.github/workflows/integration-sqlite.yml index 8fbea470911..0ec7e452a74 100644 --- a/.github/workflows/integration-sqlite.yml +++ b/.github/workflows/integration-sqlite.yml @@ -62,6 +62,7 @@ jobs: - '--tags ~@large files_features' - 'filesdrop_features' - 'file_conversions' + - 'files_reminders' - 'openldap_features' - 'openldap_numerical_features' - 'ldap_features' diff --git a/build/integration/config/behat.yml b/build/integration/config/behat.yml index 0a3fe4fd823..9d06553ba38 100644 --- a/build/integration/config/behat.yml +++ b/build/integration/config/behat.yml @@ -131,6 +131,16 @@ default: - admin - admin regular_user_password: 123456 + files_reminders: + paths: + - "%paths.base%/../files_reminders" + contexts: + - FilesRemindersContext: + baseUrl: http://localhost:8080 + admin: + - admin + - admin + regular_user_password: 123456 capabilities: paths: - "%paths.base%/../capabilities_features" diff --git a/build/integration/features/bootstrap/BasicStructure.php b/build/integration/features/bootstrap/BasicStructure.php index 59a4312913e..e6ba54a7212 100644 --- a/build/integration/features/bootstrap/BasicStructure.php +++ b/build/integration/features/bootstrap/BasicStructure.php @@ -116,18 +116,27 @@ trait BasicStructure { } /** - * Parses the xml answer to get ocs response which doesn't match with + * Parses the xml or json answer to get ocs response which doesn't match with * http one in v1 of the api. * * @param ResponseInterface $response * @return string */ - public function getOCSResponse($response) { - $body = simplexml_load_string((string)$response->getBody()); - if ($body === false) { - throw new \RuntimeException('Could not parse OCS response, body is not valid XML'); + public function getOCSResponseCode($response): int { + if ($response === null) { + throw new \RuntimeException('No response available'); } - return $body->meta[0]->statuscode; + + $body = (string)$response->getBody(); + if (str_starts_with($body, '<')) { + $body = simplexml_load_string($body); + if ($body === false) { + throw new \RuntimeException('Could not parse OCS response, body is not valid XML'); + } + return (int)$body->meta[0]->statuscode; + } + + return json_decode($body, true)['ocs']['meta']['statuscode']; } /** @@ -257,7 +266,7 @@ trait BasicStructure { * @param int $statusCode */ public function theOCSStatusCodeShouldBe($statusCode) { - Assert::assertEquals($statusCode, $this->getOCSResponse($this->response)); + Assert::assertEquals($statusCode, $this->getOCSResponseCode($this->response)); } /** diff --git a/build/integration/features/bootstrap/FilesRemindersContext.php b/build/integration/features/bootstrap/FilesRemindersContext.php new file mode 100644 index 00000000000..13adfaf5f83 --- /dev/null +++ b/build/integration/features/bootstrap/FilesRemindersContext.php @@ -0,0 +1,96 @@ +getFileIdForPath($this->currentUser, $path); + $this->sendRequestForJSON( + 'PUT', + '/apps/files_reminders/api/v1/' . $fileId, + ['dueDate' => $dueDate], + ['OCS-APIREQUEST' => 'true'] + ); + } + + /** + * @Then the user sees the reminder for :path is set to :dueDate + */ + public function retrievingTheReminderForFile($path, $dueDate) { + $fileId = $this->getFileIdForPath($this->currentUser, $path); + $this->sendRequestForJSON( + 'GET', + '/apps/files_reminders/api/v1/' . $fileId, + null, + ['OCS-APIREQUEST' => 'true'] + ); + $response = $this->getDueDateFromOCSResponse(); + Assert::assertEquals($dueDate, $response); + } + + /** + * @Then the user sees the reminder for :path is not set + */ + public function retrievingTheReminderForFileIsNotSet($path) { + $fileId = $this->getFileIdForPath($this->currentUser, $path); + $this->sendRequestForJSON( + 'GET', + '/apps/files_reminders/api/v1/' . $fileId, + null, + ['OCS-APIREQUEST' => 'true'] + ); + $response = $this->getDueDateFromOCSResponse(); + Assert::assertNull($response); + } + + /** + * @When the user removes the reminder for :path + */ + public function removingTheReminderForFile($path) { + $fileId = $this->getFileIdForPath($this->currentUser, $path); + $this->sendRequestForJSON( + 'DELETE', + '/apps/files_reminders/api/v1/' . $fileId, + null, + ['OCS-APIREQUEST' => 'true'] + ); + } + + /** + * Check the due date from OCS response + */ + private function getDueDateFromOCSResponse(): ?string { + if ($this->response === null) { + throw new \RuntimeException('No response available'); + } + + $body = (string)$this->response->getBody(); + if (str_starts_with($body, '<')) { + $body = simplexml_load_string($body); + if ($body === false) { + throw new \RuntimeException('Could not parse OCS response, body is not valid XML'); + } + return $body->data->dueDate; + } + + $body = json_decode($body, true); + return $body['ocs']['data']['dueDate'] ?? null; + } +} diff --git a/build/integration/files_reminders/files_reminders.feature b/build/integration/files_reminders/files_reminders.feature new file mode 100644 index 00000000000..b8446814418 --- /dev/null +++ b/build/integration/files_reminders/files_reminders.feature @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-only +Feature: Files reminders + + Background: + Given using api version "2" + + Scenario: Set a reminder with a past due date + Given user "user0" exists + Given As an "user0" + Given User "user0" uploads file "data/textfile.txt" to "/file.txt" + When the user sets a reminder for "/file.txt" with due date "2000-01-01T00:00:00Z" + Then the OCS status code should be "400" + Then the user sees the reminder for "/file.txt" is not set + + Scenario: Set a reminder with a valid due date + Given user "user1" exists + Given As an "user1" + Given User "user1" uploads file "data/textfile.txt" to "/file.txt" + When the user sets a reminder for "/file.txt" with due date "2100-01-01T00:00:00Z" + Then the OCS status code should be "201" + Then the user sees the reminder for "/file.txt" is set to "2100-01-01T00:00:00+00:00" + + Scenario: Remove a reminder + Given user "user2" exists + Given As an "user2" + Given User "user2" uploads file "data/textfile.txt" to "/file.txt" + When the user sets a reminder for "/file.txt" with due date "2100-01-01T00:00:00Z" + Then the OCS status code should be "201" + Then the user sees the reminder for "/file.txt" is set to "2100-01-01T00:00:00+00:00" + When the user removes the reminder for "/file.txt" + Then the OCS status code should be "200" + Then the user sees the reminder for "/file.txt" is not set