From 2e9bf5fb43aca7fff00321c3f08ad77e7afb3ceb Mon Sep 17 00:00:00 2001 From: Hamza Date: Fri, 17 Apr 2026 15:29:05 +0200 Subject: [PATCH 1/2] test(integration): add tests for calendar delegation Signed-off-by: Hamza --- .../dav_features/caldav-delegation.feature | 21 +++++++++++++++++++ .../features/bootstrap/CalDavContext.php | 20 ++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 build/integration/dav_features/caldav-delegation.feature diff --git a/build/integration/dav_features/caldav-delegation.feature b/build/integration/dav_features/caldav-delegation.feature new file mode 100644 index 0000000000000..ce52bca6ab837 --- /dev/null +++ b/build/integration/dav_features/caldav-delegation.feature @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +Feature: calendar delegation + Calendar delegation grants another user/principal control of a calendar account, + including all calendars the delegator can access. + + Scenario: admin grants user0 read access to her calendar account + Given user "admin" exists + And user "user0" exists + When "admin" updates property "{DAV:}group-member-set" to href "/remote.php/dav/principals/users/user0" of principal "users/admin/calendar-proxy-read" on the endpoint "/remote.php/dav/principals/" + Then The CalDAV response should be multi status + And The CalDAV response should contain an href "/remote.php/dav/principals/users/admin/calendar-proxy-read" + And The CalDAV response should contain a property "{DAV:}group-member-set" + + Scenario: admin grants write access to her calendar account + Given user "admin" exists + And user "user0" exists + When "admin" updates property "{DAV:}group-member-set" to href "/remote.php/dav/principals/users/user0" of principal "users/admin/calendar-proxy-write" on the endpoint "/remote.php/dav/principals/" + Then The CalDAV response should be multi status + And The CalDAV response should contain an href "/remote.php/dav/principals/users/admin/calendar-proxy-write" + And The CalDAV response should contain a property "{DAV:}group-member-set" \ No newline at end of file diff --git a/build/integration/features/bootstrap/CalDavContext.php b/build/integration/features/bootstrap/CalDavContext.php index 459c35089fa52..cbfed5210d8ca 100644 --- a/build/integration/features/bootstrap/CalDavContext.php +++ b/build/integration/features/bootstrap/CalDavContext.php @@ -174,6 +174,26 @@ public function theCaldavResponseShouldContainAPropertyWithHrefValue( } } + /** + * @Then The CalDAV response should contain an href :href + * @throws \Exception + */ + public function theCaldavResponseShouldContainAnHref(string $href): void { + /** @var \Sabre\DAV\Xml\Response\MultiStatus $multiStatus */ + $multiStatus = $this->responseXml['value']; + foreach ($multiStatus->getResponses() as $response) { + if ($response->getHref() === $href) { + return; + } + } + throw new \Exception( + sprintf( + 'Expected href %s not found in response', + $href, + ) + ); + } + /** * @Then The CalDAV response should be multi status * @throws \Exception From d6f4de3651ac5678bbc6498adff8587584c34658 Mon Sep 17 00:00:00 2001 From: Hamza Date: Mon, 20 Apr 2026 14:17:47 +0200 Subject: [PATCH 2/2] test(integration): add proper cleanup for caldav scenarios Signed-off-by: Hamza --- .../dav_features/caldav-delegation.feature | 2 + .../features/bootstrap/CalDavContext.php | 46 +++++++++++++------ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/build/integration/dav_features/caldav-delegation.feature b/build/integration/dav_features/caldav-delegation.feature index ce52bca6ab837..d4cc781f320e6 100644 --- a/build/integration/dav_features/caldav-delegation.feature +++ b/build/integration/dav_features/caldav-delegation.feature @@ -4,6 +4,7 @@ Feature: calendar delegation Calendar delegation grants another user/principal control of a calendar account, including all calendars the delegator can access. + @caldav-delegation Scenario: admin grants user0 read access to her calendar account Given user "admin" exists And user "user0" exists @@ -12,6 +13,7 @@ Feature: calendar delegation And The CalDAV response should contain an href "/remote.php/dav/principals/users/admin/calendar-proxy-read" And The CalDAV response should contain a property "{DAV:}group-member-set" + @caldav-delegation Scenario: admin grants write access to her calendar account Given user "admin" exists And user "user0" exists diff --git a/build/integration/features/bootstrap/CalDavContext.php b/build/integration/features/bootstrap/CalDavContext.php index cbfed5210d8ca..14100ffa51086 100644 --- a/build/integration/features/bootstrap/CalDavContext.php +++ b/build/integration/features/bootstrap/CalDavContext.php @@ -42,21 +42,39 @@ public function setUpScenario() { /** @AfterScenario */ public function afterScenario() { - $davUrl = $this->baseUrl . '/remote.php/dav/calendars/admin/MyCalendar'; - try { - $this->client->delete( - $davUrl, - [ - 'auth' => [ - 'admin', - 'admin', - ], - 'headers' => [ - 'X-NC-CalDAV-No-Trashbin' => '1', + foreach (['MyCalendar', 'MyCalendar2'] as $calendarName) { + try { + $this->client->delete( + $this->baseUrl . '/remote.php/dav/calendars/admin/' . $calendarName, + [ + 'auth' => ['admin', 'admin'], + 'headers' => ['X-NC-CalDAV-No-Trashbin' => '1'], ] - ] - ); - } catch (\GuzzleHttp\Exception\ClientException $e) { + ); + } catch (\GuzzleHttp\Exception\ClientException $e) { + } + } + } + + /** @AfterScenario @caldav-delegation */ + public function afterDelegationScenario() { + foreach (['calendar-proxy-read', 'calendar-proxy-write'] as $proxyType) { + try { + $propPatch = new \Sabre\DAV\Xml\Request\PropPatch(); + $propPatch->properties = ['{DAV:}group-member-set' => new \Sabre\DAV\Xml\Property\Href([])]; + $xml = new \Sabre\Xml\Service(); + $body = $xml->write('{DAV:}propertyupdate', $propPatch, '/'); + $this->client->request( + 'PROPPATCH', + $this->baseUrl . '/remote.php/dav/principals/users/admin/' . $proxyType, + [ + 'headers' => ['Content-Type' => 'application/xml; charset=UTF-8'], + 'body' => $body, + 'auth' => ['admin', 'admin'], + ] + ); + } catch (\GuzzleHttp\Exception\ClientException $e) { + } } }