aboutsummaryrefslogtreecommitdiffstats
path: root/apps/dav/tests/unit
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav/tests/unit')
-rw-r--r--apps/dav/tests/unit/AppInfo/ApplicationTest.php1
-rw-r--r--apps/dav/tests/unit/AppInfo/PluginManagerTest.php4
-rw-r--r--apps/dav/tests/unit/Avatars/AvatarHomeTest.php32
-rw-r--r--apps/dav/tests/unit/Avatars/AvatarNodeTest.php8
-rw-r--r--apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php15
-rw-r--r--apps/dav/tests/unit/BackgroundJob/CleanupOrphanedChildrenJobTest.php170
-rw-r--r--apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php31
-rw-r--r--apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php16
-rw-r--r--apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php26
-rw-r--r--apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php26
-rw-r--r--apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php27
-rw-r--r--apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php48
-rw-r--r--apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php405
-rw-r--r--apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php35
-rw-r--r--apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php54
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/BackendTest.php69
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Filter/CalendarTest.php17
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Filter/GenericTest.php68
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Filter/TodoTest.php17
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Provider/BaseTest.php58
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php123
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Setting/GenericTest.php77
-rw-r--r--apps/dav/tests/unit/CalDAV/AppCalendar/AppCalendarTest.php21
-rw-r--r--apps/dav/tests/unit/CalDAV/AppCalendar/CalendarObjectTest.php33
-rw-r--r--apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php23
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php5
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionObjectTest.php6
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php7
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php49
-rw-r--r--apps/dav/tests/unit/CalDAV/CalDavBackendTest.php225
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarHomeTest.php28
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarImplTest.php101
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarManagerTest.php23
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarTest.php105
-rw-r--r--apps/dav/tests/unit/CalDAV/DefaultCalendarValidatorTest.php171
-rw-r--r--apps/dav/tests/unit/CalDAV/EventComparisonServiceTest.php3
-rw-r--r--apps/dav/tests/unit/CalDAV/EventReaderTest.php1087
-rw-r--r--apps/dav/tests/unit/CalDAV/Export/ExportServiceTest.php81
-rw-r--r--apps/dav/tests/unit/CalDAV/Integration/ExternalCalendarTest.php17
-rw-r--r--apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php19
-rw-r--r--apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php15
-rw-r--r--apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php27
-rw-r--r--apps/dav/tests/unit/CalDAV/OutboxTest.php11
-rw-r--r--apps/dav/tests/unit/CalDAV/PluginTest.php16
-rw-r--r--apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php45
-rw-r--r--apps/dav/tests/unit/CalDAV/PublicCalendarTest.php30
-rw-r--r--apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php8
-rw-r--r--apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php33
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php65
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/AbstractNotificationProviderTestCase.php (renamed from apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/AbstractNotificationProviderTest.php)45
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php85
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php25
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotificationProviderManagerTest.php16
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotifierTest.php45
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php231
-rw-r--r--apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTestCase.php (renamed from apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTest.php)125
-rw-r--r--apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php4
-rw-r--r--apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php4
-rw-r--r--apps/dav/tests/unit/CalDAV/Schedule/IMipPluginCharsetTest.php193
-rw-r--r--apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php443
-rw-r--r--apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php2145
-rw-r--r--apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php484
-rw-r--r--apps/dav/tests/unit/CalDAV/Search/Request/CalendarSearchReportTest.php18
-rw-r--r--apps/dav/tests/unit/CalDAV/Search/SearchPluginTest.php4
-rw-r--r--apps/dav/tests/unit/CalDAV/Security/RateLimitingPluginTest.php10
-rw-r--r--apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php18
-rw-r--r--apps/dav/tests/unit/CalDAV/TimeZoneFactoryTest.php51
-rw-r--r--apps/dav/tests/unit/CalDAV/TimezoneServiceTest.php12
-rw-r--r--apps/dav/tests/unit/CalDAV/TipBrokerTest.php180
-rw-r--r--apps/dav/tests/unit/CalDAV/Validation/CalDavValidatePluginTest.php73
-rw-r--r--apps/dav/tests/unit/CalDAV/WebcalCaching/ConnectionTest.php176
-rw-r--r--apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php2
-rw-r--r--apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php483
-rw-r--r--apps/dav/tests/unit/CapabilitiesTest.php39
-rw-r--r--apps/dav/tests/unit/CardDAV/Activity/BackendTest.php74
-rw-r--r--apps/dav/tests/unit/CardDAV/AddressBookImplTest.php125
-rw-r--r--apps/dav/tests/unit/CardDAV/AddressBookTest.php36
-rw-r--r--apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php142
-rw-r--r--apps/dav/tests/unit/CardDAV/CardDavBackendTest.php275
-rw-r--r--apps/dav/tests/unit/CardDAV/ContactsManagerTest.php16
-rw-r--r--apps/dav/tests/unit/CardDAV/ConverterTest.php61
-rw-r--r--apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php80
-rw-r--r--apps/dav/tests/unit/CardDAV/Security/CardDavRateLimitingPluginTest.php10
-rw-r--r--apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php28
-rw-r--r--apps/dav/tests/unit/CardDAV/SyncServiceTest.php466
-rw-r--r--apps/dav/tests/unit/CardDAV/SystemAddressBookTest.php24
-rw-r--r--apps/dav/tests/unit/CardDAV/Validation/CardDavValidatePluginTest.php73
-rw-r--r--apps/dav/tests/unit/Command/DeleteCalendarTest.php35
-rw-r--r--apps/dav/tests/unit/Command/ListAddressbooksTest.php107
-rw-r--r--apps/dav/tests/unit/Command/ListCalendarSharesTest.php172
-rw-r--r--apps/dav/tests/unit/Command/ListCalendarsTest.php27
-rw-r--r--apps/dav/tests/unit/Command/MoveCalendarTest.php240
-rw-r--r--apps/dav/tests/unit/Command/RemoveInvalidSharesTest.php20
-rw-r--r--apps/dav/tests/unit/Comments/CommentsNodeTest.php99
-rw-r--r--apps/dav/tests/unit/Comments/CommentsPluginTest.php52
-rw-r--r--apps/dav/tests/unit/Comments/EntityCollectionTest.php54
-rw-r--r--apps/dav/tests/unit/Comments/EntityTypeCollectionTest.php47
-rw-r--r--apps/dav/tests/unit/Comments/RootCollectionTest.php55
-rw-r--r--apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php79
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/AuthTest.php295
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php29
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/BlockLegacyClientPluginTest.php121
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/CommentsPropertiesPluginTest.php92
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/CopyEtagHeaderPluginTest.php17
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php67
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php125
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/DummyGetResponsePluginTest.php17
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/Exception/ForbiddenTest.php8
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/Exception/InvalidPathTest.php8
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php20
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/FakeLockerPluginTest.php81
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/FileTest.php554
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php490
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php290
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/MaintenancePluginTest.php15
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/NodeTest.php117
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php123
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php170
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/PropFindMonitorPluginTest.php133
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/PropFindPreloadNotifyPluginTest.php92
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/PropfindCompressionPluginTest.php3
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php124
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/QuotaPluginTest.php114
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php24
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/DeleteTest.php6
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/DownloadTest.php7
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionMasterKeyUploadTest.php10
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionUploadTest.php10
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/ExceptionPlugin.php5
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/PartFileInRootUploadTest.php10
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/RequestTestCase.php48
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/Sapi.php11
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/UploadTest.php120
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php65
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php167
-rw-r--r--apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php52
-rw-r--r--apps/dav/tests/unit/Controller/DirectControllerTest.php33
-rw-r--r--apps/dav/tests/unit/Controller/InvitationResponseControllerTest.php50
-rw-r--r--apps/dav/tests/unit/Controller/UpcomingEventsControllerTest.php73
-rw-r--r--apps/dav/tests/unit/DAV/AnonymousOptionsTest.php6
-rw-r--r--apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php22
-rw-r--r--apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php136
-rw-r--r--apps/dav/tests/unit/DAV/GroupPrincipalTest.php50
-rw-r--r--apps/dav/tests/unit/DAV/HookManagerTest.php222
-rw-r--r--apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php183
-rw-r--r--apps/dav/tests/unit/DAV/Sharing/BackendTest.php38
-rw-r--r--apps/dav/tests/unit/DAV/Sharing/PluginTest.php22
-rw-r--r--apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php58
-rw-r--r--apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php54
-rw-r--r--apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php73
-rw-r--r--apps/dav/tests/unit/Direct/DirectFileTest.php27
-rw-r--r--apps/dav/tests/unit/Direct/DirectHomeTest.php33
-rw-r--r--apps/dav/tests/unit/Files/FileSearchBackendTest.php90
-rw-r--r--apps/dav/tests/unit/Files/MultipartRequestParserTest.php147
-rw-r--r--apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php226
-rw-r--r--apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php22
-rw-r--r--apps/dav/tests/unit/Listener/CalendarContactInteractionListenerTest.php28
-rw-r--r--apps/dav/tests/unit/Listener/OutOfOfficeListenerTest.php28
-rw-r--r--apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php50
-rw-r--r--apps/dav/tests/unit/Migration/CreateSystemAddressBookStepTest.php47
-rw-r--r--apps/dav/tests/unit/Migration/RefreshWebcalJobRegistrarTest.php52
-rw-r--r--apps/dav/tests/unit/Migration/RegenerateBirthdayCalendarsTest.php15
-rw-r--r--apps/dav/tests/unit/Migration/RemoveDeletedUsersCalendarSubscriptionsTest.php58
-rw-r--r--apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningNodeTest.php13
-rw-r--r--apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningPluginTest.php74
-rw-r--r--apps/dav/tests/unit/Search/ContactsSearchProviderTest.php68
-rw-r--r--apps/dav/tests/unit/Search/EventsSearchProviderTest.php390
-rw-r--r--apps/dav/tests/unit/Search/TasksSearchProviderTest.php175
-rw-r--r--apps/dav/tests/unit/ServerTest.php9
-rw-r--r--apps/dav/tests/unit/Service/AbsenceServiceTest.php39
-rw-r--r--apps/dav/tests/unit/Service/ExampleContactServiceTest.php194
-rw-r--r--apps/dav/tests/unit/Service/ExampleEventServiceTest.php196
-rw-r--r--apps/dav/tests/unit/Service/UpcomingEventsServiceTest.php89
-rw-r--r--apps/dav/tests/unit/Settings/CalDAVSettingsTest.php70
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php40
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagNodeTest.php133
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php218
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php86
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php57
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php54
-rw-r--r--apps/dav/tests/unit/Upload/AssemblyStreamTest.php104
-rw-r--r--apps/dav/tests/unit/Upload/ChunkingPluginTest.php109
-rw-r--r--apps/dav/tests/unit/Upload/FutureFileTest.php19
-rw-r--r--apps/dav/tests/unit/Upload/UploadAutoMkcolPluginTest.php133
-rw-r--r--apps/dav/tests/unit/bootstrap.php15
-rw-r--r--apps/dav/tests/unit/phpunit.xml1
-rw-r--r--apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-1.ics17
-rw-r--r--apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-2.ics17
-rw-r--r--apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-3.ics17
-rw-r--r--apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-4.ics17
-rw-r--r--apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-5.ics14
-rw-r--r--apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-6.ics15
-rw-r--r--apps/dav/tests/unit/test_fixtures/caldav-search-missing-start-1.ics14
-rw-r--r--apps/dav/tests/unit/test_fixtures/caldav-search-missing-start-2.ics14
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics20
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics.license2
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event-expected.ics18
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event-expected.ics.license2
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics21
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics.license2
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event.ics18
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event.ics.license2
202 files changed, 12008 insertions, 6860 deletions
diff --git a/apps/dav/tests/unit/AppInfo/ApplicationTest.php b/apps/dav/tests/unit/AppInfo/ApplicationTest.php
index f8ddd9bb821..336f487e0b8 100644
--- a/apps/dav/tests/unit/AppInfo/ApplicationTest.php
+++ b/apps/dav/tests/unit/AppInfo/ApplicationTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
diff --git a/apps/dav/tests/unit/AppInfo/PluginManagerTest.php b/apps/dav/tests/unit/AppInfo/PluginManagerTest.php
index 8211cdfc02c..0082aa45286 100644
--- a/apps/dav/tests/unit/AppInfo/PluginManagerTest.php
+++ b/apps/dav/tests/unit/AppInfo/PluginManagerTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 ownCloud GmbH.
* SPDX-License-Identifier: AGPL-3.0-only
@@ -24,7 +26,7 @@ class PluginManagerTest extends TestCase {
$server = $this->createMock(ServerContainer::class);
$appManager = $this->createMock(AppManager::class);
- $appManager->method('getInstalledApps')
+ $appManager->method('getEnabledApps')
->willReturn(['adavapp', 'adavapp2']);
$appInfo1 = [
diff --git a/apps/dav/tests/unit/Avatars/AvatarHomeTest.php b/apps/dav/tests/unit/Avatars/AvatarHomeTest.php
index 9699c146c8a..7117637a000 100644
--- a/apps/dav/tests/unit/Avatars/AvatarHomeTest.php
+++ b/apps/dav/tests/unit/Avatars/AvatarHomeTest.php
@@ -1,27 +1,25 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2017 ownCloud GmbH
* SPDX-License-Identifier: AGPL-3.0-only
*/
-namespace OCA\DAV\Tests\Unit\Avatars;
+namespace OCA\DAV\Tests\unit\Avatars;
use OCA\DAV\Avatars\AvatarHome;
use OCA\DAV\Avatars\AvatarNode;
use OCP\IAvatar;
use OCP\IAvatarManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\MethodNotAllowed;
use Sabre\DAV\Exception\NotFound;
use Test\TestCase;
class AvatarHomeTest extends TestCase {
-
- /** @var AvatarHome */
- private $home;
-
- /** @var IAvatarManager | \PHPUnit\Framework\MockObject\MockObject */
- private $avatarManager;
+ private AvatarHome $home;
+ private IAvatarManager&MockObject $avatarManager;
protected function setUp(): void {
parent::setUp();
@@ -29,16 +27,14 @@ class AvatarHomeTest extends TestCase {
$this->home = new AvatarHome(['uri' => 'principals/users/admin'], $this->avatarManager);
}
- /**
- * @dataProvider providesForbiddenMethods
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesForbiddenMethods')]
public function testForbiddenMethods($method): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->home->$method('');
}
- public function providesForbiddenMethods() {
+ public static function providesForbiddenMethods(): array {
return [
['createFile'],
['createDirectory'],
@@ -52,7 +48,7 @@ class AvatarHomeTest extends TestCase {
self::assertEquals('admin', $n);
}
- public function providesTestGetChild() {
+ public static function providesTestGetChild(): array {
return [
[MethodNotAllowed::class, false, ''],
[MethodNotAllowed::class, false, 'bla.foo'],
@@ -62,10 +58,8 @@ class AvatarHomeTest extends TestCase {
];
}
- /**
- * @dataProvider providesTestGetChild
- */
- public function testGetChild($expectedException, $hasAvatar, $path): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesTestGetChild')]
+ public function testGetChild(?string $expectedException, bool $hasAvatar, string $path): void {
if ($expectedException !== null) {
$this->expectException($expectedException);
}
@@ -89,10 +83,8 @@ class AvatarHomeTest extends TestCase {
self::assertEquals(1, count($avatarNodes));
}
- /**
- * @dataProvider providesTestGetChild
- */
- public function testChildExists($expectedException, $hasAvatar, $path): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesTestGetChild')]
+ public function testChildExists(?string $expectedException, bool $hasAvatar, string $path): void {
$avatar = $this->createMock(IAvatar::class);
$avatar->method('exists')->willReturn($hasAvatar);
diff --git a/apps/dav/tests/unit/Avatars/AvatarNodeTest.php b/apps/dav/tests/unit/Avatars/AvatarNodeTest.php
index 92c02e17ff8..0ca147a1f3b 100644
--- a/apps/dav/tests/unit/Avatars/AvatarNodeTest.php
+++ b/apps/dav/tests/unit/Avatars/AvatarNodeTest.php
@@ -1,26 +1,28 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2017 ownCloud GmbH
* SPDX-License-Identifier: AGPL-3.0-only
*/
-namespace OCA\DAV\Tests\Unit\Avatars;
+namespace OCA\DAV\Tests\unit\Avatars;
use OCA\DAV\Avatars\AvatarNode;
use OCP\IAvatar;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class AvatarNodeTest extends TestCase {
public function testGetName(): void {
- /** @var IAvatar | \PHPUnit\Framework\MockObject\MockObject $a */
+ /** @var IAvatar&MockObject $a */
$a = $this->createMock(IAvatar::class);
$n = new AvatarNode(1024, 'png', $a);
$this->assertEquals('1024.png', $n->getName());
}
public function testGetContentType(): void {
- /** @var IAvatar | \PHPUnit\Framework\MockObject\MockObject $a */
+ /** @var IAvatar&MockObject $a */
$a = $this->createMock(IAvatar::class);
$n = new AvatarNode(1024, 'png', $a);
$this->assertEquals('image/png', $n->getContentType());
diff --git a/apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php b/apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php
index 85000aba6d3..b2199e3e657 100644
--- a/apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php
@@ -10,19 +10,16 @@ namespace OCA\DAV\Tests\unit\BackgroundJob;
use OCA\DAV\BackgroundJob\CleanupInvitationTokenJob;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\DB\QueryBuilder\IExpressionBuilder;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CleanupInvitationTokenJobTest extends TestCase {
- /** @var IDBConnection | \PHPUnit\Framework\MockObject\MockObject */
- private $dbConnection;
-
- /** @var ITimeFactory | \PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
-
- /** @var \OCA\DAV\BackgroundJob\CleanupInvitationTokenJob */
- private $backgroundJob;
+ private IDBConnection&MockObject $dbConnection;
+ private ITimeFactory&MockObject $timeFactory;
+ private CleanupInvitationTokenJob $backgroundJob;
protected function setUp(): void {
parent::setUp();
@@ -41,7 +38,7 @@ class CleanupInvitationTokenJobTest extends TestCase {
->willReturn(1337);
$queryBuilder = $this->createMock(IQueryBuilder::class);
- $expr = $this->createMock(\OCP\DB\QueryBuilder\IExpressionBuilder::class);
+ $expr = $this->createMock(IExpressionBuilder::class);
$stmt = $this->createMock(\Doctrine\DBAL\Driver\Statement::class);
$this->dbConnection->expects($this->once())
diff --git a/apps/dav/tests/unit/BackgroundJob/CleanupOrphanedChildrenJobTest.php b/apps/dav/tests/unit/BackgroundJob/CleanupOrphanedChildrenJobTest.php
new file mode 100644
index 00000000000..2065b8fe946
--- /dev/null
+++ b/apps/dav/tests/unit/BackgroundJob/CleanupOrphanedChildrenJobTest.php
@@ -0,0 +1,170 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\BackgroundJob;
+
+use OCA\DAV\BackgroundJob\CleanupOrphanedChildrenJob;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\IJobList;
+use OCP\DB\IResult;
+use OCP\DB\QueryBuilder\IExpressionBuilder;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+use Test\TestCase;
+
+class CleanupOrphanedChildrenJobTest extends TestCase {
+ private CleanupOrphanedChildrenJob $job;
+
+ private ITimeFactory&MockObject $timeFactory;
+ private IDBConnection&MockObject $connection;
+ private LoggerInterface&MockObject $logger;
+ private IJobList&MockObject $jobList;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->connection = $this->createMock(IDBConnection::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->jobList = $this->createMock(IJobList::class);
+
+ $this->job = new CleanupOrphanedChildrenJob(
+ $this->timeFactory,
+ $this->connection,
+ $this->logger,
+ $this->jobList,
+ );
+ }
+
+ private function getArgument(): array {
+ return [
+ 'childTable' => 'childTable',
+ 'parentTable' => 'parentTable',
+ 'parentId' => 'parentId',
+ 'logMessage' => 'logMessage',
+ ];
+ }
+
+ private function getMockQueryBuilder(): IQueryBuilder&MockObject {
+ $expr = $this->createMock(IExpressionBuilder::class);
+ $qb = $this->createMock(IQueryBuilder::class);
+ $qb->method('select')
+ ->willReturnSelf();
+ $qb->method('from')
+ ->willReturnSelf();
+ $qb->method('leftJoin')
+ ->willReturnSelf();
+ $qb->method('where')
+ ->willReturnSelf();
+ $qb->method('setMaxResults')
+ ->willReturnSelf();
+ $qb->method('andWhere')
+ ->willReturnSelf();
+ $qb->method('expr')
+ ->willReturn($expr);
+ $qb->method('delete')
+ ->willReturnSelf();
+ return $qb;
+ }
+
+ public function testRunWithoutOrphans(): void {
+ $argument = $this->getArgument();
+ $selectQb = $this->getMockQueryBuilder();
+ $result = $this->createMock(IResult::class);
+
+ $this->connection->expects(self::once())
+ ->method('getQueryBuilder')
+ ->willReturn($selectQb);
+ $selectQb->expects(self::once())
+ ->method('executeQuery')
+ ->willReturn($result);
+ $result->expects(self::once())
+ ->method('fetchAll')
+ ->willReturn([]);
+ $result->expects(self::once())
+ ->method('closeCursor');
+ $this->jobList->expects(self::never())
+ ->method('add');
+
+ self::invokePrivate($this->job, 'run', [$argument]);
+ }
+
+ public function testRunWithPartialBatch(): void {
+ $argument = $this->getArgument();
+ $selectQb = $this->getMockQueryBuilder();
+ $deleteQb = $this->getMockQueryBuilder();
+ $result = $this->createMock(IResult::class);
+
+ $calls = [
+ $selectQb,
+ $deleteQb,
+ ];
+ $this->connection->method('getQueryBuilder')
+ ->willReturnCallback(function () use (&$calls) {
+ return array_shift($calls);
+ });
+ $selectQb->expects(self::once())
+ ->method('executeQuery')
+ ->willReturn($result);
+ $result->expects(self::once())
+ ->method('fetchAll')
+ ->willReturn([
+ ['id' => 42],
+ ['id' => 43],
+ ]);
+ $result->expects(self::once())
+ ->method('closeCursor');
+ $deleteQb->expects(self::once())
+ ->method('delete')
+ ->willReturnSelf();
+ $deleteQb->expects(self::once())
+ ->method('executeStatement');
+ $this->jobList->expects(self::never())
+ ->method('add');
+
+ self::invokePrivate($this->job, 'run', [$argument]);
+ }
+
+ public function testRunWithFullBatch(): void {
+ $argument = $this->getArgument();
+ $selectQb = $this->getMockQueryBuilder();
+ $deleteQb = $this->getMockQueryBuilder();
+ $result = $this->createMock(IResult::class);
+
+ $calls = [
+ $selectQb,
+ $deleteQb,
+ ];
+ $this->connection->method('getQueryBuilder')
+ ->willReturnCallback(function () use (&$calls) {
+ return array_shift($calls);
+ });
+
+ $selectQb->expects(self::once())
+ ->method('executeQuery')
+ ->willReturn($result);
+ $result->expects(self::once())
+ ->method('fetchAll')
+ ->willReturn(array_map(static fn ($i) => ['id' => 42 + $i], range(0, 999)));
+ $result->expects(self::once())
+ ->method('closeCursor');
+ $deleteQb->expects(self::once())
+ ->method('delete')
+ ->willReturnSelf();
+ $deleteQb->expects(self::once())
+ ->method('executeStatement');
+ $this->jobList->expects(self::once())
+ ->method('add')
+ ->with(CleanupOrphanedChildrenJob::class, $argument);
+
+ self::invokePrivate($this->job, 'run', [$argument]);
+ }
+}
diff --git a/apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php b/apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php
index 1173e516a22..a46a1e5e5b0 100644
--- a/apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php
@@ -16,17 +16,10 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class EventReminderJobTest extends TestCase {
- /** @var ITimeFactory|MockObject */
- private $time;
-
- /** @var ReminderService|MockObject */
- private $reminderService;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var EventReminderJob|MockObject */
- private $backgroundJob;
+ private ITimeFactory&MockObject $time;
+ private ReminderService&MockObject $reminderService;
+ private IConfig&MockObject $config;
+ private EventReminderJob $backgroundJob;
protected function setUp(): void {
parent::setUp();
@@ -42,7 +35,7 @@ class EventReminderJobTest extends TestCase {
);
}
- public function data(): array {
+ public static function data(): array {
return [
[true, true, true],
[true, false, false],
@@ -52,23 +45,19 @@ class EventReminderJobTest extends TestCase {
}
/**
- * @dataProvider data
*
* @param bool $sendEventReminders
* @param bool $sendEventRemindersMode
* @param bool $expectCall
*/
+ #[\PHPUnit\Framework\Attributes\DataProvider('data')]
public function testRun(bool $sendEventReminders, bool $sendEventRemindersMode, bool $expectCall): void {
$this->config->expects($this->exactly($sendEventReminders ? 2 : 1))
->method('getAppValue')
- ->withConsecutive(
- ['dav', 'sendEventReminders', 'yes'],
- ['dav', 'sendEventRemindersMode', 'backgroundjob'],
- )
- ->willReturnOnConsecutiveCalls(
- $sendEventReminders ? 'yes' : 'no',
- $sendEventRemindersMode ? 'backgroundjob' : 'cron'
- );
+ ->willReturnMap([
+ ['dav', 'sendEventReminders', 'yes', ($sendEventReminders ? 'yes' : 'no')],
+ ['dav', 'sendEventRemindersMode', 'backgroundjob', ($sendEventRemindersMode ? 'backgroundjob' : 'cron')],
+ ]);
if ($expectCall) {
$this->reminderService->expects($this->once())
diff --git a/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php b/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php
index 4874e79b9a2..88a76ae1332 100644
--- a/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php
@@ -16,18 +16,10 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class GenerateBirthdayCalendarBackgroundJobTest extends TestCase {
-
- /** @var ITimeFactory|MockObject */
- private $time;
-
- /** @var BirthdayService | MockObject */
- private $birthdayService;
-
- /** @var IConfig | MockObject */
- private $config;
-
- /** @var \OCA\DAV\BackgroundJob\GenerateBirthdayCalendarBackgroundJob */
- private $backgroundJob;
+ private ITimeFactory&MockObject $time;
+ private BirthdayService&MockObject $birthdayService;
+ private IConfig&MockObject $config;
+ private GenerateBirthdayCalendarBackgroundJob $backgroundJob;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php b/apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php
index b42334523f8..6135fd00fdc 100644
--- a/apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php
@@ -25,21 +25,11 @@ use Test\TestCase;
class OutOfOfficeEventDispatcherJobTest extends TestCase {
private OutOfOfficeEventDispatcherJob $job;
-
- /** @var MockObject|ITimeFactory */
- private $timeFactory;
-
- /** @var MockObject|AbsenceMapper */
- private $absenceMapper;
-
- /** @var MockObject|LoggerInterface */
- private $logger;
-
- /** @var MockObject|IEventDispatcher */
- private $eventDispatcher;
-
- /** @var MockObject|IUserManager */
- private $userManager;
+ private ITimeFactory&MockObject $timeFactory;
+ private AbsenceMapper&MockObject $absenceMapper;
+ private LoggerInterface&MockObject $logger;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private IUserManager&MockObject $userManager;
private MockObject|TimezoneService $timezoneService;
protected function setUp(): void {
@@ -62,7 +52,7 @@ class OutOfOfficeEventDispatcherJobTest extends TestCase {
);
}
- public function testDispatchStartEvent() {
+ public function testDispatchStartEvent(): void {
$this->timezoneService->method('getUserTimezone')->with('user')->willReturn('Europe/Berlin');
$absence = new Absence();
@@ -94,7 +84,7 @@ class OutOfOfficeEventDispatcherJobTest extends TestCase {
]);
}
- public function testDispatchStopEvent() {
+ public function testDispatchStopEvent(): void {
$this->timezoneService->method('getUserTimezone')->with('user')->willReturn('Europe/Berlin');
$absence = new Absence();
@@ -126,7 +116,7 @@ class OutOfOfficeEventDispatcherJobTest extends TestCase {
]);
}
- public function testDoesntDispatchUnknownEvent() {
+ public function testDoesntDispatchUnknownEvent(): void {
$this->timezoneService->method('getUserTimezone')->with('user')->willReturn('Europe/Berlin');
$absence = new Absence();
diff --git a/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php b/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php
index 9cd75445232..1838fb2537d 100644
--- a/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php
@@ -20,21 +20,11 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class PruneOutdatedSyncTokensJobTest extends TestCase {
- /** @var ITimeFactory | MockObject */
- private $timeFactory;
-
- /** @var CalDavBackend | MockObject */
- private $calDavBackend;
-
- /** @var CardDavBackend | MockObject */
- private $cardDavBackend;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var LoggerInterface|MockObject*/
- private $logger;
-
+ private ITimeFactory&MockObject $timeFactory;
+ private CalDavBackend&MockObject $calDavBackend;
+ private CardDavBackend&MockObject $cardDavBackend;
+ private IConfig&MockObject $config;
+ private LoggerInterface&MockObject $logger;
private PruneOutdatedSyncTokensJob $backgroundJob;
protected function setUp(): void {
@@ -49,9 +39,7 @@ class PruneOutdatedSyncTokensJobTest extends TestCase {
$this->backgroundJob = new PruneOutdatedSyncTokensJob($this->timeFactory, $this->calDavBackend, $this->cardDavBackend, $this->config, $this->logger);
}
- /**
- * @dataProvider dataForTestRun
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataForTestRun')]
public function testRun(string $configToKeep, string $configRetentionDays, int $actualLimit, int $retentionDays, int $deletedCalendarSyncTokens, int $deletedAddressBookSyncTokens): void {
$this->config->expects($this->exactly(2))
->method('getAppValue')
@@ -84,7 +72,7 @@ class PruneOutdatedSyncTokensJobTest extends TestCase {
$this->backgroundJob->run(null);
}
- public function dataForTestRun(): array {
+ public static function dataForTestRun(): array {
return [
['100', '2', 100, 7 * 24 * 3600, 2, 3],
['100', '14', 100, 14 * 24 * 3600, 2, 3],
diff --git a/apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php b/apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php
index f97626a6a73..7713ef2945a 100644
--- a/apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php
@@ -19,20 +19,11 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class RefreshWebcalJobTest extends TestCase {
-
- /** @var RefreshWebcalService | MockObject */
- private $refreshWebcalService;
-
- /** @var IConfig | MockObject */
- private $config;
-
+ private RefreshWebcalService&MockObject $refreshWebcalService;
+ private IConfig&MockObject $config;
private LoggerInterface $logger;
-
- /** @var ITimeFactory | MockObject */
- private $timeFactory;
-
- /** @var IJobList | MockObject */
- private $jobList;
+ private ITimeFactory&MockObject $timeFactory;
+ private IJobList&MockObject $jobList;
protected function setUp(): void {
parent::setUp();
@@ -50,9 +41,8 @@ class RefreshWebcalJobTest extends TestCase {
* @param int $lastRun
* @param int $time
* @param bool $process
- *
- * @dataProvider runDataProvider
*/
+ #[\PHPUnit\Framework\Attributes\DataProvider('runDataProvider')]
public function testRun(int $lastRun, int $time, bool $process): void {
$backgroundJob = new RefreshWebcalJob($this->refreshWebcalService, $this->config, $this->logger, $this->timeFactory);
$backgroundJob->setId(42);
@@ -78,7 +68,7 @@ class RefreshWebcalJobTest extends TestCase {
$this->config->expects($this->once())
->method('getAppValue')
- ->with('dav', 'calendarSubscriptionRefreshRate', 'P1W')
+ ->with('dav', 'calendarSubscriptionRefreshRate', 'P1D')
->willReturn('P1W');
$this->timeFactory->method('getTime')
@@ -97,10 +87,7 @@ class RefreshWebcalJobTest extends TestCase {
$backgroundJob->start($this->jobList);
}
- /**
- * @return array
- */
- public function runDataProvider():array {
+ public static function runDataProvider():array {
return [
[0, 100000, true],
[100000, 100000, false]
diff --git a/apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php b/apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php
index 88493d91d9b..6c9214d0268 100644
--- a/apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php
@@ -14,20 +14,14 @@ use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJobList;
use OCP\IUser;
use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class RegisterRegenerateBirthdayCalendarsTest extends TestCase {
- /** @var ITimeFactory | \PHPUnit\Framework\MockObject\MockObject */
- private $time;
-
- /** @var IUserManager | \PHPUnit\Framework\MockObject\MockObject */
- private $userManager;
-
- /** @var IJobList | \PHPUnit\Framework\MockObject\MockObject */
- private $jobList;
-
- /** @var RegisterRegenerateBirthdayCalendars */
- private $backgroundJob;
+ private ITimeFactory&MockObject $time;
+ private IUserManager&MockObject $userManager;
+ private IJobList&MockObject $jobList;
+ private RegisterRegenerateBirthdayCalendars $backgroundJob;
protected function setUp(): void {
parent::setUp();
@@ -59,22 +53,26 @@ class RegisterRegenerateBirthdayCalendarsTest extends TestCase {
$closure($user3);
});
+ $calls = [
+ 'uid1',
+ 'uid2',
+ 'uid3',
+ ];
$this->jobList->expects($this->exactly(3))
->method('add')
- ->withConsecutive(
- [GenerateBirthdayCalendarBackgroundJob::class, [
- 'userId' => 'uid1',
- 'purgeBeforeGenerating' => true
- ]],
- [GenerateBirthdayCalendarBackgroundJob::class, [
- 'userId' => 'uid2',
- 'purgeBeforeGenerating' => true
- ]],
- [GenerateBirthdayCalendarBackgroundJob::class, [
- 'userId' => 'uid3',
- 'purgeBeforeGenerating' => true
- ]],
- );
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals(
+ [
+ GenerateBirthdayCalendarBackgroundJob::class,
+ [
+ 'userId' => $expected,
+ 'purgeBeforeGenerating' => true
+ ]
+ ],
+ func_get_args()
+ );
+ });
$this->backgroundJob->run([]);
}
diff --git a/apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php b/apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php
index 7e81616a3e2..38a981787cd 100644
--- a/apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php
@@ -10,36 +10,17 @@ namespace OCA\DAV\Tests\unit\BackgroundJob;
use OCA\DAV\BackgroundJob\UpdateCalendarResourcesRoomsBackgroundJob;
-use OCA\DAV\CalDAV\CalDavBackend;
use OCP\AppFramework\Utility\ITimeFactory;
-use OCP\Calendar\BackendTemporarilyUnavailableException;
-use OCP\Calendar\IMetadataProvider;
-use OCP\Calendar\Resource\IBackend;
use OCP\Calendar\Resource\IManager as IResourceManager;
-use OCP\Calendar\Resource\IResource;
use OCP\Calendar\Room\IManager as IRoomManager;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
-interface tmpI extends IResource, IMetadataProvider {
-}
-
class UpdateCalendarResourcesRoomsBackgroundJobTest extends TestCase {
-
- /** @var ITimeFactory|MockObject */
- private $time;
-
- /** @var IResourceManager|MockObject */
- private $resourceManager;
-
- /** @var IRoomManager|MockObject */
- private $roomManager;
-
- /** @var CalDavBackend|MockObject */
- private $calDavBackend;
-
- /** @var UpdateCalendarResourcesRoomsBackgroundJob */
- private $backgroundJob;
+ private UpdateCalendarResourcesRoomsBackgroundJob $backgroundJob;
+ private ITimeFactory&MockObject $time;
+ private IResourceManager&MockObject $resourceManager;
+ private IRoomManager&MockObject $roomManager;
protected function setUp(): void {
parent::setUp();
@@ -47,390 +28,20 @@ class UpdateCalendarResourcesRoomsBackgroundJobTest extends TestCase {
$this->time = $this->createMock(ITimeFactory::class);
$this->resourceManager = $this->createMock(IResourceManager::class);
$this->roomManager = $this->createMock(IRoomManager::class);
- $this->calDavBackend = $this->createMock(CalDavBackend::class);
$this->backgroundJob = new UpdateCalendarResourcesRoomsBackgroundJob(
$this->time,
$this->resourceManager,
$this->roomManager,
- self::$realDatabase,
- $this->calDavBackend
);
}
- protected function tearDown(): void {
- $query = self::$realDatabase->getQueryBuilder();
- $query->delete('calendar_resources')->execute();
- $query->delete('calendar_resources_md')->execute();
- $query->delete('calendar_rooms')->execute();
- $query->delete('calendar_rooms_md')->execute();
- }
-
- /**
- * Data in Cache:
- * resources:
- * [backend1, res1, Beamer1, {}] - []
- * [backend1, res2, TV1, {}] - []
- * [backend2, res3, Beamer2, {}] - ['meta1' => 'value1', 'meta2' => 'value2']
- * [backend2, res4, TV2, {}] - ['meta1' => 'value1', 'meta3' => 'value3-old']
- * [backend3, res5, Beamer3, {}] - []
- * [backend3, res6, Pointer, {foo, bar}] - ['meta99' => 'value99']
- *
- * Data in Backend:
- * backend1 gone
- * backend2 throws BackendTemporarilyUnavailableException
- * [backend3, res6, Pointer123, {foo, biz}] - ['meta99' => 'value99-new', 'meta123' => 'meta456']
- * [backend3, res7, Resource4, {biz}] - ['meta1' => 'value1']
- * [backend4, res8, Beamer, {}] - ['meta2' => 'value2']
- * [backend4, res9, Beamer2, {}] - []
- *
- * Expected after run:
- * [backend1, res1, Beamer1, {}] - []
- * [backend1, res2, TV1, {}] - []
- * [backend2, res3, Beamer2, {}] - ['meta1' => 'value1', 'meta2' => 'value2']
- * [backend2, res4, TV2, {}] - ['meta1' => 'value1', 'meta3' => 'value3-old']
- * [backend3, res6, Pointer123, {foo, biz}] - ['meta99' => 'value99-new', 'meta123' => 'meta456']
- * [backend3, res7, Resource4, {biz}] - ['meta1' => 'value1']
- * [backend4, res8, Beamer, {}] - ['meta2' => 'value2']
- * [backend4, res9, Beamer2, {}] - []
- */
-
public function testRun(): void {
- $this->createTestResourcesInCache();
-
- $backend2 = $this->createMock(IBackend::class);
- $backend3 = $this->createMock(IBackend::class);
- $backend4 = $this->createMock(IBackend::class);
-
- $res6 = $this->createMock(tmpI::class);
- $res7 = $this->createMock(tmpI::class);
- $res8 = $this->createMock(tmpI::class);
- $res9 = $this->createMock(IResource::class);
-
- $backend2->method('getBackendIdentifier')
- ->willReturn('backend2');
- $backend2->method('listAllResources')
- ->will($this->throwException(new BackendTemporarilyUnavailableException()));
- $backend2->method('getResource')
- ->will($this->throwException(new BackendTemporarilyUnavailableException()));
- $backend2->method('getAllResources')
- ->will($this->throwException(new BackendTemporarilyUnavailableException()));
- $backend3->method('getBackendIdentifier')
- ->willReturn('backend3');
- $backend3->method('listAllResources')
- ->willReturn(['res6', 'res7']);
- $backend3->method('getResource')
- ->willReturnMap([
- ['res6', $res6],
- ['res7', $res7],
- ]);
- $backend4->method('getBackendIdentifier')
- ->willReturn('backend4');
- $backend4->method('listAllResources')
- ->willReturn(['res8', 'res9']);
- $backend4->method('getResource')
- ->willReturnMap([
- ['res8', $res8],
- ['res9', $res9],
- ]);
-
- $res6->method('getId')->willReturn('res6');
- $res6->method('getDisplayName')->willReturn('Pointer123');
- $res6->method('getGroupRestrictions')->willReturn(['foo', 'biz']);
- $res6->method('getEMail')->willReturn('res6@foo.bar');
- $res6->method('getBackend')->willReturn($backend3);
-
- $res6->method('getAllAvailableMetadataKeys')->willReturn(['meta99', 'meta123']);
- $res6->method('getMetadataForKey')->willReturnCallback(function ($key) {
- switch ($key) {
- case 'meta99':
- return 'value99-new';
-
- case 'meta123':
- return 'meta456';
-
- default:
- return null;
- }
- });
-
- $res7->method('getId')->willReturn('res7');
- $res7->method('getDisplayName')->willReturn('Resource4');
- $res7->method('getGroupRestrictions')->willReturn(['biz']);
- $res7->method('getEMail')->willReturn('res7@foo.bar');
- $res7->method('getBackend')->willReturn($backend3);
- $res7->method('getAllAvailableMetadataKeys')->willReturn(['meta1']);
- $res7->method('getMetadataForKey')->willReturnCallback(function ($key) {
- switch ($key) {
- case 'meta1':
- return 'value1';
-
- default:
- return null;
- }
- });
-
- $res8->method('getId')->willReturn('res8');
- $res8->method('getDisplayName')->willReturn('Beamer');
- $res8->method('getGroupRestrictions')->willReturn([]);
- $res8->method('getEMail')->willReturn('res8@foo.bar');
- $res8->method('getBackend')->willReturn($backend4);
- $res8->method('getAllAvailableMetadataKeys')->willReturn(['meta2']);
- $res8->method('getMetadataForKey')->willReturnCallback(function ($key) {
- switch ($key) {
- case 'meta2':
- return 'value2';
-
- default:
- return null;
- }
- });
-
- $res9->method('getId')->willReturn('res9');
- $res9->method('getDisplayName')->willReturn('Beamer2');
- $res9->method('getGroupRestrictions')->willReturn([]);
- $res9->method('getEMail')->willReturn('res9@foo.bar');
- $res9->method('getBackend')->willReturn($backend4);
-
- $this->resourceManager
- ->method('getBackends')
- ->willReturn([
- $backend2, $backend3, $backend4
- ]);
- $this->resourceManager
- ->method('getBackend')
- ->willReturnMap([
- ['backend2', $backend2],
- ['backend3', $backend3],
- ['backend4', $backend4],
- ]);
+ $this->resourceManager->expects(self::once())
+ ->method('update');
+ $this->roomManager->expects(self::once())
+ ->method('update');
$this->backgroundJob->run([]);
-
- $query = self::$realDatabase->getQueryBuilder();
- $query->select('*')->from('calendar_resources');
-
- $rows = [];
- $ids = [];
- $stmt = $query->execute();
- while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
- $ids[$row['backend_id'] . '::' . $row['resource_id']] = $row['id'];
- unset($row['id']);
- $rows[] = $row;
- }
-
- $this->assertEquals([
- [
- 'backend_id' => 'backend1',
- 'resource_id' => 'res1',
- 'displayname' => 'Beamer1',
- 'email' => 'res1@foo.bar',
- 'group_restrictions' => '[]',
- ],
- [
- 'backend_id' => 'backend1',
- 'resource_id' => 'res2',
- 'displayname' => 'TV1',
- 'email' => 'res2@foo.bar',
- 'group_restrictions' => '[]',
- ],
- [
- 'backend_id' => 'backend2',
- 'resource_id' => 'res3',
- 'displayname' => 'Beamer2',
- 'email' => 'res3@foo.bar',
- 'group_restrictions' => '[]',
- ],
- [
- 'backend_id' => 'backend2',
- 'resource_id' => 'res4',
- 'displayname' => 'TV2',
- 'email' => 'res4@foo.bar',
- 'group_restrictions' => '[]',
- ],
- [
- 'backend_id' => 'backend3',
- 'resource_id' => 'res6',
- 'displayname' => 'Pointer123',
- 'email' => 'res6@foo.bar',
- 'group_restrictions' => '["foo","biz"]',
- ],
- [
- 'backend_id' => 'backend3',
- 'resource_id' => 'res7',
- 'displayname' => 'Resource4',
- 'email' => 'res7@foo.bar',
- 'group_restrictions' => '["biz"]',
- ],
- [
- 'backend_id' => 'backend4',
- 'resource_id' => 'res8',
- 'displayname' => 'Beamer',
- 'email' => 'res8@foo.bar',
- 'group_restrictions' => '[]',
- ],
- [
- 'backend_id' => 'backend4',
- 'resource_id' => 'res9',
- 'displayname' => 'Beamer2',
- 'email' => 'res9@foo.bar',
- 'group_restrictions' => '[]',
- ],
- ], $rows);
-
- $query2 = self::$realDatabase->getQueryBuilder();
- $query2->select('*')->from('calendar_resources_md');
-
- $rows2 = [];
- $stmt = $query2->execute();
- while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
- unset($row['id']);
- $rows2[] = $row;
- }
-
- $this->assertEquals([
- [
- 'resource_id' => $ids['backend2::res3'],
- 'key' => 'meta1',
- 'value' => 'value1',
- ],
- [
- 'resource_id' => $ids['backend2::res3'],
- 'key' => 'meta2',
- 'value' => 'value2',
- ],
- [
- 'resource_id' => $ids['backend2::res4'],
- 'key' => 'meta1',
- 'value' => 'value1',
- ],
- [
- 'resource_id' => $ids['backend2::res4'],
- 'key' => 'meta3',
- 'value' => 'value3-old',
- ],
- [
- 'resource_id' => $ids['backend3::res6'],
- 'key' => 'meta99',
- 'value' => 'value99-new',
- ],
- [
- 'resource_id' => $ids['backend3::res7'],
- 'key' => 'meta1',
- 'value' => 'value1',
- ],
- [
- 'resource_id' => $ids['backend3::res6'],
- 'key' => 'meta123',
- 'value' => 'meta456',
- ],
- [
- 'resource_id' => $ids['backend4::res8'],
- 'key' => 'meta2',
- 'value' => 'value2',
- ]
- ], $rows2);
- }
-
- protected function createTestResourcesInCache() {
- $query = self::$realDatabase->getQueryBuilder();
- $query->insert('calendar_resources')
- ->values([
- 'backend_id' => $query->createNamedParameter('backend1'),
- 'resource_id' => $query->createNamedParameter('res1'),
- 'email' => $query->createNamedParameter('res1@foo.bar'),
- 'displayname' => $query->createNamedParameter('Beamer1'),
- 'group_restrictions' => $query->createNamedParameter('[]'),
- ])
- ->execute();
-
- $query->insert('calendar_resources')
- ->values([
- 'backend_id' => $query->createNamedParameter('backend1'),
- 'resource_id' => $query->createNamedParameter('res2'),
- 'email' => $query->createNamedParameter('res2@foo.bar'),
- 'displayname' => $query->createNamedParameter('TV1'),
- 'group_restrictions' => $query->createNamedParameter('[]'),
- ])
- ->execute();
-
- $query->insert('calendar_resources')
- ->values([
- 'backend_id' => $query->createNamedParameter('backend2'),
- 'resource_id' => $query->createNamedParameter('res3'),
- 'email' => $query->createNamedParameter('res3@foo.bar'),
- 'displayname' => $query->createNamedParameter('Beamer2'),
- 'group_restrictions' => $query->createNamedParameter('[]'),
- ])
- ->execute();
- $id3 = $query->getLastInsertId();
-
- $query->insert('calendar_resources')
- ->values([
- 'backend_id' => $query->createNamedParameter('backend2'),
- 'resource_id' => $query->createNamedParameter('res4'),
- 'email' => $query->createNamedParameter('res4@foo.bar'),
- 'displayname' => $query->createNamedParameter('TV2'),
- 'group_restrictions' => $query->createNamedParameter('[]'),
- ])
- ->execute();
- $id4 = $query->getLastInsertId();
-
- $query->insert('calendar_resources')
- ->values([
- 'backend_id' => $query->createNamedParameter('backend3'),
- 'resource_id' => $query->createNamedParameter('res5'),
- 'email' => $query->createNamedParameter('res5@foo.bar'),
- 'displayname' => $query->createNamedParameter('Beamer3'),
- 'group_restrictions' => $query->createNamedParameter('[]'),
- ])
- ->execute();
-
- $query->insert('calendar_resources')
- ->values([
- 'backend_id' => $query->createNamedParameter('backend3'),
- 'resource_id' => $query->createNamedParameter('res6'),
- 'email' => $query->createNamedParameter('res6@foo.bar'),
- 'displayname' => $query->createNamedParameter('Pointer'),
- 'group_restrictions' => $query->createNamedParameter('["foo", "bar"]'),
- ])
- ->execute();
- $id6 = $query->getLastInsertId();
-
- $query->insert('calendar_resources_md')
- ->values([
- 'resource_id' => $query->createNamedParameter($id3),
- 'key' => $query->createNamedParameter('meta1'),
- 'value' => $query->createNamedParameter('value1')
- ])
- ->execute();
- $query->insert('calendar_resources_md')
- ->values([
- 'resource_id' => $query->createNamedParameter($id3),
- 'key' => $query->createNamedParameter('meta2'),
- 'value' => $query->createNamedParameter('value2')
- ])
- ->execute();
- $query->insert('calendar_resources_md')
- ->values([
- 'resource_id' => $query->createNamedParameter($id4),
- 'key' => $query->createNamedParameter('meta1'),
- 'value' => $query->createNamedParameter('value1')
- ])
- ->execute();
- $query->insert('calendar_resources_md')
- ->values([
- 'resource_id' => $query->createNamedParameter($id4),
- 'key' => $query->createNamedParameter('meta3'),
- 'value' => $query->createNamedParameter('value3-old')
- ])
- ->execute();
- $query->insert('calendar_resources_md')
- ->values([
- 'resource_id' => $query->createNamedParameter($id6),
- 'key' => $query->createNamedParameter('meta99'),
- 'value' => $query->createNamedParameter('value99')
- ])
- ->execute();
}
}
diff --git a/apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php b/apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php
index fb3f9255f1a..d49d20180d9 100644
--- a/apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php
@@ -14,8 +14,10 @@ use OCA\DAV\BackgroundJob\UserStatusAutomation;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
+use OCP\IDBConnection;
use OCP\IUser;
use OCP\IUserManager;
+use OCP\Server;
use OCP\User\IAvailabilityCoordinator;
use OCP\UserStatus\IManager;
use OCP\UserStatus\IUserStatus;
@@ -27,14 +29,13 @@ use Test\TestCase;
* @group DB
*/
class UserStatusAutomationTest extends TestCase {
-
- protected MockObject|ITimeFactory $time;
- protected MockObject|IJobList $jobList;
- protected MockObject|LoggerInterface $logger;
- protected MockObject|IManager $statusManager;
- protected MockObject|IConfig $config;
- private IAvailabilityCoordinator|MockObject $coordinator;
- private IUserManager|MockObject $userManager;
+ protected ITimeFactory&MockObject $time;
+ protected IJobList&MockObject $jobList;
+ protected LoggerInterface&MockObject $logger;
+ protected IManager&MockObject $statusManager;
+ protected IConfig&MockObject $config;
+ private IAvailabilityCoordinator&MockObject $coordinator;
+ private IUserManager&MockObject $userManager;
protected function setUp(): void {
parent::setUp();
@@ -53,7 +54,7 @@ class UserStatusAutomationTest extends TestCase {
if (empty($methods)) {
return new UserStatusAutomation(
$this->time,
- \OC::$server->getDatabaseConnection(),
+ Server::get(IDBConnection::class),
$this->jobList,
$this->logger,
$this->statusManager,
@@ -66,7 +67,7 @@ class UserStatusAutomationTest extends TestCase {
return $this->getMockBuilder(UserStatusAutomation::class)
->setConstructorArgs([
$this->time,
- \OC::$server->getDatabaseConnection(),
+ Server::get(IDBConnection::class),
$this->jobList,
$this->logger,
$this->statusManager,
@@ -74,11 +75,11 @@ class UserStatusAutomationTest extends TestCase {
$this->coordinator,
$this->userManager,
])
- ->setMethods($methods)
+ ->onlyMethods($methods)
->getMock();
}
- public function dataRun(): array {
+ public static function dataRun(): array {
return [
['20230217', '2023-02-24 10:49:36.613834', true],
['20230224', '2023-02-24 10:49:36.613834', true],
@@ -87,9 +88,7 @@ class UserStatusAutomationTest extends TestCase {
];
}
- /**
- * @dataProvider dataRun
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataRun')]
public function testRunNoOOO(string $ruleDay, string $currentTime, bool $isAvailable): void {
$user = $this->createConfiguredMock(IUser::class, [
'getUID' => 'user'
@@ -108,8 +107,6 @@ class UserStatusAutomationTest extends TestCase {
->willReturn(new \DateTime($currentTime, new \DateTimeZone('UTC')));
$this->logger->expects(self::exactly(4))
->method('debug');
- $this->statusManager->expects(self::exactly(2))
- ->method('revertUserStatus');
if (!$isAvailable) {
$this->statusManager->expects(self::once())
->method('setUserStatus')
@@ -172,8 +169,6 @@ END:VCALENDAR');
->willReturn('yes');
$this->time->method('getDateTime')
->willReturn(new \DateTime('2023-02-24 13:58:24.479357', new \DateTimeZone('UTC')));
- $this->statusManager->expects($this->exactly(3))
- ->method('revertUserStatus');
$this->jobList->expects($this->once())
->method('remove')
->with(UserStatusAutomation::class, ['userId' => 'user']);
@@ -207,8 +202,6 @@ END:VCALENDAR');
$this->coordinator->expects(self::once())
->method('isInEffect')
->willReturn(true);
- $this->statusManager->expects($this->exactly(2))
- ->method('revertUserStatus');
$this->statusManager->expects(self::once())
->method('setUserStatus')
->with('user', IUserStatus::MESSAGE_OUT_OF_OFFICE, IUserStatus::DND, true, $ooo->getShortMessage());
diff --git a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
index de0684d1320..45937d86873 100644
--- a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
+++ b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
@@ -25,6 +25,7 @@ use OCP\IUserManager;
use OCP\IUserSession;
use OCP\L10N\IFactory;
use OCP\Security\ISecureRandom;
+use OCP\Server;
use OCP\Share\IManager as ShareManager;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
@@ -43,12 +44,12 @@ abstract class AbstractCalDavBackend extends TestCase {
protected CalDavBackend $backend;
- protected Principal|MockObject $principal;
- protected IUserManager|MockObject $userManager;
- protected IGroupManager|MockObject $groupManager;
- protected IEventDispatcher|MockObject $dispatcher;
- private LoggerInterface|MockObject $logger;
- private IConfig|MockObject $config;
+ protected Principal&MockObject $principal;
+ protected IUserManager&MockObject $userManager;
+ protected IGroupManager&MockObject $groupManager;
+ protected IEventDispatcher&MockObject $dispatcher;
+ private LoggerInterface&MockObject $logger;
+ private IConfig&MockObject $config;
private ISecureRandom $random;
protected SharingBackend $sharingBackend;
protected IDBConnection $db;
@@ -76,7 +77,7 @@ abstract class AbstractCalDavBackend extends TestCase {
$this->createMock(IConfig::class),
$this->createMock(IFactory::class)
])
- ->setMethods(['getPrincipalByPath', 'getGroupMembership', 'findByUri'])
+ ->onlyMethods(['getPrincipalByPath', 'getGroupMembership', 'findByUri'])
->getMock();
$this->principal->expects($this->any())->method('getPrincipalByPath')
->willReturn([
@@ -87,8 +88,8 @@ abstract class AbstractCalDavBackend extends TestCase {
->withAnyParameters()
->willReturn([self::UNIT_TEST_GROUP, self::UNIT_TEST_GROUP2]);
- $this->db = \OC::$server->getDatabaseConnection();
- $this->random = \OC::$server->getSecureRandom();
+ $this->db = Server::get(IDBConnection::class);
+ $this->random = Server::get(ISecureRandom::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->config = $this->createMock(IConfig::class);
$this->sharingBackend = new SharingBackend(
@@ -142,7 +143,7 @@ abstract class AbstractCalDavBackend extends TestCase {
}
}
- protected function createTestCalendar() {
+ protected function createTestCalendar(): int {
$this->dispatcher->expects(self::any())
->method('dispatchTyped');
@@ -154,14 +155,12 @@ abstract class AbstractCalDavBackend extends TestCase {
$this->assertEquals(self::UNIT_TEST_USER, $calendars[0]['principaluri']);
/** @var SupportedCalendarComponentSet $components */
$components = $calendars[0]['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set'];
- $this->assertEquals(['VEVENT','VTODO'], $components->getValue());
+ $this->assertEquals(['VEVENT','VTODO','VJOURNAL'], $components->getValue());
$color = $calendars[0]['{http://apple.com/ns/ical/}calendar-color'];
$this->assertEquals('#1C4587FF', $color);
$this->assertEquals('Example', $calendars[0]['uri']);
$this->assertEquals('Example', $calendars[0]['{DAV:}displayname']);
- $calendarId = $calendars[0]['id'];
-
- return $calendarId;
+ return (int)$calendars[0]['id'];
}
protected function createTestSubscription() {
@@ -207,6 +206,33 @@ EOD;
return $uri0;
}
+ protected function modifyEvent($calendarId, $objectId, $start = '20130912T130000Z', $end = '20130912T140000Z') {
+ $randomPart = self::getUniqueID();
+
+ $calData = <<<EOD
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:ownCloud Calendar
+BEGIN:VEVENT
+CREATED;VALUE=DATE-TIME:20130910T125139Z
+UID:47d15e3ec8-$randomPart
+LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
+DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
+SUMMARY:Test Event
+DTSTART;VALUE=DATE-TIME:$start
+DTEND;VALUE=DATE-TIME:$end
+CLASS:PUBLIC
+END:VEVENT
+END:VCALENDAR
+EOD;
+
+ $this->backend->updateCalendarObject($calendarId, $objectId, $calData);
+ }
+
+ protected function deleteEvent($calendarId, $objectId) {
+ $this->backend->deleteCalendarObject($calendarId, $objectId);
+ }
+
protected function assertAcl($principal, $privilege, $acl) {
foreach ($acl as $a) {
if ($a['principal'] === $principal && $a['privilege'] === $privilege) {
diff --git a/apps/dav/tests/unit/CalDAV/Activity/BackendTest.php b/apps/dav/tests/unit/CalDAV/Activity/BackendTest.php
index 6ace633b072..4848a01f6b9 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/BackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/BackendTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -19,21 +21,11 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class BackendTest extends TestCase {
-
- /** @var IManager|MockObject */
- protected $activityManager;
-
- /** @var IGroupManager|MockObject */
- protected $groupManager;
-
- /** @var IUserSession|MockObject */
- protected $userSession;
-
- /** @var IAppManager|MockObject */
- protected $appManager;
-
- /** @var IUserManager|MockObject */
- protected $userManager;
+ protected IManager&MockObject $activityManager;
+ protected IGroupManager&MockObject $groupManager;
+ protected IUserSession&MockObject $userSession;
+ protected IAppManager&MockObject $appManager;
+ protected IUserManager&MockObject $userManager;
protected function setUp(): void {
parent::setUp();
@@ -45,10 +37,9 @@ class BackendTest extends TestCase {
}
/**
- * @param array $methods
- * @return Backend|MockObject
+ * @return Backend|(Backend&MockObject)
*/
- protected function getBackend(array $methods = []) {
+ protected function getBackend(array $methods = []): Backend {
if (empty($methods)) {
return new Backend(
$this->activityManager,
@@ -71,7 +62,7 @@ class BackendTest extends TestCase {
}
}
- public function dataCallTriggerCalendarActivity() {
+ public static function dataCallTriggerCalendarActivity(): array {
return [
['onCalendarAdd', [['data']], Calendar::SUBJECT_ADD, [['data'], [], []]],
['onCalendarUpdate', [['data'], ['shares'], ['changed-properties']], Calendar::SUBJECT_UPDATE, [['data'], ['shares'], ['changed-properties']]],
@@ -80,15 +71,8 @@ class BackendTest extends TestCase {
];
}
- /**
- * @dataProvider dataCallTriggerCalendarActivity
- *
- * @param string $method
- * @param array $payload
- * @param string $expectedSubject
- * @param array $expectedPayload
- */
- public function testCallTriggerCalendarActivity($method, array $payload, $expectedSubject, array $expectedPayload): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataCallTriggerCalendarActivity')]
+ public function testCallTriggerCalendarActivity(string $method, array $payload, string $expectedSubject, array $expectedPayload): void {
$backend = $this->getBackend(['triggerCalendarActivity']);
$backend->expects($this->once())
->method('triggerCalendarActivity')
@@ -101,7 +85,7 @@ class BackendTest extends TestCase {
call_user_func_array([$backend, $method], $payload);
}
- public function dataTriggerCalendarActivity() {
+ public static function dataTriggerCalendarActivity(): array {
return [
// Add calendar
[Calendar::SUBJECT_ADD, [], [], [], '', '', null, []],
@@ -182,18 +166,8 @@ class BackendTest extends TestCase {
];
}
- /**
- * @dataProvider dataTriggerCalendarActivity
- * @param string $action
- * @param array $data
- * @param array $shares
- * @param array $changedProperties
- * @param string $currentUser
- * @param string $author
- * @param string[]|null $shareUsers
- * @param string[] $users
- */
- public function testTriggerCalendarActivity($action, array $data, array $shares, array $changedProperties, $currentUser, $author, $shareUsers, array $users): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTriggerCalendarActivity')]
+ public function testTriggerCalendarActivity(string $action, array $data, array $shares, array $changedProperties, string $currentUser, string $author, ?array $shareUsers, array $users): void {
$backend = $this->getBackend(['getUsersForShares']);
if ($shareUsers === null) {
@@ -278,7 +252,7 @@ class BackendTest extends TestCase {
], [], []]);
}
- public function dataGetUsersForShares() {
+ public static function dataGetUsersForShares(): array {
return [
[
[],
@@ -321,12 +295,7 @@ class BackendTest extends TestCase {
];
}
- /**
- * @dataProvider dataGetUsersForShares
- * @param array $shares
- * @param array $groups
- * @param array $expected
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataGetUsersForShares')]
public function testGetUsersForShares(array $shares, array $groups, array $expected): void {
$backend = $this->getBackend();
@@ -356,7 +325,7 @@ class BackendTest extends TestCase {
/**
* @param string[] $users
- * @return IUser[]|MockObject[]
+ * @return IUser[]&MockObject[]
*/
protected function getUsers(array $users) {
$list = [];
@@ -368,7 +337,7 @@ class BackendTest extends TestCase {
/**
* @param string $uid
- * @return IUser|MockObject
+ * @return IUser&MockObject
*/
protected function getUserMock($uid) {
$user = $this->createMock(IUser::class);
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Filter/CalendarTest.php b/apps/dav/tests/unit/CalDAV/Activity/Filter/CalendarTest.php
index a7c84260f21..b4c4e14fe7d 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Filter/CalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Filter/CalendarTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -9,15 +11,12 @@ use OCA\DAV\CalDAV\Activity\Filter\Calendar;
use OCP\Activity\IFilter;
use OCP\IL10N;
use OCP\IURLGenerator;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CalendarTest extends TestCase {
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- protected $url;
-
- /** @var IFilter|\PHPUnit\Framework\MockObject\MockObject */
- protected $filter;
+ protected IURLGenerator&MockObject $url;
+ protected IFilter $filter;
protected function setUp(): void {
parent::setUp();
@@ -48,7 +47,7 @@ class CalendarTest extends TestCase {
$this->assertEquals('absolute-path-to-icon', $this->filter->getIcon());
}
- public function dataFilterTypes() {
+ public static function dataFilterTypes(): array {
return [
[[], []],
[['calendar', 'calendar_event'], ['calendar', 'calendar_event']],
@@ -58,11 +57,11 @@ class CalendarTest extends TestCase {
}
/**
- * @dataProvider dataFilterTypes
* @param string[] $types
* @param string[] $expected
*/
- public function testFilterTypes($types, $expected): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataFilterTypes')]
+ public function testFilterTypes(array $types, array $expected): void {
$this->assertEquals($expected, $this->filter->filterTypes($types));
}
}
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Filter/GenericTest.php b/apps/dav/tests/unit/CalDAV/Activity/Filter/GenericTest.php
index fcfd1f81517..87b55f14bcc 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Filter/GenericTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Filter/GenericTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -8,89 +10,69 @@ namespace OCA\DAV\Tests\unit\CalDAV\Activity\Filter;
use OCA\DAV\CalDAV\Activity\Filter\Calendar;
use OCA\DAV\CalDAV\Activity\Filter\Todo;
use OCP\Activity\IFilter;
+use OCP\Server;
use Test\TestCase;
/**
* @group DB
*/
class GenericTest extends TestCase {
- public function dataFilters() {
+ public static function dataFilters(): array {
return [
[Calendar::class],
[Todo::class],
];
}
- /**
- * @dataProvider dataFilters
- * @param string $filterClass
- */
- public function testImplementsInterface($filterClass): void {
- $filter = \OC::$server->query($filterClass);
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')]
+ public function testImplementsInterface(string $filterClass): void {
+ $filter = Server::get($filterClass);
$this->assertInstanceOf(IFilter::class, $filter);
}
- /**
- * @dataProvider dataFilters
- * @param string $filterClass
- */
- public function testGetIdentifier($filterClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')]
+ public function testGetIdentifier(string $filterClass): void {
/** @var IFilter $filter */
- $filter = \OC::$server->query($filterClass);
+ $filter = Server::get($filterClass);
$this->assertIsString($filter->getIdentifier());
}
- /**
- * @dataProvider dataFilters
- * @param string $filterClass
- */
- public function testGetName($filterClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')]
+ public function testGetName(string $filterClass): void {
/** @var IFilter $filter */
- $filter = \OC::$server->query($filterClass);
+ $filter = Server::get($filterClass);
$this->assertIsString($filter->getName());
}
- /**
- * @dataProvider dataFilters
- * @param string $filterClass
- */
- public function testGetPriority($filterClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')]
+ public function testGetPriority(string $filterClass): void {
/** @var IFilter $filter */
- $filter = \OC::$server->query($filterClass);
+ $filter = Server::get($filterClass);
$priority = $filter->getPriority();
$this->assertIsInt($filter->getPriority());
$this->assertGreaterThanOrEqual(0, $priority);
$this->assertLessThanOrEqual(100, $priority);
}
- /**
- * @dataProvider dataFilters
- * @param string $filterClass
- */
- public function testGetIcon($filterClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')]
+ public function testGetIcon(string $filterClass): void {
/** @var IFilter $filter */
- $filter = \OC::$server->query($filterClass);
+ $filter = Server::get($filterClass);
$this->assertIsString($filter->getIcon());
$this->assertStringStartsWith('http', $filter->getIcon());
}
- /**
- * @dataProvider dataFilters
- * @param string $filterClass
- */
- public function testFilterTypes($filterClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')]
+ public function testFilterTypes(string $filterClass): void {
/** @var IFilter $filter */
- $filter = \OC::$server->query($filterClass);
+ $filter = Server::get($filterClass);
$this->assertIsArray($filter->filterTypes([]));
}
- /**
- * @dataProvider dataFilters
- * @param string $filterClass
- */
- public function testAllowedApps($filterClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')]
+ public function testAllowedApps(string $filterClass): void {
/** @var IFilter $filter */
- $filter = \OC::$server->query($filterClass);
+ $filter = Server::get($filterClass);
$this->assertIsArray($filter->allowedApps());
}
}
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Filter/TodoTest.php b/apps/dav/tests/unit/CalDAV/Activity/Filter/TodoTest.php
index 6aa47f33750..f18d66b9774 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Filter/TodoTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Filter/TodoTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -9,15 +11,12 @@ use OCA\DAV\CalDAV\Activity\Filter\Todo;
use OCP\Activity\IFilter;
use OCP\IL10N;
use OCP\IURLGenerator;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class TodoTest extends TestCase {
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- protected $url;
-
- /** @var IFilter|\PHPUnit\Framework\MockObject\MockObject */
- protected $filter;
+ protected IURLGenerator&MockObject $url;
+ protected IFilter $filter;
protected function setUp(): void {
parent::setUp();
@@ -48,7 +47,7 @@ class TodoTest extends TestCase {
$this->assertEquals('absolute-path-to-icon', $this->filter->getIcon());
}
- public function dataFilterTypes() {
+ public static function dataFilterTypes(): array {
return [
[[], []],
[['calendar_todo'], ['calendar_todo']],
@@ -58,11 +57,11 @@ class TodoTest extends TestCase {
}
/**
- * @dataProvider dataFilterTypes
* @param string[] $types
* @param string[] $expected
*/
- public function testFilterTypes($types, $expected): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataFilterTypes')]
+ public function testFilterTypes(array $types, array $expected): void {
$this->assertEquals($expected, $this->filter->filterTypes($types));
}
}
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Provider/BaseTest.php b/apps/dav/tests/unit/CalDAV/Activity/Provider/BaseTest.php
index ba97c888b0c..3e6219beef8 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Provider/BaseTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Provider/BaseTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,7 +9,6 @@ namespace OCA\DAV\Tests\unit\CalDAV\Activity\Provider;
use OCA\DAV\CalDAV\Activity\Provider\Base;
use OCP\Activity\IEvent;
-use OCP\Activity\IProvider;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IURLGenerator;
@@ -16,17 +17,10 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class BaseTest extends TestCase {
- /** @var IUserManager|MockObject */
- protected $userManager;
-
- /** @var IGroupManager|MockObject */
- protected $groupManager;
-
- /** @var IURLGenerator|MockObject */
- protected $url;
-
- /** @var IProvider|Base|MockObject */
- protected $provider;
+ protected IUserManager&MockObject $userManager;
+ protected IGroupManager&MockObject $groupManager;
+ protected IURLGenerator&MockObject $url;
+ protected Base&MockObject $provider;
protected function setUp(): void {
parent::setUp();
@@ -39,24 +33,19 @@ class BaseTest extends TestCase {
$this->groupManager,
$this->url,
])
- ->setMethods(['parse'])
+ ->onlyMethods(['parse'])
->getMock();
}
- public function dataSetSubjects() {
+ public static function dataSetSubjects(): array {
return [
- ['abc', [], 'abc'],
- ['{actor} created {calendar}', ['actor' => ['name' => 'abc'], 'calendar' => ['name' => 'xyz']], 'abc created xyz'],
+ ['abc', []],
+ ['{actor} created {calendar}', ['actor' => ['name' => 'abc'], 'calendar' => ['name' => 'xyz']]],
];
}
- /**
- * @dataProvider dataSetSubjects
- * @param string $subject
- * @param array $parameters
- * @param string $parsedSubject
- */
- public function testSetSubjects(string $subject, array $parameters, string $parsedSubject): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSetSubjects')]
+ public function testSetSubjects(string $subject, array $parameters): void {
$event = $this->createMock(IEvent::class);
$event->expects($this->once())
->method('setRichSubject')
@@ -68,7 +57,7 @@ class BaseTest extends TestCase {
$this->invokePrivate($this->provider, 'setSubjects', [$event, $subject, $parameters]);
}
- public function dataGenerateCalendarParameter() {
+ public static function dataGenerateCalendarParameter(): array {
return [
[['id' => 23, 'uri' => 'foo', 'name' => 'bar'], 'bar'],
[['id' => 42, 'uri' => 'foo', 'name' => 'Personal'], 'Personal'],
@@ -77,11 +66,7 @@ class BaseTest extends TestCase {
];
}
- /**
- * @dataProvider dataGenerateCalendarParameter
- * @param array $data
- * @param string $name
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataGenerateCalendarParameter')]
public function testGenerateCalendarParameter(array $data, string $name): void {
$l = $this->createMock(IL10N::class);
$l->expects($this->any())
@@ -97,18 +82,14 @@ class BaseTest extends TestCase {
], $this->invokePrivate($this->provider, 'generateCalendarParameter', [$data, $l]));
}
- public function dataGenerateLegacyCalendarParameter() {
+ public static function dataGenerateLegacyCalendarParameter(): array {
return [
[23, 'c1'],
[42, 'c2'],
];
}
- /**
- * @dataProvider dataGenerateLegacyCalendarParameter
- * @param int $id
- * @param string $name
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataGenerateLegacyCalendarParameter')]
public function testGenerateLegacyCalendarParameter(int $id, string $name): void {
$this->assertEquals([
'type' => 'calendar',
@@ -117,17 +98,14 @@ class BaseTest extends TestCase {
], $this->invokePrivate($this->provider, 'generateLegacyCalendarParameter', [$id, $name]));
}
- public function dataGenerateGroupParameter() {
+ public static function dataGenerateGroupParameter(): array {
return [
['g1'],
['g2'],
];
}
- /**
- * @dataProvider dataGenerateGroupParameter
- * @param string $gid
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataGenerateGroupParameter')]
public function testGenerateGroupParameter(string $gid): void {
$this->assertEquals([
'type' => 'user-group',
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php b/apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php
index b0b2cc936a5..4fd38c1aed2 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -6,11 +8,9 @@
namespace OCA\DAV\Tests\unit\CalDAV\Activity\Provider;
use InvalidArgumentException;
-use OCA\DAV\CalDAV\Activity\Provider\Base;
use OCA\DAV\CalDAV\Activity\Provider\Event;
use OCP\Activity\IEventMerger;
use OCP\Activity\IManager;
-use OCP\Activity\IProvider;
use OCP\App\IAppManager;
use OCP\IGroupManager;
use OCP\IURLGenerator;
@@ -21,30 +21,14 @@ use Test\TestCase;
use TypeError;
class EventTest extends TestCase {
-
- /** @var IUserManager|MockObject */
- protected $userManager;
-
- /** @var IGroupManager|MockObject */
- protected $groupManager;
-
- /** @var IURLGenerator|MockObject */
- protected $url;
-
- /** @var IProvider|Base|MockObject */
- protected $provider;
-
- /** @var IAppManager|MockObject */
- protected $appManager;
-
- /** @var IFactory|MockObject */
- protected $i10nFactory;
-
- /** @var IManager|MockObject */
- protected $activityManager;
-
- /** @var IEventMerger|MockObject */
- protected $eventMerger;
+ protected IUserManager&MockObject $userManager;
+ protected IGroupManager&MockObject $groupManager;
+ protected IURLGenerator&MockObject $url;
+ protected IAppManager&MockObject $appManager;
+ protected IFactory&MockObject $i10nFactory;
+ protected IManager&MockObject $activityManager;
+ protected IEventMerger&MockObject $eventMerger;
+ protected Event&MockObject $provider;
protected function setUp(): void {
parent::setUp();
@@ -65,11 +49,11 @@ class EventTest extends TestCase {
$this->eventMerger,
$this->appManager
])
- ->setMethods(['parse'])
+ ->onlyMethods(['parse'])
->getMock();
}
- public function dataGenerateObjectParameter() {
+ public static function dataGenerateObjectParameter(): array {
$link = [
'object_uri' => 'someuuid.ics',
'calendar_uri' => 'personal',
@@ -83,23 +67,13 @@ class EventTest extends TestCase {
];
}
- /**
- * @dataProvider dataGenerateObjectParameter
- * @param int $id
- * @param string $name
- * @param array|null $link
- * @param bool $calendarAppEnabled
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataGenerateObjectParameter')]
public function testGenerateObjectParameter(int $id, string $name, ?array $link, bool $calendarAppEnabled = true): void {
$affectedUser = 'otheruser';
if ($link) {
$affectedUser = $link['owner'];
$generatedLink = [
- 'view' => 'dayGridMonth',
- 'timeRange' => 'now',
- 'mode' => 'sidebar',
'objectId' => base64_encode('/remote.php/dav/calendars/' . $link['owner'] . '/' . $link['calendar_uri'] . '/' . $link['object_uri']),
- 'recurrenceId' => 'next'
];
$this->appManager->expects($this->once())
->method('isEnabledForUser')
@@ -110,7 +84,7 @@ class EventTest extends TestCase {
->method('getWebroot');
$this->url->expects($this->once())
->method('linkToRouteAbsolute')
- ->with('calendar.view.indexview.timerange.edit', $generatedLink)
+ ->with('calendar.view.indexdirect.edit', $generatedLink)
->willReturn('fullLink');
}
}
@@ -129,18 +103,55 @@ class EventTest extends TestCase {
$this->assertEquals($result, $this->invokePrivate($this->provider, 'generateObjectParameter', [$objectParameter, $affectedUser]));
}
- public function testGenerateObjectParameterWithSharedCalendar(): void {
- $link = [
- 'object_uri' => 'someuuid.ics',
- 'calendar_uri' => 'personal',
- 'owner' => 'sharer'
+ public static function generateObjectParameterLinkEncodingDataProvider(): array {
+ return [
+ [ // Shared calendar
+ [
+ 'object_uri' => 'someuuid.ics',
+ 'calendar_uri' => 'personal',
+ 'owner' => 'sharer'
+ ],
+ base64_encode('/remote.php/dav/calendars/sharee/personal_shared_by_sharer/someuuid.ics'),
+ ],
+ [ // Shared calendar with umlauts
+ [
+ 'object_uri' => 'someuuid.ics',
+ 'calendar_uri' => 'umlaut_äüöß',
+ 'owner' => 'sharer'
+ ],
+ base64_encode('/remote.php/dav/calendars/sharee/umlaut_%c3%a4%c3%bc%c3%b6%c3%9f_shared_by_sharer/someuuid.ics'),
+ ],
+ [ // Shared calendar with umlauts and mixed casing
+ [
+ 'object_uri' => 'someuuid.ics',
+ 'calendar_uri' => 'Umlaut_äüöß',
+ 'owner' => 'sharer'
+ ],
+ base64_encode('/remote.php/dav/calendars/sharee/Umlaut_%c3%a4%c3%bc%c3%b6%c3%9f_shared_by_sharer/someuuid.ics'),
+ ],
+ [ // Owned calendar with umlauts
+ [
+ 'object_uri' => 'someuuid.ics',
+ 'calendar_uri' => 'umlaut_äüöß',
+ 'owner' => 'sharee'
+ ],
+ base64_encode('/remote.php/dav/calendars/sharee/umlaut_%c3%a4%c3%bc%c3%b6%c3%9f/someuuid.ics'),
+ ],
+ [ // Owned calendar with umlauts and mixed casing
+ [
+ 'object_uri' => 'someuuid.ics',
+ 'calendar_uri' => 'Umlaut_äüöß',
+ 'owner' => 'sharee'
+ ],
+ base64_encode('/remote.php/dav/calendars/sharee/Umlaut_%c3%a4%c3%bc%c3%b6%c3%9f/someuuid.ics'),
+ ],
];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('generateObjectParameterLinkEncodingDataProvider')]
+ public function testGenerateObjectParameterLinkEncoding(array $link, string $objectId): void {
$generatedLink = [
- 'view' => 'dayGridMonth',
- 'timeRange' => 'now',
- 'mode' => 'sidebar',
- 'objectId' => base64_encode('/remote.php/dav/calendars/sharee/' . $link['calendar_uri'] . '_shared_by_sharer/' . $link['object_uri']),
- 'recurrenceId' => 'next'
+ 'objectId' => $objectId,
];
$this->appManager->expects($this->once())
->method('isEnabledForUser')
@@ -150,7 +161,7 @@ class EventTest extends TestCase {
->method('getWebroot');
$this->url->expects($this->once())
->method('linkToRouteAbsolute')
- ->with('calendar.view.indexview.timerange.edit', $generatedLink)
+ ->with('calendar.view.indexdirect.edit', $generatedLink)
->willReturn('fullLink');
$objectParameter = ['id' => 42, 'name' => 'calendar', 'link' => $link];
$result = [
@@ -162,7 +173,7 @@ class EventTest extends TestCase {
$this->assertEquals($result, $this->invokePrivate($this->provider, 'generateObjectParameter', [$objectParameter, 'sharee']));
}
- public function dataGenerateObjectParameterThrows() {
+ public static function dataGenerateObjectParameterThrows(): array {
return [
['event', TypeError::class],
[['name' => 'event']],
@@ -170,12 +181,8 @@ class EventTest extends TestCase {
];
}
- /**
- * @dataProvider dataGenerateObjectParameterThrows
- * @param mixed $eventData
- * @param string $exception
- */
- public function testGenerateObjectParameterThrows($eventData, string $exception = InvalidArgumentException::class): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataGenerateObjectParameterThrows')]
+ public function testGenerateObjectParameterThrows(string|array $eventData, string $exception = InvalidArgumentException::class): void {
$this->expectException($exception);
$this->invokePrivate($this->provider, 'generateObjectParameter', [$eventData, 'no_user']);
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Setting/GenericTest.php b/apps/dav/tests/unit/CalDAV/Activity/Setting/GenericTest.php
index 678b815999c..23126b6bbcf 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Setting/GenericTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Setting/GenericTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -9,10 +11,11 @@ use OCA\DAV\CalDAV\Activity\Setting\Calendar;
use OCA\DAV\CalDAV\Activity\Setting\Event;
use OCA\DAV\CalDAV\Activity\Setting\Todo;
use OCP\Activity\ISetting;
+use OCP\Server;
use Test\TestCase;
class GenericTest extends TestCase {
- public function dataSettings() {
+ public static function dataSettings(): array {
return [
[Calendar::class],
[Event::class],
@@ -20,85 +23,61 @@ class GenericTest extends TestCase {
];
}
- /**
- * @dataProvider dataSettings
- * @param string $settingClass
- */
- public function testImplementsInterface($settingClass): void {
- $setting = \OC::$server->query($settingClass);
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')]
+ public function testImplementsInterface(string $settingClass): void {
+ $setting = Server::get($settingClass);
$this->assertInstanceOf(ISetting::class, $setting);
}
- /**
- * @dataProvider dataSettings
- * @param string $settingClass
- */
- public function testGetIdentifier($settingClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')]
+ public function testGetIdentifier(string $settingClass): void {
/** @var ISetting $setting */
- $setting = \OC::$server->query($settingClass);
+ $setting = Server::get($settingClass);
$this->assertIsString($setting->getIdentifier());
}
- /**
- * @dataProvider dataSettings
- * @param string $settingClass
- */
- public function testGetName($settingClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')]
+ public function testGetName(string $settingClass): void {
/** @var ISetting $setting */
- $setting = \OC::$server->query($settingClass);
+ $setting = Server::get($settingClass);
$this->assertIsString($setting->getName());
}
- /**
- * @dataProvider dataSettings
- * @param string $settingClass
- */
- public function testGetPriority($settingClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')]
+ public function testGetPriority(string $settingClass): void {
/** @var ISetting $setting */
- $setting = \OC::$server->query($settingClass);
+ $setting = Server::get($settingClass);
$priority = $setting->getPriority();
$this->assertIsInt($setting->getPriority());
$this->assertGreaterThanOrEqual(0, $priority);
$this->assertLessThanOrEqual(100, $priority);
}
- /**
- * @dataProvider dataSettings
- * @param string $settingClass
- */
- public function testCanChangeStream($settingClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')]
+ public function testCanChangeStream(string $settingClass): void {
/** @var ISetting $setting */
- $setting = \OC::$server->query($settingClass);
+ $setting = Server::get($settingClass);
$this->assertIsBool($setting->canChangeStream());
}
- /**
- * @dataProvider dataSettings
- * @param string $settingClass
- */
- public function testIsDefaultEnabledStream($settingClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')]
+ public function testIsDefaultEnabledStream(string $settingClass): void {
/** @var ISetting $setting */
- $setting = \OC::$server->query($settingClass);
+ $setting = Server::get($settingClass);
$this->assertIsBool($setting->isDefaultEnabledStream());
}
- /**
- * @dataProvider dataSettings
- * @param string $settingClass
- */
- public function testCanChangeMail($settingClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')]
+ public function testCanChangeMail(string $settingClass): void {
/** @var ISetting $setting */
- $setting = \OC::$server->query($settingClass);
+ $setting = Server::get($settingClass);
$this->assertIsBool($setting->canChangeMail());
}
- /**
- * @dataProvider dataSettings
- * @param string $settingClass
- */
- public function testIsDefaultEnabledMail($settingClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')]
+ public function testIsDefaultEnabledMail(string $settingClass): void {
/** @var ISetting $setting */
- $setting = \OC::$server->query($settingClass);
+ $setting = Server::get($settingClass);
$this->assertIsBool($setting->isDefaultEnabledMail());
}
}
diff --git a/apps/dav/tests/unit/CalDAV/AppCalendar/AppCalendarTest.php b/apps/dav/tests/unit/CalDAV/AppCalendar/AppCalendarTest.php
index b8983350348..84879e87238 100644
--- a/apps/dav/tests/unit/CalDAV/AppCalendar/AppCalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/AppCalendar/AppCalendarTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -16,13 +17,13 @@ use Test\TestCase;
use function rewind;
class AppCalendarTest extends TestCase {
- private $principal = 'principals/users/foo';
+ private string $principal = 'principals/users/foo';
private AppCalendar $appCalendar;
private AppCalendar $writeableAppCalendar;
- private ICalendar|MockObject $calendar;
- private ICalendar|MockObject $writeableCalendar;
+ private ICalendar&MockObject $calendar;
+ private ICalendar&MockObject $writeableCalendar;
protected function setUp(): void {
parent::setUp();
@@ -52,10 +53,18 @@ class AppCalendarTest extends TestCase {
$this->appCalendar->delete();
}
- public function testCreateFile() {
+ public function testCreateFile(): void {
+ $calls = [
+ ['some-name', 'data'],
+ ['other-name', ''],
+ ['name', 'some data'],
+ ];
$this->writeableCalendar->expects($this->exactly(3))
->method('createFromString')
- ->withConsecutive(['some-name', 'data'], ['other-name', ''], ['name', 'some data']);
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
// pass data
$this->assertNull($this->writeableAppCalendar->createFile('some-name', 'data'));
@@ -69,7 +78,7 @@ class AppCalendarTest extends TestCase {
fclose($fp);
}
- public function testCreateFile_readOnly() {
+ public function testCreateFile_readOnly(): void {
// If writing is not supported
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->expectExceptionMessage('Creating a new entry is not allowed');
diff --git a/apps/dav/tests/unit/CalDAV/AppCalendar/CalendarObjectTest.php b/apps/dav/tests/unit/CalDAV/AppCalendar/CalendarObjectTest.php
index 92288f5dfb0..3d72d5c97b8 100644
--- a/apps/dav/tests/unit/CalDAV/AppCalendar/CalendarObjectTest.php
+++ b/apps/dav/tests/unit/CalDAV/AppCalendar/CalendarObjectTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -17,9 +18,9 @@ use Test\TestCase;
class CalendarObjectTest extends TestCase {
private CalendarObject $calendarObject;
- private AppCalendar|MockObject $calendar;
- private ICalendar|MockObject $backend;
- private VCalendar|MockObject $vobject;
+ private AppCalendar&MockObject $calendar;
+ private ICalendar&MockObject $backend;
+ private VCalendar&MockObject $vobject;
protected function setUp(): void {
parent::setUp();
@@ -33,15 +34,15 @@ class CalendarObjectTest extends TestCase {
$this->calendarObject = new CalendarObject($this->calendar, $this->backend, $this->vobject);
}
- public function testGetOwner() {
+ public function testGetOwner(): void {
$this->assertEquals($this->calendarObject->getOwner(), 'owner');
}
- public function testGetGroup() {
+ public function testGetGroup(): void {
$this->assertEquals($this->calendarObject->getGroup(), 'group');
}
- public function testGetACL() {
+ public function testGetACL(): void {
$this->calendar->expects($this->exactly(2))
->method('getPermissions')
->willReturnOnConsecutiveCalls(Constants::PERMISSION_READ, Constants::PERMISSION_ALL);
@@ -70,17 +71,17 @@ class CalendarObjectTest extends TestCase {
]);
}
- public function testSetACL() {
+ public function testSetACL(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->calendarObject->setACL([]);
}
- public function testPut_readOnlyBackend() {
+ public function testPut_readOnlyBackend(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->calendarObject->put('foo');
}
- public function testPut_noPermissions() {
+ public function testPut_noPermissions(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$backend = $this->createMock(ICreateFromString::class);
@@ -93,7 +94,7 @@ class CalendarObjectTest extends TestCase {
$calendarObject->put('foo');
}
- public function testPut() {
+ public function testPut(): void {
$backend = $this->createMock(ICreateFromString::class);
$calendarObject = new CalendarObject($this->calendar, $backend, $this->vobject);
@@ -110,19 +111,19 @@ class CalendarObjectTest extends TestCase {
$calendarObject->put('foo');
}
- public function testGet() {
+ public function testGet(): void {
$this->vobject->expects($this->once())
->method('serialize')
->willReturn('foo');
$this->assertEquals($this->calendarObject->get(), 'foo');
}
- public function testDelete_notWriteable() {
+ public function testDelete_notWriteable(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->calendarObject->delete();
}
- public function testDelete_noPermission() {
+ public function testDelete_noPermission(): void {
$backend = $this->createMock(ICreateFromString::class);
$calendarObject = new CalendarObject($this->calendar, $backend, $this->vobject);
@@ -130,7 +131,7 @@ class CalendarObjectTest extends TestCase {
$calendarObject->delete();
}
- public function testDelete() {
+ public function testDelete(): void {
$backend = $this->createMock(ICreateFromString::class);
$calendarObject = new CalendarObject($this->calendar, $backend, $this->vobject);
@@ -153,7 +154,7 @@ class CalendarObjectTest extends TestCase {
$calendarObject->delete();
}
- public function testGetName() {
+ public function testGetName(): void {
$this->vobject->expects($this->exactly(2))
->method('getBaseComponent')
->willReturnOnConsecutiveCalls((object)['UID' => 'someid'], (object)['UID' => 'someid', 'X-FILENAME' => 'real-filename.ics']);
@@ -162,7 +163,7 @@ class CalendarObjectTest extends TestCase {
$this->assertEquals($this->calendarObject->getName(), 'real-filename.ics');
}
- public function testSetName() {
+ public function testSetName(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->calendarObject->setName('Some name');
}
diff --git a/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php b/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php
index e7de7d0a55e..a5811271ce2 100644
--- a/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -11,24 +13,15 @@ use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CalDAV\CalendarHome;
use OCP\IConfig;
use OCP\IUser;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class EnablePluginTest extends TestCase {
-
- /** @var \Sabre\DAV\Server|\PHPUnit\Framework\MockObject\MockObject */
- protected $server;
-
- /** @var \OCP\IConfig|\PHPUnit\Framework\MockObject\MockObject */
- protected $config;
-
- /** @var BirthdayService |\PHPUnit\Framework\MockObject\MockObject */
- protected $birthdayService;
-
- /** @var IUser|\PHPUnit\Framework\MockObject\MockObject */
- protected $user;
-
- /** @var \OCA\DAV\CalDAV\BirthdayCalendar\EnablePlugin $plugin */
- protected $plugin;
+ protected \Sabre\DAV\Server&MockObject $server;
+ protected IConfig&MockObject $config;
+ protected BirthdayService&MockObject $birthdayService;
+ protected IUser&MockObject $user;
+ protected EnablePlugin $plugin;
protected $request;
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php
index 2378a75a7d5..935d8314f29 100644
--- a/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php
@@ -12,13 +12,14 @@ namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\CalDAV\CachedSubscription;
use OCA\DAV\CalDAV\CachedSubscriptionImpl;
use OCA\DAV\CalDAV\CalDavBackend;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CachedSubscriptionImplTest extends TestCase {
- private CachedSubscription $cachedSubscription;
+ private CachedSubscription&MockObject $cachedSubscription;
private array $cachedSubscriptionInfo;
+ private CalDavBackend&MockObject $backend;
private CachedSubscriptionImpl $cachedSubscriptionImpl;
- private CalDavBackend $backend;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionObjectTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionObjectTest.php
index 56e4930d3b3..03a2c9f20ee 100644
--- a/apps/dav/tests/unit/CalDAV/CachedSubscriptionObjectTest.php
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionObjectTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -32,7 +34,7 @@ class CachedSubscriptionObjectTest extends \Test\TestCase {
$this->assertEquals('BEGIN...', $calendarObject->get());
}
-
+
public function testPut(): void {
$this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
$this->expectExceptionMessage('Creating objects in a cached subscription is not allowed');
@@ -52,7 +54,7 @@ class CachedSubscriptionObjectTest extends \Test\TestCase {
$calendarObject->put('');
}
-
+
public function testDelete(): void {
$this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
$this->expectExceptionMessage('Deleting objects in a cached subscription is not allowed');
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php
index 22998eec3d9..58d5ca7835c 100644
--- a/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php
@@ -12,11 +12,12 @@ namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\CalDAV\CachedSubscriptionImpl;
use OCA\DAV\CalDAV\CachedSubscriptionProvider;
use OCA\DAV\CalDAV\CalDavBackend;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CachedSubscriptionProviderTest extends TestCase {
- private CalDavBackend $backend;
+ private CalDavBackend&MockObject $backend;
private CachedSubscriptionProvider $provider;
protected function setUp(): void {
@@ -47,7 +48,7 @@ class CachedSubscriptionProviderTest extends TestCase {
$this->provider = new CachedSubscriptionProvider($this->backend);
}
- public function testGetCalendars() {
+ public function testGetCalendars(): void {
$calendars = $this->provider->getCalendars(
'user-principal-123',
[]
@@ -58,7 +59,7 @@ class CachedSubscriptionProviderTest extends TestCase {
$this->assertInstanceOf(CachedSubscriptionImpl::class, $calendars[1]);
}
- public function testGetCalendarsFilterByUri() {
+ public function testGetCalendarsFilterByUri(): void {
$calendars = $this->provider->getCalendars(
'user-principal-123',
['subscription-1']
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php
index e1d22bc3e7b..ba0da422290 100644
--- a/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -140,19 +141,21 @@ class CachedSubscriptionTest extends \Test\TestCase {
'uri' => 'cal',
];
+ $calls = [
+ [666, 'foo1', 1, [
+ 'id' => 99,
+ 'uri' => 'foo1'
+ ]],
+ [666, 'foo2', 1, null],
+ ];
$backend->expects($this->exactly(2))
->method('getCalendarObject')
- ->withConsecutive(
- [666, 'foo1', 1],
- [666, 'foo2', 1],
- )
- ->willReturnOnConsecutiveCalls(
- [
- 'id' => 99,
- 'uri' => 'foo1'
- ],
- null
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $return = array_pop($expected);
+ $this->assertEquals($expected, func_get_args());
+ return $return;
+ });
$calendar = new CachedSubscription($backend, $calendarInfo);
@@ -250,19 +253,21 @@ class CachedSubscriptionTest extends \Test\TestCase {
'uri' => 'cal',
];
+ $calls = [
+ [666, 'foo1', 1, [
+ 'id' => 99,
+ 'uri' => 'foo1'
+ ]],
+ [666, 'foo2', 1, null],
+ ];
$backend->expects($this->exactly(2))
->method('getCalendarObject')
- ->withConsecutive(
- [666, 'foo1', 1],
- [666, 'foo2', 1],
- )
- ->willReturnOnConsecutiveCalls(
- [
- 'id' => 99,
- 'uri' => 'foo1'
- ],
- null
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $return = array_pop($expected);
+ $this->assertEquals($expected, func_get_args());
+ return $return;
+ });
$calendar = new CachedSubscription($backend, $calendarInfo);
diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
index 94d55336444..f9205d5d322 100644
--- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -17,6 +19,7 @@ use OCA\DAV\DAV\Sharing\Plugin as SharingPlugin;
use OCA\DAV\Events\CalendarDeletedEvent;
use OCP\IConfig;
use OCP\IL10N;
+use Psr\Log\NullLogger;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\PropPatch;
use Sabre\DAV\Xml\Property\Href;
@@ -27,8 +30,6 @@ use function time;
* Class CalDavBackendTest
*
* @group DB
- *
- * @package OCA\DAV\Tests\unit\CalDAV
*/
class CalDavBackendTest extends AbstractCalDavBackend {
public function testCalendarOperations(): void {
@@ -58,7 +59,7 @@ class CalDavBackendTest extends AbstractCalDavBackend {
self::assertEmpty($calendars);
}
- public function providesSharingData() {
+ public static function providesSharingData(): array {
return [
[true, true, true, false, [
[
@@ -111,13 +112,11 @@ class CalDavBackendTest extends AbstractCalDavBackend {
];
}
- /**
- * @dataProvider providesSharingData
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesSharingData')]
public function testCalendarSharing($userCanRead, $userCanWrite, $groupCanRead, $groupCanWrite, $add, $principals): void {
$logger = $this->createMock(\Psr\Log\LoggerInterface::class);
$config = $this->createMock(IConfig::class);
- /** @var IL10N|MockObject $l10n */
+
$l10n = $this->createMock(IL10N::class);
$l10n->expects($this->any())
->method('t')
@@ -402,9 +401,7 @@ EOD;
$this->assertCount(0, $calendarObjects);
}
- /**
- * @dataProvider providesCalendarQueryParameters
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesCalendarQueryParameters')]
public function testCalendarQuery($expectedEventsInResult, $propFilters, $compFilter): void {
$calendarId = $this->createTestCalendar();
$events = [];
@@ -457,7 +454,7 @@ EOD;
$this->assertNotNull($co);
}
- public function providesCalendarQueryParameters() {
+ public static function providesCalendarQueryParameters(): array {
return [
'all' => [[0, 1, 2, 3], [], []],
'only-todos' => [[], ['name' => 'VTODO'], []],
@@ -468,19 +465,91 @@ EOD;
];
}
- public function testSyncSupport(): void {
- $calendarId = $this->createTestCalendar();
+ public function testCalendarSynchronization(): void {
- // fist call without synctoken
- $changes = $this->backend->getChangesForCalendar($calendarId, '', 1);
- $syncToken = $changes['syncToken'];
+ // construct calendar for testing
+ $calendarId = $this->createTestCalendar();
- // add a change
- $event = $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z');
+ /** test fresh sync state with NO events in calendar */
+ // construct test state
+ $stateTest = ['syncToken' => 1, 'added' => [], 'modified' => [], 'deleted' => []];
+ // retrieve live state
+ $stateLive = $this->backend->getChangesForCalendar($calendarId, '', 1);
+ // test live state
+ $this->assertEquals($stateTest, $stateLive, 'Failed test fresh sync state with NO events in calendar');
+
+ /** test delta sync state with NO events in calendar */
+ // construct test state
+ $stateTest = ['syncToken' => 1, 'added' => [], 'modified' => [], 'deleted' => []];
+ // retrieve live state
+ $stateLive = $this->backend->getChangesForCalendar($calendarId, '2', 1);
+ // test live state
+ $this->assertEquals($stateTest, $stateLive, 'Failed test delta sync state with NO events in calendar');
+
+ /** add events to calendar */
+ $event1 = $this->createEvent($calendarId, '20240701T130000Z', '20240701T140000Z');
+ $event2 = $this->createEvent($calendarId, '20240701T140000Z', '20240701T150000Z');
+ $event3 = $this->createEvent($calendarId, '20240701T150000Z', '20240701T160000Z');
+
+ /** test fresh sync state with events in calendar */
+ // construct expected state
+ $stateTest = ['syncToken' => 4, 'added' => [$event1, $event2, $event3], 'modified' => [], 'deleted' => []];
+ sort($stateTest['added']);
+ // retrieve live state
+ $stateLive = $this->backend->getChangesForCalendar($calendarId, '', 1);
+ // sort live state results
+ sort($stateLive['added']);
+ sort($stateLive['modified']);
+ sort($stateLive['deleted']);
+ // test live state
+ $this->assertEquals($stateTest, $stateLive, 'Failed test fresh sync state with events in calendar');
+
+ /** test delta sync state with events in calendar */
+ // construct expected state
+ $stateTest = ['syncToken' => 4, 'added' => [$event2, $event3], 'modified' => [], 'deleted' => []];
+ sort($stateTest['added']);
+ // retrieve live state
+ $stateLive = $this->backend->getChangesForCalendar($calendarId, '2', 1);
+ // sort live state results
+ sort($stateLive['added']);
+ sort($stateLive['modified']);
+ sort($stateLive['deleted']);
+ // test live state
+ $this->assertEquals($stateTest, $stateLive, 'Failed test delta sync state with events in calendar');
+
+ /** modify/delete events in calendar */
+ $this->deleteEvent($calendarId, $event1);
+ $this->modifyEvent($calendarId, $event2, '20250701T140000Z', '20250701T150000Z');
+
+ /** test fresh sync state with modified/deleted events in calendar */
+ // construct expected state
+ $stateTest = ['syncToken' => 6, 'added' => [$event2, $event3], 'modified' => [], 'deleted' => []];
+ sort($stateTest['added']);
+ // retrieve live state
+ $stateLive = $this->backend->getChangesForCalendar($calendarId, '', 1);
+ // sort live state results
+ sort($stateLive['added']);
+ sort($stateLive['modified']);
+ sort($stateLive['deleted']);
+ // test live state
+ $this->assertEquals($stateTest, $stateLive, 'Failed test fresh sync state with modified/deleted events in calendar');
+
+ /** test delta sync state with modified/deleted events in calendar */
+ // construct expected state
+ $stateTest = ['syncToken' => 6, 'added' => [$event3], 'modified' => [$event2], 'deleted' => [$event1]];
+ // retrieve live state
+ $stateLive = $this->backend->getChangesForCalendar($calendarId, '3', 1);
+ // test live state
+ $this->assertEquals($stateTest, $stateLive, 'Failed test delta sync state with modified/deleted events in calendar');
+
+ /** test delta sync state with modified/deleted events in calendar and invalid token */
+ // construct expected state
+ $stateTest = ['syncToken' => 6, 'added' => [], 'modified' => [], 'deleted' => []];
+ // retrieve live state
+ $stateLive = $this->backend->getChangesForCalendar($calendarId, '6', 1);
+ // test live state
+ $this->assertEquals($stateTest, $stateLive, 'Failed test delta sync state with modified/deleted events in calendar and invalid token');
- // look for changes
- $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 1);
- $this->assertEquals($event, $changes['added'][0]);
}
public function testPublications(): void {
@@ -546,7 +615,7 @@ EOD;
$this->assertCount(0, $subscriptions);
}
- public function providesSchedulingData() {
+ public static function providesSchedulingData(): array {
$data = <<<EOS
BEGIN:VCALENDAR
VERSION:2.0
@@ -619,9 +688,9 @@ EOS;
}
/**
- * @dataProvider providesSchedulingData
* @param $objectData
*/
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesSchedulingData')]
public function testScheduling($objectData): void {
$this->backend->createSchedulingObject(self::UNIT_TEST_USER, 'Sample Schedule', $objectData);
@@ -637,9 +706,7 @@ EOS;
$this->assertCount(0, $sos);
}
- /**
- * @dataProvider providesCalDataForGetDenormalizedData
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesCalDataForGetDenormalizedData')]
public function testGetDenormalizedData($expected, $key, $calData): void {
try {
$actual = $this->backend->getDenormalizedData($calData);
@@ -652,7 +719,7 @@ EOS;
}
}
- public function providesCalDataForGetDenormalizedData(): array {
+ public static function providesCalDataForGetDenormalizedData(): array {
return [
'first occurrence before unix epoch starts' => [0, 'firstOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:413F269B-B51B-46B1-AFB6-40055C53A4DC\r\nDTSTAMP:20160309T095056Z\r\nDTSTART;VALUE=DATE:16040222\r\nDTEND;VALUE=DATE:16040223\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:SUMMARY\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"],
'no first occurrence because yearly' => [null, 'firstOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:413F269B-B51B-46B1-AFB6-40055C53A4DC\r\nDTSTAMP:20160309T095056Z\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:SUMMARY\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"],
@@ -661,7 +728,7 @@ EOS;
'last occurrence before unix epoch starts' => [0, 'lastOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.3.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nDTSTART;VALUE=DATE:19110324\r\nDTEND;VALUE=DATE:19110325\r\nDTSTAMP:20200927T180638Z\r\nUID:asdfasdfasdf@google.com\r\nCREATED:20200626T181848Z\r\nDESCRIPTION:Very old event\r\nLAST-MODIFIED:20200922T192707Z\r\nSUMMARY:Some old event\r\nTRANSP:OPAQUE\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"],
- 'first occurrence is found when not first VEVENT in group' => [(new DateTime('2020-09-01T110000', new DateTimeZone("America/Los_Angeles")))->getTimestamp(), 'firstOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.3.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nDTSTART;TZID=America/Los_Angeles:20201013T110000\r\nDTEND;TZID=America/Los_Angeles:20201013T120000\r\nDTSTAMP:20200927T180638Z\r\nUID:asdf0000@google.com\r\nRECURRENCE-ID;TZID=America/Los_Angeles:20201013T110000\r\nCREATED:20160330T034726Z\r\nLAST-MODIFIED:20200925T042014Z\r\nSTATUS:CONFIRMED\r\nTRANSP:OPAQUE\r\nEND:VEVENT\r\nBEGIN:VEVENT\r\nDTSTART;TZID=America/Los_Angeles:20200901T110000\r\nDTEND;TZID=America/Los_Angeles:20200901T120000\r\nRRULE:FREQ=WEEKLY;BYDAY=TU\r\nEXDATE;TZID=America/Los_Angeles:20200922T110000\r\nEXDATE;TZID=America/Los_Angeles:20200915T110000\r\nEXDATE;TZID=America/Los_Angeles:20200908T110000\r\nDTSTAMP:20200927T180638Z\r\nUID:asdf0000@google.com\r\nCREATED:20160330T034726Z\r\nLAST-MODIFIED:20200915T162810Z\r\nSTATUS:CONFIRMED\r\nTRANSP:OPAQUE\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"],
+ 'first occurrence is found when not first VEVENT in group' => [(new DateTime('2020-09-01T110000', new DateTimeZone('America/Los_Angeles')))->getTimestamp(), 'firstOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.3.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nDTSTART;TZID=America/Los_Angeles:20201013T110000\r\nDTEND;TZID=America/Los_Angeles:20201013T120000\r\nDTSTAMP:20200927T180638Z\r\nUID:asdf0000@google.com\r\nRECURRENCE-ID;TZID=America/Los_Angeles:20201013T110000\r\nCREATED:20160330T034726Z\r\nLAST-MODIFIED:20200925T042014Z\r\nSTATUS:CONFIRMED\r\nTRANSP:OPAQUE\r\nEND:VEVENT\r\nBEGIN:VEVENT\r\nDTSTART;TZID=America/Los_Angeles:20200901T110000\r\nDTEND;TZID=America/Los_Angeles:20200901T120000\r\nRRULE:FREQ=WEEKLY;BYDAY=TU\r\nEXDATE;TZID=America/Los_Angeles:20200922T110000\r\nEXDATE;TZID=America/Los_Angeles:20200915T110000\r\nEXDATE;TZID=America/Los_Angeles:20200908T110000\r\nDTSTAMP:20200927T180638Z\r\nUID:asdf0000@google.com\r\nCREATED:20160330T034726Z\r\nLAST-MODIFIED:20200915T162810Z\r\nSTATUS:CONFIRMED\r\nTRANSP:OPAQUE\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"],
'CLASS:PRIVATE' => [CalDavBackend::CLASSIFICATION_PRIVATE, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:PRIVATE\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"],
@@ -805,9 +872,7 @@ EOD;
$this->assertEquals(count($search5), 0);
}
- /**
- * @dataProvider searchDataProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('searchDataProvider')]
public function testSearch(bool $isShared, array $searchOptions, int $count): void {
$calendarId = $this->createTestCalendar();
@@ -907,7 +972,7 @@ EOD;
$this->assertCount($count, $result);
}
- public function searchDataProvider() {
+ public static function searchDataProvider(): array {
return [
[false, [], 4],
[true, ['timerange' => ['start' => new DateTime('2013-09-12 13:00:00'), 'end' => new DateTime('2013-09-12 14:00:00')]], 2],
@@ -1418,7 +1483,7 @@ EOD;
self::assertSame(0, $deleted);
}
- public function testSearchAndExpandRecurrences() {
+ public function testSearchAndExpandRecurrences(): void {
$calendarId = $this->createTestCalendar();
$calendarInfo = [
'id' => $calendarId,
@@ -1574,7 +1639,7 @@ EOD;
self::assertEquals([$uri2], $changesAfter['deleted']);
}
- public function testSearchWithLimitAndTimeRange() {
+ public function testSearchWithLimitAndTimeRange(): void {
$calendarId = $this->createTestCalendar();
$calendarInfo = [
'id' => $calendarId,
@@ -1583,12 +1648,12 @@ EOD;
];
$testFiles = [
- __DIR__ . '/../../misc/caldav-search-limit-timerange-1.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-2.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-3.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-4.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-5.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-6.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-1.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-2.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-3.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-4.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-5.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-6.ics',
];
foreach ($testFiles as $testFile) {
@@ -1631,7 +1696,7 @@ EOD;
);
}
- public function testSearchWithLimitAndTimeRangeShouldNotReturnMoreObjectsThenLimit() {
+ public function testSearchWithLimitAndTimeRangeShouldNotReturnMoreObjectsThenLimit(): void {
$calendarId = $this->createTestCalendar();
$calendarInfo = [
'id' => $calendarId,
@@ -1640,12 +1705,12 @@ EOD;
];
$testFiles = [
- __DIR__ . '/../../misc/caldav-search-limit-timerange-1.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-2.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-3.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-4.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-5.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-6.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-1.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-2.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-3.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-4.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-5.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-6.ics',
];
foreach ($testFiles as $testFile) {
@@ -1681,7 +1746,7 @@ EOD;
);
}
- public function testSearchWithLimitAndTimeRangeShouldReturnObjectsInTheSameOrder() {
+ public function testSearchWithLimitAndTimeRangeShouldReturnObjectsInTheSameOrder(): void {
$calendarId = $this->createTestCalendar();
$calendarInfo = [
'id' => $calendarId,
@@ -1690,12 +1755,12 @@ EOD;
];
$testFiles = [
- __DIR__ . '/../../misc/caldav-search-limit-timerange-1.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-2.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-3.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-4.ics',
- __DIR__ . '/../../misc/caldav-search-limit-timerange-6.ics', // <-- intentional!
- __DIR__ . '/../../misc/caldav-search-limit-timerange-5.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-1.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-2.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-3.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-4.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-6.ics', // <-- intentional!
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-5.ics',
];
foreach ($testFiles as $testFile) {
@@ -1738,7 +1803,7 @@ EOD;
);
}
- public function testSearchShouldReturnObjectsInTheSameOrderMissingDate() {
+ public function testSearchShouldReturnObjectsInTheSameOrderMissingDate(): void {
$calendarId = $this->createTestCalendar();
$calendarInfo = [
'id' => $calendarId,
@@ -1747,10 +1812,10 @@ EOD;
];
$testFiles = [
- __DIR__ . '/../../misc/caldav-search-limit-timerange-6.ics', // <-- intentional!
- __DIR__ . '/../../misc/caldav-search-limit-timerange-5.ics',
- __DIR__ . '/../../misc/caldav-search-missing-start-1.ics',
- __DIR__ . '/../../misc/caldav-search-missing-start-2.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-6.ics', // <-- intentional!
+ __DIR__ . '/../test_fixtures/caldav-search-limit-timerange-5.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-missing-start-1.ics',
+ __DIR__ . '/../test_fixtures/caldav-search-missing-start-2.ics',
];
foreach ($testFiles as $testFile) {
@@ -1775,4 +1840,46 @@ EOD;
$this->assertEquals('Missing DTSTART 1', $results[2]['objects'][0]['SUMMARY'][0]);
$this->assertEquals('Missing DTSTART 2', $results[3]['objects'][0]['SUMMARY'][0]);
}
+
+ public function testUnshare(): void {
+ $principalGroup = 'principal:' . self::UNIT_TEST_GROUP;
+ $principalUser = 'principal:' . self::UNIT_TEST_USER;
+
+ $l10n = $this->createMock(IL10N::class);
+ $l10n->method('t')
+ ->willReturnCallback(fn ($text, $parameters = []) => vsprintf($text, $parameters));
+ $config = $this->createMock(IConfig::class);
+ $logger = new NullLogger();
+
+ $this->principal->expects($this->exactly(2))
+ ->method('findByUri')
+ ->willReturnMap([
+ [$principalGroup, '', self::UNIT_TEST_GROUP],
+ [$principalUser, '', self::UNIT_TEST_USER],
+ ]);
+ $this->groupManager->expects($this->once())
+ ->method('groupExists')
+ ->willReturn(true);
+ $this->dispatcher->expects($this->exactly(2))
+ ->method('dispatchTyped');
+
+ $calendarId = $this->createTestCalendar();
+ $calendarInfo = $this->backend->getCalendarById($calendarId);
+
+ $calendar = new Calendar($this->backend, $calendarInfo, $l10n, $config, $logger);
+
+ $this->backend->updateShares(
+ shareable: $calendar,
+ add: [
+ ['href' => $principalGroup, 'readOnly' => false]
+ ],
+ remove: []
+ );
+
+ $this->backend->unshare(
+ shareable: $calendar,
+ principal: $principalUser
+ );
+
+ }
}
diff --git a/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php b/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
index 9956c17fff3..e25cc099bd6 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -22,21 +24,11 @@ use Sabre\DAV\MkCol;
use Test\TestCase;
class CalendarHomeTest extends TestCase {
-
- /** @var CalDavBackend | MockObject */
- private $backend;
-
- /** @var array */
- private $principalInfo = [];
-
- /** @var PluginManager */
- private $pluginManager;
-
- /** @var CalendarHome */
- private $calendarHome;
-
- /** @var MockObject|LoggerInterface */
- private $logger;
+ private CalDavBackend&MockObject $backend;
+ private array $principalInfo = [];
+ private PluginManager&MockObject $pluginManager;
+ private LoggerInterface&MockObject $logger;
+ private CalendarHome $calendarHome;
protected function setUp(): void {
parent::setUp();
@@ -62,7 +54,7 @@ class CalendarHomeTest extends TestCase {
}
public function testCreateCalendarValidName(): void {
- /** @var MkCol | MockObject $mkCol */
+ /** @var MkCol&MockObject $mkCol */
$mkCol = $this->createMock(MkCol::class);
$mkCol->method('getResourceType')
@@ -82,7 +74,7 @@ class CalendarHomeTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
$this->expectExceptionMessage('The resource you tried to create has a reserved name');
- /** @var MkCol | MockObject $mkCol */
+ /** @var MkCol&MockObject $mkCol */
$mkCol = $this->createMock(MkCol::class);
$this->calendarHome->createExtendedCollection('contact_birthdays', $mkCol);
@@ -92,7 +84,7 @@ class CalendarHomeTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
$this->expectExceptionMessage('The resource you tried to create has a reserved name');
- /** @var MkCol | MockObject $mkCol */
+ /** @var MkCol&MockObject $mkCol */
$mkCol = $this->createMock(MkCol::class);
$this->calendarHome->createExtendedCollection('app-generated--example--foo-1', $mkCol);
diff --git a/apps/dav/tests/unit/CalDAV/CalendarImplTest.php b/apps/dav/tests/unit/CalDAV/CalendarImplTest.php
index 85545854918..d6a8f3b910e 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarImplTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarImplTest.php
@@ -1,10 +1,13 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\DAV\Tests\unit\CalDAV;
+use Generator;
use OCA\DAV\CalDAV\Auth\CustomPrincipalPlugin;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\Calendar;
@@ -20,37 +23,35 @@ use Sabre\VObject\ITip\Message;
use Sabre\VObject\Reader;
class CalendarImplTest extends \Test\TestCase {
- /** @var CalendarImpl */
- private $calendarImpl;
-
- /** @var Calendar | \PHPUnit\Framework\MockObject\MockObject */
- private $calendar;
-
- /** @var array */
- private $calendarInfo;
-
- /** @var CalDavBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $backend;
+ private Calendar&MockObject $calendar;
+ private array $calendarInfo;
+ private CalDavBackend&MockObject $backend;
+ private CalendarImpl $calendarImpl;
+ private array $mockExportCollection;
protected function setUp(): void {
parent::setUp();
$this->calendar = $this->createMock(Calendar::class);
$this->calendarInfo = [
- 'id' => 'fancy_id_123',
+ 'id' => 1,
'{DAV:}displayname' => 'user readable name 123',
'{http://apple.com/ns/ical/}calendar-color' => '#AABBCC',
- 'uri' => '/this/is/a/uri'
+ 'uri' => '/this/is/a/uri',
+ 'principaluri' => 'principal/users/foobar'
];
$this->backend = $this->createMock(CalDavBackend::class);
- $this->calendarImpl = new CalendarImpl($this->calendar,
- $this->calendarInfo, $this->backend);
+ $this->calendarImpl = new CalendarImpl(
+ $this->calendar,
+ $this->calendarInfo,
+ $this->backend
+ );
}
public function testGetKey(): void {
- $this->assertEquals($this->calendarImpl->getKey(), 'fancy_id_123');
+ $this->assertEquals($this->calendarImpl->getKey(), 1);
}
public function testGetDisplayname(): void {
@@ -76,7 +77,10 @@ class CalendarImplTest extends \Test\TestCase {
->method('getACL')
->with()
->willReturn([
- ['privilege' => '{DAV:}read']
+ ['privilege' => '{DAV:}read', 'principal' => 'principal/users/foobar'],
+ ['privilege' => '{DAV:}read', 'principal' => 'principal/users/other'],
+ ['privilege' => '{DAV:}write', 'principal' => 'principal/users/other'],
+ ['privilege' => '{DAV:}all', 'principal' => 'principal/users/other'],
]);
$this->assertEquals(1, $this->calendarImpl->getPermissions());
@@ -87,7 +91,9 @@ class CalendarImplTest extends \Test\TestCase {
->method('getACL')
->with()
->willReturn([
- ['privilege' => '{DAV:}write']
+ ['privilege' => '{DAV:}write', 'principal' => 'principal/users/foobar'],
+ ['privilege' => '{DAV:}read', 'principal' => 'principal/users/other'],
+ ['privilege' => '{DAV:}all', 'principal' => 'principal/users/other'],
]);
$this->assertEquals(6, $this->calendarImpl->getPermissions());
@@ -98,8 +104,9 @@ class CalendarImplTest extends \Test\TestCase {
->method('getACL')
->with()
->willReturn([
- ['privilege' => '{DAV:}read'],
- ['privilege' => '{DAV:}write']
+ ['privilege' => '{DAV:}write', 'principal' => 'principal/users/foobar'],
+ ['privilege' => '{DAV:}read', 'principal' => 'principal/users/foobar'],
+ ['privilege' => '{DAV:}all', 'principal' => 'principal/users/other'],
]);
$this->assertEquals(7, $this->calendarImpl->getPermissions());
@@ -110,7 +117,7 @@ class CalendarImplTest extends \Test\TestCase {
->method('getACL')
->with()
->willReturn([
- ['privilege' => '{DAV:}all']
+ ['privilege' => '{DAV:}all', 'principal' => 'principal/users/foobar'],
]);
$this->assertEquals(31, $this->calendarImpl->getPermissions());
@@ -138,13 +145,13 @@ EOF;
->method('setCurrentPrincipal')
->with($this->calendar->getPrincipalURI());
- /** @var \Sabre\DAVACL\Plugin|MockObject $aclPlugin*/
+ /** @var \Sabre\DAVACL\Plugin|MockObject $aclPlugin */
$aclPlugin = $this->createMock(\Sabre\DAVACL\Plugin::class);
/** @var Plugin|MockObject $schedulingPlugin */
$schedulingPlugin = $this->createMock(Plugin::class);
$iTipMessage = $this->getITipMessage($message);
- $iTipMessage->recipient = "mailto:lewis@stardew-tent-living.com";
+ $iTipMessage->recipient = 'mailto:lewis@stardew-tent-living.com';
$server = $this->createMock(Server::class);
$server->expects($this->any())
@@ -191,8 +198,8 @@ EOF;
/** @var \Sabre\DAVACL\Plugin|MockObject $schedulingPlugin */
$aclPlugin = $this->createMock(\Sabre\DAVACL\Plugin::class);
- $server =
- $this->createMock(Server::class);
+ $server
+ = $this->createMock(Server::class);
$server->expects($this->any())
->method('getPlugin')
->willReturnMap([
@@ -254,4 +261,48 @@ EOF;
$iTipMessage->message = $vObject;
return $iTipMessage;
}
+
+ protected function mockExportGenerator(): Generator {
+ foreach ($this->mockExportCollection as $entry) {
+ yield $entry;
+ }
+ }
+
+ public function testExport(): void {
+ // Arrange
+ // construct calendar with a 1 hour event and same start/end time zones
+ $vCalendar = new VCalendar();
+ /** @var VEvent $vEvent */
+ $vEvent = $vCalendar->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('SUMMARY', 'Test Recurrence Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ // construct data store return
+ $this->mockExportCollection[] = [
+ 'id' => 1,
+ 'calendardata' => $vCalendar->serialize()
+ ];
+ $this->backend->expects($this->once())
+ ->method('exportCalendar')
+ ->with(1, $this->backend::CALENDAR_TYPE_CALENDAR, null)
+ ->willReturn($this->mockExportGenerator());
+
+ // Act
+ foreach ($this->calendarImpl->export(null) as $entry) {
+ $exported[] = $entry;
+ }
+
+ // Assert
+ $this->assertCount(1, $exported, 'Invalid exported items count');
+ }
+
}
diff --git a/apps/dav/tests/unit/CalDAV/CalendarManagerTest.php b/apps/dav/tests/unit/CalDAV/CalendarManagerTest.php
index 63d92dff40d..e8159ffe07c 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarManagerTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarManagerTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -16,20 +18,11 @@ use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
class CalendarManagerTest extends \Test\TestCase {
- /** @var CalDavBackend | MockObject */
- private $backend;
-
- /** @var IL10N | MockObject */
- private $l10n;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var CalendarManager */
- private $manager;
-
- /** @var MockObject|LoggerInterface */
- private $logger;
+ private CalDavBackend&MockObject $backend;
+ private IL10N&MockObject $l10n;
+ private IConfig&MockObject $config;
+ private LoggerInterface&MockObject $logger;
+ private CalendarManager $manager;
protected function setUp(): void {
parent::setUp();
@@ -54,7 +47,7 @@ class CalendarManagerTest extends \Test\TestCase {
['id' => 456, 'uri' => 'blablub2'],
]);
- /** @var IManager | MockObject $calendarManager */
+ /** @var IManager&MockObject $calendarManager */
$calendarManager = $this->createMock(Manager::class);
$registeredIds = [];
$calendarManager->expects($this->exactly(2))
diff --git a/apps/dav/tests/unit/CalDAV/CalendarTest.php b/apps/dav/tests/unit/CalDAV/CalendarTest.php
index ca6b3191df4..b0d3c35bfe7 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -18,20 +20,13 @@ use Sabre\VObject\Reader;
use Test\TestCase;
class CalendarTest extends TestCase {
-
- /** @var IL10N */
- protected $l10n;
-
- /** @var IConfig */
- protected $config;
-
- /** @var MockObject|LoggerInterface */
- protected $logger;
+ protected IL10N&MockObject $l10n;
+ protected IConfig&MockObject $config;
+ protected LoggerInterface&MockObject $logger;
protected function setUp(): void {
parent::setUp();
- $this->l10n = $this->getMockBuilder(IL10N::class)
- ->disableOriginalConstructor()->getMock();
+ $this->l10n = $this->createMock(IL10N::class);
$this->config = $this->createMock(IConfig::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->l10n
@@ -43,12 +38,13 @@ class CalendarTest extends TestCase {
}
public function testDelete(): void {
- /** @var MockObject | CalDavBackend $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
- $backend->expects($this->once())->method('updateShares');
- $backend->expects($this->any())->method('getShares')->willReturn([
- ['href' => 'principal:user2']
- ]);
+ /** @var CalDavBackend&MockObject $backend */
+ $backend = $this->createMock(CalDavBackend::class);
+ $backend->expects($this->never())
+ ->method('updateShares');
+ $backend->expects($this->once())
+ ->method('unshare');
+
$calendarInfo = [
'{http://owncloud.org/ns}owner-principal' => 'user1',
'principaluri' => 'user2',
@@ -61,12 +57,13 @@ class CalendarTest extends TestCase {
public function testDeleteFromGroup(): void {
- /** @var MockObject | CalDavBackend $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
- $backend->expects($this->once())->method('updateShares');
- $backend->expects($this->any())->method('getShares')->willReturn([
- ['href' => 'principal:group2']
- ]);
+ /** @var CalDavBackend&MockObject $backend */
+ $backend = $this->createMock(CalDavBackend::class);
+ $backend->expects($this->never())
+ ->method('updateShares');
+ $backend->expects($this->once())
+ ->method('unshare');
+
$calendarInfo = [
'{http://owncloud.org/ns}owner-principal' => 'user1',
'principaluri' => 'user2',
@@ -78,7 +75,7 @@ class CalendarTest extends TestCase {
}
public function testDeleteOwn(): void {
- /** @var MockObject | CalDavBackend $backend */
+ /** @var CalDavBackend&MockObject $backend */
$backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->never())->method('updateShares');
$backend->expects($this->never())->method('getShares');
@@ -99,7 +96,7 @@ class CalendarTest extends TestCase {
}
public function testDeleteBirthdayCalendar(): void {
- /** @var MockObject | CalDavBackend $backend */
+ /** @var CalDavBackend&MockObject $backend */
$backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->once())->method('deleteCalendar')
->with(666);
@@ -113,13 +110,14 @@ class CalendarTest extends TestCase {
'principaluri' => 'principals/users/user1',
'id' => 666,
'uri' => 'contact_birthdays',
+ '{DAV:}displayname' => 'Test',
];
$c = new Calendar($backend, $calendarInfo, $this->l10n, $this->config, $this->logger);
$c->delete();
}
- public function dataPropPatch() {
+ public static function dataPropPatch(): array {
return [
['user1', 'user2', [], true],
['user1', 'user2', [
@@ -146,12 +144,10 @@ class CalendarTest extends TestCase {
];
}
- /**
- * @dataProvider dataPropPatch
- */
- public function testPropPatch($ownerPrincipal, $principalUri, $mutations, $shared): void {
- /** @var MockObject | CalDavBackend $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataPropPatch')]
+ public function testPropPatch(string $ownerPrincipal, string $principalUri, array $mutations, bool $shared): void {
+ /** @var CalDavBackend&MockObject $backend */
+ $backend = $this->createMock(CalDavBackend::class);
$calendarInfo = [
'{http://owncloud.org/ns}owner-principal' => $ownerPrincipal,
'principaluri' => $principalUri,
@@ -170,18 +166,17 @@ class CalendarTest extends TestCase {
$this->addToAssertionCount(1);
}
- /**
- * @dataProvider providesReadOnlyInfo
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesReadOnlyInfo')]
public function testAcl($expectsWrite, $readOnlyValue, $hasOwnerSet, $uri = 'default'): void {
- /** @var MockObject | CalDavBackend $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
+ /** @var CalDavBackend&MockObject $backend */
+ $backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->any())->method('applyShareAcl')->willReturnArgument(1);
$calendarInfo = [
'principaluri' => 'user2',
'id' => 666,
'uri' => $uri
];
+ $calendarInfo['{DAV:}displayname'] = 'Test';
if (!is_null($readOnlyValue)) {
$calendarInfo['{http://owncloud.org/ns}read-only'] = $readOnlyValue;
}
@@ -259,7 +254,7 @@ class CalendarTest extends TestCase {
$this->assertEquals($expectedAcl, $childAcl);
}
- public function providesReadOnlyInfo() {
+ public static function providesReadOnlyInfo(): array {
return [
'read-only property not set' => [true, null, true],
'read-only property is false' => [true, false, true],
@@ -271,18 +266,14 @@ class CalendarTest extends TestCase {
];
}
- /**
- * @dataProvider providesConfidentialClassificationData
- * @param int $expectedChildren
- * @param bool $isShared
- */
- public function testPrivateClassification($expectedChildren, $isShared): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesConfidentialClassificationData')]
+ public function testPrivateClassification(int $expectedChildren, bool $isShared): void {
$calObject0 = ['uri' => 'event-0', 'classification' => CalDavBackend::CLASSIFICATION_PUBLIC];
$calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL];
$calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
- /** @var MockObject | CalDavBackend $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
+ /** @var CalDavBackend&MockObject $backend */
+ $backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->any())->method('getCalendarObjects')->willReturn([
$calObject0, $calObject1, $calObject2
]);
@@ -313,12 +304,8 @@ class CalendarTest extends TestCase {
$this->assertEquals(!$isShared, $c->childExists('event-2'));
}
- /**
- * @dataProvider providesConfidentialClassificationData
- * @param int $expectedChildren
- * @param bool $isShared
- */
- public function testConfidentialClassification($expectedChildren, $isShared): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesConfidentialClassificationData')]
+ public function testConfidentialClassification(int $expectedChildren, bool $isShared): void {
$start = '20160609';
$end = '20160610';
@@ -368,8 +355,8 @@ EOD;
$calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL, 'calendardata' => $calData];
$calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
- /** @var MockObject | CalDavBackend $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
+ /** @var CalDavBackend&MockObject $backend */
+ $backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->any())->method('getCalendarObjects')->willReturn([
$calObject0, $calObject1, $calObject2
]);
@@ -416,7 +403,7 @@ EOD;
$l10n->expects($this->once())
->method('t')
->with('Busy')
- ->willReturn("Translated busy");
+ ->willReturn('Translated busy');
} else {
$l10n->expects($this->never())
->method('t');
@@ -433,14 +420,14 @@ EOD;
}
}
- public function providesConfidentialClassificationData() {
+ public static function providesConfidentialClassificationData(): array {
return [
[3, false],
[2, true]
];
}
- public function testRemoveVAlarms() {
+ public function testRemoveVAlarms(): void {
$publicObjectData = <<<EOD
BEGIN:VCALENDAR
VERSION:2.0
@@ -536,7 +523,7 @@ EOD;
'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL,
'calendardata' => $confidentialObjectData];
- /** @var MockObject | CalDavBackend $backend */
+ /** @var CalDavBackend&MockObject $backend */
$backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->any())
->method('getCalendarObjects')
@@ -615,7 +602,7 @@ EOD;
$this->fixLinebreak($confidentialObjectCleaned));
}
- private function fixLinebreak($str) {
+ private function fixLinebreak(string $str): string {
return preg_replace('~(*BSR_ANYCRLF)\R~', "\r\n", $str);
}
}
diff --git a/apps/dav/tests/unit/CalDAV/DefaultCalendarValidatorTest.php b/apps/dav/tests/unit/CalDAV/DefaultCalendarValidatorTest.php
new file mode 100644
index 00000000000..194009827da
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/DefaultCalendarValidatorTest.php
@@ -0,0 +1,171 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\CalDAV;
+
+use OCA\DAV\CalDAV\Calendar;
+use OCA\DAV\CalDAV\DefaultCalendarValidator;
+use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet;
+use Test\TestCase;
+
+class DefaultCalendarValidatorTest extends TestCase {
+ private DefaultCalendarValidator $validator;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->validator = new DefaultCalendarValidator();
+ }
+
+ public function testValidateScheduleDefaultCalendar(): void {
+ $node = $this->createMock(Calendar::class);
+ $node->expects(self::once())
+ ->method('isSubscription')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('canWrite')
+ ->willReturn(true);
+ $node->expects(self::once())
+ ->method('isShared')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('isDeleted')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('getProperties')
+ ->willReturn([
+ '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new SupportedCalendarComponentSet(['VEVENT']),
+ ]);
+
+ $this->validator->validateScheduleDefaultCalendar($node);
+ }
+
+ public function testValidateScheduleDefaultCalendarWithEmptyProperties(): void {
+ $node = $this->createMock(Calendar::class);
+ $node->expects(self::once())
+ ->method('isSubscription')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('canWrite')
+ ->willReturn(true);
+ $node->expects(self::once())
+ ->method('isShared')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('isDeleted')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('getProperties')
+ ->willReturn([]);
+
+ $this->validator->validateScheduleDefaultCalendar($node);
+ }
+
+ public function testValidateScheduleDefaultCalendarWithSubscription(): void {
+ $node = $this->createMock(Calendar::class);
+ $node->expects(self::once())
+ ->method('isSubscription')
+ ->willReturn(true);
+ $node->expects(self::never())
+ ->method('canWrite');
+ $node->expects(self::never())
+ ->method('isShared');
+ $node->expects(self::never())
+ ->method('isDeleted');
+ $node->expects(self::never())
+ ->method('getProperties');
+
+ $this->expectException(\Sabre\DAV\Exception::class);
+ $this->validator->validateScheduleDefaultCalendar($node);
+ }
+
+ public function testValidateScheduleDefaultCalendarWithoutWrite(): void {
+ $node = $this->createMock(Calendar::class);
+ $node->expects(self::once())
+ ->method('isSubscription')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('canWrite')
+ ->willReturn(false);
+ $node->expects(self::never())
+ ->method('isShared');
+ $node->expects(self::never())
+ ->method('isDeleted');
+ $node->expects(self::never())
+ ->method('getProperties');
+
+ $this->expectException(\Sabre\DAV\Exception::class);
+ $this->validator->validateScheduleDefaultCalendar($node);
+ }
+
+ public function testValidateScheduleDefaultCalendarWithShared(): void {
+ $node = $this->createMock(Calendar::class);
+ $node->expects(self::once())
+ ->method('isSubscription')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('canWrite')
+ ->willReturn(true);
+ $node->expects(self::once())
+ ->method('isShared')
+ ->willReturn(true);
+ $node->expects(self::never())
+ ->method('isDeleted');
+ $node->expects(self::never())
+ ->method('getProperties');
+
+ $this->expectException(\Sabre\DAV\Exception::class);
+ $this->validator->validateScheduleDefaultCalendar($node);
+ }
+
+ public function testValidateScheduleDefaultCalendarWithDeleted(): void {
+ $node = $this->createMock(Calendar::class);
+ $node->expects(self::once())
+ ->method('isSubscription')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('canWrite')
+ ->willReturn(true);
+ $node->expects(self::once())
+ ->method('isShared')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('isDeleted')
+ ->willReturn(true);
+ $node->expects(self::never())
+ ->method('getProperties');
+
+ $this->expectException(\Sabre\DAV\Exception::class);
+ $this->validator->validateScheduleDefaultCalendar($node);
+ }
+
+ public function testValidateScheduleDefaultCalendarWithoutVeventSupport(): void {
+ $node = $this->createMock(Calendar::class);
+ $node->expects(self::once())
+ ->method('isSubscription')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('canWrite')
+ ->willReturn(true);
+ $node->expects(self::once())
+ ->method('isShared')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('isDeleted')
+ ->willReturn(false);
+ $node->expects(self::once())
+ ->method('getProperties')
+ ->willReturn([
+ '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new SupportedCalendarComponentSet(['VTODO']),
+ ]);
+
+ $this->expectException(\Sabre\DAV\Exception::class);
+ $this->validator->validateScheduleDefaultCalendar($node);
+ }
+}
diff --git a/apps/dav/tests/unit/CalDAV/EventComparisonServiceTest.php b/apps/dav/tests/unit/CalDAV/EventComparisonServiceTest.php
index 43a7180647f..90b6f9ec0db 100644
--- a/apps/dav/tests/unit/CalDAV/EventComparisonServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/EventComparisonServiceTest.php
@@ -14,8 +14,7 @@ use Sabre\VObject\Component\VCalendar;
use Test\TestCase;
class EventComparisonServiceTest extends TestCase {
- /** @var EventComparisonService */
- private $eventComparisonService;
+ private EventComparisonService $eventComparisonService;
protected function setUp(): void {
$this->eventComparisonService = new EventComparisonService();
diff --git a/apps/dav/tests/unit/CalDAV/EventReaderTest.php b/apps/dav/tests/unit/CalDAV/EventReaderTest.php
new file mode 100644
index 00000000000..3bd4f9d85c2
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/EventReaderTest.php
@@ -0,0 +1,1087 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\CalDAV;
+
+use DateTimeZone;
+use OCA\DAV\CalDAV\EventReader;
+use Sabre\VObject\Component\VCalendar;
+use Test\TestCase;
+
+class EventReaderTest extends TestCase {
+
+ private VCalendar $vCalendar1a;
+ private VCalendar $vCalendar1b;
+ private VCalendar $vCalendar1c;
+ private VCalendar $vCalendar1d;
+ private VCalendar $vCalendar1e;
+ private VCalendar $vCalendar2;
+ private VCalendar $vCalendar3;
+
+ protected function setUp(): void {
+
+ parent::setUp();
+
+ // construct calendar with a 1 hour event and same start/end time zones
+ $this->vCalendar1a = new VCalendar();
+ $vEvent = $this->vCalendar1a->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('SUMMARY', 'Test Recurrence Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+
+ // construct calendar with a 1 hour event and different start/end time zones
+ $this->vCalendar1b = new VCalendar();
+ $vEvent = $this->vCalendar1b->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Vancouver']);
+ $vEvent->add('SUMMARY', 'Test Recurrence Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+
+ // construct calendar with a 1 hour event and global time zone
+ $this->vCalendar1c = new VCalendar();
+ // time zone component
+ $vTimeZone = $this->vCalendar1c->add('VTIMEZONE');
+ $vTimeZone->add('TZID', 'America/Toronto');
+ // event component
+ $vEvent = $this->vCalendar1c->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000');
+ $vEvent->add('DTEND', '20240701T090000');
+ $vEvent->add('SUMMARY', 'Test Recurrence Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+
+ // construct calendar with a 1 hour event and no time zone
+ $this->vCalendar1d = new VCalendar();
+ $vEvent = $this->vCalendar1d->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000');
+ $vEvent->add('DTEND', '20240701T090000');
+ $vEvent->add('SUMMARY', 'Test Recurrence Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+
+ // construct calendar with a 1 hour event and Microsoft time zone
+ $this->vCalendar1e = new VCalendar();
+ $vEvent = $this->vCalendar1e->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'Eastern Standard Time']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'Eastern Standard Time']);
+ $vEvent->add('SUMMARY', 'Test Recurrence Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+
+ // construct calendar with a full day event
+ $this->vCalendar2 = new VCalendar();
+ // time zone component
+ $vTimeZone = $this->vCalendar2->add('VTIMEZONE');
+ $vTimeZone->add('TZID', 'America/Toronto');
+ // event component
+ $vEvent = $this->vCalendar2->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701');
+ $vEvent->add('DTEND', '20240702');
+ $vEvent->add('SUMMARY', 'Test Recurrence Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+
+ // construct calendar with a multi day event
+ $this->vCalendar3 = new VCalendar();
+ // time zone component
+ $vTimeZone = $this->vCalendar3->add('VTIMEZONE');
+ $vTimeZone->add('TZID', 'America/Toronto');
+ // event component
+ $vEvent = $this->vCalendar3->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701');
+ $vEvent->add('DTEND', '20240706');
+ $vEvent->add('SUMMARY', 'Test Recurrence Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+
+ }
+
+ public function testConstructFromCalendarString(): void {
+
+ // construct event reader
+ $er = new EventReader($this->vCalendar1a->serialize(), '96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ // test object creation
+ $this->assertInstanceOf(EventReader::class, $er);
+
+ }
+
+ public function testConstructFromCalendarObject(): void {
+
+ // construct event reader
+ $er = new EventReader($this->vCalendar1a, '96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ // test object creation
+ $this->assertInstanceOf(EventReader::class, $er);
+
+ }
+
+ public function testConstructFromEventObject(): void {
+
+ // construct event reader
+ $er = new EventReader($this->vCalendar1a->VEVENT[0]);
+ // test object creation
+ $this->assertInstanceOf(EventReader::class, $er);
+
+ }
+
+ public function testStartDateTime(): void {
+
+ /** test day part event with same start/end time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->startDateTime());
+
+ /** test day part event with different start/end time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1b, $this->vCalendar1b->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->startDateTime());
+
+ /** test day part event with global time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1c, $this->vCalendar1c->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->startDateTime());
+
+ /** test day part event with no time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1d, $this->vCalendar1d->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('UTC')))), $er->startDateTime());
+
+ /** test day part event with microsoft time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1e, $this->vCalendar1e->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->startDateTime());
+
+ /** test full day event */
+ // construct event reader
+ $er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240701T000000', (new DateTimeZone('America/Toronto')))), $er->startDateTime());
+
+ /** test multi day event */
+ // construct event reader
+ $er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240701T000000', (new DateTimeZone('America/Toronto')))), $er->startDateTime());
+
+ }
+
+ public function testStartTimeZone(): void {
+
+ /** test day part event with same start/end time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone());
+
+ /** test day part event with different start/end time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1b, $this->vCalendar1b->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone());
+
+ /** test day part event with global time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1c, $this->vCalendar1c->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone());
+
+ /** test day part event with no time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1d, $this->vCalendar1d->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('UTC')), $er->startTimeZone());
+
+ /** test day part event with microsoft time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1e, $this->vCalendar1e->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone());
+
+ /** test full day event */
+ // construct event reader
+ $er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone());
+
+ /** test multi day event */
+ // construct event reader
+ $er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone());
+
+ }
+
+ public function testEndDate(): void {
+
+ /** test day part event with same start/end time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('America/Toronto')))), $er->endDateTime());
+
+ /** test day part event with different start/end time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1b, $this->vCalendar1b->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('America/Vancouver')))), $er->endDateTime());
+
+ /** test day part event with global time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1c, $this->vCalendar1c->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('America/Toronto')))), $er->endDateTime());
+
+ /** test day part event with no time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1d, $this->vCalendar1d->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('UTC')))), $er->endDateTime());
+
+ /** test day part event with microsoft time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1e, $this->vCalendar1e->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('America/Toronto')))), $er->endDateTime());
+
+ /** test full day event */
+ // construct event reader
+ $er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240702T000000', (new DateTimeZone('America/Toronto')))), $er->endDateTime());
+
+ /** test multi day event */
+ // construct event reader
+ $er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240706T000000', (new DateTimeZone('America/Toronto')))), $er->endDateTime());
+
+ }
+
+ public function testEndTimeZone(): void {
+
+ /** test day part event with same start/end time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('America/Toronto')), $er->endTimeZone());
+
+ /** test day part event with different start/end time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1b, $this->vCalendar1b->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('America/Vancouver')), $er->endTimeZone());
+
+ /** test day part event with global time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1c, $this->vCalendar1c->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('America/Toronto')), $er->endTimeZone());
+
+ /** test day part event with no time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1d, $this->vCalendar1d->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('UTC')), $er->endTimeZone());
+
+ /** test day part event with microsoft time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1e, $this->vCalendar1e->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('America/Toronto')), $er->endTimeZone());
+
+ /** test full day event */
+ // construct event reader
+ $er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('America/Toronto')), $er->endTimeZone());
+
+ /** test multi day event */
+ // construct event reader
+ $er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new DateTimeZone('America/Toronto')), $er->endTimeZone());
+
+ }
+
+ public function testEntireDay(): void {
+
+ /** test day part event with same start/end time zone */
+ // construct event reader
+ $er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertFalse($er->entireDay());
+
+ /** test full day event */
+ // construct event reader
+ $er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertTrue($er->entireDay());
+
+ /** test multi day event */
+ // construct event reader
+ $er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertTrue($er->entireDay());
+
+ }
+
+ public function testRecurs(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertFalse($er->recurs());
+
+ /** test rrule recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertTrue($er->recurs());
+
+ /** test rdate recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertTrue($er->recurs());
+
+ }
+
+ public function testRecurringPattern(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertNull($er->recurringPattern());
+
+ /** test absolute rrule recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals('A', $er->recurringPattern());
+
+ /** test relative rrule recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=MO;BYSETPOS=1');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals('R', $er->recurringPattern());
+
+ /** test rdate recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals('A', $er->recurringPattern());
+
+ }
+
+ public function testRecurringPrecision(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertNull($er->recurringPrecision());
+
+ /** test daily rrule recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals('daily', $er->recurringPrecision());
+
+ /** test weekly rrule recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals('weekly', $er->recurringPrecision());
+
+ /** test monthly rrule recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8,15');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals('monthly', $er->recurringPrecision());
+
+ /** test yearly rrule recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYMONTHDAY=1');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals('yearly', $er->recurringPrecision());
+
+ /** test rdate recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals('fixed', $er->recurringPrecision());
+
+ }
+
+ public function testRecurringInterval(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertNull($er->recurringInterval());
+
+ /** test daily rrule recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals(2, $er->recurringInterval());
+
+ /** test rdate recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertNull($er->recurringInterval());
+
+ }
+
+ public function testRecurringConcludes(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertFalse($er->recurringConcludes());
+
+ /** test rrule recurrance with no end */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertFalse($er->recurringConcludes());
+
+ /** test rrule recurrance with until date end */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;UNTIL=20240712T080000Z;BYDAY=MO,WE,FR');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertTrue($er->recurringConcludes());
+
+ /** test rrule recurrance with iteration end */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertTrue($er->recurringConcludes());
+
+ /** test rdate recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertTrue($er->recurringConcludes());
+
+ /** test rdate (multiple property instances) recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703');
+ $vCalendar->VEVENT[0]->add('RDATE', '20240705');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertTrue($er->recurringConcludes());
+
+ /** test rrule and rdate recurrance with rdate as last date */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR');
+ $vCalendar->VEVENT[0]->add('RDATE', '20240706,20240715');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertTrue($er->recurringConcludes());
+
+ /** test rrule and rdate recurrance with rrule as last date */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=7;BYDAY=MO,WE,FR');
+ $vCalendar->VEVENT[0]->add('RDATE', '20240706,20240713');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertTrue($er->recurringConcludes());
+
+ }
+
+ public function testRecurringConcludesAfter(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertNull($er->recurringConcludesAfter());
+
+ /** test rrule recurrance with count */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals(6, $er->recurringConcludesAfter());
+
+ /** test rdate recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals(2, $er->recurringConcludesAfter());
+
+ /** test rdate (multiple property instances) recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703');
+ $vCalendar->VEVENT[0]->add('RDATE', '20240705');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals(2, $er->recurringConcludesAfter());
+
+ /** test rrule and rdate recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR');
+ $vCalendar->VEVENT[0]->add('RDATE', '20240706,20240715');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals(8, $er->recurringConcludesAfter());
+
+ }
+
+ public function testRecurringConcludesOn(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertNull($er->recurringConcludesOn());
+
+ /** test rrule recurrance with no end */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertNull($er->recurringConcludesOn());
+
+ /** test rrule recurrance with until date end */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;UNTIL=20240712T080000Z;BYDAY=MO,WE,FR');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+
+ // TODO: Fix until time zone
+ //$this->assertEquals((new \DateTime('20240712T080000', (new DateTimeZone('America/Toronto')))), $er->recurringConcludesOn());
+
+ /** test rdate recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240705T000000', (new DateTimeZone('America/Toronto')))), $er->recurringConcludesOn());
+
+ /** test rdate (multiple property instances) recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703');
+ $vCalendar->VEVENT[0]->add('RDATE', '20240705');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240705T000000', (new DateTimeZone('America/Toronto')))), $er->recurringConcludesOn());
+
+ /** test rrule and rdate recurrance with rdate as last date */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR');
+ $vCalendar->VEVENT[0]->add('RDATE', '20240706,20240715');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240715T000000', (new DateTimeZone('America/Toronto')))), $er->recurringConcludesOn());
+
+ /** test rrule and rdate recurrance with rrule as last date */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=7;BYDAY=MO,WE,FR');
+ $vCalendar->VEVENT[0]->add('RDATE', '20240706,20240713');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals((new \DateTime('20240715T080000', (new DateTimeZone('America/Toronto')))), $er->recurringConcludesOn());
+
+ }
+
+ public function testRecurringDaysOfWeek(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([], $er->recurringDaysOfWeek());
+
+ /** test rrule recurrance with weekly days*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;UNTIL=20240712T080000Z;BYDAY=MO,WE,FR');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals(['MO','WE','FR'], $er->recurringDaysOfWeek());
+
+ }
+
+ public function testRecurringDaysOfWeekNamed(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([], $er->recurringDaysOfWeekNamed());
+
+ /** test rrule recurrance with weekly days*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;UNTIL=20240712T080000Z;BYDAY=MO,WE,FR');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals(['Monday','Wednesday','Friday'], $er->recurringDaysOfWeekNamed());
+
+ }
+
+ public function testRecurringDaysOfMonth(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([], $er->recurringDaysOfMonth());
+
+ /** test rrule recurrance with monthly absolute dates*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=6,13,20,27');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([6,13,20,27], $er->recurringDaysOfMonth());
+
+ }
+
+ public function testRecurringDaysOfYear(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([], $er->recurringDaysOfYear());
+
+ /** test rrule recurrance with monthly absolute dates*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYYEARDAY=1,30,180,365');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([1,30,180,365], $er->recurringDaysOfYear());
+
+ }
+
+ public function testRecurringWeeksOfMonth(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([], $er->recurringWeeksOfMonth());
+
+ /** test rrule recurrance with monthly days*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=MO;BYSETPOS=1');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([1], $er->recurringWeeksOfMonth());
+
+ }
+
+ public function testRecurringWeeksOfMonthNamed(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([], $er->recurringWeeksOfMonthNamed());
+
+ /** test rrule recurrance with weekly days*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=MO;BYSETPOS=1');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals(['First'], $er->recurringWeeksOfMonthNamed());
+
+ }
+
+ public function testRecurringWeeksOfYear(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([], $er->recurringWeeksOfYear());
+
+ /** test rrule recurrance with monthly days*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;INTERVAL=1;BYWEEKNO=35,42;BYDAY=TU');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([35,42], $er->recurringWeeksOfYear());
+
+ }
+
+ public function testRecurringMonthsOfYear(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([], $er->recurringMonthsOfYear());
+
+ /** test rrule recurrance with monthly days*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;INTERVAL=1;BYMONTH=7;BYMONTHDAY=1');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([7], $er->recurringMonthsOfYear());
+
+ }
+
+ public function testRecurringMonthsOfYearNamed(): void {
+
+ /** test no recurrance */
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals([], $er->recurringMonthsOfYearNamed());
+
+ /** test rrule recurrance with weekly days*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;INTERVAL=1;BYMONTH=7;BYMONTHDAY=1');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test set by constructor
+ $this->assertEquals(['July'], $er->recurringMonthsOfYearNamed());
+
+ }
+
+ public function testRecurringIterationDaily(): void {
+
+ /** test rrule recurrance with daily frequency*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=3;UNTIL=20240714T040000Z');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test initial recurrance
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240704T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240707T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240710T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240713T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance (This is past the last recurrance and should return null)
+ $er->recurrenceAdvance();
+ $this->assertNull($er->recurrenceDate());
+ // test rewind to initial recurrance
+ $er->recurrenceRewind();
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvanceTo((new \DateTime('20240709T080000')));
+ $this->assertEquals((new \DateTime('20240710T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+
+ }
+
+ public function testRecurringIterationWeekly(): void {
+
+ /** test rrule recurrance with weekly frequency*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20240713T040000Z');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test initial recurrance
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240703T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240705T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240708T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240710T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240712T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance (This is past the last recurrance and should return null)
+ $er->recurrenceAdvance();
+ $this->assertNull($er->recurrenceDate());
+ // test rewind to initial recurrance
+ $er->recurrenceRewind();
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvanceTo((new \DateTime('20240709T080000')));
+ $this->assertEquals((new \DateTime('20240710T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+
+ }
+
+ public function testRecurringIterationMonthlyAbsolute(): void {
+
+ /** test rrule recurrance with monthly absolute frequency on the 1st of each month*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;COUNT=3;BYMONTHDAY=1');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test initial recurrance
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240801T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240901T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance (This is past the last recurrance and should return null)
+ $er->recurrenceAdvance();
+ $this->assertNull($er->recurrenceDate());
+ // test rewind to initial recurrance
+ $er->recurrenceRewind();
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvanceTo((new \DateTime('20240809T080000')));
+ $this->assertEquals((new \DateTime('20240901T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+
+ }
+
+ public function testRecurringIterationMonthlyRelative(): void {
+
+ /** test rrule recurrance with monthly relative frequency on the first monday of each month*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;COUNT=3;BYDAY=MO;BYSETPOS=1');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test initial recurrance
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240805T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240902T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance (This is past the last recurrance and should return null)
+ $er->recurrenceAdvance();
+ $this->assertNull($er->recurrenceDate());
+ // test rewind to initial recurrance
+ $er->recurrenceRewind();
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvanceTo((new \DateTime('20240809T080000')));
+ $this->assertEquals((new \DateTime('20240902T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+
+ }
+
+ public function testRecurringIterationYearlyAbsolute(): void {
+
+ /** test rrule recurrance with yearly absolute frequency on the 1st of july*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;COUNT=3;BYMONTH=7');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test initial recurrance
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20250701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20260701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance (This is past the last recurrance and should return null)
+ $er->recurrenceAdvance();
+ $this->assertNull($er->recurrenceDate());
+ // test rewind to initial recurrance
+ $er->recurrenceRewind();
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvanceTo((new \DateTime('20250809T080000')));
+ $this->assertEquals((new \DateTime('20260701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+
+ }
+
+ public function testRecurringIterationYearlyRelative(): void {
+
+ /** test rrule recurrance with yearly relative frequency on the first monday of july*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;COUNT=3;BYMONTH=7;BYDAY=MO;BYSETPOS=1');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test initial recurrance
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20250707T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20260706T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance (This is past the last recurrance and should return null)
+ $er->recurrenceAdvance();
+ $this->assertNull($er->recurrenceDate());
+ // test rewind to initial recurrance
+ $er->recurrenceRewind();
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvanceTo((new \DateTime('20250809T080000')));
+ $this->assertEquals((new \DateTime('20260706T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+
+ }
+
+ public function testRecurringIterationFixed(): void {
+
+ /** test rrule recurrance with yearly relative frequency on the first monday of july*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703T080000,20240905T080000,20241231T080000');
+ // construct event reader
+ $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test initial recurrance
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240703T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20240905T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvance();
+ $this->assertEquals((new \DateTime('20241231T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance (This is past the last recurrance and should return null)
+ $er->recurrenceAdvance();
+ $this->assertNull($er->recurrenceDate());
+ // test rewind to initial recurrance
+ $er->recurrenceRewind();
+ $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+ // test next recurrance
+ $er->recurrenceAdvanceTo((new \DateTime('20240809T080000')));
+ $this->assertEquals((new \DateTime('20240905T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate());
+
+ }
+
+}
diff --git a/apps/dav/tests/unit/CalDAV/Export/ExportServiceTest.php b/apps/dav/tests/unit/CalDAV/Export/ExportServiceTest.php
new file mode 100644
index 00000000000..838dfc18f2f
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/Export/ExportServiceTest.php
@@ -0,0 +1,81 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\Tests\unit\CalDAV\Export;
+
+use Generator;
+use OCA\DAV\CalDAV\Export\ExportService;
+use OCP\Calendar\CalendarExportOptions;
+use OCP\Calendar\ICalendarExport;
+use OCP\ServerVersion;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\VObject\Component\VCalendar;
+
+class ExportServiceTest extends \Test\TestCase {
+ private ServerVersion&MockObject $serverVersion;
+ private ExportService $service;
+ private ICalendarExport&MockObject $calendar;
+ private array $mockExportCollection;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->serverVersion = $this->createMock(ServerVersion::class);
+ $this->serverVersion->method('getVersionString')
+ ->willReturn('32.0.0.0');
+ $this->service = new ExportService($this->serverVersion);
+ $this->calendar = $this->createMock(ICalendarExport::class);
+
+ }
+
+ protected function mockGenerator(): Generator {
+ foreach ($this->mockExportCollection as $entry) {
+ yield $entry;
+ }
+ }
+
+ public function testExport(): void {
+ // Arrange
+ // construct calendar with a 1 hour event and same start/end time zones
+ $vCalendar = new VCalendar();
+ /** @var \Sabre\VObject\Component\VEvent $vEvent */
+ $vEvent = $vCalendar->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('SUMMARY', 'Test Recurrence Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ // construct calendar return
+ $options = new CalendarExportOptions();
+ $this->mockExportCollection[] = $vCalendar;
+ $this->calendar->expects($this->once())
+ ->method('export')
+ ->with($options)
+ ->willReturn($this->mockGenerator());
+
+ // Act
+ $document = '';
+ foreach ($this->service->export($this->calendar, $options) as $chunk) {
+ $document .= $chunk;
+ }
+
+ // Assert
+ $this->assertStringContainsString('BEGIN:VCALENDAR', $document, 'Exported document calendar start missing');
+ $this->assertStringContainsString('BEGIN:VEVENT', $document, 'Exported document event start missing');
+ $this->assertStringContainsString('END:VEVENT', $document, 'Exported document event end missing');
+ $this->assertStringContainsString('END:VCALENDAR', $document, 'Exported document calendar end missing');
+
+ }
+
+}
diff --git a/apps/dav/tests/unit/CalDAV/Integration/ExternalCalendarTest.php b/apps/dav/tests/unit/CalDAV/Integration/ExternalCalendarTest.php
index 778df5697f0..b2f479ac0e3 100644
--- a/apps/dav/tests/unit/CalDAV/Integration/ExternalCalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/Integration/ExternalCalendarTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -6,16 +8,17 @@
namespace OCA\DAV\Tests\unit\CalDAV\Integration;
use OCA\DAV\CalDAV\Integration\ExternalCalendar;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ExternalCalendarTest extends TestCase {
- private $abstractExternalCalendar;
+ private ExternalCalendar&MockObject $abstractExternalCalendar;
protected function setUp(): void {
parent::setUp();
- $this->abstractExternalCalendar =
- $this->getMockForAbstractClass(ExternalCalendar::class, ['example-app-id', 'calendar-uri-in-backend']);
+ $this->abstractExternalCalendar
+ = $this->getMockForAbstractClass(ExternalCalendar::class, ['example-app-id', 'calendar-uri-in-backend']);
}
public function testGetName():void {
@@ -39,7 +42,7 @@ class ExternalCalendarTest extends TestCase {
$this->abstractExternalCalendar->setName('other-name');
}
- public function createDirectory():void {
+ public function createDirectory(): void {
// Check that the method is final and can't be overridden by other classes
$reflectionMethod = new \ReflectionMethod(ExternalCalendar::class, 'createDirectory');
$this->assertTrue($reflectionMethod->isFinal());
@@ -63,9 +66,7 @@ class ExternalCalendarTest extends TestCase {
$this->assertTrue(ExternalCalendar::isAppGeneratedCalendar('app-generated--example--foo--2'));
}
- /**
- * @dataProvider splitAppGeneratedCalendarUriDataProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('splitAppGeneratedCalendarUriDataProvider')]
public function testSplitAppGeneratedCalendarUriInvalid(string $name):void {
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Provided calendar uri was not app-generated');
@@ -73,7 +74,7 @@ class ExternalCalendarTest extends TestCase {
ExternalCalendar::splitAppGeneratedCalendarUri($name);
}
- public function splitAppGeneratedCalendarUriDataProvider():array {
+ public static function splitAppGeneratedCalendarUriDataProvider():array {
return [
['personal'],
['foo_shared_by_admin'],
diff --git a/apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php b/apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php
index b55359cd208..3ba0b832593 100644
--- a/apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php
+++ b/apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -15,20 +17,11 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class CalendarPublicationListenerTest extends TestCase {
-
- /** @var Backend|MockObject */
- private $activityBackend;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
-
+ private Backend&MockObject $activityBackend;
+ private LoggerInterface&MockObject $logger;
private CalendarPublicationListener $calendarPublicationListener;
-
- /** @var CalendarPublishedEvent|MockObject */
- private $publicationEvent;
-
- /** @var CalendarUnpublishedEvent|MockObject */
- private $unpublicationEvent;
+ private CalendarPublishedEvent&MockObject $publicationEvent;
+ private CalendarUnpublishedEvent&MockObject $unpublicationEvent;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php b/apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php
index b8414ecd695..d5697a862db 100644
--- a/apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php
+++ b/apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -14,17 +16,10 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class CalendarShareUpdateListenerTest extends TestCase {
-
- /** @var Backend|MockObject */
- private $activityBackend;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
-
+ private Backend&MockObject $activityBackend;
+ private LoggerInterface&MockObject $logger;
private CalendarShareUpdateListener $calendarPublicationListener;
-
- /** @var CalendarShareUpdatedEvent|MockObject */
- private $event;
+ private CalendarShareUpdatedEvent&MockObject $event;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php b/apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php
index 589e659b9ea..cbfdfd6b9b7 100644
--- a/apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php
+++ b/apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -18,26 +20,13 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class SubscriptionListenerTest extends TestCase {
-
- /** @var RefreshWebcalService|MockObject */
- private $refreshWebcalService;
-
- /** @var Backend|MockObject */
- private $reminderBackend;
-
- /** @var IJobList|MockObject */
- private $jobList;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
-
+ private RefreshWebcalService&MockObject $refreshWebcalService;
+ private Backend&MockObject $reminderBackend;
+ private IJobList&MockObject $jobList;
+ private LoggerInterface&MockObject $logger;
private SubscriptionListener $calendarPublicationListener;
-
- /** @var SubscriptionCreatedEvent|MockObject */
- private $subscriptionCreatedEvent;
-
- /** @var SubscriptionDeletedEvent|MockObject */
- private $subscriptionDeletedEvent;
+ private SubscriptionCreatedEvent&MockObject $subscriptionCreatedEvent;
+ private SubscriptionDeletedEvent&MockObject $subscriptionDeletedEvent;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/OutboxTest.php b/apps/dav/tests/unit/CalDAV/OutboxTest.php
index def2bd80157..cc0a3f0405f 100644
--- a/apps/dav/tests/unit/CalDAV/OutboxTest.php
+++ b/apps/dav/tests/unit/CalDAV/OutboxTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,15 +9,12 @@ namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\CalDAV\Outbox;
use OCP\IConfig;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class OutboxTest extends TestCase {
-
- /** @var IConfig */
- private $config;
-
- /** @var Outbox */
- private $outbox;
+ private IConfig&MockObject $config;
+ private Outbox $outbox;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/PluginTest.php b/apps/dav/tests/unit/CalDAV/PluginTest.php
index 0915fdf2646..c5725a1fa81 100644
--- a/apps/dav/tests/unit/CalDAV/PluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/PluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -9,8 +11,7 @@ use OCA\DAV\CalDAV\Plugin;
use Test\TestCase;
class PluginTest extends TestCase {
- /** @var Plugin */
- private $plugin;
+ private Plugin $plugin;
protected function setUp(): void {
parent::setUp();
@@ -18,7 +19,7 @@ class PluginTest extends TestCase {
$this->plugin = new Plugin();
}
- public function linkProvider() {
+ public static function linkProvider(): array {
return [
[
'principals/users/MyUserName',
@@ -35,13 +36,8 @@ class PluginTest extends TestCase {
];
}
- /**
- * @dataProvider linkProvider
- *
- * @param $input
- * @param $expected
- */
- public function testGetCalendarHomeForPrincipal($input, $expected): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('linkProvider')]
+ public function testGetCalendarHomeForPrincipal(string $input, string $expected): void {
$this->assertSame($expected, $this->plugin->getCalendarHomeForPrincipal($input));
}
diff --git a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
index 4333754222b..6acceed6f64 100644
--- a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
+++ b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -12,10 +14,13 @@ use OCA\DAV\CalDAV\PublicCalendarRoot;
use OCA\DAV\Connector\Sabre\Principal;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
+use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IUserManager;
use OCP\Security\ISecureRandom;
+use OCP\Server;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Test\TestCase;
@@ -28,34 +33,24 @@ use Test\TestCase;
*/
class PublicCalendarRootTest extends TestCase {
public const UNIT_TEST_USER = '';
- /** @var CalDavBackend */
- private $backend;
- /** @var PublicCalendarRoot */
- private $publicCalendarRoot;
- /** @var IL10N */
- private $l10n;
- /** @var Principal|\PHPUnit\Framework\MockObject\MockObject */
- private $principal;
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $userManager;
- /** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $groupManager;
- /** @var IConfig */
- protected $config;
-
- /** @var ISecureRandom */
- private $random;
- /** @var LoggerInterface */
- private $logger;
+ private CalDavBackend $backend;
+ private PublicCalendarRoot $publicCalendarRoot;
+ private IL10N&MockObject $l10n;
+ private Principal&MockObject $principal;
+ protected IUserManager&MockObject $userManager;
+ protected IGroupManager&MockObject $groupManager;
+ protected IConfig&MockObject $config;
+ private ISecureRandom $random;
+ private LoggerInterface&MockObject $logger;
protected function setUp(): void {
parent::setUp();
- $db = \OC::$server->getDatabaseConnection();
+ $db = Server::get(IDBConnection::class);
$this->principal = $this->createMock('OCA\DAV\Connector\Sabre\Principal');
$this->userManager = $this->createMock(IUserManager::class);
$this->groupManager = $this->createMock(IGroupManager::class);
- $this->random = \OC::$server->getSecureRandom();
+ $this->random = Server::get(ISecureRandom::class);
$this->logger = $this->createMock(LoggerInterface::class);
$dispatcher = $this->createMock(IEventDispatcher::class);
$config = $this->createMock(IConfig::class);
@@ -80,8 +75,7 @@ class PublicCalendarRootTest extends TestCase {
$sharingBackend,
false,
);
- $this->l10n = $this->getMockBuilder(IL10N::class)
- ->disableOriginalConstructor()->getMock();
+ $this->l10n = $this->createMock(IL10N::class);
$this->config = $this->createMock(IConfig::class);
$this->publicCalendarRoot = new PublicCalendarRoot($this->backend,
@@ -132,10 +126,7 @@ class PublicCalendarRootTest extends TestCase {
$this->assertSame([], $calendarResults);
}
- /**
- * @return Calendar
- */
- protected function createPublicCalendar() {
+ protected function createPublicCalendar(): Calendar {
$this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []);
$calendarInfo = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0];
diff --git a/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php b/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php
index 04b99b70124..98153a067fb 100644
--- a/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -14,17 +16,13 @@ use Sabre\VObject\Reader;
class PublicCalendarTest extends CalendarTest {
- /**
- * @dataProvider providesConfidentialClassificationData
- * @param int $expectedChildren
- * @param bool $isShared
- */
- public function testPrivateClassification($expectedChildren, $isShared): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesConfidentialClassificationData')]
+ public function testPrivateClassification(int $expectedChildren, bool $isShared): void {
$calObject0 = ['uri' => 'event-0', 'classification' => CalDavBackend::CLASSIFICATION_PUBLIC];
$calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL];
$calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
- /** @var MockObject | CalDavBackend $backend */
+ /** @var CalDavBackend&MockObject $backend */
$backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
$backend->expects($this->any())->method('getCalendarObjects')->willReturn([
$calObject0, $calObject1, $calObject2
@@ -44,9 +42,9 @@ class PublicCalendarTest extends CalendarTest {
'id' => 666,
'uri' => 'cal',
];
- /** @var MockObject | IConfig $config */
+ /** @var IConfig&MockObject $config */
$config = $this->createMock(IConfig::class);
- /** @var MockObject | LoggerInterface $logger */
+ /** @var LoggerInterface&MockObject $logger */
$logger = $this->createMock(LoggerInterface::class);
$c = new PublicCalendar($backend, $calendarInfo, $this->l10n, $config, $logger);
$children = $c->getChildren();
@@ -57,12 +55,8 @@ class PublicCalendarTest extends CalendarTest {
$this->assertFalse($c->childExists('event-2'));
}
- /**
- * @dataProvider providesConfidentialClassificationData
- * @param int $expectedChildren
- * @param bool $isShared
- */
- public function testConfidentialClassification($expectedChildren, $isShared): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesConfidentialClassificationData')]
+ public function testConfidentialClassification(int $expectedChildren, bool $isShared): void {
$start = '20160609';
$end = '20160610';
@@ -112,7 +106,7 @@ EOD;
$calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL, 'calendardata' => $calData];
$calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
- /** @var MockObject | CalDavBackend $backend */
+ /** @var CalDavBackend&MockObject $backend */
$backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
$backend->expects($this->any())->method('getCalendarObjects')->willReturn([
$calObject0, $calObject1, $calObject2
@@ -132,9 +126,9 @@ EOD;
'id' => 666,
'uri' => 'cal',
];
- /** @var MockObject | IConfig $config */
+ /** @var IConfig&MockObject $config */
$config = $this->createMock(IConfig::class);
- /** @var MockObject | LoggerInterface $logger */
+ /** @var LoggerInterface&MockObject $logger */
$logger = $this->createMock(LoggerInterface::class);
$c = new PublicCalendar($backend, $calendarInfo, $this->l10n, $config, $logger);
diff --git a/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php b/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php
index 769e1537646..5344ec5d7cd 100644
--- a/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php
+++ b/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -43,9 +45,9 @@ class PublisherTest extends TestCase {
}
- protected $elementMap = [];
- protected $namespaceMap = ['DAV:' => 'd'];
- protected $contextUri = '/';
+ protected array $elementMap = [];
+ protected array $namespaceMap = ['DAV:' => 'd'];
+ protected string $contextUri = '/';
private function write($input) {
$writer = new Writer();
diff --git a/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php b/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php
index 8aecdf7f0dd..ec2ae37a929 100644
--- a/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php
+++ b/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -10,6 +12,7 @@ use OCA\DAV\CalDAV\Publishing\PublishPlugin;
use OCP\IConfig;
use OCP\IRequest;
use OCP\IURLGenerator;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Server;
use Sabre\DAV\SimpleCollection;
use Sabre\HTTP\Request;
@@ -17,31 +20,21 @@ use Sabre\HTTP\Response;
use Test\TestCase;
class PublishingTest extends TestCase {
-
- /** @var PublishPlugin */
- private $plugin;
- /** @var Server */
- private $server;
- /** @var Calendar | \PHPUnit\Framework\MockObject\MockObject */
- private $book;
- /** @var IConfig | \PHPUnit\Framework\MockObject\MockObject */
- private $config;
- /** @var IURLGenerator | \PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
+ private PublishPlugin $plugin;
+ private Server $server;
+ private Calendar&MockObject $book;
+ private IConfig&MockObject $config;
+ private IURLGenerator&MockObject $urlGenerator;
protected function setUp(): void {
parent::setUp();
- $this->config = $this->getMockBuilder(IConfig::class)->
- disableOriginalConstructor()->
- getMock();
+ $this->config = $this->createMock(IConfig::class);
$this->config->expects($this->any())->method('getSystemValue')
->with($this->equalTo('secret'))
->willReturn('mysecret');
- $this->urlGenerator = $this->getMockBuilder(IURLGenerator::class)->
- disableOriginalConstructor()->
- getMock();
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
/** @var IRequest $request */
$this->plugin = new PublishPlugin($this->config, $this->urlGenerator);
@@ -49,9 +42,9 @@ class PublishingTest extends TestCase {
$root = new SimpleCollection('calendars');
$this->server = new Server($root);
/** @var SimpleCollection $node */
- $this->book = $this->getMockBuilder(Calendar::class)->
- disableOriginalConstructor()->
- getMock();
+ $this->book = $this->getMockBuilder(Calendar::class)
+ ->disableOriginalConstructor()
+ ->getMock();
$this->book->method('getName')->willReturn('cal1');
$root->addChild($this->book);
$this->plugin->initialize($this->server);
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php b/apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php
index ffba1a2fc96..356acf2dd7f 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php
@@ -10,27 +10,20 @@ namespace OCA\DAV\Tests\unit\CalDAV\Reminder;
use OCA\DAV\CalDAV\Reminder\Backend as ReminderBackend;
use OCP\AppFramework\Utility\ITimeFactory;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class BackendTest extends TestCase {
-
- /**
- * Reminder Backend
- *
- * @var ReminderBackend|\PHPUnit\Framework\MockObject\MockObject
- */
- private $reminderBackend;
-
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
+ private ReminderBackend $reminderBackend;
+ private ITimeFactory&MockObject $timeFactory;
protected function setUp(): void {
parent::setUp();
$query = self::$realDatabase->getQueryBuilder();
- $query->delete('calendar_reminders')->execute();
- $query->delete('calendarobjects')->execute();
- $query->delete('calendars')->execute();
+ $query->delete('calendar_reminders')->executeStatement();
+ $query->delete('calendarobjects')->executeStatement();
+ $query->delete('calendars')->executeStatement();
$this->timeFactory = $this->createMock(ITimeFactory::class);
$this->reminderBackend = new ReminderBackend(self::$realDatabase, $this->timeFactory);
@@ -40,9 +33,11 @@ class BackendTest extends TestCase {
protected function tearDown(): void {
$query = self::$realDatabase->getQueryBuilder();
- $query->delete('calendar_reminders')->execute();
- $query->delete('calendarobjects')->execute();
- $query->delete('calendars')->execute();
+ $query->delete('calendar_reminders')->executeStatement();
+ $query->delete('calendarobjects')->executeStatement();
+ $query->delete('calendars')->executeStatement();
+
+ parent::tearDown();
}
@@ -95,7 +90,7 @@ class BackendTest extends TestCase {
$this->assertCount(4, $rows);
- $this->reminderBackend->removeReminder((int) $rows[3]['id']);
+ $this->reminderBackend->removeReminder((int)$rows[3]['id']);
$query = self::$realDatabase->getQueryBuilder();
$rows = $query->select('*')
@@ -118,7 +113,7 @@ class BackendTest extends TestCase {
unset($rows[0]['id']);
unset($rows[1]['id']);
- $this->assertEquals($rows[0], [
+ $expected1 = [
'calendar_id' => 1,
'object_id' => 1,
'uid' => 'asd',
@@ -134,8 +129,8 @@ class BackendTest extends TestCase {
'calendardata' => 'Calendar data 123',
'displayname' => 'Displayname 123',
'principaluri' => 'principals/users/user001',
- ]);
- $this->assertEquals($rows[1], [
+ ];
+ $expected2 = [
'calendar_id' => 1,
'object_id' => 1,
'uid' => 'asd',
@@ -151,7 +146,9 @@ class BackendTest extends TestCase {
'calendardata' => 'Calendar data 123',
'displayname' => 'Displayname 123',
'principaluri' => 'principals/users/user001',
- ]);
+ ];
+
+ $this->assertEqualsCanonicalizing([$rows[0],$rows[1]], [$expected1,$expected2]);
}
public function testGetAllScheduledRemindersForEvent(): void {
@@ -233,14 +230,14 @@ class BackendTest extends TestCase {
$query = self::$realDatabase->getQueryBuilder();
$rows = $query->select('*')
->from('calendar_reminders')
- ->execute()
+ ->executeQuery()
->fetchAll();
$this->assertCount(4, $rows);
$this->assertEquals($rows[3]['notification_date'], 123600);
- $reminderId = (int) $rows[3]['id'];
+ $reminderId = (int)$rows[3]['id'];
$newNotificationDate = 123700;
$this->reminderBackend->updateReminder($reminderId, $newNotificationDate);
@@ -249,10 +246,10 @@ class BackendTest extends TestCase {
$row = $query->select('notification_date')
->from('calendar_reminders')
->where($query->expr()->eq('id', $query->createNamedParameter($reminderId)))
- ->execute()
+ ->executeQuery()
->fetch();
- $this->assertEquals((int) $row['notification_date'], 123700);
+ $this->assertEquals((int)$row['notification_date'], 123700);
}
@@ -264,7 +261,7 @@ class BackendTest extends TestCase {
'principaluri' => $query->createNamedParameter('principals/users/user001'),
'displayname' => $query->createNamedParameter('Displayname 123'),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendars')
@@ -273,7 +270,7 @@ class BackendTest extends TestCase {
'principaluri' => $query->createNamedParameter('principals/users/user002'),
'displayname' => $query->createNamedParameter('Displayname 99'),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendarobjects')
@@ -283,7 +280,7 @@ class BackendTest extends TestCase {
'calendarid' => $query->createNamedParameter(1),
'size' => $query->createNamedParameter(42),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendarobjects')
@@ -293,7 +290,7 @@ class BackendTest extends TestCase {
'calendarid' => $query->createNamedParameter(1),
'size' => $query->createNamedParameter(42),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendarobjects')
@@ -303,7 +300,7 @@ class BackendTest extends TestCase {
'calendarid' => $query->createNamedParameter(99),
'size' => $query->createNamedParameter(42),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendar_reminders')
@@ -321,7 +318,7 @@ class BackendTest extends TestCase {
'notification_date' => $query->createNamedParameter(123456),
'is_repeat_based' => $query->createNamedParameter(0),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendar_reminders')
@@ -339,7 +336,7 @@ class BackendTest extends TestCase {
'notification_date' => $query->createNamedParameter(123456),
'is_repeat_based' => $query->createNamedParameter(0),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendar_reminders')
@@ -357,7 +354,7 @@ class BackendTest extends TestCase {
'notification_date' => $query->createNamedParameter(123499),
'is_repeat_based' => $query->createNamedParameter(0),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendar_reminders')
@@ -375,6 +372,6 @@ class BackendTest extends TestCase {
'notification_date' => $query->createNamedParameter(123600),
'is_repeat_based' => $query->createNamedParameter(0),
])
- ->execute();
+ ->executeStatement();
}
}
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/AbstractNotificationProviderTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/AbstractNotificationProviderTestCase.php
index 60ef1df43d5..70b374298ea 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/AbstractNotificationProviderTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/AbstractNotificationProviderTestCase.php
@@ -14,44 +14,21 @@ use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\L10N\IFactory as L10NFactory;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\VObject\Component\VCalendar;
use Test\TestCase;
-abstract class AbstractNotificationProviderTest extends TestCase {
-
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $logger;
-
- /** @var L10NFactory|\PHPUnit\Framework\MockObject\MockObject */
- protected $l10nFactory;
-
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
- protected $l10n;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- protected $urlGenerator;
-
- /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
- protected $config;
-
- /** @var AbstractProvider|\PHPUnit\Framework\MockObject\MockObject */
- protected $provider;
-
- /**
- * @var VCalendar
- */
- protected $vcalendar;
-
- /**
- * @var string
- */
- protected $calendarDisplayName;
-
- /**
- * @var IUser|\PHPUnit\Framework\MockObject\MockObject
- */
- protected $user;
+abstract class AbstractNotificationProviderTestCase extends TestCase {
+ protected LoggerInterface&MockObject $logger;
+ protected L10NFactory&MockObject $l10nFactory;
+ protected IL10N&MockObject $l10n;
+ protected IURLGenerator&MockObject $urlGenerator;
+ protected IConfig&MockObject $config;
+ protected AbstractProvider $provider;
+ protected VCalendar $vcalendar;
+ protected string $calendarDisplayName;
+ protected IUser&MockObject $user;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php
index 708581f9b6d..f7fbac2c407 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php
@@ -14,14 +14,13 @@ use OCP\IUser;
use OCP\Mail\IEMailTemplate;
use OCP\Mail\IMailer;
use OCP\Mail\IMessage;
+use OCP\Util;
use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Component\VCalendar;
-class EmailProviderTest extends AbstractNotificationProviderTest {
+class EmailProviderTest extends AbstractNotificationProviderTestCase {
public const USER_EMAIL = 'frodo@hobb.it';
-
- /** @var IMailer|MockObject */
- private $mailer;
+ private IMailer&MockObject $mailer;
protected function setUp(): void {
parent::setUp();
@@ -96,18 +95,12 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
$this->mailer->expects($this->exactly(4))
->method('validateMailAddress')
- ->withConsecutive(
- ['uid1@example.com'],
- ['uid2@example.com'],
- ['uid3@example.com'],
- ['invalid'],
- )
- ->willReturnOnConsecutiveCalls(
- true,
- true,
- true,
- false,
- );
+ ->willReturnMap([
+ ['uid1@example.com', true],
+ ['uid2@example.com', true],
+ ['uid3@example.com', true],
+ ['invalid', false],
+ ]);
$this->mailer->expects($this->exactly(3))
->method('createMessage')
@@ -118,14 +111,18 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
$message22
);
- $this->mailer->expects($this->exactly(3))
+ $calls = [
+ [$message11],
+ [$message21],
+ [$message22],
+ ];
+ $this->mailer->expects($this->exactly(count($calls)))
->method('send')
- ->withConsecutive(
- [$message11],
- [$message21],
- [$message22],
- )
- ->willReturn([]);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return [];
+ });
$this->setupURLGeneratorMock(2);
@@ -214,16 +211,22 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
$message22,
$message23,
);
- $this->mailer->expects($this->exactly(6))
+
+ $calls = [
+ [$message11],
+ [$message12],
+ [$message13],
+ [$message21],
+ [$message22],
+ [$message23],
+ ];
+ $this->mailer->expects($this->exactly(count($calls)))
->method('send')
- ->withConsecutive(
- [$message11],
- [$message12],
- [$message13],
- [$message21],
- [$message22],
- [$message23],
- )->willReturn([]);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return [];
+ });
$this->setupURLGeneratorMock(2);
$vcalendar = $this->getAttendeeVCalendar();
@@ -292,12 +295,18 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
$message12,
$message13,
);
- $this->mailer->expects($this->exactly(2))
+
+ $calls = [
+ [$message12],
+ [$message13],
+ ];
+ $this->mailer->expects($this->exactly(count($calls)))
->method('send')
- ->withConsecutive(
- [$message12],
- [$message13],
- )->willReturn([]);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return [];
+ });
$this->setupURLGeneratorMock(1);
$vcalendar = $this->getAttendeeVCalendar();
@@ -350,7 +359,7 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
$message->expects($this->once())
->method('setFrom')
- ->with([\OCP\Util::getDefaultEmailAddress('reminders-noreply')])
+ ->with([Util::getDefaultEmailAddress('reminders-noreply')])
->willReturn($message);
if ($replyTo) {
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php
index b090fa0e5e7..5034af49cae 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php
@@ -13,13 +13,11 @@ use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IUser;
use OCP\Notification\IManager;
use OCP\Notification\INotification;
+use PHPUnit\Framework\MockObject\MockObject;
-class PushProviderTest extends AbstractNotificationProviderTest {
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- private $manager;
-
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
+class PushProviderTest extends AbstractNotificationProviderTestCase {
+ private IManager&MockObject $manager;
+ private ITimeFactory&MockObject $timeFactory;
protected function setUp(): void {
parent::setUp();
@@ -96,20 +94,23 @@ class PushProviderTest extends AbstractNotificationProviderTest {
$this->manager->expects($this->exactly(3))
->method('createNotification')
- ->with()
->willReturnOnConsecutiveCalls(
$notification1,
$notification2,
$notification3
);
+ $calls = [
+ $notification1,
+ $notification2,
+ $notification3,
+ ];
$this->manager->expects($this->exactly(3))
->method('notify')
- ->withConsecutive(
- [$notification1],
- [$notification2],
- [$notification3],
- );
+ ->willReturnCallback(function ($notification) use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, $notification);
+ });
$this->provider->send($this->vcalendar->VEVENT, $this->calendarDisplayName, [], $users);
}
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProviderManagerTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProviderManagerTest.php
index 98d49552b02..6b813ed0228 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProviderManagerTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProviderManagerTest.php
@@ -14,15 +14,17 @@ use OCA\DAV\CalDAV\Reminder\NotificationProvider\PushProvider;
use OCA\DAV\CalDAV\Reminder\NotificationProviderManager;
use OCA\DAV\CalDAV\Reminder\NotificationTypeDoesNotExistException;
use OCA\DAV\Capabilities;
+use OCP\AppFramework\QueryException;
use Test\TestCase;
+/**
+ * @group DB
+ */
class NotificationProviderManagerTest extends TestCase {
-
- /** @var NotificationProviderManager|\PHPUnit\Framework\MockObject\MockObject */
- private $providerManager;
+ private NotificationProviderManager $providerManager;
/**
- * @throws \OCP\AppFramework\QueryException
+ * @throws QueryException
*/
protected function setUp(): void {
parent::setUp();
@@ -36,7 +38,7 @@ class NotificationProviderManagerTest extends TestCase {
* @throws NotificationTypeDoesNotExistException
*/
public function testGetProviderForUnknownType(): void {
- $this->expectException(\OCA\DAV\CalDAV\Reminder\NotificationTypeDoesNotExistException::class);
+ $this->expectException(NotificationTypeDoesNotExistException::class);
$this->expectExceptionMessage('Type NOT EXISTENT is not an accepted type of notification');
$this->providerManager->getProvider('NOT EXISTENT');
@@ -47,7 +49,7 @@ class NotificationProviderManagerTest extends TestCase {
* @throws ProviderNotAvailableException
*/
public function testGetProviderForUnRegisteredType(): void {
- $this->expectException(\OCA\DAV\CalDAV\Reminder\NotificationProvider\ProviderNotAvailableException::class);
+ $this->expectException(ProviderNotAvailableException::class);
$this->expectExceptionMessage('No notification provider for type AUDIO available');
$this->providerManager->getProvider('AUDIO');
@@ -65,7 +67,7 @@ class NotificationProviderManagerTest extends TestCase {
}
/**
- * @throws \OCP\AppFramework\QueryException
+ * @throws QueryException
*/
public function testRegisterBadProvider(): void {
$this->expectException(\InvalidArgumentException::class);
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotifierTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotifierTest.php
index 6f319766d21..c091f590711 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotifierTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotifierTest.php
@@ -16,24 +16,16 @@ use OCP\IURLGenerator;
use OCP\L10N\IFactory;
use OCP\Notification\AlreadyProcessedException;
use OCP\Notification\INotification;
+use OCP\Notification\UnknownNotificationException;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class NotifierTest extends TestCase {
- /** @var Notifier */
- protected $notifier;
-
- /** @var IFactory|MockObject */
- protected $factory;
-
- /** @var IURLGenerator|MockObject */
- protected $urlGenerator;
-
- /** @var IL10N|MockObject */
- protected $l10n;
-
- /** @var ITimeFactory|MockObject */
- protected $timeFactory;
+ protected IFactory&MockObject $factory;
+ protected IURLGenerator&MockObject $urlGenerator;
+ protected IL10N&MockObject $l10n;
+ protected ITimeFactory&MockObject $timeFactory;
+ protected Notifier $notifier;
protected function setUp(): void {
parent::setUp();
@@ -88,10 +80,10 @@ class NotifierTest extends TestCase {
public function testPrepareWrongApp(): void {
- $this->expectException(\InvalidArgumentException::class);
+ $this->expectException(UnknownNotificationException::class);
$this->expectExceptionMessage('Notification not from this app');
- /** @var INotification|MockObject $notification */
+ /** @var INotification&MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
@@ -105,10 +97,10 @@ class NotifierTest extends TestCase {
public function testPrepareWrongSubject(): void {
- $this->expectException(\InvalidArgumentException::class);
+ $this->expectException(UnknownNotificationException::class);
$this->expectExceptionMessage('Unknown subject');
- /** @var INotification|MockObject $notification */
+ /** @var INotification&MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
@@ -129,7 +121,7 @@ class NotifierTest extends TestCase {
return $d1->diff($d2)->y < 0;
}
- public function dataPrepare(): array {
+ public static function dataPrepare(): array {
return [
[
'calendar_reminder',
@@ -178,18 +170,9 @@ class NotifierTest extends TestCase {
];
}
- /**
- * @dataProvider dataPrepare
- *
- * @param string $subjectType
- * @param array $subjectParams
- * @param string $subject
- * @param array $messageParams
- * @param string $message
- * @throws \Exception
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataPrepare')]
public function testPrepare(string $subjectType, array $subjectParams, string $subject, array $messageParams, string $message): void {
- /** @var INotification|MockObject $notification */
+ /** @var INotification&MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
@@ -234,7 +217,7 @@ class NotifierTest extends TestCase {
}
public function testPassedEvent(): void {
- /** @var INotification|MockObject $notification */
+ /** @var INotification&MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php b/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php
index 593131ba5dd..c18901c5f58 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php
@@ -26,35 +26,16 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class ReminderServiceTest extends TestCase {
- /** @var Backend|MockObject */
- private $backend;
-
- /** @var NotificationProviderManager|MockObject */
- private $notificationProviderManager;
-
- /** @var IUserManager|MockObject */
- private $userManager;
-
- /** @var IGroupManager|MockObject*/
- private $groupManager;
-
- /** @var CalDavBackend|MockObject */
- private $caldavBackend;
-
- /** @var ITimeFactory|MockObject */
- private $timeFactory;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var ReminderService */
- private $reminderService;
-
- /** @var MockObject|LoggerInterface */
- private $logger;
-
- /** @var MockObject|Principal */
- private $principalConnector;
+ private Backend&MockObject $backend;
+ private NotificationProviderManager&MockObject $notificationProviderManager;
+ private IUserManager&MockObject $userManager;
+ private IGroupManager&MockObject $groupManager;
+ private CalDavBackend&MockObject $caldavBackend;
+ private ITimeFactory&MockObject $timeFactory;
+ private IConfig&MockObject $config;
+ private LoggerInterface&MockObject $logger;
+ private Principal&MockObject $principalConnector;
+ private ReminderService $reminderService;
public const CALENDAR_DATA = <<<EOD
BEGIN:VCALENDAR
@@ -252,9 +233,7 @@ END:VTIMEZONE
END:VCALENDAR
ICS;
-
- /** @var null|string */
- private $oldTimezone;
+ private ?string $oldTimezone;
protected function setUp(): void {
parent::setUp();
@@ -305,13 +284,17 @@ ICS;
'component' => 'vevent',
];
- $this->backend->expects($this->exactly(2))
+ $calls = [
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1465429500, false],
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', '35b3eae8e792aa2209f0b4e1a302f105', 'DISPLAY', false, 1465344000, false]
+ ];
+ $this->backend->expects($this->exactly(count($calls)))
->method('insertReminder')
- ->withConsecutive(
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1465429500, false],
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', '35b3eae8e792aa2209f0b4e1a302f105', 'DISPLAY', false, 1465344000, false]
- )
- ->willReturn(1);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return 1;
+ });
$this->timeFactory->expects($this->once())
->method('getDateTime')
@@ -353,12 +336,7 @@ EOD;
];
$this->backend->expects($this->never())
- ->method('insertReminder')
- ->withConsecutive(
- [1337, 42, 'wej2z68l9h', false, null, false, '5c70531aab15c92b52518ae10a2f78a4', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1465429500, false],
- [1337, 42, 'wej2z68l9h', false, null, false, '5c70531aab15c92b52518ae10a2f78a4', '35b3eae8e792aa2209f0b4e1a302f105', 'DISPLAY', false, 1465344000, false]
- )
- ->willReturn(1);
+ ->method('insertReminder');
$this->reminderService->onCalendarObjectCreate($objectData);
}
@@ -371,16 +349,20 @@ EOD;
'component' => 'vevent',
];
- $this->backend->expects($this->exactly(5))
+ $calls = [
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429500, false],
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429620, true],
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429740, true],
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429860, true],
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429980, true]
+ ];
+ $this->backend->expects($this->exactly(count($calls)))
->method('insertReminder')
- ->withConsecutive(
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429500, false],
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429620, true],
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429740, true],
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429860, true],
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429980, true]
- )
- ->willReturn(1);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return 1;
+ });
$this->timeFactory->expects($this->once())
->method('getDateTime')
@@ -398,13 +380,17 @@ EOD;
'component' => 'vevent',
];
- $this->backend->expects($this->exactly(2))
+ $calls = [
+ [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1467243900, false],
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467158400, false]
+ ];
+ $this->backend->expects($this->exactly(count($calls)))
->method('insertReminder')
- ->withConsecutive(
- [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1467243900, false],
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467158400, false]
- )
- ->willReturn(1);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return 1;
+ });
$this->timeFactory->expects($this->once())
->method('getDateTime')
@@ -427,7 +413,7 @@ EOD;
$this->reminderService->onCalendarObjectCreate($objectData);
}
- public function testOnCalendarObjectCreateAllDayWithoutTimezone(): void {
+ public function testOnCalendarObjectCreateAllDayWithNullTimezone(): void {
$objectData = [
'calendardata' => self::CALENDAR_DATA_ALL_DAY,
'id' => '42',
@@ -454,6 +440,33 @@ EOD;
$this->reminderService->onCalendarObjectCreate($objectData);
}
+ public function testOnCalendarObjectCreateAllDayWithBlankTimezone(): void {
+ $objectData = [
+ 'calendardata' => self::CALENDAR_DATA_ALL_DAY,
+ 'id' => '42',
+ 'calendarid' => '1337',
+ 'component' => 'vevent',
+ ];
+ $this->timeFactory->expects($this->once())
+ ->method('getDateTime')
+ ->with()
+ ->willReturn(DateTime::createFromFormat(DateTime::ATOM, '2023-02-03T13:28:00+00:00'));
+ $this->caldavBackend->expects(self::once())
+ ->method('getCalendarById')
+ ->with(1337)
+ ->willReturn([
+ '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => '',
+ ]);
+
+ // One hour before midnight relative to the server's time
+ $expectedReminderTimstamp = (new DateTime('2023-02-03T23:00:00'))->getTimestamp();
+ $this->backend->expects(self::once())
+ ->method('insertReminder')
+ ->with(1337, 42, self::anything(), false, 1675468800, false, self::anything(), self::anything(), 'EMAIL', true, $expectedReminderTimstamp, false);
+
+ $this->reminderService->onCalendarObjectCreate($objectData);
+ }
+
public function testOnCalendarObjectCreateAllDayWithTimezone(): void {
$objectData = [
'calendardata' => self::CALENDAR_DATA_ALL_DAY,
@@ -494,17 +507,23 @@ EOD;
->willReturn([
'{urn:ietf:params:xml:ns:caldav}calendar-timezone' => null,
]);
- $this->backend->expects($this->exactly(6))
+
+ $calls = [
+ [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467243900, false],
+ [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244020, true],
+ [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244140, true],
+ [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244260, true],
+ [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244380, true],
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467158400, false]
+ ];
+ $this->backend->expects($this->exactly(count($calls)))
->method('insertReminder')
- ->withConsecutive(
- [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467243900, false],
- [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244020, true],
- [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244140, true],
- [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244260, true],
- [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244380, true],
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467158400, false]
- )
- ->willReturn(1);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return 1;
+ });
+
$this->timeFactory->expects($this->once())
->method('getDateTime')
->with()
@@ -529,9 +548,7 @@ EOD;
$expectedReminderTimstamp = (new DateTime('2023-02-04T08:00:00', new DateTimeZone('Europe/Vienna')))->getTimestamp();
$this->backend->expects(self::once())
->method('insertReminder')
- ->withConsecutive(
- [1337, 42, self::anything(), false, self::anything(), false, self::anything(), self::anything(), self::anything(), true, $expectedReminderTimstamp, false],
- )
+ ->with(1337, 42, self::anything(), false, self::anything(), false, self::anything(), self::anything(), self::anything(), true, $expectedReminderTimstamp, false)
->willReturn(1);
$this->caldavBackend->expects(self::once())
->method('getCalendarById')
@@ -657,22 +674,22 @@ EOD;
$provider3 = $this->createMock(INotificationProvider::class);
$provider4 = $this->createMock(INotificationProvider::class);
$provider5 = $this->createMock(INotificationProvider::class);
- $this->notificationProviderManager->expects($this->exactly(5))
+
+ $getProviderCalls = [
+ ['EMAIL', $provider1],
+ ['EMAIL', $provider2],
+ ['DISPLAY', $provider3],
+ ['EMAIL', $provider4],
+ ['EMAIL', $provider5],
+ ];
+ $this->notificationProviderManager->expects($this->exactly(count($getProviderCalls)))
->method('getProvider')
- ->withConsecutive(
- ['EMAIL'],
- ['EMAIL'],
- ['DISPLAY'],
- ['EMAIL'],
- ['EMAIL'],
- )
- ->willReturnOnConsecutiveCalls(
- $provider1,
- $provider2,
- $provider3,
- $provider4,
- $provider5,
- );
+ ->willReturnCallback(function () use (&$getProviderCalls) {
+ $expected = array_shift($getProviderCalls);
+ $return = array_pop($expected);
+ $this->assertEquals($expected, func_get_args());
+ return $return;
+ });
$user = $this->createMock(IUser::class);
$this->userManager->expects($this->exactly(5))
@@ -721,20 +738,36 @@ EOD;
return true;
}, 'Displayname 123', $user));
+ $removeReminderCalls = [
+ [1],
+ [2],
+ [3],
+ [4],
+ [5],
+ ];
$this->backend->expects($this->exactly(5))
->method('removeReminder')
- ->withConsecutive([1], [2], [3], [4], [5]);
- $this->backend->expects($this->exactly(6))
+ ->willReturnCallback(function () use (&$removeReminderCalls): void {
+ $expected = array_shift($removeReminderCalls);
+ $this->assertEquals($expected, func_get_args());
+ });
+
+
+ $insertReminderCalls = [
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848700, false],
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848820, true],
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848940, true],
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467849060, true],
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467849180, true],
+ [1337, 42, 'wej2z68l9h', true, 1468454400, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467763200, false],
+ ];
+ $this->backend->expects($this->exactly(count($insertReminderCalls)))
->method('insertReminder')
- ->withConsecutive(
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848700, false],
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848820, true],
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848940, true],
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467849060, true],
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467849180, true],
- [1337, 42, 'wej2z68l9h', true, 1468454400, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467763200, false],
- )
- ->willReturn(99);
+ ->willReturnCallback(function () use (&$insertReminderCalls) {
+ $expected = array_shift($insertReminderCalls);
+ $this->assertEquals($expected, func_get_args());
+ return 99;
+ });
$this->timeFactory->method('getDateTime')
->willReturn(DateTime::createFromFormat(DateTime::ATOM, '2016-06-08T00:00:00+00:00'));
diff --git a/apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTest.php b/apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTestCase.php
index ed39129fa56..364bc74de49 100644
--- a/apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTestCase.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,43 +9,27 @@ namespace OCA\DAV\Tests\unit\CalDAV\ResourceBooking;
use OCA\DAV\CalDAV\Proxy\Proxy;
use OCA\DAV\CalDAV\Proxy\ProxyMapper;
+use OCA\DAV\CalDAV\ResourceBooking\ResourcePrincipalBackend;
+use OCA\DAV\CalDAV\ResourceBooking\RoomPrincipalBackend;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\PropPatch;
use Test\TestCase;
-abstract class AbstractPrincipalBackendTest extends TestCase {
- /** @var \OCA\DAV\CalDAV\ResourceBooking\ResourcePrincipalBackend|\OCA\DAV\CalDAV\ResourceBooking\RoomPrincipalBackend */
- protected $principalBackend;
-
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- protected $userSession;
-
- /** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $groupManager;
-
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $logger;
-
- /** @var ProxyMapper|\PHPUnit\Framework\MockObject\MockObject */
- protected $proxyMapper;
-
- /** @var string */
- protected $mainDbTable;
-
- /** @var string */
- protected $metadataDbTable;
-
- /** @var string */
- protected $foreignKey;
-
- /** @var string */
- protected $principalPrefix;
-
- /** @var string */
- protected $expectedCUType;
+abstract class AbstractPrincipalBackendTestCase extends TestCase {
+ protected ResourcePrincipalBackend|RoomPrincipalBackend $principalBackend;
+ protected IUserSession&MockObject $userSession;
+ protected IGroupManager&MockObject $groupManager;
+ protected LoggerInterface&MockObject $logger;
+ protected ProxyMapper&MockObject $proxyMapper;
+ protected string $mainDbTable;
+ protected string $metadataDbTable;
+ protected string $foreignKey;
+ protected string $principalPrefix;
+ protected string $expectedCUType;
protected function setUp(): void {
parent::setUp();
@@ -57,10 +43,10 @@ abstract class AbstractPrincipalBackendTest extends TestCase {
protected function tearDown(): void {
$query = self::$realDatabase->getQueryBuilder();
- $query->delete('calendar_resources')->execute();
- $query->delete('calendar_resources_md')->execute();
- $query->delete('calendar_rooms')->execute();
- $query->delete('calendar_rooms_md')->execute();
+ $query->delete('calendar_resources')->executeStatement();
+ $query->delete('calendar_resources_md')->executeStatement();
+ $query->delete('calendar_rooms')->executeStatement();
+ $query->delete('calendar_rooms_md')->executeStatement();
}
public function testGetPrincipalsByPrefix(): void {
@@ -212,38 +198,43 @@ abstract class AbstractPrincipalBackendTest extends TestCase {
->with($this->principalPrefix . '/backend1-res1')
->willReturn([]);
+ $calls = [
+ function ($proxy) {
+ /** @var Proxy $proxy */
+ if ($proxy->getOwnerId() !== $this->principalPrefix . '/backend1-res1') {
+ return false;
+ }
+ if ($proxy->getProxyId() !== $this->principalPrefix . '/backend1-res2') {
+ return false;
+ }
+ if ($proxy->getPermissions() !== 3) {
+ return false;
+ }
+
+ return true;
+ },
+ function ($proxy) {
+ /** @var Proxy $proxy */
+ if ($proxy->getOwnerId() !== $this->principalPrefix . '/backend1-res1') {
+ return false;
+ }
+ if ($proxy->getProxyId() !== $this->principalPrefix . '/backend2-res3') {
+ return false;
+ }
+ if ($proxy->getPermissions() !== 3) {
+ return false;
+ }
+
+ return true;
+ }
+ ];
$this->proxyMapper->expects($this->exactly(2))
->method('insert')
- ->withConsecutive(
- [$this->callback(function ($proxy) {
- /** @var Proxy $proxy */
- if ($proxy->getOwnerId() !== $this->principalPrefix . '/backend1-res1') {
- return false;
- }
- if ($proxy->getProxyId() !== $this->principalPrefix . '/backend1-res2') {
- return false;
- }
- if ($proxy->getPermissions() !== 3) {
- return false;
- }
-
- return true;
- })],
- [$this->callback(function ($proxy) {
- /** @var Proxy $proxy */
- if ($proxy->getOwnerId() !== $this->principalPrefix . '/backend1-res1') {
- return false;
- }
- if ($proxy->getProxyId() !== $this->principalPrefix . '/backend2-res3') {
- return false;
- }
- if ($proxy->getPermissions() !== 3) {
- return false;
- }
-
- return true;
- })],
- );
+ ->willReturnCallback(function ($proxy) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertTrue($expected($proxy));
+ return $proxy;
+ });
$this->principalBackend->setGroupMemberSet($this->principalPrefix . '/backend1-res1/calendar-proxy-write', [$this->principalPrefix . '/backend1-res2', $this->principalPrefix . '/backend2-res3']);
}
@@ -255,9 +246,7 @@ abstract class AbstractPrincipalBackendTest extends TestCase {
$this->assertEquals(0, $actual);
}
- /**
- * @dataProvider dataSearchPrincipals
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataSearchPrincipals')]
public function testSearchPrincipals($expected, $test): void {
$user = $this->createMock(IUser::class);
$this->userSession->expects($this->once())
@@ -279,7 +268,7 @@ abstract class AbstractPrincipalBackendTest extends TestCase {
$actual);
}
- public function dataSearchPrincipals() {
+ public static function dataSearchPrincipals(): array {
// data providers are called before we subclass
// this class, $this->principalPrefix is null
// at that point, so we need this hack
diff --git a/apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php b/apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php
index d430afb0b01..168e21c3a91 100644
--- a/apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,7 +9,7 @@ namespace OCA\DAV\Tests\unit\CalDAV\ResourceBooking;
use OCA\DAV\CalDAV\ResourceBooking\ResourcePrincipalBackend;
-class ResourcePrincipalBackendTest extends AbstractPrincipalBackendTest {
+class ResourcePrincipalBackendTest extends AbstractPrincipalBackendTestCase {
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php b/apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php
index cd63a3512ae..8a53b0ee25e 100644
--- a/apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,7 +9,7 @@ namespace OCA\DAV\Tests\unit\CalDAV\ResourceBooking;
use OCA\DAV\CalDAV\ResourceBooking\RoomPrincipalBackend;
-class RoomPrincipalBackendTest extends AbstractPrincipalBackendTest {
+class RoomPrincipalBackendTest extends AbstractPrincipalBackendTestCase {
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginCharsetTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginCharsetTest.php
new file mode 100644
index 00000000000..fa52d5319c9
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginCharsetTest.php
@@ -0,0 +1,193 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\CalDAV\Schedule;
+
+use OC\L10N\L10N;
+use OC\URLGenerator;
+use OCA\DAV\CalDAV\EventComparisonService;
+use OCA\DAV\CalDAV\Schedule\IMipPlugin;
+use OCA\DAV\CalDAV\Schedule\IMipService;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Defaults;
+use OCP\IAppConfig;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\IURLGenerator;
+use OCP\IUser;
+use OCP\IUserSession;
+use OCP\L10N\IFactory;
+use OCP\Mail\IMailer;
+use OCP\Mail\IMessage;
+use OCP\Mail\Provider\IManager;
+use OCP\Mail\Provider\IMessageSend;
+use OCP\Mail\Provider\IService;
+use OCP\Mail\Provider\Message as MailProviderMessage;
+use OCP\Security\ISecureRandom;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+use Psr\Log\NullLogger;
+use Sabre\VObject\Component\VCalendar;
+use Sabre\VObject\Component\VEvent;
+use Sabre\VObject\ITip\Message;
+use Sabre\VObject\Property\ICalendar\CalAddress;
+use Symfony\Component\Mime\Email;
+use Test\TestCase;
+
+class IMipPluginCharsetTest extends TestCase {
+ // Dependencies
+ private Defaults&MockObject $defaults;
+ private IAppConfig&MockObject $appConfig;
+ private IConfig&MockObject $config;
+ private IDBConnection&MockObject $db;
+ private IFactory $l10nFactory;
+ private IManager&MockObject $mailManager;
+ private IMailer&MockObject $mailer;
+ private ISecureRandom&MockObject $random;
+ private ITimeFactory&MockObject $timeFactory;
+ private IUrlGenerator&MockObject $urlGenerator;
+ private IUserSession&MockObject $userSession;
+ private LoggerInterface $logger;
+
+ // Services
+ private EventComparisonService $eventComparisonService;
+ private IMipPlugin $imipPlugin;
+ private IMipService $imipService;
+
+ // ITip Message
+ private Message $itipMessage;
+
+ protected function setUp(): void {
+ // Used by IMipService and IMipPlugin
+ $today = new \DateTime('2025-06-15 14:30');
+ $this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->timeFactory->method('getTime')
+ ->willReturn($today->getTimestamp());
+ $this->timeFactory->method('getDateTime')
+ ->willReturn($today);
+
+ // IMipService
+ $this->urlGenerator = $this->createMock(URLGenerator::class);
+ $this->config = $this->createMock(IConfig::class);
+ $this->db = $this->createMock(IDBConnection::class);
+ $this->random = $this->createMock(ISecureRandom::class);
+ $l10n = $this->createMock(L10N::class);
+ $this->l10nFactory = $this->createMock(IFactory::class);
+ $this->l10nFactory->method('findGenericLanguage')
+ ->willReturn('en');
+ $this->l10nFactory->method('findLocale')
+ ->willReturn('en_US');
+ $this->l10nFactory->method('get')
+ ->willReturn($l10n);
+ $this->imipService = new IMipService(
+ $this->urlGenerator,
+ $this->config,
+ $this->db,
+ $this->random,
+ $this->l10nFactory,
+ $this->timeFactory,
+ );
+
+ // EventComparisonService
+ $this->eventComparisonService = new EventComparisonService();
+
+ // IMipPlugin
+ $this->appConfig = $this->createMock(IAppConfig::class);
+ $message = new \OC\Mail\Message(new Email(), false);
+ $this->mailer = $this->createMock(IMailer::class);
+ $this->mailer->method('createMessage')
+ ->willReturn($message);
+ $this->mailer->method('validateMailAddress')
+ ->willReturn(true);
+ $this->logger = new NullLogger();
+ $this->defaults = $this->createMock(Defaults::class);
+ $this->defaults->method('getName')
+ ->willReturn('Instance Name 123');
+ $user = $this->createMock(IUser::class);
+ $user->method('getUID')
+ ->willReturn('luigi');
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->userSession->method('getUser')
+ ->willReturn($user);
+ $this->mailManager = $this->createMock(IManager::class);
+ $this->imipPlugin = new IMipPlugin(
+ $this->appConfig,
+ $this->mailer,
+ $this->logger,
+ $this->timeFactory,
+ $this->defaults,
+ $this->userSession,
+ $this->imipService,
+ $this->eventComparisonService,
+ $this->mailManager,
+ );
+
+ // ITipMessage
+ $calendar = new VCalendar();
+ $event = new VEvent($calendar, 'VEVENT');
+ $event->UID = 'uid-1234';
+ $event->SEQUENCE = 1;
+ $event->SUMMARY = 'Lunch';
+ $event->DTSTART = new \DateTime('2025-06-20 12:30:00');
+ $organizer = new CalAddress($calendar, 'ORGANIZER', 'mailto:luigi@example.org');
+ $event->add($organizer);
+ $attendee = new CalAddress($calendar, 'ATTENDEE', 'mailto:jose@example.org', ['RSVP' => 'TRUE', 'CN' => 'José']);
+ $event->add($attendee);
+ $calendar->add($event);
+ $this->itipMessage = new Message();
+ $this->itipMessage->method = 'REQUEST';
+ $this->itipMessage->message = $calendar;
+ $this->itipMessage->sender = 'mailto:luigi@example.org';
+ $this->itipMessage->senderName = 'Luigi';
+ $this->itipMessage->recipient = 'mailto:' . 'jose@example.org';
+ }
+
+ public function testCharsetMailer(): void {
+ // Arrange
+ $symfonyEmail = null;
+ $this->mailer->expects(self::once())
+ ->method('send')
+ ->willReturnCallback(function (IMessage $message) use (&$symfonyEmail): array {
+ if ($message instanceof \OC\Mail\Message) {
+ $symfonyEmail = $message->getSymfonyEmail();
+ }
+ return [];
+ });
+
+ // Act
+ $this->imipPlugin->schedule($this->itipMessage);
+
+ // Assert
+ $this->assertNotNull($symfonyEmail);
+ $body = $symfonyEmail->getBody()->toString();
+ $this->assertStringContainsString('Content-Type: text/calendar; method=REQUEST; charset="utf-8"; name=event.ics', $body);
+ }
+
+ public function testCharsetMailProvider(): void {
+ // Arrange
+ $this->appConfig->method('getValueBool')
+ ->with('core', 'mail_providers_enabled', true)
+ ->willReturn(true);
+ $mailMessage = new MailProviderMessage();
+ $mailService = $this->createStubForIntersectionOfInterfaces([IService::class, IMessageSend::class]);
+ $mailService->method('initiateMessage')
+ ->willReturn($mailMessage);
+ $mailService->expects(self::once())
+ ->method('sendMessage');
+ $this->mailManager->method('findServiceByAddress')
+ ->willReturn($mailService);
+
+ // Act
+ $this->imipPlugin->schedule($this->itipMessage);
+
+ // Assert
+ $attachments = $mailMessage->getAttachments();
+ $this->assertCount(1, $attachments);
+ $this->assertStringContainsString('text/calendar; method=REQUEST; charset="utf-8"; name=event.ics', $attachments[0]->getType());
+ }
+}
diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php
index 433f3a87c59..8e71bfa6edf 100644
--- a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -11,13 +13,17 @@ use OCA\DAV\CalDAV\Schedule\IMipPlugin;
use OCA\DAV\CalDAV\Schedule\IMipService;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Defaults;
-use OCP\IConfig;
+use OCP\IAppConfig;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Mail\IAttachment;
use OCP\Mail\IEMailTemplate;
use OCP\Mail\IMailer;
use OCP\Mail\IMessage;
+use OCP\Mail\Provider\IManager as IMailManager;
+use OCP\Mail\Provider\IMessage as IMailMessageNew;
+use OCP\Mail\Provider\IMessageSend as IMailMessageSend;
+use OCP\Mail\Provider\IService as IMailService;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\VObject\Component\VCalendar;
@@ -26,46 +32,28 @@ use Sabre\VObject\ITip\Message;
use Test\TestCase;
use function array_merge;
-class IMipPluginTest extends TestCase {
-
- /** @var IMessage|MockObject */
- private $mailMessage;
-
- /** @var IMailer|MockObject */
- private $mailer;
-
- /** @var IEMailTemplate|MockObject */
- private $emailTemplate;
-
- /** @var IAttachment|MockObject */
- private $emailAttachment;
-
- /** @var ITimeFactory|MockObject */
- private $timeFactory;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var IUserSession|MockObject */
- private $userSession;
-
- /** @var IUser|MockObject */
- private $user;
-
- /** @var IMipPlugin */
- private $plugin;
-
- /** @var IMipService|MockObject */
- private $service;
-
- /** @var Defaults|MockObject */
- private $defaults;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
+interface IMailServiceMock extends IMailService, IMailMessageSend {
+ // workaround for creating mock class with multiple interfaces
+ // TODO: remove after phpUnit 10 is supported.
+}
- /** @var EventComparisonService|MockObject */
- private $eventComparisonService;
+class IMipPluginTest extends TestCase {
+ private IMessage&MockObject $mailMessage;
+ private IMailer&MockObject $mailer;
+ private IEMailTemplate&MockObject $emailTemplate;
+ private IAttachment&MockObject $emailAttachment;
+ private ITimeFactory&MockObject $timeFactory;
+ private IAppConfig&MockObject $config;
+ private IUserSession&MockObject $userSession;
+ private IUser&MockObject $user;
+ private IMipPlugin $plugin;
+ private IMipService&MockObject $service;
+ private Defaults&MockObject $defaults;
+ private LoggerInterface&MockObject $logger;
+ private EventComparisonService&MockObject $eventComparisonService;
+ private IMailManager&MockObject $mailManager;
+ private IMailServiceMock&MockObject $mailService;
+ private IMailMessageNew&MockObject $mailMessageNew;
protected function setUp(): void {
$this->mailMessage = $this->createMock(IMessage::class);
@@ -87,13 +75,9 @@ class IMipPluginTest extends TestCase {
$this->timeFactory = $this->createMock(ITimeFactory::class);
$this->timeFactory->method('getTime')->willReturn(1496912528); // 2017-01-01
- $this->config = $this->createMock(IConfig::class);
-
+ $this->config = $this->createMock(IAppConfig::class);
+
$this->user = $this->createMock(IUser::class);
- /*
- $this->user->method('getUID');
- $this->user->method('getDisplayName');
- */
$this->userSession = $this->createMock(IUserSession::class);
$this->userSession->method('getUser')
@@ -107,6 +91,12 @@ class IMipPluginTest extends TestCase {
$this->eventComparisonService = $this->createMock(EventComparisonService::class);
+ $this->mailManager = $this->createMock(IMailManager::class);
+
+ $this->mailService = $this->createMock(IMailServiceMock::class);
+
+ $this->mailMessageNew = $this->createMock(IMailMessageNew::class);
+
$this->plugin = new IMipPlugin(
$this->config,
$this->mailer,
@@ -115,7 +105,8 @@ class IMipPluginTest extends TestCase {
$this->defaults,
$this->userSession,
$this->service,
- $this->eventComparisonService
+ $this->eventComparisonService,
+ $this->mailManager,
);
}
@@ -181,7 +172,7 @@ class IMipPluginTest extends TestCase {
$this->plugin->setVCalendar($oldVCalendar);
$this->service->expects(self::once())
->method('getLastOccurrence')
- ->willReturn('1496912700');
+ ->willReturn(1496912700);
$this->mailer->expects(self::once())
->method('validateMailAddress')
->with('frodo@hobb.it')
@@ -198,6 +189,10 @@ class IMipPluginTest extends TestCase {
->with($atnd)
->willReturn(false);
$this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
->method('buildBodyData')
->with($newVevent, $oldVEvent)
->willReturn($data);
@@ -222,12 +217,12 @@ class IMipPluginTest extends TestCase {
->method('getAttendeeRsvpOrReqForParticipant')
->willReturn(true);
$this->config->expects(self::once())
- ->method('getAppValue')
+ ->method('getValueString')
->with('dav', 'invitation_link_recipients', 'yes')
->willReturn('yes');
$this->service->expects(self::once())
->method('createInvitationToken')
- ->with($message, $newVevent, '1496912700')
+ ->with($message, $newVevent, 1496912700)
->willReturn('token');
$this->service->expects(self::once())
->method('addResponseButtons')
@@ -284,7 +279,7 @@ class IMipPluginTest extends TestCase {
$this->plugin->setVCalendar($oldVCalendar);
$this->service->expects(self::once())
->method('getLastOccurrence')
- ->willReturn('1496912700');
+ ->willReturn(1496912700);
$this->mailer->expects(self::once())
->method('validateMailAddress')
->with('the-shire@hobb.it')
@@ -301,6 +296,88 @@ class IMipPluginTest extends TestCase {
->with($room)
->willReturn(true);
$this->service->expects(self::never())
+ ->method('isCircle');
+ $this->service->expects(self::never())
+ ->method('buildBodyData');
+ $this->user->expects(self::any())
+ ->method('getUID')
+ ->willReturn('user1');
+ $this->user->expects(self::any())
+ ->method('getDisplayName')
+ ->willReturn('Mr. Wizard');
+ $this->userSession->expects(self::any())
+ ->method('getUser')
+ ->willReturn($this->user);
+ $this->service->expects(self::never())
+ ->method('getFrom');
+ $this->service->expects(self::never())
+ ->method('addSubjectAndHeading');
+ $this->service->expects(self::never())
+ ->method('addBulletList');
+ $this->service->expects(self::never())
+ ->method('getAttendeeRsvpOrReqForParticipant');
+ $this->config->expects(self::never())
+ ->method('getValueString');
+ $this->service->expects(self::never())
+ ->method('createInvitationToken');
+ $this->service->expects(self::never())
+ ->method('addResponseButtons');
+ $this->service->expects(self::never())
+ ->method('addMoreOptionsButton');
+ $this->mailer->expects(self::never())
+ ->method('send');
+ $this->plugin->schedule($message);
+ $this->assertEquals('1.0', $message->getScheduleStatus());
+ }
+
+ public function testAttendeeIsCircle(): void {
+ $message = new Message();
+ $message->method = 'REQUEST';
+ $newVCalendar = new VCalendar();
+ $newVevent = new VEvent($newVCalendar, 'one', array_merge([
+ 'UID' => 'uid-1234',
+ 'SEQUENCE' => 1,
+ 'SUMMARY' => 'Fellowship meeting without (!) Boromir',
+ 'DTSTART' => new \DateTime('2016-01-01 00:00:00')
+ ], []));
+ $newVevent->add('ORGANIZER', 'mailto:gandalf@wiz.ard');
+ $newVevent->add('ATTENDEE', 'mailto:' . 'circle+82utEV1Fle8wvxndZLK5TVAPtxj8IIe@middle.earth', ['RSVP' => 'TRUE', 'CN' => 'The Fellowship', 'CUTYPE' => 'GROUP']);
+ $newVevent->add('ATTENDEE', 'mailto:' . 'boromir@tra.it.or', ['RSVP' => 'TRUE', 'MEMBER' => 'circle+82utEV1Fle8wvxndZLK5TVAPtxj8IIe@middle.earth']);
+ $message->message = $newVCalendar;
+ $message->sender = 'mailto:gandalf@wiz.ard';
+ $message->senderName = 'Mr. Wizard';
+ $message->recipient = 'mailto:' . 'circle+82utEV1Fle8wvxndZLK5TVAPtxj8IIe@middle.earth';
+ $attendees = $newVevent->select('ATTENDEE');
+ $circle = '';
+ foreach ($attendees as $attendee) {
+ if (strcasecmp($attendee->getValue(), $message->recipient) === 0) {
+ $circle = $attendee;
+ }
+ }
+ $this->assertNotEmpty($circle, 'Failed to find attendee belonging to the circle');
+ $this->service->expects(self::once())
+ ->method('getLastOccurrence')
+ ->willReturn(1496912700);
+ $this->mailer->expects(self::once())
+ ->method('validateMailAddress')
+ ->with('circle+82utEV1Fle8wvxndZLK5TVAPtxj8IIe@middle.earth')
+ ->willReturn(true);
+ $this->eventComparisonService->expects(self::once())
+ ->method('findModified')
+ ->willReturn(['new' => [$newVevent], 'old' => null]);
+ $this->service->expects(self::once())
+ ->method('getCurrentAttendee')
+ ->with($message)
+ ->willReturn($circle);
+ $this->service->expects(self::once())
+ ->method('isRoomOrResource')
+ ->with($circle)
+ ->willReturn(false);
+ $this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($circle)
+ ->willReturn(true);
+ $this->service->expects(self::never())
->method('buildBodyData');
$this->user->expects(self::any())
->method('getUID')
@@ -320,7 +397,7 @@ class IMipPluginTest extends TestCase {
$this->service->expects(self::never())
->method('getAttendeeRsvpOrReqForParticipant');
$this->config->expects(self::never())
- ->method('getAppValue');
+ ->method('getValueString');
$this->service->expects(self::never())
->method('createInvitationToken');
$this->service->expects(self::never())
@@ -385,7 +462,7 @@ class IMipPluginTest extends TestCase {
$this->plugin->setVCalendar($oldVCalendar);
$this->service->expects(self::once())
->method('getLastOccurrence')
- ->willReturn('1496912700');
+ ->willReturn(1496912700);
$this->mailer->expects(self::once())
->method('validateMailAddress')
->with('frodo@hobb.it')
@@ -402,6 +479,10 @@ class IMipPluginTest extends TestCase {
->with($atnd)
->willReturn(false);
$this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
->method('buildBodyData')
->with($newVevent, null)
->willReturn($data);
@@ -426,12 +507,12 @@ class IMipPluginTest extends TestCase {
->method('getAttendeeRsvpOrReqForParticipant')
->willReturn(true);
$this->config->expects(self::once())
- ->method('getAppValue')
+ ->method('getValueString')
->with('dav', 'invitation_link_recipients', 'yes')
->willReturn('yes');
$this->service->expects(self::once())
->method('createInvitationToken')
- ->with($message, $newVevent, '1496912700')
+ ->with($message, $newVevent, 1496912700)
->willReturn('token');
$this->service->expects(self::once())
->method('addResponseButtons')
@@ -446,7 +527,7 @@ class IMipPluginTest extends TestCase {
$this->assertEquals('1.1', $message->getScheduleStatus());
}
- public function testEmailValidationFailed() {
+ public function testEmailValidationFailed(): void {
$message = new Message();
$message->method = 'REQUEST';
$message->message = new VCalendar();
@@ -464,7 +545,7 @@ class IMipPluginTest extends TestCase {
$this->service->expects(self::once())
->method('getLastOccurrence')
- ->willReturn('1496912700');
+ ->willReturn(1496912700);
$this->mailer->expects(self::once())
->method('validateMailAddress')
->with('frodo@hobb.it')
@@ -516,7 +597,7 @@ class IMipPluginTest extends TestCase {
$this->plugin->setVCalendar($oldVcalendar);
$this->service->expects(self::once())
->method('getLastOccurrence')
- ->willReturn('1496912700');
+ ->willReturn(1496912700);
$this->mailer->expects(self::once())
->method('validateMailAddress')
->with('frodo@hobb.it')
@@ -533,6 +614,10 @@ class IMipPluginTest extends TestCase {
->with($atnd)
->willReturn(false);
$this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
->method('buildBodyData')
->with($newVevent, null)
->willReturn($data);
@@ -557,12 +642,12 @@ class IMipPluginTest extends TestCase {
->method('getAttendeeRsvpOrReqForParticipant')
->willReturn(true);
$this->config->expects(self::once())
- ->method('getAppValue')
+ ->method('getValueString')
->with('dav', 'invitation_link_recipients', 'yes')
->willReturn('yes');
$this->service->expects(self::once())
->method('createInvitationToken')
- ->with($message, $newVevent, '1496912700')
+ ->with($message, $newVevent, 1496912700)
->willReturn('token');
$this->service->expects(self::once())
->method('addResponseButtons')
@@ -582,6 +667,226 @@ class IMipPluginTest extends TestCase {
$this->assertEquals('5.0', $message->getScheduleStatus());
}
+ public function testMailProviderSend(): void {
+ // construct iTip message with event and attendees
+ $message = new Message();
+ $message->method = 'REQUEST';
+ $calendar = new VCalendar();
+ $event = new VEvent($calendar, 'one', array_merge([
+ 'UID' => 'uid-1234',
+ 'SEQUENCE' => 1,
+ 'SUMMARY' => 'Fellowship meeting without (!) Boromir',
+ 'DTSTART' => new \DateTime('2016-01-01 00:00:00')
+ ], []));
+ $event->add('ORGANIZER', 'mailto:gandalf@wiz.ard');
+ $event->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']);
+ $message->message = $calendar;
+ $message->sender = 'mailto:gandalf@wiz.ard';
+ $message->senderName = 'Mr. Wizard';
+ $message->recipient = 'mailto:' . 'frodo@hobb.it';
+ // construct
+ foreach ($event->select('ATTENDEE') as $entry) {
+ if (strcasecmp($entry->getValue(), $message->recipient) === 0) {
+ $attendee = $entry;
+ }
+ }
+ // construct body data return
+ $data = ['invitee_name' => 'Mr. Wizard',
+ 'meeting_title' => 'Fellowship meeting without (!) Boromir',
+ 'attendee_name' => 'frodo@hobb.it'
+ ];
+ // construct system config mock returns
+ $this->config->expects(self::once())
+ ->method('getValueString')
+ ->with('dav', 'invitation_link_recipients', 'yes')
+ ->willReturn('yes');
+ // construct user mock returns
+ $this->user->expects(self::any())
+ ->method('getUID')
+ ->willReturn('user1');
+ $this->user->expects(self::any())
+ ->method('getDisplayName')
+ ->willReturn('Mr. Wizard');
+ // construct user session mock returns
+ $this->userSession->expects(self::any())
+ ->method('getUser')
+ ->willReturn($this->user);
+ // construct service mock returns
+ $this->service->expects(self::once())
+ ->method('getLastOccurrence')
+ ->willReturn(1496912700);
+ $this->service->expects(self::once())
+ ->method('getCurrentAttendee')
+ ->with($message)
+ ->willReturn($attendee);
+ $this->service->expects(self::once())
+ ->method('isRoomOrResource')
+ ->with($attendee)
+ ->willReturn(false);
+ $this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($attendee)
+ ->willReturn(false);
+ $this->service->expects(self::once())
+ ->method('buildBodyData')
+ ->with($event, null)
+ ->willReturn($data);
+ $this->service->expects(self::once())
+ ->method('getFrom');
+ $this->service->expects(self::once())
+ ->method('addSubjectAndHeading')
+ ->with($this->emailTemplate, 'request', 'Mr. Wizard', 'Fellowship meeting without (!) Boromir', false);
+ $this->service->expects(self::once())
+ ->method('addBulletList')
+ ->with($this->emailTemplate, $event, $data);
+ $this->service->expects(self::once())
+ ->method('getAttendeeRsvpOrReqForParticipant')
+ ->willReturn(true);
+ $this->service->expects(self::once())
+ ->method('createInvitationToken')
+ ->with($message, $event, 1496912700)
+ ->willReturn('token');
+ $this->service->expects(self::once())
+ ->method('addResponseButtons')
+ ->with($this->emailTemplate, 'token');
+ $this->service->expects(self::once())
+ ->method('addMoreOptionsButton')
+ ->with($this->emailTemplate, 'token');
+ $this->eventComparisonService->expects(self::once())
+ ->method('findModified')
+ ->willReturn(['old' => [] ,'new' => [$event]]);
+ // construct mail mock returns
+ $this->mailer->expects(self::once())
+ ->method('validateMailAddress')
+ ->with('frodo@hobb.it')
+ ->willReturn(true);
+ // construct mail provider mock returns
+ $this->mailService
+ ->method('initiateMessage')
+ ->willReturn($this->mailMessageNew);
+ $this->mailService
+ ->method('sendMessage')
+ ->with($this->mailMessageNew);
+ $this->mailManager
+ ->method('findServiceByAddress')
+ ->with('user1', 'gandalf@wiz.ard')
+ ->willReturn($this->mailService);
+
+ $this->plugin->schedule($message);
+ $this->assertEquals('1.1', $message->getScheduleStatus());
+ }
+
+ public function testMailProviderDisabled(): void {
+ $message = new Message();
+ $message->method = 'REQUEST';
+ $newVCalendar = new VCalendar();
+ $newVevent = new VEvent($newVCalendar, 'one', array_merge([
+ 'UID' => 'uid-1234',
+ 'SEQUENCE' => 1,
+ 'SUMMARY' => 'Fellowship meeting without (!) Boromir',
+ 'DTSTART' => new \DateTime('2016-01-01 00:00:00')
+ ], []));
+ $newVevent->add('ORGANIZER', 'mailto:gandalf@wiz.ard');
+ $newVevent->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']);
+ $message->message = $newVCalendar;
+ $message->sender = 'mailto:gandalf@wiz.ard';
+ $message->senderName = 'Mr. Wizard';
+ $message->recipient = 'mailto:' . 'frodo@hobb.it';
+ // save the old copy in the plugin
+ $oldVCalendar = new VCalendar();
+ $oldVEvent = new VEvent($oldVCalendar, 'one', [
+ 'UID' => 'uid-1234',
+ 'SEQUENCE' => 0,
+ 'SUMMARY' => 'Fellowship meeting',
+ 'DTSTART' => new \DateTime('2016-01-01 00:00:00')
+ ]);
+ $oldVEvent->add('ORGANIZER', 'mailto:gandalf@wiz.ard');
+ $oldVEvent->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']);
+ $oldVEvent->add('ATTENDEE', 'mailto:' . 'boromir@tra.it.or', ['RSVP' => 'TRUE']);
+ $oldVCalendar->add($oldVEvent);
+ $data = ['invitee_name' => 'Mr. Wizard',
+ 'meeting_title' => 'Fellowship meeting without (!) Boromir',
+ 'attendee_name' => 'frodo@hobb.it'
+ ];
+ $attendees = $newVevent->select('ATTENDEE');
+ $atnd = '';
+ foreach ($attendees as $attendee) {
+ if (strcasecmp($attendee->getValue(), $message->recipient) === 0) {
+ $atnd = $attendee;
+ }
+ }
+ $this->plugin->setVCalendar($oldVCalendar);
+ $this->service->expects(self::once())
+ ->method('getLastOccurrence')
+ ->willReturn(1496912700);
+ $this->mailer->expects(self::once())
+ ->method('validateMailAddress')
+ ->with('frodo@hobb.it')
+ ->willReturn(true);
+ $this->eventComparisonService->expects(self::once())
+ ->method('findModified')
+ ->willReturn(['new' => [$newVevent], 'old' => [$oldVEvent]]);
+ $this->service->expects(self::once())
+ ->method('getCurrentAttendee')
+ ->with($message)
+ ->willReturn($atnd);
+ $this->service->expects(self::once())
+ ->method('isRoomOrResource')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
+ ->method('buildBodyData')
+ ->with($newVevent, $oldVEvent)
+ ->willReturn($data);
+ $this->user->expects(self::any())
+ ->method('getUID')
+ ->willReturn('user1');
+ $this->user->expects(self::any())
+ ->method('getDisplayName')
+ ->willReturn('Mr. Wizard');
+ $this->userSession->expects(self::any())
+ ->method('getUser')
+ ->willReturn($this->user);
+ $this->service->expects(self::once())
+ ->method('getFrom');
+ $this->service->expects(self::once())
+ ->method('addSubjectAndHeading')
+ ->with($this->emailTemplate, 'request', 'Mr. Wizard', 'Fellowship meeting without (!) Boromir', true);
+ $this->service->expects(self::once())
+ ->method('addBulletList')
+ ->with($this->emailTemplate, $newVevent, $data);
+ $this->service->expects(self::once())
+ ->method('getAttendeeRsvpOrReqForParticipant')
+ ->willReturn(true);
+ $this->config->expects(self::once())
+ ->method('getValueString')
+ ->with('dav', 'invitation_link_recipients', 'yes')
+ ->willReturn('yes');
+ $this->config->expects(self::once())
+ ->method('getValueBool')
+ ->with('core', 'mail_providers_enabled', true)
+ ->willReturn(false);
+ $this->service->expects(self::once())
+ ->method('createInvitationToken')
+ ->with($message, $newVevent, 1496912700)
+ ->willReturn('token');
+ $this->service->expects(self::once())
+ ->method('addResponseButtons')
+ ->with($this->emailTemplate, 'token');
+ $this->service->expects(self::once())
+ ->method('addMoreOptionsButton')
+ ->with($this->emailTemplate, 'token');
+ $this->mailer->expects(self::once())
+ ->method('send')
+ ->willReturn([]);
+ $this->plugin->schedule($message);
+ $this->assertEquals('1.1', $message->getScheduleStatus());
+ }
+
public function testNoOldEvent(): void {
$message = new Message();
$message->method = 'REQUEST';
@@ -611,7 +916,7 @@ class IMipPluginTest extends TestCase {
}
$this->service->expects(self::once())
->method('getLastOccurrence')
- ->willReturn('1496912700');
+ ->willReturn(1496912700);
$this->mailer->expects(self::once())
->method('validateMailAddress')
->with('frodo@hobb.it')
@@ -629,6 +934,10 @@ class IMipPluginTest extends TestCase {
->with($atnd)
->willReturn(false);
$this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
->method('buildBodyData')
->with($newVevent, null)
->willReturn($data);
@@ -653,12 +962,12 @@ class IMipPluginTest extends TestCase {
->method('getAttendeeRsvpOrReqForParticipant')
->willReturn(true);
$this->config->expects(self::once())
- ->method('getAppValue')
+ ->method('getValueString')
->with('dav', 'invitation_link_recipients', 'yes')
->willReturn('yes');
$this->service->expects(self::once())
->method('createInvitationToken')
- ->with($message, $newVevent, '1496912700')
+ ->with($message, $newVevent, 1496912700)
->willReturn('token');
$this->service->expects(self::once())
->method('addResponseButtons')
@@ -704,7 +1013,7 @@ class IMipPluginTest extends TestCase {
}
$this->service->expects(self::once())
->method('getLastOccurrence')
- ->willReturn('1496912700');
+ ->willReturn(1496912700);
$this->mailer->expects(self::once())
->method('validateMailAddress')
->with('frodo@hobb.it')
@@ -722,6 +1031,10 @@ class IMipPluginTest extends TestCase {
->with($atnd)
->willReturn(false);
$this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
->method('buildBodyData')
->with($newVevent, null)
->willReturn($data);
@@ -746,7 +1059,7 @@ class IMipPluginTest extends TestCase {
->method('getAttendeeRsvpOrReqForParticipant')
->willReturn(true);
$this->config->expects(self::once())
- ->method('getAppValue')
+ ->method('getValueString')
->with('dav', 'invitation_link_recipients', 'yes')
->willReturn('no');
$this->service->expects(self::never())
diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php
index d4f1dd66897..2be6a1cf8b1 100644
--- a/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -7,49 +9,48 @@
namespace OCA\DAV\Tests\unit\CalDAV\Schedule;
-use OC\L10N\L10N;
-use OC\L10N\LazyL10N;
use OC\URLGenerator;
+use OCA\DAV\CalDAV\EventReader;
use OCA\DAV\CalDAV\Schedule\IMipService;
+use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\IDBConnection;
-use OCP\L10N\IFactory as L10NFactory;
+use OCP\IL10N;
+use OCP\L10N\IFactory;
use OCP\Security\ISecureRandom;
use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Component\VCalendar;
-use Sabre\VObject\Component\VEvent;
use Sabre\VObject\Property\ICalendar\DateTime;
use Test\TestCase;
class IMipServiceTest extends TestCase {
- /** @var URLGenerator|MockObject */
- private $urlGenerator;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var IDBConnection|MockObject */
- private $db;
-
- /** @var ISecureRandom|MockObject */
- private $random;
-
- /** @var L10NFactory|MockObject */
- private $l10nFactory;
+ private URLGenerator&MockObject $urlGenerator;
+ private IConfig&MockObject $config;
+ private IDBConnection&MockObject $db;
+ private ISecureRandom&MockObject $random;
+ private IFactory&MockObject $l10nFactory;
+ private IL10N&MockObject $l10n;
+ private ITimeFactory&MockObject $timeFactory;
+ private IMipService $service;
- /** @var L10N|MockObject */
- private $l10n;
- /** @var IMipService */
- private $service;
+ private VCalendar $vCalendar1a;
+ private VCalendar $vCalendar1b;
+ private VCalendar $vCalendar2;
+ private VCalendar $vCalendar3;
+ /** @var DateTime DateTime object that will be returned by DateTime() or DateTime('now') */
+ public static $datetimeNow;
protected function setUp(): void {
+ parent::setUp();
+
$this->urlGenerator = $this->createMock(URLGenerator::class);
$this->config = $this->createMock(IConfig::class);
$this->db = $this->createMock(IDBConnection::class);
$this->random = $this->createMock(ISecureRandom::class);
- $this->l10nFactory = $this->createMock(L10NFactory::class);
- $this->l10n = $this->createMock(LazyL10N::class);
+ $this->l10nFactory = $this->createMock(IFactory::class);
+ $this->l10n = $this->createMock(IL10N::class);
+ $this->timeFactory = $this->createMock(ITimeFactory::class);
$this->l10nFactory->expects(self::once())
->method('findGenericLanguage')
->willReturn('en');
@@ -62,14 +63,87 @@ class IMipServiceTest extends TestCase {
$this->config,
$this->db,
$this->random,
- $this->l10nFactory
+ $this->l10nFactory,
+ $this->timeFactory
);
+
+ // construct calendar with a 1 hour event and same start/end time zones
+ $this->vCalendar1a = new VCalendar();
+ $vEvent = $this->vCalendar1a->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('SUMMARY', 'Testing Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+
+ // construct calendar with a 1 hour event and different start/end time zones
+ $this->vCalendar1b = new VCalendar();
+ $vEvent = $this->vCalendar1b->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Vancouver']);
+ $vEvent->add('SUMMARY', 'Testing Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+
+ // construct calendar with a full day event
+ $this->vCalendar2 = new VCalendar();
+ // time zone component
+ $vTimeZone = $this->vCalendar2->add('VTIMEZONE');
+ $vTimeZone->add('TZID', 'America/Toronto');
+ // event component
+ $vEvent = $this->vCalendar2->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701');
+ $vEvent->add('DTEND', '20240702');
+ $vEvent->add('SUMMARY', 'Testing Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+
+ // construct calendar with a multi day event
+ $this->vCalendar3 = new VCalendar();
+ // time zone component
+ $vTimeZone = $this->vCalendar3->add('VTIMEZONE');
+ $vTimeZone->add('TZID', 'America/Toronto');
+ // event component
+ $vEvent = $this->vCalendar3->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701');
+ $vEvent->add('DTEND', '20240706');
+ $vEvent->add('SUMMARY', 'Testing Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
}
public function testGetFrom(): void {
- $senderName = "Detective McQueen";
- $default = "Twin Lakes Police Department - Darkside Division";
- $expected = "Detective McQueen via Twin Lakes Police Department - Darkside Division";
+ $senderName = 'Detective McQueen';
+ $default = 'Twin Lakes Police Department - Darkside Division';
+ $expected = 'Detective McQueen via Twin Lakes Police Department - Darkside Division';
$this->l10n->expects(self::once())
->method('t')
@@ -80,96 +154,105 @@ class IMipServiceTest extends TestCase {
}
public function testBuildBodyDataCreated(): void {
- $vCalendar = new VCalendar();
- $oldVevent = null;
- $newVevent = new VEvent($vCalendar, 'two', [
- 'UID' => 'uid-1234',
- 'SEQUENCE' => 3,
- 'LAST-MODIFIED' => 789456,
- 'SUMMARY' => 'Second Breakfast',
- 'DTSTART' => new \DateTime('2016-01-01 00:00:00'),
- 'RECURRENCE-ID' => new \DateTime('2016-01-01 00:00:00')
- ]);
+ // construct l10n return(s)
+ $this->l10n->method('l')->willReturnCallback(
+ function ($v1, $v2, $v3) {
+ return match (true) {
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM',
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM',
+ $v1 === 'date' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'full'] => 'July 1, 2024'
+ };
+ }
+ );
+ $this->l10n->method('n')->willReturnMap([
+ [
+ 'In a day on %1$s between %2$s - %3$s',
+ 'In %n days on %1$s between %2$s - %3$s',
+ 1,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ]
+ ]);
+ // construct time factory return(s)
+ $this->timeFactory->method('getDateTime')->willReturnCallback(
+ function ($v1, $v2) {
+ return match (true) {
+ $v1 == 'now' && $v2 == null => (new \DateTime('20240630T000000'))
+ };
+ }
+ );
+ /** test singleton partial day event*/
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // define expected output
$expected = [
- 'meeting_when' => $this->service->generateWhenString($newVevent),
+ 'meeting_when' => $this->service->generateWhenString($eventReader),
'meeting_description' => '',
- 'meeting_title' => 'Second Breakfast',
+ 'meeting_title' => 'Testing Event',
'meeting_location' => '',
'meeting_url' => '',
'meeting_url_html' => '',
];
-
- $actual = $this->service->buildBodyData($newVevent, $oldVevent);
-
+ // generate actual output
+ $actual = $this->service->buildBodyData($vCalendar->VEVENT[0], null);
+ // test output
$this->assertEquals($expected, $actual);
}
public function testBuildBodyDataUpdate(): void {
- $vCalendar = new VCalendar();
- $oldVevent = new VEvent($vCalendar, 'two', [
- 'UID' => 'uid-1234',
- 'SEQUENCE' => 1,
- 'LAST-MODIFIED' => 456789,
- 'SUMMARY' => 'Elevenses',
- 'DTSTART' => new \DateTime('2016-01-01 00:00:00'),
- 'RECURRENCE-ID' => new \DateTime('2016-01-01 00:00:00')
- ]);
- $oldVevent->add('ORGANIZER', 'mailto:gandalf@wiz.ard');
- $oldVevent->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']);
- $newVevent = new VEvent($vCalendar, 'two', [
- 'UID' => 'uid-1234',
- 'SEQUENCE' => 3,
- 'LAST-MODIFIED' => 789456,
- 'SUMMARY' => 'Second Breakfast',
- 'DTSTART' => new \DateTime('2016-01-01 00:00:00'),
- 'RECURRENCE-ID' => new \DateTime('2016-01-01 00:00:00')
- ]);
+ // construct l10n return(s)
+ $this->l10n->method('l')->willReturnCallback(
+ function ($v1, $v2, $v3) {
+ return match (true) {
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM',
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM',
+ $v1 === 'date' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'full'] => 'July 1, 2024'
+ };
+ }
+ );
+ $this->l10n->method('n')->willReturnMap([
+ [
+ 'In a day on %1$s between %2$s - %3$s',
+ 'In %n days on %1$s between %2$s - %3$s',
+ 1,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ]
+ ]);
+ // construct time factory return(s)
+ $this->timeFactory->method('getDateTime')->willReturnCallback(
+ function ($v1, $v2) {
+ return match (true) {
+ $v1 == 'now' && $v2 == null => (new \DateTime('20240630T000000'))
+ };
+ }
+ );
+ /** test singleton partial day event*/
+ $vCalendarNew = clone $this->vCalendar1a;
+ $vCalendarOld = clone $this->vCalendar1a;
+ // construct event reader
+ $eventReaderNew = new EventReader($vCalendarNew, $vCalendarNew->VEVENT[0]->UID->getValue());
+ // alter old event label/title
+ $vCalendarOld->VEVENT[0]->SUMMARY->setValue('Testing Singleton Event');
+ // define expected output
$expected = [
- 'meeting_when' => $this->service->generateWhenString($newVevent),
+ 'meeting_when' => $this->service->generateWhenString($eventReaderNew),
'meeting_description' => '',
- 'meeting_title' => 'Second Breakfast',
+ 'meeting_title' => 'Testing Event',
'meeting_location' => '',
'meeting_url' => '',
'meeting_url_html' => '',
- 'meeting_when_html' => $this->service->generateWhenString($newVevent),
- 'meeting_title_html' => sprintf("<span style='text-decoration: line-through'>%s</span><br />%s", 'Elevenses', 'Second Breakfast'),
+ 'meeting_when_html' => $this->service->generateWhenString($eventReaderNew),
+ 'meeting_title_html' => sprintf("<span style='text-decoration: line-through'>%s</span><br />%s", 'Testing Singleton Event', 'Testing Event'),
'meeting_description_html' => '',
'meeting_location_html' => ''
];
-
- $actual = $this->service->buildBodyData($newVevent, $oldVevent);
-
- $this->assertEquals($expected, $actual);
- }
-
- public function testGenerateWhenStringHourlyEvent(): void {
- $vCalendar = new VCalendar();
- $vevent = new VEvent($vCalendar, 'two', [
- 'UID' => 'uid-1234',
- 'SEQUENCE' => 1,
- 'LAST-MODIFIED' => 456789,
- 'SUMMARY' => 'Elevenses',
- 'TZID' => 'Europe/Vienna',
- 'DTSTART' => (new \DateTime('2016-01-01 08:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')),
- 'DTEND' => (new \DateTime('2016-01-01 09:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')),
- ]);
-
- $this->l10n->expects(self::exactly(3))
- ->method('l')
- ->withConsecutive(
- ['weekdayName', (new \DateTime('2016-01-01 08:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), ['width' => 'abbreviated']],
- ['datetime', (new \DateTime('2016-01-01 08:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), ['width' => 'medium|short']],
- ['time', (new \DateTime('2016-01-01 09:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), ['width' => 'short']]
- )->willReturnOnConsecutiveCalls(
- 'Fr.',
- '01.01. 08:00',
- '09:00'
- );
-
- $expected = 'Fr., 01.01. 08:00 - 09:00 (Europe/Vienna)';
- $actual = $this->service->generateWhenString($vevent);
+ // generate actual output
+ $actual = $this->service->buildBodyData($vCalendarNew->VEVENT[0], $vCalendarOld->VEVENT[0]);
+ // test output
$this->assertEquals($expected, $actual);
}
@@ -248,4 +331,1870 @@ class IMipServiceTest extends TestCase {
$occurrence = $this->service->getLastOccurrence($vCalendar);
$this->assertEquals(1451606400, $occurrence);
}
+
+ public function testGenerateWhenStringSingular(): void {
+
+ // construct l10n return(s)
+ $this->l10n->method('l')->willReturnCallback(
+ function ($v1, $v2, $v3) {
+ return match (true) {
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM',
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM',
+ $v1 === 'date' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'full'] => 'July 1, 2024',
+ $v1 === 'date' && $v2 == (new \DateTime('20240701T000000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'full'] => 'July 1, 2024'
+ };
+ }
+ );
+ $this->l10n->method('t')->willReturnMap([
+ [
+ 'In the past on %1$s for the entire day',
+ ['July 1, 2024'],
+ 'In the past on July 1, 2024 for the entire day'
+ ],
+ [
+ 'In the past on %1$s between %2$s - %3$s',
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In the past on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ ]);
+ $this->l10n->method('n')->willReturnMap([
+ // singular entire day
+ [
+ 'In a minute on %1$s for the entire day',
+ 'In %n minutes on %1$s for the entire day',
+ 1,
+ ['July 1, 2024'],
+ 'In a minute on July 1, 2024 for the entire day'
+ ],
+ [
+ 'In a hour on %1$s for the entire day',
+ 'In %n hours on %1$s for the entire day',
+ 1,
+ ['July 1, 2024'],
+ 'In a hour on July 1, 2024 for the entire day'
+ ],
+ [
+ 'In a day on %1$s for the entire day',
+ 'In %n days on %1$s for the entire day',
+ 1,
+ ['July 1, 2024'],
+ 'In a day on July 1, 2024 for the entire day'
+ ],
+ [
+ 'In a week on %1$s for the entire day',
+ 'In %n weeks on %1$s for the entire day',
+ 1,
+ ['July 1, 2024'],
+ 'In a week on July 1, 2024 for the entire day'
+ ],
+ [
+ 'In a month on %1$s for the entire day',
+ 'In %n months on %1$s for the entire day',
+ 1,
+ ['July 1, 2024'],
+ 'In a month on July 1, 2024 for the entire day'
+ ],
+ [
+ 'In a year on %1$s for the entire day',
+ 'In %n years on %1$s for the entire day',
+ 1,
+ ['July 1, 2024'],
+ 'In a year on July 1, 2024 for the entire day'
+ ],
+ // plural entire day
+ [
+ 'In a minute on %1$s for the entire day',
+ 'In %n minutes on %1$s for the entire day',
+ 2,
+ ['July 1, 2024'],
+ 'In 2 minutes on July 1, 2024 for the entire day'
+ ],
+ [
+ 'In a hour on %1$s for the entire day',
+ 'In %n hours on %1$s for the entire day',
+ 2,
+ ['July 1, 2024'],
+ 'In 2 hours on July 1, 2024 for the entire day'
+ ],
+ [
+ 'In a day on %1$s for the entire day',
+ 'In %n days on %1$s for the entire day',
+ 2,
+ ['July 1, 2024'],
+ 'In 2 days on July 1, 2024 for the entire day'
+ ],
+ [
+ 'In a week on %1$s for the entire day',
+ 'In %n weeks on %1$s for the entire day',
+ 2,
+ ['July 1, 2024'],
+ 'In 2 weeks on July 1, 2024 for the entire day'
+ ],
+ [
+ 'In a month on %1$s for the entire day',
+ 'In %n months on %1$s for the entire day',
+ 2,
+ ['July 1, 2024'],
+ 'In 2 months on July 1, 2024 for the entire day'
+ ],
+ [
+ 'In a year on %1$s for the entire day',
+ 'In %n years on %1$s for the entire day',
+ 2,
+ ['July 1, 2024'],
+ 'In 2 years on July 1, 2024 for the entire day'
+ ],
+ // singular partial day
+ [
+ 'In a minute on %1$s between %2$s - %3$s',
+ 'In %n minutes on %1$s between %2$s - %3$s',
+ 1,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In a minute on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ [
+ 'In a hour on %1$s between %2$s - %3$s',
+ 'In %n hours on %1$s between %2$s - %3$s',
+ 1,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In a hour on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ [
+ 'In a day on %1$s between %2$s - %3$s',
+ 'In %n days on %1$s between %2$s - %3$s',
+ 1,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ [
+ 'In a week on %1$s between %2$s - %3$s',
+ 'In %n weeks on %1$s between %2$s - %3$s',
+ 1,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In a week on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ [
+ 'In a month on %1$s between %2$s - %3$s',
+ 'In %n months on %1$s between %2$s - %3$s',
+ 1,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In a month on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ [
+ 'In a year on %1$s between %2$s - %3$s',
+ 'In %n years on %1$s between %2$s - %3$s',
+ 1,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In a year on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ // plural partial day
+ [
+ 'In a minute on %1$s between %2$s - %3$s',
+ 'In %n minutes on %1$s between %2$s - %3$s',
+ 2,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In 2 minutes on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ [
+ 'In a hour on %1$s between %2$s - %3$s',
+ 'In %n hours on %1$s between %2$s - %3$s',
+ 2,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In 2 hours on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ [
+ 'In a day on %1$s between %2$s - %3$s',
+ 'In %n days on %1$s between %2$s - %3$s',
+ 2,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In 2 days on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ [
+ 'In a week on %1$s between %2$s - %3$s',
+ 'In %n weeks on %1$s between %2$s - %3$s',
+ 2,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In 2 weeks on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ [
+ 'In a month on %1$s between %2$s - %3$s',
+ 'In %n months on %1$s between %2$s - %3$s',
+ 2,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In 2 months on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ [
+ 'In a year on %1$s between %2$s - %3$s',
+ 'In %n years on %1$s between %2$s - %3$s',
+ 2,
+ ['July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'],
+ 'In 2 years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'
+ ],
+ ]);
+
+ // construct time factory return(s)
+ $this->timeFactory->method('getDateTime')->willReturnOnConsecutiveCalls(
+ // past interval test dates
+ (new \DateTime('20240702T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240703T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240702T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240703T170000', (new \DateTimeZone('America/Toronto')))),
+ // minute interval test dates
+ (new \DateTime('20240701T075900', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240630T235900', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240701T075800', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240630T235800', (new \DateTimeZone('America/Toronto')))),
+ // hour interval test dates
+ (new \DateTime('20240701T070000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240630T230000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240701T060000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240630T220000', (new \DateTimeZone('America/Toronto')))),
+ // day interval test dates
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ // week interval test dates
+ (new \DateTime('20240621T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240621T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240614T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240614T170000', (new \DateTimeZone('America/Toronto')))),
+ // month interval test dates
+ (new \DateTime('20240530T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240530T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240430T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240430T170000', (new \DateTimeZone('America/Toronto')))),
+ // year interval test dates
+ (new \DateTime('20230630T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20230630T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20220630T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20220630T170000', (new \DateTimeZone('America/Toronto'))))
+ );
+
+ /** test partial day event in 1 day in the past*/
+ $vCalendar = clone $this->vCalendar1a;
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ $this->assertEquals(
+ 'In the past on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 1 day in the past*/
+ $vCalendar = clone $this->vCalendar2;
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ $this->assertEquals(
+ 'In the past on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test partial day event in 2 days in the past*/
+ $vCalendar = clone $this->vCalendar1a;
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ $this->assertEquals(
+ 'In the past on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 2 days in the past*/
+ $vCalendar = clone $this->vCalendar2;
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ $this->assertEquals(
+ 'In the past on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test partial day event in 1 minute*/
+ $vCalendar = clone $this->vCalendar1a;
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ $this->assertEquals(
+ 'In a minute on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 1 minute*/
+ $vCalendar = clone $this->vCalendar2;
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ $this->assertEquals(
+ 'In a minute on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test partial day event in 2 minutes*/
+ $vCalendar = clone $this->vCalendar1a;
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ $this->assertEquals(
+ 'In 2 minutes on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 2 minutes*/
+ $vCalendar = clone $this->vCalendar2;
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ $this->assertEquals(
+ 'In 2 minutes on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test partial day event in 1 hour*/
+ $vCalendar = clone $this->vCalendar1a;
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ $this->assertEquals(
+ 'In a hour on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 1 hour*/
+ $vCalendar = clone $this->vCalendar2;
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ $this->assertEquals(
+ 'In a hour on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test partial day event in 2 hours*/
+ $vCalendar = clone $this->vCalendar1a;
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ $this->assertEquals(
+ 'In 2 hours on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 2 hours*/
+ $vCalendar = clone $this->vCalendar2;
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ $this->assertEquals(
+ 'In 2 hours on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test patrial day event in 1 day*/
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 1 day*/
+ $vCalendar = clone $this->vCalendar2;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test patrial day event in 2 days*/
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 2 days*/
+ $vCalendar = clone $this->vCalendar2;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test patrial day event in 1 week*/
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a week on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 1 week*/
+ $vCalendar = clone $this->vCalendar2;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a week on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test patrial day event in 2 weeks*/
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 weeks on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 2 weeks*/
+ $vCalendar = clone $this->vCalendar2;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 weeks on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test patrial day event in 1 month*/
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a month on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 1 month*/
+ $vCalendar = clone $this->vCalendar2;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a month on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test patrial day event in 2 months*/
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 months on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 2 months*/
+ $vCalendar = clone $this->vCalendar2;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 months on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test patrial day event in 1 year*/
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a year on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 1 year*/
+ $vCalendar = clone $this->vCalendar2;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a year on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test patrial day event in 2 years*/
+ $vCalendar = clone $this->vCalendar1a;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event in 2 years*/
+ $vCalendar = clone $this->vCalendar2;
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 years on July 1, 2024 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ }
+
+ public function testGenerateWhenStringRecurringDaily(): void {
+
+ // construct l10n return maps
+ $this->l10n->method('l')->willReturnCallback(
+ function ($v1, $v2, $v3) {
+ return match (true) {
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM',
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM',
+ $v1 === 'date' && $v2 == (new \DateTime('20240713T080000', (new \DateTimeZone('UTC')))) && $v3 == ['width' => 'long'] => 'July 13, 2024'
+ };
+ }
+ );
+ $this->l10n->method('t')->willReturnMap([
+ ['Every Day for the entire day', [], 'Every Day for the entire day'],
+ ['Every Day for the entire day until %1$s', ['July 13, 2024'], 'Every Day for the entire day until July 13, 2024'],
+ ['Every Day between %1$s - %2$s', ['8:00 AM', '9:00 AM (America/Toronto)'], 'Every Day between 8:00 AM - 9:00 AM (America/Toronto)'],
+ ['Every Day between %1$s - %2$s until %3$s', ['8:00 AM', '9:00 AM (America/Toronto)', 'July 13, 2024'], 'Every Day between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024'],
+ ['Every %1$d Days for the entire day', [3], 'Every 3 Days for the entire day'],
+ ['Every %1$d Days for the entire day until %2$s', [3, 'July 13, 2024'], 'Every 3 Days for the entire day until July 13, 2024'],
+ ['Every %1$d Days between %2$s - %3$s', [3, '8:00 AM', '9:00 AM (America/Toronto)'], 'Every 3 Days between 8:00 AM - 9:00 AM (America/Toronto)'],
+ ['Every %1$d Days between %2$s - %3$s until %4$s', [3, '8:00 AM', '9:00 AM (America/Toronto)', 'July 13, 2024'], 'Every 3 Days between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024'],
+ ['Could not generate event recurrence statement', [], 'Could not generate event recurrence statement'],
+ ]);
+
+ /** test partial day event with every day interval and no conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=1;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Day between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test partial day event with every day interval and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=1;UNTIL=20240713T080000Z');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Day between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test partial day event every 3rd day interval and no conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=3;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 3 Days between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test partial day event with every 3rd day interval and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=3;UNTIL=20240713T080000Z');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 3 Days between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event with every day interval and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=1;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Day for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event with every day interval and conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=1;UNTIL=20240713T080000Z');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Day for the entire day until July 13, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event with every 3rd day interval and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=3;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 3 Days for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event with every 3rd day interval and conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=3;UNTIL=20240713T080000Z');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 3 Days for the entire day until July 13, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ }
+
+ public function testGenerateWhenStringRecurringWeekly(): void {
+
+ // construct l10n return maps
+ $this->l10n->method('l')->willReturnCallback(
+ function ($v1, $v2, $v3) {
+ return match (true) {
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM',
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM',
+ $v1 === 'date' && $v2 == (new \DateTime('20240722T080000', (new \DateTimeZone('UTC')))) && $v3 == ['width' => 'long'] => 'July 13, 2024'
+ };
+ }
+ );
+ $this->l10n->method('t')->willReturnMap([
+ ['Every Week on %1$s for the entire day', ['Monday, Wednesday, Friday'], 'Every Week on Monday, Wednesday, Friday for the entire day'],
+ ['Every Week on %1$s for the entire day until %2$s', ['Monday, Wednesday, Friday', 'July 13, 2024'], 'Every Week on Monday, Wednesday, Friday for the entire day until July 13, 2024'],
+ ['Every Week on %1$s between %2$s - %3$s', ['Monday, Wednesday, Friday', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every Week on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto)'],
+ ['Every Week on %1$s between %2$s - %3$s until %4$s', ['Monday, Wednesday, Friday', '8:00 AM', '9:00 AM (America/Toronto)', 'July 13, 2024'], 'Every Week on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024'],
+ ['Every %1$d Weeks on %2$s for the entire day', [2, 'Monday, Wednesday, Friday'], 'Every 2 Weeks on Monday, Wednesday, Friday for the entire day'],
+ ['Every %1$d Weeks on %2$s for the entire day until %3$s', [2, 'Monday, Wednesday, Friday', 'July 13, 2024'], 'Every 2 Weeks on Monday, Wednesday, Friday for the entire day until July 13, 2024'],
+ ['Every %1$d Weeks on %2$s between %3$s - %4$s', [2, 'Monday, Wednesday, Friday', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every 2 Weeks on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto)'],
+ ['Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s', [2, 'Monday, Wednesday, Friday', '8:00 AM', '9:00 AM (America/Toronto)', 'July 13, 2024'], 'Every 2 Weeks on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024'],
+ ['Could not generate event recurrence statement', [], 'Could not generate event recurrence statement'],
+ ['Monday', [], 'Monday'],
+ ['Wednesday', [], 'Wednesday'],
+ ['Friday', [], 'Friday'],
+ ]);
+
+ /** test partial day event with every week interval on Mon, Wed, Fri and no conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Week on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test partial day event with every week interval on Mon, Wed, Fri and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20240722T080000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Week on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test partial day event with every 2nd week interval on Mon, Wed, Fri and no conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;INTERVAL=2;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Weeks on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test partial day event with every 2nd week interval on Mon, Wed, Fri and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;INTERVAL=2;UNTIL=20240722T080000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Weeks on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event with every week interval on Mon, Wed, Fri and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Week on Monday, Wednesday, Friday for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event with every week interval on Mon, Wed, Fri and conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20240722T080000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Week on Monday, Wednesday, Friday for the entire day until July 13, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event with every 2nd week interval on Mon, Wed, Fri and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;INTERVAL=2;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Weeks on Monday, Wednesday, Friday for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event with every 2nd week interval on Mon, Wed, Fri and conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;INTERVAL=2;UNTIL=20240722T080000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Weeks on Monday, Wednesday, Friday for the entire day until July 13, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ }
+
+ public function testGenerateWhenStringRecurringMonthly(): void {
+
+ // construct l10n return maps
+ $this->l10n->method('l')->willReturnCallback(
+ function ($v1, $v2, $v3) {
+ return match (true) {
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM',
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM',
+ $v1 === 'date' && $v2 == (new \DateTime('20241231T080000', (new \DateTimeZone('UTC')))) && $v3 == ['width' => 'long'] => 'December 31, 2024'
+ };
+ }
+ );
+ $this->l10n->method('t')->willReturnMap([
+ ['Every Month on the %1$s for the entire day', ['1, 8'], 'Every Month on the 1, 8 for the entire day'],
+ ['Every Month on the %1$s for the entire day until %2$s', ['1, 8', 'December 31, 2024'], 'Every Month on the 1, 8 for the entire day until December 31, 2024'],
+ ['Every Month on the %1$s between %2$s - %3$s', ['1, 8', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every Month on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto)'],
+ ['Every Month on the %1$s between %2$s - %3$s until %4$s', ['1, 8', '8:00 AM', '9:00 AM (America/Toronto)', 'December 31, 2024'], 'Every Month on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024'],
+ ['Every %1$d Months on the %2$s for the entire day', [2, '1, 8'], 'Every 2 Months on the 1, 8 for the entire day'],
+ ['Every %1$d Months on the %2$s for the entire day until %3$s', [2, '1, 8', 'December 31, 2024'], 'Every 2 Months on the 1, 8 for the entire day until December 31, 2024'],
+ ['Every %1$d Months on the %2$s between %3$s - %4$s', [2, '1, 8', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every 2 Months on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto)'],
+ ['Every %1$d Months on the %2$s between %3$s - %4$s until %5$s', [2, '1, 8', '8:00 AM', '9:00 AM (America/Toronto)', 'December 31, 2024'], 'Every 2 Months on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024'],
+ ['Every Month on the %1$s for the entire day', ['First Sunday, Saturday'], 'Every Month on the First Sunday, Saturday for the entire day'],
+ ['Every Month on the %1$s for the entire day until %2$s', ['First Sunday, Saturday', 'December 31, 2024'], 'Every Month on the First Sunday, Saturday for the entire day until December 31, 2024'],
+ ['Every Month on the %1$s between %2$s - %3$s', ['First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every Month on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)'],
+ ['Every Month on the %1$s between %2$s - %3$s until %4$s', ['First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)', 'December 31, 2024'], 'Every Month on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024'],
+ ['Every %1$d Months on the %2$s for the entire day', [2, 'First Sunday, Saturday'], 'Every 2 Months on the First Sunday, Saturday for the entire day'],
+ ['Every %1$d Months on the %2$s for the entire day until %3$s', [2, 'First Sunday, Saturday', 'December 31, 2024'], 'Every 2 Months on the First Sunday, Saturday for the entire day until December 31, 2024'],
+ ['Every %1$d Months on the %2$s between %3$s - %4$s', [2, 'First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every 2 Months on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)'],
+ ['Every %1$d Months on the %2$s between %3$s - %4$s until %5$s', [2, 'First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)', 'December 31, 2024'], 'Every 2 Months on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024'],
+ ['Could not generate event recurrence statement', [], 'Could not generate event recurrence statement'],
+ ['Saturday', [], 'Saturday'],
+ ['Sunday', [], 'Sunday'],
+ ['First', [], 'First'],
+ ]);
+
+ /** test absolute partial day event with every month interval on 1st, 8th and no conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Month on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute partial day event with every Month interval on 1st, 8th and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;UNTIL=20241231T080000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Month on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute partial day event with every 2nd Month interval on 1st, 8th and no conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;INTERVAL=2;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Months on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute partial day event with every 2nd Month interval on 1st, 8th and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;INTERVAL=2;UNTIL=20241231T080000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Months on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute entire day event with every Month interval on 1st, 8th and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Month on the 1, 8 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute entire day event with every Month interval on 1st, 8th and conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;UNTIL=20241231T080000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Month on the 1, 8 for the entire day until December 31, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute entire day event with every 2nd Month interval on 1st, 8th and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;INTERVAL=2;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Months on the 1, 8 for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute entire day event with every 2nd Month interval on 1st, 8th and conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;INTERVAL=2;UNTIL=20241231T080000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Months on the 1, 8 for the entire day until December 31, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative partial day event with every month interval on the 1st Saturday, Sunday and no conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Month on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative partial day event with every Month interval on the 1st Saturday, Sunday and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;UNTIL=20241231T080000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Month on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative partial day event with every 2nd Month interval on the 1st Saturday, Sunday and no conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Months on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative partial day event with every 2nd Month interval on the 1st Saturday, Sunday and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;UNTIL=20241231T080000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Months on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative entire day event with every Month interval on the 1st Saturday, Sunday and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Month on the First Sunday, Saturday for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative entire day event with every Month interval on the 1st Saturday, Sunday and conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;UNTIL=20241231T080000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Month on the First Sunday, Saturday for the entire day until December 31, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative entire day event with every 2nd Month interval on the 1st Saturday, Sunday and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Months on the First Sunday, Saturday for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative entire day event with every 2nd Month interval on the 1st Saturday, Sunday and conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;UNTIL=20241231T080000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Months on the First Sunday, Saturday for the entire day until December 31, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ }
+
+ public function testGenerateWhenStringRecurringYearly(): void {
+
+ // construct l10n return maps
+ $this->l10n->method('l')->willReturnCallback(
+ function ($v1, $v2, $v3) {
+ return match (true) {
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM',
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM',
+ $v1 === 'date' && $v2 == (new \DateTime('20260731T040000', (new \DateTimeZone('UTC')))) && $v3 == ['width' => 'long'] => 'July 31, 2026'
+ };
+ }
+ );
+ $this->l10n->method('t')->willReturnMap([
+ ['Every Year in %1$s on the %2$s for the entire day', ['July', '1st'], 'Every Year in July on the 1st for the entire day'],
+ ['Every Year in %1$s on the %2$s for the entire day until %3$s', ['July', '1st', 'July 31, 2026'], 'Every Year in July on the 1st for the entire day until July 31, 2026'],
+ ['Every Year in %1$s on the %2$s between %3$s - %4$s', ['July', '1st', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every Year in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto)'],
+ ['Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s', ['July', '1st', '8:00 AM', '9:00 AM (America/Toronto)', 'July 31, 2026'], 'Every Year in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026'],
+ ['Every %1$d Years in %2$s on the %3$s for the entire day', [2, 'July', '1st'], 'Every 2 Years in July on the 1st for the entire day'],
+ ['Every %1$d Years in %2$s on the %3$s for the entire day until %4$s', [2, 'July', '1st', 'July 31, 2026'], 'Every 2 Years in July on the 1st for the entire day until July 31, 2026'],
+ ['Every %1$d Years in %2$s on the %3$s between %4$s - %5$s', [2, 'July', '1st', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every 2 Years in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto)'],
+ ['Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s', [2, 'July', '1st', '8:00 AM', '9:00 AM (America/Toronto)', 'July 31, 2026'], 'Every 2 Years in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026'],
+ ['Every Year in %1$s on the %2$s for the entire day', ['July', 'First Sunday, Saturday'], 'Every Year in July on the First Sunday, Saturday for the entire day'],
+ ['Every Year in %1$s on the %2$s for the entire day until %3$s', ['July', 'First Sunday, Saturday', 'July 31, 2026'], 'Every Year in July on the First Sunday, Saturday for the entire day until July 31, 2026'],
+ ['Every Year in %1$s on the %2$s between %3$s - %4$s', ['July', 'First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every Year in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)'],
+ ['Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s', ['July', 'First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)', 'July 31, 2026'], 'Every Year in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026'],
+ ['Every %1$d Years in %2$s on the %3$s for the entire day', [2, 'July', 'First Sunday, Saturday'], 'Every 2 Years in July on the First Sunday, Saturday for the entire day'],
+ ['Every %1$d Years in %2$s on the %3$s for the entire day until %4$s', [2, 'July', 'First Sunday, Saturday', 'July 31, 2026'], 'Every 2 Years in July on the First Sunday, Saturday for the entire day until July 31, 2026'],
+ ['Every %1$d Years in %2$s on the %3$s between %4$s - %5$s', [2, 'July', 'First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every 2 Years in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)'],
+ ['Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s', [2, 'July', 'First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)', 'July 31, 2026'], 'Every 2 Years in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026'],
+ ['Could not generate event recurrence statement', [], 'Could not generate event recurrence statement'],
+ ['July', [], 'July'],
+ ['Saturday', [], 'Saturday'],
+ ['Sunday', [], 'Sunday'],
+ ['First', [], 'First'],
+ ]);
+
+ /** test absolute partial day event with every year interval on July 1 and no conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Year in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute partial day event with every year interval on July 1 and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;UNTIL=20260731T040000Z');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Year in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute partial day event with every 2nd year interval on July 1 and no conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;INTERVAL=2;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Years in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute partial day event with every 2nd year interval on July 1 and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;INTERVAL=2;UNTIL=20260731T040000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Years in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute entire day event with every year interval on July 1 and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Year in July on the 1st for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute entire day event with every year interval on July 1 and conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;UNTIL=20260731T040000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Year in July on the 1st for the entire day until July 31, 2026',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute entire day event with every 2nd year interval on July 1 and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;INTERVAL=2;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Years in July on the 1st for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test absolute entire day event with every 2nd year interval on July 1 and conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;INTERVAL=2;UNTIL=20260731T040000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Years in July on the 1st for the entire day until July 31, 2026',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative partial day event with every year interval on the 1st Saturday, Sunday in July and no conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Year in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative partial day event with every year interval on the 1st Saturday, Sunday in July and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;UNTIL=20260731T040000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Year in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative partial day event with every 2nd year interval on the 1st Saturday, Sunday in July and no conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Years in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative partial day event with every 2nd year interval on the 1st Saturday, Sunday in July and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;UNTIL=20260731T040000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Years in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative entire day event with every year interval on the 1st Saturday, Sunday in July and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Year in July on the First Sunday, Saturday for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative entire day event with every year interval on the 1st Saturday, Sunday in July and conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;UNTIL=20260731T040000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every Year in July on the First Sunday, Saturday for the entire day until July 31, 2026',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative entire day event with every 2nd year interval on the 1st Saturday, Sunday in July and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Years in July on the First Sunday, Saturday for the entire day',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test relative entire day event with every 2nd year interval on the 1st Saturday, Sunday in July and conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;UNTIL=20260731T040000Z;');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'Every 2 Years in July on the First Sunday, Saturday for the entire day until July 31, 2026',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ }
+
+ public function testGenerateWhenStringRecurringFixed(): void {
+
+ // construct l10n return maps
+ $this->l10n->method('l')->willReturnCallback(
+ function ($v1, $v2, $v3) {
+ return match (true) {
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM',
+ $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM',
+ $v1 === 'date' && $v2 == (new \DateTime('20240713T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 13, 2024'
+ };
+ }
+ );
+ $this->l10n->method('t')->willReturnMap([
+ ['On specific dates for the entire day until %1$s', ['July 13, 2024'], 'On specific dates for the entire day until July 13, 2024'],
+ ['On specific dates between %1$s - %2$s until %3$s', ['8:00 AM', '9:00 AM (America/Toronto)', 'July 13, 2024'], 'On specific dates between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024'],
+ ]);
+
+ /** test partial day event with every day interval and conclusion*/
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703T080000,20240709T080000,20240713T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'On specific dates between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ /** test entire day event with every day interval and no conclusion*/
+ $vCalendar = clone $this->vCalendar2;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703T080000,20240709T080000,20240713T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'On specific dates for the entire day until July 13, 2024',
+ $this->service->generateWhenString($eventReader)
+ );
+
+ }
+
+ public function testGenerateOccurringStringWithRrule(): void {
+
+ // construct l10n return(s)
+ $this->l10n->method('l')->willReturnCallback(
+ function ($v1, $v2, $v3) {
+ return match (true) {
+ $v1 === 'date' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 1, 2024',
+ $v1 === 'date' && $v2 == (new \DateTime('20240703T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 3, 2024',
+ $v1 === 'date' && $v2 == (new \DateTime('20240705T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 5, 2024'
+ };
+ }
+ );
+ $this->l10n->method('n')->willReturnMap([
+ // singular
+ [
+ 'In a day on %1$s',
+ 'In %n days on %1$s',
+ 1,
+ ['July 1, 2024'],
+ 'In a day on July 1, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s',
+ 'In %n days on %1$s then on %2$s',
+ 1,
+ ['July 1, 2024', 'July 3, 2024'],
+ 'In a day on July 1, 2024 then on July 3, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s and %3$s',
+ 'In %n days on %1$s then on %2$s and %3$s',
+ 1,
+ ['July 1, 2024', 'July 3, 2024', 'July 5, 2024'],
+ 'In a day on July 1, 2024 then on July 3, 2024 and July 5, 2024'
+ ],
+ // plural
+ [
+ 'In a day on %1$s',
+ 'In %n days on %1$s',
+ 2,
+ ['July 1, 2024'],
+ 'In 2 days on July 1, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s',
+ 'In %n days on %1$s then on %2$s',
+ 2,
+ ['July 1, 2024', 'July 3, 2024'],
+ 'In 2 days on July 1, 2024 then on July 3, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s and %3$s',
+ 'In %n days on %1$s then on %2$s and %3$s',
+ 2,
+ ['July 1, 2024', 'July 3, 2024', 'July 5, 2024'],
+ 'In 2 days on July 1, 2024 then on July 3, 2024 and July 5, 2024'
+ ],
+ ]);
+
+ // construct time factory return(s)
+ $this->timeFactory->method('getDateTime')->willReturnOnConsecutiveCalls(
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ );
+
+ /** test patrial day recurring event in 1 day with single occurrence remaining */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=1');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024',
+ $this->service->generateOccurringString($eventReader)
+ );
+
+ /** test patrial day recurring event in 1 day with two occurrences remaining */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=2');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024 then on July 3, 2024',
+ $this->service->generateOccurringString($eventReader)
+ );
+
+ /** test patrial day recurring event in 1 day with three occurrences remaining */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=3');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024 then on July 3, 2024 and July 5, 2024',
+ $this->service->generateOccurringString($eventReader)
+ );
+
+ /** test patrial day recurring event in 2 days with single occurrence remaining */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=1');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024',
+ $this->service->generateOccurringString($eventReader)
+ );
+
+ /** test patrial day recurring event in 2 days with two occurrences remaining */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=2');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024 then on July 3, 2024',
+ $this->service->generateOccurringString($eventReader)
+ );
+
+ /** test patrial day recurring event in 2 days with three occurrences remaining */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=3');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024 then on July 3, 2024 and July 5, 2024',
+ $this->service->generateOccurringString($eventReader)
+ );
+ }
+
+ public function testGenerateOccurringStringWithRdate(): void {
+
+ // construct l10n return(s)
+ $this->l10n->method('l')->willReturnCallback(
+ function ($v1, $v2, $v3) {
+ return match (true) {
+ $v1 === 'date' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 1, 2024',
+ $v1 === 'date' && $v2 == (new \DateTime('20240703T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 3, 2024',
+ $v1 === 'date' && $v2 == (new \DateTime('20240705T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 5, 2024'
+ };
+ }
+ );
+ $this->l10n->method('n')->willReturnMap([
+ // singular
+ [
+ 'In a day on %1$s',
+ 'In %n days on %1$s',
+ 1,
+ ['July 1, 2024'],
+ 'In a day on July 1, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s',
+ 'In %n days on %1$s then on %2$s',
+ 1,
+ ['July 1, 2024', 'July 3, 2024'],
+ 'In a day on July 1, 2024 then on July 3, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s and %3$s',
+ 'In %n days on %1$s then on %2$s and %3$s',
+ 1,
+ ['July 1, 2024', 'July 3, 2024', 'July 5, 2024'],
+ 'In a day on July 1, 2024 then on July 3, 2024 and July 5, 2024'
+ ],
+ // plural
+ [
+ 'In a day on %1$s',
+ 'In %n days on %1$s',
+ 2,
+ ['July 1, 2024'],
+ 'In 2 days on July 1, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s',
+ 'In %n days on %1$s then on %2$s',
+ 2,
+ ['July 1, 2024', 'July 3, 2024'],
+ 'In 2 days on July 1, 2024 then on July 3, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s and %3$s',
+ 'In %n days on %1$s then on %2$s and %3$s',
+ 2,
+ ['July 1, 2024', 'July 3, 2024', 'July 5, 2024'],
+ 'In 2 days on July 1, 2024 then on July 3, 2024 and July 5, 2024'
+ ],
+ ]);
+
+ // construct time factory return(s)
+ $this->timeFactory->method('getDateTime')->willReturnOnConsecutiveCalls(
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ );
+
+ /** test patrial day recurring event in 1 day with single occurrence remaining */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240701T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 1 day with single occurrence remaining'
+ );
+
+ /** test patrial day recurring event in 1 day with two occurrences remaining */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240701T080000,20240703T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024 then on July 3, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 1 day with two occurrences remaining'
+ );
+
+ /** test patrial day recurring event in 1 day with three occurrences remaining */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240701T080000,20240703T080000,20240705T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024 then on July 3, 2024 and July 5, 2024',
+ $this->service->generateOccurringString($eventReader),
+ ''
+ );
+
+ /** test patrial day recurring event in 2 days with single occurrences remaining */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240701T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024',
+ $this->service->generateOccurringString($eventReader),
+ ''
+ );
+
+ /** test patrial day recurring event in 2 days with two occurrences remaining */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240701T080000');
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024 then on July 3, 2024',
+ $this->service->generateOccurringString($eventReader),
+ ''
+ );
+
+ /** test patrial day recurring event in 2 days with three occurrences remaining */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RDATE', '20240701T080000');
+ $vCalendar->VEVENT[0]->add('RDATE', '20240703T080000');
+ $vCalendar->VEVENT[0]->add('RDATE', '20240705T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024 then on July 3, 2024 and July 5, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 2 days with three occurrences remaining'
+ );
+ }
+
+ public function testGenerateOccurringStringWithOneExdate(): void {
+
+ // construct l10n return(s)
+ $this->l10n->method('l')->willReturnCallback(
+ function ($v1, $v2, $v3) {
+ return match (true) {
+ $v1 === 'date' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 1, 2024',
+ $v1 === 'date' && $v2 == (new \DateTime('20240705T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 5, 2024',
+ $v1 === 'date' && $v2 == (new \DateTime('20240707T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 7, 2024'
+ };
+ }
+ );
+ $this->l10n->method('n')->willReturnMap([
+ // singular
+ [
+ 'In a day on %1$s',
+ 'In %n days on %1$s',
+ 1,
+ ['July 1, 2024'],
+ 'In a day on July 1, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s',
+ 'In %n days on %1$s then on %2$s',
+ 1,
+ ['July 1, 2024', 'July 5, 2024'],
+ 'In a day on July 1, 2024 then on July 5, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s and %3$s',
+ 'In %n days on %1$s then on %2$s and %3$s',
+ 1,
+ ['July 1, 2024', 'July 5, 2024', 'July 7, 2024'],
+ 'In a day on July 1, 2024 then on July 5, 2024 and July 7, 2024'
+ ],
+ // plural
+ [
+ 'In a day on %1$s',
+ 'In %n days on %1$s',
+ 2,
+ ['July 1, 2024'],
+ 'In 2 days on July 1, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s',
+ 'In %n days on %1$s then on %2$s',
+ 2,
+ ['July 1, 2024', 'July 5, 2024'],
+ 'In 2 days on July 1, 2024 then on July 5, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s and %3$s',
+ 'In %n days on %1$s then on %2$s and %3$s',
+ 2,
+ ['July 1, 2024', 'July 5, 2024', 'July 7, 2024'],
+ 'In 2 days on July 1, 2024 then on July 5, 2024 and July 7, 2024'
+ ],
+ ]);
+
+ // construct time factory return(s)
+ $this->timeFactory->method('getDateTime')->willReturnOnConsecutiveCalls(
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ );
+
+ /** test patrial day recurring event in 1 day with single occurrence remaining and one exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=1');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 1 day with single occurrence remaining and one exception'
+ );
+
+ /** test patrial day recurring event in 1 day with two occurrences remaining and one exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=2');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 1 day with two occurrences remaining and one exception'
+ );
+
+ /** test patrial day recurring event in 1 day with three occurrences remaining and one exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=3');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024 then on July 5, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 1 day with three occurrences remaining and one exception'
+ );
+
+ /** test patrial day recurring event in 1 day with four occurrences remaining and one exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=4');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024 then on July 5, 2024 and July 7, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 1 day with four occurrences remaining and one exception'
+ );
+
+ /** test patrial day recurring event in 2 days with single occurrences remaining and one exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=1');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 2 days with single occurrences remaining and one exception'
+ );
+
+ /** test patrial day recurring event in 2 days with two occurrences remaining and one exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=2');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 2 days with two occurrences remaining and one exception'
+ );
+
+ /** test patrial day recurring event in 2 days with three occurrences remaining and one exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=3');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024 then on July 5, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 2 days with three occurrences remaining and one exception'
+ );
+
+ /** test patrial day recurring event in 2 days with four occurrences remaining and one exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=4');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024 then on July 5, 2024 and July 7, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 2 days with four occurrences remaining and one exception'
+ );
+ }
+
+ public function testGenerateOccurringStringWithTwoExdate(): void {
+
+ // construct l10n return(s)
+ $this->l10n->method('l')->willReturnCallback(
+ function ($v1, $v2, $v3) {
+ return match (true) {
+ $v1 === 'date' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 1, 2024',
+ $v1 === 'date' && $v2 == (new \DateTime('20240705T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 5, 2024',
+ $v1 === 'date' && $v2 == (new \DateTime('20240709T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 9, 2024'
+ };
+ }
+ );
+ $this->l10n->method('n')->willReturnMap([
+ // singular
+ [
+ 'In a day on %1$s',
+ 'In %n days on %1$s',
+ 1,
+ ['July 1, 2024'],
+ 'In a day on July 1, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s',
+ 'In %n days on %1$s then on %2$s',
+ 1,
+ ['July 1, 2024', 'July 5, 2024'],
+ 'In a day on July 1, 2024 then on July 5, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s and %3$s',
+ 'In %n days on %1$s then on %2$s and %3$s',
+ 1,
+ ['July 1, 2024', 'July 5, 2024', 'July 9, 2024'],
+ 'In a day on July 1, 2024 then on July 5, 2024 and July 9, 2024'
+ ],
+ // plural
+ [
+ 'In a day on %1$s',
+ 'In %n days on %1$s',
+ 2,
+ ['July 1, 2024'],
+ 'In 2 days on July 1, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s',
+ 'In %n days on %1$s then on %2$s',
+ 2,
+ ['July 1, 2024', 'July 5, 2024'],
+ 'In 2 days on July 1, 2024 then on July 5, 2024'
+ ],
+ [
+ 'In a day on %1$s then on %2$s and %3$s',
+ 'In %n days on %1$s then on %2$s and %3$s',
+ 2,
+ ['July 1, 2024', 'July 5, 2024', 'July 9, 2024'],
+ 'In 2 days on July 1, 2024 then on July 5, 2024 and July 9, 2024'
+ ],
+ ]);
+
+ // construct time factory return(s)
+ $this->timeFactory->method('getDateTime')->willReturnOnConsecutiveCalls(
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))),
+ );
+
+ /** test patrial day recurring event in 1 day with single occurrence remaining and two exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=1');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240707T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 1 day with single occurrence remaining and two exception'
+ );
+
+ /** test patrial day recurring event in 1 day with two occurrences remaining and two exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=2');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240707T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 1 day with two occurrences remaining and two exception'
+ );
+
+ /** test patrial day recurring event in 1 day with three occurrences remaining and two exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=3');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240707T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024 then on July 5, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 1 day with three occurrences remaining and two exception'
+ );
+
+ /** test patrial day recurring event in 1 day with four occurrences remaining and two exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=5');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240707T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In a day on July 1, 2024 then on July 5, 2024 and July 9, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 1 day with four occurrences remaining and two exception'
+ );
+
+ /** test patrial day recurring event in 2 days with single occurrences remaining and two exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=1');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240707T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 2 days with single occurrences remaining and two exception'
+ );
+
+ /** test patrial day recurring event in 2 days with two occurrences remaining and two exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=2');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240707T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 2 days with two occurrences remaining and two exception'
+ );
+
+ /** test patrial day recurring event in 2 days with three occurrences remaining and two exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=3');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240707T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024 then on July 5, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 2 days with three occurrences remaining and two exception'
+ );
+
+ /** test patrial day recurring event in 2 days with five occurrences remaining and two exception */
+ $vCalendar = clone $this->vCalendar1a;
+ $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=5');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240703T080000');
+ $vCalendar->VEVENT[0]->add('EXDATE', '20240707T080000');
+ // construct event reader
+ $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
+ // test output
+ $this->assertEquals(
+ 'In 2 days on July 1, 2024 then on July 5, 2024 and July 9, 2024',
+ $this->service->generateOccurringString($eventReader),
+ 'test patrial day recurring event in 2 days with five occurrences remaining and two exception'
+ );
+ }
+
}
diff --git a/apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php b/apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php
index c727079a367..524ac556e19 100644
--- a/apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -8,6 +10,7 @@ namespace OCA\DAV\Tests\unit\CalDAV\Schedule;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CalDAV\CalendarHome;
+use OCA\DAV\CalDAV\DefaultCalendarValidator;
use OCA\DAV\CalDAV\Plugin as CalDAVPlugin;
use OCA\DAV\CalDAV\Schedule\Plugin;
use OCA\DAV\CalDAV\Trashbin\Plugin as TrashbinPlugin;
@@ -15,70 +18,68 @@ use OCP\IConfig;
use OCP\IL10N;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
+use Sabre\CalDAV\Backend\BackendInterface;
use Sabre\DAV\PropFind;
use Sabre\DAV\Server;
use Sabre\DAV\Tree;
use Sabre\DAV\Xml\Property\Href;
use Sabre\DAV\Xml\Property\LocalHref;
use Sabre\DAVACL\IPrincipal;
+use Sabre\HTTP\Request;
+use Sabre\HTTP\Response;
use Sabre\HTTP\ResponseInterface;
+use Sabre\VObject\Component\VCalendar;
+use Sabre\VObject\ITip\Message;
use Sabre\VObject\Parameter;
use Sabre\VObject\Property\ICalendar\CalAddress;
use Sabre\Xml\Service;
use Test\TestCase;
class PluginTest extends TestCase {
- /** @var Plugin */
- private $plugin;
- /** @var Server|MockObject */
- private $server;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var MockObject|LoggerInterface */
- private $logger;
+ private Plugin $plugin;
+ private Server&MockObject $server;
+ private IConfig&MockObject $config;
+ private LoggerInterface&MockObject $logger;
+ private DefaultCalendarValidator $calendarValidator;
protected function setUp(): void {
parent::setUp();
- $this->server = $this->createMock(Server::class);
$this->config = $this->createMock(IConfig::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->calendarValidator = new DefaultCalendarValidator();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->server->httpResponse = $response;
+ $this->server = $this->createMock(Server::class);
+ $this->server->httpResponse = $this->createMock(ResponseInterface::class);
$this->server->xml = new Service();
- $this->logger = $this->createMock(LoggerInterface::class);
-
- $this->plugin = new Plugin($this->config, $this->logger);
+ $this->plugin = new Plugin($this->config, $this->logger, $this->calendarValidator);
$this->plugin->initialize($this->server);
}
public function testInitialize(): void {
- $plugin = new Plugin($this->config, $this->logger);
-
- $this->server->expects($this->exactly(10))
+ $calls = [
+ // Sabre\CalDAV\Schedule\Plugin events
+ ['method:POST', [$this->plugin, 'httpPost'], 100],
+ ['propFind', [$this->plugin, 'propFind'], 100],
+ ['propPatch', [$this->plugin, 'propPatch'], 100],
+ ['calendarObjectChange', [$this->plugin, 'calendarObjectChange'], 100],
+ ['beforeUnbind', [$this->plugin, 'beforeUnbind'], 100],
+ ['schedule', [$this->plugin, 'scheduleLocalDelivery'], 100],
+ ['getSupportedPrivilegeSet', [$this->plugin, 'getSupportedPrivilegeSet'], 100],
+ // OCA\DAV\CalDAV\Schedule\Plugin events
+ ['propFind', [$this->plugin, 'propFindDefaultCalendarUrl'], 90],
+ ['afterWriteContent', [$this->plugin, 'dispatchSchedulingResponses'], 100],
+ ['afterCreateFile', [$this->plugin, 'dispatchSchedulingResponses'], 100],
+ ];
+ $this->server->expects($this->exactly(count($calls)))
->method('on')
- ->withConsecutive(
- // Sabre\CalDAV\Schedule\Plugin events
- ['method:POST', [$plugin, 'httpPost']],
- ['propFind', [$plugin, 'propFind']],
- ['propPatch', [$plugin, 'propPatch']],
- ['calendarObjectChange', [$plugin, 'calendarObjectChange']],
- ['beforeUnbind', [$plugin, 'beforeUnbind']],
- ['schedule', [$plugin, 'scheduleLocalDelivery']],
- ['getSupportedPrivilegeSet', [$plugin, 'getSupportedPrivilegeSet']],
- // OCA\DAV\CalDAV\Schedule\Plugin events
- ['propFind', [$plugin, 'propFindDefaultCalendarUrl'], 90],
- ['afterWriteContent', [$plugin, 'dispatchSchedulingResponses']],
- ['afterCreateFile', [$plugin, 'dispatchSchedulingResponses']]
- );
-
- $plugin->initialize($this->server);
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
+
+ $this->plugin->initialize($this->server);
}
public function testGetAddressesForPrincipal(): void {
@@ -104,7 +105,6 @@ class PluginTest extends TestCase {
$this->assertSame(['lukas@nextcloud.com', 'rullzer@nextcloud.com'], $result);
}
-
public function testGetAddressesForPrincipalEmpty(): void {
$this->server
->expects($this->once())
@@ -160,7 +160,7 @@ class PluginTest extends TestCase {
$this->assertFalse($this->invokePrivate($this->plugin, 'getAttendeeRSVP', [$property3]));
}
- public function propFindDefaultCalendarUrlProvider(): array {
+ public static function propFindDefaultCalendarUrlProvider(): array {
return [
[
'principals/users/myuser',
@@ -251,9 +251,7 @@ class PluginTest extends TestCase {
];
}
- /**
- * @dataProvider propFindDefaultCalendarUrlProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('propFindDefaultCalendarUrlProvider')]
public function testPropFindDefaultCalendarUrl(string $principalUri, ?string $calendarHome, bool $isResource, string $calendarUri, string $displayName, bool $exists, bool $deleted = false, bool $hasExistingCalendars = false, bool $propertiesForPath = true): void {
$propFind = new PropFind(
$principalUri,
@@ -262,7 +260,7 @@ class PluginTest extends TestCase {
],
0
);
- /** @var IPrincipal|MockObject $node */
+ /** @var IPrincipal&MockObject $node */
$node = $this->getMockBuilder(IPrincipal::class)
->disableOriginalConstructor()
->getMock();
@@ -340,12 +338,12 @@ class PluginTest extends TestCase {
if (!$exists || $deleted) {
if (!$hasExistingCalendars) {
$calendarBackend->expects($this->once())
- ->method('createCalendar')
- ->with($principalUri, $calendarUri, [
- '{DAV:}displayname' => $displayName,
- ]);
+ ->method('createCalendar')
+ ->with($principalUri, $calendarUri, [
+ '{DAV:}displayname' => $displayName,
+ ]);
- $calendarHomeObject->expects($this->once())
+ $calendarHomeObject->expects($this->exactly($deleted ? 2 : 1))
->method('getCalDAVBackend')
->with()
->willReturn($calendarBackend);
@@ -359,7 +357,7 @@ class PluginTest extends TestCase {
}
}
- /** @var Tree|MockObject $tree */
+ /** @var Tree&MockObject $tree */
$tree = $this->createMock(Tree::class);
$tree->expects($this->once())
->method('getNodeForPath')
@@ -373,7 +371,7 @@ class PluginTest extends TestCase {
$this->server->expects($this->once())
->method('getPropertiesForPath')
- ->with($calendarHome .'/' . $calendarUri, [], 1)
+ ->with($calendarHome . '/' . $calendarUri, [], 1)
->willReturn($properties);
$this->plugin->propFindDefaultCalendarUrl($propFind, $node);
@@ -385,6 +383,388 @@ class PluginTest extends TestCase {
/** @var LocalHref $result */
$result = $propFind->get(Plugin::SCHEDULE_DEFAULT_CALENDAR_URL);
- $this->assertEquals('/remote.php/dav/'. $calendarHome . '/' . $calendarUri, $result->getHref());
+ $this->assertEquals('/remote.php/dav/' . $calendarHome . '/' . $calendarUri, $result->getHref());
+ }
+
+ /**
+ * Test Calendar Event Creation for Personal Calendar
+ *
+ * Should generate 2 messages for attendees User 2 and User External
+ */
+ public function testCalendarObjectChangePersonalCalendarCreate(): void {
+
+ // define place holders
+ /** @var Message[] $iTipMessages */
+ $iTipMessages = [];
+ // construct calendar node
+ $calendarNode = new Calendar(
+ $this->createMock(BackendInterface::class),
+ [
+ 'uri' => 'personal',
+ 'principaluri' => 'principals/users/user1',
+ '{DAV:}displayname' => 'Calendar Shared By User1',
+ ],
+ $this->createMock(IL10N::class),
+ $this->config,
+ $this->logger
+ );
+ // construct server request object
+ $request = new Request(
+ 'PUT',
+ '/remote.php/dav/calendars/user1/personal/B0DC78AE-6DD7-47E3-80BE-89F23E6D5383.ics'
+ );
+ $request->setBaseUrl('/remote.php/dav/');
+ // construct server response object
+ $response = new Response();
+ // construct server tree object
+ $tree = $this->createMock(Tree::class);
+ $tree->expects($this->once())
+ ->method('getNodeForPath')
+ ->with('calendars/user1/personal')
+ ->willReturn($calendarNode);
+ // construct server properties and returns
+ $this->server->httpRequest = $request;
+ $this->server->tree = $tree;
+ $this->server->expects($this->exactly(1))->method('getProperties')
+ ->willReturnMap([
+ [
+ 'principals/users/user1',
+ ['{urn:ietf:params:xml:ns:caldav}calendar-user-address-set'],
+ ['{urn:ietf:params:xml:ns:caldav}calendar-user-address-set' => new LocalHref(
+ ['mailto:user1@testing.local','/remote.php/dav/principals/users/user1/']
+ )]
+ ]
+ ]);
+ $this->server->expects($this->exactly(2))->method('emit')->willReturnCallback(
+ function (string $eventName, array $arguments = [], ?callable $continueCallBack = null) use (&$iTipMessages) {
+ $this->assertEquals('schedule', $eventName);
+ $this->assertCount(1, $arguments);
+ $iTipMessages[] = $arguments[0];
+ return true;
+ }
+ );
+ // construct calendar with a 1 hour event and same start/end time zones
+ $vCalendar = new VCalendar();
+ $vEvent = $vCalendar->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('SUMMARY', 'Test Recurring Event');
+ $vEvent->add('ORGANIZER', 'mailto:user1@testing.local', ['CN' => 'User One']);
+ $vEvent->add('ATTENDEE', 'mailto:user2@testing.local', [
+ 'CN' => 'User Two',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ $vEvent->add('ATTENDEE', 'mailto:user@external.local', [
+ 'CN' => 'User External',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ // define flags
+ $newFlag = true;
+ $modifiedFlag = false;
+ // execute method
+ $this->plugin->calendarObjectChange(
+ $request,
+ $response,
+ $vCalendar,
+ 'calendars/user1/personal',
+ $modifiedFlag,
+ $newFlag
+ );
+ // test for correct iTip message count
+ $this->assertCount(2, $iTipMessages);
+ // test for Sharer Attendee
+ $this->assertEquals('mailto:user1@testing.local', $iTipMessages[0]->sender);
+ $this->assertEquals('mailto:user2@testing.local', $iTipMessages[0]->recipient);
+ $this->assertTrue($iTipMessages[0]->significantChange);
+ // test for External Attendee
+ $this->assertEquals('mailto:user1@testing.local', $iTipMessages[1]->sender);
+ $this->assertEquals('mailto:user@external.local', $iTipMessages[1]->recipient);
+ $this->assertTrue($iTipMessages[1]->significantChange);
+
+ }
+
+ /**
+ * Test Calendar Event Creation for Shared Calendar as Sharer/Owner
+ *
+ * Should generate 3 messages for attendees User 2 (Sharee), User 3 (Non-Sharee) and User External
+ */
+ public function testCalendarObjectChangeSharedCalendarSharerCreate(): void {
+
+ // define place holders
+ /** @var Message[] $iTipMessages */
+ $iTipMessages = [];
+ // construct calendar node
+ $calendarNode = new Calendar(
+ $this->createMock(BackendInterface::class),
+ [
+ 'uri' => 'calendar_shared_by_user1',
+ 'principaluri' => 'principals/users/user1',
+ '{DAV:}displayname' => 'Calendar Shared By User1',
+ '{http://owncloud.org/ns}owner-principal' => 'principals/users/user1'
+ ],
+ $this->createMock(IL10N::class),
+ $this->config,
+ $this->logger
+ );
+ // construct server request object
+ $request = new Request(
+ 'PUT',
+ '/remote.php/dav/calendars/user1/calendar_shared_by_user1/B0DC78AE-6DD7-47E3-80BE-89F23E6D5383.ics'
+ );
+ $request->setBaseUrl('/remote.php/dav/');
+ // construct server response object
+ $response = new Response();
+ // construct server tree object
+ $tree = $this->createMock(Tree::class);
+ $tree->expects($this->once())
+ ->method('getNodeForPath')
+ ->with('calendars/user1/calendar_shared_by_user1')
+ ->willReturn($calendarNode);
+ // construct server properties and returns
+ $this->server->httpRequest = $request;
+ $this->server->tree = $tree;
+ $this->server->expects($this->exactly(1))->method('getProperties')
+ ->willReturnMap([
+ [
+ 'principals/users/user1',
+ ['{urn:ietf:params:xml:ns:caldav}calendar-user-address-set'],
+ ['{urn:ietf:params:xml:ns:caldav}calendar-user-address-set' => new LocalHref(
+ ['mailto:user1@testing.local','/remote.php/dav/principals/users/user1/']
+ )]
+ ]
+ ]);
+ $this->server->expects($this->exactly(3))->method('emit')->willReturnCallback(
+ function (string $eventName, array $arguments = [], ?callable $continueCallBack = null) use (&$iTipMessages) {
+ $this->assertEquals('schedule', $eventName);
+ $this->assertCount(1, $arguments);
+ $iTipMessages[] = $arguments[0];
+ return true;
+ }
+ );
+ // construct calendar with a 1 hour event and same start/end time zones
+ $vCalendar = new VCalendar();
+ $vEvent = $vCalendar->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('SUMMARY', 'Test Recurring Event');
+ $vEvent->add('ORGANIZER', 'mailto:user1@testing.local', ['CN' => 'User One']);
+ $vEvent->add('ATTENDEE', 'mailto:user2@testing.local', [
+ 'CN' => 'User Two',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ $vEvent->add('ATTENDEE', 'mailto:user3@testing.local', [
+ 'CN' => 'User Three',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ $vEvent->add('ATTENDEE', 'mailto:user@external.local', [
+ 'CN' => 'User External',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ // define flags
+ $newFlag = true;
+ $modifiedFlag = false;
+ // execute method
+ $this->plugin->calendarObjectChange(
+ $request,
+ $response,
+ $vCalendar,
+ 'calendars/user1/calendar_shared_by_user1',
+ $modifiedFlag,
+ $newFlag
+ );
+ // test for correct iTip message count
+ $this->assertCount(3, $iTipMessages);
+ // test for Sharer Attendee
+ $this->assertEquals('mailto:user1@testing.local', $iTipMessages[0]->sender);
+ $this->assertEquals('mailto:user2@testing.local', $iTipMessages[0]->recipient);
+ $this->assertTrue($iTipMessages[0]->significantChange);
+ // test for Non Shee Attendee
+ $this->assertEquals('mailto:user1@testing.local', $iTipMessages[1]->sender);
+ $this->assertEquals('mailto:user3@testing.local', $iTipMessages[1]->recipient);
+ $this->assertTrue($iTipMessages[1]->significantChange);
+ // test for External Attendee
+ $this->assertEquals('mailto:user1@testing.local', $iTipMessages[2]->sender);
+ $this->assertEquals('mailto:user@external.local', $iTipMessages[2]->recipient);
+ $this->assertTrue($iTipMessages[2]->significantChange);
+
+ }
+
+ /**
+ * Test Calendar Event Creation for Shared Calendar as Shree
+ *
+ * Should generate 3 messages for attendees User 1 (Sharer/Owner), User 3 (Non-Sharee) and User External
+ */
+ public function testCalendarObjectChangeSharedCalendarShreeCreate(): void {
+
+ // define place holders
+ /** @var Message[] $iTipMessages */
+ $iTipMessages = [];
+ // construct calendar node
+ $calendarNode = new Calendar(
+ $this->createMock(BackendInterface::class),
+ [
+ 'uri' => 'calendar_shared_by_user1',
+ 'principaluri' => 'principals/users/user2',
+ '{DAV:}displayname' => 'Calendar Shared By User1',
+ '{http://owncloud.org/ns}owner-principal' => 'principals/users/user1'
+ ],
+ $this->createMock(IL10N::class),
+ $this->config,
+ $this->logger
+ );
+ // construct server request object
+ $request = new Request(
+ 'PUT',
+ '/remote.php/dav/calendars/user2/calendar_shared_by_user1/B0DC78AE-6DD7-47E3-80BE-89F23E6D5383.ics'
+ );
+ $request->setBaseUrl('/remote.php/dav/');
+ // construct server response object
+ $response = new Response();
+ // construct server tree object
+ $tree = $this->createMock(Tree::class);
+ $tree->expects($this->once())
+ ->method('getNodeForPath')
+ ->with('calendars/user2/calendar_shared_by_user1')
+ ->willReturn($calendarNode);
+ // construct server properties and returns
+ $this->server->httpRequest = $request;
+ $this->server->tree = $tree;
+ $this->server->expects($this->exactly(2))->method('getProperties')
+ ->willReturnMap([
+ [
+ 'principals/users/user1',
+ ['{urn:ietf:params:xml:ns:caldav}calendar-user-address-set'],
+ ['{urn:ietf:params:xml:ns:caldav}calendar-user-address-set' => new LocalHref(
+ ['mailto:user1@testing.local','/remote.php/dav/principals/users/user1/']
+ )]
+ ],
+ [
+ 'principals/users/user2',
+ ['{urn:ietf:params:xml:ns:caldav}calendar-user-address-set'],
+ ['{urn:ietf:params:xml:ns:caldav}calendar-user-address-set' => new LocalHref(
+ ['mailto:user2@testing.local','/remote.php/dav/principals/users/user2/']
+ )]
+ ]
+ ]);
+ $this->server->expects($this->exactly(3))->method('emit')->willReturnCallback(
+ function (string $eventName, array $arguments = [], ?callable $continueCallBack = null) use (&$iTipMessages) {
+ $this->assertEquals('schedule', $eventName);
+ $this->assertCount(1, $arguments);
+ $iTipMessages[] = $arguments[0];
+ return true;
+ }
+ );
+ // construct calendar with a 1 hour event and same start/end time zones
+ $vCalendar = new VCalendar();
+ $vEvent = $vCalendar->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('SUMMARY', 'Test Recurring Event');
+ $vEvent->add('ORGANIZER', 'mailto:user2@testing.local', ['CN' => 'User Two']);
+ $vEvent->add('ATTENDEE', 'mailto:user1@testing.local', [
+ 'CN' => 'User One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ $vEvent->add('ATTENDEE', 'mailto:user3@testing.local', [
+ 'CN' => 'User Three',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ $vEvent->add('ATTENDEE', 'mailto:user@external.local', [
+ 'CN' => 'User External',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ // define flags
+ $newFlag = true;
+ $modifiedFlag = false;
+ // execute method
+ $this->plugin->calendarObjectChange(
+ $request,
+ $response,
+ $vCalendar,
+ 'calendars/user2/calendar_shared_by_user1',
+ $modifiedFlag,
+ $newFlag
+ );
+ // test for correct iTip message count
+ $this->assertCount(3, $iTipMessages);
+ // test for Sharer Attendee
+ $this->assertEquals('mailto:user2@testing.local', $iTipMessages[0]->sender);
+ $this->assertEquals('mailto:user1@testing.local', $iTipMessages[0]->recipient);
+ $this->assertTrue($iTipMessages[0]->significantChange);
+ // test for Non Shee Attendee
+ $this->assertEquals('mailto:user2@testing.local', $iTipMessages[1]->sender);
+ $this->assertEquals('mailto:user3@testing.local', $iTipMessages[1]->recipient);
+ $this->assertTrue($iTipMessages[1]->significantChange);
+ // test for External Attendee
+ $this->assertEquals('mailto:user2@testing.local', $iTipMessages[2]->sender);
+ $this->assertEquals('mailto:user@external.local', $iTipMessages[2]->recipient);
+ $this->assertTrue($iTipMessages[2]->significantChange);
+
+ }
+
+ /**
+ * Test Calendar Event Creation with iTip and iMip disabled
+ *
+ * Should generate 2 messages for attendees User 2 and User External
+ */
+ public function testCalendarObjectChangeWithSchedulingDisabled(): void {
+ // construct server request
+ $request = new Request(
+ 'PUT',
+ '/remote.php/dav/calendars/user1/personal/B0DC78AE-6DD7-47E3-80BE-89F23E6D5383.ics',
+ ['x-nc-scheduling' => 'false']
+ );
+ $request->setBaseUrl('/remote.php/dav/');
+ // construct server response
+ $response = new Response();
+ // construct server tree
+ $tree = $this->createMock(Tree::class);
+ $tree->expects($this->never())
+ ->method('getNodeForPath');
+ // construct server properties and returns
+ $this->server->httpRequest = $request;
+ $this->server->tree = $tree;
+ // construct empty calendar event
+ $vCalendar = new VCalendar();
+ $vEvent = $vCalendar->add('VEVENT', []);
+ // define flags
+ $newFlag = true;
+ $modifiedFlag = false;
+ // execute method
+ $this->plugin->calendarObjectChange(
+ $request,
+ $response,
+ $vCalendar,
+ 'calendars/user1/personal',
+ $modifiedFlag,
+ $newFlag
+ );
}
}
diff --git a/apps/dav/tests/unit/CalDAV/Search/Request/CalendarSearchReportTest.php b/apps/dav/tests/unit/CalDAV/Search/Request/CalendarSearchReportTest.php
index cbfd4639ed7..02ae504bce0 100644
--- a/apps/dav/tests/unit/CalDAV/Search/Request/CalendarSearchReportTest.php
+++ b/apps/dav/tests/unit/CalDAV/Search/Request/CalendarSearchReportTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -10,9 +12,9 @@ use Sabre\Xml\Reader;
use Test\TestCase;
class CalendarSearchReportTest extends TestCase {
- private $elementMap = [
- '{http://nextcloud.com/ns}calendar-search' =>
- 'OCA\\DAV\\CalDAV\\Search\\Xml\\Request\\CalendarSearchReport',
+ private array $elementMap = [
+ '{http://nextcloud.com/ns}calendar-search'
+ => 'OCA\\DAV\\CalDAV\\Search\\Xml\\Request\\CalendarSearchReport',
];
public function testFoo(): void {
@@ -112,7 +114,7 @@ XML;
);
}
-
+
public function testRequiresCompFilter(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('{http://nextcloud.com/ns}prop-filter or {http://nextcloud.com/ns}param-filter given without any {http://nextcloud.com/ns}comp-filter');
@@ -139,7 +141,7 @@ XML;
$this->parse($xml);
}
-
+
public function testRequiresFilter(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('The {http://nextcloud.com/ns}filter element is required for this request');
@@ -157,7 +159,7 @@ XML;
$this->parse($xml);
}
-
+
public function testNoSearchTerm(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('{http://nextcloud.com/ns}search-term is required for this request');
@@ -185,7 +187,7 @@ XML;
$this->parse($xml);
}
-
+
public function testCompOnly(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('At least one{http://nextcloud.com/ns}prop-filter or {http://nextcloud.com/ns}param-filter is required for this request');
@@ -313,7 +315,7 @@ XML;
);
}
- private function parse($xml, array $elementMap = []) {
+ private function parse(string $xml, array $elementMap = []): array {
$reader = new Reader();
$reader->elementMap = array_merge($this->elementMap, $elementMap);
$reader->xml($xml);
diff --git a/apps/dav/tests/unit/CalDAV/Search/SearchPluginTest.php b/apps/dav/tests/unit/CalDAV/Search/SearchPluginTest.php
index ae4519e2542..e576fbae34c 100644
--- a/apps/dav/tests/unit/CalDAV/Search/SearchPluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/Search/SearchPluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -14,7 +16,7 @@ use Test\TestCase;
class SearchPluginTest extends TestCase {
protected $server;
- /** @var \OCA\DAV\CalDAV\Search\SearchPlugin $plugin */
+ /** @var SearchPlugin $plugin */
protected $plugin;
protected function setUp(): void {
diff --git a/apps/dav/tests/unit/CalDAV/Security/RateLimitingPluginTest.php b/apps/dav/tests/unit/CalDAV/Security/RateLimitingPluginTest.php
index fc0bd1502b2..a5cf6a23c66 100644
--- a/apps/dav/tests/unit/CalDAV/Security/RateLimitingPluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/Security/RateLimitingPluginTest.php
@@ -24,11 +24,11 @@ use Test\TestCase;
class RateLimitingPluginTest extends TestCase {
- private Limiter|MockObject $limiter;
- private CalDavBackend|MockObject $caldavBackend;
- private IUserManager|MockObject $userManager;
- private LoggerInterface|MockObject $logger;
- private IAppConfig|MockObject $config;
+ private Limiter&MockObject $limiter;
+ private CalDavBackend&MockObject $caldavBackend;
+ private IUserManager&MockObject $userManager;
+ private LoggerInterface&MockObject $logger;
+ private IAppConfig&MockObject $config;
private string $userId = 'user123';
private RateLimitingPlugin $plugin;
diff --git a/apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php b/apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php
index 78e76cf507d..ee0ef2334ec 100644
--- a/apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -25,14 +27,14 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class StatusServiceTest extends TestCase {
- private ITimeFactory|MockObject $timeFactory;
- private IManager|MockObject $calendarManager;
- private IUserManager|MockObject $userManager;
- private UserStatusService|MockObject $userStatusService;
- private IAvailabilityCoordinator|MockObject $availabilityCoordinator;
- private ICacheFactory|MockObject $cacheFactory;
- private LoggerInterface|MockObject $logger;
- private ICache|MockObject $cache;
+ private ITimeFactory&MockObject $timeFactory;
+ private IManager&MockObject $calendarManager;
+ private IUserManager&MockObject $userManager;
+ private UserStatusService&MockObject $userStatusService;
+ private IAvailabilityCoordinator&MockObject $availabilityCoordinator;
+ private ICacheFactory&MockObject $cacheFactory;
+ private LoggerInterface&MockObject $logger;
+ private ICache&MockObject $cache;
private StatusService $service;
protected function setUp(): void {
diff --git a/apps/dav/tests/unit/CalDAV/TimeZoneFactoryTest.php b/apps/dav/tests/unit/CalDAV/TimeZoneFactoryTest.php
new file mode 100644
index 00000000000..2d6d0e86358
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/TimeZoneFactoryTest.php
@@ -0,0 +1,51 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\Tests\unit\CalDAV;
+
+use DateTimeZone;
+use OCA\DAV\CalDAV\TimeZoneFactory;
+use Test\TestCase;
+
+class TimeZoneFactoryTest extends TestCase {
+
+ private TimeZoneFactory $factory;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->factory = new TimeZoneFactory();
+ }
+
+ public function testIsMS(): void {
+ // test Microsoft time zone
+ $this->assertTrue(TimeZoneFactory::isMS('Eastern Standard Time'));
+ // test IANA time zone
+ $this->assertFalse(TimeZoneFactory::isMS('America/Toronto'));
+ // test Fake time zone
+ $this->assertFalse(TimeZoneFactory::isMS('Fake Eastern Time'));
+ }
+
+ public function testToIana(): void {
+ // test Microsoft time zone
+ $this->assertEquals('America/Toronto', TimeZoneFactory::toIANA('Eastern Standard Time'));
+ // test IANA time zone
+ $this->assertEquals(null, TimeZoneFactory::toIANA('America/Toronto'));
+ // test Fake time zone
+ $this->assertEquals(null, TimeZoneFactory::toIANA('Fake Eastern Time'));
+ }
+
+ public function testFromName(): void {
+ // test Microsoft time zone
+ $this->assertEquals(new DateTimeZone('America/Toronto'), $this->factory->fromName('Eastern Standard Time'));
+ // test IANA time zone
+ $this->assertEquals(new DateTimeZone('America/Toronto'), $this->factory->fromName('America/Toronto'));
+ // test Fake time zone
+ $this->assertEquals(null, $this->factory->fromName('Fake Eastern Time'));
+ }
+
+}
diff --git a/apps/dav/tests/unit/CalDAV/TimezoneServiceTest.php b/apps/dav/tests/unit/CalDAV/TimezoneServiceTest.php
index b01139e4093..5bb87be67c1 100644
--- a/apps/dav/tests/unit/CalDAV/TimezoneServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/TimezoneServiceTest.php
@@ -1,11 +1,6 @@
<?php
-/**
- * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
declare(strict_types=1);
-
/**
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -26,10 +21,9 @@ use Sabre\VObject\Component\VTimeZone;
use Test\TestCase;
class TimezoneServiceTest extends TestCase {
-
- private IConfig|MockObject $config;
- private PropertyMapper|MockObject $propertyMapper;
- private IManager|MockObject $calendarManager;
+ private IConfig&MockObject $config;
+ private PropertyMapper&MockObject $propertyMapper;
+ private IManager&MockObject $calendarManager;
private TimezoneService $service;
protected function setUp(): void {
diff --git a/apps/dav/tests/unit/CalDAV/TipBrokerTest.php b/apps/dav/tests/unit/CalDAV/TipBrokerTest.php
new file mode 100644
index 00000000000..ddf992767d6
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/TipBrokerTest.php
@@ -0,0 +1,180 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\Tests\unit\CalDAV;
+
+use OCA\DAV\CalDAV\TipBroker;
+use Sabre\VObject\Component\VCalendar;
+use Test\TestCase;
+
+class TipBrokerTest extends TestCase {
+
+ private TipBroker $broker;
+ private VCalendar $vCalendar1a;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->broker = new TipBroker();
+ // construct calendar with a 1 hour event and same start/end time zones
+ $this->vCalendar1a = new VCalendar();
+ /** @var VEvent $vEvent */
+ $vEvent = $this->vCalendar1a->add('VEVENT', []);
+ $vEvent->add('UID', '96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTAMP', '20240701T000000Z');
+ $vEvent->add('CREATED', '20240701T000000Z');
+ $vEvent->add('LAST-MODIFIED', '20240701T000000Z');
+ $vEvent->add('SEQUENCE', '1');
+ $vEvent->add('STATUS', 'CONFIRMED');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('SUMMARY', 'Test Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ }
+
+ public function testParseEventForOrganizerOnCreate(): void {
+
+ // construct calendar and generate event info for newly created event with one attendee
+ $calendar = clone $this->vCalendar1a;
+ $previousEventInfo = [
+ 'organizer' => null,
+ 'significantChangeHash' => '',
+ 'attendees' => [],
+ ];
+ $currentEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
+ // test iTip generation
+ $messages = $this->invokePrivate($this->broker, 'parseEventForOrganizer', [$calendar, $currentEventInfo, $previousEventInfo]);
+ $this->assertCount(1, $messages);
+ $this->assertEquals('REQUEST', $messages[0]->method);
+ $this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[0]->sender);
+ $this->assertEquals($calendar->VEVENT->ATTENDEE[0]->getValue(), $messages[0]->recipient);
+
+ }
+
+ public function testParseEventForOrganizerOnModify(): void {
+
+ // construct calendar and generate event info for modified event with one attendee
+ $calendar = clone $this->vCalendar1a;
+ $previousEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
+ $calendar->VEVENT->{'LAST-MODIFIED'}->setValue('20240701T020000Z');
+ $calendar->VEVENT->SEQUENCE->setValue(2);
+ $calendar->VEVENT->SUMMARY->setValue('Test Event Modified');
+ $currentEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
+ // test iTip generation
+ $messages = $this->invokePrivate($this->broker, 'parseEventForOrganizer', [$calendar, $currentEventInfo, $previousEventInfo]);
+ $this->assertCount(1, $messages);
+ $this->assertEquals('REQUEST', $messages[0]->method);
+ $this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[0]->sender);
+ $this->assertEquals($calendar->VEVENT->ATTENDEE[0]->getValue(), $messages[0]->recipient);
+
+ }
+
+ public function testParseEventForOrganizerOnDelete(): void {
+
+ // construct calendar and generate event info for modified event with one attendee
+ $calendar = clone $this->vCalendar1a;
+ $previousEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
+ $currentEventInfo = $previousEventInfo;
+ $currentEventInfo['attendees'] = [];
+ ++$currentEventInfo['sequence'];
+ // test iTip generation
+ $messages = $this->invokePrivate($this->broker, 'parseEventForOrganizer', [$calendar, $currentEventInfo, $previousEventInfo]);
+ $this->assertCount(1, $messages);
+ $this->assertEquals('CANCEL', $messages[0]->method);
+ $this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[0]->sender);
+ $this->assertEquals($calendar->VEVENT->ATTENDEE[0]->getValue(), $messages[0]->recipient);
+
+ }
+
+ public function testParseEventForOrganizerOnStatusCancelled(): void {
+
+ // construct calendar and generate event info for modified event with one attendee
+ $calendar = clone $this->vCalendar1a;
+ $previousEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
+ $calendar->VEVENT->{'LAST-MODIFIED'}->setValue('20240701T020000Z');
+ $calendar->VEVENT->SEQUENCE->setValue(2);
+ $calendar->VEVENT->STATUS->setValue('CANCELLED');
+ $currentEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
+ // test iTip generation
+ $messages = $this->invokePrivate($this->broker, 'parseEventForOrganizer', [$calendar, $currentEventInfo, $previousEventInfo]);
+ $this->assertCount(1, $messages);
+ $this->assertEquals('CANCEL', $messages[0]->method);
+ $this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[0]->sender);
+ $this->assertEquals($calendar->VEVENT->ATTENDEE[0]->getValue(), $messages[0]->recipient);
+
+ }
+
+ public function testParseEventForOrganizerOnAddAttendee(): void {
+
+ // construct calendar and generate event info for modified event with two attendees
+ $calendar = clone $this->vCalendar1a;
+ $previousEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
+ $calendar->VEVENT->{'LAST-MODIFIED'}->setValue('20240701T020000Z');
+ $calendar->VEVENT->SEQUENCE->setValue(2);
+ $calendar->VEVENT->add('ATTENDEE', 'mailto:attendee2@testing.com', [
+ 'CN' => 'Attendee Two',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ $currentEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
+ // test iTip generation
+ $messages = $this->invokePrivate($this->broker, 'parseEventForOrganizer', [$calendar, $currentEventInfo, $previousEventInfo]);
+ $this->assertCount(2, $messages);
+ $this->assertEquals('REQUEST', $messages[0]->method);
+ $this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[0]->sender);
+ $this->assertEquals($calendar->VEVENT->ATTENDEE[0]->getValue(), $messages[0]->recipient);
+ $this->assertEquals('REQUEST', $messages[1]->method);
+ $this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[1]->sender);
+ $this->assertEquals($calendar->VEVENT->ATTENDEE[1]->getValue(), $messages[1]->recipient);
+
+ }
+
+ public function testParseEventForOrganizerOnRemoveAttendee(): void {
+
+ // construct calendar and generate event info for modified event with two attendees
+ $calendar = clone $this->vCalendar1a;
+ $calendar->VEVENT->add('ATTENDEE', 'mailto:attendee2@testing.com', [
+ 'CN' => 'Attendee Two',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ $previousEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
+ $calendar->VEVENT->{'LAST-MODIFIED'}->setValue('20240701T020000Z');
+ $calendar->VEVENT->SEQUENCE->setValue(2);
+ $calendar->VEVENT->remove('ATTENDEE');
+ $calendar->VEVENT->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ $currentEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
+ // test iTip generation
+ $messages = $this->invokePrivate($this->broker, 'parseEventForOrganizer', [$calendar, $currentEventInfo, $previousEventInfo]);
+ $this->assertCount(2, $messages);
+ $this->assertEquals('REQUEST', $messages[0]->method);
+ $this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[0]->sender);
+ $this->assertEquals($calendar->VEVENT->ATTENDEE[0]->getValue(), $messages[0]->recipient);
+ $this->assertEquals('CANCEL', $messages[1]->method);
+ $this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[1]->sender);
+ $this->assertEquals('mailto:attendee2@testing.com', $messages[1]->recipient);
+
+ }
+
+}
diff --git a/apps/dav/tests/unit/CalDAV/Validation/CalDavValidatePluginTest.php b/apps/dav/tests/unit/CalDAV/Validation/CalDavValidatePluginTest.php
new file mode 100644
index 00000000000..74fb4b5e94e
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/Validation/CalDavValidatePluginTest.php
@@ -0,0 +1,73 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\CalDAV\Validation;
+
+use OCA\DAV\CalDAV\Validation\CalDavValidatePlugin;
+use OCP\IAppConfig;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\DAV\Exception\Forbidden;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use Test\TestCase;
+
+class CalDavValidatePluginTest extends TestCase {
+ private IAppConfig&MockObject $config;
+ private RequestInterface&MockObject $request;
+ private ResponseInterface&MockObject $response;
+
+ private CalDavValidatePlugin $plugin;
+
+ protected function setUp(): void {
+ parent::setUp();
+ // construct mock objects
+ $this->config = $this->createMock(IAppConfig::class);
+ $this->request = $this->createMock(RequestInterface::class);
+ $this->response = $this->createMock(ResponseInterface::class);
+ $this->plugin = new CalDavValidatePlugin(
+ $this->config,
+ );
+ }
+
+ public function testPutSizeLessThenLimit(): void {
+
+ // construct method responses
+ $this->config
+ ->method('getValueInt')
+ ->with('dav', 'event_size_limit', 10485760)
+ ->willReturn(10485760);
+ $this->request
+ ->method('getRawServerValue')
+ ->with('CONTENT_LENGTH')
+ ->willReturn('1024');
+ // test condition
+ $this->assertTrue(
+ $this->plugin->beforePut($this->request, $this->response)
+ );
+
+ }
+
+ public function testPutSizeMoreThenLimit(): void {
+
+ // construct method responses
+ $this->config
+ ->method('getValueInt')
+ ->with('dav', 'event_size_limit', 10485760)
+ ->willReturn(10485760);
+ $this->request
+ ->method('getRawServerValue')
+ ->with('CONTENT_LENGTH')
+ ->willReturn('16242880');
+ $this->expectException(Forbidden::class);
+ // test condition
+ $this->plugin->beforePut($this->request, $this->response);
+
+ }
+
+}
diff --git a/apps/dav/tests/unit/CalDAV/WebcalCaching/ConnectionTest.php b/apps/dav/tests/unit/CalDAV/WebcalCaching/ConnectionTest.php
new file mode 100644
index 00000000000..c29415ecef3
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/WebcalCaching/ConnectionTest.php
@@ -0,0 +1,176 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\Tests\unit\CalDAV\WebcalCaching;
+
+use OCA\DAV\CalDAV\WebcalCaching\Connection;
+use OCP\Http\Client\IClient;
+use OCP\Http\Client\IClientService;
+use OCP\Http\Client\IResponse;
+use OCP\Http\Client\LocalServerException;
+use OCP\IAppConfig;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+
+use Test\TestCase;
+
+class ConnectionTest extends TestCase {
+
+ private IClientService&MockObject $clientService;
+ private IAppConfig&MockObject $config;
+ private LoggerInterface&MockObject $logger;
+ private Connection $connection;
+
+ public function setUp(): void {
+ $this->clientService = $this->createMock(IClientService::class);
+ $this->config = $this->createMock(IAppConfig::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->connection = new Connection($this->clientService, $this->config, $this->logger);
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('runLocalURLDataProvider')]
+ public function testLocalUrl($source): void {
+ $subscription = [
+ 'id' => 42,
+ 'uri' => 'sub123',
+ 'refreshreate' => 'P1H',
+ 'striptodos' => 1,
+ 'stripalarms' => 1,
+ 'stripattachments' => 1,
+ 'source' => $source,
+ 'lastmodified' => 0,
+ ];
+
+ $client = $this->createMock(IClient::class);
+ $this->clientService->expects(self::once())
+ ->method('newClient')
+ ->with()
+ ->willReturn($client);
+
+ $this->config->expects(self::once())
+ ->method('getValueString')
+ ->with('dav', 'webcalAllowLocalAccess', 'no')
+ ->willReturn('no');
+
+ $localServerException = new LocalServerException();
+ $client->expects(self::once())
+ ->method('get')
+ ->willThrowException($localServerException);
+ $this->logger->expects(self::once())
+ ->method('warning')
+ ->with('Subscription 42 was not refreshed because it violates local access rules', ['exception' => $localServerException]);
+
+ $this->connection->queryWebcalFeed($subscription);
+ }
+
+ public function testInvalidUrl(): void {
+ $subscription = [
+ 'id' => 42,
+ 'uri' => 'sub123',
+ 'refreshreate' => 'P1H',
+ 'striptodos' => 1,
+ 'stripalarms' => 1,
+ 'stripattachments' => 1,
+ 'source' => '!@#$',
+ 'lastmodified' => 0,
+ ];
+
+ $client = $this->createMock(IClient::class);
+ $this->config->expects(self::never())
+ ->method('getValueString');
+ $client->expects(self::never())
+ ->method('get');
+
+ $this->connection->queryWebcalFeed($subscription);
+
+ }
+
+ /**
+ * @param string $result
+ * @param string $contentType
+ */
+ #[\PHPUnit\Framework\Attributes\DataProvider('urlDataProvider')]
+ public function testConnection(string $url, string $result, string $contentType): void {
+ $client = $this->createMock(IClient::class);
+ $response = $this->createMock(IResponse::class);
+ $subscription = [
+ 'id' => 42,
+ 'uri' => 'sub123',
+ 'refreshreate' => 'P1H',
+ 'striptodos' => 1,
+ 'stripalarms' => 1,
+ 'stripattachments' => 1,
+ 'source' => $url,
+ 'lastmodified' => 0,
+ ];
+
+ $this->clientService->expects($this->once())
+ ->method('newClient')
+ ->with()
+ ->willReturn($client);
+
+ $this->config->expects($this->once())
+ ->method('getValueString')
+ ->with('dav', 'webcalAllowLocalAccess', 'no')
+ ->willReturn('no');
+
+ $client->expects($this->once())
+ ->method('get')
+ ->with('https://foo.bar/bla2')
+ ->willReturn($response);
+
+ $response->expects($this->once())
+ ->method('getBody')
+ ->with()
+ ->willReturn($result);
+ $response->expects($this->once())
+ ->method('getHeader')
+ ->with('Content-Type')
+ ->willReturn($contentType);
+
+ $this->connection->queryWebcalFeed($subscription);
+ }
+
+ public static function runLocalURLDataProvider(): array {
+ return [
+ ['localhost/foo.bar'],
+ ['localHost/foo.bar'],
+ ['random-host/foo.bar'],
+ ['[::1]/bla.blub'],
+ ['[::]/bla.blub'],
+ ['192.168.0.1'],
+ ['172.16.42.1'],
+ ['[fdf8:f53b:82e4::53]/secret.ics'],
+ ['[fe80::200:5aee:feaa:20a2]/secret.ics'],
+ ['[0:0:0:0:0:0:10.0.0.1]/secret.ics'],
+ ['[0:0:0:0:0:ffff:127.0.0.0]/secret.ics'],
+ ['10.0.0.1'],
+ ['another-host.local'],
+ ['service.localhost'],
+ ];
+ }
+
+ public static function urlDataProvider(): array {
+ return [
+ [
+ 'https://foo.bar/bla2',
+ "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20160218T133704Z\r\nDTSTART;VALUE=DATE:19000101\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:12345's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n",
+ 'text/calendar;charset=utf8',
+ ],
+ [
+ 'https://foo.bar/bla2',
+ '["vcalendar",[["prodid",{},"text","-//Example Corp.//Example Client//EN"],["version",{},"text","2.0"]],[["vtimezone",[["last-modified",{},"date-time","2004-01-10T03:28:45Z"],["tzid",{},"text","US/Eastern"]],[["daylight",[["dtstart",{},"date-time","2000-04-04T02:00:00"],["rrule",{},"recur",{"freq":"YEARLY","byday":"1SU","bymonth":4}],["tzname",{},"text","EDT"],["tzoffsetfrom",{},"utc-offset","-05:00"],["tzoffsetto",{},"utc-offset","-04:00"]],[]],["standard",[["dtstart",{},"date-time","2000-10-26T02:00:00"],["rrule",{},"recur",{"freq":"YEARLY","byday":"1SU","bymonth":10}],["tzname",{},"text","EST"],["tzoffsetfrom",{},"utc-offset","-04:00"],["tzoffsetto",{},"utc-offset","-05:00"]],[]]]],["vevent",[["dtstamp",{},"date-time","2006-02-06T00:11:21Z"],["dtstart",{"tzid":"US/Eastern"},"date-time","2006-01-02T14:00:00"],["duration",{},"duration","PT1H"],["recurrence-id",{"tzid":"US/Eastern"},"date-time","2006-01-04T12:00:00"],["summary",{},"text","Event #2"],["uid",{},"text","12345"]],[]]]]',
+ 'application/calendar+json',
+ ],
+ [
+ 'https://foo.bar/bla2',
+ '<?xml version="1.0" encoding="utf-8" ?><icalendar xmlns="urn:ietf:params:xml:ns:icalendar-2.0"><vcalendar><properties><prodid><text>-//Example Inc.//Example Client//EN</text></prodid><version><text>2.0</text></version></properties><components><vevent><properties><dtstamp><date-time>2006-02-06T00:11:21Z</date-time></dtstamp><dtstart><parameters><tzid><text>US/Eastern</text></tzid></parameters><date-time>2006-01-04T14:00:00</date-time></dtstart><duration><duration>PT1H</duration></duration><recurrence-id><parameters><tzid><text>US/Eastern</text></tzid></parameters><date-time>2006-01-04T12:00:00</date-time></recurrence-id><summary><text>Event #2 bis</text></summary><uid><text>12345</text></uid></properties></vevent></components></vcalendar></icalendar>',
+ 'application/calendar+xml',
+ ],
+ ];
+ }
+}
diff --git a/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php b/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
index 82c03c5cf68..804af021d5a 100644
--- a/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php b/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php
index c483fa3e234..d4f4b9e878f 100644
--- a/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php
@@ -1,18 +1,16 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\DAV\Tests\unit\CalDAV\WebcalCaching;
-use GuzzleHttp\HandlerStack;
use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CalDAV\WebcalCaching\Connection;
use OCA\DAV\CalDAV\WebcalCaching\RefreshWebcalService;
-use OCP\Http\Client\IClient;
-use OCP\Http\Client\IClientService;
-use OCP\Http\Client\IResponse;
-use OCP\Http\Client\LocalServerException;
-use OCP\IConfig;
+use OCP\AppFramework\Utility\ITimeFactory;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\BadRequest;
@@ -22,121 +20,187 @@ use Sabre\VObject\Recur\NoInstancesException;
use Test\TestCase;
class RefreshWebcalServiceTest extends TestCase {
-
- /** @var CalDavBackend | MockObject */
- private $caldavBackend;
-
- /** @var IClientService | MockObject */
- private $clientService;
-
- /** @var IConfig | MockObject */
- private $config;
-
- /** @var LoggerInterface | MockObject */
- private $logger;
+ private CalDavBackend&MockObject $caldavBackend;
+ private Connection&MockObject $connection;
+ private LoggerInterface&MockObject $logger;
+ private ITimeFactory&MockObject $time;
protected function setUp(): void {
parent::setUp();
$this->caldavBackend = $this->createMock(CalDavBackend::class);
- $this->clientService = $this->createMock(IClientService::class);
- $this->config = $this->createMock(IConfig::class);
+ $this->connection = $this->createMock(Connection::class);
$this->logger = $this->createMock(LoggerInterface::class);
+ $this->time = $this->createMock(ITimeFactory::class);
}
- /**
- * @param string $body
- * @param string $contentType
- * @param string $result
- *
- * @dataProvider runDataProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('runDataProvider')]
public function testRun(string $body, string $contentType, string $result): void {
$refreshWebcalService = $this->getMockBuilder(RefreshWebcalService::class)
->onlyMethods(['getRandomCalendarObjectUri'])
- ->setConstructorArgs([$this->caldavBackend, $this->clientService, $this->config, $this->logger])
+ ->setConstructorArgs([$this->caldavBackend, $this->logger, $this->connection, $this->time])
->getMock();
$refreshWebcalService
->method('getRandomCalendarObjectUri')
->willReturn('uri-1.ics');
- $this->caldavBackend->expects($this->once())
+ $this->caldavBackend->expects(self::once())
->method('getSubscriptionsForUser')
->with('principals/users/testuser')
->willReturn([
[
'id' => '99',
'uri' => 'sub456',
- '{http://apple.com/ns/ical/}refreshrate' => 'P1D',
- '{http://calendarserver.org/ns/}subscribed-strip-todos' => '1',
- '{http://calendarserver.org/ns/}subscribed-strip-alarms' => '1',
- '{http://calendarserver.org/ns/}subscribed-strip-attachments' => '1',
- 'source' => 'webcal://foo.bar/bla'
+ RefreshWebcalService::REFRESH_RATE => 'P1D',
+ RefreshWebcalService::STRIP_TODOS => '1',
+ RefreshWebcalService::STRIP_ALARMS => '1',
+ RefreshWebcalService::STRIP_ATTACHMENTS => '1',
+ 'source' => 'webcal://foo.bar/bla',
+ 'lastmodified' => 0,
],
[
'id' => '42',
'uri' => 'sub123',
- '{http://apple.com/ns/ical/}refreshrate' => 'PT1H',
- '{http://calendarserver.org/ns/}subscribed-strip-todos' => '1',
- '{http://calendarserver.org/ns/}subscribed-strip-alarms' => '1',
- '{http://calendarserver.org/ns/}subscribed-strip-attachments' => '1',
- 'source' => 'webcal://foo.bar/bla2'
+ RefreshWebcalService::REFRESH_RATE => 'PT1H',
+ RefreshWebcalService::STRIP_TODOS => '1',
+ RefreshWebcalService::STRIP_ALARMS => '1',
+ RefreshWebcalService::STRIP_ATTACHMENTS => '1',
+ 'source' => 'webcal://foo.bar/bla2',
+ 'lastmodified' => 0,
],
]);
- $client = $this->createMock(IClient::class);
- $response = $this->createMock(IResponse::class);
- $this->clientService->expects($this->once())
- ->method('newClient')
- ->with()
- ->willReturn($client);
-
- $this->config->expects($this->once())
- ->method('getAppValue')
- ->with('dav', 'webcalAllowLocalAccess', 'no')
- ->willReturn('no');
-
- $client->expects($this->once())
- ->method('get')
- ->with('https://foo.bar/bla2', $this->callback(function ($obj) {
- return $obj['allow_redirects']['redirects'] === 10 && $obj['handler'] instanceof HandlerStack;
- }))
- ->willReturn($response);
-
- $response->expects($this->once())
- ->method('getBody')
- ->with()
- ->willReturn($body);
- $response->expects($this->once())
- ->method('getHeader')
- ->with('Content-Type')
- ->willReturn($contentType);
-
- $this->caldavBackend->expects($this->once())
- ->method('purgeAllCachedEventsForSubscription')
- ->with(42);
-
- $this->caldavBackend->expects($this->once())
+ $this->connection->expects(self::once())
+ ->method('queryWebcalFeed')
+ ->willReturn($result);
+ $this->caldavBackend->expects(self::once())
->method('createCalendarObject')
->with(42, 'uri-1.ics', $result, 1);
$refreshWebcalService->refreshSubscription('principals/users/testuser', 'sub123');
}
- /**
- * @param string $body
- * @param string $contentType
- * @param string $result
- *
- * @dataProvider runDataProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('identicalDataProvider')]
+ public function testRunIdentical(string $uid, array $calendarObject, string $body, string $contentType, string $result): void {
+ $refreshWebcalService = $this->getMockBuilder(RefreshWebcalService::class)
+ ->onlyMethods(['getRandomCalendarObjectUri'])
+ ->setConstructorArgs([$this->caldavBackend, $this->logger, $this->connection, $this->time])
+ ->getMock();
+
+ $refreshWebcalService
+ ->method('getRandomCalendarObjectUri')
+ ->willReturn('uri-1.ics');
+
+ $this->caldavBackend->expects(self::once())
+ ->method('getSubscriptionsForUser')
+ ->with('principals/users/testuser')
+ ->willReturn([
+ [
+ 'id' => '99',
+ 'uri' => 'sub456',
+ RefreshWebcalService::REFRESH_RATE => 'P1D',
+ RefreshWebcalService::STRIP_TODOS => '1',
+ RefreshWebcalService::STRIP_ALARMS => '1',
+ RefreshWebcalService::STRIP_ATTACHMENTS => '1',
+ 'source' => 'webcal://foo.bar/bla',
+ 'lastmodified' => 0,
+ ],
+ [
+ 'id' => '42',
+ 'uri' => 'sub123',
+ RefreshWebcalService::REFRESH_RATE => 'PT1H',
+ RefreshWebcalService::STRIP_TODOS => '1',
+ RefreshWebcalService::STRIP_ALARMS => '1',
+ RefreshWebcalService::STRIP_ATTACHMENTS => '1',
+ 'source' => 'webcal://foo.bar/bla2',
+ 'lastmodified' => 0,
+ ],
+ ]);
+
+ $this->connection->expects(self::once())
+ ->method('queryWebcalFeed')
+ ->willReturn($result);
+
+ $this->caldavBackend->expects(self::once())
+ ->method('getLimitedCalendarObjects')
+ ->willReturn($calendarObject);
+
+ $denormalised = [
+ 'etag' => 100,
+ 'size' => strlen($calendarObject[$uid]['calendardata']),
+ 'uid' => 'sub456'
+ ];
+
+ $this->caldavBackend->expects(self::once())
+ ->method('getDenormalizedData')
+ ->willReturn($denormalised);
+
+ $this->caldavBackend->expects(self::never())
+ ->method('createCalendarObject');
+
+ $refreshWebcalService->refreshSubscription('principals/users/testuser', 'sub456');
+ }
+
+ public function testRunJustUpdated(): void {
+ $refreshWebcalService = $this->getMockBuilder(RefreshWebcalService::class)
+ ->onlyMethods(['getRandomCalendarObjectUri'])
+ ->setConstructorArgs([$this->caldavBackend, $this->logger, $this->connection, $this->time])
+ ->getMock();
+
+ $refreshWebcalService
+ ->method('getRandomCalendarObjectUri')
+ ->willReturn('uri-1.ics');
+
+ $this->caldavBackend->expects(self::once())
+ ->method('getSubscriptionsForUser')
+ ->with('principals/users/testuser')
+ ->willReturn([
+ [
+ 'id' => '99',
+ 'uri' => 'sub456',
+ RefreshWebcalService::REFRESH_RATE => 'P1D',
+ RefreshWebcalService::STRIP_TODOS => '1',
+ RefreshWebcalService::STRIP_ALARMS => '1',
+ RefreshWebcalService::STRIP_ATTACHMENTS => '1',
+ 'source' => 'webcal://foo.bar/bla',
+ 'lastmodified' => time(),
+ ],
+ [
+ 'id' => '42',
+ 'uri' => 'sub123',
+ RefreshWebcalService::REFRESH_RATE => 'PT1H',
+ RefreshWebcalService::STRIP_TODOS => '1',
+ RefreshWebcalService::STRIP_ALARMS => '1',
+ RefreshWebcalService::STRIP_ATTACHMENTS => '1',
+ 'source' => 'webcal://foo.bar/bla2',
+ 'lastmodified' => time(),
+ ],
+ ]);
+
+ $timeMock = $this->createMock(\DateTime::class);
+ $this->time->expects(self::once())
+ ->method('getDateTime')
+ ->willReturn($timeMock);
+ $timeMock->expects(self::once())
+ ->method('getTimestamp')
+ ->willReturn(2101724667);
+ $this->time->expects(self::once())
+ ->method('getTime')
+ ->willReturn(time());
+ $this->connection->expects(self::never())
+ ->method('queryWebcalFeed');
+ $this->caldavBackend->expects(self::never())
+ ->method('createCalendarObject');
+
+ $refreshWebcalService->refreshSubscription('principals/users/testuser', 'sub123');
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('runDataProvider')]
public function testRunCreateCalendarNoException(string $body, string $contentType, string $result): void {
- $client = $this->createMock(IClient::class);
- $response = $this->createMock(IResponse::class);
$refreshWebcalService = $this->getMockBuilder(RefreshWebcalService::class)
- ->onlyMethods(['getRandomCalendarObjectUri', 'getSubscription', 'queryWebcalFeed'])
- ->setConstructorArgs([$this->caldavBackend, $this->clientService, $this->config, $this->logger])
+ ->onlyMethods(['getRandomCalendarObjectUri', 'getSubscription',])
+ ->setConstructorArgs([$this->caldavBackend, $this->logger, $this->connection, $this->time])
->getMock();
$refreshWebcalService
@@ -148,72 +212,39 @@ class RefreshWebcalServiceTest extends TestCase {
->willReturn([
'id' => '42',
'uri' => 'sub123',
- '{http://apple.com/ns/ical/}refreshrate' => 'PT1H',
- '{http://calendarserver.org/ns/}subscribed-strip-todos' => '1',
- '{http://calendarserver.org/ns/}subscribed-strip-alarms' => '1',
- '{http://calendarserver.org/ns/}subscribed-strip-attachments' => '1',
- 'source' => 'webcal://foo.bar/bla2'
+ RefreshWebcalService::REFRESH_RATE => 'PT1H',
+ RefreshWebcalService::STRIP_TODOS => '1',
+ RefreshWebcalService::STRIP_ALARMS => '1',
+ RefreshWebcalService::STRIP_ATTACHMENTS => '1',
+ 'source' => 'webcal://foo.bar/bla2',
+ 'lastmodified' => 0,
]);
- $this->clientService->expects($this->once())
- ->method('newClient')
- ->with()
- ->willReturn($client);
-
- $this->config->expects($this->once())
- ->method('getAppValue')
- ->with('dav', 'webcalAllowLocalAccess', 'no')
- ->willReturn('no');
-
- $client->expects($this->once())
- ->method('get')
- ->with('https://foo.bar/bla2', $this->callback(function ($obj) {
- return $obj['allow_redirects']['redirects'] === 10 && $obj['handler'] instanceof HandlerStack;
- }))
- ->willReturn($response);
-
- $response->expects($this->once())
- ->method('getBody')
- ->with()
- ->willReturn($body);
- $response->expects($this->once())
- ->method('getHeader')
- ->with('Content-Type')
- ->willReturn($contentType);
-
- $this->caldavBackend->expects($this->once())
- ->method('purgeAllCachedEventsForSubscription')
- ->with(42);
-
- $this->caldavBackend->expects($this->once())
+ $this->connection->expects(self::once())
+ ->method('queryWebcalFeed')
+ ->willReturn($result);
+
+ $this->caldavBackend->expects(self::once())
->method('createCalendarObject')
->with(42, 'uri-1.ics', $result, 1);
$noInstanceException = new NoInstancesException("can't add calendar object");
- $this->caldavBackend->expects($this->once())
- ->method("createCalendarObject")
+ $this->caldavBackend->expects(self::once())
+ ->method('createCalendarObject')
->willThrowException($noInstanceException);
- $this->logger->expects($this->once())
- ->method('error')
+ $this->logger->expects(self::once())
+ ->method('warning')
->with('Unable to create calendar object from subscription {subscriptionId}', ['exception' => $noInstanceException, 'subscriptionId' => '42', 'source' => 'webcal://foo.bar/bla2']);
$refreshWebcalService->refreshSubscription('principals/users/testuser', 'sub123');
}
- /**
- * @param string $body
- * @param string $contentType
- * @param string $result
- *
- * @dataProvider runDataProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('runDataProvider')]
public function testRunCreateCalendarBadRequest(string $body, string $contentType, string $result): void {
- $client = $this->createMock(IClient::class);
- $response = $this->createMock(IResponse::class);
$refreshWebcalService = $this->getMockBuilder(RefreshWebcalService::class)
- ->onlyMethods(['getRandomCalendarObjectUri', 'getSubscription', 'queryWebcalFeed'])
- ->setConstructorArgs([$this->caldavBackend, $this->clientService, $this->config, $this->logger])
+ ->onlyMethods(['getRandomCalendarObjectUri', 'getSubscription'])
+ ->setConstructorArgs([$this->caldavBackend, $this->logger, $this->connection, $this->time])
->getMock();
$refreshWebcalService
@@ -225,63 +256,54 @@ class RefreshWebcalServiceTest extends TestCase {
->willReturn([
'id' => '42',
'uri' => 'sub123',
- '{http://apple.com/ns/ical/}refreshrate' => 'PT1H',
- '{http://calendarserver.org/ns/}subscribed-strip-todos' => '1',
- '{http://calendarserver.org/ns/}subscribed-strip-alarms' => '1',
- '{http://calendarserver.org/ns/}subscribed-strip-attachments' => '1',
- 'source' => 'webcal://foo.bar/bla2'
+ RefreshWebcalService::REFRESH_RATE => 'PT1H',
+ RefreshWebcalService::STRIP_TODOS => '1',
+ RefreshWebcalService::STRIP_ALARMS => '1',
+ RefreshWebcalService::STRIP_ATTACHMENTS => '1',
+ 'source' => 'webcal://foo.bar/bla2',
+ 'lastmodified' => 0,
]);
- $this->clientService->expects($this->once())
- ->method('newClient')
- ->with()
- ->willReturn($client);
-
- $this->config->expects($this->once())
- ->method('getAppValue')
- ->with('dav', 'webcalAllowLocalAccess', 'no')
- ->willReturn('no');
-
- $client->expects($this->once())
- ->method('get')
- ->with('https://foo.bar/bla2', $this->callback(function ($obj) {
- return $obj['allow_redirects']['redirects'] === 10 && $obj['handler'] instanceof HandlerStack;
- }))
- ->willReturn($response);
-
- $response->expects($this->once())
- ->method('getBody')
- ->with()
- ->willReturn($body);
- $response->expects($this->once())
- ->method('getHeader')
- ->with('Content-Type')
- ->willReturn($contentType);
-
- $this->caldavBackend->expects($this->once())
- ->method('purgeAllCachedEventsForSubscription')
- ->with(42);
-
- $this->caldavBackend->expects($this->once())
+ $this->connection->expects(self::once())
+ ->method('queryWebcalFeed')
+ ->willReturn($result);
+
+ $this->caldavBackend->expects(self::once())
->method('createCalendarObject')
->with(42, 'uri-1.ics', $result, 1);
$badRequestException = new BadRequest("can't add reach calendar url");
- $this->caldavBackend->expects($this->once())
- ->method("createCalendarObject")
+ $this->caldavBackend->expects(self::once())
+ ->method('createCalendarObject')
->willThrowException($badRequestException);
- $this->logger->expects($this->once())
- ->method('error')
+ $this->logger->expects(self::once())
+ ->method('warning')
->with('Unable to create calendar object from subscription {subscriptionId}', ['exception' => $badRequestException, 'subscriptionId' => '42', 'source' => 'webcal://foo.bar/bla2']);
$refreshWebcalService->refreshSubscription('principals/users/testuser', 'sub123');
}
- /**
- * @return array
- */
- public function runDataProvider():array {
+ public static function identicalDataProvider(): array {
+ return [
+ [
+ '12345',
+ [
+ '12345' => [
+ 'id' => 42,
+ 'etag' => 100,
+ 'uri' => 'sub456',
+ 'calendardata' => "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20160218T133704Z\r\nDTSTART;VALUE=DATE:19000101\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:12345's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n",
+ ],
+ ],
+ "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20160218T133704Z\r\nDTSTART;VALUE=DATE:19000101\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:12345's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n",
+ 'text/calendar;charset=utf8',
+ "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20180218T133704Z\r\nDTSTART;VALUE=DATE:19000101\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:12345's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n",
+ ],
+ ];
+ }
+
+ public static function runDataProvider(): array {
return [
[
"BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20160218T133704Z\r\nDTSTART;VALUE=DATE:19000101\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:12345's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n",
@@ -300,109 +322,4 @@ class RefreshWebcalServiceTest extends TestCase {
]
];
}
-
- /**
- * @dataProvider runLocalURLDataProvider
- */
- public function testRunLocalURL(string $source): void {
- $refreshWebcalService = new RefreshWebcalService(
- $this->caldavBackend,
- $this->clientService,
- $this->config,
- $this->logger
- );
-
- $this->caldavBackend->expects($this->once())
- ->method('getSubscriptionsForUser')
- ->with('principals/users/testuser')
- ->willReturn([
- [
- 'id' => 42,
- 'uri' => 'sub123',
- 'refreshreate' => 'P1H',
- 'striptodos' => 1,
- 'stripalarms' => 1,
- 'stripattachments' => 1,
- 'source' => $source
- ],
- ]);
-
- $client = $this->createMock(IClient::class);
- $this->clientService->expects($this->once())
- ->method('newClient')
- ->with()
- ->willReturn($client);
-
- $this->config->expects($this->once())
- ->method('getAppValue')
- ->with('dav', 'webcalAllowLocalAccess', 'no')
- ->willReturn('no');
-
- $localServerException = new LocalServerException();
-
- $client->expects($this->once())
- ->method('get')
- ->willThrowException($localServerException);
-
- $this->logger->expects($this->once())
- ->method('warning')
- ->with("Subscription 42 was not refreshed because it violates local access rules", ['exception' => $localServerException]);
-
- $refreshWebcalService->refreshSubscription('principals/users/testuser', 'sub123');
- }
-
- public function runLocalURLDataProvider():array {
- return [
- ['localhost/foo.bar'],
- ['localHost/foo.bar'],
- ['random-host/foo.bar'],
- ['[::1]/bla.blub'],
- ['[::]/bla.blub'],
- ['192.168.0.1'],
- ['172.16.42.1'],
- ['[fdf8:f53b:82e4::53]/secret.ics'],
- ['[fe80::200:5aee:feaa:20a2]/secret.ics'],
- ['[0:0:0:0:0:0:10.0.0.1]/secret.ics'],
- ['[0:0:0:0:0:ffff:127.0.0.0]/secret.ics'],
- ['10.0.0.1'],
- ['another-host.local'],
- ['service.localhost'],
- ];
- }
-
- public function testInvalidUrl(): void {
- $refreshWebcalService = new RefreshWebcalService($this->caldavBackend,
- $this->clientService, $this->config, $this->logger);
-
- $this->caldavBackend->expects($this->once())
- ->method('getSubscriptionsForUser')
- ->with('principals/users/testuser')
- ->willReturn([
- [
- 'id' => 42,
- 'uri' => 'sub123',
- 'refreshreate' => 'P1H',
- 'striptodos' => 1,
- 'stripalarms' => 1,
- 'stripattachments' => 1,
- 'source' => '!@#$'
- ],
- ]);
-
- $client = $this->createMock(IClient::class);
- $this->clientService->expects($this->once())
- ->method('newClient')
- ->with()
- ->willReturn($client);
-
- $this->config->expects($this->once())
- ->method('getAppValue')
- ->with('dav', 'webcalAllowLocalAccess', 'no')
- ->willReturn('no');
-
- $client->expects($this->never())
- ->method('get');
-
- $refreshWebcalService->refreshSubscription('principals/users/testuser', 'sub123');
- }
}
diff --git a/apps/dav/tests/unit/CapabilitiesTest.php b/apps/dav/tests/unit/CapabilitiesTest.php
index acdfb4a2443..ad70d576d48 100644
--- a/apps/dav/tests/unit/CapabilitiesTest.php
+++ b/apps/dav/tests/unit/CapabilitiesTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,6 +9,7 @@ namespace OCA\DAV\Tests\unit;
use OCA\DAV\Capabilities;
use OCP\IConfig;
+use OCP\User\IAvailabilityCoordinator;
use Test\TestCase;
/**
@@ -19,10 +22,15 @@ class CapabilitiesTest extends TestCase {
->method('getSystemValueBool')
->with('bulkupload.enabled', $this->isType('bool'))
->willReturn(false);
- $capabilities = new Capabilities($config);
+ $coordinator = $this->createMock(IAvailabilityCoordinator::class);
+ $coordinator->expects($this->once())
+ ->method('isEnabled')
+ ->willReturn(false);
+ $capabilities = new Capabilities($config, $coordinator);
$expected = [
'dav' => [
'chunking' => '1.0',
+ 'public_shares_chunking' => true,
],
];
$this->assertSame($expected, $capabilities->getCapabilities());
@@ -34,13 +42,40 @@ class CapabilitiesTest extends TestCase {
->method('getSystemValueBool')
->with('bulkupload.enabled', $this->isType('bool'))
->willReturn(true);
- $capabilities = new Capabilities($config);
+ $coordinator = $this->createMock(IAvailabilityCoordinator::class);
+ $coordinator->expects($this->once())
+ ->method('isEnabled')
+ ->willReturn(false);
+ $capabilities = new Capabilities($config, $coordinator);
$expected = [
'dav' => [
'chunking' => '1.0',
+ 'public_shares_chunking' => true,
'bulkupload' => '1.0',
],
];
$this->assertSame($expected, $capabilities->getCapabilities());
}
+
+ public function testGetCapabilitiesWithAbsence(): void {
+ $config = $this->createMock(IConfig::class);
+ $config->expects($this->once())
+ ->method('getSystemValueBool')
+ ->with('bulkupload.enabled', $this->isType('bool'))
+ ->willReturn(false);
+ $coordinator = $this->createMock(IAvailabilityCoordinator::class);
+ $coordinator->expects($this->once())
+ ->method('isEnabled')
+ ->willReturn(true);
+ $capabilities = new Capabilities($config, $coordinator);
+ $expected = [
+ 'dav' => [
+ 'chunking' => '1.0',
+ 'public_shares_chunking' => true,
+ 'absence-supported' => true,
+ 'absence-replacement' => true,
+ ],
+ ];
+ $this->assertSame($expected, $capabilities->getCapabilities());
+ }
}
diff --git a/apps/dav/tests/unit/CardDAV/Activity/BackendTest.php b/apps/dav/tests/unit/CardDAV/Activity/BackendTest.php
index 134a6ca5ca0..a070a3d7131 100644
--- a/apps/dav/tests/unit/CardDAV/Activity/BackendTest.php
+++ b/apps/dav/tests/unit/CardDAV/Activity/BackendTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -20,20 +22,11 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class BackendTest extends TestCase {
- /** @var IManager|MockObject */
- protected $activityManager;
-
- /** @var IGroupManager|MockObject */
- protected $groupManager;
-
- /** @var IUserSession|MockObject */
- protected $userSession;
-
- /** @var IAppManager|MockObject */
- protected $appManager;
-
- /** @var IUserManager|MockObject */
- protected $userManager;
+ protected IManager&MockObject $activityManager;
+ protected IGroupManager&MockObject $groupManager;
+ protected IUserSession&MockObject $userSession;
+ protected IAppManager&MockObject $appManager;
+ protected IUserManager&MockObject $userManager;
protected function setUp(): void {
parent::setUp();
@@ -45,10 +38,9 @@ class BackendTest extends TestCase {
}
/**
- * @param array $methods
* @return Backend|MockObject
*/
- protected function getBackend(array $methods = []) {
+ protected function getBackend(array $methods = []): Backend {
if (empty($methods)) {
return new Backend(
$this->activityManager,
@@ -71,7 +63,7 @@ class BackendTest extends TestCase {
}
}
- public function dataCallTriggerAddressBookActivity(): array {
+ public static function dataCallTriggerAddressBookActivity(): array {
return [
['onAddressbookCreate', [['data']], Addressbook::SUBJECT_ADD, [['data'], [], []]],
['onAddressbookUpdate', [['data'], ['shares'], ['changed-properties']], Addressbook::SUBJECT_UPDATE, [['data'], ['shares'], ['changed-properties']]],
@@ -79,9 +71,7 @@ class BackendTest extends TestCase {
];
}
- /**
- * @dataProvider dataCallTriggerAddressBookActivity
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataCallTriggerAddressBookActivity')]
public function testCallTriggerAddressBookActivity(string $method, array $payload, string $expectedSubject, array $expectedPayload): void {
$backend = $this->getBackend(['triggerAddressbookActivity']);
$backend->expects($this->once())
@@ -95,7 +85,7 @@ class BackendTest extends TestCase {
call_user_func_array([$backend, $method], $payload);
}
- public function dataTriggerAddressBookActivity(): array {
+ public static function dataTriggerAddressBookActivity(): array {
return [
// Add addressbook
[Addressbook::SUBJECT_ADD, [], [], [], '', '', null, []],
@@ -159,16 +149,10 @@ class BackendTest extends TestCase {
}
/**
- * @dataProvider dataTriggerAddressBookActivity
- * @param string $action
- * @param array $data
- * @param array $shares
- * @param array $changedProperties
- * @param string $currentUser
- * @param string $author
* @param string[]|null $shareUsers
* @param string[] $users
*/
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTriggerAddressBookActivity')]
public function testTriggerAddressBookActivity(string $action, array $data, array $shares, array $changedProperties, string $currentUser, string $author, ?array $shareUsers, array $users): void {
$backend = $this->getBackend(['getUsersForShares']);
@@ -219,13 +203,13 @@ class BackendTest extends TestCase {
->method('userExists')
->willReturn(true);
- $event->expects($this->exactly(sizeof($users)))
+ $event->expects($this->exactly(count($users)))
->method('setAffectedUser')
->willReturnSelf();
- $event->expects($this->exactly(sizeof($users)))
+ $event->expects($this->exactly(count($users)))
->method('setSubject')
->willReturnSelf();
- $this->activityManager->expects($this->exactly(sizeof($users)))
+ $this->activityManager->expects($this->exactly(count($users)))
->method('publish')
->with($event);
} else {
@@ -261,7 +245,7 @@ class BackendTest extends TestCase {
], [], []]);
}
- public function dataTriggerCardActivity(): array {
+ public static function dataTriggerCardActivity(): array {
$cardData = "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.4.8//EN\r\nUID:test-user\r\nFN:test-user\r\nN:test-user;;;;\r\nEND:VCARD\r\n\r\n";
return [
@@ -329,16 +313,10 @@ class BackendTest extends TestCase {
}
/**
- * @dataProvider dataTriggerCardActivity
- * @param string $action
- * @param array $addressBookData
- * @param array $shares
- * @param array $cardData
- * @param string $currentUser
- * @param string $author
* @param string[]|null $shareUsers
* @param string[] $users
*/
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTriggerCardActivity')]
public function testTriggerCardActivity(string $action, array $addressBookData, array $shares, array $cardData, string $currentUser, string $author, ?array $shareUsers, array $users): void {
$backend = $this->getBackend(['getUsersForShares']);
@@ -385,13 +363,13 @@ class BackendTest extends TestCase {
->with($author)
->willReturnSelf();
- $event->expects($this->exactly(sizeof($users)))
+ $event->expects($this->exactly(count($users)))
->method('setAffectedUser')
->willReturnSelf();
- $event->expects($this->exactly(sizeof($users)))
+ $event->expects($this->exactly(count($users)))
->method('setSubject')
->willReturnSelf();
- $this->activityManager->expects($this->exactly(sizeof($users)))
+ $this->activityManager->expects($this->exactly(count($users)))
->method('publish')
->with($event);
} else {
@@ -409,7 +387,7 @@ class BackendTest extends TestCase {
$this->assertEmpty($this->invokePrivate($backend, 'triggerCardActivity', [Card::SUBJECT_UPDATE, ['principaluri' => 'principals/system/system'], [], []]));
}
- public function dataGetUsersForShares(): array {
+ public static function dataGetUsersForShares(): array {
return [
[
[],
@@ -452,12 +430,7 @@ class BackendTest extends TestCase {
];
}
- /**
- * @dataProvider dataGetUsersForShares
- * @param array $shares
- * @param array $groups
- * @param array $expected
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataGetUsersForShares')]
public function testGetUsersForShares(array $shares, array $groups, array $expected): void {
$backend = $this->getBackend();
@@ -498,10 +471,9 @@ class BackendTest extends TestCase {
}
/**
- * @param string $uid
* @return IUser|MockObject
*/
- protected function getUserMock(string $uid) {
+ protected function getUserMock(string $uid): IUser {
$user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
diff --git a/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php b/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php
index fb12b5b0884..74699cf3925 100644
--- a/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php
+++ b/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php
@@ -10,30 +10,22 @@ namespace OCA\DAV\Tests\unit\CardDAV;
use OCA\DAV\CardDAV\AddressBook;
use OCA\DAV\CardDAV\AddressBookImpl;
use OCA\DAV\CardDAV\CardDavBackend;
+use OCA\DAV\Db\PropertyMapper;
use OCP\IURLGenerator;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Component\VCard;
use Sabre\VObject\Property\Text;
//use Sabre\VObject\Property\;
use Test\TestCase;
class AddressBookImplTest extends TestCase {
- /** @var AddressBookImpl */
- private $addressBookImpl;
-
- /** @var array */
- private $addressBookInfo;
-
- /** @var AddressBook | \PHPUnit\Framework\MockObject\MockObject */
- private $addressBook;
-
- /** @var IURLGenerator | \PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
-
- /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $backend;
-
- /** @var VCard | \PHPUnit\Framework\MockObject\MockObject */
- private $vCard;
+ private array $addressBookInfo;
+ private AddressBook&MockObject $addressBook;
+ private IURLGenerator&MockObject $urlGenerator;
+ private CardDavBackend&MockObject $backend;
+ private PropertyMapper&MockObject $propertyMapper;
+ private VCard&MockObject $vCard;
+ private AddressBookImpl $addressBookImpl;
protected function setUp(): void {
parent::setUp();
@@ -44,18 +36,19 @@ class AddressBookImplTest extends TestCase {
'principaluri' => 'principals/system/system',
'{DAV:}displayname' => 'display name',
];
- $this->addressBook = $this->getMockBuilder(AddressBook::class)
- ->disableOriginalConstructor()->getMock();
- $this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->disableOriginalConstructor()->getMock();
+ $this->addressBook = $this->createMock(AddressBook::class);
+ $this->backend = $this->createMock(CardDavBackend::class);
$this->vCard = $this->createMock(VCard::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
+ $this->propertyMapper = $this->createMock(PropertyMapper::class);
$this->addressBookImpl = new AddressBookImpl(
$this->addressBook,
$this->addressBookInfo,
$this->backend,
- $this->urlGenerator
+ $this->urlGenerator,
+ $this->propertyMapper,
+ null
);
}
@@ -70,7 +63,7 @@ class AddressBookImplTest extends TestCase {
}
public function testSearch(): void {
- /** @var \PHPUnit\Framework\MockObject\MockObject | AddressBookImpl $addressBookImpl */
+ /** @var MockObject&AddressBookImpl $addressBookImpl */
$addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
->setConstructorArgs(
[
@@ -78,9 +71,11 @@ class AddressBookImplTest extends TestCase {
$this->addressBookInfo,
$this->backend,
$this->urlGenerator,
+ $this->propertyMapper,
+ null
]
)
- ->setMethods(['vCard2Array', 'readCard'])
+ ->onlyMethods(['vCard2Array', 'readCard'])
->getMock();
$pattern = 'pattern';
@@ -98,25 +93,21 @@ class AddressBookImplTest extends TestCase {
$addressBookImpl->expects($this->exactly(2))->method('readCard')
->willReturn($this->vCard);
$addressBookImpl->expects($this->exactly(2))->method('vCard2Array')
- ->withConsecutive(
- ['foo.vcf', $this->vCard],
- ['bar.vcf', $this->vCard]
- )->willReturn('vCard');
+ ->willReturnMap([
+ ['foo.vcf', $this->vCard, 'vCard'],
+ ['bar.vcf', $this->vCard, 'vCard'],
+ ]);
$result = $addressBookImpl->search($pattern, $searchProperties, []);
$this->assertTrue((is_array($result)));
$this->assertSame(2, count($result));
}
- /**
- * @dataProvider dataTestCreate
- *
- * @param array $properties
- */
- public function testCreate($properties): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestCreate')]
+ public function testCreate(array $properties): void {
$uid = 'uid';
- /** @var \PHPUnit\Framework\MockObject\MockObject | AddressBookImpl $addressBookImpl */
+ /** @var MockObject&AddressBookImpl $addressBookImpl */
$addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
->setConstructorArgs(
[
@@ -124,9 +115,11 @@ class AddressBookImplTest extends TestCase {
$this->addressBookInfo,
$this->backend,
$this->urlGenerator,
+ $this->propertyMapper,
+ null
]
)
- ->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard'])
+ ->onlyMethods(['vCard2Array', 'createUid', 'createEmptyVCard'])
->getMock();
$expectedProperties = 0;
@@ -153,7 +146,7 @@ class AddressBookImplTest extends TestCase {
$this->assertTrue($addressBookImpl->createOrUpdate($properties));
}
- public function dataTestCreate() {
+ public static function dataTestCreate(): array {
return [
[[]],
[['FN' => 'John Doe']],
@@ -166,7 +159,7 @@ class AddressBookImplTest extends TestCase {
$uri = 'bla.vcf';
$properties = ['URI' => $uri, 'UID' => $uid, 'FN' => 'John Doe'];
- /** @var \PHPUnit\Framework\MockObject\MockObject | AddressBookImpl $addressBookImpl */
+ /** @var MockObject&AddressBookImpl $addressBookImpl */
$addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
->setConstructorArgs(
[
@@ -174,9 +167,11 @@ class AddressBookImplTest extends TestCase {
$this->addressBookInfo,
$this->backend,
$this->urlGenerator,
+ $this->propertyMapper,
+ null
]
)
- ->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard'])
+ ->onlyMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard'])
->getMock();
$addressBookImpl->expects($this->never())->method('createUid');
@@ -203,7 +198,7 @@ class AddressBookImplTest extends TestCase {
$vCard = new vCard;
$textProperty = $vCard->createProperty('KEY', 'value');
- /** @var \PHPUnit\Framework\MockObject\MockObject | AddressBookImpl $addressBookImpl */
+ /** @var MockObject&AddressBookImpl $addressBookImpl */
$addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
->setConstructorArgs(
[
@@ -211,9 +206,11 @@ class AddressBookImplTest extends TestCase {
$this->addressBookInfo,
$this->backend,
$this->urlGenerator,
+ $this->propertyMapper,
+ null
]
)
- ->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard'])
+ ->onlyMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard'])
->getMock();
$this->backend->expects($this->once())->method('getCard')
@@ -231,13 +228,8 @@ class AddressBookImplTest extends TestCase {
$addressBookImpl->createOrUpdate($properties);
}
- /**
- * @dataProvider dataTestGetPermissions
- *
- * @param array $permissions
- * @param int $expected
- */
- public function testGetPermissions($permissions, $expected): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestGetPermissions')]
+ public function testGetPermissions(array $permissions, int $expected): void {
$this->addressBook->expects($this->once())->method('getACL')
->willReturn($permissions);
@@ -246,17 +238,18 @@ class AddressBookImplTest extends TestCase {
);
}
- public function dataTestGetPermissions() {
+ public static function dataTestGetPermissions(): array {
return [
[[], 0],
- [[['privilege' => '{DAV:}read']], 1],
- [[['privilege' => '{DAV:}write']], 6],
- [[['privilege' => '{DAV:}all']], 31],
- [[['privilege' => '{DAV:}read'],['privilege' => '{DAV:}write']], 7],
- [[['privilege' => '{DAV:}read'],['privilege' => '{DAV:}all']], 31],
- [[['privilege' => '{DAV:}all'],['privilege' => '{DAV:}write']], 31],
- [[['privilege' => '{DAV:}read'],['privilege' => '{DAV:}write'],['privilege' => '{DAV:}all']], 31],
- [[['privilege' => '{DAV:}all'],['privilege' => '{DAV:}read'],['privilege' => '{DAV:}write']], 31],
+ [[['privilege' => '{DAV:}read', 'principal' => 'principals/system/system']], 1],
+ [[['privilege' => '{DAV:}read', 'principal' => 'principals/system/system'], ['privilege' => '{DAV:}write', 'principal' => 'principals/someone/else']], 1],
+ [[['privilege' => '{DAV:}write', 'principal' => 'principals/system/system']], 6],
+ [[['privilege' => '{DAV:}all', 'principal' => 'principals/system/system']], 31],
+ [[['privilege' => '{DAV:}read', 'principal' => 'principals/system/system'],['privilege' => '{DAV:}write', 'principal' => 'principals/system/system']], 7],
+ [[['privilege' => '{DAV:}read', 'principal' => 'principals/system/system'],['privilege' => '{DAV:}all', 'principal' => 'principals/system/system']], 31],
+ [[['privilege' => '{DAV:}all', 'principal' => 'principals/system/system'],['privilege' => '{DAV:}write', 'principal' => 'principals/system/system']], 31],
+ [[['privilege' => '{DAV:}read', 'principal' => 'principals/system/system'],['privilege' => '{DAV:}write', 'principal' => 'principals/system/system'],['privilege' => '{DAV:}all', 'principal' => 'principals/system/system']], 31],
+ [[['privilege' => '{DAV:}all', 'principal' => 'principals/system/system'],['privilege' => '{DAV:}read', 'principal' => 'principals/system/system'],['privilege' => '{DAV:}write', 'principal' => 'principals/system/system']], 31],
];
}
@@ -284,7 +277,7 @@ class AddressBookImplTest extends TestCase {
}
public function testCreateUid(): void {
- /** @var \PHPUnit\Framework\MockObject\MockObject | AddressBookImpl $addressBookImpl */
+ /** @var MockObject&AddressBookImpl $addressBookImpl */
$addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
->setConstructorArgs(
[
@@ -292,9 +285,11 @@ class AddressBookImplTest extends TestCase {
$this->addressBookInfo,
$this->backend,
$this->urlGenerator,
+ $this->propertyMapper,
+ null
]
)
- ->setMethods(['getUid'])
+ ->onlyMethods(['getUid'])
->getMock();
$addressBookImpl->expects($this->exactly(2))
@@ -488,7 +483,9 @@ class AddressBookImplTest extends TestCase {
$this->addressBook,
$addressBookInfo,
$this->backend,
- $this->urlGenerator
+ $this->urlGenerator,
+ $this->propertyMapper,
+ null
);
$this->assertTrue($addressBookImpl->isSystemAddressBook());
@@ -507,7 +504,9 @@ class AddressBookImplTest extends TestCase {
$this->addressBook,
$addressBookInfo,
$this->backend,
- $this->urlGenerator
+ $this->urlGenerator,
+ $this->propertyMapper,
+ 'user2'
);
$this->assertFalse($addressBookImpl->isSystemAddressBook());
@@ -527,7 +526,9 @@ class AddressBookImplTest extends TestCase {
$this->addressBook,
$addressBookInfo,
$this->backend,
- $this->urlGenerator
+ $this->urlGenerator,
+ $this->propertyMapper,
+ 'user2'
);
$this->assertFalse($addressBookImpl->isSystemAddressBook());
diff --git a/apps/dav/tests/unit/CardDAV/AddressBookTest.php b/apps/dav/tests/unit/CardDAV/AddressBookTest.php
index cbdb9a1402c..cf28b7b8a8e 100644
--- a/apps/dav/tests/unit/CardDAV/AddressBookTest.php
+++ b/apps/dav/tests/unit/CardDAV/AddressBookTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -28,19 +29,20 @@ class AddressBookTest extends TestCase {
'uri' => 'default',
];
$l10n = $this->createMock(IL10N::class);
- $logger = $this->createMock(LoggerInterface::class);
- $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger);
+ $addressBook = new AddressBook($backend, $addressBookInfo, $l10n);
$card = new Card($backend, $addressBookInfo, ['id' => 5, 'carddata' => 'RANDOM VCF DATA', 'uri' => 'something', 'addressbookid' => 23]);
- $backend->expects($this->once())->method('moveCard')->with(23, 666, 'something', 'user1')->willReturn(true);
+ $backend->expects($this->once())->method('moveCard')
+ ->with(23, 'something', 666, 'new')
+ ->willReturn(true);
$addressBook->moveInto('new', 'old', $card);
}
public function testDelete(): void {
/** @var MockObject | CardDavBackend $backend */
- $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ $backend = $this->createMock(CardDavBackend::class);
$backend->expects($this->once())->method('updateShares');
$backend->expects($this->any())->method('getShares')->willReturn([
['href' => 'principal:user2']
@@ -54,7 +56,7 @@ class AddressBookTest extends TestCase {
];
$l10n = $this->createMock(IL10N::class);
$logger = $this->createMock(LoggerInterface::class);
- $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger);
+ $addressBook = new AddressBook($backend, $addressBookInfo, $l10n);
$addressBook->delete();
}
@@ -63,7 +65,7 @@ class AddressBookTest extends TestCase {
$this->expectException(Forbidden::class);
/** @var MockObject | CardDavBackend $backend */
- $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ $backend = $this->createMock(CardDavBackend::class);
$backend->expects($this->never())->method('updateShares');
$backend->expects($this->any())->method('getShares')->willReturn([
['href' => 'principal:group2']
@@ -77,14 +79,14 @@ class AddressBookTest extends TestCase {
];
$l10n = $this->createMock(IL10N::class);
$logger = $this->createMock(LoggerInterface::class);
- $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger);
+ $addressBook = new AddressBook($backend, $addressBookInfo, $l10n);
$addressBook->delete();
}
public function testPropPatchShared(): void {
/** @var MockObject | CardDavBackend $backend */
- $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ $backend = $this->createMock(CardDavBackend::class);
$backend->expects($this->never())->method('updateAddressBook');
$addressBookInfo = [
'{http://owncloud.org/ns}owner-principal' => 'user1',
@@ -95,13 +97,13 @@ class AddressBookTest extends TestCase {
];
$l10n = $this->createMock(IL10N::class);
$logger = $this->createMock(LoggerInterface::class);
- $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger);
+ $addressBook = new AddressBook($backend, $addressBookInfo, $l10n);
$addressBook->propPatch(new PropPatch(['{DAV:}displayname' => 'Test address book']));
}
public function testPropPatchNotShared(): void {
/** @var MockObject | CardDavBackend $backend */
- $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ $backend = $this->createMock(CardDavBackend::class);
$backend->expects($this->atLeast(1))->method('updateAddressBook');
$addressBookInfo = [
'{DAV:}displayname' => 'Test address book',
@@ -111,16 +113,14 @@ class AddressBookTest extends TestCase {
];
$l10n = $this->createMock(IL10N::class);
$logger = $this->createMock(LoggerInterface::class);
- $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger);
+ $addressBook = new AddressBook($backend, $addressBookInfo, $l10n);
$addressBook->propPatch(new PropPatch(['{DAV:}displayname' => 'Test address book']));
}
- /**
- * @dataProvider providesReadOnlyInfo
- */
- public function testAcl($expectsWrite, $readOnlyValue, $hasOwnerSet): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesReadOnlyInfo')]
+ public function testAcl(bool $expectsWrite, ?bool $readOnlyValue, bool $hasOwnerSet): void {
/** @var MockObject | CardDavBackend $backend */
- $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ $backend = $this->createMock(CardDavBackend::class);
$backend->expects($this->any())->method('applyShareAcl')->willReturnArgument(1);
$addressBookInfo = [
'{DAV:}displayname' => 'Test address book',
@@ -136,7 +136,7 @@ class AddressBookTest extends TestCase {
}
$l10n = $this->createMock(IL10N::class);
$logger = $this->createMock(LoggerInterface::class);
- $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger);
+ $addressBook = new AddressBook($backend, $addressBookInfo, $l10n);
$acl = $addressBook->getACL();
$childAcl = $addressBook->getChildACL();
@@ -171,7 +171,7 @@ class AddressBookTest extends TestCase {
$this->assertEquals($expectedAcl, $childAcl);
}
- public function providesReadOnlyInfo(): array {
+ public static function providesReadOnlyInfo(): array {
return [
'read-only property not set' => [true, null, true],
'read-only property is false' => [true, false, true],
diff --git a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
index aeee04fd6ee..6908dfd17bc 100644
--- a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
+++ b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -14,25 +15,19 @@ use OCA\DAV\DAV\GroupPrincipalBackend;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IL10N;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\Reader;
use Test\TestCase;
class BirthdayServiceTest extends TestCase {
- /** @var BirthdayService */
- private $service;
- /** @var CalDavBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $calDav;
- /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $cardDav;
- /** @var GroupPrincipalBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $groupPrincipalBackend;
- /** @var IConfig | \PHPUnit\Framework\MockObject\MockObject */
- private $config;
- /** @var IDBConnection | \PHPUnit\Framework\MockObject\MockObject */
- private $dbConnection;
- /** @var IL10N | \PHPUnit\Framework\MockObject\MockObject */
- private $l10n;
+ private CalDavBackend&MockObject $calDav;
+ private CardDavBackend&MockObject $cardDav;
+ private GroupPrincipalBackend&MockObject $groupPrincipalBackend;
+ private IConfig&MockObject $config;
+ private IDBConnection&MockObject $dbConnection;
+ private IL10N&MockObject $l10n;
+ private BirthdayService $service;
protected function setUp(): void {
parent::setUp();
@@ -55,18 +50,8 @@ class BirthdayServiceTest extends TestCase {
$this->dbConnection, $this->l10n);
}
- /**
- * @dataProvider providesVCards
- * @param string $expectedSummary
- * @param string $expectedDTStart
- * @param string $expectedRrule
- * @param string $expectedFieldType
- * @param string $expectedUnknownYear
- * @param string $expectedOriginalYear
- * @param string|null $expectedReminder
- * @param string | null $data
- */
- public function testBuildBirthdayFromContact($expectedSummary, $expectedDTStart, $expectedRrule, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Bytes, $configuredReminder): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesVCards')]
+ public function testBuildBirthdayFromContact(?string $expectedSummary, ?string $expectedDTStart, ?string $expectedRrule, ?string $expectedFieldType, ?string $expectedUnknownYear, ?string $expectedOriginalYear, ?string $expectedReminder, ?string $data, string $fieldType, string $prefix, bool $supports4Bytes, ?string $configuredReminder): void {
$this->dbConnection->method('supports4ByteText')->willReturn($supports4Bytes);
$cal = $this->service->buildDateFromContact($data, $fieldType, $prefix, $configuredReminder);
@@ -152,13 +137,17 @@ class BirthdayServiceTest extends TestCase {
->willReturn([
'id' => 1234
]);
- $this->calDav->expects($this->exactly(3))
+ $calls = [
+ [1234, 'default-gump.vcf.ics'],
+ [1234, 'default-gump.vcf-death.ics'],
+ [1234, 'default-gump.vcf-anniversary.ics'],
+ ];
+ $this->calDav->expects($this->exactly(count($calls)))
->method('deleteCalendarObject')
- ->withConsecutive(
- [1234, 'default-gump.vcf.ics'],
- [1234, 'default-gump.vcf-death.ics'],
- [1234, 'default-gump.vcf-anniversary.ics'],
- );
+ ->willReturnCallback(function ($calendarId, $objectUri) use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, [$calendarId, $objectUri]);
+ });
$this->cardDav->expects($this->once())->method('getShares')->willReturn([]);
$this->service->onCardDeleted(666, 'gump.vcf');
@@ -173,7 +162,7 @@ class BirthdayServiceTest extends TestCase {
$this->cardDav->expects($this->never())->method('getAddressBookById');
$service = $this->getMockBuilder(BirthdayService::class)
- ->setMethods(['buildDateFromContact', 'birthdayEvenChanged'])
+ ->onlyMethods(['buildDateFromContact', 'birthdayEvenChanged'])
->setConstructorArgs([$this->calDav, $this->cardDav, $this->groupPrincipalBackend, $this->config, $this->dbConnection, $this->l10n])
->getMock();
@@ -200,19 +189,17 @@ class BirthdayServiceTest extends TestCase {
$this->cardDav->expects($this->once())->method('getShares')->willReturn([]);
$this->calDav->expects($this->never())->method('getCalendarByUri');
- /** @var BirthdayService | \PHPUnit\Framework\MockObject\MockObject $service */
+ /** @var BirthdayService&MockObject $service */
$service = $this->getMockBuilder(BirthdayService::class)
- ->setMethods(['buildDateFromContact', 'birthdayEvenChanged'])
+ ->onlyMethods(['buildDateFromContact', 'birthdayEvenChanged'])
->setConstructorArgs([$this->calDav, $this->cardDav, $this->groupPrincipalBackend, $this->config, $this->dbConnection, $this->l10n])
->getMock();
$service->onCardChanged(666, 'gump.vcf', '');
}
- /**
- * @dataProvider providesCardChanges
- */
- public function testOnCardChanged($expectedOp): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesCardChanges')]
+ public function testOnCardChanged(string $expectedOp): void {
$this->config->expects($this->once())
->method('getAppValue')
->with('dav', 'generateBirthdayCalendar', 'yes')
@@ -220,11 +207,10 @@ class BirthdayServiceTest extends TestCase {
$this->config->expects($this->exactly(2))
->method('getUserValue')
- ->withConsecutive(
- ['user01', 'dav', 'generateBirthdayCalendar', 'yes'],
- ['user01', 'dav', 'birthdayCalendarReminderOffset', 'PT9H'],
- )
- ->willReturnOnConsecutiveCalls('yes', 'PT9H');
+ ->willReturnMap([
+ ['user01', 'dav', 'generateBirthdayCalendar', 'yes', 'yes'],
+ ['user01', 'dav', 'birthdayCalendarReminderOffset', 'PT9H', 'PT9H'],
+ ]);
$this->cardDav->expects($this->once())->method('getAddressBookById')
->with(666)
@@ -239,31 +225,45 @@ class BirthdayServiceTest extends TestCase {
]);
$this->cardDav->expects($this->once())->method('getShares')->willReturn([]);
- /** @var BirthdayService | \PHPUnit\Framework\MockObject\MockObject $service */
+ /** @var BirthdayService&MockObject $service */
$service = $this->getMockBuilder(BirthdayService::class)
- ->setMethods(['buildDateFromContact', 'birthdayEvenChanged'])
+ ->onlyMethods(['buildDateFromContact', 'birthdayEvenChanged'])
->setConstructorArgs([$this->calDav, $this->cardDav, $this->groupPrincipalBackend, $this->config, $this->dbConnection, $this->l10n])
->getMock();
if ($expectedOp === 'delete') {
$this->calDav->expects($this->exactly(3))->method('getCalendarObject')->willReturn('');
$service->expects($this->exactly(3))->method('buildDateFromContact')->willReturn(null);
- $this->calDav->expects($this->exactly(3))->method('deleteCalendarObject')->withConsecutive(
+
+ $calls = [
[1234, 'default-gump.vcf.ics'],
[1234, 'default-gump.vcf-death.ics'],
[1234, 'default-gump.vcf-anniversary.ics']
- );
+ ];
+ $this->calDav->expects($this->exactly(count($calls)))
+ ->method('deleteCalendarObject')
+ ->willReturnCallback(function ($calendarId, $objectUri) use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, [$calendarId, $objectUri]);
+ });
}
if ($expectedOp === 'create') {
$vCal = new VCalendar();
$vCal->PRODID = '-//Nextcloud testing//mocked object//';
$service->expects($this->exactly(3))->method('buildDateFromContact')->willReturn($vCal);
- $this->calDav->expects($this->exactly(3))->method('createCalendarObject')->withConsecutive(
+
+ $createCalendarObjectCalls = [
[1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nPRODID:-//Nextcloud testing//mocked object//\r\nEND:VCALENDAR\r\n"],
[1234, 'default-gump.vcf-death.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nPRODID:-//Nextcloud testing//mocked object//\r\nEND:VCALENDAR\r\n"],
[1234, 'default-gump.vcf-anniversary.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nPRODID:-//Nextcloud testing//mocked object//\r\nEND:VCALENDAR\r\n"]
- );
+ ];
+ $this->calDav->expects($this->exactly(count($createCalendarObjectCalls)))
+ ->method('createCalendarObject')
+ ->willReturnCallback(function ($calendarId, $objectUri, $calendarData) use (&$createCalendarObjectCalls): void {
+ $expected = array_shift($createCalendarObjectCalls);
+ $this->assertEquals($expected, [$calendarId, $objectUri, $calendarData]);
+ });
}
if ($expectedOp === 'update') {
$vCal = new VCalendar();
@@ -272,23 +272,25 @@ class BirthdayServiceTest extends TestCase {
$service->expects($this->exactly(3))->method('buildDateFromContact')->willReturn($vCal);
$service->expects($this->exactly(3))->method('birthdayEvenChanged')->willReturn(true);
$this->calDav->expects($this->exactly(3))->method('getCalendarObject')->willReturn(['calendardata' => '']);
- $this->calDav->expects($this->exactly(3))->method('updateCalendarObject')->withConsecutive(
+
+ $updateCalendarObjectCalls = [
[1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nPRODID:-//Nextcloud testing//mocked object//\r\nEND:VCALENDAR\r\n"],
[1234, 'default-gump.vcf-death.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nPRODID:-//Nextcloud testing//mocked object//\r\nEND:VCALENDAR\r\n"],
[1234, 'default-gump.vcf-anniversary.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nPRODID:-//Nextcloud testing//mocked object//\r\nEND:VCALENDAR\r\n"]
- );
+ ];
+ $this->calDav->expects($this->exactly(count($updateCalendarObjectCalls)))
+ ->method('updateCalendarObject')
+ ->willReturnCallback(function ($calendarId, $objectUri, $calendarData) use (&$updateCalendarObjectCalls): void {
+ $expected = array_shift($updateCalendarObjectCalls);
+ $this->assertEquals($expected, [$calendarId, $objectUri, $calendarData]);
+ });
}
$service->onCardChanged(666, 'gump.vcf', '');
}
- /**
- * @dataProvider providesBirthday
- * @param $expected
- * @param $old
- * @param $new
- */
- public function testBirthdayEvenChanged($expected, $old, $new): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesBirthday')]
+ public function testBirthdayEvenChanged(bool $expected, string $old, string $new): void {
$new = Reader::read($new);
$this->assertEquals($expected, $this->service->birthdayEvenChanged($old, $new));
}
@@ -354,18 +356,22 @@ class BirthdayServiceTest extends TestCase {
->with(42, 0)
->willReturn([['uri' => '1.ics'], ['uri' => '2.ics'], ['uri' => '3.ics']]);
- $this->calDav->expects($this->exactly(3))
+ $calls = [
+ [42, '1.ics', 0],
+ [42, '2.ics', 0],
+ [42, '3.ics', 0],
+ ];
+ $this->calDav->expects($this->exactly(count($calls)))
->method('deleteCalendarObject')
- ->withConsecutive(
- [42, '1.ics', 0],
- [42, '2.ics', 0],
- [42, '3.ics', 0],
- );
+ ->willReturnCallback(function ($calendarId, $objectUri, $calendarType) use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, [$calendarId, $objectUri, $calendarType]);
+ });
$this->service->resetForUser('user123');
}
- public function providesBirthday() {
+ public static function providesBirthday(): array {
return [
[true,
'',
@@ -382,7 +388,7 @@ class BirthdayServiceTest extends TestCase {
];
}
- public function providesCardChanges() {
+ public static function providesCardChanges(): array {
return[
['delete'],
['create'],
@@ -390,7 +396,7 @@ class BirthdayServiceTest extends TestCase {
];
}
- public function providesVCards() {
+ public static function providesVCards(): array {
return [
// $expectedSummary, $expectedDTStart, $expectedRrule, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Byte, $configuredReminder
[null, null, null, null, null, null, null, 'yasfewf', '', '', true, null],
diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
index b8887e6f930..c5eafa0764a 100644
--- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
+++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
@@ -27,7 +27,9 @@ use OCP\IL10N;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\L10N\IFactory;
+use OCP\Server;
use OCP\Share\IManager as ShareManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\BadRequest;
use Sabre\DAV\PropPatch;
@@ -44,70 +46,58 @@ use function time;
* @package OCA\DAV\Tests\unit\CardDAV
*/
class CardDavBackendTest extends TestCase {
- /** @var CardDavBackend */
- private $backend;
-
- /** @var Principal | \PHPUnit\Framework\MockObject\MockObject */
- private $principal;
-
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- private $userManager;
-
- /** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */
- private $groupManager;
-
- /** @var IEventDispatcher|MockObject */
- private $dispatcher;
+ private Principal&MockObject $principal;
+ private IUserManager&MockObject $userManager;
+ private IGroupManager&MockObject $groupManager;
+ private IEventDispatcher&MockObject $dispatcher;
+ private IConfig&MockObject $config;
private Backend $sharingBackend;
- /** @var IDBConnection */
- private $db;
-
- /** @var string */
- private $dbCardsTable = 'cards';
-
- /** @var string */
- private $dbCardsPropertiesTable = 'cards_properties';
+ private IDBConnection $db;
+ private CardDavBackend $backend;
+ private string $dbCardsTable = 'cards';
+ private string $dbCardsPropertiesTable = 'cards_properties';
public const UNIT_TEST_USER = 'principals/users/carddav-unit-test';
public const UNIT_TEST_USER1 = 'principals/users/carddav-unit-test1';
public const UNIT_TEST_GROUP = 'principals/groups/carddav-unit-test-group';
- private $vcardTest0 = 'BEGIN:VCARD'.PHP_EOL.
- 'VERSION:3.0'.PHP_EOL.
- 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN'.PHP_EOL.
- 'UID:Test'.PHP_EOL.
- 'FN:Test'.PHP_EOL.
- 'N:Test;;;;'.PHP_EOL.
- 'END:VCARD';
-
- private $vcardTest1 = 'BEGIN:VCARD'.PHP_EOL.
- 'VERSION:3.0'.PHP_EOL.
- 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN'.PHP_EOL.
- 'UID:Test2'.PHP_EOL.
- 'FN:Test2'.PHP_EOL.
- 'N:Test2;;;;'.PHP_EOL.
- 'END:VCARD';
-
- private $vcardTest2 = 'BEGIN:VCARD'.PHP_EOL.
- 'VERSION:3.0'.PHP_EOL.
- 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN'.PHP_EOL.
- 'UID:Test3'.PHP_EOL.
- 'FN:Test3'.PHP_EOL.
- 'N:Test3;;;;'.PHP_EOL.
- 'END:VCARD';
-
- private $vcardTestNoUID = 'BEGIN:VCARD'.PHP_EOL.
- 'VERSION:3.0'.PHP_EOL.
- 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN'.PHP_EOL.
- 'FN:TestNoUID'.PHP_EOL.
- 'N:TestNoUID;;;;'.PHP_EOL.
- 'END:VCARD';
+ private $vcardTest0 = 'BEGIN:VCARD' . PHP_EOL
+ . 'VERSION:3.0' . PHP_EOL
+ . 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL
+ . 'UID:Test' . PHP_EOL
+ . 'FN:Test' . PHP_EOL
+ . 'N:Test;;;;' . PHP_EOL
+ . 'END:VCARD';
+
+ private $vcardTest1 = 'BEGIN:VCARD' . PHP_EOL
+ . 'VERSION:3.0' . PHP_EOL
+ . 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL
+ . 'UID:Test2' . PHP_EOL
+ . 'FN:Test2' . PHP_EOL
+ . 'N:Test2;;;;' . PHP_EOL
+ . 'END:VCARD';
+
+ private $vcardTest2 = 'BEGIN:VCARD' . PHP_EOL
+ . 'VERSION:3.0' . PHP_EOL
+ . 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL
+ . 'UID:Test3' . PHP_EOL
+ . 'FN:Test3' . PHP_EOL
+ . 'N:Test3;;;;' . PHP_EOL
+ . 'END:VCARD';
+
+ private $vcardTestNoUID = 'BEGIN:VCARD' . PHP_EOL
+ . 'VERSION:3.0' . PHP_EOL
+ . 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL
+ . 'FN:TestNoUID' . PHP_EOL
+ . 'N:TestNoUID;;;;' . PHP_EOL
+ . 'END:VCARD';
protected function setUp(): void {
parent::setUp();
$this->userManager = $this->createMock(IUserManager::class);
$this->groupManager = $this->createMock(IGroupManager::class);
+ $this->config = $this->createMock(IConfig::class);
$this->principal = $this->getMockBuilder(Principal::class)
->setConstructorArgs([
$this->userManager,
@@ -118,10 +108,10 @@ class CardDavBackendTest extends TestCase {
$this->createMock(IAppManager::class),
$this->createMock(ProxyMapper::class),
$this->createMock(KnownUserService::class),
- $this->createMock(IConfig::class),
+ $this->config,
$this->createMock(IFactory::class)
])
- ->setMethods(['getPrincipalByPath', 'getGroupMembership', 'findByUri'])
+ ->onlyMethods(['getPrincipalByPath', 'getGroupMembership', 'findByUri'])
->getMock();
$this->principal->method('getPrincipalByPath')
->willReturn([
@@ -133,7 +123,7 @@ class CardDavBackendTest extends TestCase {
->willReturn([self::UNIT_TEST_GROUP]);
$this->dispatcher = $this->createMock(IEventDispatcher::class);
- $this->db = \OC::$server->getDatabaseConnection();
+ $this->db = Server::get(IDBConnection::class);
$this->sharingBackend = new Backend($this->userManager,
$this->groupManager,
$this->principal,
@@ -147,19 +137,24 @@ class CardDavBackendTest extends TestCase {
$this->userManager,
$this->dispatcher,
$this->sharingBackend,
+ $this->config,
);
// start every test with a empty cards_properties and cards table
$query = $this->db->getQueryBuilder();
- $query->delete('cards_properties')->execute();
+ $query->delete('cards_properties')->executeStatement();
$query = $this->db->getQueryBuilder();
- $query->delete('cards')->execute();
+ $query->delete('cards')->executeStatement();
- $this->tearDown();
+ $this->principal->method('getGroupMembership')
+ ->withAnyParameters()
+ ->willReturn([self::UNIT_TEST_GROUP]);
+ $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER);
+ foreach ($books as $book) {
+ $this->backend->deleteAddressBook($book['id']);
+ }
}
protected function tearDown(): void {
- parent::tearDown();
-
if (is_null($this->backend)) {
return;
}
@@ -171,6 +166,8 @@ class CardDavBackendTest extends TestCase {
foreach ($books as $book) {
$this->backend->deleteAddressBook($book['id']);
}
+
+ parent::tearDown();
}
public function testAddressBookOperations(): void {
@@ -235,10 +232,11 @@ class CardDavBackendTest extends TestCase {
}
public function testCardOperations(): void {
- /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject $backend */
+ /** @var CardDavBackend&MockObject $backend */
$backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
- ->onlyMethods(['updateProperties', 'purgeProperties'])->getMock();
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend,$this->config])
+ ->onlyMethods(['updateProperties', 'purgeProperties'])
+ ->getMock();
// create a new address book
$backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -248,12 +246,16 @@ class CardDavBackendTest extends TestCase {
$uri = $this->getUniqueID('card');
// updateProperties is expected twice, once for createCard and once for updateCard
- $backend->expects($this->exactly(2))
+ $calls = [
+ [$bookId, $uri, $this->vcardTest0],
+ [$bookId, $uri, $this->vcardTest1],
+ ];
+ $backend->expects($this->exactly(count($calls)))
->method('updateProperties')
- ->withConsecutive(
- [$bookId, $uri, $this->vcardTest0],
- [$bookId, $uri, $this->vcardTest1],
- );
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
// Expect event
$this->dispatcher
@@ -292,8 +294,9 @@ class CardDavBackendTest extends TestCase {
public function testMultiCard(): void {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
- ->setMethods(['updateProperties'])->getMock();
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend,$this->config])
+ ->onlyMethods(['updateProperties'])
+ ->getMock();
// create a new address book
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -332,7 +335,7 @@ class CardDavBackendTest extends TestCase {
$this->assertArrayHasKey('lastmodified', $card);
$this->assertArrayHasKey('etag', $card);
$this->assertArrayHasKey('size', $card);
- $this->assertEquals($this->{ 'vcardTest'.($index + 1) }, $card['carddata']);
+ $this->assertEquals($this->{ 'vcardTest' . ($index + 1) }, $card['carddata']);
}
// delete the card
@@ -345,8 +348,9 @@ class CardDavBackendTest extends TestCase {
public function testMultipleUIDOnDifferentAddressbooks(): void {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
- ->onlyMethods(['updateProperties'])->getMock();
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend,$this->config])
+ ->onlyMethods(['updateProperties'])
+ ->getMock();
// create 2 new address books
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -367,8 +371,9 @@ class CardDavBackendTest extends TestCase {
public function testMultipleUIDDenied(): void {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
- ->setMethods(['updateProperties'])->getMock();
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend, $this->config])
+ ->onlyMethods(['updateProperties'])
+ ->getMock();
// create a new address book
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -388,8 +393,9 @@ class CardDavBackendTest extends TestCase {
public function testNoValidUID(): void {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
- ->setMethods(['updateProperties'])->getMock();
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend, $this->config])
+ ->onlyMethods(['updateProperties'])
+ ->getMock();
// create a new address book
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -405,7 +411,7 @@ class CardDavBackendTest extends TestCase {
public function testDeleteWithoutCard(): void {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend, $this->config])
->onlyMethods([
'getCardId',
'addChange',
@@ -427,12 +433,17 @@ class CardDavBackendTest extends TestCase {
->method('getCardId')
->with($bookId, $uri)
->willThrowException(new \InvalidArgumentException());
- $this->backend->expects($this->exactly(2))
+
+ $calls = [
+ [$bookId, $uri, 1],
+ [$bookId, $uri, 3],
+ ];
+ $this->backend->expects($this->exactly(count($calls)))
->method('addChange')
- ->withConsecutive(
- [$bookId, $uri, 1],
- [$bookId, $uri, 3]
- );
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$this->backend->expects($this->never())
->method('purgeProperties');
@@ -445,8 +456,9 @@ class CardDavBackendTest extends TestCase {
public function testSyncSupport(): void {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
- ->setMethods(['updateProperties'])->getMock();
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend, $this->config])
+ ->onlyMethods(['updateProperties'])
+ ->getMock();
// create a new address book
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -513,7 +525,7 @@ class CardDavBackendTest extends TestCase {
$cardId = 2;
$backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend, $this->config])
->onlyMethods(['getCardId'])->getMock();
$backend->expects($this->any())->method('getCardId')->willReturn($cardId);
@@ -526,7 +538,8 @@ class CardDavBackendTest extends TestCase {
$query = $this->db->getQueryBuilder();
$query->select('*')
- ->from('cards_properties');
+ ->from('cards_properties')
+ ->orderBy('name');
$qResult = $query->execute();
$result = $qResult->fetchAll();
@@ -534,13 +547,13 @@ class CardDavBackendTest extends TestCase {
$this->assertSame(2, count($result));
- $this->assertSame('UID', $result[0]['name']);
- $this->assertSame($cardUri, $result[0]['value']);
+ $this->assertSame('FN', $result[0]['name']);
+ $this->assertSame('John Doe', $result[0]['value']);
$this->assertSame($bookId, (int)$result[0]['addressbookid']);
$this->assertSame($cardId, (int)$result[0]['cardid']);
- $this->assertSame('FN', $result[1]['name']);
- $this->assertSame('John Doe', $result[1]['value']);
+ $this->assertSame('UID', $result[1]['name']);
+ $this->assertSame($cardUri, $result[1]['value']);
$this->assertSame($bookId, (int)$result[1]['addressbookid']);
$this->assertSame($cardId, (int)$result[1]['cardid']);
@@ -635,15 +648,8 @@ class CardDavBackendTest extends TestCase {
$this->invokePrivate($this->backend, 'getCardId', [1, 'uri']);
}
- /**
- * @dataProvider dataTestSearch
- *
- * @param string $pattern
- * @param array $properties
- * @param array $options
- * @param array $expected
- */
- public function testSearch($pattern, $properties, $options, $expected): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestSearch')]
+ public function testSearch(string $pattern, array $properties, array $options, array $expected): void {
/** @var VCard $vCards */
$vCards = [];
$vCards[0] = new VCard();
@@ -662,20 +668,21 @@ class CardDavBackendTest extends TestCase {
$query = $this->db->getQueryBuilder();
for ($i = 0; $i < 3; $i++) {
$query->insert($this->dbCardsTable)
- ->values(
- [
- 'addressbookid' => $query->createNamedParameter(0),
- 'carddata' => $query->createNamedParameter($vCards[$i]->serialize(), IQueryBuilder::PARAM_LOB),
- 'uri' => $query->createNamedParameter('uri' . $i),
- 'lastmodified' => $query->createNamedParameter(time()),
- 'etag' => $query->createNamedParameter('etag' . $i),
- 'size' => $query->createNamedParameter(120),
- ]
- );
+ ->values(
+ [
+ 'addressbookid' => $query->createNamedParameter(0),
+ 'carddata' => $query->createNamedParameter($vCards[$i]->serialize(), IQueryBuilder::PARAM_LOB),
+ 'uri' => $query->createNamedParameter('uri' . $i),
+ 'lastmodified' => $query->createNamedParameter(time()),
+ 'etag' => $query->createNamedParameter('etag' . $i),
+ 'size' => $query->createNamedParameter(120),
+ ]
+ );
$query->execute();
$vCardIds[] = $query->getLastInsertId();
}
+ $query = $this->db->getQueryBuilder();
$query->insert($this->dbCardsPropertiesTable)
->values(
[
@@ -687,6 +694,7 @@ class CardDavBackendTest extends TestCase {
]
);
$query->execute();
+ $query = $this->db->getQueryBuilder();
$query->insert($this->dbCardsPropertiesTable)
->values(
[
@@ -698,6 +706,7 @@ class CardDavBackendTest extends TestCase {
]
);
$query->execute();
+ $query = $this->db->getQueryBuilder();
$query->insert($this->dbCardsPropertiesTable)
->values(
[
@@ -709,6 +718,7 @@ class CardDavBackendTest extends TestCase {
]
);
$query->execute();
+ $query = $this->db->getQueryBuilder();
$query->insert($this->dbCardsPropertiesTable)
->values(
[
@@ -720,6 +730,7 @@ class CardDavBackendTest extends TestCase {
]
);
$query->execute();
+ $query = $this->db->getQueryBuilder();
$query->insert($this->dbCardsPropertiesTable)
->values(
[
@@ -749,7 +760,7 @@ class CardDavBackendTest extends TestCase {
$this->assertSame(count($expected), count($found));
}
- public function dataTestSearch() {
+ public static function dataTestSearch(): array {
return [
['John', ['FN'], [], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]],
['M. Doe', ['FN'], [], [['uri1', 'John M. Doe']]],
@@ -766,16 +777,16 @@ class CardDavBackendTest extends TestCase {
public function testGetCardUri(): void {
$query = $this->db->getQueryBuilder();
$query->insert($this->dbCardsTable)
- ->values(
- [
- 'addressbookid' => $query->createNamedParameter(1),
- 'carddata' => $query->createNamedParameter('carddata', IQueryBuilder::PARAM_LOB),
- 'uri' => $query->createNamedParameter('uri'),
- 'lastmodified' => $query->createNamedParameter(5489543),
- 'etag' => $query->createNamedParameter('etag'),
- 'size' => $query->createNamedParameter(120),
- ]
- );
+ ->values(
+ [
+ 'addressbookid' => $query->createNamedParameter(1),
+ 'carddata' => $query->createNamedParameter('carddata', IQueryBuilder::PARAM_LOB),
+ 'uri' => $query->createNamedParameter('uri'),
+ 'lastmodified' => $query->createNamedParameter(5489543),
+ 'etag' => $query->createNamedParameter('etag'),
+ 'size' => $query->createNamedParameter(120),
+ ]
+ );
$query->execute();
$id = $query->getLastInsertId();
@@ -794,16 +805,16 @@ class CardDavBackendTest extends TestCase {
$query = $this->db->getQueryBuilder();
for ($i = 0; $i < 2; $i++) {
$query->insert($this->dbCardsTable)
- ->values(
- [
- 'addressbookid' => $query->createNamedParameter($i),
- 'carddata' => $query->createNamedParameter('carddata' . $i, IQueryBuilder::PARAM_LOB),
- 'uri' => $query->createNamedParameter('uri' . $i),
- 'lastmodified' => $query->createNamedParameter(5489543),
- 'etag' => $query->createNamedParameter('etag' . $i),
- 'size' => $query->createNamedParameter(120),
- ]
- );
+ ->values(
+ [
+ 'addressbookid' => $query->createNamedParameter($i),
+ 'carddata' => $query->createNamedParameter('carddata' . $i, IQueryBuilder::PARAM_LOB),
+ 'uri' => $query->createNamedParameter('uri' . $i),
+ 'lastmodified' => $query->createNamedParameter(5489543),
+ 'etag' => $query->createNamedParameter('etag' . $i),
+ 'size' => $query->createNamedParameter(120),
+ ]
+ );
$query->execute();
}
@@ -837,7 +848,7 @@ class CardDavBackendTest extends TestCase {
'preferred' => $query->createNamedParameter(0)
]
)
- ->execute();
+ ->execute();
$result = $this->backend->collectCardProperties(666, 'FN');
$this->assertEquals(['John Doe'], $result);
diff --git a/apps/dav/tests/unit/CardDAV/ContactsManagerTest.php b/apps/dav/tests/unit/CardDAV/ContactsManagerTest.php
index 6b1abb2718d..bdd826f671b 100644
--- a/apps/dav/tests/unit/CardDAV/ContactsManagerTest.php
+++ b/apps/dav/tests/unit/CardDAV/ContactsManagerTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -9,25 +10,28 @@ namespace OCA\DAV\Tests\unit\CardDAV;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\CardDAV\ContactsManager;
+use OCA\DAV\Db\PropertyMapper;
use OCP\Contacts\IManager;
use OCP\IL10N;
use OCP\IURLGenerator;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ContactsManagerTest extends TestCase {
public function test(): void {
- /** @var IManager | \PHPUnit\Framework\MockObject\MockObject $cm */
- $cm = $this->getMockBuilder(IManager::class)->disableOriginalConstructor()->getMock();
+ /** @var IManager&MockObject $cm */
+ $cm = $this->createMock(IManager::class);
$cm->expects($this->exactly(2))->method('registerAddressBook');
- $urlGenerator = $this->getMockBuilder(IURLGenerator::class)->disableOriginalConstructor()->getMock();
- /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject $backEnd */
- $backEnd = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ $urlGenerator = $this->createMock(IURLGenerator::class);
+ /** @var CardDavBackend&MockObject $backEnd */
+ $backEnd = $this->createMock(CardDavBackend::class);
$backEnd->method('getAddressBooksForUser')->willReturn([
['{DAV:}displayname' => 'Test address book', 'uri' => 'default'],
]);
+ $propertyMapper = $this->createMock(PropertyMapper::class);
$l = $this->createMock(IL10N::class);
- $app = new ContactsManager($backEnd, $l);
+ $app = new ContactsManager($backEnd, $l, $propertyMapper);
$app->setupContactsProvider($cm, 'user01', $urlGenerator);
}
}
diff --git a/apps/dav/tests/unit/CardDAV/ConverterTest.php b/apps/dav/tests/unit/CardDAV/ConverterTest.php
index df6489d5053..00519b82766 100644
--- a/apps/dav/tests/unit/CardDAV/ConverterTest.php
+++ b/apps/dav/tests/unit/CardDAV/ConverterTest.php
@@ -22,17 +22,10 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class ConverterTest extends TestCase {
-
- /** @var IAccountManager|\PHPUnit\Framework\MockObject\MockObject */
- private $accountManager;
- /** @var IUserManager|(IUserManager&MockObject)|MockObject */
- private IUserManager|MockObject $userManager;
-
- /** @var IURLGenerator */
- private $urlGenerator;
-
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $logger;
+ private IAccountManager&MockObject $accountManager;
+ private IUserManager&MockObject $userManager;
+ private IURLGenerator&MockObject $urlGenerator;
+ private LoggerInterface&MockObject $logger;
protected function setUp(): void {
parent::setUp();
@@ -44,7 +37,7 @@ class ConverterTest extends TestCase {
}
/**
- * @return IAccountProperty|MockObject
+ * @return IAccountProperty&MockObject
*/
protected function getAccountPropertyMock(string $name, ?string $value, string $scope) {
$property = $this->createMock(IAccountProperty::class);
@@ -77,17 +70,16 @@ class ConverterTest extends TestCase {
yield $this->getAccountPropertyMock(IAccountManager::PROPERTY_TWITTER, '', IAccountManager::SCOPE_LOCAL);
});
- $accountManager = $this->getMockBuilder(IAccountManager::class)
- ->disableOriginalConstructor()->getMock();
+ $accountManager = $this->createMock(IAccountManager::class);
- $accountManager->expects($this->any())->method('getAccount')->willReturn($account);
+ $accountManager->expects($this->any())
+ ->method('getAccount')
+ ->willReturn($account);
return $accountManager;
}
- /**
- * @dataProvider providesNewUsers
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesNewUsers')]
public function testCreation($expectedVCard, $displayName = null, $eMailAddress = null, $cloudId = null): void {
$user = $this->getUserMock((string)$displayName, $eMailAddress, $cloudId);
$accountManager = $this->getAccountManager($user);
@@ -104,7 +96,7 @@ class ConverterTest extends TestCase {
}
public function testManagerProp(): void {
- $user = $this->getUserMock("user", "user@domain.tld", "user@cloud.domain.tld");
+ $user = $this->getUserMock('user', 'user@domain.tld', 'user@cloud.domain.tld');
$user->method('getManagerUids')
->willReturn(['mgr']);
$this->userManager->expects(self::once())
@@ -126,7 +118,7 @@ class ConverterTest extends TestCase {
);
}
- protected function compareData($expected, $data) {
+ protected function compareData(array $expected, array $data): void {
foreach ($expected as $key => $value) {
$found = false;
foreach ($data[1] as $d) {
@@ -141,7 +133,7 @@ class ConverterTest extends TestCase {
}
}
- public function providesNewUsers() {
+ public static function providesNewUsers(): array {
return [
[
null
@@ -168,8 +160,8 @@ class ConverterTest extends TestCase {
'fn' => 'Dr. Foo Bar',
'photo' => 'MTIzNDU2Nzg5',
],
- "Dr. Foo Bar",
- "foo@bar.net",
+ 'Dr. Foo Bar',
+ 'foo@bar.net',
'foo@cloud.net'
],
[
@@ -178,9 +170,9 @@ class ConverterTest extends TestCase {
'fn' => 'Dr. Foo Bar',
'photo' => 'MTIzNDU2Nzg5',
],
- "Dr. Foo Bar",
+ 'Dr. Foo Bar',
null,
- "foo@cloud.net"
+ 'foo@cloud.net'
],
[
[
@@ -195,19 +187,15 @@ class ConverterTest extends TestCase {
];
}
- /**
- * @dataProvider providesNames
- * @param $expected
- * @param $fullName
- */
- public function testNameSplitter($expected, $fullName): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesNames')]
+ public function testNameSplitter(string $expected, string $fullName): void {
$converter = new Converter($this->accountManager, $this->userManager, $this->urlGenerator, $this->logger);
$r = $converter->splitFullName($fullName);
$r = implode(';', $r);
$this->assertEquals($expected, $r);
}
- public function providesNames() {
+ public static function providesNames(): array {
return [
['Sauron;;;;', 'Sauron'],
['Baggins;Bilbo;;;', 'Bilbo Baggins'],
@@ -216,16 +204,13 @@ class ConverterTest extends TestCase {
}
/**
- * @param $displayName
- * @param $eMailAddress
- * @param $cloudId
- * @return IUser | \PHPUnit\Framework\MockObject\MockObject
+ * @return IUser&MockObject
*/
protected function getUserMock(string $displayName, ?string $eMailAddress, ?string $cloudId) {
- $image0 = $this->getMockBuilder(IImage::class)->disableOriginalConstructor()->getMock();
+ $image0 = $this->createMock(IImage::class);
$image0->method('mimeType')->willReturn('image/jpeg');
$image0->method('data')->willReturn('123456789');
- $user = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock();
+ $user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('12345');
$user->method('getDisplayName')->willReturn($displayName);
$user->method('getEMailAddress')->willReturn($eMailAddress);
diff --git a/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php b/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php
index 6718153f910..d47f53bddcd 100644
--- a/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php
+++ b/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -10,8 +11,10 @@ namespace OCA\DAV\Tests\unit\CardDAV;
use OCA\DAV\CardDAV\AddressBook;
use OCA\DAV\CardDAV\ImageExportPlugin;
use OCA\DAV\CardDAV\PhotoCache;
+use OCP\AppFramework\Http;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\CardDAV\Card;
use Sabre\DAV\Node;
use Sabre\DAV\Server;
@@ -21,18 +24,12 @@ use Sabre\HTTP\ResponseInterface;
use Test\TestCase;
class ImageExportPluginTest extends TestCase {
- /** @var ResponseInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $response;
- /** @var RequestInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
- /** @var ImageExportPlugin|\PHPUnit\Framework\MockObject\MockObject */
- private $plugin;
- /** @var Server */
- private $server;
- /** @var Tree|\PHPUnit\Framework\MockObject\MockObject */
- private $tree;
- /** @var PhotoCache|\PHPUnit\Framework\MockObject\MockObject */
- private $cache;
+ private ResponseInterface&MockObject $response;
+ private RequestInterface&MockObject $request;
+ private Server&MockObject $server;
+ private Tree&MockObject $tree;
+ private PhotoCache&MockObject $cache;
+ private ImageExportPlugin $plugin;
protected function setUp(): void {
parent::setUp();
@@ -44,24 +41,18 @@ class ImageExportPluginTest extends TestCase {
$this->server->tree = $this->tree;
$this->cache = $this->createMock(PhotoCache::class);
- $this->plugin = $this->getMockBuilder(ImageExportPlugin::class)
- ->setMethods(['getPhoto'])
- ->setConstructorArgs([$this->cache])
- ->getMock();
+ $this->plugin = new ImageExportPlugin($this->cache);
$this->plugin->initialize($this->server);
}
- /**
- * @dataProvider providesQueryParams
- * @param $param
- */
- public function testQueryParams($param): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesQueryParams')]
+ public function testQueryParams(array $param): void {
$this->request->expects($this->once())->method('getQueryParameters')->willReturn($param);
$result = $this->plugin->httpGet($this->request, $this->response);
$this->assertTrue($result);
}
- public function providesQueryParams() {
+ public static function providesQueryParams(): array {
return [
[[]],
[['1']],
@@ -86,7 +77,7 @@ class ImageExportPluginTest extends TestCase {
$this->assertTrue($result);
}
- public function dataTestCard() {
+ public static function dataTestCard(): array {
return [
[null, false],
[null, true],
@@ -95,13 +86,8 @@ class ImageExportPluginTest extends TestCase {
];
}
- /**
- * @dataProvider dataTestCard
- *
- * @param $size
- * @param bool $photo
- */
- public function testCard($size, $photo): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestCard')]
+ public function testCard(?int $size, bool $photo): void {
$query = ['photo' => null];
if ($size !== null) {
$query['size'] = $size;
@@ -144,14 +130,18 @@ class ImageExportPluginTest extends TestCase {
->with(1, 'card', $size, $card)
->willReturn($file);
- $this->response->expects($this->exactly(4))
+ $setHeaderCalls = [
+ ['Cache-Control', 'private, max-age=3600, must-revalidate'],
+ ['Etag', '"myEtag"'],
+ ['Content-Type', 'image/jpeg'],
+ ['Content-Disposition', 'attachment; filename=card.jpg'],
+ ];
+ $this->response->expects($this->exactly(count($setHeaderCalls)))
->method('setHeader')
- ->withConsecutive(
- ['Cache-Control', 'private, max-age=3600, must-revalidate'],
- ['Etag', '"myEtag"'],
- ['Content-Type', 'image/jpeg'],
- ['Content-Disposition', 'attachment; filename=card.jpg'],
- );
+ ->willReturnCallback(function () use (&$setHeaderCalls): void {
+ $expected = array_shift($setHeaderCalls);
+ $this->assertEquals($expected, func_get_args());
+ });
$this->response->expects($this->once())
->method('setStatus')
@@ -160,18 +150,22 @@ class ImageExportPluginTest extends TestCase {
->method('setBody')
->with('imgdata');
} else {
- $this->response->expects($this->exactly(2))
+ $setHeaderCalls = [
+ ['Cache-Control', 'private, max-age=3600, must-revalidate'],
+ ['Etag', '"myEtag"'],
+ ];
+ $this->response->expects($this->exactly(count($setHeaderCalls)))
->method('setHeader')
- ->withConsecutive(
- ['Cache-Control', 'private, max-age=3600, must-revalidate'],
- ['Etag', '"myEtag"'],
- );
+ ->willReturnCallback(function () use (&$setHeaderCalls): void {
+ $expected = array_shift($setHeaderCalls);
+ $this->assertEquals($expected, func_get_args());
+ });
$this->cache->method('get')
->with(1, 'card', $size, $card)
->willThrowException(new NotFoundException());
$this->response->expects($this->once())
->method('setStatus')
- ->with(404);
+ ->with(Http::STATUS_NO_CONTENT);
}
$result = $this->plugin->httpGet($this->request, $this->response);
diff --git a/apps/dav/tests/unit/CardDAV/Security/CardDavRateLimitingPluginTest.php b/apps/dav/tests/unit/CardDAV/Security/CardDavRateLimitingPluginTest.php
index 33ab83a74ac..ee599d5a76c 100644
--- a/apps/dav/tests/unit/CardDAV/Security/CardDavRateLimitingPluginTest.php
+++ b/apps/dav/tests/unit/CardDAV/Security/CardDavRateLimitingPluginTest.php
@@ -24,11 +24,11 @@ use Test\TestCase;
class CardDavRateLimitingPluginTest extends TestCase {
- private Limiter|MockObject $limiter;
- private CardDavBackend|MockObject $cardDavBackend;
- private IUserManager|MockObject $userManager;
- private LoggerInterface|MockObject $logger;
- private IAppConfig|MockObject $config;
+ private Limiter&MockObject $limiter;
+ private CardDavBackend&MockObject $cardDavBackend;
+ private IUserManager&MockObject $userManager;
+ private LoggerInterface&MockObject $logger;
+ private IAppConfig&MockObject $config;
private string $userId = 'user123';
private CardDavRateLimitingPlugin $plugin;
diff --git a/apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php b/apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php
index f35eb9f0040..1e934a69a53 100644
--- a/apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php
+++ b/apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -12,6 +13,7 @@ use OCA\DAV\DAV\Sharing\IShareable;
use OCA\DAV\DAV\Sharing\Plugin;
use OCP\IConfig;
use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Server;
use Sabre\DAV\SimpleCollection;
use Sabre\HTTP\Request;
@@ -19,31 +21,25 @@ use Sabre\HTTP\Response;
use Test\TestCase;
class PluginTest extends TestCase {
-
- /** @var Plugin */
- private $plugin;
- /** @var Server */
- private $server;
- /** @var IShareable | \PHPUnit\Framework\MockObject\MockObject */
- private $book;
+ private Plugin $plugin;
+ private Server $server;
+ private IShareable&MockObject $book;
protected function setUp(): void {
parent::setUp();
- /** @var Auth | \PHPUnit\Framework\MockObject\MockObject $authBackend */
- $authBackend = $this->getMockBuilder(Auth::class)->disableOriginalConstructor()->getMock();
- $authBackend->method('isDavAuthenticated')->willReturn(true);
-
- /** @var IRequest $request */
- $request = $this->getMockBuilder(IRequest::class)->disableOriginalConstructor()->getMock();
+ $authBackend = $this->createMock(Auth::class);
+ $authBackend->method('isDavAuthenticated')
+ ->willReturn(true);
+ $request = $this->createMock(IRequest::class);
$config = $this->createMock(IConfig::class);
$this->plugin = new Plugin($authBackend, $request, $config);
$root = new SimpleCollection('root');
$this->server = new \Sabre\DAV\Server($root);
- /** @var SimpleCollection $node */
- $this->book = $this->getMockBuilder(IShareable::class)->disableOriginalConstructor()->getMock();
- $this->book->method('getName')->willReturn('addressbook1.vcf');
+ $this->book = $this->createMock(IShareable::class);
+ $this->book->method('getName')
+ ->willReturn('addressbook1.vcf');
$root->addChild($this->book);
$this->plugin->initialize($this->server);
}
diff --git a/apps/dav/tests/unit/CardDAV/SyncServiceTest.php b/apps/dav/tests/unit/CardDAV/SyncServiceTest.php
index a09d5de6a44..77caed336f4 100644
--- a/apps/dav/tests/unit/CardDAV/SyncServiceTest.php
+++ b/apps/dav/tests/unit/CardDAV/SyncServiceTest.php
@@ -7,54 +7,298 @@
*/
namespace OCA\DAV\Tests\unit\CardDAV;
+use GuzzleHttp\Exception\ClientException;
+use GuzzleHttp\Psr7\Request as PsrRequest;
+use GuzzleHttp\Psr7\Response as PsrResponse;
+use OC\Http\Client\Response;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\CardDAV\Converter;
use OCA\DAV\CardDAV\SyncService;
+use OCP\Http\Client\IClient;
+use OCP\Http\Client\IClientService;
+use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IUser;
use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Http\Client\ClientExceptionInterface;
use Psr\Log\LoggerInterface;
+use Psr\Log\NullLogger;
use Sabre\VObject\Component\VCard;
use Test\TestCase;
class SyncServiceTest extends TestCase {
+
+ protected CardDavBackend&MockObject $backend;
+ protected IUserManager&MockObject $userManager;
+ protected IDBConnection&MockObject $dbConnection;
+ protected LoggerInterface $logger;
+ protected Converter&MockObject $converter;
+ protected IClient&MockObject $client;
+ protected IConfig&MockObject $config;
+ protected SyncService $service;
+
+ public function setUp(): void {
+ parent::setUp();
+
+ $addressBook = [
+ 'id' => 1,
+ 'uri' => 'system',
+ 'principaluri' => 'principals/system/system',
+ '{DAV:}displayname' => 'system',
+ // watch out, incomplete address book mock.
+ ];
+
+ $this->backend = $this->createMock(CardDavBackend::class);
+ $this->backend->method('getAddressBooksByUri')
+ ->with('principals/system/system', 1)
+ ->willReturn($addressBook);
+
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->dbConnection = $this->createMock(IDBConnection::class);
+ $this->logger = new NullLogger();
+ $this->converter = $this->createMock(Converter::class);
+ $this->client = $this->createMock(IClient::class);
+ $this->config = $this->createMock(IConfig::class);
+
+ $clientService = $this->createMock(IClientService::class);
+ $clientService->method('newClient')
+ ->willReturn($this->client);
+
+ $this->service = new SyncService(
+ $this->backend,
+ $this->userManager,
+ $this->dbConnection,
+ $this->logger,
+ $this->converter,
+ $clientService,
+ $this->config
+ );
+ }
+
public function testEmptySync(): void {
- $backend = $this->getBackendMock(0, 0, 0);
+ $this->backend->expects($this->exactly(0))
+ ->method('createCard');
+ $this->backend->expects($this->exactly(0))
+ ->method('updateCard');
+ $this->backend->expects($this->exactly(0))
+ ->method('deleteCard');
+
+ $body = '<?xml version="1.0"?>
+<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:card="urn:ietf:params:xml:ns:carddav" xmlns:oc="http://owncloud.org/ns">
+ <d:sync-token>http://sabre.io/ns/sync/1</d:sync-token>
+</d:multistatus>';
+
+ $requestResponse = new Response(new PsrResponse(
+ 207,
+ ['Content-Type' => 'application/xml; charset=utf-8', 'Content-Length' => strlen($body)],
+ $body
+ ));
- $ss = $this->getSyncServiceMock($backend, []);
- $return = $ss->syncRemoteAddressBook('', 'system', 'system', '1234567890', null, '1', 'principals/system/system', []);
- $this->assertEquals('sync-token-1', $return);
+ $this->client
+ ->method('request')
+ ->willReturn($requestResponse);
+
+ $token = $this->service->syncRemoteAddressBook(
+ '',
+ 'system',
+ 'system',
+ '1234567890',
+ null,
+ '1',
+ 'principals/system/system',
+ []
+ )[0];
+
+ $this->assertEquals('http://sabre.io/ns/sync/1', $token);
}
public function testSyncWithNewElement(): void {
- $backend = $this->getBackendMock(1, 0, 0);
- $backend->method('getCard')->willReturn(false);
+ $this->backend->expects($this->exactly(1))
+ ->method('createCard');
+ $this->backend->expects($this->exactly(0))
+ ->method('updateCard');
+ $this->backend->expects($this->exactly(0))
+ ->method('deleteCard');
+
+ $this->backend->method('getCard')
+ ->willReturn(false);
- $ss = $this->getSyncServiceMock($backend, ['0' => [200 => '']]);
- $return = $ss->syncRemoteAddressBook('', 'system', 'system', '1234567890', null, '1', 'principals/system/system', []);
- $this->assertEquals('sync-token-1', $return);
+
+ $body = '<?xml version="1.0"?>
+<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:card="urn:ietf:params:xml:ns:carddav" xmlns:oc="http://owncloud.org/ns">
+ <d:response>
+ <d:href>/remote.php/dav/addressbooks/system/system/system/Database:alice.vcf</d:href>
+ <d:propstat>
+ <d:prop>
+ <d:getcontenttype>text/vcard; charset=utf-8</d:getcontenttype>
+ <d:getetag>&quot;2df155fa5c2a24cd7f750353fc63f037&quot;</d:getetag>
+ </d:prop>
+ <d:status>HTTP/1.1 200 OK</d:status>
+ </d:propstat>
+ </d:response>
+ <d:sync-token>http://sabre.io/ns/sync/2</d:sync-token>
+</d:multistatus>';
+
+ $reportResponse = new Response(new PsrResponse(
+ 207,
+ ['Content-Type' => 'application/xml; charset=utf-8', 'Content-Length' => strlen($body)],
+ $body
+ ));
+
+ $this->client
+ ->method('request')
+ ->willReturn($reportResponse);
+
+ $vCard = 'BEGIN:VCARD
+VERSION:3.0
+PRODID:-//Sabre//Sabre VObject 4.5.4//EN
+UID:alice
+FN;X-NC-SCOPE=v2-federated:alice
+N;X-NC-SCOPE=v2-federated:alice;;;;
+X-SOCIALPROFILE;TYPE=NEXTCLOUD;X-NC-SCOPE=v2-published:https://server2.internal/index.php/u/alice
+CLOUD:alice@server2.internal
+END:VCARD';
+
+ $getResponse = new Response(new PsrResponse(
+ 200,
+ ['Content-Type' => 'text/vcard; charset=utf-8', 'Content-Length' => strlen($vCard)],
+ $vCard,
+ ));
+
+ $this->client
+ ->method('get')
+ ->willReturn($getResponse);
+
+ $token = $this->service->syncRemoteAddressBook(
+ '',
+ 'system',
+ 'system',
+ '1234567890',
+ null,
+ '1',
+ 'principals/system/system',
+ []
+ )[0];
+
+ $this->assertEquals('http://sabre.io/ns/sync/2', $token);
}
public function testSyncWithUpdatedElement(): void {
- $backend = $this->getBackendMock(0, 1, 0);
- $backend->method('getCard')->willReturn(true);
+ $this->backend->expects($this->exactly(0))
+ ->method('createCard');
+ $this->backend->expects($this->exactly(1))
+ ->method('updateCard');
+ $this->backend->expects($this->exactly(0))
+ ->method('deleteCard');
+
+ $this->backend->method('getCard')
+ ->willReturn(true);
+
+
+ $body = '<?xml version="1.0"?>
+<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:card="urn:ietf:params:xml:ns:carddav" xmlns:oc="http://owncloud.org/ns">
+ <d:response>
+ <d:href>/remote.php/dav/addressbooks/system/system/system/Database:alice.vcf</d:href>
+ <d:propstat>
+ <d:prop>
+ <d:getcontenttype>text/vcard; charset=utf-8</d:getcontenttype>
+ <d:getetag>&quot;2df155fa5c2a24cd7f750353fc63f037&quot;</d:getetag>
+ </d:prop>
+ <d:status>HTTP/1.1 200 OK</d:status>
+ </d:propstat>
+ </d:response>
+ <d:sync-token>http://sabre.io/ns/sync/3</d:sync-token>
+</d:multistatus>';
+
+ $reportResponse = new Response(new PsrResponse(
+ 207,
+ ['Content-Type' => 'application/xml; charset=utf-8', 'Content-Length' => strlen($body)],
+ $body
+ ));
+
+ $this->client
+ ->method('request')
+ ->willReturn($reportResponse);
+
+ $vCard = 'BEGIN:VCARD
+VERSION:3.0
+PRODID:-//Sabre//Sabre VObject 4.5.4//EN
+UID:alice
+FN;X-NC-SCOPE=v2-federated:alice
+N;X-NC-SCOPE=v2-federated:alice;;;;
+X-SOCIALPROFILE;TYPE=NEXTCLOUD;X-NC-SCOPE=v2-published:https://server2.internal/index.php/u/alice
+CLOUD:alice@server2.internal
+END:VCARD';
+
+ $getResponse = new Response(new PsrResponse(
+ 200,
+ ['Content-Type' => 'text/vcard; charset=utf-8', 'Content-Length' => strlen($vCard)],
+ $vCard,
+ ));
- $ss = $this->getSyncServiceMock($backend, ['0' => [200 => '']]);
- $return = $ss->syncRemoteAddressBook('', 'system', 'system', '1234567890', null, '1', 'principals/system/system', []);
- $this->assertEquals('sync-token-1', $return);
+ $this->client
+ ->method('get')
+ ->willReturn($getResponse);
+
+ $token = $this->service->syncRemoteAddressBook(
+ '',
+ 'system',
+ 'system',
+ '1234567890',
+ null,
+ '1',
+ 'principals/system/system',
+ []
+ )[0];
+
+ $this->assertEquals('http://sabre.io/ns/sync/3', $token);
}
public function testSyncWithDeletedElement(): void {
- $backend = $this->getBackendMock(0, 0, 1);
+ $this->backend->expects($this->exactly(0))
+ ->method('createCard');
+ $this->backend->expects($this->exactly(0))
+ ->method('updateCard');
+ $this->backend->expects($this->exactly(1))
+ ->method('deleteCard');
+
+ $body = '<?xml version="1.0"?>
+<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:card="urn:ietf:params:xml:ns:carddav" xmlns:oc="http://owncloud.org/ns">
+<d:response>
+ <d:href>/remote.php/dav/addressbooks/system/system/system/Database:alice.vcf</d:href>
+ <d:status>HTTP/1.1 404 Not Found</d:status>
+</d:response>
+<d:sync-token>http://sabre.io/ns/sync/4</d:sync-token>
+</d:multistatus>';
+
+ $reportResponse = new Response(new PsrResponse(
+ 207,
+ ['Content-Type' => 'application/xml; charset=utf-8', 'Content-Length' => strlen($body)],
+ $body
+ ));
- $ss = $this->getSyncServiceMock($backend, ['0' => [404 => '']]);
- $return = $ss->syncRemoteAddressBook('', 'system', 'system', '1234567890', null, '1', 'principals/system/system', []);
- $this->assertEquals('sync-token-1', $return);
+ $this->client
+ ->method('request')
+ ->willReturn($reportResponse);
+
+ $token = $this->service->syncRemoteAddressBook(
+ '',
+ 'system',
+ 'system',
+ '1234567890',
+ null,
+ '1',
+ 'principals/system/system',
+ []
+ )[0];
+
+ $this->assertEquals('http://sabre.io/ns/sync/4', $token);
}
public function testEnsureSystemAddressBookExists(): void {
- /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject $backend */
- $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ /** @var CardDavBackend&MockObject $backend */
+ $backend = $this->createMock(CardDavBackend::class);
$backend->expects($this->exactly(1))->method('createAddressBook');
$backend->expects($this->exactly(2))
->method('getAddressBooksByUri')
@@ -63,34 +307,27 @@ class SyncServiceTest extends TestCase {
[],
);
- /** @var IUserManager $userManager */
- $userManager = $this->getMockBuilder(IUserManager::class)->disableOriginalConstructor()->getMock();
+ $userManager = $this->createMock(IUserManager::class);
$dbConnection = $this->createMock(IDBConnection::class);
- $logger = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock();
+ $logger = $this->createMock(LoggerInterface::class);
$converter = $this->createMock(Converter::class);
+ $clientService = $this->createMock(IClientService::class);
+ $config = $this->createMock(IConfig::class);
- $ss = new SyncService($backend, $userManager, $dbConnection, $logger, $converter);
+ $ss = new SyncService($backend, $userManager, $dbConnection, $logger, $converter, $clientService, $config);
$ss->ensureSystemAddressBookExists('principals/users/adam', 'contacts', []);
}
- public function dataActivatedUsers() {
+ public static function dataActivatedUsers(): array {
return [
[true, 1, 1, 1],
[false, 0, 0, 3],
];
}
- /**
- * @dataProvider dataActivatedUsers
- *
- * @param boolean $activated
- * @param integer $createCalls
- * @param integer $updateCalls
- * @param integer $deleteCalls
- * @return void
- */
- public function testUpdateAndDeleteUser($activated, $createCalls, $updateCalls, $deleteCalls): void {
- /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject $backend */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataActivatedUsers')]
+ public function testUpdateAndDeleteUser(bool $activated, int $createCalls, int $updateCalls, int $deleteCalls): void {
+ /** @var CardDavBackend | MockObject $backend */
$backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
$logger = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock();
@@ -106,12 +343,9 @@ class SyncServiceTest extends TestCase {
->with('principals/system/system', 'system')
->willReturn(['id' => -1]);
- /** @var IUserManager | \PHPUnit\Framework\MockObject\MockObject $userManager */
- $userManager = $this->getMockBuilder(IUserManager::class)->disableOriginalConstructor()->getMock();
+ $userManager = $this->createMock(IUserManager::class);
$dbConnection = $this->createMock(IDBConnection::class);
-
- /** @var IUser | \PHPUnit\Framework\MockObject\MockObject $user */
- $user = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock();
+ $user = $this->createMock(IUser::class);
$user->method('getBackendClassName')->willReturn('unittest');
$user->method('getUID')->willReturn('test-user');
$user->method('getCloudId')->willReturn('cloudId');
@@ -122,7 +356,10 @@ class SyncServiceTest extends TestCase {
->method('createCardFromUser')
->willReturn($this->createMock(VCard::class));
- $ss = new SyncService($backend, $userManager, $dbConnection, $logger, $converter);
+ $clientService = $this->createMock(IClientService::class);
+ $config = $this->createMock(IConfig::class);
+
+ $ss = new SyncService($backend, $userManager, $dbConnection, $logger, $converter, $clientService, $config);
$ss->updateUser($user);
$ss->updateUser($user);
@@ -130,45 +367,114 @@ class SyncServiceTest extends TestCase {
$ss->deleteUser($user);
}
- /**
- * @param int $createCount
- * @param int $updateCount
- * @param int $deleteCount
- * @return \PHPUnit\Framework\MockObject\MockObject|CardDavBackend
- */
- private function getBackendMock($createCount, $updateCount, $deleteCount) {
- $backend = $this->getMockBuilder(CardDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $backend->expects($this->exactly($createCount))->method('createCard');
- $backend->expects($this->exactly($updateCount))->method('updateCard');
- $backend->expects($this->exactly($deleteCount))->method('deleteCard');
- return $backend;
+ public function testDeleteAddressbookWhenAccessRevoked(): void {
+ $this->expectException(ClientExceptionInterface::class);
+
+ $this->backend->expects($this->exactly(0))
+ ->method('createCard');
+ $this->backend->expects($this->exactly(0))
+ ->method('updateCard');
+ $this->backend->expects($this->exactly(0))
+ ->method('deleteCard');
+ $this->backend->expects($this->exactly(1))
+ ->method('deleteAddressBook');
+
+ $request = new PsrRequest(
+ 'REPORT',
+ 'https://server2.internal/remote.php/dav/addressbooks/system/system/system',
+ ['Content-Type' => 'application/xml'],
+ );
+
+ $body = '<?xml version="1.0" encoding="utf-8"?>
+<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
+ <s:exception>Sabre\DAV\Exception\NotAuthenticated</s:exception>
+ <s:message>No public access to this resource., Username or password was incorrect, No \'Authorization: Bearer\' header found. Either the client didn\'t send one, or the server is mis-configured, Username or password was incorrect</s:message>
+</d:error>';
+
+ $response = new PsrResponse(
+ 401,
+ ['Content-Type' => 'application/xml; charset=utf-8', 'Content-Length' => strlen($body)],
+ $body
+ );
+
+ $message = 'Client error: `REPORT https://server2.internal/cloud/remote.php/dav/addressbooks/system/system/system` resulted in a `401 Unauthorized` response:
+<?xml version="1.0" encoding="utf-8"?>
+<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
+ <s:exception>Sabre\DA (truncated...)
+';
+
+ $reportException = new ClientException(
+ $message,
+ $request,
+ $response
+ );
+
+ $this->client
+ ->method('request')
+ ->willThrowException($reportException);
+
+ $this->service->syncRemoteAddressBook(
+ '',
+ 'system',
+ 'system',
+ '1234567890',
+ null,
+ '1',
+ 'principals/system/system',
+ []
+ );
}
- /**
- * @param $backend
- * @param $response
- * @return SyncService|\PHPUnit\Framework\MockObject\MockObject
- */
- private function getSyncServiceMock($backend, $response) {
- $userManager = $this->getMockBuilder(IUserManager::class)->disableOriginalConstructor()->getMock();
- $dbConnection = $this->createMock(IDBConnection::class);
- $logger = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock();
- $converter = $this->createMock(Converter::class);
- /** @var SyncService | \PHPUnit\Framework\MockObject\MockObject $ss */
- $ss = $this->getMockBuilder(SyncService::class)
- ->setMethods(['ensureSystemAddressBookExists', 'requestSyncReport', 'download', 'getCertPath'])
- ->setConstructorArgs([$backend, $userManager, $dbConnection, $logger, $converter])
- ->getMock();
- $ss->method('requestSyncReport')->withAnyParameters()->willReturn(['response' => $response, 'token' => 'sync-token-1']);
- $ss->method('ensureSystemAddressBookExists')->willReturn(['id' => 1]);
- $ss->method('download')->willReturn([
- 'body' => '',
- 'statusCode' => 200,
- 'headers' => []
- ]);
- $ss->method('getCertPath')->willReturn('');
- return $ss;
+ #[\PHPUnit\Framework\Attributes\DataProvider('providerUseAbsoluteUriReport')]
+ public function testUseAbsoluteUriReport(string $host, string $expected): void {
+ $body = '<?xml version="1.0"?>
+<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:card="urn:ietf:params:xml:ns:carddav" xmlns:oc="http://owncloud.org/ns">
+ <d:sync-token>http://sabre.io/ns/sync/1</d:sync-token>
+</d:multistatus>';
+
+ $requestResponse = new Response(new PsrResponse(
+ 207,
+ ['Content-Type' => 'application/xml; charset=utf-8', 'Content-Length' => strlen($body)],
+ $body
+ ));
+
+ $this->client
+ ->method('request')
+ ->with(
+ 'REPORT',
+ $this->callback(function ($uri) use ($expected) {
+ $this->assertEquals($expected, $uri);
+ return true;
+ }),
+ $this->callback(function ($options) {
+ $this->assertIsArray($options);
+ return true;
+ }),
+ )
+ ->willReturn($requestResponse);
+
+ $this->service->syncRemoteAddressBook(
+ $host,
+ 'system',
+ 'remote.php/dav/addressbooks/system/system/system',
+ '1234567890',
+ null,
+ '1',
+ 'principals/system/system',
+ []
+ );
+ }
+
+ public static function providerUseAbsoluteUriReport(): array {
+ return [
+ ['https://server.internal', 'https://server.internal/remote.php/dav/addressbooks/system/system/system'],
+ ['https://server.internal/', 'https://server.internal/remote.php/dav/addressbooks/system/system/system'],
+ ['https://server.internal/nextcloud', 'https://server.internal/nextcloud/remote.php/dav/addressbooks/system/system/system'],
+ ['https://server.internal/nextcloud/', 'https://server.internal/nextcloud/remote.php/dav/addressbooks/system/system/system'],
+ ['https://server.internal:8080', 'https://server.internal:8080/remote.php/dav/addressbooks/system/system/system'],
+ ['https://server.internal:8080/', 'https://server.internal:8080/remote.php/dav/addressbooks/system/system/system'],
+ ['https://server.internal:8080/nextcloud', 'https://server.internal:8080/nextcloud/remote.php/dav/addressbooks/system/system/system'],
+ ['https://server.internal:8080/nextcloud/', 'https://server.internal:8080/nextcloud/remote.php/dav/addressbooks/system/system/system'],
+ ];
}
}
diff --git a/apps/dav/tests/unit/CardDAV/SystemAddressBookTest.php b/apps/dav/tests/unit/CardDAV/SystemAddressBookTest.php
index a1c614cb69d..4a218fa4616 100644
--- a/apps/dav/tests/unit/CardDAV/SystemAddressBookTest.php
+++ b/apps/dav/tests/unit/CardDAV/SystemAddressBookTest.php
@@ -30,15 +30,15 @@ use Sabre\VObject\Reader;
use Test\TestCase;
class SystemAddressBookTest extends TestCase {
- private MockObject|BackendInterface $cardDavBackend;
+ private BackendInterface&MockObject $cardDavBackend;
private array $addressBookInfo;
- private IL10N|MockObject $l10n;
- private IConfig|MockObject $config;
+ private IL10N&MockObject $l10n;
+ private IConfig&MockObject $config;
private IUserSession $userSession;
- private IRequest|MockObject $request;
+ private IRequest&MockObject $request;
private array $server;
- private TrustedServers|MockObject $trustedServers;
- private IGroupManager|MockObject $groupManager;
+ private TrustedServers&MockObject $trustedServers;
+ private IGroupManager&MockObject $groupManager;
private SystemAddressbook $addressBook;
protected function setUp(): void {
@@ -150,7 +150,7 @@ VCF;
->with(123, 'user.vcf')
->willReturn($originalCard);
- $card = $this->addressBook->getChild("user.vcf");
+ $card = $this->addressBook->getChild('user.vcf');
/** @var VCard $vCard */
$vCard = Reader::read($card->get());
@@ -180,7 +180,7 @@ VCF;
]);
$this->expectException(NotFound::class);
- $this->addressBook->getChild("LDAP:user.vcf");
+ $this->addressBook->getChild('LDAP:user.vcf');
}
public function testGetChildWithoutEnumeration(): void {
@@ -193,7 +193,7 @@ VCF;
]);
$this->expectException(Forbidden::class);
- $this->addressBook->getChild("LDAP:user.vcf");
+ $this->addressBook->getChild('LDAP:user.vcf');
}
public function testGetChildAsGuest(): void {
@@ -211,7 +211,7 @@ VCF;
->willReturn($user);
$this->expectException(Forbidden::class);
- $this->addressBook->getChild("LDAP:user.vcf");
+ $this->addressBook->getChild('LDAP:user.vcf');
}
public function testGetChildWithGroupEnumerationRestriction(): void {
@@ -272,7 +272,7 @@ VCF;
->willReturn($user);
$this->expectException(Forbidden::class);
- $this->addressBook->getChild("LDAP:user.vcf");
+ $this->addressBook->getChild('LDAP:user.vcf');
}
public function testGetOwnChildWithPhoneNumberEnumerationRestriction(): void {
@@ -305,7 +305,7 @@ VCF;
'carddata' => $cardData,
]);
- $this->addressBook->getChild("LDAP:user.vcf");
+ $this->addressBook->getChild('LDAP:user.vcf');
}
public function testGetMultipleChildrenWithGroupEnumerationRestriction(): void {
diff --git a/apps/dav/tests/unit/CardDAV/Validation/CardDavValidatePluginTest.php b/apps/dav/tests/unit/CardDAV/Validation/CardDavValidatePluginTest.php
new file mode 100644
index 00000000000..058735ba32a
--- /dev/null
+++ b/apps/dav/tests/unit/CardDAV/Validation/CardDavValidatePluginTest.php
@@ -0,0 +1,73 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\CardDAV\Validation;
+
+use OCA\DAV\CardDAV\Validation\CardDavValidatePlugin;
+use OCP\IAppConfig;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\DAV\Exception\Forbidden;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use Test\TestCase;
+
+class CardDavValidatePluginTest extends TestCase {
+
+ private CardDavValidatePlugin $plugin;
+ private IAppConfig&MockObject $config;
+ private RequestInterface&MockObject $request;
+ private ResponseInterface&MockObject $response;
+
+ protected function setUp(): void {
+ parent::setUp();
+ // construct mock objects
+ $this->config = $this->createMock(IAppConfig::class);
+ $this->request = $this->createMock(RequestInterface::class);
+ $this->response = $this->createMock(ResponseInterface::class);
+ $this->plugin = new CardDavValidatePlugin(
+ $this->config,
+ );
+ }
+
+ public function testPutSizeLessThenLimit(): void {
+
+ // construct method responses
+ $this->config
+ ->method('getValueInt')
+ ->with('dav', 'card_size_limit', 5242880)
+ ->willReturn(5242880);
+ $this->request
+ ->method('getRawServerValue')
+ ->with('CONTENT_LENGTH')
+ ->willReturn('1024');
+ // test condition
+ $this->assertTrue(
+ $this->plugin->beforePut($this->request, $this->response)
+ );
+
+ }
+
+ public function testPutSizeMoreThenLimit(): void {
+
+ // construct method responses
+ $this->config
+ ->method('getValueInt')
+ ->with('dav', 'card_size_limit', 5242880)
+ ->willReturn(5242880);
+ $this->request
+ ->method('getRawServerValue')
+ ->with('CONTENT_LENGTH')
+ ->willReturn('6242880');
+ $this->expectException(Forbidden::class);
+ // test condition
+ $this->plugin->beforePut($this->request, $this->response);
+
+ }
+
+}
diff --git a/apps/dav/tests/unit/Command/DeleteCalendarTest.php b/apps/dav/tests/unit/Command/DeleteCalendarTest.php
index 3e3095a7bce..2bd269de6dc 100644
--- a/apps/dav/tests/unit/Command/DeleteCalendarTest.php
+++ b/apps/dav/tests/unit/Command/DeleteCalendarTest.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Command;
+namespace OCA\DAV\Tests\unit\Command;
use OCA\DAV\CalDAV\BirthdayService;
use OCA\DAV\CalDAV\CalDavBackend;
@@ -28,23 +28,12 @@ class DeleteCalendarTest extends TestCase {
public const USER = 'user';
public const NAME = 'calendar';
- /** @var CalDavBackend|MockObject */
- private $calDav;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var IL10N|MockObject */
- private $l10n;
-
- /** @var IUserManager|MockObject */
- private $userManager;
-
- /** @var DeleteCalendar */
- private $command;
-
- /** @var MockObject|LoggerInterface */
- private $logger;
+ private CalDavBackend&MockObject $calDav;
+ private IConfig&MockObject $config;
+ private IL10N&MockObject $l10n;
+ private IUserManager&MockObject $userManager;
+ private LoggerInterface&MockObject $logger;
+ private DeleteCalendar $command;
protected function setUp(): void {
parent::setUp();
@@ -100,7 +89,7 @@ class DeleteCalendarTest extends TestCase {
public function testInvalidCalendar(): void {
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage(
- 'User <' . self::USER . '> has no calendar named <' . self::NAME . '>.');
+ 'User <' . self::USER . '> has no calendar named <' . self::NAME . '>.');
$this->userManager->expects($this->once())
->method('userExists')
@@ -126,7 +115,7 @@ class DeleteCalendarTest extends TestCase {
$calendar = [
'id' => $id,
'principaluri' => 'principals/users/' . self::USER,
- 'uri' => self::NAME
+ 'uri' => self::NAME,
];
$this->userManager->expects($this->once())
@@ -187,7 +176,8 @@ class DeleteCalendarTest extends TestCase {
$calendar = [
'id' => $id,
'principaluri' => 'principals/users/' . self::USER,
- 'uri' => BirthdayService::BIRTHDAY_CALENDAR_URI
+ 'uri' => BirthdayService::BIRTHDAY_CALENDAR_URI,
+ '{DAV:}displayname' => 'Test',
];
$this->userManager->expects($this->once())
@@ -216,7 +206,8 @@ class DeleteCalendarTest extends TestCase {
$calendar = [
'id' => 1234,
'principaluri' => 'principals/users/' . self::USER,
- 'uri' => BirthdayService::BIRTHDAY_CALENDAR_URI
+ 'uri' => BirthdayService::BIRTHDAY_CALENDAR_URI,
+ '{DAV:}displayname' => 'Test',
];
$this->userManager->expects($this->once())
->method('userExists')
diff --git a/apps/dav/tests/unit/Command/ListAddressbooksTest.php b/apps/dav/tests/unit/Command/ListAddressbooksTest.php
new file mode 100644
index 00000000000..2768ed576c3
--- /dev/null
+++ b/apps/dav/tests/unit/Command/ListAddressbooksTest.php
@@ -0,0 +1,107 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\Tests\unit\Command;
+
+use OCA\DAV\CardDAV\CardDavBackend;
+use OCA\DAV\Command\ListAddressbooks;
+use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use Symfony\Component\Console\Tester\CommandTester;
+use Test\TestCase;
+
+/**
+ * Class ListCalendarsTest
+ *
+ * @package OCA\DAV\Tests\Command
+ */
+class ListAddressbooksTest extends TestCase {
+ private IUserManager&MockObject $userManager;
+ private CardDavBackend&MockObject $cardDavBackend;
+ private ListAddressbooks $command;
+
+ public const USERNAME = 'username';
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->cardDavBackend = $this->createMock(CardDavBackend::class);
+
+ $this->command = new ListAddressbooks(
+ $this->userManager,
+ $this->cardDavBackend
+ );
+ }
+
+ public function testWithBadUser(): void {
+ $this->expectException(\InvalidArgumentException::class);
+
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with(self::USERNAME)
+ ->willReturn(false);
+
+ $commandTester = new CommandTester($this->command);
+ $commandTester->execute([
+ 'uid' => self::USERNAME,
+ ]);
+ $this->assertStringContainsString('User <' . self::USERNAME . '> in unknown', $commandTester->getDisplay());
+ }
+
+ public function testWithCorrectUserWithNoCalendars(): void {
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with(self::USERNAME)
+ ->willReturn(true);
+
+ $this->cardDavBackend->expects($this->once())
+ ->method('getAddressBooksForUser')
+ ->with('principals/users/' . self::USERNAME)
+ ->willReturn([]);
+
+ $commandTester = new CommandTester($this->command);
+ $commandTester->execute([
+ 'uid' => self::USERNAME,
+ ]);
+ $this->assertStringContainsString('User <' . self::USERNAME . "> has no addressbooks\n", $commandTester->getDisplay());
+ }
+
+ public static function dataExecute(): array {
+ return [
+ [false, '✓'],
+ [true, 'x']
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataExecute')]
+ public function testWithCorrectUser(bool $readOnly, string $output): void {
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with(self::USERNAME)
+ ->willReturn(true);
+
+ $this->cardDavBackend->expects($this->once())
+ ->method('getAddressBooksForUser')
+ ->with('principals/users/' . self::USERNAME)
+ ->willReturn([
+ [
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only' => $readOnly,
+ 'uri' => 'test',
+ '{DAV:}displayname' => 'dp',
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => 'owner-principal',
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}owner-displayname' => 'owner-dp',
+ ]
+ ]);
+
+ $commandTester = new CommandTester($this->command);
+ $commandTester->execute([
+ 'uid' => self::USERNAME,
+ ]);
+ $this->assertStringContainsString($output, $commandTester->getDisplay());
+ }
+}
diff --git a/apps/dav/tests/unit/Command/ListCalendarSharesTest.php b/apps/dav/tests/unit/Command/ListCalendarSharesTest.php
new file mode 100644
index 00000000000..e5d4251cbf9
--- /dev/null
+++ b/apps/dav/tests/unit/Command/ListCalendarSharesTest.php
@@ -0,0 +1,172 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\Command;
+
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\Command\ListCalendarShares;
+use OCA\DAV\Connector\Sabre\Principal;
+use OCA\DAV\DAV\Sharing\SharingMapper;
+use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use Symfony\Component\Console\Tester\CommandTester;
+use Test\TestCase;
+
+class ListCalendarSharesTest extends TestCase {
+
+ private IUserManager&MockObject $userManager;
+ private Principal&MockObject $principal;
+ private CalDavBackend&MockObject $caldav;
+ private SharingMapper $sharingMapper;
+ private ListCalendarShares $command;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->principal = $this->createMock(Principal::class);
+ $this->caldav = $this->createMock(CalDavBackend::class);
+ $this->sharingMapper = $this->createMock(SharingMapper::class);
+
+ $this->command = new ListCalendarShares(
+ $this->userManager,
+ $this->principal,
+ $this->caldav,
+ $this->sharingMapper,
+ );
+ }
+
+ public function testUserUnknown(): void {
+ $user = 'bob';
+
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage("User $user is unknown");
+
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with($user)
+ ->willReturn(false);
+
+ $commandTester = new CommandTester($this->command);
+ $commandTester->execute([
+ 'uid' => $user,
+ ]);
+ }
+
+ public function testPrincipalNotFound(): void {
+ $user = 'bob';
+
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage("Unable to fetch principal for user $user");
+
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with($user)
+ ->willReturn(true);
+
+ $this->principal->expects($this->once())
+ ->method('getPrincipalByPath')
+ ->with('principals/users/' . $user)
+ ->willReturn(null);
+
+ $commandTester = new CommandTester($this->command);
+ $commandTester->execute([
+ 'uid' => $user,
+ ]);
+ }
+
+ public function testNoCalendarShares(): void {
+ $user = 'bob';
+
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with($user)
+ ->willReturn(true);
+
+ $this->principal->expects($this->once())
+ ->method('getPrincipalByPath')
+ ->with('principals/users/' . $user)
+ ->willReturn([
+ 'uri' => 'principals/users/' . $user,
+ ]);
+
+ $this->principal->expects($this->once())
+ ->method('getGroupMembership')
+ ->willReturn([]);
+ $this->principal->expects($this->once())
+ ->method('getCircleMembership')
+ ->willReturn([]);
+
+ $this->sharingMapper->expects($this->once())
+ ->method('getSharesByPrincipals')
+ ->willReturn([]);
+
+ $commandTester = new CommandTester($this->command);
+ $commandTester->execute([
+ 'uid' => $user,
+ ]);
+
+ $this->assertStringContainsString(
+ "User $user has no calendar shares",
+ $commandTester->getDisplay()
+ );
+ }
+
+ public function testFilterByCalendarId(): void {
+ $user = 'bob';
+
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with($user)
+ ->willReturn(true);
+
+ $this->principal->expects($this->once())
+ ->method('getPrincipalByPath')
+ ->with('principals/users/' . $user)
+ ->willReturn([
+ 'uri' => 'principals/users/' . $user,
+ ]);
+
+ $this->principal->expects($this->once())
+ ->method('getGroupMembership')
+ ->willReturn([]);
+ $this->principal->expects($this->once())
+ ->method('getCircleMembership')
+ ->willReturn([]);
+
+ $this->sharingMapper->expects($this->once())
+ ->method('getSharesByPrincipals')
+ ->willReturn([
+ [
+ 'id' => 1000,
+ 'principaluri' => 'principals/users/bob',
+ 'type' => 'calendar',
+ 'access' => 2,
+ 'resourceid' => 10
+ ],
+ [
+ 'id' => 1001,
+ 'principaluri' => 'principals/users/bob',
+ 'type' => 'calendar',
+ 'access' => 3,
+ 'resourceid' => 11
+ ],
+ ]);
+
+ $commandTester = new CommandTester($this->command);
+ $commandTester->execute([
+ 'uid' => $user,
+ '--calendar-id' => 10,
+ ]);
+
+ $this->assertStringNotContainsString(
+ '1001',
+ $commandTester->getDisplay()
+ );
+ }
+}
diff --git a/apps/dav/tests/unit/Command/ListCalendarsTest.php b/apps/dav/tests/unit/Command/ListCalendarsTest.php
index 30df9ee79dc..d398a7c772f 100644
--- a/apps/dav/tests/unit/Command/ListCalendarsTest.php
+++ b/apps/dav/tests/unit/Command/ListCalendarsTest.php
@@ -1,14 +1,17 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Command;
+namespace OCA\DAV\Tests\unit\Command;
use OCA\DAV\CalDAV\BirthdayService;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Command\ListCalendars;
use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Tester\CommandTester;
use Test\TestCase;
@@ -18,15 +21,9 @@ use Test\TestCase;
* @package OCA\DAV\Tests\Command
*/
class ListCalendarsTest extends TestCase {
-
- /** @var \OCP\IUserManager|\PHPUnit\Framework\MockObject\MockObject $userManager */
- private $userManager;
-
- /** @var CalDavBackend|\PHPUnit\Framework\MockObject\MockObject $l10n */
- private $calDav;
-
- /** @var ListCalendars */
- private $command;
+ private IUserManager&MockObject $userManager;
+ private CalDavBackend&MockObject $calDav;
+ private ListCalendars $command;
public const USERNAME = 'username';
@@ -54,7 +51,7 @@ class ListCalendarsTest extends TestCase {
$commandTester->execute([
'uid' => self::USERNAME,
]);
- $this->assertStringContainsString("User <" . self::USERNAME . "> in unknown", $commandTester->getDisplay());
+ $this->assertStringContainsString('User <' . self::USERNAME . '> in unknown', $commandTester->getDisplay());
}
public function testWithCorrectUserWithNoCalendars(): void {
@@ -72,19 +69,17 @@ class ListCalendarsTest extends TestCase {
$commandTester->execute([
'uid' => self::USERNAME,
]);
- $this->assertStringContainsString("User <" . self::USERNAME . "> has no calendars\n", $commandTester->getDisplay());
+ $this->assertStringContainsString('User <' . self::USERNAME . "> has no calendars\n", $commandTester->getDisplay());
}
- public function dataExecute() {
+ public static function dataExecute(): array {
return [
[false, '✓'],
[true, 'x']
];
}
- /**
- * @dataProvider dataExecute
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataExecute')]
public function testWithCorrectUser(bool $readOnly, string $output): void {
$this->userManager->expects($this->once())
->method('userExists')
diff --git a/apps/dav/tests/unit/Command/MoveCalendarTest.php b/apps/dav/tests/unit/Command/MoveCalendarTest.php
index 09831fdb1b2..e9f016961f2 100644
--- a/apps/dav/tests/unit/Command/MoveCalendarTest.php
+++ b/apps/dav/tests/unit/Command/MoveCalendarTest.php
@@ -1,9 +1,11 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Command;
+namespace OCA\DAV\Tests\unit\Command;
use InvalidArgumentException;
use OCA\DAV\CalDAV\CalDavBackend;
@@ -24,29 +26,14 @@ use Test\TestCase;
* @package OCA\DAV\Tests\Command
*/
class MoveCalendarTest extends TestCase {
- /** @var \OCP\IUserManager|MockObject $userManager */
- private $userManager;
-
- /** @var \OCP\IGroupManager|MockObject $groupManager */
- private $groupManager;
-
- /** @var \OCP\Share\IManager|MockObject $shareManager */
- private $shareManager;
-
- /** @var IConfig|MockObject $l10n */
- private $config;
-
- /** @var IL10N|MockObject $l10n */
- private $l10n;
-
- /** @var CalDavBackend|MockObject $l10n */
- private $calDav;
-
- /** @var MoveCalendar */
- private $command;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
+ private IUserManager&MockObject $userManager;
+ private IGroupManager&MockObject $groupManager;
+ private \OCP\Share\IManager&MockObject $shareManager;
+ private IConfig&MockObject $config;
+ private IL10N&MockObject $l10n;
+ private CalDavBackend&MockObject $calDav;
+ private LoggerInterface&MockObject $logger;
+ private MoveCalendar $command;
protected function setUp(): void {
parent::setUp();
@@ -70,32 +57,23 @@ class MoveCalendarTest extends TestCase {
);
}
- public function dataExecute() {
+ public static function dataExecute(): array {
return [
[false, true],
[true, false]
];
}
- /**
- * @dataProvider dataExecute
- *
- * @param $userOriginExists
- * @param $userDestinationExists
- */
- public function testWithBadUserOrigin($userOriginExists, $userDestinationExists): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataExecute')]
+ public function testWithBadUserOrigin(bool $userOriginExists, bool $userDestinationExists): void {
$this->expectException(\InvalidArgumentException::class);
$this->userManager->expects($this->exactly($userOriginExists ? 2 : 1))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturnOnConsecutiveCalls(
- $userOriginExists,
- $userDestinationExists,
- );
+ ->willReturnMap([
+ ['user', $userOriginExists],
+ ['user2', $userDestinationExists],
+ ]);
$commandTester = new CommandTester($this->command);
$commandTester->execute([
@@ -112,11 +90,10 @@ class MoveCalendarTest extends TestCase {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->once())->method('getCalendarByUri')
->with('principals/users/user', 'personal')
@@ -137,20 +114,20 @@ class MoveCalendarTest extends TestCase {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->exactly(2))
->method('getCalendarByUri')
- ->withConsecutive(
- ['principals/users/user', 'personal'],
- ['principals/users/user2', 'personal'],
- )
- ->willReturn([
- 'id' => 1234,
+ ->willReturnMap([
+ ['principals/users/user', 'personal', [
+ 'id' => 1234,
+ ]],
+ ['principals/users/user2', 'personal', [
+ 'id' => 1234,
+ ]],
]);
$commandTester = new CommandTester($this->command);
@@ -164,24 +141,19 @@ class MoveCalendarTest extends TestCase {
public function testMove(): void {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->exactly(2))
->method('getCalendarByUri')
- ->withConsecutive(
- ['principals/users/user', 'personal'],
- ['principals/users/user2', 'personal'],
- )
- ->willReturnOnConsecutiveCalls(
- [
+ ->willReturnMap([
+ ['principals/users/user', 'personal', [
'id' => 1234,
- ],
- null,
- );
+ ]],
+ ['principals/users/user2', 'personal', null],
+ ]);
$this->calDav->expects($this->once())->method('getShares')
->with(1234)
@@ -194,41 +166,34 @@ class MoveCalendarTest extends TestCase {
'destinationuid' => 'user2',
]);
- $this->assertStringContainsString("[OK] Calendar <personal> was moved from user <user> to <user2>", $commandTester->getDisplay());
+ $this->assertStringContainsString('[OK] Calendar <personal> was moved from user <user> to <user2>', $commandTester->getDisplay());
}
- public function dataTestMoveWithDestinationNotPartOfGroup(): array {
+ public static function dataTestMoveWithDestinationNotPartOfGroup(): array {
return [
[true],
[false]
];
}
- /**
- * @dataProvider dataTestMoveWithDestinationNotPartOfGroup
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestMoveWithDestinationNotPartOfGroup')]
public function testMoveWithDestinationNotPartOfGroup(bool $shareWithGroupMembersOnly): void {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->exactly(2))
->method('getCalendarByUri')
- ->withConsecutive(
- ['principals/users/user', 'personal'],
- ['principals/users/user2', 'personal'],
- )
- ->willReturnOnConsecutiveCalls(
- [
+ ->willReturnMap([
+ ['principals/users/user', 'personal', [
'id' => 1234,
'uri' => 'personal',
- ],
- null,
- );
+ ]],
+ ['principals/users/user2', 'personal', null],
+ ]);
$this->shareManager->expects($this->once())->method('shareWithGroupMembersOnly')
->willReturn($shareWithGroupMembersOnly);
@@ -240,7 +205,7 @@ class MoveCalendarTest extends TestCase {
]);
if ($shareWithGroupMembersOnly === true) {
$this->expectException(InvalidArgumentException::class);
- $this->expectExceptionMessage("User <user2> is not part of the group <nextclouders> with whom the calendar <personal> was shared. You may use -f to move the calendar while deleting this share.");
+ $this->expectExceptionMessage('User <user2> is not part of the group <nextclouders> with whom the calendar <personal> was shared. You may use -f to move the calendar while deleting this share.');
}
$commandTester = new CommandTester($this->command);
@@ -254,25 +219,20 @@ class MoveCalendarTest extends TestCase {
public function testMoveWithDestinationPartOfGroup(): void {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->exactly(2))
->method('getCalendarByUri')
- ->withConsecutive(
- ['principals/users/user', 'personal'],
- ['principals/users/user2', 'personal'],
- )
- ->willReturnOnConsecutiveCalls(
- [
+ ->willReturnMap([
+ ['principals/users/user', 'personal', [
'id' => 1234,
'uri' => 'personal',
- ],
- null,
- );
+ ]],
+ ['principals/users/user2', 'personal', null],
+ ]);
$this->shareManager->expects($this->once())->method('shareWithGroupMembersOnly')
->willReturn(true);
@@ -294,32 +254,27 @@ class MoveCalendarTest extends TestCase {
'destinationuid' => 'user2',
]);
- $this->assertStringContainsString("[OK] Calendar <personal> was moved from user <user> to <user2>", $commandTester->getDisplay());
+ $this->assertStringContainsString('[OK] Calendar <personal> was moved from user <user> to <user2>', $commandTester->getDisplay());
}
public function testMoveWithDestinationNotPartOfGroupAndForce(): void {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->exactly(2))
->method('getCalendarByUri')
- ->withConsecutive(
- ['principals/users/user', 'personal'],
- ['principals/users/user2', 'personal'],
- )
- ->willReturnOnConsecutiveCalls(
- [
+ ->willReturnMap([
+ ['principals/users/user', 'personal', [
'id' => 1234,
'uri' => 'personal',
'{DAV:}displayname' => 'Personal'
- ],
- null,
- );
+ ]],
+ ['principals/users/user2', 'personal', null],
+ ]);
$this->shareManager->expects($this->once())->method('shareWithGroupMembersOnly')
->willReturn(true);
@@ -342,55 +297,48 @@ class MoveCalendarTest extends TestCase {
'--force' => true
]);
- $this->assertStringContainsString("[OK] Calendar <personal> was moved from user <user> to <user2>", $commandTester->getDisplay());
+ $this->assertStringContainsString('[OK] Calendar <personal> was moved from user <user> to <user2>', $commandTester->getDisplay());
}
- public function dataTestMoveWithCalendarAlreadySharedToDestination(): array {
+ public static function dataTestMoveWithCalendarAlreadySharedToDestination(): array {
return [
[true],
[false]
];
}
- /**
- * @dataProvider dataTestMoveWithCalendarAlreadySharedToDestination
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestMoveWithCalendarAlreadySharedToDestination')]
public function testMoveWithCalendarAlreadySharedToDestination(bool $force): void {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->exactly(2))
->method('getCalendarByUri')
- ->withConsecutive(
- ['principals/users/user', 'personal'],
- ['principals/users/user2', 'personal'],
- )
- ->willReturnOnConsecutiveCalls(
- [
+ ->willReturnMap([
+ ['principals/users/user', 'personal', [
'id' => 1234,
'uri' => 'personal',
'{DAV:}displayname' => 'Personal'
- ],
- null,
- );
+ ]],
+ ['principals/users/user2', 'personal', null],
+ ]);
$this->calDav->expects($this->once())->method('getShares')
- ->with(1234)
- ->willReturn([
- [
- 'href' => 'principal:principals/users/user2',
- '{DAV:}displayname' => 'Personal'
- ]
- ]);
+ ->with(1234)
+ ->willReturn([
+ [
+ 'href' => 'principal:principals/users/user2',
+ '{DAV:}displayname' => 'Personal'
+ ]
+ ]);
if ($force === false) {
$this->expectException(InvalidArgumentException::class);
- $this->expectExceptionMessage("The calendar <personal> is already shared to user <user2>.You may use -f to move the calendar while deleting this share.");
+ $this->expectExceptionMessage('The calendar <personal> is already shared to user <user2>.You may use -f to move the calendar while deleting this share.');
} else {
$this->calDav->expects($this->once())->method('updateShares');
}
diff --git a/apps/dav/tests/unit/Command/RemoveInvalidSharesTest.php b/apps/dav/tests/unit/Command/RemoveInvalidSharesTest.php
index 3c597e22a95..ec56aa64eb2 100644
--- a/apps/dav/tests/unit/Command/RemoveInvalidSharesTest.php
+++ b/apps/dav/tests/unit/Command/RemoveInvalidSharesTest.php
@@ -1,15 +1,17 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2018 ownCloud GmbH
* SPDX-License-Identifier: AGPL-3.0-only
*/
-namespace OCA\DAV\Tests\Unit\Command;
+namespace OCA\DAV\Tests\unit\Command;
use OCA\DAV\Command\RemoveInvalidShares;
use OCA\DAV\Connector\Sabre\Principal;
-use OCP\Migration\IOutput;
+use OCP\IDBConnection;
+use OCP\Server;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Test\TestCase;
@@ -23,7 +25,7 @@ use Test\TestCase;
class RemoveInvalidSharesTest extends TestCase {
protected function setUp(): void {
parent::setUp();
- $db = \OC::$server->getDatabaseConnection();
+ $db = Server::get(IDBConnection::class);
$db->insertIfNotExist('*PREFIX*dav_shares', [
'principaluri' => 'principal:unknown',
@@ -34,19 +36,17 @@ class RemoveInvalidSharesTest extends TestCase {
}
public function test(): void {
- $db = \OC::$server->getDatabaseConnection();
- /** @var Principal | \PHPUnit\Framework\MockObject\MockObject $principal */
+ $db = Server::get(IDBConnection::class);
$principal = $this->createMock(Principal::class);
- /** @var IOutput | \PHPUnit\Framework\MockObject\MockObject $output */
- $output = $this->createMock(IOutput::class);
-
$repair = new RemoveInvalidShares($db, $principal);
$this->invokePrivate($repair, 'run', [$this->createMock(InputInterface::class), $this->createMock(OutputInterface::class)]);
$query = $db->getQueryBuilder();
- $result = $query->select('*')->from('dav_shares')
- ->where($query->expr()->eq('principaluri', $query->createNamedParameter('principal:unknown')))->execute();
+ $query->select('*')
+ ->from('dav_shares')
+ ->where($query->expr()->eq('principaluri', $query->createNamedParameter('principal:unknown')));
+ $result = $query->executeQuery();
$data = $result->fetchAll();
$result->closeCursor();
$this->assertEquals(0, count($data));
diff --git a/apps/dav/tests/unit/Comments/CommentsNodeTest.php b/apps/dav/tests/unit/Comments/CommentsNodeTest.php
index d2bb60af4b2..9e108b4cf63 100644
--- a/apps/dav/tests/unit/Comments/CommentsNodeTest.php
+++ b/apps/dav/tests/unit/Comments/CommentsNodeTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -14,38 +15,26 @@ use OCP\Comments\MessageTooLongException;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\PropPatch;
class CommentsNodeTest extends \Test\TestCase {
-
- /** @var ICommentsManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $commentsManager;
-
- protected $comment;
- protected $node;
- protected $userManager;
- protected $logger;
- protected $userSession;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected IComment&MockObject $comment;
+ protected IUserManager&MockObject $userManager;
+ protected LoggerInterface&MockObject $logger;
+ protected IUserSession&MockObject $userSession;
+ protected CommentNode $node;
protected function setUp(): void {
parent::setUp();
- $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->comment = $this->getMockBuilder(IComment::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->logger = $this->getMockBuilder(LoggerInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->commentsManager = $this->createMock(ICommentsManager::class);
+ $this->comment = $this->createMock(IComment::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
$this->node = new CommentNode(
$this->commentsManager,
@@ -57,10 +46,7 @@ class CommentsNodeTest extends \Test\TestCase {
}
public function testDelete(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('alice');
@@ -92,10 +78,7 @@ class CommentsNodeTest extends \Test\TestCase {
public function testDeleteForbidden(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('mallory');
@@ -144,10 +127,7 @@ class CommentsNodeTest extends \Test\TestCase {
public function testUpdateComment(): void {
$msg = 'Hello Earth';
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('alice');
@@ -182,10 +162,7 @@ class CommentsNodeTest extends \Test\TestCase {
$msg = null;
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('alice');
@@ -197,7 +174,7 @@ class CommentsNodeTest extends \Test\TestCase {
$this->comment->expects($this->once())
->method('setMessage')
->with($msg)
- ->will($this->throwException(new \Exception('buh!')));
+ ->willThrowException(new \Exception('buh!'));
$this->comment->expects($this->any())
->method('getActorType')
@@ -221,10 +198,7 @@ class CommentsNodeTest extends \Test\TestCase {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('Message exceeds allowed character limit of');
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('alice');
@@ -235,7 +209,7 @@ class CommentsNodeTest extends \Test\TestCase {
$this->comment->expects($this->once())
->method('setMessage')
- ->will($this->throwException(new MessageTooLongException()));
+ ->willThrowException(new MessageTooLongException());
$this->comment->expects($this->any())
->method('getActorType')
@@ -261,10 +235,7 @@ class CommentsNodeTest extends \Test\TestCase {
$msg = 'HaXX0r';
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('mallory');
@@ -296,10 +267,7 @@ class CommentsNodeTest extends \Test\TestCase {
$msg = 'HaXX0r';
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->never())
->method('getUID');
@@ -344,10 +312,7 @@ class CommentsNodeTest extends \Test\TestCase {
}
public function testPropPatch(): void {
- $propPatch = $this->getMockBuilder(PropPatch::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $propPatch = $this->createMock(PropPatch::class);
$propPatch->expects($this->once())
->method('handle')
->with('{http://owncloud.org/ns}message');
@@ -396,11 +361,10 @@ class CommentsNodeTest extends \Test\TestCase {
$this->commentsManager->expects($this->exactly(2))
->method('resolveDisplayName')
- ->withConsecutive(
- [$this->equalTo('user'), $this->equalTo('alice')],
- [$this->equalTo('user'), $this->equalTo('bob')]
- )
- ->willReturnOnConsecutiveCalls('Alice Al-Isson', 'Unknown user');
+ ->willReturnMap([
+ ['user', 'alice', 'Alice Al-Isson'],
+ ['user', 'bob', 'Unknown user']
+ ]);
$this->comment->expects($this->once())
->method('getId')
@@ -491,7 +455,7 @@ class CommentsNodeTest extends \Test\TestCase {
$this->assertTrue(empty($expected));
}
- public function readCommentProvider() {
+ public static function readCommentProvider(): array {
$creationDT = new \DateTime('2016-01-19 18:48:00');
$diff = new \DateInterval('PT2H');
$readDT1 = clone $creationDT;
@@ -505,11 +469,8 @@ class CommentsNodeTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider readCommentProvider
- * @param $expected
- */
- public function testGetPropertiesUnreadProperty($creationDT, $readDT, $expected): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('readCommentProvider')]
+ public function testGetPropertiesUnreadProperty(\DateTime $creationDT, ?\DateTime $readDT, string $expected): void {
$this->comment->expects($this->any())
->method('getCreationDateTime')
->willReturn($creationDT);
diff --git a/apps/dav/tests/unit/Comments/CommentsPluginTest.php b/apps/dav/tests/unit/Comments/CommentsPluginTest.php
index 60c3e52ef54..18d32772f7b 100644
--- a/apps/dav/tests/unit/Comments/CommentsPluginTest.php
+++ b/apps/dav/tests/unit/Comments/CommentsPluginTest.php
@@ -14,44 +14,30 @@ use OCP\Comments\IComment;
use OCP\Comments\ICommentsManager;
use OCP\IUser;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\INode;
use Sabre\DAV\Tree;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
class CommentsPluginTest extends \Test\TestCase {
- /** @var \Sabre\DAV\Server */
- private $server;
-
- /** @var Tree */
- private $tree;
-
- /** @var ICommentsManager */
- private $commentsManager;
-
- /** @var IUserSession */
- private $userSession;
-
- /** @var CommentsPluginImplementation */
- private $plugin;
+ private \Sabre\DAV\Server&MockObject $server;
+ private Tree&MockObject $tree;
+ private ICommentsManager&MockObject $commentsManager;
+ private IUserSession&MockObject $userSession;
+ private CommentsPluginImplementation $plugin;
protected function setUp(): void {
parent::setUp();
- $this->tree = $this->getMockBuilder(Tree::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->tree = $this->createMock(Tree::class);
- $this->server = $this->getMockBuilder('\Sabre\DAV\Server')
+ $this->server = $this->getMockBuilder(\Sabre\DAV\Server::class)
->setConstructorArgs([$this->tree])
- ->setMethods(['getRequestUri'])
+ ->onlyMethods(['getRequestUri'])
->getMock();
- $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->commentsManager = $this->createMock(ICommentsManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
$this->plugin = new CommentsPluginImplementation($this->commentsManager, $this->userSession);
}
@@ -151,7 +137,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testCreateCommentInvalidObject(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
@@ -198,7 +184,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->tree->expects($this->any())
->method('getNodeForPath')
->with('/' . $path)
- ->will($this->throwException(new \Sabre\DAV\Exception\NotFound()));
+ ->willThrowException(new \Sabre\DAV\Exception\NotFound());
$request = $this->getMockBuilder(RequestInterface::class)
->disableOriginalConstructor()
@@ -233,7 +219,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testCreateCommentInvalidActor(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
@@ -321,7 +307,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testCreateCommentUnsupportedMediaType(): void {
$this->expectException(\Sabre\DAV\Exception\UnsupportedMediaType::class);
@@ -409,7 +395,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testCreateCommentInvalidPayload(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
@@ -503,7 +489,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testCreateCommentMessageTooLong(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('Message exceeds allowed character limit of');
@@ -597,7 +583,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testOnReportInvalidNode(): void {
$this->expectException(\Sabre\DAV\Exception\ReportNotSupported::class);
@@ -620,7 +606,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->onReport(CommentsPluginImplementation::REPORT_NAME, [], '/' . $path);
}
-
+
public function testOnReportInvalidReportName(): void {
$this->expectException(\Sabre\DAV\Exception\ReportNotSupported::class);
diff --git a/apps/dav/tests/unit/Comments/EntityCollectionTest.php b/apps/dav/tests/unit/Comments/EntityCollectionTest.php
index 0d4adae250e..29ebde7d602 100644
--- a/apps/dav/tests/unit/Comments/EntityCollectionTest.php
+++ b/apps/dav/tests/unit/Comments/EntityCollectionTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -7,43 +8,32 @@
*/
namespace OCA\DAV\Tests\unit\Comments;
+use OCA\DAV\Comments\CommentNode;
use OCA\DAV\Comments\EntityCollection;
use OCP\Comments\IComment;
use OCP\Comments\ICommentsManager;
+use OCP\Comments\NotFoundException;
use OCP\IUserManager;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
class EntityCollectionTest extends \Test\TestCase {
-
- /** @var \OCP\Comments\ICommentsManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $commentsManager;
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $userManager;
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $logger;
- /** @var EntityCollection */
- protected $collection;
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- protected $userSession;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected IUserManager&MockObject $userManager;
+ protected LoggerInterface&MockObject $logger;
+ protected IUserSession&MockObject $userSession;
+ protected EntityCollection $collection;
protected function setUp(): void {
parent::setUp();
- $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->logger = $this->getMockBuilder(LoggerInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->collection = new \OCA\DAV\Comments\EntityCollection(
+ $this->commentsManager = $this->createMock(ICommentsManager::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+
+ $this->collection = new EntityCollection(
'19',
'files',
$this->commentsManager,
@@ -68,7 +58,7 @@ class EntityCollectionTest extends \Test\TestCase {
);
$node = $this->collection->getChild('55');
- $this->assertTrue($node instanceof \OCA\DAV\Comments\CommentNode);
+ $this->assertInstanceOf(CommentNode::class, $node);
}
@@ -78,7 +68,7 @@ class EntityCollectionTest extends \Test\TestCase {
$this->commentsManager->expects($this->once())
->method('get')
->with('55')
- ->will($this->throwException(new \OCP\Comments\NotFoundException()));
+ ->willThrowException(new NotFoundException());
$this->collection->getChild('55');
}
@@ -95,8 +85,8 @@ class EntityCollectionTest extends \Test\TestCase {
$result = $this->collection->getChildren();
- $this->assertSame(count($result), 1);
- $this->assertTrue($result[0] instanceof \OCA\DAV\Comments\CommentNode);
+ $this->assertCount(1, $result);
+ $this->assertInstanceOf(CommentNode::class, $result[0]);
}
public function testFindChildren(): void {
@@ -112,8 +102,8 @@ class EntityCollectionTest extends \Test\TestCase {
$result = $this->collection->findChildren(5, 15, $dt);
- $this->assertSame(count($result), 1);
- $this->assertTrue($result[0] instanceof \OCA\DAV\Comments\CommentNode);
+ $this->assertCount(1, $result);
+ $this->assertInstanceOf(CommentNode::class, $result[0]);
}
public function testChildExistsTrue(): void {
@@ -124,7 +114,7 @@ class EntityCollectionTest extends \Test\TestCase {
$this->commentsManager->expects($this->once())
->method('get')
->with('44')
- ->will($this->throwException(new \OCP\Comments\NotFoundException()));
+ ->willThrowException(new NotFoundException());
$this->assertFalse($this->collection->childExists('44'));
}
diff --git a/apps/dav/tests/unit/Comments/EntityTypeCollectionTest.php b/apps/dav/tests/unit/Comments/EntityTypeCollectionTest.php
index 5ab9c38ecd0..e5178a3e786 100644
--- a/apps/dav/tests/unit/Comments/EntityTypeCollectionTest.php
+++ b/apps/dav/tests/unit/Comments/EntityTypeCollectionTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,52 +9,38 @@
namespace OCA\DAV\Tests\unit\Comments;
use OCA\DAV\Comments\EntityCollection as EntityCollectionImplemantation;
+use OCA\DAV\Comments\EntityTypeCollection;
use OCP\Comments\ICommentsManager;
use OCP\IUserManager;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
class EntityTypeCollectionTest extends \Test\TestCase {
-
- /** @var ICommentsManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $commentsManager;
- /** @var \OCP\IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $userManager;
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $logger;
- /** @var \OCA\DAV\Comments\EntityTypeCollection */
- protected $collection;
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- protected $userSession;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected IUserManager&MockObject $userManager;
+ protected LoggerInterface&MockObject $logger;
+ protected IUserSession&MockObject $userSession;
+ protected EntityTypeCollection $collection;
protected $childMap = [];
protected function setUp(): void {
parent::setUp();
- $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->logger = $this->getMockBuilder(LoggerInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $instance = $this;
-
- $this->collection = new \OCA\DAV\Comments\EntityTypeCollection(
+ $this->commentsManager = $this->createMock(ICommentsManager::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+
+ $this->collection = new EntityTypeCollection(
'files',
$this->commentsManager,
$this->userManager,
$this->userSession,
$this->logger,
- function ($child) use ($instance) {
- return !empty($instance->childMap[$child]);
+ function ($child) {
+ return !empty($this->childMap[$child]);
}
);
}
@@ -71,7 +58,7 @@ class EntityTypeCollectionTest extends \Test\TestCase {
$this->childMap[17] = true;
$ec = $this->collection->getChild('17');
- $this->assertTrue($ec instanceof EntityCollectionImplemantation);
+ $this->assertInstanceOf(EntityCollectionImplemantation::class, $ec);
}
diff --git a/apps/dav/tests/unit/Comments/RootCollectionTest.php b/apps/dav/tests/unit/Comments/RootCollectionTest.php
index 6da96be5818..9a05d996c8c 100644
--- a/apps/dav/tests/unit/Comments/RootCollectionTest.php
+++ b/apps/dav/tests/unit/Comments/RootCollectionTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -9,57 +10,41 @@ namespace OCA\DAV\Tests\unit\Comments;
use OC\EventDispatcher\EventDispatcher;
use OCA\DAV\Comments\EntityTypeCollection as EntityTypeCollectionImplementation;
+use OCA\DAV\Comments\RootCollection;
use OCP\Comments\CommentsEntityEvent;
use OCP\Comments\ICommentsManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
class RootCollectionTest extends \Test\TestCase {
-
- /** @var \OCP\Comments\ICommentsManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $commentsManager;
- /** @var \OCP\IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $userManager;
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $logger;
- /** @var \OCA\DAV\Comments\RootCollection */
- protected $collection;
- /** @var \OCP\IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- protected $userSession;
- /** @var IEventDispatcher */
- protected $dispatcher;
- /** @var \OCP\IUser|\PHPUnit\Framework\MockObject\MockObject */
- protected $user;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected IUserManager&MockObject $userManager;
+ protected LoggerInterface&MockObject $logger;
+ protected IUserSession&MockObject $userSession;
+ protected IEventDispatcher $dispatcher;
+ protected IUser&MockObject $user;
+ protected RootCollection $collection;
protected function setUp(): void {
parent::setUp();
- $this->user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->logger = $this->getMockBuilder(LoggerInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->user = $this->createMock(IUser::class);
+
+ $this->commentsManager = $this->createMock(ICommentsManager::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
$this->dispatcher = new EventDispatcher(
new \Symfony\Component\EventDispatcher\EventDispatcher(),
\OC::$server,
$this->logger
);
- $this->collection = new \OCA\DAV\Comments\RootCollection(
+ $this->collection = new RootCollection(
$this->commentsManager,
$this->userManager,
$this->userSession,
@@ -68,7 +53,7 @@ class RootCollectionTest extends \Test\TestCase {
);
}
- protected function prepareForInitCollections() {
+ protected function prepareForInitCollections(): void {
$this->user->expects($this->any())
->method('getUID')
->willReturn('alice');
@@ -101,7 +86,7 @@ class RootCollectionTest extends \Test\TestCase {
public function testGetChild(): void {
$this->prepareForInitCollections();
$etc = $this->collection->getChild('files');
- $this->assertTrue($etc instanceof EntityTypeCollectionImplementation);
+ $this->assertInstanceOf(EntityTypeCollectionImplementation::class, $etc);
}
@@ -124,7 +109,7 @@ class RootCollectionTest extends \Test\TestCase {
$children = $this->collection->getChildren();
$this->assertFalse(empty($children));
foreach ($children as $child) {
- $this->assertTrue($child instanceof EntityTypeCollectionImplementation);
+ $this->assertInstanceOf(EntityTypeCollectionImplementation::class, $child);
}
}
diff --git a/apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php b/apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php
index 4f3581d6071..8b8c775c8ec 100644
--- a/apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php
+++ b/apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -7,12 +8,14 @@
*/
namespace OCA\DAV\Tests\unit\Connector;
+use OCA\DAV\Connector\LegacyPublicAuth;
use OCP\IRequest;
use OCP\ISession;
use OCP\Security\Bruteforce\IThrottler;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
use OCP\Share\IShare;
+use PHPUnit\Framework\MockObject\MockObject;
/**
* Class LegacyPublicAuthTest
@@ -22,38 +25,22 @@ use OCP\Share\IShare;
* @package OCA\DAV\Tests\unit\Connector
*/
class LegacyPublicAuthTest extends \Test\TestCase {
-
- /** @var ISession|\PHPUnit\Framework\MockObject\MockObject */
- private $session;
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- private $shareManager;
- /** @var \OCA\DAV\Connector\LegacyPublicAuth */
- private $auth;
- /** @var IThrottler|\PHPUnit\Framework\MockObject\MockObject */
- private $throttler;
-
- /** @var string */
- private $oldUser;
+ private ISession&MockObject $session;
+ private IRequest&MockObject $request;
+ private IManager&MockObject $shareManager;
+ private IThrottler&MockObject $throttler;
+ private LegacyPublicAuth $auth;
+ private string|false $oldUser;
protected function setUp(): void {
parent::setUp();
- $this->session = $this->getMockBuilder(ISession::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->request = $this->getMockBuilder(IRequest::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->shareManager = $this->getMockBuilder(IManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->throttler = $this->getMockBuilder(IThrottler::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->auth = new \OCA\DAV\Connector\LegacyPublicAuth(
+ $this->session = $this->createMock(ISession::class);
+ $this->request = $this->createMock(IRequest::class);
+ $this->shareManager = $this->createMock(IManager::class);
+ $this->throttler = $this->createMock(IThrottler::class);
+
+ $this->auth = new LegacyPublicAuth(
$this->request,
$this->shareManager,
$this->session,
@@ -69,7 +56,9 @@ class LegacyPublicAuthTest extends \Test\TestCase {
// Set old user
\OC_User::setUserId($this->oldUser);
- \OC_Util::setupFS($this->oldUser);
+ if ($this->oldUser !== false) {
+ \OC_Util::setupFS($this->oldUser);
+ }
parent::tearDown();
}
@@ -85,9 +74,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
}
public function testShareNoPassword(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn(null);
$this->shareManager->expects($this->once())
@@ -100,9 +87,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
}
public function testSharePasswordFancyShareType(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(42);
@@ -117,9 +102,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
public function testSharePasswordRemote(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_REMOTE);
@@ -133,9 +116,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
}
public function testSharePasswordLinkValidPassword(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
@@ -155,9 +136,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
}
public function testSharePasswordMailValidPassword(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
@@ -177,9 +156,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
}
public function testInvalidSharePasswordLinkValidSession(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
$share->method('getId')->willReturn('42');
@@ -203,9 +180,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
}
public function testSharePasswordLinkInvalidSession(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
$share->method('getId')->willReturn('42');
@@ -230,9 +205,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
public function testSharePasswordMailInvalidSession(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
$share->method('getId')->willReturn('42');
diff --git a/apps/dav/tests/unit/Connector/Sabre/AuthTest.php b/apps/dav/tests/unit/Connector/Sabre/AuthTest.php
index c9868debb43..4b42a815708 100644
--- a/apps/dav/tests/unit/Connector/Sabre/AuthTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/AuthTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -7,12 +8,16 @@
*/
namespace OCA\DAV\Tests\unit\Connector\Sabre;
+use OC\Authentication\Exceptions\PasswordLoginForbiddenException;
use OC\Authentication\TwoFactorAuth\Manager;
use OC\User\Session;
+use OCA\DAV\Connector\Sabre\Auth;
+use OCA\DAV\Connector\Sabre\Exception\PasswordLoginForbidden;
use OCP\IRequest;
use OCP\ISession;
use OCP\IUser;
use OCP\Security\Bruteforce\IThrottler;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Server;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
@@ -25,34 +30,21 @@ use Test\TestCase;
* @group DB
*/
class AuthTest extends TestCase {
- /** @var ISession */
- private $session;
- /** @var \OCA\DAV\Connector\Sabre\Auth */
- private $auth;
- /** @var Session */
- private $userSession;
- /** @var IRequest */
- private $request;
- /** @var Manager */
- private $twoFactorManager;
- /** @var IThrottler */
- private $throttler;
+ private ISession&MockObject $session;
+ private Session&MockObject $userSession;
+ private IRequest&MockObject $request;
+ private Manager&MockObject $twoFactorManager;
+ private IThrottler&MockObject $throttler;
+ private Auth $auth;
protected function setUp(): void {
parent::setUp();
- $this->session = $this->getMockBuilder(ISession::class)
- ->disableOriginalConstructor()->getMock();
- $this->userSession = $this->getMockBuilder(Session::class)
- ->disableOriginalConstructor()->getMock();
- $this->request = $this->getMockBuilder(IRequest::class)
- ->disableOriginalConstructor()->getMock();
- $this->twoFactorManager = $this->getMockBuilder(Manager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->throttler = $this->getMockBuilder(IThrottler::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->auth = new \OCA\DAV\Connector\Sabre\Auth(
+ $this->session = $this->createMock(ISession::class);
+ $this->userSession = $this->createMock(Session::class);
+ $this->request = $this->createMock(IRequest::class);
+ $this->twoFactorManager = $this->createMock(Manager::class);
+ $this->throttler = $this->createMock(IThrottler::class);
+ $this->auth = new Auth(
$this->session,
$this->userSession,
$this->request,
@@ -68,7 +60,7 @@ class AuthTest extends TestCase {
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn(null);
- $this->assertFalse($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
+ $this->assertFalse(self::invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
}
public function testIsDavAuthenticatedWithWrongDavSession(): void {
@@ -78,7 +70,7 @@ class AuthTest extends TestCase {
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn('AnotherUser');
- $this->assertFalse($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
+ $this->assertFalse(self::invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
}
public function testIsDavAuthenticatedWithCorrectDavSession(): void {
@@ -88,13 +80,11 @@ class AuthTest extends TestCase {
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn('MyTestUser');
- $this->assertTrue($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
+ $this->assertTrue(self::invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
}
public function testValidateUserPassOfAlreadyDAVAuthenticatedUser(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->exactly(1))
->method('getUID')
->willReturn('MyTestUser');
@@ -115,13 +105,11 @@ class AuthTest extends TestCase {
->expects($this->once())
->method('close');
- $this->assertTrue($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
+ $this->assertTrue(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
}
public function testValidateUserPassOfInvalidDAVAuthenticatedUser(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('MyTestUser');
@@ -142,13 +130,11 @@ class AuthTest extends TestCase {
->expects($this->once())
->method('close');
- $this->assertFalse($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
+ $this->assertFalse(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
}
public function testValidateUserPassOfInvalidDAVAuthenticatedUserWithValidPassword(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->exactly(2))
->method('getUID')
->willReturn('MyTestUser');
@@ -178,7 +164,7 @@ class AuthTest extends TestCase {
->expects($this->once())
->method('close');
- $this->assertTrue($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
+ $this->assertTrue(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
}
public function testValidateUserPassWithInvalidPassword(): void {
@@ -195,12 +181,12 @@ class AuthTest extends TestCase {
->expects($this->once())
->method('close');
- $this->assertFalse($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
+ $this->assertFalse(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
}
public function testValidateUserPassWithPasswordLoginForbidden(): void {
- $this->expectException(\OCA\DAV\Connector\Sabre\Exception\PasswordLoginForbidden::class);
+ $this->expectException(PasswordLoginForbidden::class);
$this->userSession
->expects($this->once())
@@ -210,21 +196,17 @@ class AuthTest extends TestCase {
->expects($this->once())
->method('logClientIn')
->with('MyTestUser', 'MyTestPassword')
- ->will($this->throwException(new \OC\Authentication\Exceptions\PasswordLoginForbiddenException()));
+ ->willThrowException(new PasswordLoginForbiddenException());
$this->session
->expects($this->once())
->method('close');
- $this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']);
+ self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']);
}
public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenForNonGet(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -238,9 +220,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn(null);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('MyWrongDavUser');
@@ -262,12 +242,8 @@ class AuthTest extends TestCase {
}
public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenAndCorrectlyDavAuthenticated(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -285,9 +261,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn('LoggedInUser');
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('LoggedInUser');
@@ -307,12 +281,8 @@ class AuthTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
$this->expectExceptionMessage('2FA challenge not passed.');
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -330,9 +300,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn('LoggedInUser');
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('LoggedInUser');
@@ -356,12 +324,8 @@ class AuthTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
$this->expectExceptionMessage('CSRF check not passed.');
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -379,9 +343,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn('AnotherUser');
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('LoggedInUser');
@@ -397,12 +359,8 @@ class AuthTest extends TestCase {
}
public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenForNonGetAndDesktopClient(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -420,9 +378,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn(null);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('MyWrongDavUser');
@@ -439,12 +395,8 @@ class AuthTest extends TestCase {
}
public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenForGet(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -454,9 +406,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn(null);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('MyWrongDavUser');
@@ -474,12 +424,8 @@ class AuthTest extends TestCase {
}
public function testAuthenticateAlreadyLoggedInWithCsrfTokenForGet(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -489,9 +435,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn(null);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('MyWrongDavUser');
@@ -509,15 +453,9 @@ class AuthTest extends TestCase {
}
public function testAuthenticateNoBasicAuthenticateHeadersProvided(): void {
- $server = $this->getMockBuilder(Server::class)
- ->disableOriginalConstructor()
- ->getMock();
- $server->httpRequest = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $server->httpResponse = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $server = $this->createMock(Server::class);
+ $server->httpRequest = $this->createMock(RequestInterface::class);
+ $server->httpResponse = $this->createMock(ResponseInterface::class);
$response = $this->auth->check($server->httpRequest, $server->httpResponse);
$this->assertEquals([false, 'No \'Authorization: Basic\' header found. Either the client didn\'t send one, or the server is misconfigured'], $response);
}
@@ -527,39 +465,71 @@ class AuthTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
$this->expectExceptionMessage('Cannot authenticate over ajax calls');
- /** @var \Sabre\HTTP\RequestInterface $httpRequest */
- $httpRequest = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- /** @var \Sabre\HTTP\ResponseInterface $httpResponse */
- $httpResponse = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var \Sabre\HTTP\RequestInterface&MockObject $httpRequest */
+ $httpRequest = $this->createMock(RequestInterface::class);
+ /** @var \Sabre\HTTP\ResponseInterface&MockObject $httpResponse */
+ $httpResponse = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
->willReturn(false);
$httpRequest
+ ->expects($this->exactly(2))
+ ->method('getHeader')
+ ->willReturnMap([
+ ['X-Requested-With', 'XMLHttpRequest'],
+ ['Authorization', null],
+ ]);
+
+ $this->auth->check($httpRequest, $httpResponse);
+ }
+
+ public function testAuthenticateWithBasicAuthenticateHeadersProvidedWithAjax(): void {
+ // No CSRF
+ $this->request
->expects($this->once())
+ ->method('passesCSRFCheck')
+ ->willReturn(false);
+
+ /** @var \Sabre\HTTP\RequestInterface&MockObject $httpRequest */
+ $httpRequest = $this->createMock(RequestInterface::class);
+ /** @var \Sabre\HTTP\ResponseInterface&MockObject $httpResponse */
+ $httpResponse = $this->createMock(ResponseInterface::class);
+ $httpRequest
+ ->expects($this->any())
->method('getHeader')
- ->with('X-Requested-With')
- ->willReturn('XMLHttpRequest');
+ ->willReturnMap([
+ ['X-Requested-With', 'XMLHttpRequest'],
+ ['Authorization', 'basic dXNlcm5hbWU6cGFzc3dvcmQ='],
+ ]);
+
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->any())
+ ->method('getUID')
+ ->willReturn('MyDavUser');
+ $this->userSession
+ ->expects($this->any())
+ ->method('isLoggedIn')
+ ->willReturn(false);
+ $this->userSession
+ ->expects($this->once())
+ ->method('logClientIn')
+ ->with('username', 'password')
+ ->willReturn(true);
+ $this->userSession
+ ->expects($this->any())
+ ->method('getUser')
+ ->willReturn($user);
+
$this->auth->check($httpRequest, $httpResponse);
}
public function testAuthenticateNoBasicAuthenticateHeadersProvidedWithAjaxButUserIsStillLoggedIn(): void {
/** @var \Sabre\HTTP\RequestInterface $httpRequest */
- $httpRequest = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $httpRequest = $this->createMock(RequestInterface::class);
/** @var \Sabre\HTTP\ResponseInterface $httpResponse */
- $httpResponse = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- /** @var IUser */
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $httpResponse = $this->createMock(ResponseInterface::class);
+ $user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('MyTestUser');
$this->userSession
->expects($this->any())
@@ -590,34 +560,21 @@ class AuthTest extends TestCase {
}
public function testAuthenticateValidCredentials(): void {
- $server = $this->getMockBuilder(Server::class)
- ->disableOriginalConstructor()
- ->getMock();
- $server->httpRequest = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $server = $this->createMock(Server::class);
+ $server->httpRequest = $this->createMock(RequestInterface::class);
$server->httpRequest
- ->expects($this->exactly(2))
+ ->expects($this->once())
->method('getHeader')
- ->withConsecutive(
- ['X-Requested-With'],
- ['Authorization'],
- )
- ->willReturnOnConsecutiveCalls(
- null,
- 'basic dXNlcm5hbWU6cGFzc3dvcmQ=',
- );
- $server->httpResponse = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ ->with('Authorization')
+ ->willReturn('basic dXNlcm5hbWU6cGFzc3dvcmQ=');
+
+ $server->httpResponse = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->once())
->method('logClientIn')
->with('username', 'password')
->willReturn(true);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->exactly(2))
->method('getUID')
->willReturn('MyTestUser');
@@ -630,26 +587,16 @@ class AuthTest extends TestCase {
}
public function testAuthenticateInvalidCredentials(): void {
- $server = $this->getMockBuilder(Server::class)
- ->disableOriginalConstructor()
- ->getMock();
- $server->httpRequest = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $server = $this->createMock(Server::class);
+ $server->httpRequest = $this->createMock(RequestInterface::class);
$server->httpRequest
->expects($this->exactly(2))
->method('getHeader')
- ->withConsecutive(
- ['X-Requested-With'],
- ['Authorization'],
- )
- ->willReturnOnConsecutiveCalls(
- null,
- 'basic dXNlcm5hbWU6cGFzc3dvcmQ=',
- );
- $server->httpResponse = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ ->willReturnMap([
+ ['Authorization', 'basic dXNlcm5hbWU6cGFzc3dvcmQ='],
+ ['X-Requested-With', null],
+ ]);
+ $server->httpResponse = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->once())
->method('logClientIn')
diff --git a/apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php b/apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php
index 9922dee5e6e..1e6267d4cbb 100644
--- a/apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php
@@ -1,15 +1,20 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\DAV\Tests\unit\Connector\Sabre;
+use OC\User\Session;
use OCA\DAV\Connector\Sabre\BearerAuth;
+use OCP\IConfig;
use OCP\IRequest;
use OCP\ISession;
use OCP\IUser;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
use Test\TestCase;
@@ -18,26 +23,26 @@ use Test\TestCase;
* @group DB
*/
class BearerAuthTest extends TestCase {
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- private $userSession;
- /** @var ISession|\PHPUnit\Framework\MockObject\MockObject */
- private $session;
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
- /** @var BearerAuth */
- private $bearerAuth;
+ private IUserSession&MockObject $userSession;
+ private ISession&MockObject $session;
+ private IRequest&MockObject $request;
+ private BearerAuth $bearerAuth;
+
+ private IConfig&MockObject $config;
protected function setUp(): void {
parent::setUp();
- $this->userSession = $this->createMock(\OC\User\Session::class);
+ $this->userSession = $this->createMock(Session::class);
$this->session = $this->createMock(ISession::class);
$this->request = $this->createMock(IRequest::class);
+ $this->config = $this->createMock(IConfig::class);
$this->bearerAuth = new BearerAuth(
$this->userSession,
$this->session,
- $this->request
+ $this->request,
+ $this->config,
);
}
@@ -67,9 +72,9 @@ class BearerAuthTest extends TestCase {
}
public function testChallenge(): void {
- /** @var \PHPUnit\Framework\MockObject\MockObject|RequestInterface $request */
+ /** @var RequestInterface&MockObject $request */
$request = $this->createMock(RequestInterface::class);
- /** @var \PHPUnit\Framework\MockObject\MockObject|ResponseInterface $response */
+ /** @var ResponseInterface&MockObject $response */
$response = $this->createMock(ResponseInterface::class);
$result = $this->bearerAuth->challenge($request, $response);
$this->assertEmpty($result);
diff --git a/apps/dav/tests/unit/Connector/Sabre/BlockLegacyClientPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/BlockLegacyClientPluginTest.php
index 607ad71b11d..366c9475b1b 100644
--- a/apps/dav/tests/unit/Connector/Sabre/BlockLegacyClientPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/BlockLegacyClientPluginTest.php
@@ -10,42 +10,113 @@ declare(strict_types=1);
namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin;
+use OCA\Theming\ThemingDefaults;
use OCP\IConfig;
use PHPUnit\Framework\MockObject\MockObject;
use Sabre\HTTP\RequestInterface;
use Test\TestCase;
+enum ERROR_TYPE {
+ case MIN_ERROR;
+ case MAX_ERROR;
+ case NONE;
+}
+
/**
* Class BlockLegacyClientPluginTest
*
* @package OCA\DAV\Tests\unit\Connector\Sabre
*/
class BlockLegacyClientPluginTest extends TestCase {
- /** @var IConfig|MockObject */
- private $config;
- /** @var BlockLegacyClientPlugin */
- private $blockLegacyClientVersionPlugin;
+
+ private IConfig&MockObject $config;
+ private ThemingDefaults&MockObject $themingDefaults;
+ private BlockLegacyClientPlugin $blockLegacyClientVersionPlugin;
protected function setUp(): void {
parent::setUp();
$this->config = $this->createMock(IConfig::class);
- $this->blockLegacyClientVersionPlugin = new BlockLegacyClientPlugin($this->config);
+ $this->themingDefaults = $this->createMock(ThemingDefaults::class);
+ $this->blockLegacyClientVersionPlugin = new BlockLegacyClientPlugin(
+ $this->config,
+ $this->themingDefaults,
+ );
}
- public function oldDesktopClientProvider(): array {
+ public static function oldDesktopClientProvider(): array {
return [
- ['Mozilla/5.0 (Windows) mirall/1.5.0'],
- ['Mozilla/5.0 (Bogus Text) mirall/1.6.9'],
+ ['Mozilla/5.0 (Windows) mirall/1.5.0', ERROR_TYPE::MIN_ERROR],
+ ['Mozilla/5.0 (Bogus Text) mirall/1.6.9', ERROR_TYPE::MIN_ERROR],
+ ['Mozilla/5.0 (Windows) mirall/2.5.0', ERROR_TYPE::MAX_ERROR],
+ ['Mozilla/5.0 (Bogus Text) mirall/2.0.1', ERROR_TYPE::MAX_ERROR],
+ ['Mozilla/5.0 (Windows) mirall/2.0.0', ERROR_TYPE::NONE],
+ ['Mozilla/5.0 (Bogus Text) mirall/2.0.0', ERROR_TYPE::NONE],
];
}
+ #[\PHPUnit\Framework\Attributes\DataProvider('oldDesktopClientProvider')]
+ public function testBeforeHandlerException(string $userAgent, ERROR_TYPE $errorType): void {
+ $this->themingDefaults
+ ->expects($this->atMost(1))
+ ->method('getSyncClientUrl')
+ ->willReturn('https://nextcloud.com/install/#install-clients');
+
+ $this->config
+ ->expects($this->exactly(2))
+ ->method('getSystemValueString')
+ ->willReturnCallback(function (string $key) {
+ if ($key === 'minimum.supported.desktop.version') {
+ return '1.7.0';
+ }
+ return '2.0.0';
+ });
+
+ if ($errorType !== ERROR_TYPE::NONE) {
+ $errorString = $errorType === ERROR_TYPE::MIN_ERROR
+ ? 'This version of the client is unsupported. Upgrade to <a href="https://nextcloud.com/install/#install-clients">version 1.7.0 or later</a>.'
+ : 'This version of the client is unsupported. Downgrade to <a href="https://nextcloud.com/install/#install-clients">version 2.0.0 or earlier</a>.';
+ $this->expectException(\Sabre\DAV\Exception\Forbidden::class);
+ $this->expectExceptionMessage($errorString);
+ }
+
+ /** @var RequestInterface|MockObject $request */
+ $request = $this->createMock(RequestInterface::class);
+ $request
+ ->expects($this->once())
+ ->method('getHeader')
+ ->with('User-Agent')
+ ->willReturn($userAgent);
+
+ $this->blockLegacyClientVersionPlugin->beforeHandler($request);
+ }
+
/**
- * @dataProvider oldDesktopClientProvider
+ * Ensure that there is no room for XSS attack through configured URL / version
*/
- public function testBeforeHandlerException(string $userAgent): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('oldDesktopClientProvider')]
+ public function testBeforeHandlerExceptionPreventXSSAttack(string $userAgent, ERROR_TYPE $errorType): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
- $this->expectExceptionMessage('Unsupported client version.');
+
+ $this->themingDefaults
+ ->expects($this->atMost(1))
+ ->method('getSyncClientUrl')
+ ->willReturn('https://example.com"><script>alter("hacked");</script>');
+
+ $this->config
+ ->expects($this->exactly(2))
+ ->method('getSystemValueString')
+ ->willReturnCallback(function (string $key) {
+ if ($key === 'minimum.supported.desktop.version') {
+ return '1.7.0 <script>alert("unsafe")</script>';
+ }
+ return '2.0.0 <script>alert("unsafe")</script>';
+ });
+
+ $errorString = $errorType === ERROR_TYPE::MIN_ERROR
+ ? 'This version of the client is unsupported. Upgrade to <a href="https://example.com&quot;&gt;&lt;script&gt;alter(&quot;hacked&quot;);&lt;/script&gt;">version 1.7.0 &lt;script&gt;alert(&quot;unsafe&quot;)&lt;/script&gt; or later</a>.'
+ : 'This version of the client is unsupported. Downgrade to <a href="https://example.com&quot;&gt;&lt;script&gt;alter(&quot;hacked&quot;);&lt;/script&gt;">version 2.0.0 &lt;script&gt;alert(&quot;unsafe&quot;)&lt;/script&gt; or earlier</a>.';
+ $this->expectExceptionMessage($errorString);
/** @var RequestInterface|MockObject $request */
$request = $this->createMock('\Sabre\HTTP\RequestInterface');
@@ -55,26 +126,21 @@ class BlockLegacyClientPluginTest extends TestCase {
->with('User-Agent')
->willReturn($userAgent);
- $this->config
- ->expects($this->once())
- ->method('getSystemValue')
- ->with('minimum.supported.desktop.version', '2.3.0')
- ->willReturn('1.7.0');
-
$this->blockLegacyClientVersionPlugin->beforeHandler($request);
}
- public function newAndAlternateDesktopClientProvider(): array {
+ public static function newAndAlternateDesktopClientProvider(): array {
return [
['Mozilla/5.0 (Windows) mirall/1.7.0'],
['Mozilla/5.0 (Bogus Text) mirall/1.9.3'],
['Mozilla/5.0 (Not Our Client But Old Version) LegacySync/1.1.0'],
+ ['Mozilla/5.0 (Windows) mirall/4.7.0'],
+ ['Mozilla/5.0 (Bogus Text) mirall/3.9.3'],
+ ['Mozilla/5.0 (Not Our Client But Old Version) LegacySync/45.0.0'],
];
}
- /**
- * @dataProvider newAndAlternateDesktopClientProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('newAndAlternateDesktopClientProvider')]
public function testBeforeHandlerSuccess(string $userAgent): void {
/** @var RequestInterface|MockObject $request */
$request = $this->createMock(RequestInterface::class);
@@ -85,10 +151,14 @@ class BlockLegacyClientPluginTest extends TestCase {
->willReturn($userAgent);
$this->config
- ->expects($this->once())
- ->method('getSystemValue')
- ->with('minimum.supported.desktop.version', '2.3.0')
- ->willReturn('1.7.0');
+ ->expects($this->exactly(2))
+ ->method('getSystemValueString')
+ ->willReturnCallback(function (string $key) {
+ if ($key === 'minimum.supported.desktop.version') {
+ return '1.7.0';
+ }
+ return '10.0.0';
+ });
$this->blockLegacyClientVersionPlugin->beforeHandler($request);
}
@@ -101,6 +171,7 @@ class BlockLegacyClientPluginTest extends TestCase {
->method('getHeader')
->with('User-Agent')
->willReturn(null);
+
$this->blockLegacyClientVersionPlugin->beforeHandler($request);
}
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/CommentsPropertiesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/CommentsPropertiesPluginTest.php
index c2167214451..a934d6401c2 100644
--- a/apps/dav/tests/unit/Connector/Sabre/CommentsPropertiesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/CommentsPropertiesPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,62 +9,43 @@
namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OCA\DAV\Connector\Sabre\CommentPropertiesPlugin as CommentPropertiesPluginImplementation;
+use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\File;
use OCP\Comments\ICommentsManager;
use OCP\IUser;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\PropFind;
+use Sabre\DAV\Server;
class CommentsPropertiesPluginTest extends \Test\TestCase {
-
- /** @var CommentPropertiesPluginImplementation */
- protected $plugin;
- protected $commentsManager;
- protected $userSession;
- protected $server;
+ protected CommentPropertiesPluginImplementation $plugin;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected IUserSession&MockObject $userSession;
+ protected Server&MockObject $server;
protected function setUp(): void {
parent::setUp();
- $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->server = $this->getMockBuilder('\Sabre\DAV\Server')
- ->disableOriginalConstructor()
- ->getMock();
+ $this->commentsManager = $this->createMock(ICommentsManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->server = $this->createMock(Server::class);
$this->plugin = new CommentPropertiesPluginImplementation($this->commentsManager, $this->userSession);
$this->plugin->initialize($this->server);
}
- public function nodeProvider() {
- $mocks = [];
- foreach (['\OCA\DAV\Connector\Sabre\File', '\OCA\DAV\Connector\Sabre\Directory', '\Sabre\DAV\INode'] as $class) {
- $mocks[] = $this->getMockBuilder($class)
- ->disableOriginalConstructor()
- ->getMock();
- }
-
+ public static function nodeProvider(): array {
return [
- [$mocks[0], true],
- [$mocks[1], true],
- [$mocks[2], false]
+ [File::class, true],
+ [Directory::class, true],
+ [\Sabre\DAV\INode::class, false]
];
}
- /**
- * @dataProvider nodeProvider
- * @param $node
- * @param $expectedSuccessful
- */
- public function testHandleGetProperties($node, $expectedSuccessful): void {
- $propFind = $this->getMockBuilder(PropFind::class)
- ->disableOriginalConstructor()
- ->getMock();
+ #[\PHPUnit\Framework\Attributes\DataProvider('nodeProvider')]
+ public function testHandleGetProperties(string $class, bool $expectedSuccessful): void {
+ $propFind = $this->createMock(PropFind::class);
if ($expectedSuccessful) {
$propFind->expects($this->exactly(3))
@@ -73,10 +55,11 @@ class CommentsPropertiesPluginTest extends \Test\TestCase {
->method('handle');
}
+ $node = $this->createMock($class);
$this->plugin->handleGetProperties($propFind, $node);
}
- public function baseUriProvider() {
+ public static function baseUriProvider(): array {
return [
['owncloud/remote.php/webdav/', '4567', 'owncloud/remote.php/dav/comments/files/4567'],
['owncloud/remote.php/files/', '4567', 'owncloud/remote.php/dav/comments/files/4567'],
@@ -84,16 +67,9 @@ class CommentsPropertiesPluginTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider baseUriProvider
- * @param $baseUri
- * @param $fid
- * @param $expectedHref
- */
- public function testGetCommentsLink($baseUri, $fid, $expectedHref): void {
- $node = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ #[\PHPUnit\Framework\Attributes\DataProvider('baseUriProvider')]
+ public function testGetCommentsLink(string $baseUri, string $fid, ?string $expectedHref): void {
+ $node = $this->createMock(File::class);
$node->expects($this->any())
->method('getId')
->willReturn($fid);
@@ -106,29 +82,23 @@ class CommentsPropertiesPluginTest extends \Test\TestCase {
$this->assertSame($expectedHref, $href);
}
- public function userProvider() {
+ public static function userProvider(): array {
return [
- [
- $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock()
- ],
+ [IUser::class],
[null]
];
}
- /**
- * @dataProvider userProvider
- * @param $user
- */
- public function testGetUnreadCount($user): void {
- $node = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ #[\PHPUnit\Framework\Attributes\DataProvider('userProvider')]
+ public function testGetUnreadCount(?string $user): void {
+ $node = $this->createMock(File::class);
$node->expects($this->any())
->method('getId')
->willReturn('4567');
+ if ($user !== null) {
+ $user = $this->createMock($user);
+ }
$this->userSession->expects($this->once())
->method('getUser')
->willReturn($user);
diff --git a/apps/dav/tests/unit/Connector/Sabre/CopyEtagHeaderPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/CopyEtagHeaderPluginTest.php
index bc19e071ee7..7067cf335ed 100644
--- a/apps/dav/tests/unit/Connector/Sabre/CopyEtagHeaderPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/CopyEtagHeaderPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -15,12 +16,8 @@ use Sabre\DAV\Tree;
use Test\TestCase;
class CopyEtagHeaderPluginTest extends TestCase {
-
- /** @var CopyEtagHeaderPlugin */
- private $plugin;
-
- /** @var Server */
- private $server;
+ private CopyEtagHeaderPlugin $plugin;
+ private Server $server;
protected function setUp(): void {
parent::setUp();
@@ -62,15 +59,11 @@ class CopyEtagHeaderPluginTest extends TestCase {
}
public function testAfterMove(): void {
- $node = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(File::class);
$node->expects($this->once())
->method('getETag')
->willReturn('123456');
- $tree = $this->getMockBuilder(Tree::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $tree = $this->createMock(Tree::class);
$tree->expects($this->once())
->method('getNodeForPath')
->with('test.txt')
diff --git a/apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php b/apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php
index 4d6e1f13d5f..cafbdd3ca40 100644
--- a/apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -7,9 +8,15 @@
*/
namespace OCA\DAV\Tests\unit\Connector\Sabre;
+use OCA\DAV\CalDAV\DefaultCalendarValidator;
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\File;
+use OCA\DAV\DAV\CustomPropertiesBackend;
+use OCA\DAV\Db\PropertyMapper;
+use OCP\IDBConnection;
use OCP\IUser;
+use OCP\Server;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Tree;
/**
@@ -20,56 +27,42 @@ use Sabre\DAV\Tree;
* @package OCA\DAV\Tests\unit\Connector\Sabre
*/
class CustomPropertiesBackendTest extends \Test\TestCase {
-
- /**
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var \Sabre\DAV\Tree
- */
- private $tree;
-
- /**
- * @var \OCA\DAV\DAV\CustomPropertiesBackend
- */
- private $plugin;
-
- /**
- * @var \OCP\IUser
- */
- private $user;
+ private \Sabre\DAV\Server $server;
+ private \Sabre\DAV\Tree&MockObject $tree;
+ private IUser&MockObject $user;
+ private DefaultCalendarValidator&MockObject $defaultCalendarValidator;
+ private CustomPropertiesBackend $plugin;
protected function setUp(): void {
parent::setUp();
+
$this->server = new \Sabre\DAV\Server();
- $this->tree = $this->getMockBuilder(Tree::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->tree = $this->createMock(Tree::class);
- $userId = $this->getUniqueID('testcustompropertiesuser');
+ $userId = self::getUniqueID('testcustompropertiesuser');
- $this->user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->user = $this->createMock(IUser::class);
$this->user->expects($this->any())
->method('getUID')
->willReturn($userId);
- $this->plugin = new \OCA\DAV\DAV\CustomPropertiesBackend(
+ $this->defaultCalendarValidator = $this->createMock(DefaultCalendarValidator::class);
+
+ $this->plugin = new CustomPropertiesBackend(
$this->server,
$this->tree,
- \OC::$server->getDatabaseConnection(),
- $this->user
+ Server::get(IDBConnection::class),
+ $this->user,
+ Server::get(PropertyMapper::class),
+ $this->defaultCalendarValidator,
);
}
protected function tearDown(): void {
- $connection = \OC::$server->getDatabaseConnection();
+ $connection = Server::get(IDBConnection::class);
$deleteStatement = $connection->prepare(
- 'DELETE FROM `*PREFIX*properties`' .
- ' WHERE `userid` = ?'
+ 'DELETE FROM `*PREFIX*properties`'
+ . ' WHERE `userid` = ?'
);
$deleteStatement->execute(
[
@@ -77,12 +70,12 @@ class CustomPropertiesBackendTest extends \Test\TestCase {
]
);
$deleteStatement->closeCursor();
+
+ parent::tearDown();
}
- private function createTestNode($class) {
- $node = $this->getMockBuilder($class)
- ->disableOriginalConstructor()
- ->getMock();
+ private function createTestNode(string $class) {
+ $node = $this->createMock($class);
$node->expects($this->any())
->method('getId')
->willReturn(123);
diff --git a/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php b/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php
index 3eca9b7ac1c..421ee1bdc12 100644
--- a/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php
@@ -1,11 +1,12 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
-namespace OCA\DAV\Tests\Unit\Connector\Sabre;
+namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OC\Files\FileInfo;
use OC\Files\Filesystem;
@@ -13,20 +14,23 @@ use OC\Files\Node\Node;
use OC\Files\Storage\Wrapper\Quota;
use OC\Files\View;
use OCA\DAV\Connector\Sabre\Directory;
+use OCA\DAV\Connector\Sabre\Exception\Forbidden;
+use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
+use OCA\Files_Sharing\External\Storage;
use OCP\Constants;
use OCP\Files\ForbiddenException;
+use OCP\Files\InvalidPathException;
use OCP\Files\Mount\IMountPoint;
+use OCP\Files\StorageNotAvailableException;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\Traits\UserTrait;
-class TestViewDirectory extends \OC\Files\View {
- private $updatables;
- private $deletables;
- private $canRename;
-
- public function __construct($updatables, $deletables, $canRename = true) {
- $this->updatables = $updatables;
- $this->deletables = $deletables;
- $this->canRename = $canRename;
+class TestViewDirectory extends View {
+ public function __construct(
+ private $updatables,
+ private $deletables,
+ private $canRename = true,
+ ) {
}
public function isUpdatable($path) {
@@ -41,7 +45,7 @@ class TestViewDirectory extends \OC\Files\View {
return $this->deletables[$path];
}
- public function rename($path1, $path2) {
+ public function rename($source, $target, array $options = []) {
return $this->canRename;
}
@@ -57,29 +61,27 @@ class TestViewDirectory extends \OC\Files\View {
class DirectoryTest extends \Test\TestCase {
use UserTrait;
- /** @var \OC\Files\View | \PHPUnit\Framework\MockObject\MockObject */
- private $view;
- /** @var \OC\Files\FileInfo | \PHPUnit\Framework\MockObject\MockObject */
- private $info;
+ private View&MockObject $view;
+ private FileInfo&MockObject $info;
protected function setUp(): void {
parent::setUp();
- $this->view = $this->createMock('OC\Files\View');
- $this->info = $this->createMock('OC\Files\FileInfo');
+ $this->view = $this->createMock(View::class);
+ $this->info = $this->createMock(FileInfo::class);
$this->info->method('isReadable')
->willReturn(true);
$this->info->method('getType')
->willReturn(Node::TYPE_FOLDER);
$this->info->method('getName')
- ->willReturn("folder");
+ ->willReturn('folder');
$this->info->method('getPath')
- ->willReturn("/admin/files/folder");
+ ->willReturn('/admin/files/folder');
$this->info->method('getPermissions')
->willReturn(Constants::PERMISSION_READ);
}
- private function getDir($path = '/') {
+ private function getDir(string $path = '/'): Directory {
$this->view->expects($this->once())
->method('getRelativePath')
->willReturn($path);
@@ -106,7 +108,7 @@ class DirectoryTest extends \Test\TestCase {
public function testDeleteForbidden(): void {
- $this->expectException(\OCA\DAV\Connector\Sabre\Exception\Forbidden::class);
+ $this->expectException(Forbidden::class);
// deletion allowed
$this->info->expects($this->once())
@@ -172,12 +174,8 @@ class DirectoryTest extends \Test\TestCase {
}
public function testGetChildren(): void {
- $info1 = $this->getMockBuilder(FileInfo::class)
- ->disableOriginalConstructor()
- ->getMock();
- $info2 = $this->getMockBuilder(FileInfo::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $info1 = $this->createMock(FileInfo::class);
+ $info2 = $this->createMock(FileInfo::class);
$info1->method('getName')
->willReturn('first');
$info1->method('getPath')
@@ -212,7 +210,7 @@ class DirectoryTest extends \Test\TestCase {
$dir = new Directory($this->view, $this->info);
$nodes = $dir->getChildren();
- $this->assertEquals(2, count($nodes));
+ $this->assertCount(2, $nodes);
// calling a second time just returns the cached values,
// does not call getDirectoryContents again
@@ -250,7 +248,7 @@ class DirectoryTest extends \Test\TestCase {
$this->view->expects($this->once())
->method('getFileInfo')
- ->willThrowException(new \OCP\Files\StorageNotAvailableException());
+ ->willThrowException(new StorageNotAvailableException());
$dir = new Directory($this->view, $this->info);
$dir->getChild('.');
@@ -258,11 +256,11 @@ class DirectoryTest extends \Test\TestCase {
public function testGetChildThrowInvalidPath(): void {
- $this->expectException(\OCA\DAV\Connector\Sabre\Exception\InvalidPath::class);
+ $this->expectException(InvalidPath::class);
$this->view->expects($this->once())
->method('verifyPath')
- ->willThrowException(new \OCP\Files\InvalidPathException());
+ ->willThrowException(new InvalidPathException());
$this->view->expects($this->never())
->method('getFileInfo');
@@ -271,20 +269,19 @@ class DirectoryTest extends \Test\TestCase {
}
public function testGetQuotaInfoUnlimited(): void {
- self::createUser('user', 'password');
+ $this->createUser('user', 'password');
self::loginAsUser('user');
$mountPoint = $this->createMock(IMountPoint::class);
- $storage = $this->getMockBuilder(Quota::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $storage = $this->createMock(Quota::class);
$mountPoint->method('getStorage')
->willReturn($storage);
$storage->expects($this->any())
->method('instanceOfStorage')
->willReturnMap([
- '\OCA\Files_Sharing\SharedStorage' => false,
- '\OC\Files\Storage\Wrapper\Quota' => false,
+ ['\OCA\Files_Sharing\SharedStorage', false],
+ ['\OC\Files\Storage\Wrapper\Quota', false],
+ [Storage::class, false],
]);
$storage->expects($this->once())
@@ -314,6 +311,10 @@ class DirectoryTest extends \Test\TestCase {
->method('getRelativePath')
->willReturn('/foo');
+ $this->info->expects($this->once())
+ ->method('getInternalPath')
+ ->willReturn('/foo');
+
$mountPoint->method('getMountPoint')
->willReturn('/user/files/mymountpoint');
@@ -322,12 +323,10 @@ class DirectoryTest extends \Test\TestCase {
}
public function testGetQuotaInfoSpecific(): void {
- self::createUser('user', 'password');
+ $this->createUser('user', 'password');
self::loginAsUser('user');
$mountPoint = $this->createMock(IMountPoint::class);
- $storage = $this->getMockBuilder(Quota::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $storage = $this->createMock(Quota::class);
$mountPoint->method('getStorage')
->willReturn($storage);
@@ -336,6 +335,7 @@ class DirectoryTest extends \Test\TestCase {
->willReturnMap([
['\OCA\Files_Sharing\SharedStorage', false],
['\OC\Files\Storage\Wrapper\Quota', true],
+ [Storage::class, false],
]);
$storage->expects($this->once())
@@ -358,6 +358,10 @@ class DirectoryTest extends \Test\TestCase {
->method('getMountPoint')
->willReturn($mountPoint);
+ $this->info->expects($this->once())
+ ->method('getInternalPath')
+ ->willReturn('/foo');
+
$mountPoint->method('getMountPoint')
->willReturn('/user/files/mymountpoint');
@@ -369,39 +373,33 @@ class DirectoryTest extends \Test\TestCase {
$this->assertEquals([200, 800], $dir->getQuotaInfo()); //200 used, 800 free
}
- /**
- * @dataProvider moveFailedProvider
- */
- public function testMoveFailed($source, $destination, $updatables, $deletables): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('moveFailedProvider')]
+ public function testMoveFailed(string $source, string $destination, array $updatables, array $deletables): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->moveTest($source, $destination, $updatables, $deletables);
}
- /**
- * @dataProvider moveSuccessProvider
- */
- public function testMoveSuccess($source, $destination, $updatables, $deletables): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('moveSuccessProvider')]
+ public function testMoveSuccess(string $source, string $destination, array $updatables, array $deletables): void {
$this->moveTest($source, $destination, $updatables, $deletables);
$this->addToAssertionCount(1);
}
- /**
- * @dataProvider moveFailedInvalidCharsProvider
- */
- public function testMoveFailedInvalidChars($source, $destination, $updatables, $deletables): void {
- $this->expectException(\OCA\DAV\Connector\Sabre\Exception\InvalidPath::class);
+ #[\PHPUnit\Framework\Attributes\DataProvider('moveFailedInvalidCharsProvider')]
+ public function testMoveFailedInvalidChars(string $source, string $destination, array $updatables, array $deletables): void {
+ $this->expectException(InvalidPath::class);
$this->moveTest($source, $destination, $updatables, $deletables);
}
- public function moveFailedInvalidCharsProvider() {
+ public static function moveFailedInvalidCharsProvider(): array {
return [
- ['a/b', 'a/*', ['a' => true, 'a/b' => true, 'a/c*' => false], []],
+ ['a/valid', "a/i\nvalid", ['a' => true, 'a/valid' => true, 'a/c*' => false], []],
];
}
- public function moveFailedProvider() {
+ public static function moveFailedProvider(): array {
return [
['a/b', 'a/c', ['a' => false, 'a/b' => false, 'a/c' => false], []],
['a/b', 'b/b', ['a' => false, 'a/b' => false, 'b' => false, 'b/b' => false], []],
@@ -412,7 +410,7 @@ class DirectoryTest extends \Test\TestCase {
];
}
- public function moveSuccessProvider() {
+ public static function moveSuccessProvider(): array {
return [
['a/b', 'b/b', ['a' => true, 'a/b' => true, 'b' => true, 'b/b' => false], ['a/b' => true]],
// older files with special chars can still be renamed to valid names
@@ -420,12 +418,7 @@ class DirectoryTest extends \Test\TestCase {
];
}
- /**
- * @param $source
- * @param $destination
- * @param $updatables
- */
- private function moveTest($source, $destination, $updatables, $deletables): void {
+ private function moveTest(string $source, string $destination, array $updatables, array $deletables): void {
$view = new TestViewDirectory($updatables, $deletables);
$sourceInfo = new FileInfo($source, null, null, [
@@ -437,7 +430,7 @@ class DirectoryTest extends \Test\TestCase {
$sourceNode = new Directory($view, $sourceInfo);
$targetNode = $this->getMockBuilder(Directory::class)
- ->setMethods(['childExists'])
+ ->onlyMethods(['childExists'])
->setConstructorArgs([$view, $targetInfo])
->getMock();
$targetNode->expects($this->any())->method('childExists')
@@ -463,7 +456,7 @@ class DirectoryTest extends \Test\TestCase {
$sourceNode = new Directory($view, $sourceInfo);
$targetNode = $this->getMockBuilder(Directory::class)
- ->setMethods(['childExists'])
+ ->onlyMethods(['childExists'])
->setConstructorArgs([$view, $targetInfo])
->getMock();
$targetNode->expects($this->once())->method('childExists')
diff --git a/apps/dav/tests/unit/Connector/Sabre/DummyGetResponsePluginTest.php b/apps/dav/tests/unit/Connector/Sabre/DummyGetResponsePluginTest.php
index 03c31dc47f8..2d688d64600 100644
--- a/apps/dav/tests/unit/Connector/Sabre/DummyGetResponsePluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/DummyGetResponsePluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -19,8 +20,7 @@ use Test\TestCase;
* @package OCA\DAV\Tests\unit\Connector\Sabre
*/
class DummyGetResponsePluginTest extends TestCase {
- /** @var DummyGetResponsePlugin */
- private $dummyGetResponsePlugin;
+ private DummyGetResponsePlugin $dummyGetResponsePlugin;
protected function setUp(): void {
parent::setUp();
@@ -29,10 +29,7 @@ class DummyGetResponsePluginTest extends TestCase {
}
public function testInitialize(): void {
- /** @var Server $server */
- $server = $this->getMockBuilder(Server::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $server = $this->createMock(Server::class);
$server
->expects($this->once())
->method('on')
@@ -44,13 +41,9 @@ class DummyGetResponsePluginTest extends TestCase {
public function testHttpGet(): void {
/** @var \Sabre\HTTP\RequestInterface $request */
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
/** @var \Sabre\HTTP\ResponseInterface $response */
- $response = $server = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $response = $this->createMock(ResponseInterface::class);
$response
->expects($this->once())
->method('setBody');
diff --git a/apps/dav/tests/unit/Connector/Sabre/Exception/ForbiddenTest.php b/apps/dav/tests/unit/Connector/Sabre/Exception/ForbiddenTest.php
index 74f90507bb3..2f9e0ae9196 100644
--- a/apps/dav/tests/unit/Connector/Sabre/Exception/ForbiddenTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/Exception/ForbiddenTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,6 +9,7 @@
namespace OCA\DAV\Tests\unit\Connector\Sabre\Exception;
use OCA\DAV\Connector\Sabre\Exception\Forbidden;
+use Sabre\DAV\Server;
class ForbiddenTest extends \Test\TestCase {
public function testSerialization(): void {
@@ -20,7 +22,7 @@ class ForbiddenTest extends \Test\TestCase {
$DOM->appendChild($error);
// serialize the exception
- $message = "1234567890";
+ $message = '1234567890';
$retry = false;
$expectedXml = <<<EOD
<?xml version="1.0" encoding="utf-8"?>
@@ -32,9 +34,7 @@ class ForbiddenTest extends \Test\TestCase {
EOD;
$ex = new Forbidden($message, $retry);
- $server = $this->getMockBuilder('Sabre\DAV\Server')
- ->disableOriginalConstructor()
- ->getMock();
+ $server = $this->createMock(Server::class);
$ex->serialize($server, $error);
// assert
diff --git a/apps/dav/tests/unit/Connector/Sabre/Exception/InvalidPathTest.php b/apps/dav/tests/unit/Connector/Sabre/Exception/InvalidPathTest.php
index 3da0c41b7b3..6f62bef86a3 100644
--- a/apps/dav/tests/unit/Connector/Sabre/Exception/InvalidPathTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/Exception/InvalidPathTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,6 +9,7 @@
namespace OCA\DAV\Tests\unit\Connector\Sabre\Exception;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
+use Sabre\DAV\Server;
class InvalidPathTest extends \Test\TestCase {
public function testSerialization(): void {
@@ -20,7 +22,7 @@ class InvalidPathTest extends \Test\TestCase {
$DOM->appendChild($error);
// serialize the exception
- $message = "1234567890";
+ $message = '1234567890';
$retry = false;
$expectedXml = <<<EOD
<?xml version="1.0" encoding="utf-8"?>
@@ -32,9 +34,7 @@ class InvalidPathTest extends \Test\TestCase {
EOD;
$ex = new InvalidPath($message, $retry);
- $server = $this->getMockBuilder('Sabre\DAV\Server')
- ->disableOriginalConstructor()
- ->getMock();
+ $server = $this->createMock(Server::class);
$ex->serialize($server, $error);
// assert
diff --git a/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php
index 1d50fb2fb9a..416ac8a75c9 100644
--- a/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -11,21 +12,16 @@ use OC\SystemConfig;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
use OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin;
use OCA\DAV\Exception\ServerMaintenanceMode;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\Server;
use Test\TestCase;
class ExceptionLoggerPluginTest extends TestCase {
-
- /** @var Server */
- private $server;
-
- /** @var ExceptionLoggerPlugin */
- private $plugin;
-
- /** @var LoggerInterface | \PHPUnit\Framework\MockObject\MockObject */
- private $logger;
+ private Server $server;
+ private ExceptionLoggerPlugin $plugin;
+ private LoggerInterface&MockObject $logger;
private function init(): void {
$config = $this->createMock(SystemConfig::class);
@@ -46,9 +42,7 @@ class ExceptionLoggerPluginTest extends TestCase {
$this->plugin->initialize($this->server);
}
- /**
- * @dataProvider providesExceptions
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesExceptions')]
public function testLogging(string $expectedLogLevel, \Throwable $e): void {
$this->init();
@@ -59,7 +53,7 @@ class ExceptionLoggerPluginTest extends TestCase {
$this->plugin->logException($e);
}
- public function providesExceptions() {
+ public static function providesExceptions(): array {
return [
['debug', new NotFound()],
['debug', new ServerMaintenanceMode('System is in maintenance mode.')],
diff --git a/apps/dav/tests/unit/Connector/Sabre/FakeLockerPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/FakeLockerPluginTest.php
index 40ebc69e42d..366932137f4 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FakeLockerPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FakeLockerPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -22,8 +23,7 @@ use Test\TestCase;
* @package OCA\DAV\Tests\unit\Connector\Sabre
*/
class FakeLockerPluginTest extends TestCase {
- /** @var FakeLockerPlugin */
- private $fakeLockerPlugin;
+ private FakeLockerPlugin $fakeLockerPlugin;
protected function setUp(): void {
parent::setUp();
@@ -32,18 +32,19 @@ class FakeLockerPluginTest extends TestCase {
public function testInitialize(): void {
/** @var Server $server */
- $server = $this->getMockBuilder(Server::class)
- ->disableOriginalConstructor()
- ->getMock();
- $server
- ->expects($this->exactly(4))
+ $server = $this->createMock(Server::class);
+ $calls = [
+ ['method:LOCK', [$this->fakeLockerPlugin, 'fakeLockProvider'], 1],
+ ['method:UNLOCK', [$this->fakeLockerPlugin, 'fakeUnlockProvider'], 1],
+ ['propFind', [$this->fakeLockerPlugin, 'propFind'], 100],
+ ['validateTokens', [$this->fakeLockerPlugin, 'validateTokens'], 100],
+ ];
+ $server->expects($this->exactly(count($calls)))
->method('on')
- ->withConsecutive(
- ['method:LOCK', [$this->fakeLockerPlugin, 'fakeLockProvider'], 1],
- ['method:UNLOCK', [$this->fakeLockerPlugin, 'fakeUnlockProvider'], 1],
- ['propFind', [$this->fakeLockerPlugin, 'propFind']],
- ['validateTokens', [$this->fakeLockerPlugin, 'validateTokens']],
- );
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$this->fakeLockerPlugin->initialize($server);
}
@@ -64,24 +65,24 @@ class FakeLockerPluginTest extends TestCase {
}
public function testPropFind(): void {
- $propFind = $this->getMockBuilder(PropFind::class)
- ->disableOriginalConstructor()
- ->getMock();
- $node = $this->getMockBuilder(INode::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $propFind = $this->createMock(PropFind::class);
+ $node = $this->createMock(INode::class);
- $propFind->expects($this->exactly(2))
+ $calls = [
+ '{DAV:}supportedlock',
+ '{DAV:}lockdiscovery',
+ ];
+ $propFind->expects($this->exactly(count($calls)))
->method('handle')
- ->withConsecutive(
- ['{DAV:}supportedlock'],
- ['{DAV:}lockdiscovery'],
- );
+ ->willReturnCallback(function ($propertyName) use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, $propertyName);
+ });
$this->fakeLockerPlugin->propFind($propFind, $node);
}
- public function tokenDataProvider() {
+ public static function tokenDataProvider(): array {
return [
[
[
@@ -118,23 +119,15 @@ class FakeLockerPluginTest extends TestCase {
];
}
- /**
- * @dataProvider tokenDataProvider
- * @param array $input
- * @param array $expected
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('tokenDataProvider')]
public function testValidateTokens(array $input, array $expected): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
$this->fakeLockerPlugin->validateTokens($request, $input);
$this->assertSame($expected, $input);
}
public function testFakeLockProvider(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
$response = new Response();
$server = $this->getMockBuilder(Server::class)
->getMock();
@@ -152,19 +145,15 @@ class FakeLockerPluginTest extends TestCase {
}
public function testFakeUnlockProvider(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$response->expects($this->once())
- ->method('setStatus')
- ->with('204');
+ ->method('setStatus')
+ ->with('204');
$response->expects($this->once())
- ->method('setHeader')
- ->with('Content-Length', '0');
+ ->method('setHeader')
+ ->with('Content-Length', '0');
$this->assertSame(false, $this->fakeLockerPlugin->fakeUnlockProvider($request, $response));
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/FileTest.php b/apps/dav/tests/unit/Connector/Sabre/FileTest.php
index 2830ccc0f18..60c8382e131 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FileTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FileTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -13,16 +14,29 @@ use OC\Files\Storage\Local;
use OC\Files\Storage\Temporary;
use OC\Files\Storage\Wrapper\PermissionsMask;
use OC\Files\View;
+use OCA\DAV\Connector\Sabre\Exception\FileLocked;
+use OCA\DAV\Connector\Sabre\Exception\Forbidden;
+use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
use OCA\DAV\Connector\Sabre\File;
use OCP\Constants;
+use OCP\Encryption\Exceptions\GenericEncryptionException;
+use OCP\Files\EntityTooLargeException;
use OCP\Files\FileInfo;
use OCP\Files\ForbiddenException;
-use OCP\Files\Storage;
+use OCP\Files\InvalidContentException;
+use OCP\Files\InvalidPathException;
+use OCP\Files\LockNotAcquiredException;
+use OCP\Files\NotPermittedException;
+use OCP\Files\Storage\IStorage;
+use OCP\Files\StorageNotAvailableException;
use OCP\IConfig;
use OCP\IRequestId;
use OCP\ITempManager;
use OCP\IUserManager;
use OCP\Lock\ILockingProvider;
+use OCP\Lock\LockedException;
+use OCP\Server;
+use OCP\Util;
use PHPUnit\Framework\MockObject\MockObject;
use Test\HookHelper;
use Test\TestCase;
@@ -40,16 +54,9 @@ class FileTest extends TestCase {
use MountProviderTrait;
use UserTrait;
- /**
- * @var string
- */
- private $user;
-
- /** @var IConfig|MockObject */
- protected $config;
-
- /** @var IRequestId|MockObject */
- protected $requestId;
+ private string $user;
+ protected IConfig&MockObject $config;
+ protected IRequestId&MockObject $requestId;
protected function setUp(): void {
parent::setUp();
@@ -59,35 +66,27 @@ class FileTest extends TestCase {
$this->user = 'test_user';
$this->createUser($this->user, 'pass');
- $this->loginAsUser($this->user);
+ self::loginAsUser($this->user);
$this->config = $this->createMock(IConfig::class);
$this->requestId = $this->createMock(IRequestId::class);
}
protected function tearDown(): void {
- $userManager = \OCP\Server::get(IUserManager::class);
+ $userManager = Server::get(IUserManager::class);
$userManager->get($this->user)->delete();
parent::tearDown();
}
- /**
- * @return MockObject|Storage
- */
- private function getMockStorage() {
- $storage = $this->getMockBuilder(Storage::class)
- ->disableOriginalConstructor()
- ->getMock();
+ private function getMockStorage(): MockObject&IStorage {
+ $storage = $this->createMock(IStorage::class);
$storage->method('getId')
->willReturn('home::someuser');
return $storage;
}
- /**
- * @param string $string
- */
- private function getStream($string) {
+ private function getStream(string $string) {
$stream = fopen('php://temp', 'r+');
fwrite($stream, $string);
fseek($stream, 0);
@@ -95,7 +94,7 @@ class FileTest extends TestCase {
}
- public function fopenFailuresProvider() {
+ public static function fopenFailuresProvider(): array {
return [
[
// return false
@@ -104,39 +103,39 @@ class FileTest extends TestCase {
false
],
[
- new \OCP\Files\NotPermittedException(),
+ new NotPermittedException(),
'Sabre\DAV\Exception\Forbidden'
],
[
- new \OCP\Files\EntityTooLargeException(),
+ new EntityTooLargeException(),
'OCA\DAV\Connector\Sabre\Exception\EntityTooLarge'
],
[
- new \OCP\Files\InvalidContentException(),
+ new InvalidContentException(),
'OCA\DAV\Connector\Sabre\Exception\UnsupportedMediaType'
],
[
- new \OCP\Files\InvalidPathException(),
+ new InvalidPathException(),
'Sabre\DAV\Exception\Forbidden'
],
[
- new \OCP\Files\ForbiddenException('', true),
+ new ForbiddenException('', true),
'OCA\DAV\Connector\Sabre\Exception\Forbidden'
],
[
- new \OCP\Files\LockNotAcquiredException('/test.txt', 1),
+ new LockNotAcquiredException('/test.txt', 1),
'OCA\DAV\Connector\Sabre\Exception\FileLocked'
],
[
- new \OCP\Lock\LockedException('/test.txt'),
+ new LockedException('/test.txt'),
'OCA\DAV\Connector\Sabre\Exception\FileLocked'
],
[
- new \OCP\Encryption\Exceptions\GenericEncryptionException(),
+ new GenericEncryptionException(),
'Sabre\DAV\Exception\ServiceUnavailable'
],
[
- new \OCP\Files\StorageNotAvailableException(),
+ new StorageNotAvailableException(),
'Sabre\DAV\Exception\ServiceUnavailable'
],
[
@@ -151,17 +150,15 @@ class FileTest extends TestCase {
];
}
- /**
- * @dataProvider fopenFailuresProvider
- */
- public function testSimplePutFails($thrownException, $expectedException, $checkPreviousClass = true): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('fopenFailuresProvider')]
+ public function testSimplePutFails(?\Throwable $thrownException, string $expectedException, bool $checkPreviousClass = true): void {
// setup
$storage = $this->getMockBuilder(Local::class)
->onlyMethods(['writeStream'])
- ->setConstructorArgs([['datadir' => \OCP\Server::get(ITempManager::class)->getTemporaryFolder()]])
+ ->setConstructorArgs([['datadir' => Server::get(ITempManager::class)->getTemporaryFolder()]])
->getMock();
- \OC\Files\Filesystem::mount($storage, [], $this->user . '/');
- /** @var View | MockObject $view */
+ Filesystem::mount($storage, [], $this->user . '/');
+ /** @var View&MockObject $view */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['getRelativePath', 'resolvePath'])
->getMock();
@@ -176,7 +173,7 @@ class FileTest extends TestCase {
if ($thrownException !== null) {
$storage->expects($this->once())
->method('writeStream')
- ->will($this->throwException($thrownException));
+ ->willThrowException($thrownException);
} else {
$storage->expects($this->once())
->method('writeStream')
@@ -188,11 +185,11 @@ class FileTest extends TestCase {
->willReturnArgument(0);
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FOLDER,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $file = new File($view, $info);
// action
$caughtException = null;
@@ -211,98 +208,18 @@ class FileTest extends TestCase {
}
/**
- * Test putting a file using chunking
- *
- * @dataProvider fopenFailuresProvider
- */
- public function testChunkedPutFails($thrownException, $expectedException, $checkPreviousClass = false): void {
- // setup
- $storage = $this->getMockBuilder(Local::class)
- ->onlyMethods(['fopen'])
- ->setConstructorArgs([['datadir' => \OCP\Server::get(ITempManager::class)->getTemporaryFolder()]])
- ->getMock();
- \OC\Files\Filesystem::mount($storage, [], $this->user . '/');
- /** @var View|MockObject */
- $view = $this->getMockBuilder(View::class)
- ->onlyMethods(['getRelativePath', 'resolvePath'])
- ->getMock();
- $view->expects($this->atLeastOnce())
- ->method('resolvePath')
- ->willReturnCallback(
- function ($path) use ($storage) {
- return [$storage, $path];
- }
- );
-
- if ($thrownException !== null) {
- $storage->expects($this->once())
- ->method('fopen')
- ->will($this->throwException($thrownException));
- } else {
- $storage->expects($this->once())
- ->method('fopen')
- ->willReturn(false);
- }
-
- $view->expects($this->any())
- ->method('getRelativePath')
- ->willReturnArgument(0);
-
- $request = new Request([
- 'server' => [
- 'HTTP_OC_CHUNKED' => 'true'
- ]
- ], $this->requestId, $this->config, null);
-
- $info = new \OC\Files\FileInfo('/test.txt-chunking-12345-2-0', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
- 'type' => FileInfo::TYPE_FOLDER,
- ], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info, null, $request);
-
- // put first chunk
- $file->acquireLock(ILockingProvider::LOCK_SHARED);
- $this->assertNull($file->put('test data one'));
- $file->releaseLock(ILockingProvider::LOCK_SHARED);
-
- $info = new \OC\Files\FileInfo('/test.txt-chunking-12345-2-1', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
- 'type' => FileInfo::TYPE_FOLDER,
- ], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info, null, $request);
-
- // action
- $caughtException = null;
- try {
- // last chunk
- $file->acquireLock(ILockingProvider::LOCK_SHARED);
- $file->put('test data two');
- $file->releaseLock(ILockingProvider::LOCK_SHARED);
- } catch (\Exception $e) {
- $caughtException = $e;
- }
-
- $this->assertInstanceOf($expectedException, $caughtException);
- if ($checkPreviousClass) {
- $this->assertInstanceOf(get_class($thrownException), $caughtException->getPrevious());
- }
-
- $this->assertEmpty($this->listPartFiles($view, ''), 'No stray part files');
- }
-
- /**
* Simulate putting a file to the given path.
*
* @param string $path path to put the file into
- * @param string $viewRoot root to use for the view
+ * @param ?string $viewRoot root to use for the view
* @param null|Request $request the HTTP request
*
* @return null|string of the PUT operation which is usually the etag
*/
- private function doPut($path, $viewRoot = null, ?Request $request = null) {
- $view = \OC\Files\Filesystem::getView();
+ private function doPut(string $path, ?string $viewRoot = null, ?Request $request = null) {
+ $view = Filesystem::getView();
if (!is_null($viewRoot)) {
- $view = new \OC\Files\View($viewRoot);
+ $view = new View($viewRoot);
} else {
$viewRoot = '/' . $this->user . '/files';
}
@@ -312,14 +229,14 @@ class FileTest extends TestCase {
$this->getMockStorage(),
null,
[
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FOLDER,
],
null
);
- /** @var \OCA\DAV\Connector\Sabre\File | MockObject $file */
- $file = $this->getMockBuilder(\OCA\DAV\Connector\Sabre\File::class)
+ /** @var File&MockObject $file */
+ $file = $this->getMockBuilder(File::class)
->setConstructorArgs([$view, $info, null, $request])
->onlyMethods(['header'])
->getMock();
@@ -342,64 +259,64 @@ class FileTest extends TestCase {
$this->assertNotEmpty($this->doPut('/foo.txt'));
}
- public function legalMtimeProvider() {
+ public static function legalMtimeProvider(): array {
return [
- "string" => [
- 'HTTP_X_OC_MTIME' => "string",
- 'expected result' => null
+ 'string' => [
+ 'requestMtime' => 'string',
+ 'resultMtime' => null
],
- "castable string (int)" => [
- 'HTTP_X_OC_MTIME' => "987654321",
- 'expected result' => 987654321
+ 'castable string (int)' => [
+ 'requestMtime' => '987654321',
+ 'resultMtime' => 987654321
],
- "castable string (float)" => [
- 'HTTP_X_OC_MTIME' => "123456789.56",
- 'expected result' => 123456789
+ 'castable string (float)' => [
+ 'requestMtime' => '123456789.56',
+ 'resultMtime' => 123456789
],
- "float" => [
- 'HTTP_X_OC_MTIME' => 123456789.56,
- 'expected result' => 123456789
+ 'float' => [
+ 'requestMtime' => 123456789.56,
+ 'resultMtime' => 123456789
],
- "zero" => [
- 'HTTP_X_OC_MTIME' => 0,
- 'expected result' => null
+ 'zero' => [
+ 'requestMtime' => 0,
+ 'resultMtime' => null
],
- "zero string" => [
- 'HTTP_X_OC_MTIME' => "0",
- 'expected result' => null
+ 'zero string' => [
+ 'requestMtime' => '0',
+ 'resultMtime' => null
],
- "negative zero string" => [
- 'HTTP_X_OC_MTIME' => "-0",
- 'expected result' => null
+ 'negative zero string' => [
+ 'requestMtime' => '-0',
+ 'resultMtime' => null
],
- "string starting with number following by char" => [
- 'HTTP_X_OC_MTIME' => "2345asdf",
- 'expected result' => null
+ 'string starting with number following by char' => [
+ 'requestMtime' => '2345asdf',
+ 'resultMtime' => null
],
- "string castable hex int" => [
- 'HTTP_X_OC_MTIME' => "0x45adf",
- 'expected result' => null
+ 'string castable hex int' => [
+ 'requestMtime' => '0x45adf',
+ 'resultMtime' => null
],
- "string that looks like invalid hex int" => [
- 'HTTP_X_OC_MTIME' => "0x123g",
- 'expected result' => null
+ 'string that looks like invalid hex int' => [
+ 'requestMtime' => '0x123g',
+ 'resultMtime' => null
],
- "negative int" => [
- 'HTTP_X_OC_MTIME' => -34,
- 'expected result' => null
+ 'negative int' => [
+ 'requestMtime' => -34,
+ 'resultMtime' => null
],
- "negative float" => [
- 'HTTP_X_OC_MTIME' => -34.43,
- 'expected result' => null
+ 'negative float' => [
+ 'requestMtime' => -34.43,
+ 'resultMtime' => null
],
];
}
/**
* Test putting a file with string Mtime
- * @dataProvider legalMtimeProvider
*/
- public function testPutSingleFileLegalMtime($requestMtime, $resultMtime): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('legalMtimeProvider')]
+ public function testPutSingleFileLegalMtime(mixed $requestMtime, ?int $resultMtime): void {
$request = new Request([
'server' => [
'HTTP_X_OC_MTIME' => (string)$requestMtime,
@@ -419,45 +336,6 @@ class FileTest extends TestCase {
}
/**
- * Test putting a file with string Mtime using chunking
- * @dataProvider legalMtimeProvider
- */
- public function testChunkedPutLegalMtime($requestMtime, $resultMtime): void {
- $request = new Request([
- 'server' => [
- 'HTTP_X_OC_MTIME' => (string)$requestMtime,
- 'HTTP_OC_CHUNKED' => 'true'
- ]
- ], $this->requestId, $this->config, null);
-
- $file = 'foo.txt';
-
- if ($resultMtime === null) {
- $this->expectException(\Sabre\DAV\Exception::class);
- }
-
- $this->doPut($file.'-chunking-12345-2-0', null, $request);
- $this->doPut($file.'-chunking-12345-2-1', null, $request);
-
- if ($resultMtime !== null) {
- $this->assertEquals($resultMtime, $this->getFileInfos($file)['mtime']);
- }
- }
-
- /**
- * Test putting a file using chunking
- */
- public function testChunkedPut(): void {
- $request = new Request([
- 'server' => [
- 'HTTP_OC_CHUNKED' => 'true'
- ]
- ], $this->requestId, $this->config, null);
- $this->assertNull($this->doPut('/test.txt-chunking-12345-2-0', null, $request));
- $this->assertNotEmpty($this->doPut('/test.txt-chunking-12345-2-1', null, $request));
- }
-
- /**
* Test that putting a file triggers create hooks
*/
public function testPutSingleFileTriggersHooks(): void {
@@ -492,7 +370,7 @@ class FileTest extends TestCase {
* Test that putting a file triggers update hooks
*/
public function testPutOverwriteFileTriggersHooks(): void {
- $view = \OC\Files\Filesystem::getView();
+ $view = Filesystem::getView();
$view->file_put_contents('/foo.txt', 'some content that will be replaced');
HookHelper::setUpHooks();
@@ -528,7 +406,7 @@ class FileTest extends TestCase {
* where the root is the share root)
*/
public function testPutSingleFileTriggersHooksDifferentRoot(): void {
- $view = \OC\Files\Filesystem::getView();
+ $view = Filesystem::getView();
$view->mkdir('noderoot');
HookHelper::setUpHooks();
@@ -559,83 +437,6 @@ class FileTest extends TestCase {
);
}
- /**
- * Test that putting a file with chunks triggers create hooks
- */
- public function testPutChunkedFileTriggersHooks(): void {
- HookHelper::setUpHooks();
-
- $request = new Request([
- 'server' => [
- 'HTTP_OC_CHUNKED' => 'true'
- ]
- ], $this->requestId, $this->config, null);
- $this->assertNull($this->doPut('/foo.txt-chunking-12345-2-0', null, $request));
- $this->assertNotEmpty($this->doPut('/foo.txt-chunking-12345-2-1', null, $request));
-
- $this->assertCount(4, HookHelper::$hookCalls);
- $this->assertHookCall(
- HookHelper::$hookCalls[0],
- Filesystem::signal_create,
- '/foo.txt'
- );
- $this->assertHookCall(
- HookHelper::$hookCalls[1],
- Filesystem::signal_write,
- '/foo.txt'
- );
- $this->assertHookCall(
- HookHelper::$hookCalls[2],
- Filesystem::signal_post_create,
- '/foo.txt'
- );
- $this->assertHookCall(
- HookHelper::$hookCalls[3],
- Filesystem::signal_post_write,
- '/foo.txt'
- );
- }
-
- /**
- * Test that putting a chunked file triggers update hooks
- */
- public function testPutOverwriteChunkedFileTriggersHooks(): void {
- $view = \OC\Files\Filesystem::getView();
- $view->file_put_contents('/foo.txt', 'some content that will be replaced');
-
- HookHelper::setUpHooks();
-
- $request = new Request([
- 'server' => [
- 'HTTP_OC_CHUNKED' => 'true'
- ]
- ], $this->requestId, $this->config, null);
- $this->assertNull($this->doPut('/foo.txt-chunking-12345-2-0', null, $request));
- $this->assertNotEmpty($this->doPut('/foo.txt-chunking-12345-2-1', null, $request));
-
- $this->assertCount(4, HookHelper::$hookCalls);
- $this->assertHookCall(
- HookHelper::$hookCalls[0],
- Filesystem::signal_update,
- '/foo.txt'
- );
- $this->assertHookCall(
- HookHelper::$hookCalls[1],
- Filesystem::signal_write,
- '/foo.txt'
- );
- $this->assertHookCall(
- HookHelper::$hookCalls[2],
- Filesystem::signal_post_update,
- '/foo.txt'
- );
- $this->assertHookCall(
- HookHelper::$hookCalls[3],
- Filesystem::signal_post_write,
- '/foo.txt'
- );
- }
-
public static function cancellingHook($params): void {
self::$hookCalls[] = [
'signal' => Filesystem::signal_post_create,
@@ -647,7 +448,7 @@ class FileTest extends TestCase {
* Test put file with cancelled hook
*/
public function testPutSingleFileCancelPreHook(): void {
- \OCP\Util::connectHook(
+ Util::connectHook(
Filesystem::CLASSNAME,
Filesystem::signal_create,
'\Test\HookHelper',
@@ -671,7 +472,7 @@ class FileTest extends TestCase {
*/
public function testSimplePutFailsSizeCheck(): void {
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['rename', 'getRelativePath', 'filesize'])
->getMock();
@@ -695,11 +496,11 @@ class FileTest extends TestCase {
], $this->requestId, $this->config, null);
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FOLDER,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info, null, $request);
+ $file = new File($view, $info, null, $request);
// action
$thrown = false;
@@ -723,17 +524,17 @@ class FileTest extends TestCase {
* Test exception during final rename in simple upload mode
*/
public function testSimplePutFailsMoveFromStorage(): void {
- $view = new \OC\Files\View('/' . $this->user . '/files');
+ $view = new View('/' . $this->user . '/files');
// simulate situation where the target file is locked
$view->lockFile('/test.txt', ILockingProvider::LOCK_EXCLUSIVE);
$info = new \OC\Files\FileInfo('/' . $this->user . '/files/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FOLDER,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $file = new File($view, $info);
// action
$thrown = false;
@@ -745,51 +546,7 @@ class FileTest extends TestCase {
// afterMethod unlocks
$view->unlockFile($info->getPath(), ILockingProvider::LOCK_SHARED);
- } catch (\OCA\DAV\Connector\Sabre\Exception\FileLocked $e) {
- $thrown = true;
- }
-
- $this->assertTrue($thrown);
- $this->assertEmpty($this->listPartFiles($view, ''), 'No stray part files');
- }
-
- /**
- * Test exception during final rename in chunk upload mode
- */
- public function testChunkedPutFailsFinalRename(): void {
- $view = new \OC\Files\View('/' . $this->user . '/files');
-
- // simulate situation where the target file is locked
- $view->lockFile('/test.txt', ILockingProvider::LOCK_EXCLUSIVE);
-
- $request = new Request([
- 'server' => [
- 'HTTP_OC_CHUNKED' => 'true'
- ]
- ], $this->requestId, $this->config, null);
-
- $info = new \OC\Files\FileInfo('/' . $this->user . '/files/test.txt-chunking-12345-2-0', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
- 'type' => FileInfo::TYPE_FOLDER,
- ], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info, null, $request);
- $file->acquireLock(ILockingProvider::LOCK_SHARED);
- $this->assertNull($file->put('test data one'));
- $file->releaseLock(ILockingProvider::LOCK_SHARED);
-
- $info = new \OC\Files\FileInfo('/' . $this->user . '/files/test.txt-chunking-12345-2-1', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
- 'type' => FileInfo::TYPE_FOLDER,
- ], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info, null, $request);
-
- // action
- $thrown = false;
- try {
- $file->acquireLock(ILockingProvider::LOCK_SHARED);
- $file->put($this->getStream('test data'));
- $file->releaseLock(ILockingProvider::LOCK_SHARED);
- } catch (\OCA\DAV\Connector\Sabre\Exception\FileLocked $e) {
+ } catch (FileLocked $e) {
$thrown = true;
}
@@ -802,7 +559,7 @@ class FileTest extends TestCase {
*/
public function testSimplePutInvalidChars(): void {
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['getRelativePath'])
->getMock();
@@ -810,11 +567,11 @@ class FileTest extends TestCase {
->method('getRelativePath')
->willReturnArgument(0);
- $info = new \OC\Files\FileInfo('/*', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ $info = new \OC\Files\FileInfo("/i\nvalid", $this->getMockStorage(), null, [
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FOLDER,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $file = new File($view, $info);
// action
$thrown = false;
@@ -826,7 +583,7 @@ class FileTest extends TestCase {
// afterMethod unlocks
$view->unlockFile($info->getPath(), ILockingProvider::LOCK_SHARED);
- } catch (\OCA\DAV\Connector\Sabre\Exception\InvalidPath $e) {
+ } catch (InvalidPath $e) {
$thrown = true;
}
@@ -839,10 +596,10 @@ class FileTest extends TestCase {
*
*/
public function testSetNameInvalidChars(): void {
- $this->expectException(\OCA\DAV\Connector\Sabre\Exception\InvalidPath::class);
+ $this->expectException(InvalidPath::class);
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['getRelativePath'])
->getMock();
@@ -851,18 +608,19 @@ class FileTest extends TestCase {
->method('getRelativePath')
->willReturnArgument(0);
- $info = new \OC\Files\FileInfo('/*', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ $info = new \OC\Files\FileInfo('/valid', $this->getMockStorage(), null, [
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FOLDER,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
- $file->setName('/super*star.txt');
+ $file = new File($view, $info);
+
+ $file->setName("/i\nvalid");
}
public function testUploadAbort(): void {
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['rename', 'getRelativePath', 'filesize'])
->getMock();
@@ -885,11 +643,11 @@ class FileTest extends TestCase {
], $this->requestId, $this->config, null);
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FOLDER,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info, null, $request);
+ $file = new File($view, $info, null, $request);
// action
$thrown = false;
@@ -912,7 +670,7 @@ class FileTest extends TestCase {
public function testDeleteWhenAllowed(): void {
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->getMock();
@@ -921,11 +679,11 @@ class FileTest extends TestCase {
->willReturn(true);
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FOLDER,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $file = new File($view, $info);
// action
$file->delete();
@@ -936,7 +694,7 @@ class FileTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->getMock();
@@ -945,7 +703,7 @@ class FileTest extends TestCase {
'type' => FileInfo::TYPE_FOLDER,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $file = new File($view, $info);
// action
$file->delete();
@@ -956,7 +714,7 @@ class FileTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->getMock();
@@ -966,11 +724,11 @@ class FileTest extends TestCase {
->willReturn(false);
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FOLDER,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $file = new File($view, $info);
// action
$file->delete();
@@ -978,10 +736,10 @@ class FileTest extends TestCase {
public function testDeleteThrowsWhenDeletionThrows(): void {
- $this->expectException(\OCA\DAV\Connector\Sabre\Exception\Forbidden::class);
+ $this->expectException(Forbidden::class);
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->getMock();
@@ -991,11 +749,11 @@ class FileTest extends TestCase {
->willThrowException(new ForbiddenException('', true));
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FOLDER,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $file = new File($view, $info);
// action
$file->delete();
@@ -1021,7 +779,7 @@ class FileTest extends TestCase {
* Test whether locks are set before and after the operation
*/
public function testPutLocking(): void {
- $view = new \OC\Files\View('/' . $this->user . '/files/');
+ $view = new View('/' . $this->user . '/files/');
$path = 'test-locking.txt';
$info = new \OC\Files\FileInfo(
@@ -1029,20 +787,20 @@ class FileTest extends TestCase {
$this->getMockStorage(),
null,
[
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FOLDER,
],
null
);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $file = new File($view, $info);
$this->assertFalse(
- $this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_SHARED),
+ $this->isFileLocked($view, $path, ILockingProvider::LOCK_SHARED),
'File unlocked before put'
);
$this->assertFalse(
- $this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE),
+ $this->isFileLocked($view, $path, ILockingProvider::LOCK_EXCLUSIVE),
'File unlocked before put'
);
@@ -1058,26 +816,26 @@ class FileTest extends TestCase {
->method('writeCallback')
->willReturnCallback(
function () use ($view, $path, &$wasLockedPre): void {
- $wasLockedPre = $this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_SHARED);
- $wasLockedPre = $wasLockedPre && !$this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE);
+ $wasLockedPre = $this->isFileLocked($view, $path, ILockingProvider::LOCK_SHARED);
+ $wasLockedPre = $wasLockedPre && !$this->isFileLocked($view, $path, ILockingProvider::LOCK_EXCLUSIVE);
}
);
$eventHandler->expects($this->once())
->method('postWriteCallback')
->willReturnCallback(
function () use ($view, $path, &$wasLockedPost): void {
- $wasLockedPost = $this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_SHARED);
- $wasLockedPost = $wasLockedPost && !$this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE);
+ $wasLockedPost = $this->isFileLocked($view, $path, ILockingProvider::LOCK_SHARED);
+ $wasLockedPost = $wasLockedPost && !$this->isFileLocked($view, $path, ILockingProvider::LOCK_EXCLUSIVE);
}
);
- \OCP\Util::connectHook(
+ Util::connectHook(
Filesystem::CLASSNAME,
Filesystem::signal_write,
$eventHandler,
'writeCallback'
);
- \OCP\Util::connectHook(
+ Util::connectHook(
Filesystem::CLASSNAME,
Filesystem::signal_post_write,
$eventHandler,
@@ -1096,11 +854,11 @@ class FileTest extends TestCase {
$this->assertTrue($wasLockedPost, 'File was locked during post-hooks');
$this->assertFalse(
- $this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_SHARED),
+ $this->isFileLocked($view, $path, ILockingProvider::LOCK_SHARED),
'File unlocked after put'
);
$this->assertFalse(
- $this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE),
+ $this->isFileLocked($view, $path, ILockingProvider::LOCK_EXCLUSIVE),
'File unlocked after put'
);
}
@@ -1113,9 +871,9 @@ class FileTest extends TestCase {
*
* @return array list of part files
*/
- private function listPartFiles(?\OC\Files\View $userView = null, $path = '') {
+ private function listPartFiles(?View $userView = null, $path = '') {
if ($userView === null) {
- $userView = \OC\Files\Filesystem::getView();
+ $userView = Filesystem::getView();
}
$files = [];
[$storage, $internalPath] = $userView->resolvePath($path);
@@ -1144,10 +902,10 @@ class FileTest extends TestCase {
$userView = Filesystem::getView();
}
return [
- "filesize" => $userView->filesize($path),
- "mtime" => $userView->filemtime($path),
- "filetype" => $userView->filetype($path),
- "mimetype" => $userView->getMimeType($path)
+ 'filesize' => $userView->filesize($path),
+ 'mtime' => $userView->filemtime($path),
+ 'filetype' => $userView->filetype($path),
+ 'mimetype' => $userView->getMimeType($path)
];
}
@@ -1155,7 +913,7 @@ class FileTest extends TestCase {
public function testGetFopenFails(): void {
$this->expectException(\Sabre\DAV\Exception\ServiceUnavailable::class);
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['fopen'])
->getMock();
@@ -1164,20 +922,20 @@ class FileTest extends TestCase {
->willReturn(false);
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FILE,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $file = new File($view, $info);
$file->get();
}
public function testGetFopenThrows(): void {
- $this->expectException(\OCA\DAV\Connector\Sabre\Exception\Forbidden::class);
+ $this->expectException(Forbidden::class);
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['fopen'])
->getMock();
@@ -1186,11 +944,11 @@ class FileTest extends TestCase {
->willThrowException(new ForbiddenException('', true));
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FILE,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $file = new File($view, $info);
$file->get();
}
@@ -1199,7 +957,7 @@ class FileTest extends TestCase {
public function testGetThrowsIfNoPermission(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['fopen'])
->getMock();
@@ -1207,11 +965,11 @@ class FileTest extends TestCase {
->method('fopen');
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_CREATE, // no read perm
+ 'permissions' => Constants::PERMISSION_CREATE, // no read perm
'type' => FileInfo::TYPE_FOLDER,
], null);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $file = new File($view, $info);
$file->get();
}
@@ -1248,7 +1006,7 @@ class FileTest extends TestCase {
}
public function testPutLockExpired(): void {
- $view = new \OC\Files\View('/' . $this->user . '/files/');
+ $view = new View('/' . $this->user . '/files/');
$path = 'test-locking.txt';
$info = new \OC\Files\FileInfo(
@@ -1256,13 +1014,13 @@ class FileTest extends TestCase {
$this->getMockStorage(),
null,
[
- 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'permissions' => Constants::PERMISSION_ALL,
'type' => FileInfo::TYPE_FOLDER,
],
null
);
- $file = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $file = new File($view, $info);
// don't lock before the PUT to simulate an expired shared lock
$this->assertNotEmpty($file->put($this->getStream('test data')));
diff --git a/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
index f1460591a91..4df3accfda9 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -7,12 +8,18 @@
*/
namespace OCA\DAV\Tests\unit\Connector\Sabre;
+use OC\Accounts\Account;
+use OC\Accounts\AccountProperty;
use OC\User\User;
use OCA\DAV\Connector\Sabre\Directory;
+use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
use OCA\DAV\Connector\Sabre\File;
use OCA\DAV\Connector\Sabre\FilesPlugin;
use OCA\DAV\Connector\Sabre\Node;
+use OCP\Accounts\IAccountManager;
use OCP\Files\FileInfo;
+use OCP\Files\IFilenameValidator;
+use OCP\Files\InvalidPathException;
use OCP\Files\StorageNotAvailableException;
use OCP\IConfig;
use OCP\IPreview;
@@ -32,51 +39,16 @@ use Test\TestCase;
* @group DB
*/
class FilesPluginTest extends TestCase {
- public const GETETAG_PROPERTYNAME = FilesPlugin::GETETAG_PROPERTYNAME;
- public const FILEID_PROPERTYNAME = FilesPlugin::FILEID_PROPERTYNAME;
- public const INTERNAL_FILEID_PROPERTYNAME = FilesPlugin::INTERNAL_FILEID_PROPERTYNAME;
- public const SIZE_PROPERTYNAME = FilesPlugin::SIZE_PROPERTYNAME;
- public const PERMISSIONS_PROPERTYNAME = FilesPlugin::PERMISSIONS_PROPERTYNAME;
- public const LASTMODIFIED_PROPERTYNAME = FilesPlugin::LASTMODIFIED_PROPERTYNAME;
- public const CREATIONDATE_PROPERTYNAME = FilesPlugin::CREATIONDATE_PROPERTYNAME;
- public const DOWNLOADURL_PROPERTYNAME = FilesPlugin::DOWNLOADURL_PROPERTYNAME;
- public const OWNER_ID_PROPERTYNAME = FilesPlugin::OWNER_ID_PROPERTYNAME;
- public const OWNER_DISPLAY_NAME_PROPERTYNAME = FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME;
- public const DATA_FINGERPRINT_PROPERTYNAME = FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME;
- public const HAS_PREVIEW_PROPERTYNAME = FilesPlugin::HAS_PREVIEW_PROPERTYNAME;
- /**
- * @var \Sabre\DAV\Server | \PHPUnit\Framework\MockObject\MockObject
- */
- private $server;
-
- /**
- * @var \Sabre\DAV\Tree | \PHPUnit\Framework\MockObject\MockObject
- */
- private $tree;
-
- /**
- * @var FilesPlugin
- */
- private $plugin;
-
- /**
- * @var \OCP\IConfig | \PHPUnit\Framework\MockObject\MockObject
- */
- private $config;
-
- /**
- * @var \OCP\IRequest | \PHPUnit\Framework\MockObject\MockObject
- */
- private $request;
-
- /**
- * @var \OCP\IPreview | \PHPUnit\Framework\MockObject\MockObject
- */
- private $previewManager;
-
- /** @var IUserSession|MockObject */
- private $userSession;
+ private Tree&MockObject $tree;
+ private Server&MockObject $server;
+ private IConfig&MockObject $config;
+ private IRequest&MockObject $request;
+ private IPreview&MockObject $previewManager;
+ private IUserSession&MockObject $userSession;
+ private IFilenameValidator&MockObject $filenameValidator;
+ private IAccountManager&MockObject $accountManager;
+ private FilesPlugin $plugin;
protected function setUp(): void {
parent::setUp();
@@ -89,32 +61,28 @@ class FilesPluginTest extends TestCase {
$this->request = $this->createMock(IRequest::class);
$this->previewManager = $this->createMock(IPreview::class);
$this->userSession = $this->createMock(IUserSession::class);
+ $this->filenameValidator = $this->createMock(IFilenameValidator::class);
+ $this->accountManager = $this->createMock(IAccountManager::class);
$this->plugin = new FilesPlugin(
$this->tree,
$this->config,
$this->request,
$this->previewManager,
- $this->userSession
+ $this->userSession,
+ $this->filenameValidator,
+ $this->accountManager,
);
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $response = $this->createMock(ResponseInterface::class);
$this->server->httpResponse = $response;
$this->server->xml = new Service();
$this->plugin->initialize($this->server);
}
- /**
- * @param string $class
- * @return \PHPUnit\Framework\MockObject\MockObject
- */
- private function createTestNode($class, $path = '/dummypath') {
- $node = $this->getMockBuilder($class)
- ->disableOriginalConstructor()
- ->getMock();
+ private function createTestNode(string $class, string $path = '/dummypath'): MockObject {
+ $node = $this->createMock($class);
$node->expects($this->any())
->method('getId')
@@ -154,28 +122,27 @@ class FilesPluginTest extends TestCase {
}
public function testGetPropertiesForFile(): void {
- /** @var \OCA\DAV\Connector\Sabre\File | \PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File');
+ /** @var File&MockObject $node */
+ $node = $this->createTestNode(File::class);
$propFind = new PropFind(
'/dummyPath',
[
- self::GETETAG_PROPERTYNAME,
- self::FILEID_PROPERTYNAME,
- self::INTERNAL_FILEID_PROPERTYNAME,
- self::SIZE_PROPERTYNAME,
- self::PERMISSIONS_PROPERTYNAME,
- self::DOWNLOADURL_PROPERTYNAME,
- self::OWNER_ID_PROPERTYNAME,
- self::OWNER_DISPLAY_NAME_PROPERTYNAME,
- self::DATA_FINGERPRINT_PROPERTYNAME,
- self::CREATIONDATE_PROPERTYNAME,
+ FilesPlugin::GETETAG_PROPERTYNAME,
+ FilesPlugin::FILEID_PROPERTYNAME,
+ FilesPlugin::INTERNAL_FILEID_PROPERTYNAME,
+ FilesPlugin::SIZE_PROPERTYNAME,
+ FilesPlugin::PERMISSIONS_PROPERTYNAME,
+ FilesPlugin::DOWNLOADURL_PROPERTYNAME,
+ FilesPlugin::OWNER_ID_PROPERTYNAME,
+ FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME,
+ FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME,
+ FilesPlugin::CREATIONDATE_PROPERTYNAME,
],
0
);
- $user = $this->getMockBuilder(User::class)
- ->disableOriginalConstructor()->getMock();
+ $user = $this->createMock(User::class);
$user
->expects($this->once())
->method('getUID')
@@ -185,6 +152,12 @@ class FilesPluginTest extends TestCase {
->method('getDisplayName')
->willReturn('M. Foo');
+ $owner = $this->createMock(Account::class);
+ $this->accountManager->expects($this->once())
+ ->method('getAccount')
+ ->with($user)
+ ->willReturn($owner);
+
$node->expects($this->once())
->method('getDirectDownload')
->willReturn(['url' => 'http://example.com/']);
@@ -192,70 +165,170 @@ class FilesPluginTest extends TestCase {
->method('getOwner')
->willReturn($user);
+ $displayNameProp = $this->createMock(AccountProperty::class);
+ $owner
+ ->expects($this->once())
+ ->method('getProperty')
+ ->with(IAccountManager::PROPERTY_DISPLAYNAME)
+ ->willReturn($displayNameProp);
+ $displayNameProp
+ ->expects($this->once())
+ ->method('getScope')
+ ->willReturn(IAccountManager::SCOPE_PUBLISHED);
+
$this->plugin->handleGetProperties(
$propFind,
$node
);
- $this->assertEquals('"abc"', $propFind->get(self::GETETAG_PROPERTYNAME));
- $this->assertEquals('00000123instanceid', $propFind->get(self::FILEID_PROPERTYNAME));
- $this->assertEquals('123', $propFind->get(self::INTERNAL_FILEID_PROPERTYNAME));
- $this->assertEquals('1973-11-29T21:33:09+00:00', $propFind->get(self::CREATIONDATE_PROPERTYNAME));
- $this->assertEquals(0, $propFind->get(self::SIZE_PROPERTYNAME));
- $this->assertEquals('DWCKMSR', $propFind->get(self::PERMISSIONS_PROPERTYNAME));
- $this->assertEquals('http://example.com/', $propFind->get(self::DOWNLOADURL_PROPERTYNAME));
- $this->assertEquals('foo', $propFind->get(self::OWNER_ID_PROPERTYNAME));
- $this->assertEquals('M. Foo', $propFind->get(self::OWNER_DISPLAY_NAME_PROPERTYNAME));
- $this->assertEquals('my_fingerprint', $propFind->get(self::DATA_FINGERPRINT_PROPERTYNAME));
+ $this->assertEquals('"abc"', $propFind->get(FilesPlugin::GETETAG_PROPERTYNAME));
+ $this->assertEquals('00000123instanceid', $propFind->get(FilesPlugin::FILEID_PROPERTYNAME));
+ $this->assertEquals('123', $propFind->get(FilesPlugin::INTERNAL_FILEID_PROPERTYNAME));
+ $this->assertEquals('1973-11-29T21:33:09+00:00', $propFind->get(FilesPlugin::CREATIONDATE_PROPERTYNAME));
+ $this->assertEquals(0, $propFind->get(FilesPlugin::SIZE_PROPERTYNAME));
+ $this->assertEquals('DWCKMSR', $propFind->get(FilesPlugin::PERMISSIONS_PROPERTYNAME));
+ $this->assertEquals('http://example.com/', $propFind->get(FilesPlugin::DOWNLOADURL_PROPERTYNAME));
+ $this->assertEquals('foo', $propFind->get(FilesPlugin::OWNER_ID_PROPERTYNAME));
+ $this->assertEquals('M. Foo', $propFind->get(FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME));
+ $this->assertEquals('my_fingerprint', $propFind->get(FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME));
$this->assertEquals([], $propFind->get404Properties());
}
+ public function testGetDisplayNamePropertyWhenNotPublished(): void {
+ $node = $this->createTestNode(File::class);
+ $propFind = new PropFind(
+ '/dummyPath',
+ [
+ FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME,
+ ],
+ 0
+ );
+
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->willReturn(null);
+
+ $user = $this->createMock(User::class);
+
+ $user->expects($this->never())
+ ->method('getDisplayName');
+
+ $owner = $this->createMock(Account::class);
+ $this->accountManager->expects($this->once())
+ ->method('getAccount')
+ ->with($user)
+ ->willReturn($owner);
+
+ $node->expects($this->once())
+ ->method('getOwner')
+ ->willReturn($user);
+
+ $displayNameProp = $this->createMock(AccountProperty::class);
+ $owner
+ ->expects($this->once())
+ ->method('getProperty')
+ ->with(IAccountManager::PROPERTY_DISPLAYNAME)
+ ->willReturn($displayNameProp);
+ $displayNameProp
+ ->expects($this->once())
+ ->method('getScope')
+ ->willReturn(IAccountManager::SCOPE_PRIVATE);
+
+ $this->plugin->handleGetProperties(
+ $propFind,
+ $node
+ );
+
+ $this->assertEquals(null, $propFind->get(FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME));
+ }
+
+ public function testGetDisplayNamePropertyWhenNotPublishedButLoggedIn(): void {
+ $node = $this->createTestNode(File::class);
+
+ $propFind = new PropFind(
+ '/dummyPath',
+ [
+ FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME,
+ ],
+ 0
+ );
+
+ $user = $this->createMock(User::class);
+
+ $node->expects($this->once())
+ ->method('getOwner')
+ ->willReturn($user);
+
+ $loggedInUser = $this->createMock(User::class);
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->willReturn($loggedInUser);
+
+ $user
+ ->expects($this->once())
+ ->method('getDisplayName')
+ ->willReturn('M. Foo');
+
+ $this->accountManager->expects($this->never())
+ ->method('getAccount');
+
+ $this->plugin->handleGetProperties(
+ $propFind,
+ $node
+ );
+
+ $this->assertEquals('M. Foo', $propFind->get(FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME));
+ }
+
public function testGetPropertiesStorageNotAvailable(): void {
- /** @var \OCA\DAV\Connector\Sabre\File | \PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File');
+ /** @var File&MockObject $node */
+ $node = $this->createTestNode(File::class);
$propFind = new PropFind(
'/dummyPath',
[
- self::DOWNLOADURL_PROPERTYNAME,
+ FilesPlugin::DOWNLOADURL_PROPERTYNAME,
],
0
);
$node->expects($this->once())
->method('getDirectDownload')
- ->will($this->throwException(new StorageNotAvailableException()));
+ ->willThrowException(new StorageNotAvailableException());
$this->plugin->handleGetProperties(
$propFind,
$node
);
- $this->assertEquals(null, $propFind->get(self::DOWNLOADURL_PROPERTYNAME));
+ $this->assertEquals(null, $propFind->get(FilesPlugin::DOWNLOADURL_PROPERTYNAME));
}
public function testGetPublicPermissions(): void {
+ /** @var IRequest&MockObject */
+ $request = $this->createMock(IRequest::class);
$this->plugin = new FilesPlugin(
$this->tree,
$this->config,
- $this->getMockBuilder(IRequest::class)
- ->disableOriginalConstructor()
- ->getMock(),
+ $request,
$this->previewManager,
$this->userSession,
- true);
+ $this->filenameValidator,
+ $this->accountManager,
+ true,
+ );
$this->plugin->initialize($this->server);
$propFind = new PropFind(
'/dummyPath',
[
- self::PERMISSIONS_PROPERTYNAME,
+ FilesPlugin::PERMISSIONS_PROPERTYNAME,
],
0
);
- /** @var \OCA\DAV\Connector\Sabre\File | \PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File');
+ /** @var File&MockObject $node */
+ $node = $this->createTestNode(File::class);
$node->expects($this->any())
->method('getDavPermissions')
->willReturn('DWCKMSR');
@@ -265,22 +338,22 @@ class FilesPluginTest extends TestCase {
$node
);
- $this->assertEquals('DWCKR', $propFind->get(self::PERMISSIONS_PROPERTYNAME));
+ $this->assertEquals('DWCKR', $propFind->get(FilesPlugin::PERMISSIONS_PROPERTYNAME));
}
public function testGetPropertiesForDirectory(): void {
- /** @var \OCA\DAV\Connector\Sabre\Directory | \PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\Directory');
+ /** @var Directory&MockObject $node */
+ $node = $this->createTestNode(Directory::class);
$propFind = new PropFind(
'/dummyPath',
[
- self::GETETAG_PROPERTYNAME,
- self::FILEID_PROPERTYNAME,
- self::SIZE_PROPERTYNAME,
- self::PERMISSIONS_PROPERTYNAME,
- self::DOWNLOADURL_PROPERTYNAME,
- self::DATA_FINGERPRINT_PROPERTYNAME,
+ FilesPlugin::GETETAG_PROPERTYNAME,
+ FilesPlugin::FILEID_PROPERTYNAME,
+ FilesPlugin::SIZE_PROPERTYNAME,
+ FilesPlugin::PERMISSIONS_PROPERTYNAME,
+ FilesPlugin::DOWNLOADURL_PROPERTYNAME,
+ FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME,
],
0
);
@@ -294,20 +367,18 @@ class FilesPluginTest extends TestCase {
$node
);
- $this->assertEquals('"abc"', $propFind->get(self::GETETAG_PROPERTYNAME));
- $this->assertEquals('00000123instanceid', $propFind->get(self::FILEID_PROPERTYNAME));
- $this->assertEquals(1025, $propFind->get(self::SIZE_PROPERTYNAME));
- $this->assertEquals('DWCKMSR', $propFind->get(self::PERMISSIONS_PROPERTYNAME));
- $this->assertEquals(null, $propFind->get(self::DOWNLOADURL_PROPERTYNAME));
- $this->assertEquals('my_fingerprint', $propFind->get(self::DATA_FINGERPRINT_PROPERTYNAME));
- $this->assertEquals([self::DOWNLOADURL_PROPERTYNAME], $propFind->get404Properties());
+ $this->assertEquals('"abc"', $propFind->get(FilesPlugin::GETETAG_PROPERTYNAME));
+ $this->assertEquals('00000123instanceid', $propFind->get(FilesPlugin::FILEID_PROPERTYNAME));
+ $this->assertEquals(1025, $propFind->get(FilesPlugin::SIZE_PROPERTYNAME));
+ $this->assertEquals('DWCKMSR', $propFind->get(FilesPlugin::PERMISSIONS_PROPERTYNAME));
+ $this->assertEquals(null, $propFind->get(FilesPlugin::DOWNLOADURL_PROPERTYNAME));
+ $this->assertEquals('my_fingerprint', $propFind->get(FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME));
+ $this->assertEquals([FilesPlugin::DOWNLOADURL_PROPERTYNAME], $propFind->get404Properties());
}
public function testGetPropertiesForRootDirectory(): void {
- /** @var \OCA\DAV\Connector\Sabre\Directory|\PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var Directory&MockObject $node */
+ $node = $this->createMock(Directory::class);
$node->expects($this->any())->method('getPath')->willReturn('/');
$fileInfo = $this->createMock(FileInfo::class);
@@ -322,7 +393,7 @@ class FilesPluginTest extends TestCase {
$propFind = new PropFind(
'/',
[
- self::DATA_FINGERPRINT_PROPERTYNAME,
+ FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME,
],
0
);
@@ -332,18 +403,15 @@ class FilesPluginTest extends TestCase {
$node
);
- $this->assertEquals('my_fingerprint', $propFind->get(self::DATA_FINGERPRINT_PROPERTYNAME));
+ $this->assertEquals('my_fingerprint', $propFind->get(FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME));
}
public function testGetPropertiesWhenNoPermission(): void {
// No read permissions can be caused by files access control.
// But we still want to load the directory list, so this is okay for us.
// $this->expectException(\Sabre\DAV\Exception\NotFound::class);
-
- /** @var \OCA\DAV\Connector\Sabre\Directory|\PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var Directory&MockObject $node */
+ $node = $this->createMock(Directory::class);
$node->expects($this->any())->method('getPath')->willReturn('/');
$fileInfo = $this->createMock(FileInfo::class);
@@ -358,7 +426,7 @@ class FilesPluginTest extends TestCase {
$propFind = new PropFind(
'/test',
[
- self::DATA_FINGERPRINT_PROPERTYNAME,
+ FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME,
],
0
);
@@ -372,7 +440,7 @@ class FilesPluginTest extends TestCase {
}
public function testUpdateProps(): void {
- $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File');
+ $node = $this->createTestNode(File::class);
$testDate = 'Fri, 13 Feb 2015 00:01:02 GMT';
$testCreationDate = '2007-08-31T16:47+00:00';
@@ -392,9 +460,9 @@ class FilesPluginTest extends TestCase {
// properties to set
$propPatch = new PropPatch([
- self::GETETAG_PROPERTYNAME => 'newetag',
- self::LASTMODIFIED_PROPERTYNAME => $testDate,
- self::CREATIONDATE_PROPERTYNAME => $testCreationDate,
+ FilesPlugin::GETETAG_PROPERTYNAME => 'newetag',
+ FilesPlugin::LASTMODIFIED_PROPERTYNAME => $testDate,
+ FilesPlugin::CREATIONDATE_PROPERTYNAME => $testCreationDate,
]);
@@ -408,19 +476,19 @@ class FilesPluginTest extends TestCase {
$this->assertEmpty($propPatch->getRemainingMutations());
$result = $propPatch->getResult();
- $this->assertEquals(200, $result[self::LASTMODIFIED_PROPERTYNAME]);
- $this->assertEquals(200, $result[self::GETETAG_PROPERTYNAME]);
- $this->assertEquals(200, $result[self::CREATIONDATE_PROPERTYNAME]);
+ $this->assertEquals(200, $result[FilesPlugin::LASTMODIFIED_PROPERTYNAME]);
+ $this->assertEquals(200, $result[FilesPlugin::GETETAG_PROPERTYNAME]);
+ $this->assertEquals(200, $result[FilesPlugin::CREATIONDATE_PROPERTYNAME]);
}
public function testUpdatePropsForbidden(): void {
$propPatch = new PropPatch([
- self::OWNER_ID_PROPERTYNAME => 'user2',
- self::OWNER_DISPLAY_NAME_PROPERTYNAME => 'User Two',
- self::FILEID_PROPERTYNAME => 12345,
- self::PERMISSIONS_PROPERTYNAME => 'C',
- self::SIZE_PROPERTYNAME => 123,
- self::DOWNLOADURL_PROPERTYNAME => 'http://example.com/',
+ FilesPlugin::OWNER_ID_PROPERTYNAME => 'user2',
+ FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME => 'User Two',
+ FilesPlugin::FILEID_PROPERTYNAME => 12345,
+ FilesPlugin::PERMISSIONS_PROPERTYNAME => 'C',
+ FilesPlugin::SIZE_PROPERTYNAME => 123,
+ FilesPlugin::DOWNLOADURL_PROPERTYNAME => 'http://example.com/',
]);
$this->plugin->handleUpdateProperties(
@@ -433,16 +501,16 @@ class FilesPluginTest extends TestCase {
$this->assertEmpty($propPatch->getRemainingMutations());
$result = $propPatch->getResult();
- $this->assertEquals(403, $result[self::OWNER_ID_PROPERTYNAME]);
- $this->assertEquals(403, $result[self::OWNER_DISPLAY_NAME_PROPERTYNAME]);
- $this->assertEquals(403, $result[self::FILEID_PROPERTYNAME]);
- $this->assertEquals(403, $result[self::PERMISSIONS_PROPERTYNAME]);
- $this->assertEquals(403, $result[self::SIZE_PROPERTYNAME]);
- $this->assertEquals(403, $result[self::DOWNLOADURL_PROPERTYNAME]);
+ $this->assertEquals(403, $result[FilesPlugin::OWNER_ID_PROPERTYNAME]);
+ $this->assertEquals(403, $result[FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME]);
+ $this->assertEquals(403, $result[FilesPlugin::FILEID_PROPERTYNAME]);
+ $this->assertEquals(403, $result[FilesPlugin::PERMISSIONS_PROPERTYNAME]);
+ $this->assertEquals(403, $result[FilesPlugin::SIZE_PROPERTYNAME]);
+ $this->assertEquals(403, $result[FilesPlugin::DOWNLOADURL_PROPERTYNAME]);
}
/**
- * Testcase from https://github.com/owncloud/core/issues/5251
+ * Test case from https://github.com/owncloud/core/issues/5251
*
* |-FolderA
* |-text.txt
@@ -456,66 +524,122 @@ class FilesPluginTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->expectExceptionMessage('FolderA/test.txt cannot be deleted');
- $fileInfoFolderATestTXT = $this->getMockBuilder(FileInfo::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $fileInfoFolderATestTXT = $this->createMock(FileInfo::class);
$fileInfoFolderATestTXT->expects($this->once())
->method('isDeletable')
->willReturn(false);
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
- $node->expects($this->once())
+ $node = $this->createMock(Node::class);
+ $node->expects($this->atLeastOnce())
->method('getFileInfo')
->willReturn($fileInfoFolderATestTXT);
- $this->tree->expects($this->once())->method('getNodeForPath')
+ $this->tree->expects($this->atLeastOnce())
+ ->method('getNodeForPath')
->willReturn($node);
$this->plugin->checkMove('FolderA/test.txt', 'test.txt');
}
public function testMoveSrcDeletable(): void {
- $fileInfoFolderATestTXT = $this->getMockBuilder(FileInfo::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $fileInfoFolderATestTXT = $this->createMock(FileInfo::class);
$fileInfoFolderATestTXT->expects($this->once())
->method('isDeletable')
->willReturn(true);
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
- $node->expects($this->once())
+ $node = $this->createMock(Node::class);
+ $node->expects($this->atLeastOnce())
->method('getFileInfo')
->willReturn($fileInfoFolderATestTXT);
- $this->tree->expects($this->once())->method('getNodeForPath')
+ $this->tree->expects($this->atLeastOnce())
+ ->method('getNodeForPath')
->willReturn($node);
$this->plugin->checkMove('FolderA/test.txt', 'test.txt');
}
-
public function testMoveSrcNotExist(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
$this->expectExceptionMessage('FolderA/test.txt does not exist');
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
- $node->expects($this->once())
+ $node = $this->createMock(Node::class);
+ $node->expects($this->atLeastOnce())
->method('getFileInfo')
->willReturn(null);
- $this->tree->expects($this->once())->method('getNodeForPath')
+ $this->tree->expects($this->atLeastOnce())
+ ->method('getNodeForPath')
->willReturn($node);
$this->plugin->checkMove('FolderA/test.txt', 'test.txt');
}
- public function downloadHeadersProvider() {
+ public function testMoveDestinationInvalid(): void {
+ $this->expectException(InvalidPath::class);
+ $this->expectExceptionMessage('Mocked exception');
+
+ $fileInfoFolderATestTXT = $this->createMock(FileInfo::class);
+ $fileInfoFolderATestTXT->expects(self::any())
+ ->method('isDeletable')
+ ->willReturn(true);
+
+ $node = $this->createMock(Node::class);
+ $node->expects($this->atLeastOnce())
+ ->method('getFileInfo')
+ ->willReturn($fileInfoFolderATestTXT);
+
+ $this->tree->expects($this->atLeastOnce())
+ ->method('getNodeForPath')
+ ->willReturn($node);
+
+ $this->filenameValidator->expects(self::once())
+ ->method('validateFilename')
+ ->with('invalid\\path.txt')
+ ->willThrowException(new InvalidPathException('Mocked exception'));
+
+ $this->plugin->checkMove('FolderA/test.txt', 'invalid\\path.txt');
+ }
+
+ public function testCopySrcNotExist(): void {
+ $this->expectException(\Sabre\DAV\Exception\NotFound::class);
+ $this->expectExceptionMessage('FolderA/test.txt does not exist');
+
+ $node = $this->createMock(Node::class);
+ $node->expects($this->atLeastOnce())
+ ->method('getFileInfo')
+ ->willReturn(null);
+
+ $this->tree->expects($this->atLeastOnce())
+ ->method('getNodeForPath')
+ ->willReturn($node);
+
+ $this->plugin->checkCopy('FolderA/test.txt', 'test.txt');
+ }
+
+ public function testCopyDestinationInvalid(): void {
+ $this->expectException(InvalidPath::class);
+ $this->expectExceptionMessage('Mocked exception');
+
+ $fileInfoFolderATestTXT = $this->createMock(FileInfo::class);
+ $node = $this->createMock(Node::class);
+ $node->expects($this->atLeastOnce())
+ ->method('getFileInfo')
+ ->willReturn($fileInfoFolderATestTXT);
+
+ $this->tree->expects($this->atLeastOnce())
+ ->method('getNodeForPath')
+ ->willReturn($node);
+
+ $this->filenameValidator->expects(self::once())
+ ->method('validateFilename')
+ ->with('invalid\\path.txt')
+ ->willThrowException(new InvalidPathException('Mocked exception'));
+
+ $this->plugin->checkCopy('FolderA/test.txt', 'invalid\\path.txt');
+ }
+
+ public static function downloadHeadersProvider(): array {
return [
[
false,
@@ -528,25 +652,17 @@ class FilesPluginTest extends TestCase {
];
}
- /**
- * @dataProvider downloadHeadersProvider
- */
- public function testDownloadHeaders($isClumsyAgent, $contentDispositionHeader): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ #[\PHPUnit\Framework\Attributes\DataProvider('downloadHeadersProvider')]
+ public function testDownloadHeaders(bool $isClumsyAgent, string $contentDispositionHeader): void {
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request
->expects($this->once())
->method('getPath')
->willReturn('test/somefile.xml');
- $node = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(File::class);
$node
->expects($this->once())
->method('getName')
@@ -563,25 +679,29 @@ class FilesPluginTest extends TestCase {
->method('isUserAgent')
->willReturn($isClumsyAgent);
+ $calls = [
+ ['Content-Disposition', $contentDispositionHeader],
+ ['X-Accel-Buffering', 'no'],
+ ];
$response
- ->expects($this->exactly(2))
+ ->expects($this->exactly(count($calls)))
->method('addHeader')
- ->withConsecutive(
- ['Content-Disposition', $contentDispositionHeader],
- ['X-Accel-Buffering', 'no']
- );
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertSame($expected, func_get_args());
+ });
$this->plugin->httpGet($request, $response);
}
public function testHasPreview(): void {
- /** @var \OCA\DAV\Connector\Sabre\Directory | \PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\Directory');
+ /** @var Directory&MockObject $node */
+ $node = $this->createTestNode(Directory::class);
$propFind = new PropFind(
'/dummyPath',
[
- self::HAS_PREVIEW_PROPERTYNAME
+ FilesPlugin::HAS_PREVIEW_PROPERTYNAME
],
0
);
@@ -595,6 +715,6 @@ class FilesPluginTest extends TestCase {
$node
);
- $this->assertEquals("false", $propFind->get(self::HAS_PREVIEW_PROPERTYNAME));
+ $this->assertEquals('false', $propFind->get(FilesPlugin::HAS_PREVIEW_PROPERTYNAME));
}
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php
index 97f21572945..176949f999c 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -9,11 +10,14 @@ namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OC\Files\View;
use OCA\DAV\Connector\Sabre\Directory;
+use OCA\DAV\Connector\Sabre\FilesPlugin;
use OCA\DAV\Connector\Sabre\FilesReportPlugin as FilesReportPluginImplementation;
+use OCP\Accounts\IAccountManager;
use OCP\App\IAppManager;
use OCP\Files\File;
use OCP\Files\FileInfo;
use OCP\Files\Folder;
+use OCP\Files\IFilenameValidator;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IPreview;
@@ -28,83 +32,45 @@ use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagNotFoundException;
use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\INode;
+use Sabre\DAV\Server;
use Sabre\DAV\Tree;
use Sabre\HTTP\ResponseInterface;
class FilesReportPluginTest extends \Test\TestCase {
- /** @var \Sabre\DAV\Server|MockObject */
- private $server;
- /** @var \Sabre\DAV\Tree|MockObject */
- private $tree;
-
- /** @var ISystemTagObjectMapper|MockObject */
- private $tagMapper;
-
- /** @var ISystemTagManager|MockObject */
- private $tagManager;
-
- /** @var ITags|MockObject */
- private $privateTags;
-
- private ITagManager|MockObject $privateTagManager;
-
- /** @var \OCP\IUserSession */
- private $userSession;
-
- /** @var FilesReportPluginImplementation */
- private $plugin;
-
- /** @var View|MockObject **/
- private $view;
-
- /** @var IGroupManager|MockObject **/
- private $groupManager;
-
- /** @var Folder|MockObject **/
- private $userFolder;
-
- /** @var IPreview|MockObject * */
- private $previewManager;
-
- /** @var IAppManager|MockObject * */
- private $appManager;
+ private \Sabre\DAV\Server&MockObject $server;
+ private Tree&MockObject $tree;
+ private ISystemTagObjectMapper&MockObject $tagMapper;
+ private ISystemTagManager&MockObject $tagManager;
+ private ITags&MockObject $privateTags;
+ private ITagManager&MockObject $privateTagManager;
+ private IUserSession&MockObject $userSession;
+ private FilesReportPluginImplementation $plugin;
+ private View&MockObject $view;
+ private IGroupManager&MockObject $groupManager;
+ private Folder&MockObject $userFolder;
+ private IPreview&MockObject $previewManager;
+ private IAppManager&MockObject $appManager;
protected function setUp(): void {
parent::setUp();
- $this->tree = $this->getMockBuilder(Tree::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->tree = $this->createMock(Tree::class);
+ $this->view = $this->createMock(View::class);
- $this->server = $this->getMockBuilder('\Sabre\DAV\Server')
+ $this->server = $this->getMockBuilder(Server::class)
->setConstructorArgs([$this->tree])
- ->setMethods(['getRequestUri', 'getBaseUri'])
+ ->onlyMethods(['getRequestUri', 'getBaseUri'])
->getMock();
$this->server->expects($this->any())
->method('getBaseUri')
->willReturn('http://example.com/owncloud/remote.php/dav');
- $this->groupManager = $this->getMockBuilder(IGroupManager::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->userFolder = $this->getMockBuilder(Folder::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->previewManager = $this->getMockBuilder(IPreview::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->appManager = $this->getMockBuilder(IAppManager::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $this->groupManager = $this->createMock(IGroupManager::class);
+ $this->userFolder = $this->createMock(Folder::class);
+ $this->previewManager = $this->createMock(IPreview::class);
+ $this->appManager = $this->createMock(IAppManager::class);
$this->tagManager = $this->createMock(ISystemTagManager::class);
$this->tagMapper = $this->createMock(ISystemTagObjectMapper::class);
$this->userSession = $this->createMock(IUserSession::class);
@@ -115,9 +81,7 @@ class FilesReportPluginTest extends \Test\TestCase {
->with('files')
->willReturn($this->privateTags);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('testuser');
@@ -144,11 +108,7 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->tree->expects($this->any())
->method('getNodeForPath')
->with('/' . $path)
- ->willReturn(
- $this->getMockBuilder(INode::class)
- ->disableOriginalConstructor()
- ->getMock()
- );
+ ->willReturn($this->createMock(INode::class));
$this->server->expects($this->any())
->method('getRequestUri')
@@ -202,16 +162,12 @@ class FilesReportPluginTest extends \Test\TestCase {
->method('isAdmin')
->willReturn(true);
- $reportTargetNode = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $reportTargetNode = $this->createMock(Directory::class);
$reportTargetNode->expects($this->any())
->method('getPath')
->willReturn('');
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $response = $this->createMock(ResponseInterface::class);
$response->expects($this->once())
->method('setHeader')
@@ -260,14 +216,10 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->userFolder->expects($this->exactly(2))
->method('searchBySystemTag')
- ->withConsecutive(
- ['OneTwoThree'],
- ['FourFiveSix'],
- )
- ->willReturnOnConsecutiveCalls(
- [$filesNode1],
- [$filesNode2],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, [$filesNode1]],
+ ['FourFiveSix', 'testuser', 0, 0, [$filesNode2]],
+ ]);
$this->server->expects($this->any())
->method('getRequestUri')
@@ -279,74 +231,56 @@ class FilesReportPluginTest extends \Test\TestCase {
}
public function testFindNodesByFileIdsRoot(): void {
- $filesNode1 = $this->getMockBuilder(Folder::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $filesNode1 = $this->createMock(Folder::class);
$filesNode1->expects($this->once())
->method('getName')
->willReturn('first node');
- $filesNode2 = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $filesNode2 = $this->createMock(File::class);
$filesNode2->expects($this->once())
->method('getName')
->willReturn('second node');
- $reportTargetNode = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $reportTargetNode = $this->createMock(Directory::class);
$reportTargetNode->expects($this->any())
->method('getPath')
->willReturn('/');
$this->userFolder->expects($this->exactly(2))
->method('getFirstNodeById')
- ->withConsecutive(
- ['111'],
- ['222'],
- )
- ->willReturnOnConsecutiveCalls(
- $filesNode1,
- $filesNode2,
- );
+ ->willReturnMap([
+ [111, $filesNode1],
+ [222, $filesNode2],
+ ]);
- /** @var \OCA\DAV\Connector\Sabre\Directory|MockObject $reportTargetNode */
+ /** @var Directory&MockObject $reportTargetNode */
$result = $this->plugin->findNodesByFileIds($reportTargetNode, ['111', '222']);
$this->assertCount(2, $result);
- $this->assertInstanceOf('\OCA\DAV\Connector\Sabre\Directory', $result[0]);
+ $this->assertInstanceOf(Directory::class, $result[0]);
$this->assertEquals('first node', $result[0]->getName());
- $this->assertInstanceOf('\OCA\DAV\Connector\Sabre\File', $result[1]);
+ $this->assertInstanceOf(\OCA\DAV\Connector\Sabre\File::class, $result[1]);
$this->assertEquals('second node', $result[1]->getName());
}
public function testFindNodesByFileIdsSubDir(): void {
- $filesNode1 = $this->getMockBuilder(Folder::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $filesNode1 = $this->createMock(Folder::class);
$filesNode1->expects($this->once())
->method('getName')
->willReturn('first node');
- $filesNode2 = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $filesNode2 = $this->createMock(File::class);
$filesNode2->expects($this->once())
->method('getName')
->willReturn('second node');
- $reportTargetNode = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $reportTargetNode = $this->createMock(Directory::class);
$reportTargetNode->expects($this->any())
->method('getPath')
->willReturn('/sub1/sub2');
- $subNode = $this->getMockBuilder(Folder::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $subNode = $this->createMock(Folder::class);
$this->userFolder->expects($this->once())
->method('get')
@@ -355,22 +289,18 @@ class FilesReportPluginTest extends \Test\TestCase {
$subNode->expects($this->exactly(2))
->method('getFirstNodeById')
- ->withConsecutive(
- ['111'],
- ['222'],
- )
- ->willReturnOnConsecutiveCalls(
- $filesNode1,
- $filesNode2,
- );
+ ->willReturnMap([
+ [111, $filesNode1],
+ [222, $filesNode2],
+ ]);
- /** @var \OCA\DAV\Connector\Sabre\Directory|MockObject $reportTargetNode */
+ /** @var Directory&MockObject $reportTargetNode */
$result = $this->plugin->findNodesByFileIds($reportTargetNode, ['111', '222']);
$this->assertCount(2, $result);
- $this->assertInstanceOf('\OCA\DAV\Connector\Sabre\Directory', $result[0]);
+ $this->assertInstanceOf(Directory::class, $result[0]);
$this->assertEquals('first node', $result[0]->getName());
- $this->assertInstanceOf('\OCA\DAV\Connector\Sabre\File', $result[1]);
+ $this->assertInstanceOf(\OCA\DAV\Connector\Sabre\File::class, $result[1]);
$this->assertEquals('second node', $result[1]->getName());
}
@@ -380,12 +310,8 @@ class FilesReportPluginTest extends \Test\TestCase {
$fileInfo = $this->createMock(FileInfo::class);
$fileInfo->method('isReadable')->willReturn(true);
- $node1 = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $node2 = $this->getMockBuilder(\OCA\DAV\Connector\Sabre\File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node1 = $this->createMock(Directory::class);
+ $node2 = $this->createMock(\OCA\DAV\Connector\Sabre\File::class);
$node1->expects($this->once())
->method('getInternalFileId')
@@ -405,17 +331,19 @@ class FilesReportPluginTest extends \Test\TestCase {
->willReturn('/sub/node2');
$node2->method('getFileInfo')->willReturn($fileInfo);
- $config = $this->getMockBuilder(IConfig::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $config = $this->createMock(IConfig::class);
+ $validator = $this->createMock(IFilenameValidator::class);
+ $accountManager = $this->createMock(IAccountManager::class);
$this->server->addPlugin(
- new \OCA\DAV\Connector\Sabre\FilesPlugin(
+ new FilesPlugin(
$this->tree,
$config,
$this->createMock(IRequest::class),
$this->previewManager,
- $this->createMock(IUserSession::class)
+ $this->createMock(IUserSession::class),
+ $validator,
+ $accountManager,
)
);
$this->plugin->initialize($this->server);
@@ -476,7 +404,7 @@ class FilesReportPluginTest extends \Test\TestCase {
->with('OneTwoThree')
->willReturn([$filesNode1, $filesNode2]);
- $this->assertEquals([$filesNode1, $filesNode2], $this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, 0, 0]));
+ $this->assertEquals([$filesNode1, $filesNode2], self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, 0, 0]));
}
public function testProcessFilterRulesAndCondition(): void {
@@ -528,21 +456,17 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->userFolder->expects($this->exactly(2))
->method('searchBySystemTag')
- ->withConsecutive(
- ['OneTwoThree'],
- ['FourFiveSix'],
- )
- ->willReturnOnConsecutiveCalls(
- [$filesNode1, $filesNode2],
- [$filesNode2, $filesNode3],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, [$filesNode1, $filesNode2]],
+ ['FourFiveSix', 'testuser', 0, 0, [$filesNode2, $filesNode3]],
+ ]);
$rules = [
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'],
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'],
];
- $this->assertEquals([$filesNode2], array_values($this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
+ $this->assertEquals([$filesNode2], array_values(self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
}
public function testProcessFilterRulesAndConditionWithOneEmptyResult(): void {
@@ -587,21 +511,17 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->userFolder->expects($this->exactly(2))
->method('searchBySystemTag')
- ->withConsecutive(
- ['OneTwoThree'],
- ['FourFiveSix'],
- )
- ->willReturnOnConsecutiveCalls(
- [$filesNode1, $filesNode2],
- [],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, [$filesNode1, $filesNode2]],
+ ['FourFiveSix', 'testuser', 0, 0, []],
+ ]);
$rules = [
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'],
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'],
];
- $this->assertEquals([], $this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null]));
+ $this->assertEquals([], self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null]));
}
public function testProcessFilterRulesAndConditionWithFirstEmptyResult(): void {
@@ -646,18 +566,16 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->userFolder->expects($this->once())
->method('searchBySystemTag')
- ->with('OneTwoThree')
- ->willReturnOnConsecutiveCalls(
- [],
- [$filesNode1, $filesNode2],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, []],
+ ]);
$rules = [
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'],
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'],
];
- $this->assertEquals([], $this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null]));
+ $this->assertEquals([], self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null]));
}
public function testProcessFilterRulesAndConditionWithEmptyMidResult(): void {
@@ -704,7 +622,7 @@ class FilesReportPluginTest extends \Test\TestCase {
$tag789 = $this->createMock(ISystemTag::class);
$tag789->expects($this->any())
->method('getName')
- ->willReturn('SevenEightNein');
+ ->willReturn('SevenEightNine');
$tag789->expects($this->any())
->method('isUserVisible')
->willReturn(true);
@@ -716,12 +634,10 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->userFolder->expects($this->exactly(2))
->method('searchBySystemTag')
- ->withConsecutive(['OneTwoThree'], ['FourFiveSix'], ['SevenEightNein'])
- ->willReturnOnConsecutiveCalls(
- [$filesNode1, $filesNode2],
- [$filesNode3],
- [$filesNode1, $filesNode2],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, [$filesNode1, $filesNode2]],
+ ['FourFiveSix', 'testuser', 0, 0, [$filesNode3]],
+ ]);
$rules = [
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'],
@@ -729,7 +645,7 @@ class FilesReportPluginTest extends \Test\TestCase {
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '789'],
];
- $this->assertEquals([], array_values($this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
+ $this->assertEquals([], array_values(self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
}
public function testProcessFilterRulesInvisibleTagAsAdmin(): void {
@@ -781,18 +697,17 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->userFolder->expects($this->exactly(2))
->method('searchBySystemTag')
- ->withConsecutive(['OneTwoThree'], ['FourFiveSix'])
- ->willReturnOnConsecutiveCalls(
- [$filesNode1, $filesNode2],
- [$filesNode2, $filesNode3],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, [$filesNode1, $filesNode2]],
+ ['FourFiveSix', 'testuser', 0, 0, [$filesNode2, $filesNode3]],
+ ]);
$rules = [
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'],
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'],
];
- $this->assertEquals([$filesNode2], array_values($this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
+ $this->assertEquals([$filesNode2], array_values(self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
}
@@ -831,7 +746,7 @@ class FilesReportPluginTest extends \Test\TestCase {
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'],
];
- $this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null]);
+ self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null]);
}
public function testProcessFilterRulesVisibleTagAsUser(): void {
@@ -896,18 +811,17 @@ class FilesReportPluginTest extends \Test\TestCase {
// main assertion: only user visible tags are being passed through.
$this->userFolder->expects($this->exactly(2))
->method('searchBySystemTag')
- ->withConsecutive(['OneTwoThree'], ['FourFiveSix'])
- ->willReturnOnConsecutiveCalls(
- [$filesNode1, $filesNode2],
- [$filesNode2, $filesNode3],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, [$filesNode1, $filesNode2]],
+ ['FourFiveSix', 'testuser', 0, 0, [$filesNode2, $filesNode3]],
+ ]);
$rules = [
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'],
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'],
];
- $this->assertEquals([$filesNode2], array_values($this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
+ $this->assertEquals([$filesNode2], array_values(self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
}
public function testProcessFavoriteFilter(): void {
@@ -919,10 +833,10 @@ class FilesReportPluginTest extends \Test\TestCase {
->method('getFavorites')
->willReturn(['456', '789']);
- $this->assertEquals(['456', '789'], array_values($this->invokePrivate($this->plugin, 'processFilterRulesForFileIDs', [$rules])));
+ $this->assertEquals(['456', '789'], array_values(self::invokePrivate($this->plugin, 'processFilterRulesForFileIDs', [$rules])));
}
- public function filesBaseUriProvider() {
+ public static function filesBaseUriProvider(): array {
return [
['', '', ''],
['files/username', '', '/files/username'],
@@ -932,10 +846,8 @@ class FilesReportPluginTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider filesBaseUriProvider
- */
- public function testFilesBaseUri($uri, $reportPath, $expectedUri): void {
- $this->assertEquals($expectedUri, $this->invokePrivate($this->plugin, 'getFilesBaseUri', [$uri, $reportPath]));
+ #[\PHPUnit\Framework\Attributes\DataProvider('filesBaseUriProvider')]
+ public function testFilesBaseUri(string $uri, string $reportPath, string $expectedUri): void {
+ $this->assertEquals($expectedUri, self::invokePrivate($this->plugin, 'getFilesBaseUri', [$uri, $reportPath]));
}
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/MaintenancePluginTest.php b/apps/dav/tests/unit/Connector/Sabre/MaintenancePluginTest.php
index 28c22202c1e..bc1d50ac41f 100644
--- a/apps/dav/tests/unit/Connector/Sabre/MaintenancePluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/MaintenancePluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -10,6 +11,7 @@ namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OCA\DAV\Connector\Sabre\MaintenancePlugin;
use OCP\IConfig;
use OCP\IL10N;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
/**
@@ -18,18 +20,15 @@ use Test\TestCase;
* @package OCA\DAV\Tests\unit\Connector\Sabre
*/
class MaintenancePluginTest extends TestCase {
- /** @var IConfig */
- private $config;
- /** @var \PHPUnit\Framework\MockObject\Builder\InvocationMocker|\PHPUnit_Framework_MockObject_Builder_InvocationMocker|IL10N */
- private $l10n;
- /** @var MaintenancePlugin */
- private $maintenancePlugin;
+ private IConfig&MockObject $config;
+ private IL10N&MockObject $l10n;
+ private MaintenancePlugin $maintenancePlugin;
protected function setUp(): void {
parent::setUp();
- $this->config = $this->getMockBuilder(IConfig::class)->getMock();
- $this->l10n = $this->getMockBuilder(IL10N::class)->getMock();
+ $this->config = $this->createMock(IConfig::class);
+ $this->l10n = $this->createMock(IL10N::class);
$this->maintenancePlugin = new MaintenancePlugin($this->config, $this->l10n);
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/NodeTest.php b/apps/dav/tests/unit/Connector/Sabre/NodeTest.php
index 17550a2874f..11970769a1e 100644
--- a/apps/dav/tests/unit/Connector/Sabre/NodeTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/NodeTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -10,17 +11,20 @@ namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OC\Files\FileInfo;
use OC\Files\Mount\MountPoint;
+use OC\Files\Node\Folder;
use OC\Files\View;
use OC\Share20\ShareAttributes;
+use OCA\DAV\Connector\Sabre\File;
use OCA\Files_Sharing\SharedMount;
use OCA\Files_Sharing\SharedStorage;
use OCP\Constants;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Mount\IMountPoint;
-use OCP\Files\Storage;
+use OCP\Files\Storage\IStorage;
use OCP\ICache;
use OCP\Share\IManager;
use OCP\Share\IShare;
+use PHPUnit\Framework\MockObject\MockObject;
/**
* Class NodeTest
@@ -29,7 +33,7 @@ use OCP\Share\IShare;
* @package OCA\DAV\Tests\unit\Connector\Sabre
*/
class NodeTest extends \Test\TestCase {
- public function davPermissionsProvider() {
+ public static function davPermissionsProvider(): array {
return [
[Constants::PERMISSION_ALL, 'file', false, Constants::PERMISSION_ALL, false, 'test', 'RGDNVW'],
[Constants::PERMISSION_ALL, 'dir', false, Constants::PERMISSION_ALL, false, 'test', 'RGDNVCK'],
@@ -47,10 +51,8 @@ class NodeTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider davPermissionsProvider
- */
- public function testDavPermissions($permissions, $type, $shared, $shareRootPermissions, $mounted, $internalPath, $expected): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('davPermissionsProvider')]
+ public function testDavPermissions(int $permissions, string $type, bool $shared, int $shareRootPermissions, bool $mounted, string $internalPath, string $expected): void {
$info = $this->getMockBuilder(FileInfo::class)
->disableOriginalConstructor()
->onlyMethods(['getPermissions', 'isShared', 'isMounted', 'getType', 'getInternalPath', 'getStorage', 'getMountPoint'])
@@ -73,7 +75,7 @@ class NodeTest extends \Test\TestCase {
return $this->createMock(MountPoint::class);
}
});
- $storage = $this->createMock(Storage\IStorage::class);
+ $storage = $this->createMock(IStorage::class);
if ($shared) {
$storage->method('instanceOfStorage')
->willReturn(true);
@@ -91,15 +93,13 @@ class NodeTest extends \Test\TestCase {
}
$info->method('getStorage')
->willReturn($storage);
- $view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $view = $this->createMock(View::class);
- $node = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $node = new File($view, $info);
$this->assertEquals($expected, $node->getDavPermissions());
}
- public function sharePermissionsProvider() {
+ public static function sharePermissionsProvider(): array {
return [
[\OCP\Files\FileInfo::TYPE_FILE, null, 1, 1],
[\OCP\Files\FileInfo::TYPE_FILE, null, 3, 3],
@@ -139,21 +139,15 @@ class NodeTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider sharePermissionsProvider
- */
- public function testSharePermissions($type, $user, $permissions, $expected): void {
- $storage = $this->getMockBuilder(Storage::class)
- ->disableOriginalConstructor()
- ->getMock();
+ #[\PHPUnit\Framework\Attributes\DataProvider('sharePermissionsProvider')]
+ public function testSharePermissions(string $type, ?string $user, int $permissions, int $expected): void {
+ $storage = $this->createMock(IStorage::class);
$storage->method('getPermissions')->willReturn($permissions);
- $mountpoint = $this->getMockBuilder(IMountPoint::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $mountpoint = $this->createMock(IMountPoint::class);
$mountpoint->method('getMountPoint')->willReturn('myPath');
- $shareManager = $this->getMockBuilder(IManager::class)->disableOriginalConstructor()->getMock();
- $share = $this->getMockBuilder(IShare::class)->disableOriginalConstructor()->getMock();
+ $shareManager = $this->createMock(IManager::class);
+ $share = $this->createMock(IShare::class);
if ($user === null) {
$shareManager->expects($this->never())->method('getShareByToken');
@@ -166,7 +160,7 @@ class NodeTest extends \Test\TestCase {
$info = $this->getMockBuilder(FileInfo::class)
->disableOriginalConstructor()
- ->setMethods(['getStorage', 'getType', 'getMountPoint', 'getPermissions'])
+ ->onlyMethods(['getStorage', 'getType', 'getMountPoint', 'getPermissions'])
->getMock();
$info->method('getStorage')->willReturn($storage);
@@ -174,11 +168,9 @@ class NodeTest extends \Test\TestCase {
$info->method('getMountPoint')->willReturn($mountpoint);
$info->method('getPermissions')->willReturn($permissions);
- $view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $view = $this->createMock(View::class);
- $node = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $node = new File($view, $info);
$this->invokePrivate($node, 'shareManager', [$shareManager]);
$this->assertEquals($expected, $node->getSharePermissions($user));
}
@@ -186,11 +178,11 @@ class NodeTest extends \Test\TestCase {
public function testShareAttributes(): void {
$storage = $this->getMockBuilder(SharedStorage::class)
->disableOriginalConstructor()
- ->setMethods(['getShare'])
+ ->onlyMethods(['getShare'])
->getMock();
- $shareManager = $this->getMockBuilder(IManager::class)->disableOriginalConstructor()->getMock();
- $share = $this->getMockBuilder(IShare::class)->disableOriginalConstructor()->getMock();
+ $shareManager = $this->createMock(IManager::class);
+ $share = $this->createMock(IShare::class);
$storage->expects($this->once())
->method('getShare')
@@ -201,58 +193,53 @@ class NodeTest extends \Test\TestCase {
$share->expects($this->once())->method('getAttributes')->willReturn($attributes);
- $info = $this->getMockBuilder(FileInfo::class)
+ /** @var Folder&MockObject $info */
+ $info = $this->getMockBuilder(Folder::class)
->disableOriginalConstructor()
- ->setMethods(['getStorage', 'getType'])
+ ->onlyMethods(['getStorage', 'getType'])
->getMock();
$info->method('getStorage')->willReturn($storage);
$info->method('getType')->willReturn(FileInfo::TYPE_FOLDER);
- $view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var View&MockObject $view */
+ $view = $this->createMock(View::class);
- $node = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $node = new File($view, $info);
$this->invokePrivate($node, 'shareManager', [$shareManager]);
$this->assertEquals($attributes->toArray(), $node->getShareAttributes());
}
public function testShareAttributesNonShare(): void {
- $storage = $this->getMockBuilder(Storage::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $storage = $this->createMock(IStorage::class);
+ $shareManager = $this->createMock(IManager::class);
- $shareManager = $this->getMockBuilder(IManager::class)->disableOriginalConstructor()->getMock();
-
- $info = $this->getMockBuilder(FileInfo::class)
+ /** @var Folder&MockObject */
+ $info = $this->getMockBuilder(Folder::class)
->disableOriginalConstructor()
- ->setMethods(['getStorage', 'getType'])
+ ->onlyMethods(['getStorage', 'getType'])
->getMock();
$info->method('getStorage')->willReturn($storage);
$info->method('getType')->willReturn(FileInfo::TYPE_FOLDER);
- $view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var View&MockObject */
+ $view = $this->createMock(View::class);
- $node = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $node = new File($view, $info);
$this->invokePrivate($node, 'shareManager', [$shareManager]);
$this->assertEquals([], $node->getShareAttributes());
}
- public function sanitizeMtimeProvider() {
+ public static function sanitizeMtimeProvider(): array {
return [
[123456789, 123456789],
['987654321', 987654321],
];
}
- /**
- * @dataProvider sanitizeMtimeProvider
- */
- public function testSanitizeMtime($mtime, $expected): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('sanitizeMtimeProvider')]
+ public function testSanitizeMtime(string|int $mtime, int $expected): void {
$view = $this->getMockBuilder(View::class)
->disableOriginalConstructor()
->getMock();
@@ -260,31 +247,25 @@ class NodeTest extends \Test\TestCase {
->disableOriginalConstructor()
->getMock();
- $node = new \OCA\DAV\Connector\Sabre\File($view, $info);
+ $node = new File($view, $info);
$result = $this->invokePrivate($node, 'sanitizeMtime', [$mtime]);
$this->assertEquals($expected, $result);
}
- public function invalidSanitizeMtimeProvider() {
+ public static function invalidSanitizeMtimeProvider(): array {
return [
[-1337], [0], ['abcdef'], ['-1337'], ['0'], [12321], [24 * 60 * 60 - 1],
];
}
- /**
- * @dataProvider invalidSanitizeMtimeProvider
- */
- public function testInvalidSanitizeMtime($mtime): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('invalidSanitizeMtimeProvider')]
+ public function testInvalidSanitizeMtime(int|string $mtime): void {
$this->expectException(\InvalidArgumentException::class);
- $view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
- $info = $this->getMockBuilder(FileInfo::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $view = $this->createMock(View::class);
+ $info = $this->createMock(FileInfo::class);
- $node = new \OCA\DAV\Connector\Sabre\File($view, $info);
- $result = $this->invokePrivate($node, 'sanitizeMtime', [$mtime]);
+ $node = new File($view, $info);
+ self::invokePrivate($node, 'sanitizeMtime', [$mtime]);
}
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php b/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php
index ccdb501f7d3..b07778e4fbd 100644
--- a/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -10,9 +11,12 @@ namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OC\Files\FileInfo;
use OC\Files\Filesystem;
use OC\Files\Mount\Manager;
+use OC\Files\Storage\Common;
use OC\Files\Storage\Temporary;
use OC\Files\View;
use OCA\DAV\Connector\Sabre\Directory;
+use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
+use OCA\DAV\Connector\Sabre\File;
use OCA\DAV\Connector\Sabre\ObjectTree;
use OCP\Files\Mount\IMountManager;
@@ -24,7 +28,7 @@ use OCP\Files\Mount\IMountManager;
* @package OCA\DAV\Tests\Unit\Connector\Sabre
*/
class ObjectTreeTest extends \Test\TestCase {
- public function copyDataProvider() {
+ public static function copyDataProvider(): array {
return [
// copy into same dir
['a', 'b', ''],
@@ -35,10 +39,8 @@ class ObjectTreeTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider copyDataProvider
- */
- public function testCopy($sourcePath, $targetPath, $targetParent): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('copyDataProvider')]
+ public function testCopy(string $sourcePath, string $targetPath, string $targetParent): void {
$view = $this->createMock(View::class);
$view->expects($this->once())
->method('verifyPath')
@@ -64,7 +66,7 @@ class ObjectTreeTest extends \Test\TestCase {
$rootDir = new Directory($view, $info);
$objectTree = $this->getMockBuilder(ObjectTree::class)
- ->setMethods(['nodeExists', 'getNodeForPath'])
+ ->onlyMethods(['nodeExists', 'getNodeForPath'])
->setConstructorArgs([$rootDir, $view])
->getMock();
@@ -73,15 +75,13 @@ class ObjectTreeTest extends \Test\TestCase {
->with($this->identicalTo($sourcePath))
->willReturn(false);
- /** @var $objectTree \OCA\DAV\Connector\Sabre\ObjectTree */
+ /** @var ObjectTree $objectTree */
$mountManager = Filesystem::getMountManager();
$objectTree->init($rootDir, $view, $mountManager);
$objectTree->copy($sourcePath, $targetPath);
}
- /**
- * @dataProvider copyDataProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('copyDataProvider')]
public function testCopyFailNotCreatable($sourcePath, $targetPath, $targetParent): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
@@ -107,57 +107,42 @@ class ObjectTreeTest extends \Test\TestCase {
$rootDir = new Directory($view, $info);
$objectTree = $this->getMockBuilder(ObjectTree::class)
- ->setMethods(['nodeExists', 'getNodeForPath'])
+ ->onlyMethods(['nodeExists', 'getNodeForPath'])
->setConstructorArgs([$rootDir, $view])
->getMock();
$objectTree->expects($this->never())
->method('getNodeForPath');
- /** @var $objectTree \OCA\DAV\Connector\Sabre\ObjectTree */
+ /** @var ObjectTree $objectTree */
$mountManager = Filesystem::getMountManager();
$objectTree->init($rootDir, $view, $mountManager);
$objectTree->copy($sourcePath, $targetPath);
}
- /**
- * @dataProvider nodeForPathProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('nodeForPathProvider')]
public function testGetNodeForPath(
- $inputFileName,
- $fileInfoQueryPath,
- $outputFileName,
- $type,
- $enableChunkingHeader
+ string $inputFileName,
+ string $fileInfoQueryPath,
+ string $outputFileName,
+ string $type,
): void {
- if ($enableChunkingHeader) {
- $_SERVER['HTTP_OC_CHUNKED'] = true;
- }
-
- $rootNode = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $mountManager = $this->getMockBuilder(Manager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
- $fileInfo = $this->getMockBuilder(FileInfo::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $rootNode = $this->createMock(Directory::class);
+ $mountManager = $this->createMock(Manager::class);
+ $view = $this->createMock(View::class);
+ $fileInfo = $this->createMock(FileInfo::class);
$fileInfo->method('getType')
->willReturn($type);
$fileInfo->method('getName')
->willReturn($outputFileName);
$fileInfo->method('getStorage')
- ->willReturn($this->createMock(\OC\Files\Storage\Common::class));
+ ->willReturn($this->createMock(Common::class));
$view->method('getFileInfo')
->with($fileInfoQueryPath)
->willReturn($fileInfo);
- $tree = new \OCA\DAV\Connector\Sabre\ObjectTree();
+ $tree = new ObjectTree();
$tree->init($rootNode, $view, $mountManager);
$node = $tree->getNodeForPath($inputFileName);
@@ -166,15 +151,13 @@ class ObjectTreeTest extends \Test\TestCase {
$this->assertEquals($outputFileName, $node->getName());
if ($type === 'file') {
- $this->assertTrue($node instanceof \OCA\DAV\Connector\Sabre\File);
+ $this->assertInstanceOf(File::class, $node);
} else {
- $this->assertTrue($node instanceof \OCA\DAV\Connector\Sabre\Directory);
+ $this->assertInstanceOf(Directory::class, $node);
}
-
- unset($_SERVER['HTTP_OC_CHUNKED']);
}
- public function nodeForPathProvider() {
+ public static function nodeForPathProvider(): array {
return [
// regular file
[
@@ -182,7 +165,6 @@ class ObjectTreeTest extends \Test\TestCase {
'regularfile.txt',
'regularfile.txt',
'file',
- false
],
// regular directory
[
@@ -190,31 +172,6 @@ class ObjectTreeTest extends \Test\TestCase {
'regulardir',
'regulardir',
'dir',
- false
- ],
- // regular file with chunking
- [
- 'regularfile.txt',
- 'regularfile.txt',
- 'regularfile.txt',
- 'file',
- true
- ],
- // regular directory with chunking
- [
- 'regulardir',
- 'regulardir',
- 'regulardir',
- 'dir',
- true
- ],
- // file with chunky file name
- [
- 'regularfile.txt-chunking-123566789-10-1',
- 'regularfile.txt',
- 'regularfile.txt',
- 'file',
- true
],
// regular file in subdir
[
@@ -222,7 +179,6 @@ class ObjectTreeTest extends \Test\TestCase {
'subdir/regularfile.txt',
'regularfile.txt',
'file',
- false
],
// regular directory in subdir
[
@@ -230,22 +186,13 @@ class ObjectTreeTest extends \Test\TestCase {
'subdir/regulardir',
'regulardir',
'dir',
- false
- ],
- // file with chunky file name in subdir
- [
- 'subdir/regularfile.txt-chunking-123566789-10-1',
- 'subdir/regularfile.txt',
- 'regularfile.txt',
- 'file',
- true
],
];
}
public function testGetNodeForPathInvalidPath(): void {
- $this->expectException(\OCA\DAV\Connector\Sabre\Exception\InvalidPath::class);
+ $this->expectException(InvalidPath::class);
$path = '/foo\bar';
@@ -253,7 +200,7 @@ class ObjectTreeTest extends \Test\TestCase {
$storage = new Temporary([]);
$view = $this->getMockBuilder(View::class)
- ->setMethods(['resolvePath'])
+ ->onlyMethods(['resolvePath'])
->getMock();
$view->expects($this->once())
->method('resolvePath')
@@ -261,12 +208,10 @@ class ObjectTreeTest extends \Test\TestCase {
return [$storage, ltrim($path, '/')];
});
- $rootNode = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $rootNode = $this->createMock(Directory::class);
$mountManager = $this->createMock(IMountManager::class);
- $tree = new \OCA\DAV\Connector\Sabre\ObjectTree();
+ $tree = new ObjectTree();
$tree->init($rootNode, $view, $mountManager);
$tree->getNodeForPath($path);
@@ -279,7 +224,7 @@ class ObjectTreeTest extends \Test\TestCase {
$storage = new Temporary([]);
$view = $this->getMockBuilder(View::class)
- ->setMethods(['resolvePath'])
+ ->onlyMethods(['resolvePath'])
->getMock();
$view->expects($this->any())
->method('resolvePath')
@@ -287,12 +232,10 @@ class ObjectTreeTest extends \Test\TestCase {
return [$storage, ltrim($path, '/')];
});
- $rootNode = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $rootNode = $this->createMock(Directory::class);
$mountManager = $this->createMock(IMountManager::class);
- $tree = new \OCA\DAV\Connector\Sabre\ObjectTree();
+ $tree = new ObjectTree();
$tree->init($rootNode, $view, $mountManager);
$this->assertInstanceOf('\Sabre\DAV\INode', $tree->getNodeForPath($path));
diff --git a/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php b/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php
index 03910f32095..e32d2671063 100644
--- a/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -30,38 +32,21 @@ use Sabre\DAV\PropPatch;
use Test\TestCase;
class PrincipalTest extends TestCase {
- /** @var IUserManager | MockObject */
- private $userManager;
-
- /** @var Principal */
- private $connector;
-
- /** @var IGroupManager | MockObject */
- private $groupManager;
-
- /** @var IAccountManager|MockObject */
- private $accountManager;
-
- /** @var IManager | MockObject */
- private $shareManager;
-
- /** @var IUserSession | MockObject */
- private $userSession;
-
- /** @var IAppManager | MockObject */
- private $appManager;
-
- /** @var ProxyMapper | MockObject */
- private $proxyMapper;
-
- /** @var KnownUserService|MockObject */
- private $knownUserService;
- /** @var IConfig | MockObject */
- private $config;
- /** @var IFactory|MockObject */
- private $languageFactory;
+ private IUserManager&MockObject $userManager;
+ private IGroupManager&MockObject $groupManager;
+ private IAccountManager&MockObject $accountManager;
+ private IManager&MockObject $shareManager;
+ private IUserSession&MockObject $userSession;
+ private IAppManager&MockObject $appManager;
+ private ProxyMapper&MockObject $proxyMapper;
+ private KnownUserService&MockObject $knownUserService;
+ private IConfig&MockObject $config;
+ private IFactory&MockObject $languageFactory;
+ private Principal $connector;
protected function setUp(): void {
+ parent::setUp();
+
$this->userManager = $this->createMock(IUserManager::class);
$this->groupManager = $this->createMock(IGroupManager::class);
$this->accountManager = $this->createMock(IAccountManager::class);
@@ -85,7 +70,6 @@ class PrincipalTest extends TestCase {
$this->config,
$this->languageFactory
);
- parent::setUp();
}
public function testGetPrincipalsByPrefixWithoutPrefix(): void {
@@ -96,26 +80,26 @@ class PrincipalTest extends TestCase {
public function testGetPrincipalsByPrefixWithUsers(): void {
$fooUser = $this->createMock(User::class);
$fooUser
- ->expects($this->once())
- ->method('getUID')
- ->willReturn('foo');
+ ->expects($this->once())
+ ->method('getUID')
+ ->willReturn('foo');
$fooUser
- ->expects($this->once())
- ->method('getDisplayName')
- ->willReturn('Dr. Foo-Bar');
+ ->expects($this->once())
+ ->method('getDisplayName')
+ ->willReturn('Dr. Foo-Bar');
$fooUser
- ->expects($this->once())
- ->method('getSystemEMailAddress')
- ->willReturn('');
+ ->expects($this->once())
+ ->method('getSystemEMailAddress')
+ ->willReturn('');
$barUser = $this->createMock(User::class);
$barUser
->expects($this->once())
->method('getUID')
->willReturn('bar');
$barUser
- ->expects($this->once())
- ->method('getSystemEMailAddress')
- ->willReturn('bar@nextcloud.com');
+ ->expects($this->once())
+ ->method('getSystemEMailAddress')
+ ->willReturn('bar@nextcloud.com');
$this->userManager
->expects($this->once())
->method('search')
@@ -125,13 +109,14 @@ class PrincipalTest extends TestCase {
$this->languageFactory
->expects($this->exactly(2))
->method('getUserLanguage')
- ->withConsecutive([$fooUser], [$barUser])
- ->willReturnOnConsecutiveCalls('de', 'en');
+ ->willReturnMap([
+ [$fooUser, 'de'],
+ [$barUser, 'en'],
+ ]);
$fooAccountPropertyCollection = $this->createMock(IAccountPropertyCollection::class);
$fooAccountPropertyCollection->expects($this->once())
->method('getProperties')
- ->with()
->willReturn([]);
$fooAccount = $this->createMock(IAccount::class);
$fooAccount->expects($this->once())
@@ -142,18 +127,15 @@ class PrincipalTest extends TestCase {
$emailPropertyOne = $this->createMock(IAccountProperty::class);
$emailPropertyOne->expects($this->once())
->method('getValue')
- ->with()
->willReturn('alias@nextcloud.com');
$emailPropertyTwo = $this->createMock(IAccountProperty::class);
$emailPropertyTwo->expects($this->once())
->method('getValue')
- ->with()
->willReturn('alias2@nextcloud.com');
$barAccountPropertyCollection = $this->createMock(IAccountPropertyCollection::class);
$barAccountPropertyCollection->expects($this->once())
->method('getProperties')
- ->with()
->willReturn([$emailPropertyOne, $emailPropertyTwo]);
$barAccount = $this->createMock(IAccount::class);
$barAccount->expects($this->once())
@@ -164,8 +146,10 @@ class PrincipalTest extends TestCase {
$this->accountManager
->expects($this->exactly(2))
->method('getAccount')
- ->withConsecutive([$fooUser], [$barUser])
- ->willReturnOnConsecutiveCalls($fooAccount, $barAccount);
+ ->willReturnMap([
+ [$fooUser, $fooAccount],
+ [$barUser, $barAccount],
+ ]);
$expectedResponse = [
0 => [
@@ -229,13 +213,13 @@ class PrincipalTest extends TestCase {
public function testGetPrincipalsByPathWithMail(): void {
$fooUser = $this->createMock(User::class);
$fooUser
- ->expects($this->once())
- ->method('getSystemEMailAddress')
- ->willReturn('foo@nextcloud.com');
+ ->expects($this->once())
+ ->method('getSystemEMailAddress')
+ ->willReturn('foo@nextcloud.com');
$fooUser
- ->expects($this->once())
- ->method('getUID')
- ->willReturn('foo');
+ ->expects($this->once())
+ ->method('getUID')
+ ->willReturn('foo');
$this->userManager
->expects($this->once())
->method('get')
@@ -479,10 +463,8 @@ class PrincipalTest extends TestCase {
['{http://sabredav.org/ns}email-address' => 'foo']));
}
- /**
- * @dataProvider searchPrincipalsDataProvider
- */
- public function testSearchPrincipals($sharingEnabled, $groupsOnly, $test, $result): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('searchPrincipalsDataProvider')]
+ public function testSearchPrincipals(bool $sharingEnabled, bool $groupsOnly, string $test, array $result): void {
$this->shareManager->expects($this->once())
->method('shareAPIEnabled')
->willReturn($sharingEnabled);
@@ -556,7 +538,7 @@ class PrincipalTest extends TestCase {
'{DAV:}displayname' => 'User 12'], $test));
}
- public function searchPrincipalsDataProvider(): array {
+ public static function searchPrincipalsDataProvider(): array {
return [
[true, false, 'allof', ['principals/users/user3']],
[true, false, 'anyof', ['principals/users/user2', 'principals/users/user3', 'principals/users/user4']],
@@ -842,22 +824,20 @@ class PrincipalTest extends TestCase {
$this->assertEquals(null, $this->connector->findByUri('mailto:user@foo.com', 'principals/users'));
}
- /**
- * @dataProvider findByUriWithGroupRestrictionDataProvider
- */
- public function testFindByUriWithGroupRestriction($uri, $email, $expects): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('findByUriWithGroupRestrictionDataProvider')]
+ public function testFindByUriWithGroupRestriction(string $uri, string $email, ?string $expects): void {
$this->shareManager->expects($this->once())
->method('shareApiEnabled')
->willReturn(true);
$this->shareManager->expects($this->once())
- ->method('shareWithGroupMembersOnly')
- ->willReturn(true);
+ ->method('shareWithGroupMembersOnly')
+ ->willReturn(true);
$user = $this->createMock(IUser::class);
$this->userSession->expects($this->once())
- ->method('getUser')
- ->willReturn($user);
+ ->method('getUser')
+ ->willReturn($user);
$user2 = $this->createMock(IUser::class);
$user2->method('getUID')->willReturn('user2');
@@ -865,55 +845,45 @@ class PrincipalTest extends TestCase {
$user3->method('getUID')->willReturn('user3');
$this->userManager->expects($this->once())
- ->method('getByEmail')
- ->with($email)
- ->willReturn([$email === 'user2@foo.bar' ? $user2 : $user3]);
+ ->method('getByEmail')
+ ->with($email)
+ ->willReturn([$email === 'user2@foo.bar' ? $user2 : $user3]);
if ($email === 'user2@foo.bar') {
$this->groupManager->expects($this->exactly(2))
->method('getUserGroupIds')
- ->withConsecutive(
- [$user],
- [$user2],
- )
- ->willReturnOnConsecutiveCalls(
- ['group1', 'group2'],
- ['group1', 'group3'],
- );
+ ->willReturnMap([
+ [$user, ['group1', 'group2']],
+ [$user2, ['group1', 'group3']],
+ ]);
} else {
$this->groupManager->expects($this->exactly(2))
->method('getUserGroupIds')
- ->withConsecutive(
- [$user],
- [$user3],
- )
- ->willReturnOnConsecutiveCalls(
- ['group1', 'group2'],
- ['group3', 'group3'],
- );
+ ->willReturnMap([
+ [$user, ['group1', 'group2']],
+ [$user3, ['group3', 'group3']],
+ ]);
}
$this->assertEquals($expects, $this->connector->findByUri($uri, 'principals/users'));
}
- public function findByUriWithGroupRestrictionDataProvider(): array {
+ public static function findByUriWithGroupRestrictionDataProvider(): array {
return [
['mailto:user2@foo.bar', 'user2@foo.bar', 'principals/users/user2'],
['mailto:user3@foo.bar', 'user3@foo.bar', null],
];
}
- /**
- * @dataProvider findByUriWithoutGroupRestrictionDataProvider
- */
- public function testFindByUriWithoutGroupRestriction($uri, $email, $expects): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('findByUriWithoutGroupRestrictionDataProvider')]
+ public function testFindByUriWithoutGroupRestriction(string $uri, string $email, string $expects): void {
$this->shareManager->expects($this->once())
->method('shareApiEnabled')
->willReturn(true);
$this->shareManager->expects($this->once())
- ->method('shareWithGroupMembersOnly')
- ->willReturn(false);
+ ->method('shareWithGroupMembersOnly')
+ ->willReturn(false);
$user2 = $this->createMock(IUser::class);
$user2->method('getUID')->willReturn('user2');
@@ -921,14 +891,14 @@ class PrincipalTest extends TestCase {
$user3->method('getUID')->willReturn('user3');
$this->userManager->expects($this->once())
- ->method('getByEmail')
- ->with($email)
- ->willReturn([$email === 'user2@foo.bar' ? $user2 : $user3]);
+ ->method('getByEmail')
+ ->with($email)
+ ->willReturn([$email === 'user2@foo.bar' ? $user2 : $user3]);
$this->assertEquals($expects, $this->connector->findByUri($uri, 'principals/users'));
}
- public function findByUriWithoutGroupRestrictionDataProvider(): array {
+ public static function findByUriWithoutGroupRestrictionDataProvider(): array {
return [
['mailto:user2@foo.bar', 'user2@foo.bar', 'principals/users/user2'],
['mailto:user3@foo.bar', 'user3@foo.bar', 'principals/users/user3'],
diff --git a/apps/dav/tests/unit/Connector/Sabre/PropFindMonitorPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/PropFindMonitorPluginTest.php
new file mode 100644
index 00000000000..9d22befa201
--- /dev/null
+++ b/apps/dav/tests/unit/Connector/Sabre/PropFindMonitorPluginTest.php
@@ -0,0 +1,133 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace unit\Connector\Sabre;
+
+use OCA\DAV\Connector\Sabre\PropFindMonitorPlugin;
+use OCA\DAV\Connector\Sabre\Server;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+use Sabre\HTTP\Request;
+use Sabre\HTTP\Response;
+use Test\TestCase;
+
+class PropFindMonitorPluginTest extends TestCase {
+
+ private PropFindMonitorPlugin $plugin;
+ private Server&MockObject $server;
+ private LoggerInterface&MockObject $logger;
+ private Request&MockObject $request;
+ private Response&MockObject $response;
+
+ public static function dataTest(): array {
+ $minQueriesTrigger = PropFindMonitorPlugin::THRESHOLD_QUERY_FACTOR
+ * PropFindMonitorPlugin::THRESHOLD_NODES;
+ return [
+ 'No queries logged' => [[], 0],
+ 'Plugins with queries in less than threshold nodes should not be logged' => [
+ [
+ 'propFind' => [
+ [
+ 'PluginName' => [
+ 'queries' => 100,
+ 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES - 1]
+ ],
+ [],
+ ]
+ ],
+ 0
+ ],
+ 'Plugins with query-to-node ratio less than threshold should not be logged' => [
+ [
+ 'propFind' => [
+ [
+ 'PluginName' => [
+ 'queries' => $minQueriesTrigger - 1,
+ 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES ],
+ ],
+ [],
+ ]
+ ],
+ 0
+ ],
+ 'Plugins with more nodes scanned than queries executed should not be logged' => [
+ [
+ 'propFind' => [
+ [
+ 'PluginName' => [
+ 'queries' => $minQueriesTrigger,
+ 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES * 2],
+ ],
+ [],]
+ ],
+ 0
+ ],
+ 'Plugins with queries only in highest depth level should not be logged' => [
+ [
+ 'propFind' => [
+ [
+ 'PluginName' => [
+ 'queries' => $minQueriesTrigger,
+ 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES - 1
+ ]
+ ],
+ [
+ 'PluginName' => [
+ 'queries' => $minQueriesTrigger * 2,
+ 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES
+ ]
+ ],
+ ]
+ ],
+ 0
+ ],
+ 'Plugins with too many queries should be logged' => [
+ [
+ 'propFind' => [
+ [
+ 'FirstPlugin' => [
+ 'queries' => $minQueriesTrigger,
+ 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES,
+ ],
+ 'SecondPlugin' => [
+ 'queries' => $minQueriesTrigger,
+ 'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES,
+ ]
+ ],
+ [],
+ ]
+ ],
+ 2
+ ]
+ ];
+ }
+
+ /**
+ * @dataProvider dataTest
+ */
+ public function test(array $queries, $expectedLogCalls): void {
+ $this->plugin->initialize($this->server);
+ $this->server->expects($this->once())->method('getPluginQueries')
+ ->willReturn($queries);
+
+ $this->server->expects(empty($queries) ? $this->never() : $this->once())
+ ->method('getLogger')
+ ->willReturn($this->logger);
+
+ $this->logger->expects($this->exactly($expectedLogCalls))->method('error');
+ $this->plugin->afterResponse($this->request, $this->response);
+ }
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->plugin = new PropFindMonitorPlugin();
+ $this->server = $this->createMock(Server::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->request = $this->createMock(Request::class);
+ $this->response = $this->createMock(Response::class);
+ }
+}
diff --git a/apps/dav/tests/unit/Connector/Sabre/PropFindPreloadNotifyPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/PropFindPreloadNotifyPluginTest.php
new file mode 100644
index 00000000000..52fe3eba5bf
--- /dev/null
+++ b/apps/dav/tests/unit/Connector/Sabre/PropFindPreloadNotifyPluginTest.php
@@ -0,0 +1,92 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\Tests\unit\Connector\Sabre;
+
+use OCA\DAV\Connector\Sabre\PropFindPreloadNotifyPlugin;
+use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\DAV\ICollection;
+use Sabre\DAV\IFile;
+use Sabre\DAV\PropFind;
+use Sabre\DAV\Server;
+use Test\TestCase;
+
+class PropFindPreloadNotifyPluginTest extends TestCase {
+
+ private Server&MockObject $server;
+ private PropFindPreloadNotifyPlugin $plugin;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->server = $this->createMock(Server::class);
+ $this->plugin = new PropFindPreloadNotifyPlugin();
+ }
+
+ public function testInitialize(): void {
+ $this->server
+ ->expects(self::once())
+ ->method('on')
+ ->with('propFind',
+ $this->anything(), 1);
+ $this->plugin->initialize($this->server);
+ }
+
+ public static function dataTestCollectionPreloadNotifier(): array {
+ return [
+ 'When node is not a collection, should not emit' => [
+ IFile::class,
+ 1,
+ false,
+ true
+ ],
+ 'When node is a collection but depth is zero, should not emit' => [
+ ICollection::class,
+ 0,
+ false,
+ true
+ ],
+ 'When node is a collection, and depth > 0, should emit' => [
+ ICollection::class,
+ 1,
+ true,
+ true
+ ],
+ 'When node is a collection, and depth is infinite, should emit'
+ => [
+ ICollection::class,
+ Server::DEPTH_INFINITY,
+ true,
+ true
+ ],
+ 'When called called handler returns false, it should be returned'
+ => [
+ ICollection::class,
+ 1,
+ true,
+ false
+ ]
+ ];
+ }
+
+ #[DataProvider(methodName: 'dataTestCollectionPreloadNotifier')]
+ public function testCollectionPreloadNotifier(string $nodeType, int $depth, bool $shouldEmit, bool $emitReturns):
+ void {
+ $this->plugin->initialize($this->server);
+ $propFind = $this->createMock(PropFind::class);
+ $propFind->expects(self::any())->method('getDepth')->willReturn($depth);
+ $node = $this->createMock($nodeType);
+
+ $expectation = $shouldEmit ? self::once() : self::never();
+ $this->server->expects($expectation)->method('emit')->with('preloadCollection',
+ [$propFind, $node])->willReturn($emitReturns);
+ $return = $this->plugin->collectionPreloadNotifier($propFind, $node);
+ $this->assertEquals($emitReturns, $return);
+ }
+}
diff --git a/apps/dav/tests/unit/Connector/Sabre/PropfindCompressionPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/PropfindCompressionPluginTest.php
index 42414ad6efb..e6f696ed160 100644
--- a/apps/dav/tests/unit/Connector/Sabre/PropfindCompressionPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/PropfindCompressionPluginTest.php
@@ -14,8 +14,7 @@ use Sabre\HTTP\Response;
use Test\TestCase;
class PropfindCompressionPluginTest extends TestCase {
- /** @var PropfindCompressionPlugin */
- private $plugin;
+ private PropfindCompressionPlugin $plugin;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php b/apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php
index b6c91cd7ae5..fef62b51c67 100644
--- a/apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -7,12 +8,15 @@
*/
namespace OCA\DAV\Tests\unit\Connector;
+use OCA\DAV\Connector\Sabre\PublicAuth;
use OCP\IRequest;
use OCP\ISession;
+use OCP\IURLGenerator;
use OCP\Security\Bruteforce\IThrottler;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
use OCP\Share\IShare;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
/**
@@ -24,21 +28,15 @@ use Psr\Log\LoggerInterface;
*/
class PublicAuthTest extends \Test\TestCase {
- /** @var ISession|MockObject */
- private $session;
- /** @var IRequest|MockObject */
- private $request;
- /** @var IManager|MockObject */
- private $shareManager;
- /** @var PublicAuth */
- private $auth;
- /** @var IThrottler|MockObject */
- private $throttler;
- /** @var LoggerInterface|MockObject */
- private $logger;
-
- /** @var string */
- private $oldUser;
+ private ISession&MockObject $session;
+ private IRequest&MockObject $request;
+ private IManager&MockObject $shareManager;
+ private IThrottler&MockObject $throttler;
+ private LoggerInterface&MockObject $logger;
+ private IURLGenerator&MockObject $urlGenerator;
+ private PublicAuth $auth;
+
+ private bool|string $oldUser;
protected function setUp(): void {
parent::setUp();
@@ -48,13 +46,15 @@ class PublicAuthTest extends \Test\TestCase {
$this->shareManager = $this->createMock(IManager::class);
$this->throttler = $this->createMock(IThrottler::class);
$this->logger = $this->createMock(LoggerInterface::class);
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
- $this->auth = new \OCA\DAV\Connector\Sabre\PublicAuth(
+ $this->auth = new PublicAuth(
$this->request,
$this->shareManager,
$this->session,
$this->throttler,
$this->logger,
+ $this->urlGenerator,
);
// Store current user
@@ -66,7 +66,9 @@ class PublicAuthTest extends \Test\TestCase {
// Set old user
\OC_User::setUserId($this->oldUser);
- \OC_Util::setupFS($this->oldUser);
+ if ($this->oldUser !== false) {
+ \OC_Util::setupFS($this->oldUser);
+ }
parent::tearDown();
}
@@ -75,7 +77,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $result = $this->invokePrivate($this->auth, 'getToken');
+ $result = self::invokePrivate($this->auth, 'getToken');
$this->assertSame('GX9HSGQrGE', $result);
}
@@ -85,16 +87,14 @@ class PublicAuthTest extends \Test\TestCase {
->willReturn('/dav/files');
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $this->invokePrivate($this->auth, 'getToken');
+ self::invokePrivate($this->auth, 'getToken');
}
public function testCheckTokenValidShare(): void {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn(null);
$this->shareManager->expects($this->once())
@@ -102,7 +102,7 @@ class PublicAuthTest extends \Test\TestCase {
->with('GX9HSGQrGE')
->willReturn($share);
- $result = $this->invokePrivate($this->auth, 'checkToken');
+ $result = self::invokePrivate($this->auth, 'checkToken');
$this->assertSame([true, 'principals/GX9HSGQrGE'], $result);
}
@@ -114,19 +114,17 @@ class PublicAuthTest extends \Test\TestCase {
->expects($this->once())
->method('getShareByToken')
->with('GX9HSGQrGE')
- ->will($this->throwException(new ShareNotFound()));
+ ->willThrowException(new ShareNotFound());
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $this->invokePrivate($this->auth, 'checkToken');
+ self::invokePrivate($this->auth, 'checkToken');
}
public function testCheckTokenAlreadyAuthenticated(): void {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getShareType')->willReturn(42);
$this->shareManager->expects($this->once())
@@ -136,8 +134,8 @@ class PublicAuthTest extends \Test\TestCase {
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
-
- $result = $this->invokePrivate($this->auth, 'checkToken');
+
+ $result = self::invokePrivate($this->auth, 'checkToken');
$this->assertSame([true, 'principals/GX9HSGQrGE'], $result);
}
@@ -145,9 +143,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(42);
@@ -157,18 +153,16 @@ class PublicAuthTest extends \Test\TestCase {
->willReturn($share);
$this->session->method('exists')->with('public_link_authenticated')->willReturn(false);
-
+
$this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
- $this->invokePrivate($this->auth, 'checkToken');
+ self::invokePrivate($this->auth, 'checkToken');
}
public function testCheckTokenPasswordAuthenticatedWrongShare(): void {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(42);
@@ -179,9 +173,9 @@ class PublicAuthTest extends \Test\TestCase {
$this->session->method('exists')->with('public_link_authenticated')->willReturn(false);
$this->session->method('get')->with('public_link_authenticated')->willReturn('43');
-
+
$this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
- $this->invokePrivate($this->auth, 'checkToken');
+ self::invokePrivate($this->auth, 'checkToken');
}
public function testNoShare(): void {
@@ -193,7 +187,7 @@ class PublicAuthTest extends \Test\TestCase {
->with('GX9HSGQrGE')
->willThrowException(new ShareNotFound());
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertFalse($result);
}
@@ -202,9 +196,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn(null);
$this->shareManager->expects($this->once())
@@ -212,7 +204,7 @@ class PublicAuthTest extends \Test\TestCase {
->with('GX9HSGQrGE')
->willReturn($share);
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertTrue($result);
}
@@ -221,9 +213,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(42);
@@ -232,7 +222,7 @@ class PublicAuthTest extends \Test\TestCase {
->with('GX9HSGQrGE')
->willReturn($share);
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertFalse($result);
}
@@ -242,9 +232,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_REMOTE);
@@ -253,7 +241,7 @@ class PublicAuthTest extends \Test\TestCase {
->with('GX9HSGQrGE')
->willReturn($share);
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertTrue($result);
}
@@ -262,9 +250,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
@@ -279,7 +265,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->equalTo('password')
)->willReturn(true);
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertTrue($result);
}
@@ -288,9 +274,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
@@ -305,7 +289,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->equalTo('password')
)->willReturn(true);
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertTrue($result);
}
@@ -314,9 +298,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
$share->method('getId')->willReturn('42');
@@ -336,7 +318,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertTrue($result);
}
@@ -345,9 +327,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
$share->method('getId')->willReturn('42');
@@ -367,7 +347,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
$this->session->method('get')->with('public_link_authenticated')->willReturn('43');
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertFalse($result);
}
@@ -377,9 +357,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
$share->method('getId')->willReturn('42');
@@ -399,7 +377,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
$this->session->method('get')->with('public_link_authenticated')->willReturn('43');
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertFalse($result);
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/QuotaPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/QuotaPluginTest.php
index ed4a8b0404a..6fe2d6ccabe 100644
--- a/apps/dav/tests/unit/Connector/Sabre/QuotaPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/QuotaPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2013-2016 ownCloud, Inc.
@@ -13,75 +14,55 @@ use OCP\Files\FileInfo;
use Test\TestCase;
class QuotaPluginTest extends TestCase {
- /** @var \Sabre\DAV\Server | \PHPUnit\Framework\MockObject\MockObject */
- private $server;
+ private \Sabre\DAV\Server $server;
- /** @var \OCA\DAV\Connector\Sabre\QuotaPlugin | \PHPUnit\Framework\MockObject\MockObject */
- private $plugin;
+ private QuotaPlugin $plugin;
- private function init($quota, $checkedPath = ''): void {
- $view = $this->buildFileViewMock($quota, $checkedPath);
+ private function init(int $quota, string $checkedPath = ''): void {
+ $view = $this->buildFileViewMock((string)$quota, $checkedPath);
$this->server = new \Sabre\DAV\Server();
- $this->plugin = $this->getMockBuilder(QuotaPlugin::class)
- ->setConstructorArgs([$view])
- ->setMethods(['getFileChunking'])
- ->getMock();
+ $this->plugin = new QuotaPlugin($view);
$this->plugin->initialize($this->server);
}
- /**
- * @dataProvider lengthProvider
- */
- public function testLength($expected, $headers): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('lengthProvider')]
+ public function testLength(?int $expected, array $headers): void {
$this->init(0);
- $this->plugin->expects($this->never())
- ->method('getFileChunking');
+
$this->server->httpRequest = new \Sabre\HTTP\Request('POST', 'dummy.file', $headers);
$length = $this->plugin->getLength();
$this->assertEquals($expected, $length);
}
- /**
- * @dataProvider quotaOkayProvider
- */
- public function testCheckQuota($quota, $headers): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('quotaOkayProvider')]
+ public function testCheckQuota(int $quota, array $headers): void {
$this->init($quota);
- $this->plugin->expects($this->never())
- ->method('getFileChunking');
$this->server->httpRequest = new \Sabre\HTTP\Request('POST', 'dummy.file', $headers);
$result = $this->plugin->checkQuota('');
$this->assertTrue($result);
}
- /**
- * @dataProvider quotaExceededProvider
- */
- public function testCheckExceededQuota($quota, $headers): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('quotaExceededProvider')]
+ public function testCheckExceededQuota(int $quota, array $headers): void {
$this->expectException(\Sabre\DAV\Exception\InsufficientStorage::class);
$this->init($quota);
- $this->plugin->expects($this->never())
- ->method('getFileChunking');
$this->server->httpRequest = new \Sabre\HTTP\Request('POST', 'dummy.file', $headers);
$this->plugin->checkQuota('');
}
- /**
- * @dataProvider quotaOkayProvider
- */
- public function testCheckQuotaOnPath($quota, $headers): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('quotaOkayProvider')]
+ public function testCheckQuotaOnPath(int $quota, array $headers): void {
$this->init($quota, 'sub/test.txt');
- $this->plugin->expects($this->never())
- ->method('getFileChunking');
$this->server->httpRequest = new \Sabre\HTTP\Request('POST', 'dummy.file', $headers);
$result = $this->plugin->checkQuota('/sub/test.txt');
$this->assertTrue($result);
}
- public function quotaOkayProvider() {
+ public static function quotaOkayProvider(): array {
return [
[1024, []],
[1024, ['X-EXPECTED-ENTITY-LENGTH' => '1024']],
@@ -100,7 +81,7 @@ class QuotaPluginTest extends TestCase {
];
}
- public function quotaExceededProvider() {
+ public static function quotaExceededProvider(): array {
return [
[1023, ['X-EXPECTED-ENTITY-LENGTH' => '1024']],
[511, ['CONTENT-LENGTH' => '512']],
@@ -108,7 +89,7 @@ class QuotaPluginTest extends TestCase {
];
}
- public function lengthProvider() {
+ public static function lengthProvider(): array {
return [
[null, []],
[1024, ['X-EXPECTED-ENTITY-LENGTH' => '1024']],
@@ -124,7 +105,7 @@ class QuotaPluginTest extends TestCase {
];
}
- public function quotaChunkedOkProvider() {
+ public static function quotaChunkedOkProvider(): array {
return [
[1024, 0, ['X-EXPECTED-ENTITY-LENGTH' => '1024']],
[1024, 0, ['CONTENT-LENGTH' => '512']],
@@ -143,30 +124,7 @@ class QuotaPluginTest extends TestCase {
];
}
- /**
- * @dataProvider quotaChunkedOkProvider
- */
- public function testCheckQuotaChunkedOk($quota, $chunkTotalSize, $headers): void {
- $this->init($quota, 'sub/test.txt');
-
- $mockChunking = $this->getMockBuilder(\OC_FileChunking::class)
- ->disableOriginalConstructor()
- ->getMock();
- $mockChunking->expects($this->once())
- ->method('getCurrentSize')
- ->willReturn($chunkTotalSize);
-
- $this->plugin->expects($this->once())
- ->method('getFileChunking')
- ->willReturn($mockChunking);
-
- $headers['OC-CHUNKED'] = 1;
- $this->server->httpRequest = new \Sabre\HTTP\Request('POST', 'dummy.file', $headers);
- $result = $this->plugin->checkQuota('/sub/test.txt-chunking-12345-3-1');
- $this->assertTrue($result);
- }
-
- public function quotaChunkedFailProvider() {
+ public static function quotaChunkedFailProvider(): array {
return [
[400, 0, ['X-EXPECTED-ENTITY-LENGTH' => '1024']],
[400, 0, ['CONTENT-LENGTH' => '512']],
@@ -178,39 +136,15 @@ class QuotaPluginTest extends TestCase {
];
}
- /**
- * @dataProvider quotaChunkedFailProvider
- */
- public function testCheckQuotaChunkedFail($quota, $chunkTotalSize, $headers): void {
- $this->expectException(\Sabre\DAV\Exception\InsufficientStorage::class);
-
- $this->init($quota, 'sub/test.txt');
-
- $mockChunking = $this->getMockBuilder(\OC_FileChunking::class)
- ->disableOriginalConstructor()
- ->getMock();
- $mockChunking->expects($this->once())
- ->method('getCurrentSize')
- ->willReturn($chunkTotalSize);
-
- $this->plugin->expects($this->once())
- ->method('getFileChunking')
- ->willReturn($mockChunking);
-
- $headers['OC-CHUNKED'] = 1;
- $this->server->httpRequest = new \Sabre\HTTP\Request('POST', 'dummy.file', $headers);
- $this->plugin->checkQuota('/sub/test.txt-chunking-12345-3-1');
- }
-
- private function buildFileViewMock($quota, $checkedPath) {
- // mock filesysten
+ private function buildFileViewMock(string $quota, string $checkedPath): View {
+ // mock filesystem
$view = $this->getMockBuilder(View::class)
- ->setMethods(['free_space'])
+ ->onlyMethods(['free_space'])
->disableOriginalConstructor()
->getMock();
$view->expects($this->any())
->method('free_space')
- ->with($this->identicalTo($checkedPath))
+ ->with($checkedPath)
->willReturn($quota);
return $view;
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php
index bed5eb192d9..b01807d5bbb 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -7,30 +8,23 @@
*/
namespace OCA\DAV\Tests\unit\Connector\Sabre\RequestTest;
+use OCP\IUserSession;
+use OCP\Server;
use Sabre\DAV\Auth\Backend\BackendInterface;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
class Auth implements BackendInterface {
/**
- * @var string
- */
- private $user;
-
- /**
- * @var string
- */
- private $password;
-
- /**
* Auth constructor.
*
* @param string $user
* @param string $password
*/
- public function __construct($user, $password) {
- $this->user = $user;
- $this->password = $password;
+ public function __construct(
+ private $user,
+ private $password,
+ ) {
}
/**
@@ -62,7 +56,7 @@ class Auth implements BackendInterface {
* @return array
*/
public function check(RequestInterface $request, ResponseInterface $response) {
- $userSession = \OC::$server->getUserSession();
+ $userSession = Server::get(IUserSession::class);
$result = $userSession->login($this->user, $this->password);
if ($result) {
//we need to pass the user name, which may differ from login name
@@ -72,7 +66,7 @@ class Auth implements BackendInterface {
\OC::$server->getUserFolder($user);
return [true, "principals/$user"];
}
- return [false, "login failed"];
+ return [false, 'login failed'];
}
/**
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/DeleteTest.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/DeleteTest.php
index e7f20fbadfa..7d3488e6b5a 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/DeleteTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/DeleteTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,6 +9,7 @@
namespace OCA\DAV\Tests\unit\Connector\Sabre\RequestTest;
use OCP\AppFramework\Http;
+use OCP\Files\FileInfo;
/**
* Class DeleteTest
@@ -18,7 +20,7 @@ use OCP\AppFramework\Http;
*/
class DeleteTest extends RequestTestCase {
public function testBasicUpload(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'asd');
@@ -29,7 +31,7 @@ class DeleteTest extends RequestTestCase {
$mount->getStorage()->unlink($mount->getInternalPath($internalPath));
// cache entry still exists
- $this->assertInstanceOf('\OCP\Files\FileInfo', $view->getFileInfo('foo.txt'));
+ $this->assertInstanceOf(FileInfo::class, $view->getFileInfo('foo.txt'));
$response = $this->request($view, $user, 'pass', 'DELETE', '/foo.txt');
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/DownloadTest.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/DownloadTest.php
index bec4cd9967b..34171963ef0 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/DownloadTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/DownloadTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -19,7 +20,7 @@ use OCP\Lock\ILockingProvider;
*/
class DownloadTest extends RequestTestCase {
public function testDownload(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'bar');
@@ -30,7 +31,7 @@ class DownloadTest extends RequestTestCase {
}
public function testDownloadWriteLocked(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'bar');
@@ -42,7 +43,7 @@ class DownloadTest extends RequestTestCase {
}
public function testDownloadReadLocked(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'bar');
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionMasterKeyUploadTest.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionMasterKeyUploadTest.php
index cbaa0c3101b..615490ddc92 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionMasterKeyUploadTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionMasterKeyUploadTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,6 +9,9 @@
namespace OCA\DAV\Tests\unit\Connector\Sabre\RequestTest;
use OC\Files\View;
+use OCP\IConfig;
+use OCP\ITempManager;
+use OCP\Server;
use Test\Traits\EncryptionTrait;
/**
@@ -20,12 +24,12 @@ use Test\Traits\EncryptionTrait;
class EncryptionMasterKeyUploadTest extends UploadTest {
use EncryptionTrait;
- protected function setupUser($name, $password) {
+ protected function setupUser($name, $password): View {
$this->createUser($name, $password);
- $tmpFolder = \OC::$server->getTempManager()->getTemporaryFolder();
+ $tmpFolder = Server::get(ITempManager::class)->getTemporaryFolder();
$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
// we use the master key
- \OC::$server->getConfig()->setAppValue('encryption', 'useMasterKey', '1');
+ Server::get(IConfig::class)->setAppValue('encryption', 'useMasterKey', '1');
$this->setupForUser($name, $password);
$this->loginWithEncryption($name);
return new View('/' . $name . '/files');
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionUploadTest.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionUploadTest.php
index f830c54fd0d..efa7bb54cf8 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionUploadTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionUploadTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,6 +9,9 @@
namespace OCA\DAV\Tests\unit\Connector\Sabre\RequestTest;
use OC\Files\View;
+use OCP\IConfig;
+use OCP\ITempManager;
+use OCP\Server;
use Test\Traits\EncryptionTrait;
/**
@@ -20,12 +24,12 @@ use Test\Traits\EncryptionTrait;
class EncryptionUploadTest extends UploadTest {
use EncryptionTrait;
- protected function setupUser($name, $password) {
+ protected function setupUser($name, $password): View {
$this->createUser($name, $password);
- $tmpFolder = \OC::$server->getTempManager()->getTemporaryFolder();
+ $tmpFolder = Server::get(ITempManager::class)->getTemporaryFolder();
$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
// we use per-user keys
- \OC::$server->getConfig()->setAppValue('encryption', 'useMasterKey', '0');
+ Server::get(IConfig::class)->setAppValue('encryption', 'useMasterKey', '0');
$this->setupForUser($name, $password);
$this->loginWithEncryption($name);
return new View('/' . $name . '/files');
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/ExceptionPlugin.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/ExceptionPlugin.php
index 9b20b2f8630..0c53e4b1009 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/ExceptionPlugin.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/ExceptionPlugin.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -7,7 +8,9 @@
*/
namespace OCA\DAV\Tests\unit\Connector\Sabre\RequestTest;
-class ExceptionPlugin extends \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin {
+use OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin;
+
+class ExceptionPlugin extends ExceptionLoggerPlugin {
/**
* @var \Throwable[]
*/
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/PartFileInRootUploadTest.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/PartFileInRootUploadTest.php
index 200008bcfce..e6fa489fb24 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/PartFileInRootUploadTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/PartFileInRootUploadTest.php
@@ -7,7 +7,9 @@
*/
namespace OCA\DAV\Tests\unit\Connector\Sabre\RequestTest;
+use OC\AllConfig;
use OCP\IConfig;
+use OCP\Server;
/**
* Class PartFileInRootUploadTest
@@ -18,10 +20,8 @@ use OCP\IConfig;
*/
class PartFileInRootUploadTest extends UploadTest {
protected function setUp(): void {
- $config = \OC::$server->getConfig();
- $mockConfig = $this->getMockBuilder(IConfig::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $config = Server::get(IConfig::class);
+ $mockConfig = $this->createMock(IConfig::class);
$mockConfig->expects($this->any())
->method('getSystemValue')
->willReturnCallback(function ($key, $default) use ($config) {
@@ -31,7 +31,7 @@ class PartFileInRootUploadTest extends UploadTest {
return $config->getSystemValue($key, $default);
}
});
- $this->overwriteService('AllConfig', $mockConfig);
+ $this->overwriteService(AllConfig::class, $mockConfig);
parent::setUp();
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/RequestTestCase.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/RequestTestCase.php
index 29574d53bca..404dc7fa5d7 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/RequestTestCase.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/RequestTestCase.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -11,9 +12,16 @@ use OC\Files\View;
use OCA\DAV\Connector\Sabre\Server;
use OCA\DAV\Connector\Sabre\ServerFactory;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Mount\IMountManager;
use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\IPreview;
use OCP\IRequest;
use OCP\IRequestId;
+use OCP\ITagManager;
+use OCP\ITempManager;
+use OCP\IUserSession;
+use OCP\L10N\IFactory;
use Psr\Log\LoggerInterface;
use Sabre\HTTP\Request;
use Test\TestCase;
@@ -23,11 +31,7 @@ use Test\Traits\UserTrait;
abstract class RequestTestCase extends TestCase {
use UserTrait;
use MountProviderTrait;
-
- /**
- * @var \OCA\DAV\Connector\Sabre\ServerFactory
- */
- protected $serverFactory;
+ protected ServerFactory $serverFactory;
protected function getStream($string) {
$stream = fopen('php://temp', 'r+');
@@ -40,31 +44,29 @@ abstract class RequestTestCase extends TestCase {
parent::setUp();
$this->serverFactory = new ServerFactory(
- \OC::$server->getConfig(),
- \OC::$server->get(LoggerInterface::class),
- \OC::$server->getDatabaseConnection(),
- \OC::$server->getUserSession(),
- \OC::$server->getMountManager(),
- \OC::$server->getTagManager(),
- $this->getMockBuilder(IRequest::class)
- ->disableOriginalConstructor()
- ->getMock(),
- \OC::$server->getPreviewManager(),
- \OC::$server->get(IEventDispatcher::class),
- \OC::$server->getL10N('dav')
+ \OCP\Server::get(IConfig::class),
+ \OCP\Server::get(LoggerInterface::class),
+ \OCP\Server::get(IDBConnection::class),
+ \OCP\Server::get(IUserSession::class),
+ \OCP\Server::get(IMountManager::class),
+ \OCP\Server::get(ITagManager::class),
+ $this->createMock(IRequest::class),
+ \OCP\Server::get(IPreview::class),
+ \OCP\Server::get(IEventDispatcher::class),
+ \OCP\Server::get(IFactory::class)->get('dav'),
);
}
- protected function setupUser($name, $password) {
+ protected function setupUser($name, $password): View {
$this->createUser($name, $password);
- $tmpFolder = \OC::$server->getTempManager()->getTemporaryFolder();
+ $tmpFolder = \OCP\Server::get(ITempManager::class)->getTemporaryFolder();
$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
- $this->loginAsUser($name);
+ self::loginAsUser($name);
return new View('/' . $name . '/files');
}
/**
- * @param \OC\Files\View $view the view to run the webdav server against
+ * @param View $view the view to run the webdav server against
* @param string $user
* @param string $password
* @param string $method
@@ -79,7 +81,7 @@ abstract class RequestTestCase extends TestCase {
$body = $this->getStream($body);
}
$this->logout();
- $exceptionPlugin = new ExceptionPlugin('webdav', \OC::$server->get(LoggerInterface::class));
+ $exceptionPlugin = new ExceptionPlugin('webdav', \OCP\Server::get(LoggerInterface::class));
$server = $this->getSabreServer($view, $user, $password, $exceptionPlugin);
$request = new Request($method, $url, $headers, $body);
@@ -131,7 +133,7 @@ abstract class RequestTestCase extends TestCase {
$authBackend = new Auth($user, $password);
$authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend);
- $server = $this->serverFactory->createServer('/', 'dummy', $authPlugin, function () use ($view) {
+ $server = $this->serverFactory->createServer(false, '/', 'dummy', $authPlugin, function () use ($view) {
return $view;
});
$server->addPlugin($exceptionPlugin);
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/Sapi.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/Sapi.php
index f7bcdd930ca..08d774e56b8 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/Sapi.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/Sapi.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -12,11 +13,6 @@ use Sabre\HTTP\Response;
class Sapi {
/**
- * @var \Sabre\HTTP\Request
- */
- private $request;
-
- /**
* @var \Sabre\HTTP\Response
*/
private $response;
@@ -31,8 +27,9 @@ class Sapi {
return $this->request;
}
- public function __construct(Request $request) {
- $this->request = $request;
+ public function __construct(
+ private Request $request,
+ ) {
}
/**
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/UploadTest.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/UploadTest.php
index 286bba7d196..5c6d0f03334 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/UploadTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/UploadTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -19,7 +20,7 @@ use OCP\Lock\ILockingProvider;
*/
class UploadTest extends RequestTestCase {
public function testBasicUpload(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$this->assertFalse($view->file_exists('foo.txt'));
@@ -35,7 +36,7 @@ class UploadTest extends RequestTestCase {
}
public function testUploadOverWrite(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'foobar');
@@ -51,7 +52,7 @@ class UploadTest extends RequestTestCase {
}
public function testUploadOverWriteReadLocked(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'bar');
@@ -63,7 +64,7 @@ class UploadTest extends RequestTestCase {
}
public function testUploadOverWriteWriteLocked(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$this->loginAsUser($user);
@@ -74,115 +75,4 @@ class UploadTest extends RequestTestCase {
$result = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd');
$this->assertEquals(Http::STATUS_LOCKED, $result->getStatus());
}
-
- public function testChunkedUpload(): void {
- $user = $this->getUniqueID();
- $view = $this->setupUser($user, 'pass');
-
- $this->assertFalse($view->file_exists('foo.txt'));
- $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-0', 'asd', ['OC-Chunked' => '1']);
-
- $this->assertEquals(201, $response->getStatus());
- $this->assertFalse($view->file_exists('foo.txt'));
-
- $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']);
-
- $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
- $this->assertTrue($view->file_exists('foo.txt'));
-
- $this->assertEquals('asdbar', $view->file_get_contents('foo.txt'));
-
- $info = $view->getFileInfo('foo.txt');
- $this->assertInstanceOf('\OC\Files\FileInfo', $info);
- $this->assertEquals(6, $info->getSize());
- }
-
- public function testChunkedUploadOverWrite(): void {
- $user = $this->getUniqueID();
- $view = $this->setupUser($user, 'pass');
-
- $view->file_put_contents('foo.txt', 'bar');
- $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-0', 'asd', ['OC-Chunked' => '1']);
-
- $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
- $this->assertEquals('bar', $view->file_get_contents('foo.txt'));
-
- $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']);
-
- $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
-
- $this->assertEquals('asdbar', $view->file_get_contents('foo.txt'));
-
- $info = $view->getFileInfo('foo.txt');
- $this->assertInstanceOf('\OC\Files\FileInfo', $info);
- $this->assertEquals(6, $info->getSize());
- }
-
- public function testChunkedUploadOutOfOrder(): void {
- $user = $this->getUniqueID();
- $view = $this->setupUser($user, 'pass');
-
- $this->assertFalse($view->file_exists('foo.txt'));
- $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']);
-
- $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
- $this->assertFalse($view->file_exists('foo.txt'));
-
- $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-0', 'asd', ['OC-Chunked' => '1']);
-
- $this->assertEquals(201, $response->getStatus());
- $this->assertTrue($view->file_exists('foo.txt'));
-
- $this->assertEquals('asdbar', $view->file_get_contents('foo.txt'));
-
- $info = $view->getFileInfo('foo.txt');
- $this->assertInstanceOf('\OC\Files\FileInfo', $info);
- $this->assertEquals(6, $info->getSize());
- }
-
- public function testChunkedUploadOutOfOrderReadLocked(): void {
- $user = $this->getUniqueID();
- $view = $this->setupUser($user, 'pass');
-
- $this->assertFalse($view->file_exists('foo.txt'));
-
- $view->lockFile('/foo.txt', ILockingProvider::LOCK_SHARED);
-
- try {
- $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']);
- } catch (\OCA\DAV\Connector\Sabre\Exception\FileLocked $e) {
- $this->fail('Didn\'t expect locked error for the first chunk on read lock');
- return;
- }
-
- $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
- $this->assertFalse($view->file_exists('foo.txt'));
-
- // last chunk should trigger the locked error since it tries to assemble
- $result = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-0', 'asd', ['OC-Chunked' => '1']);
- $this->assertEquals(Http::STATUS_LOCKED, $result->getStatus());
- }
-
- public function testChunkedUploadOutOfOrderWriteLocked(): void {
- $user = $this->getUniqueID();
- $view = $this->setupUser($user, 'pass');
-
- $this->assertFalse($view->file_exists('foo.txt'));
-
- $view->lockFile('/foo.txt', ILockingProvider::LOCK_EXCLUSIVE);
-
- try {
- $response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']);
- } catch (\OCA\DAV\Connector\Sabre\Exception\FileLocked $e) {
- $this->fail('Didn\'t expect locked error for the first chunk on write lock'); // maybe forbid this in the future for write locks only?
- return;
- }
-
- $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
- $this->assertFalse($view->file_exists('foo.txt'));
-
- // last chunk should trigger the locked error since it tries to assemble
- $result = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-0', 'asd', ['OC-Chunked' => '1']);
- $this->assertEquals(Http::STATUS_LOCKED, $result->getStatus());
- }
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
index 546be840cd8..33f579eb913 100644
--- a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -10,41 +11,24 @@ namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\File;
use OCA\DAV\Connector\Sabre\Node;
+use OCA\DAV\Connector\Sabre\SharesPlugin;
use OCA\DAV\Upload\UploadFile;
use OCP\Files\Folder;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Share\IManager;
use OCP\Share\IShare;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Tree;
class SharesPluginTest extends \Test\TestCase {
- public const SHARETYPES_PROPERTYNAME = \OCA\DAV\Connector\Sabre\SharesPlugin::SHARETYPES_PROPERTYNAME;
+ public const SHARETYPES_PROPERTYNAME = SharesPlugin::SHARETYPES_PROPERTYNAME;
- /**
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var \Sabre\DAV\Tree
- */
- private $tree;
-
- /**
- * @var \OCP\Share\IManager
- */
- private $shareManager;
-
- /**
- * @var \OCP\Files\Folder
- */
- private $userFolder;
-
- /**
- * @var \OCA\DAV\Connector\Sabre\SharesPlugin
- */
- private $plugin;
+ private \Sabre\DAV\Server $server;
+ private \Sabre\DAV\Tree&MockObject $tree;
+ private \OCP\Share\IManager&MockObject $shareManager;
+ private Folder&MockObject $userFolder;
+ private SharesPlugin $plugin;
protected function setUp(): void {
parent::setUp();
@@ -61,7 +45,7 @@ class SharesPluginTest extends \Test\TestCase {
->willReturn($user);
$this->userFolder = $this->createMock(Folder::class);
- $this->plugin = new \OCA\DAV\Connector\Sabre\SharesPlugin(
+ $this->plugin = new SharesPlugin(
$this->tree,
$userSession,
$this->userFolder,
@@ -70,13 +54,9 @@ class SharesPluginTest extends \Test\TestCase {
$this->plugin->initialize($this->server);
}
- /**
- * @dataProvider sharesGetPropertiesDataProvider
- */
- public function testGetProperties($shareTypes): void {
- $sabreNode = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ #[\PHPUnit\Framework\Attributes\DataProvider('sharesGetPropertiesDataProvider')]
+ public function testGetProperties(array $shareTypes): void {
+ $sabreNode = $this->createMock(Node::class);
$sabreNode->expects($this->any())
->method('getId')
->willReturn(123);
@@ -85,9 +65,7 @@ class SharesPluginTest extends \Test\TestCase {
->willReturn('/subdir');
// node API nodes
- $node = $this->getMockBuilder(Folder::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Folder::class);
$sabreNode->method('getNode')
->willReturn($node);
@@ -139,10 +117,8 @@ class SharesPluginTest extends \Test\TestCase {
$this->assertEquals($shareTypes, $result[200][self::SHARETYPES_PROPERTYNAME]->getShareTypes());
}
- /**
- * @dataProvider sharesGetPropertiesDataProvider
- */
- public function testPreloadThenGetProperties($shareTypes): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('sharesGetPropertiesDataProvider')]
+ public function testPreloadThenGetProperties(array $shareTypes): void {
$sabreNode1 = $this->createMock(File::class);
$sabreNode1->method('getId')
->willReturn(111);
@@ -181,7 +157,7 @@ class SharesPluginTest extends \Test\TestCase {
->willReturn($node2);
$dummyShares = array_map(function ($type) {
- $share = $this->getMockBuilder(IShare::class)->getMock();
+ $share = $this->createMock(IShare::class);
$share->expects($this->any())
->method('getShareType')
->willReturn($type);
@@ -247,6 +223,7 @@ class SharesPluginTest extends \Test\TestCase {
0
);
+ $this->server->emit('preloadCollection', [$propFindRoot, $sabreNode]);
$this->plugin->handleGetProperties(
$propFindRoot,
$sabreNode
@@ -267,7 +244,7 @@ class SharesPluginTest extends \Test\TestCase {
$this->assertEquals($shareTypes, $result[200][self::SHARETYPES_PROPERTYNAME]->getShareTypes());
}
- public function sharesGetPropertiesDataProvider() {
+ public static function sharesGetPropertiesDataProvider(): array {
return [
[[]],
[[IShare::TYPE_USER]],
@@ -286,9 +263,7 @@ class SharesPluginTest extends \Test\TestCase {
}
public function testGetPropertiesSkipChunks(): void {
- $sabreNode = $this->getMockBuilder(UploadFile::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $sabreNode = $this->createMock(UploadFile::class);
$propFind = new \Sabre\DAV\PropFind(
'/dummyPath',
diff --git a/apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php
index 635f62dac87..554a4a1424e 100644
--- a/apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2014-2016 ownCloud, Inc.
@@ -10,68 +11,56 @@ namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\File;
use OCA\DAV\Connector\Sabre\Node;
+use OCA\DAV\Connector\Sabre\TagList;
+use OCA\DAV\Connector\Sabre\TagsPlugin;
use OCA\DAV\Upload\UploadFile;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\ITagManager;
use OCP\ITags;
+use OCP\IUser;
+use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Tree;
class TagsPluginTest extends \Test\TestCase {
- public const TAGS_PROPERTYNAME = \OCA\DAV\Connector\Sabre\TagsPlugin::TAGS_PROPERTYNAME;
- public const FAVORITE_PROPERTYNAME = \OCA\DAV\Connector\Sabre\TagsPlugin::FAVORITE_PROPERTYNAME;
- public const TAG_FAVORITE = \OCA\DAV\Connector\Sabre\TagsPlugin::TAG_FAVORITE;
-
- /**
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var Tree
- */
- private $tree;
-
- /**
- * @var \OCP\ITagManager
- */
- private $tagManager;
-
- /**
- * @var \OCP\ITags
- */
- private $tagger;
-
- /**
- * @var \OCA\DAV\Connector\Sabre\TagsPlugin
- */
- private $plugin;
+ public const TAGS_PROPERTYNAME = TagsPlugin::TAGS_PROPERTYNAME;
+ public const FAVORITE_PROPERTYNAME = TagsPlugin::FAVORITE_PROPERTYNAME;
+ public const TAG_FAVORITE = TagsPlugin::TAG_FAVORITE;
+
+ private \Sabre\DAV\Server $server;
+ private Tree&MockObject $tree;
+ private ITagManager&MockObject $tagManager;
+ private ITags&MockObject $tagger;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private IUserSession&MockObject $userSession;
+ private TagsPlugin $plugin;
protected function setUp(): void {
parent::setUp();
+
$this->server = new \Sabre\DAV\Server();
- $this->tree = $this->getMockBuilder(Tree::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->tagger = $this->getMockBuilder(ITags::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->tagManager = $this->getMockBuilder(ITagManager::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->tree = $this->createMock(Tree::class);
+ $this->tagger = $this->createMock(ITags::class);
+ $this->tagManager = $this->createMock(ITagManager::class);
+ $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
+ $user = $this->createMock(IUser::class);
+
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->userSession->expects($this->any())
+ ->method('getUser')
+ ->withAnyParameters()
+ ->willReturn($user);
$this->tagManager->expects($this->any())
->method('load')
->with('files')
->willReturn($this->tagger);
- $this->plugin = new \OCA\DAV\Connector\Sabre\TagsPlugin($this->tree, $this->tagManager);
+ $this->plugin = new TagsPlugin($this->tree, $this->tagManager, $this->eventDispatcher, $this->userSession);
$this->plugin->initialize($this->server);
}
- /**
- * @dataProvider tagsGetPropertiesDataProvider
- */
- public function testGetProperties($tags, $requestedProperties, $expectedProperties): void {
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ #[\PHPUnit\Framework\Attributes\DataProvider('tagsGetPropertiesDataProvider')]
+ public function testGetProperties(array $tags, array $requestedProperties, array $expectedProperties): void {
+ $node = $this->createMock(Node::class);
$node->expects($this->any())
->method('getId')
->willReturn(123);
@@ -104,19 +93,13 @@ class TagsPluginTest extends \Test\TestCase {
$this->assertEquals($expectedProperties, $result);
}
- /**
- * @dataProvider tagsGetPropertiesDataProvider
- */
- public function testPreloadThenGetProperties($tags, $requestedProperties, $expectedProperties): void {
- $node1 = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ #[\PHPUnit\Framework\Attributes\DataProvider('tagsGetPropertiesDataProvider')]
+ public function testPreloadThenGetProperties(array $tags, array $requestedProperties, array $expectedProperties): void {
+ $node1 = $this->createMock(File::class);
$node1->expects($this->any())
->method('getId')
->willReturn(111);
- $node2 = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node2 = $this->createMock(File::class);
$node2->expects($this->any())
->method('getId')
->willReturn(222);
@@ -129,9 +112,7 @@ class TagsPluginTest extends \Test\TestCase {
$expectedCallCount = 1;
}
- $node = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Directory::class);
$node->expects($this->any())
->method('getId')
->willReturn(123);
@@ -166,6 +147,8 @@ class TagsPluginTest extends \Test\TestCase {
0
);
+ $this->server->emit('preloadCollection', [$propFindRoot, $node]);
+
$this->plugin->handleGetProperties(
$propFindRoot,
$node
@@ -186,7 +169,7 @@ class TagsPluginTest extends \Test\TestCase {
$this->assertEquals($expectedProperties, $result);
}
- public function tagsGetPropertiesDataProvider() {
+ public static function tagsGetPropertiesDataProvider(): array {
return [
// request both, receive both
[
@@ -194,7 +177,7 @@ class TagsPluginTest extends \Test\TestCase {
[self::TAGS_PROPERTYNAME, self::FAVORITE_PROPERTYNAME],
[
200 => [
- self::TAGS_PROPERTYNAME => new \OCA\DAV\Connector\Sabre\TagList(['tag1', 'tag2']),
+ self::TAGS_PROPERTYNAME => new TagList(['tag1', 'tag2']),
self::FAVORITE_PROPERTYNAME => true,
]
]
@@ -205,7 +188,7 @@ class TagsPluginTest extends \Test\TestCase {
[self::TAGS_PROPERTYNAME],
[
200 => [
- self::TAGS_PROPERTYNAME => new \OCA\DAV\Connector\Sabre\TagList(['tag1', 'tag2']),
+ self::TAGS_PROPERTYNAME => new TagList(['tag1', 'tag2']),
]
]
],
@@ -233,7 +216,7 @@ class TagsPluginTest extends \Test\TestCase {
[self::TAGS_PROPERTYNAME, self::FAVORITE_PROPERTYNAME],
[
200 => [
- self::TAGS_PROPERTYNAME => new \OCA\DAV\Connector\Sabre\TagList([]),
+ self::TAGS_PROPERTYNAME => new TagList([]),
self::FAVORITE_PROPERTYNAME => false,
]
]
@@ -242,9 +225,7 @@ class TagsPluginTest extends \Test\TestCase {
}
public function testGetPropertiesSkipChunks(): void {
- $sabreNode = $this->getMockBuilder(UploadFile::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $sabreNode = $this->createMock(UploadFile::class);
$propFind = new \Sabre\DAV\PropFind(
'/dummyPath',
@@ -264,9 +245,7 @@ class TagsPluginTest extends \Test\TestCase {
public function testUpdateTags(): void {
// this test will replace the existing tags "tagremove" with "tag1" and "tag2"
// and keep "tagkeep"
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Node::class);
$node->expects($this->any())
->method('getId')
->willReturn(123);
@@ -282,12 +261,16 @@ class TagsPluginTest extends \Test\TestCase {
->willReturn([123 => ['tagkeep', 'tagremove', self::TAG_FAVORITE]]);
// then tag as tag1 and tag2
- $this->tagger->expects($this->exactly(2))
+ $calls = [
+ [123, 'tag1'],
+ [123, 'tag2'],
+ ];
+ $this->tagger->expects($this->exactly(count($calls)))
->method('tagAs')
- ->withConsecutive(
- [123, 'tag1'],
- [123, 'tag2'],
- );
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
// it will untag tag3
$this->tagger->expects($this->once())
@@ -296,7 +279,7 @@ class TagsPluginTest extends \Test\TestCase {
// properties to set
$propPatch = new \Sabre\DAV\PropPatch([
- self::TAGS_PROPERTYNAME => new \OCA\DAV\Connector\Sabre\TagList(['tag1', 'tag2', 'tagkeep'])
+ self::TAGS_PROPERTYNAME => new TagList(['tag1', 'tag2', 'tagkeep'])
]);
$this->plugin->handleUpdateProperties(
@@ -311,13 +294,11 @@ class TagsPluginTest extends \Test\TestCase {
$result = $propPatch->getResult();
$this->assertEquals(200, $result[self::TAGS_PROPERTYNAME]);
- $this->assertFalse(isset($result[self::FAVORITE_PROPERTYNAME]));
+ $this->assertArrayNotHasKey(self::FAVORITE_PROPERTYNAME, $result);
}
public function testUpdateTagsFromScratch(): void {
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Node::class);
$node->expects($this->any())
->method('getId')
->willReturn(123);
@@ -333,16 +314,20 @@ class TagsPluginTest extends \Test\TestCase {
->willReturn([]);
// then tag as tag1 and tag2
- $this->tagger->expects($this->exactly(2))
+ $calls = [
+ [123, 'tag1'],
+ [123, 'tag2'],
+ ];
+ $this->tagger->expects($this->exactly(count($calls)))
->method('tagAs')
- ->withConsecutive(
- [123, 'tag1'],
- [123, 'tag2'],
- );
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
// properties to set
$propPatch = new \Sabre\DAV\PropPatch([
- self::TAGS_PROPERTYNAME => new \OCA\DAV\Connector\Sabre\TagList(['tag1', 'tag2'])
+ self::TAGS_PROPERTYNAME => new TagList(['tag1', 'tag2'])
]);
$this->plugin->handleUpdateProperties(
@@ -357,15 +342,13 @@ class TagsPluginTest extends \Test\TestCase {
$result = $propPatch->getResult();
$this->assertEquals(200, $result[self::TAGS_PROPERTYNAME]);
- $this->assertFalse(false, isset($result[self::FAVORITE_PROPERTYNAME]));
+ $this->assertArrayNotHasKey(self::FAVORITE_PROPERTYNAME, $result);
}
public function testUpdateFav(): void {
// this test will replace the existing tags "tagremove" with "tag1" and "tag2"
// and keep "tagkeep"
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Node::class);
$node->expects($this->any())
->method('getId')
->willReturn(123);
@@ -396,8 +379,8 @@ class TagsPluginTest extends \Test\TestCase {
$this->assertEmpty($propPatch->getRemainingMutations());
$result = $propPatch->getResult();
- $this->assertFalse(false, isset($result[self::TAGS_PROPERTYNAME]));
- $this->assertEquals(200, isset($result[self::FAVORITE_PROPERTYNAME]));
+ $this->assertArrayNotHasKey(self::TAGS_PROPERTYNAME, $result);
+ $this->assertEquals(200, $result[self::FAVORITE_PROPERTYNAME]);
// unfavorite now
// set favorite tag
@@ -421,7 +404,7 @@ class TagsPluginTest extends \Test\TestCase {
$this->assertEmpty($propPatch->getRemainingMutations());
$result = $propPatch->getResult();
- $this->assertFalse(false, isset($result[self::TAGS_PROPERTYNAME]));
- $this->assertEquals(200, isset($result[self::FAVORITE_PROPERTYNAME]));
+ $this->assertArrayNotHasKey(self::TAGS_PROPERTYNAME, $result);
+ $this->assertEquals(200, $result[self::FAVORITE_PROPERTYNAME]);
}
}
diff --git a/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php b/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php
index c7c2bf0e431..9aa0ef3a2a7 100644
--- a/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php
+++ b/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php
@@ -1,43 +1,33 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\DAV\Controller;
+namespace OCA\DAV\Tests\unit\DAV\Controller;
use OCA\DAV\BackgroundJob\GenerateBirthdayCalendarBackgroundJob;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Controller\BirthdayCalendarController;
+use OCP\AppFramework\Http\JSONResponse;
use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class BirthdayCalendarControllerTest extends TestCase {
-
- /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
- private $config;
-
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
-
- /** @var IDBConnection|\PHPUnit\Framework\MockObject\MockObject */
- private $db;
-
- /** @var IJobList|\PHPUnit\Framework\MockObject\MockObject */
- private $jobList;
-
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- private $userManager;
-
- /** @var CalDavBackend|\PHPUnit\Framework\MockObject\MockObject */
- private $caldav;
-
- /** @var BirthdayCalendarController|\PHPUnit\Framework\MockObject\MockObject */
- private $controller;
+ private IConfig&MockObject $config;
+ private IRequest&MockObject $request;
+ private IDBConnection&MockObject $db;
+ private IJobList&MockObject $jobList;
+ private IUserManager&MockObject $userManager;
+ private CalDavBackend&MockObject $caldav;
+ private BirthdayCalendarController $controller;
protected function setUp(): void {
parent::setUp();
@@ -74,16 +64,20 @@ class BirthdayCalendarControllerTest extends TestCase {
$closure($user3);
});
+ $calls = [
+ [GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid1']],
+ [GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid2']],
+ [GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid3']],
+ ];
$this->jobList->expects($this->exactly(3))
->method('add')
- ->withConsecutive(
- [GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid1']],
- [GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid2']],
- [GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid3']],
- );
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$response = $this->controller->enable();
- $this->assertInstanceOf('OCP\AppFramework\Http\JSONResponse', $response);
+ $this->assertInstanceOf(JSONResponse::class, $response);
}
public function testDisable(): void {
@@ -97,6 +91,6 @@ class BirthdayCalendarControllerTest extends TestCase {
->method('deleteAllBirthdayCalendars');
$response = $this->controller->disable();
- $this->assertInstanceOf('OCP\AppFramework\Http\JSONResponse', $response);
+ $this->assertInstanceOf(JSONResponse::class, $response);
}
}
diff --git a/apps/dav/tests/unit/Controller/DirectControllerTest.php b/apps/dav/tests/unit/Controller/DirectControllerTest.php
index 2476681251c..837adde1da7 100644
--- a/apps/dav/tests/unit/Controller/DirectControllerTest.php
+++ b/apps/dav/tests/unit/Controller/DirectControllerTest.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\DAV\Controller;
+namespace OCA\DAV\Tests\unit\DAV\Controller;
use OCA\DAV\Controller\DirectController;
use OCA\DAV\Db\Direct;
@@ -20,29 +20,18 @@ use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\IRequest;
-use OCP\IUrlGenerator;
+use OCP\IURLGenerator;
use OCP\Security\ISecureRandom;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class DirectControllerTest extends TestCase {
-
- /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */
- private $rootFolder;
-
- /** @var DirectMapper|\PHPUnit\Framework\MockObject\MockObject */
- private $directMapper;
-
- /** @var ISecureRandom|\PHPUnit\Framework\MockObject\MockObject */
- private $random;
-
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
-
- /** @var IUrlGenerator|\PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
-
- /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */
- private $eventDispatcher;
+ private IRootFolder&MockObject $rootFolder;
+ private DirectMapper&MockObject $directMapper;
+ private ISecureRandom&MockObject $random;
+ private ITimeFactory&MockObject $timeFactory;
+ private IURLGenerator&MockObject $urlGenerator;
+ private IEventDispatcher&MockObject $eventDispatcher;
private DirectController $controller;
@@ -53,7 +42,7 @@ class DirectControllerTest extends TestCase {
$this->directMapper = $this->createMock(DirectMapper::class);
$this->random = $this->createMock(ISecureRandom::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
- $this->urlGenerator = $this->createMock(IUrlGenerator::class);
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->controller = new DirectController(
@@ -136,7 +125,7 @@ class DirectControllerTest extends TestCase {
$this->urlGenerator->method('getAbsoluteURL')
->willReturnCallback(function (string $url) {
- return 'https://my.nextcloud/'.$url;
+ return 'https://my.nextcloud/' . $url;
});
$result = $this->controller->getUrl(101);
diff --git a/apps/dav/tests/unit/Controller/InvitationResponseControllerTest.php b/apps/dav/tests/unit/Controller/InvitationResponseControllerTest.php
index 640c66b75e5..15b18d6c1b1 100644
--- a/apps/dav/tests/unit/Controller/InvitationResponseControllerTest.php
+++ b/apps/dav/tests/unit/Controller/InvitationResponseControllerTest.php
@@ -7,7 +7,7 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\DAV\Controller;
+namespace OCA\DAV\Tests\unit\DAV\Controller;
use OCA\DAV\CalDAV\InvitationResponse\InvitationResponseServer;
use OCA\DAV\Controller\InvitationResponseController;
@@ -18,24 +18,16 @@ use OCP\DB\QueryBuilder\IExpressionBuilder;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\ITip\Message;
use Test\TestCase;
class InvitationResponseControllerTest extends TestCase {
- /** @var InvitationResponseController */
- private $controller;
-
- /** @var IDBConnection|\PHPUnit\Framework\MockObject\MockObject */
- private $dbConnection;
-
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
-
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
-
- /** @var InvitationResponseServer|\PHPUnit\Framework\MockObject\MockObject */
- private $responseServer;
+ private IDBConnection&MockObject $dbConnection;
+ private IRequest&MockObject $request;
+ private ITimeFactory&MockObject $timeFactory;
+ private InvitationResponseServer&MockObject $responseServer;
+ private InvitationResponseController $controller;
protected function setUp(): void {
parent::setUp();
@@ -43,9 +35,7 @@ class InvitationResponseControllerTest extends TestCase {
$this->dbConnection = $this->createMock(IDBConnection::class);
$this->request = $this->createMock(IRequest::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
- $this->responseServer = $this->getMockBuilder(InvitationResponseServer::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->responseServer = $this->createMock(InvitationResponseServer::class);
$this->controller = new InvitationResponseController(
'appName',
@@ -56,16 +46,14 @@ class InvitationResponseControllerTest extends TestCase {
);
}
- public function attendeeProvider(): array {
+ public static function attendeeProvider(): array {
return [
'local attendee' => [false],
'external attendee' => [true]
];
}
- /**
- * @dataProvider attendeeProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('attendeeProvider')]
public function testAccept(bool $isExternalAttendee): void {
$this->buildQueryExpects('TOKEN123', [
'id' => 0,
@@ -127,9 +115,7 @@ EOF;
$this->assertTrue($called);
}
- /**
- * @dataProvider attendeeProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('attendeeProvider')]
public function testAcceptSequence(bool $isExternalAttendee): void {
$this->buildQueryExpects('TOKEN123', [
'id' => 0,
@@ -191,9 +177,7 @@ EOF;
$this->assertTrue($called);
}
- /**
- * @dataProvider attendeeProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('attendeeProvider')]
public function testAcceptRecurrenceId(bool $isExternalAttendee): void {
$this->buildQueryExpects('TOKEN123', [
'id' => 0,
@@ -283,9 +267,7 @@ EOF;
$this->assertEquals([], $response->getParams());
}
- /**
- * @dataProvider attendeeProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('attendeeProvider')]
public function testDecline(bool $isExternalAttendee): void {
$this->buildQueryExpects('TOKEN123', [
'id' => 0,
@@ -354,9 +336,7 @@ EOF;
$this->assertEquals(['token' => 'TOKEN123'], $response->getParams());
}
- /**
- * @dataProvider attendeeProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('attendeeProvider')]
public function testProcessMoreOptionsResult(bool $isExternalAttendee): void {
$this->request->expects($this->once())
->method('getParam')
@@ -424,7 +404,7 @@ EOF;
$this->assertTrue($called);
}
- private function buildQueryExpects($token, $return, $time): void {
+ private function buildQueryExpects(string $token, ?array $return, int $time): void {
$queryBuilder = $this->createMock(IQueryBuilder::class);
$stmt = $this->createMock(IResult::class);
$expr = $this->createMock(IExpressionBuilder::class);
diff --git a/apps/dav/tests/unit/Controller/UpcomingEventsControllerTest.php b/apps/dav/tests/unit/Controller/UpcomingEventsControllerTest.php
new file mode 100644
index 00000000000..527943e5221
--- /dev/null
+++ b/apps/dav/tests/unit/Controller/UpcomingEventsControllerTest.php
@@ -0,0 +1,73 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\DAV\Service;
+
+use OCA\DAV\CalDAV\UpcomingEvent;
+use OCA\DAV\CalDAV\UpcomingEventsService;
+use OCA\DAV\Controller\UpcomingEventsController;
+use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+
+class UpcomingEventsControllerTest extends TestCase {
+ private IRequest&MockObject $request;
+ private UpcomingEventsService&MockObject $service;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->request = $this->createMock(IRequest::class);
+ $this->service = $this->createMock(UpcomingEventsService::class);
+ }
+
+ public function testGetEventsAnonymously(): void {
+ $controller = new UpcomingEventsController(
+ $this->request,
+ null,
+ $this->service,
+ );
+
+ $response = $controller->getEvents('https://cloud.example.com/call/123');
+
+ self::assertNull($response->getData());
+ self::assertSame(401, $response->getStatus());
+ }
+
+ public function testGetEventsByLocation(): void {
+ $controller = new UpcomingEventsController(
+ $this->request,
+ 'u1',
+ $this->service,
+ );
+ $this->service->expects(self::once())
+ ->method('getEvents')
+ ->with('u1', 'https://cloud.example.com/call/123')
+ ->willReturn([
+ new UpcomingEvent(
+ 'abc-123',
+ null,
+ 'personal',
+ 123,
+ 'Test',
+ 'https://cloud.example.com/call/123',
+ null,
+ ),
+ ]);
+
+ $response = $controller->getEvents('https://cloud.example.com/call/123');
+
+ self::assertNotNull($response->getData());
+ self::assertIsArray($response->getData());
+ self::assertCount(1, $response->getData()['events']);
+ self::assertSame(200, $response->getStatus());
+ $event1 = $response->getData()['events'][0];
+ self::assertEquals('abc-123', $event1['uri']);
+ }
+}
diff --git a/apps/dav/tests/unit/DAV/AnonymousOptionsTest.php b/apps/dav/tests/unit/DAV/AnonymousOptionsTest.php
index ea5450391e8..c99ebf327c8 100644
--- a/apps/dav/tests/unit/DAV/AnonymousOptionsTest.php
+++ b/apps/dav/tests/unit/DAV/AnonymousOptionsTest.php
@@ -1,9 +1,11 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\tests\unit\DAV;
+namespace OCA\DAV\Tests\unit\DAV;
use OCA\DAV\Connector\Sabre\AnonymousOptionsPlugin;
use Sabre\DAV\Auth\Backend\BasicCallBack;
@@ -14,7 +16,7 @@ use Sabre\HTTP\Sapi;
use Test\TestCase;
class AnonymousOptionsTest extends TestCase {
- private function sendRequest($method, $path, $userAgent = '') {
+ private function sendRequest(string $method, string $path, string $userAgent = '') {
$server = new Server();
$server->addPlugin(new AnonymousOptionsPlugin());
$server->addPlugin(new Plugin(new BasicCallBack(function () {
diff --git a/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php b/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php
index 088330cecff..0e82ef0a3ae 100644
--- a/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php
+++ b/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,25 +9,22 @@
namespace OCA\DAV\Tests\unit\DAV;
use OCA\DAV\Files\BrowserErrorPagePlugin;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\NotFound;
use Sabre\HTTP\Response;
class BrowserErrorPagePluginTest extends \Test\TestCase {
- /**
- * @dataProvider providesExceptions
- * @param $expectedCode
- * @param $exception
- */
- public function test($expectedCode, $exception): void {
- /** @var BrowserErrorPagePlugin | \PHPUnit\Framework\MockObject\MockObject $plugin */
- $plugin = $this->getMockBuilder(BrowserErrorPagePlugin::class)->setMethods(['sendResponse', 'generateBody'])->getMock();
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesExceptions')]
+ public function test(int $expectedCode, \Throwable $exception): void {
+ /** @var BrowserErrorPagePlugin&MockObject $plugin */
+ $plugin = $this->getMockBuilder(BrowserErrorPagePlugin::class)->onlyMethods(['sendResponse', 'generateBody'])->getMock();
$plugin->expects($this->once())->method('generateBody')->willReturn(':boom:');
$plugin->expects($this->once())->method('sendResponse');
- /** @var \Sabre\DAV\Server | \PHPUnit\Framework\MockObject\MockObject $server */
- $server = $this->getMockBuilder('Sabre\DAV\Server')->disableOriginalConstructor()->getMock();
+ /** @var \Sabre\DAV\Server&MockObject $server */
+ $server = $this->createMock('Sabre\DAV\Server');
$server->expects($this->once())->method('on');
- $httpResponse = $this->getMockBuilder(Response::class)->disableOriginalConstructor()->getMock();
+ $httpResponse = $this->createMock(Response::class);
$httpResponse->expects($this->once())->method('addHeaders');
$httpResponse->expects($this->once())->method('setStatus')->with($expectedCode);
$httpResponse->expects($this->once())->method('setBody')->with(':boom:');
@@ -35,7 +33,7 @@ class BrowserErrorPagePluginTest extends \Test\TestCase {
$plugin->logException($exception);
}
- public function providesExceptions() {
+ public static function providesExceptions(): array {
return [
[ 404, new NotFound()],
[ 500, new \RuntimeException()],
diff --git a/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php b/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php
index cb6447511e4..517969fc9a3 100644
--- a/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php
+++ b/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php
@@ -1,15 +1,20 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\DAV;
+namespace OCA\DAV\Tests\unit\DAV;
+use OCA\DAV\CalDAV\Calendar;
+use OCA\DAV\CalDAV\DefaultCalendarValidator;
use OCA\DAV\DAV\CustomPropertiesBackend;
+use OCA\DAV\Db\PropertyMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IUser;
-use Sabre\CalDAV\ICalendar;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\PropFind;
use Sabre\DAV\PropPatch;
@@ -26,20 +31,13 @@ use Test\TestCase;
class CustomPropertiesBackendTest extends TestCase {
private const BASE_URI = '/remote.php/dav/';
- /** @var Server | \PHPUnit\Framework\MockObject\MockObject */
- private $server;
-
- /** @var Tree | \PHPUnit\Framework\MockObject\MockObject */
- private $tree;
-
- /** @var IDBConnection */
- private $dbConnection;
-
- /** @var IUser | \PHPUnit\Framework\MockObject\MockObject */
- private $user;
-
- /** @var CustomPropertiesBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $backend;
+ private Server&MockObject $server;
+ private Tree&MockObject $tree;
+ private IDBConnection $dbConnection;
+ private IUser&MockObject $user;
+ private DefaultCalendarValidator&MockObject $defaultCalendarValidator;
+ private CustomPropertiesBackend $backend;
+ private PropertyMapper $propertyMapper;
protected function setUp(): void {
parent::setUp();
@@ -52,13 +50,17 @@ class CustomPropertiesBackendTest extends TestCase {
$this->user->method('getUID')
->with()
->willReturn('dummy_user_42');
- $this->dbConnection = \OC::$server->getDatabaseConnection();
+ $this->dbConnection = \OCP\Server::get(IDBConnection::class);
+ $this->propertyMapper = \OCP\Server::get(PropertyMapper::class);
+ $this->defaultCalendarValidator = $this->createMock(DefaultCalendarValidator::class);
$this->backend = new CustomPropertiesBackend(
$this->server,
$this->tree,
$this->dbConnection,
$this->user,
+ $this->propertyMapper,
+ $this->defaultCalendarValidator,
);
}
@@ -78,13 +80,13 @@ class CustomPropertiesBackendTest extends TestCase {
}
}
- protected function insertProps(string $user, string $path, array $props) {
+ protected function insertProps(string $user, string $path, array $props): void {
foreach ($props as $name => $value) {
$this->insertProp($user, $path, $name, $value);
}
}
- protected function insertProp(string $user, string $path, string $name, mixed $value) {
+ protected function insertProp(string $user, string $path, string $name, mixed $value): void {
$type = CustomPropertiesBackend::PROPERTY_TYPE_STRING;
if ($value instanceof Href) {
$value = $value->getHref();
@@ -103,7 +105,7 @@ class CustomPropertiesBackendTest extends TestCase {
$query->execute();
}
- protected function getProps(string $user, string $path) {
+ protected function getProps(string $user, string $path): array {
$query = $this->dbConnection->getQueryBuilder();
$query->select('propertyname', 'propertyvalue', 'valuetype')
->from('properties')
@@ -131,6 +133,8 @@ class CustomPropertiesBackendTest extends TestCase {
$this->tree,
$db,
$this->user,
+ $this->propertyMapper,
+ $this->defaultCalendarValidator,
);
$propFind = $this->createMock(PropFind::class);
@@ -195,7 +199,7 @@ class CustomPropertiesBackendTest extends TestCase {
public function testPropFindPrincipalCall(): void {
$this->tree->method('getNodeForPath')
->willReturnCallback(function ($uri) {
- $node = $this->createMock(ICalendar::class);
+ $node = $this->createMock(Calendar::class);
$node->method('getOwner')
->willReturn('principals/users/dummy_user_42');
return $node;
@@ -237,26 +241,26 @@ class CustomPropertiesBackendTest extends TestCase {
$this->assertEquals($props, $setProps);
}
- public function propFindPrincipalScheduleDefaultCalendarProviderUrlProvider(): array {
+ public static function propFindPrincipalScheduleDefaultCalendarProviderUrlProvider(): array {
// [ user, nodes, existingProps, requestedProps, returnedProps ]
return [
[ // Exists
'dummy_user_42',
- ['calendars/dummy_user_42/foo/' => ICalendar::class],
+ ['calendars/dummy_user_42/foo/' => Calendar::class],
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/dummy_user_42/foo/')],
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL'],
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/dummy_user_42/foo/')],
],
[ // Doesn't exist
'dummy_user_42',
- ['calendars/dummy_user_42/foo/' => ICalendar::class],
+ ['calendars/dummy_user_42/foo/' => Calendar::class],
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/dummy_user_42/bar/')],
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL'],
[],
],
[ // No privilege
'dummy_user_42',
- ['calendars/user2/baz/' => ICalendar::class],
+ ['calendars/user2/baz/' => Calendar::class],
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/user2/baz/')],
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL'],
[],
@@ -272,9 +276,7 @@ class CustomPropertiesBackendTest extends TestCase {
}
- /**
- * @dataProvider propFindPrincipalScheduleDefaultCalendarProviderUrlProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('propFindPrincipalScheduleDefaultCalendarProviderUrlProvider')]
public function testPropFindPrincipalScheduleDefaultCalendarUrl(
string $user,
array $nodes,
@@ -336,9 +338,7 @@ class CustomPropertiesBackendTest extends TestCase {
$this->assertEquals($returnedProps, $setProps);
}
- /**
- * @dataProvider propPatchProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('propPatchProvider')]
public function testPropPatch(string $path, array $existing, array $props, array $result): void {
$this->server->method('calculateUri')
->willReturnCallback(function ($uri) {
@@ -349,7 +349,7 @@ class CustomPropertiesBackendTest extends TestCase {
});
$this->tree->method('getNodeForPath')
->willReturnCallback(function ($uri) {
- $node = $this->createMock(ICalendar::class);
+ $node = $this->createMock(Calendar::class);
$node->method('getOwner')
->willReturn('principals/users/' . $this->user->getUID());
return $node;
@@ -365,7 +365,7 @@ class CustomPropertiesBackendTest extends TestCase {
$this->assertEquals($result, $storedProps);
}
- public function propPatchProvider() {
+ public static function propPatchProvider(): array {
$longPath = str_repeat('long_path', 100);
return [
['foo_bar_path_1337', [], ['{DAV:}displayname' => 'anything'], ['{DAV:}displayname' => 'anything']],
@@ -377,25 +377,63 @@ class CustomPropertiesBackendTest extends TestCase {
];
}
- /**
- * @dataProvider deleteProvider
- */
+ public function testPropPatchWithUnsuitableCalendar(): void {
+ $path = 'principals/users/' . $this->user->getUID();
+
+ $node = $this->createMock(Calendar::class);
+ $node->expects(self::once())
+ ->method('getOwner')
+ ->willReturn($path);
+
+ $this->defaultCalendarValidator->expects(self::once())
+ ->method('validateScheduleDefaultCalendar')
+ ->with($node)
+ ->willThrowException(new \Sabre\DAV\Exception('Invalid calendar'));
+
+ $this->server->method('calculateUri')
+ ->willReturnCallback(function ($uri) {
+ if (str_starts_with($uri, self::BASE_URI)) {
+ return trim(substr($uri, strlen(self::BASE_URI)), '/');
+ }
+ return null;
+ });
+ $this->tree->expects(self::once())
+ ->method('getNodeForPath')
+ ->with('foo/bar/')
+ ->willReturn($node);
+
+ $storedProps = $this->getProps($this->user->getUID(), $path);
+ $this->assertEquals([], $storedProps);
+
+ $propPatch = new PropPatch([
+ '{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('foo/bar/'),
+ ]);
+ $this->backend->propPatch($path, $propPatch);
+ try {
+ $propPatch->commit();
+ } catch (\Throwable $e) {
+ $this->assertInstanceOf(\Sabre\DAV\Exception::class, $e);
+ }
+
+ $storedProps = $this->getProps($this->user->getUID(), $path);
+ $this->assertEquals([], $storedProps);
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('deleteProvider')]
public function testDelete(string $path): void {
$this->insertProps('dummy_user_42', $path, ['foo' => 'bar']);
$this->backend->delete($path);
$this->assertEquals([], $this->getProps('dummy_user_42', $path));
}
- public function deleteProvider() {
+ public static function deleteProvider(): array {
return [
['foo_bar_path_1337'],
[str_repeat('long_path', 100)]
];
}
- /**
- * @dataProvider moveProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('moveProvider')]
public function testMove(string $source, string $target): void {
$this->insertProps('dummy_user_42', $source, ['foo' => 'bar']);
$this->backend->move($source, $target);
@@ -403,10 +441,26 @@ class CustomPropertiesBackendTest extends TestCase {
$this->assertEquals(['foo' => 'bar'], $this->getProps('dummy_user_42', $target));
}
- public function moveProvider() {
+ public static function moveProvider(): array {
return [
['foo_bar_path_1337', 'foo_bar_path_7333'],
[str_repeat('long_path1', 100), str_repeat('long_path2', 100)]
];
}
+
+ public function testDecodeValueFromDatabaseObjectCurrent(): void {
+ $propertyValue = 'O:48:"Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp":1:{s:8:"\x00*\x00value";s:6:"opaque";}';
+ $propertyType = 3;
+ $decodeValue = $this->invokePrivate($this->backend, 'decodeValueFromDatabase', [$propertyValue, $propertyType]);
+ $this->assertInstanceOf(\Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp::class, $decodeValue);
+ $this->assertEquals('opaque', $decodeValue->getValue());
+ }
+
+ public function testDecodeValueFromDatabaseObjectLegacy(): void {
+ $propertyValue = 'O:48:"Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp":1:{s:8:"' . chr(0) . '*' . chr(0) . 'value";s:6:"opaque";}';
+ $propertyType = 3;
+ $decodeValue = $this->invokePrivate($this->backend, 'decodeValueFromDatabase', [$propertyValue, $propertyType]);
+ $this->assertInstanceOf(\Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp::class, $decodeValue);
+ $this->assertEquals('opaque', $decodeValue->getValue());
+ }
}
diff --git a/apps/dav/tests/unit/DAV/GroupPrincipalTest.php b/apps/dav/tests/unit/DAV/GroupPrincipalTest.php
index 92c89fc62f8..2756152a6e2 100644
--- a/apps/dav/tests/unit/DAV/GroupPrincipalTest.php
+++ b/apps/dav/tests/unit/DAV/GroupPrincipalTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -18,20 +20,11 @@ use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\PropPatch;
class GroupPrincipalTest extends \Test\TestCase {
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var IGroupManager | MockObject */
- private $groupManager;
-
- /** @var IUserSession | MockObject */
- private $userSession;
-
- /** @var IManager | MockObject */
- private $shareManager;
-
- /** @var GroupPrincipalBackend */
- private $connector;
+ private IConfig&MockObject $config;
+ private IGroupManager&MockObject $groupManager;
+ private IUserSession&MockObject $userSession;
+ private IManager&MockObject $shareManager;
+ private GroupPrincipalBackend $connector;
protected function setUp(): void {
$this->groupManager = $this->createMock(IGroupManager::class);
@@ -199,14 +192,7 @@ class GroupPrincipalTest extends \Test\TestCase {
['{DAV:}displayname' => 'Foo']));
}
- /**
- * @dataProvider searchPrincipalsDataProvider
- * @param bool $sharingEnabled
- * @param bool $groupSharingEnabled
- * @param bool $groupsOnly
- * @param string $test
- * @param array $result
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('searchPrincipalsDataProvider')]
public function testSearchPrincipals(bool $sharingEnabled, bool $groupSharingEnabled, bool $groupsOnly, string $test, array $result): void {
$this->shareManager->expects($this->once())
->method('shareAPIEnabled')
@@ -264,7 +250,7 @@ class GroupPrincipalTest extends \Test\TestCase {
['{DAV:}displayname' => 'Foo'], $test));
}
- public function searchPrincipalsDataProvider() {
+ public static function searchPrincipalsDataProvider(): array {
return [
[true, true, false, 'allof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group3', 'principals/groups/group4', 'principals/groups/group5']],
[true, true, false, 'anyof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group3', 'principals/groups/group4', 'principals/groups/group5']],
@@ -277,14 +263,7 @@ class GroupPrincipalTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider findByUriDataProvider
- * @param bool $sharingEnabled
- * @param bool $groupSharingEnabled
- * @param bool $groupsOnly
- * @param string $findUri
- * @param string|null $result
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('findByUriDataProvider')]
public function testFindByUri(bool $sharingEnabled, bool $groupSharingEnabled, bool $groupsOnly, string $findUri, ?string $result): void {
$this->shareManager->expects($this->once())
->method('shareAPIEnabled')
@@ -320,7 +299,7 @@ class GroupPrincipalTest extends \Test\TestCase {
$this->assertEquals($result, $this->connector->findByUri($findUri, 'principals/groups'));
}
- public function findByUriDataProvider() {
+ public static function findByUriDataProvider(): array {
return [
[false, false, false, 'principal:principals/groups/group1', null],
[false, false, false, 'principal:principals/groups/group3', null],
@@ -337,10 +316,7 @@ class GroupPrincipalTest extends \Test\TestCase {
];
}
- /**
- * @return Group|MockObject
- */
- private function mockGroup($gid) {
+ private function mockGroup(string $gid): Group&MockObject {
$fooGroup = $this->createMock(Group::class);
$fooGroup
->expects($this->exactly(1))
@@ -349,7 +325,7 @@ class GroupPrincipalTest extends \Test\TestCase {
$fooGroup
->expects($this->exactly(1))
->method('getDisplayName')
- ->willReturn('Group '.$gid);
+ ->willReturn('Group ' . $gid);
return $fooGroup;
}
}
diff --git a/apps/dav/tests/unit/DAV/HookManagerTest.php b/apps/dav/tests/unit/DAV/HookManagerTest.php
deleted file mode 100644
index 746727cd2b3..00000000000
--- a/apps/dav/tests/unit/DAV/HookManagerTest.php
+++ /dev/null
@@ -1,222 +0,0 @@
-<?php
-
-/**
- * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
- * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-namespace OCA\DAV\Tests\unit\DAV;
-
-use OCA\DAV\CalDAV\CalDavBackend;
-use OCA\DAV\CardDAV\CardDavBackend;
-use OCA\DAV\CardDAV\SyncService;
-use OCA\DAV\HookManager;
-use OCP\Defaults;
-use OCP\IL10N;
-use OCP\IUser;
-use OCP\IUserManager;
-use PHPUnit\Framework\MockObject\MockObject;
-use Test\TestCase;
-
-class HookManagerTest extends TestCase {
- /** @var IL10N */
- private $l10n;
-
- protected function setUp(): void {
- parent::setUp();
- $this->l10n = $this->createMock(IL10N::class);
- $this->l10n
- ->expects($this->any())
- ->method('t')
- ->willReturnCallback(function ($text, $parameters = []) {
- return vsprintf($text, $parameters);
- });
- }
-
- public function test(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
- $user->expects($this->once())->method('getUID')->willReturn('newUser');
-
- /** @var IUserManager | MockObject $userManager */
- $userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var SyncService | MockObject $syncService */
- $syncService = $this->getMockBuilder(SyncService::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var Defaults | MockObject $syncService */
- $defaults = $this->getMockBuilder(Defaults::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $defaults->expects($this->once())->method('getColorPrimary')->willReturn('#745bca');
-
- /** @var CalDavBackend | MockObject $cal */
- $cal = $this->getMockBuilder(CalDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $cal->expects($this->once())->method('getCalendarsForUserCount')->willReturn(0);
- $cal->expects($this->once())->method('createCalendar')->with(
- 'principals/users/newUser',
- 'personal', [
- '{DAV:}displayname' => 'Personal',
- '{http://apple.com/ns/ical/}calendar-color' => '#745bca',
- 'components' => 'VEVENT'
- ]);
-
- /** @var CardDavBackend | MockObject $card */
- $card = $this->getMockBuilder(CardDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $card->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(0);
- $card->expects($this->once())->method('createAddressBook')->with(
- 'principals/users/newUser',
- 'contacts', ['{DAV:}displayname' => 'Contacts']);
-
- $hm = new HookManager($userManager, $syncService, $cal, $card, $defaults);
- $hm->firstLogin($user);
- }
-
- public function testWithExisting(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
- $user->expects($this->once())->method('getUID')->willReturn('newUser');
-
- /** @var IUserManager | MockObject $userManager */
- $userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var SyncService | MockObject $syncService */
- $syncService = $this->getMockBuilder(SyncService::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var Defaults | MockObject $syncService */
- $defaults = $this->getMockBuilder(Defaults::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var CalDavBackend | MockObject $cal */
- $cal = $this->getMockBuilder(CalDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $cal->expects($this->once())->method('getCalendarsForUserCount')->willReturn(1);
- $cal->expects($this->never())->method('createCalendar');
-
- /** @var CardDavBackend | MockObject $card */
- $card = $this->getMockBuilder(CardDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $card->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(1);
- $card->expects($this->never())->method('createAddressBook');
-
- $hm = new HookManager($userManager, $syncService, $cal, $card, $defaults);
- $hm->firstLogin($user);
- }
-
- public function testWithBirthdayCalendar(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
- $user->expects($this->once())->method('getUID')->willReturn('newUser');
-
- /** @var IUserManager | MockObject $userManager */
- $userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var SyncService | MockObject $syncService */
- $syncService = $this->getMockBuilder(SyncService::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var Defaults | MockObject $syncService */
- $defaults = $this->getMockBuilder(Defaults::class)
- ->disableOriginalConstructor()
- ->getMock();
- $defaults->expects($this->once())->method('getColorPrimary')->willReturn('#745bca');
-
- /** @var CalDavBackend | MockObject $cal */
- $cal = $this->getMockBuilder(CalDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $cal->expects($this->once())->method('getCalendarsForUserCount')->willReturn(0);
- $cal->expects($this->once())->method('createCalendar')->with(
- 'principals/users/newUser',
- 'personal', [
- '{DAV:}displayname' => 'Personal',
- '{http://apple.com/ns/ical/}calendar-color' => '#745bca',
- 'components' => 'VEVENT'
- ]);
-
- /** @var CardDavBackend | MockObject $card */
- $card = $this->getMockBuilder(CardDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $card->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(0);
- $card->expects($this->once())->method('createAddressBook')->with(
- 'principals/users/newUser',
- 'contacts', ['{DAV:}displayname' => 'Contacts']);
-
- $hm = new HookManager($userManager, $syncService, $cal, $card, $defaults);
- $hm->firstLogin($user);
- }
-
- public function testDeleteCalendar(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var IUserManager | MockObject $userManager */
- $userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $userManager->expects($this->once())->method('get')->willReturn($user);
-
- /** @var SyncService | MockObject $syncService */
- $syncService = $this->getMockBuilder(SyncService::class)
- ->disableOriginalConstructor()
- ->getMock();
- $syncService->expects($this->once())
- ->method('deleteUser');
-
- /** @var Defaults | MockObject $syncService */
- $defaults = $this->getMockBuilder(Defaults::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var CalDavBackend | MockObject $cal */
- $cal = $this->getMockBuilder(CalDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $cal->expects($this->once())->method('getUsersOwnCalendars')->willReturn([
- ['id' => 'personal']
- ]);
- $cal->expects($this->once())->method('getSubscriptionsForUser')->willReturn([
- ['id' => 'some-subscription']
- ]);
- $cal->expects($this->once())->method('deleteCalendar')->with('personal');
- $cal->expects($this->once())->method('deleteSubscription')->with('some-subscription');
- $cal->expects($this->once())->method('deleteAllSharesByUser');
-
- /** @var CardDavBackend | MockObject $card */
- $card = $this->getMockBuilder(CardDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $card->expects($this->once())->method('getUsersOwnAddressBooks')->willReturn([
- ['id' => 'personal']
- ]);
- $card->expects($this->once())->method('deleteAddressBook');
-
- $hm = new HookManager($userManager, $syncService, $cal, $card, $defaults);
- $hm->preDeleteUser(['uid' => 'newUser']);
- $hm->postDeleteUser(['uid' => 'newUser']);
- }
-}
diff --git a/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php b/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php
new file mode 100644
index 00000000000..8e410eb0a78
--- /dev/null
+++ b/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php
@@ -0,0 +1,183 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+namespace OCA\DAV\Tests\unit\DAV\Listener;
+
+use OCA\DAV\BackgroundJob\UserStatusAutomation;
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CardDAV\CardDavBackend;
+use OCA\DAV\CardDAV\SyncService;
+use OCA\DAV\Listener\UserEventsListener;
+use OCA\DAV\Service\ExampleContactService;
+use OCA\DAV\Service\ExampleEventService;
+use OCP\BackgroundJob\IJobList;
+use OCP\Defaults;
+use OCP\IUser;
+use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+use Test\TestCase;
+
+class UserEventsListenerTest extends TestCase {
+ private IUserManager&MockObject $userManager;
+ private SyncService&MockObject $syncService;
+ private CalDavBackend&MockObject $calDavBackend;
+ private CardDavBackend&MockObject $cardDavBackend;
+ private Defaults&MockObject $defaults;
+ private ExampleContactService&MockObject $exampleContactService;
+ private ExampleEventService&MockObject $exampleEventService;
+ private LoggerInterface&MockObject $logger;
+
+ private UserEventsListener $userEventsListener;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->syncService = $this->createMock(SyncService::class);
+ $this->calDavBackend = $this->createMock(CalDavBackend::class);
+ $this->cardDavBackend = $this->createMock(CardDavBackend::class);
+ $this->defaults = $this->createMock(Defaults::class);
+ $this->exampleContactService = $this->createMock(ExampleContactService::class);
+ $this->exampleEventService = $this->createMock(ExampleEventService::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->jobList = $this->createMock(IJobList::class);
+
+ $this->userEventsListener = new UserEventsListener(
+ $this->userManager,
+ $this->syncService,
+ $this->calDavBackend,
+ $this->cardDavBackend,
+ $this->defaults,
+ $this->exampleContactService,
+ $this->exampleEventService,
+ $this->logger,
+ $this->jobList,
+ );
+ }
+
+ public function test(): void {
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->once())->method('getUID')->willReturn('newUser');
+
+ $this->defaults->expects($this->once())->method('getColorPrimary')->willReturn('#745bca');
+
+ $this->calDavBackend->expects($this->once())->method('getCalendarsForUserCount')->willReturn(0);
+ $this->calDavBackend->expects($this->once())->method('createCalendar')->with(
+ 'principals/users/newUser',
+ 'personal', [
+ '{DAV:}displayname' => 'Personal',
+ '{http://apple.com/ns/ical/}calendar-color' => '#745bca',
+ 'components' => 'VEVENT'
+ ])
+ ->willReturn(1000);
+ $this->calDavBackend->expects(self::never())
+ ->method('getCalendarsForUser');
+ $this->exampleEventService->expects(self::once())
+ ->method('createExampleEvent')
+ ->with(1000);
+
+ $this->cardDavBackend->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(0);
+ $this->cardDavBackend->expects($this->once())->method('createAddressBook')->with(
+ 'principals/users/newUser',
+ 'contacts', ['{DAV:}displayname' => 'Contacts']);
+
+ $this->userEventsListener->firstLogin($user);
+ }
+
+ public function testWithExisting(): void {
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->once())->method('getUID')->willReturn('newUser');
+
+ $this->calDavBackend->expects($this->once())->method('getCalendarsForUserCount')->willReturn(1);
+ $this->calDavBackend->expects($this->never())->method('createCalendar');
+ $this->calDavBackend->expects(self::never())
+ ->method('createCalendar');
+ $this->exampleEventService->expects(self::never())
+ ->method('createExampleEvent');
+
+ $this->cardDavBackend->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(1);
+ $this->cardDavBackend->expects($this->never())->method('createAddressBook');
+
+ $this->userEventsListener->firstLogin($user);
+ }
+
+ public function testWithBirthdayCalendar(): void {
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->once())->method('getUID')->willReturn('newUser');
+
+ $this->defaults->expects($this->once())->method('getColorPrimary')->willReturn('#745bca');
+
+ $this->calDavBackend->expects($this->once())->method('getCalendarsForUserCount')->willReturn(0);
+ $this->calDavBackend->expects($this->once())->method('createCalendar')->with(
+ 'principals/users/newUser',
+ 'personal', [
+ '{DAV:}displayname' => 'Personal',
+ '{http://apple.com/ns/ical/}calendar-color' => '#745bca',
+ 'components' => 'VEVENT'
+ ]);
+
+ $this->cardDavBackend->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(0);
+ $this->cardDavBackend->expects($this->once())->method('createAddressBook')->with(
+ 'principals/users/newUser',
+ 'contacts', ['{DAV:}displayname' => 'Contacts']);
+
+ $this->userEventsListener->firstLogin($user);
+ }
+
+ public function testDeleteCalendar(): void {
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->once())->method('getUID')->willReturn('newUser');
+
+ $this->syncService->expects($this->once())
+ ->method('deleteUser');
+
+ $this->calDavBackend->expects($this->once())->method('getUsersOwnCalendars')->willReturn([
+ ['id' => 'personal']
+ ]);
+ $this->calDavBackend->expects($this->once())->method('getSubscriptionsForUser')->willReturn([
+ ['id' => 'some-subscription']
+ ]);
+ $this->calDavBackend->expects($this->once())->method('deleteCalendar')->with('personal');
+ $this->calDavBackend->expects($this->once())->method('deleteSubscription')->with('some-subscription');
+ $this->calDavBackend->expects($this->once())->method('deleteAllSharesByUser');
+
+ $this->cardDavBackend->expects($this->once())->method('getUsersOwnAddressBooks')->willReturn([
+ ['id' => 'personal']
+ ]);
+ $this->cardDavBackend->expects($this->once())->method('deleteAddressBook');
+
+ $this->userEventsListener->preDeleteUser($user);
+ $this->userEventsListener->postDeleteUser('newUser');
+ }
+
+ public function testDeleteUserAutomationEvent(): void {
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->once())->method('getUID')->willReturn('newUser');
+
+ $this->syncService->expects($this->once())
+ ->method('deleteUser');
+
+ $this->calDavBackend->expects($this->once())->method('getUsersOwnCalendars')->willReturn([
+ ['id' => []]
+ ]);
+ $this->calDavBackend->expects($this->once())->method('getSubscriptionsForUser')->willReturn([
+ ['id' => []]
+ ]);
+ $this->cardDavBackend->expects($this->once())->method('getUsersOwnAddressBooks')->willReturn([
+ ['id' => []]
+ ]);
+
+ $this->jobList->expects(self::once())->method('remove')->with(UserStatusAutomation::class, ['userId' => 'newUser']);
+
+ $this->userEventsListener->preDeleteUser($user);
+ $this->userEventsListener->postDeleteUser('newUser');
+ }
+}
diff --git a/apps/dav/tests/unit/DAV/Sharing/BackendTest.php b/apps/dav/tests/unit/DAV/Sharing/BackendTest.php
index 344d57d1808..556a623a73f 100644
--- a/apps/dav/tests/unit/DAV/Sharing/BackendTest.php
+++ b/apps/dav/tests/unit/DAV/Sharing/BackendTest.php
@@ -24,14 +24,14 @@ use Test\TestCase;
class BackendTest extends TestCase {
- private IDBConnection|MockObject $db;
- private IUserManager|MockObject $userManager;
- private IGroupManager|MockObject $groupManager;
- private MockObject|Principal $principalBackend;
- private MockObject|ICache $shareCache;
- private LoggerInterface|MockObject $logger;
- private MockObject|ICacheFactory $cacheFactory;
- private Service|MockObject $calendarService;
+ private IDBConnection&MockObject $db;
+ private IUserManager&MockObject $userManager;
+ private IGroupManager&MockObject $groupManager;
+ private Principal&MockObject $principalBackend;
+ private ICache&MockObject $shareCache;
+ private LoggerInterface&MockObject $logger;
+ private ICacheFactory&MockObject $cacheFactory;
+ private Service&MockObject $calendarService;
private CalendarSharingBackend $backend;
protected function setUp(): void {
@@ -214,10 +214,7 @@ class BackendTest extends TestCase {
'getResourceId' => 42,
]);
$remove = [
- [
- 'href' => 'principal:principals/users/bob',
- 'readOnly' => true,
- ]
+ 'principal:principals/users/bob',
];
$principal = 'principals/users/bob';
@@ -229,9 +226,6 @@ class BackendTest extends TestCase {
$this->calendarService->expects(self::once())
->method('deleteShare')
->with($shareable->getResourceId(), $principal);
- $this->calendarService->expects(self::once())
- ->method('hasGroupShare')
- ->willReturn(false);
$this->calendarService->expects(self::never())
->method('unshare');
@@ -244,10 +238,7 @@ class BackendTest extends TestCase {
'getResourceId' => 42,
]);
$remove = [
- [
- 'href' => 'principal:principals/users/bob',
- 'readOnly' => true,
- ]
+ 'principal:principals/users/bob',
];
$oldShares = [
[
@@ -269,13 +260,8 @@ class BackendTest extends TestCase {
$this->calendarService->expects(self::once())
->method('deleteShare')
->with($shareable->getResourceId(), 'principals/users/bob');
- $this->calendarService->expects(self::once())
- ->method('hasGroupShare')
- ->with($oldShares)
- ->willReturn(true);
- $this->calendarService->expects(self::once())
- ->method('unshare')
- ->with($shareable->getResourceId(), 'principals/users/bob');
+ $this->calendarService->expects(self::never())
+ ->method('unshare');
$this->backend->updateShares($shareable, [], $remove, $oldShares);
}
diff --git a/apps/dav/tests/unit/DAV/Sharing/PluginTest.php b/apps/dav/tests/unit/DAV/Sharing/PluginTest.php
index 9c6950f19e8..7a88f7cc5dd 100644
--- a/apps/dav/tests/unit/DAV/Sharing/PluginTest.php
+++ b/apps/dav/tests/unit/DAV/Sharing/PluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -12,6 +13,7 @@ use OCA\DAV\DAV\Sharing\IShareable;
use OCA\DAV\DAV\Sharing\Plugin;
use OCP\IConfig;
use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Server;
use Sabre\DAV\SimpleCollection;
use Sabre\HTTP\Request;
@@ -19,32 +21,24 @@ use Sabre\HTTP\Response;
use Test\TestCase;
class PluginTest extends TestCase {
-
- /** @var Plugin */
- private $plugin;
- /** @var Server */
- private $server;
- /** @var IShareable | \PHPUnit\Framework\MockObject\MockObject */
- private $book;
+ private Plugin $plugin;
+ private Server $server;
+ private IShareable&MockObject $book;
protected function setUp(): void {
parent::setUp();
- /** @var Auth | \PHPUnit\Framework\MockObject\MockObject $authBackend */
- $authBackend = $this->getMockBuilder(Auth::class)->disableOriginalConstructor()->getMock();
+ $authBackend = $this->createMock(Auth::class);
$authBackend->method('isDavAuthenticated')->willReturn(true);
- /** @var IRequest $request */
- $request = $this->getMockBuilder(IRequest::class)->disableOriginalConstructor()->getMock();
+ $request = $this->createMock(IRequest::class);
$config = $this->createMock(IConfig::class);
$this->plugin = new Plugin($authBackend, $request, $config);
$root = new SimpleCollection('root');
$this->server = new \Sabre\DAV\Server($root);
/** @var SimpleCollection $node */
- $this->book = $this->getMockBuilder(IShareable::class)->
- disableOriginalConstructor()->
- getMock();
+ $this->book = $this->createMock(IShareable::class);
$this->book->method('getName')->willReturn('addressbook1.vcf');
$root->addChild($this->book);
$this->plugin->initialize($this->server);
diff --git a/apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php b/apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php
deleted file mode 100644
index fad077eeda3..00000000000
--- a/apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-declare(strict_types=1);
-/**
- * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-namespace OCA\DAV\Tests\unit\DAV\Sharing;
-
-use OCA\DAV\CalDAV\Sharing\Service;
-use OCA\DAV\DAV\Sharing\SharingMapper;
-use OCA\DAV\DAV\Sharing\SharingService;
-use Test\TestCase;
-
-class SharingServiceTest extends TestCase {
-
- private SharingService $service;
-
- protected function setUp(): void {
- parent::setUp();
- $this->service = new Service($this->createMock(SharingMapper::class));
- }
-
- public function testHasGroupShare(): void {
- $oldShares = [
- [
- 'href' => 'principal:principals/groups/bob',
- 'commonName' => 'bob',
- 'status' => 1,
- 'readOnly' => true,
- '{http://owncloud.org/ns}principal' => 'principals/groups/bob',
- '{http://owncloud.org/ns}group-share' => true,
- ],
- [
- 'href' => 'principal:principals/users/bob',
- 'commonName' => 'bob',
- 'status' => 1,
- 'readOnly' => true,
- '{http://owncloud.org/ns}principal' => 'principals/users/bob',
- '{http://owncloud.org/ns}group-share' => false,
- ]
- ];
-
- $this->assertTrue($this->service->hasGroupShare($oldShares));
-
- $oldShares = [
- [
- 'href' => 'principal:principals/users/bob',
- 'commonName' => 'bob',
- 'status' => 1,
- 'readOnly' => true,
- '{http://owncloud.org/ns}principal' => 'principals/users/bob',
- '{http://owncloud.org/ns}group-share' => false,
- ]
- ];
- $this->assertFalse($this->service->hasGroupShare($oldShares));
- }
-}
diff --git a/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php b/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php
index 32916804080..3df861accf2 100644
--- a/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php
+++ b/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,22 +9,19 @@
namespace OCA\DAV\Tests\unit\DAV;
use OCA\DAV\DAV\SystemPrincipalBackend;
+use Sabre\DAV\Exception;
use Test\TestCase;
class SystemPrincipalBackendTest extends TestCase {
- /**
- * @dataProvider providesPrefix
- * @param $expected
- * @param $prefix
- */
- public function testGetPrincipalsByPrefix($expected, $prefix): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesPrefix')]
+ public function testGetPrincipalsByPrefix(array $expected, string $prefix): void {
$backend = new SystemPrincipalBackend();
$result = $backend->getPrincipalsByPrefix($prefix);
$this->assertEquals($expected, $result);
}
- public function providesPrefix() {
+ public static function providesPrefix(): array {
return [
[[], ''],
[[[
@@ -38,18 +36,14 @@ class SystemPrincipalBackendTest extends TestCase {
];
}
- /**
- * @dataProvider providesPath
- * @param $expected
- * @param $path
- */
- public function testGetPrincipalByPath($expected, $path): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesPath')]
+ public function testGetPrincipalByPath(?array $expected, string $path): void {
$backend = new SystemPrincipalBackend();
$result = $backend->getPrincipalByPath($path);
$this->assertEquals($expected, $result);
}
- public function providesPath() {
+ public static function providesPath(): array {
return [
[null, ''],
[null, 'principals'],
@@ -61,59 +55,43 @@ class SystemPrincipalBackendTest extends TestCase {
];
}
- /**
- * @dataProvider providesPrincipalForGetGroupMemberSet
- *
- * @param string $principal
- * @throws \Sabre\DAV\Exception
- */
- public function testGetGroupMemberSetExceptional($principal): void {
- $this->expectException(\Sabre\DAV\Exception::class);
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesPrincipalForGetGroupMemberSet')]
+ public function testGetGroupMemberSetExceptional(?string $principal): void {
+ $this->expectException(Exception::class);
$this->expectExceptionMessage('Principal not found');
$backend = new SystemPrincipalBackend();
$backend->getGroupMemberSet($principal);
}
- public function providesPrincipalForGetGroupMemberSet() {
+ public static function providesPrincipalForGetGroupMemberSet(): array {
return [
[null],
['principals/system'],
];
}
- /**
- * @throws \Sabre\DAV\Exception
- */
public function testGetGroupMemberSet(): void {
$backend = new SystemPrincipalBackend();
$result = $backend->getGroupMemberSet('principals/system/system');
$this->assertEquals(['principals/system/system'], $result);
}
- /**
- * @dataProvider providesPrincipalForGetGroupMembership
- *
- * @param string $principal
- * @throws \Sabre\DAV\Exception
- */
- public function testGetGroupMembershipExceptional($principal): void {
- $this->expectException(\Sabre\DAV\Exception::class);
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesPrincipalForGetGroupMembership')]
+ public function testGetGroupMembershipExceptional(string $principal): void {
+ $this->expectException(Exception::class);
$this->expectExceptionMessage('Principal not found');
$backend = new SystemPrincipalBackend();
$backend->getGroupMembership($principal);
}
- public function providesPrincipalForGetGroupMembership() {
+ public static function providesPrincipalForGetGroupMembership(): array {
return [
['principals/system/a'],
];
}
- /**
- * @throws \Sabre\DAV\Exception
- */
public function testGetGroupMembership(): void {
$backend = new SystemPrincipalBackend();
$result = $backend->getGroupMembership('principals/system/system');
diff --git a/apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php b/apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php
index 63dd5b9145c..eefbc53fd22 100644
--- a/apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php
+++ b/apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2019 ownCloud GmbH
@@ -15,34 +16,34 @@ use OCA\Files_Versions\Sabre\VersionFile;
use OCA\Files_Versions\Versions\IVersion;
use OCP\Files\File;
use OCP\Files\Folder;
+use OCP\Files\Storage\ISharedStorage;
use OCP\Files\Storage\IStorage;
use OCP\IUser;
use OCP\Share\IAttributes;
use OCP\Share\IShare;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Server;
use Sabre\DAV\Tree;
use Sabre\HTTP\RequestInterface;
use Test\TestCase;
class ViewOnlyPluginTest extends TestCase {
-
+ private Tree&MockObject $tree;
+ private RequestInterface&MockObject $request;
+ private Folder&MockObject $userFolder;
private ViewOnlyPlugin $plugin;
- /** @var Tree | \PHPUnit\Framework\MockObject\MockObject */
- private $tree;
- /** @var RequestInterface | \PHPUnit\Framework\MockObject\MockObject */
- private $request;
- /** @var Folder | \PHPUnit\Framework\MockObject\MockObject */
- private $userFolder;
public function setUp(): void {
+ parent::setUp();
+
$this->userFolder = $this->createMock(Folder::class);
- $this->plugin = new ViewOnlyPlugin(
- $this->userFolder,
- );
$this->request = $this->createMock(RequestInterface::class);
$this->tree = $this->createMock(Tree::class);
-
$server = $this->createMock(Server::class);
+
+ $this->plugin = new ViewOnlyPlugin(
+ $this->userFolder,
+ );
$server->tree = $this->tree;
$this->plugin->initialize($server);
@@ -65,32 +66,36 @@ class ViewOnlyPluginTest extends TestCase {
$storage = $this->createMock(IStorage::class);
$file->method('getStorage')->willReturn($storage);
- $storage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(false);
+ $storage->method('instanceOfStorage')->with(ISharedStorage::class)->willReturn(false);
$this->assertTrue($this->plugin->checkViewOnly($this->request));
}
- public function providesDataForCanGet(): array {
+ public static function providesDataForCanGet(): array {
return [
// has attribute permissions-download enabled - can get file
- [false, true, true],
+ [false, true, true, true],
// has no attribute permissions-download - can get file
- [false, null, true],
- // has attribute permissions-download disabled- cannot get the file
- [false, false, false],
+ [false, null, true, true],
// has attribute permissions-download enabled - can get file version
- [true, true, true],
+ [true, true, true, true],
// has no attribute permissions-download - can get file version
- [true, null, true],
- // has attribute permissions-download disabled- cannot get the file version
- [true, false, false],
+ [true, null, true, true],
+ // has attribute permissions-download disabled - cannot get the file
+ [false, false, false, false],
+ // has attribute permissions-download disabled - cannot get the file version
+ [true, false, false, false],
+
+ // Has global allowViewWithoutDownload option enabled
+ // has attribute permissions-download disabled - can get file
+ [false, false, false, true],
+ // has attribute permissions-download disabled - can get file version
+ [true, false, false, true],
];
}
- /**
- * @dataProvider providesDataForCanGet
- */
- public function testCanGet(bool $isVersion, ?bool $attrEnabled, bool $expectCanDownloadFile): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesDataForCanGet')]
+ public function testCanGet(bool $isVersion, ?bool $attrEnabled, bool $expectCanDownloadFile, bool $allowViewWithoutDownload): void {
$nodeInfo = $this->createMock(File::class);
if ($isVersion) {
$davPath = 'versions/alice/versions/117/123456';
@@ -131,24 +136,28 @@ class ViewOnlyPluginTest extends TestCase {
$this->request->expects($this->once())->method('getPath')->willReturn($davPath);
$this->tree->expects($this->once())
- ->method('getNodeForPath')
- ->with($davPath)
- ->willReturn($davNode);
+ ->method('getNodeForPath')
+ ->with($davPath)
+ ->willReturn($davNode);
$storage = $this->createMock(SharedStorage::class);
$share = $this->createMock(IShare::class);
$nodeInfo->expects($this->once())
->method('getStorage')
->willReturn($storage);
- $storage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(true);
+ $storage->method('instanceOfStorage')->with(ISharedStorage::class)->willReturn(true);
$storage->method('getShare')->willReturn($share);
$extAttr = $this->createMock(IAttributes::class);
$share->method('getAttributes')->willReturn($extAttr);
$extAttr->expects($this->once())
- ->method('getAttribute')
- ->with('permissions', 'download')
- ->willReturn($attrEnabled);
+ ->method('getAttribute')
+ ->with('permissions', 'download')
+ ->willReturn($attrEnabled);
+
+ $share->expects($this->once())
+ ->method('canSeeContent')
+ ->willReturn($allowViewWithoutDownload);
if (!$expectCanDownloadFile) {
$this->expectException(Forbidden::class);
diff --git a/apps/dav/tests/unit/Direct/DirectFileTest.php b/apps/dav/tests/unit/Direct/DirectFileTest.php
index 07d19807ef0..f6f0f49fa8c 100644
--- a/apps/dav/tests/unit/Direct/DirectFileTest.php
+++ b/apps/dav/tests/unit/Direct/DirectFileTest.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\Direct;
+namespace OCA\DAV\Tests\unit\Direct;
use OCA\DAV\Db\Direct;
use OCA\DAV\Direct\DirectFile;
@@ -14,28 +14,17 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\Forbidden;
use Test\TestCase;
class DirectFileTest extends TestCase {
-
- /** @var Direct */
- private $direct;
-
- /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */
- private $rootFolder;
-
- /** @var Folder|\PHPUnit\Framework\MockObject\MockObject */
- private $userFolder;
-
- /** @var File|\PHPUnit\Framework\MockObject\MockObject */
- private $file;
-
- /** @var DirectFile */
- private $directFile;
-
- /** @var IEventDispatcher */
- private $eventDispatcher;
+ private Direct $direct;
+ private IRootFolder&MockObject $rootFolder;
+ private Folder&MockObject $userFolder;
+ private File&MockObject $file;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private DirectFile $directFile;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/Direct/DirectHomeTest.php b/apps/dav/tests/unit/Direct/DirectHomeTest.php
index 1134f0cd3af..94c82c2b7c5 100644
--- a/apps/dav/tests/unit/Direct/DirectHomeTest.php
+++ b/apps/dav/tests/unit/Direct/DirectHomeTest.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\Direct;
+namespace OCA\DAV\Tests\unit\Direct;
use OCA\DAV\Db\Direct;
use OCA\DAV\Db\DirectMapper;
@@ -18,33 +18,20 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\IRootFolder;
use OCP\IRequest;
use OCP\Security\Bruteforce\IThrottler;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\MethodNotAllowed;
use Sabre\DAV\Exception\NotFound;
use Test\TestCase;
class DirectHomeTest extends TestCase {
-
- /** @var DirectMapper|\PHPUnit\Framework\MockObject\MockObject */
- private $directMapper;
-
- /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */
- private $rootFolder;
-
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
-
- /** @var IThrottler|\PHPUnit\Framework\MockObject\MockObject */
- private $throttler;
-
- /** @var IRequest */
- private $request;
-
- /** @var DirectHome */
- private $directHome;
-
- /** @var IEventDispatcher */
- private $eventDispatcher;
+ private DirectMapper&MockObject $directMapper;
+ private IRootFolder&MockObject $rootFolder;
+ private ITimeFactory&MockObject $timeFactory;
+ private IThrottler&MockObject $throttler;
+ private IRequest&MockObject $request;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private DirectHome $directHome;
protected function setUp(): void {
parent::setUp();
@@ -160,7 +147,7 @@ class DirectHomeTest extends TestCase {
'1.2.3.4'
);
$this->throttler->expects($this->once())
- ->method('sleepDelay')
+ ->method('sleepDelayOrThrowOnMax')
->with(
'1.2.3.4',
'directlink'
diff --git a/apps/dav/tests/unit/Files/FileSearchBackendTest.php b/apps/dav/tests/unit/Files/FileSearchBackendTest.php
index f6fe8b1c116..c6d6f85347b 100644
--- a/apps/dav/tests/unit/Files/FileSearchBackendTest.php
+++ b/apps/dav/tests/unit/Files/FileSearchBackendTest.php
@@ -1,10 +1,12 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Files;
+namespace OCA\DAV\Tests\unit\Files;
use OC\Files\Search\SearchComparison;
use OC\Files\Search\SearchQuery;
@@ -13,6 +15,7 @@ use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\File;
use OCA\DAV\Connector\Sabre\FilesPlugin;
use OCA\DAV\Connector\Sabre\ObjectTree;
+use OCA\DAV\Connector\Sabre\Server;
use OCA\DAV\Files\FileSearchBackend;
use OCP\Files\FileInfo;
use OCP\Files\Folder;
@@ -23,36 +26,25 @@ use OCP\Files\Search\ISearchQuery;
use OCP\FilesMetadata\IFilesMetadataManager;
use OCP\IUser;
use OCP\Share\IManager;
+use PHPUnit\Framework\MockObject\MockObject;
use SearchDAV\Backend\SearchPropertyDefinition;
use SearchDAV\Query\Limit;
+use SearchDAV\Query\Literal;
use SearchDAV\Query\Operator;
use SearchDAV\Query\Query;
+use SearchDAV\Query\Scope;
use Test\TestCase;
class FileSearchBackendTest extends TestCase {
- /** @var ObjectTree|\PHPUnit\Framework\MockObject\MockObject */
- private $tree;
-
- /** @var IUser */
- private $user;
-
- /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */
- private $rootFolder;
-
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- private $shareManager;
-
- /** @var View|\PHPUnit\Framework\MockObject\MockObject */
- private $view;
-
- /** @var Folder|\PHPUnit\Framework\MockObject\MockObject */
- private $searchFolder;
-
- /** @var FileSearchBackend */
- private $search;
-
- /** @var Directory|\PHPUnit\Framework\MockObject\MockObject */
- private $davFolder;
+ private ObjectTree&MockObject $tree;
+ private Server&MockObject $server;
+ private IUser&MockObject $user;
+ private IRootFolder&MockObject $rootFolder;
+ private IManager&MockObject $shareManager;
+ private View&MockObject $view;
+ private Folder&MockObject $searchFolder;
+ private Directory&MockObject $davFolder;
+ private FileSearchBackend $search;
protected function setUp(): void {
parent::setUp();
@@ -62,11 +54,14 @@ class FileSearchBackendTest extends TestCase {
->method('getUID')
->willReturn('test');
- $this->tree = $this->getMockBuilder(ObjectTree::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $this->tree = $this->createMock(ObjectTree::class);
+ $this->server = $this->createMock(Server::class);
$this->view = $this->createMock(View::class);
+ $this->rootFolder = $this->createMock(IRootFolder::class);
+ $this->shareManager = $this->createMock(IManager::class);
+ $this->searchFolder = $this->createMock(Folder::class);
+ $fileInfo = $this->createMock(FileInfo::class);
+ $this->davFolder = $this->createMock(Directory::class);
$this->view->expects($this->any())
->method('getRoot')
@@ -76,16 +71,6 @@ class FileSearchBackendTest extends TestCase {
->method('getRelativePath')
->willReturnArgument(0);
- $this->rootFolder = $this->createMock(IRootFolder::class);
-
- $this->shareManager = $this->createMock(IManager::class);
-
- $this->searchFolder = $this->createMock(Folder::class);
-
- $fileInfo = $this->createMock(FileInfo::class);
-
- $this->davFolder = $this->createMock(Directory::class);
-
$this->davFolder->expects($this->any())
->method('getFileInfo')
->willReturn($fileInfo);
@@ -96,7 +81,7 @@ class FileSearchBackendTest extends TestCase {
$filesMetadataManager = $this->createMock(IFilesMetadataManager::class);
- $this->search = new FileSearchBackend($this->tree, $this->user, $this->rootFolder, $this->shareManager, $this->view, $filesMetadataManager);
+ $this->search = new FileSearchBackend($this->server, $this->tree, $this->user, $this->rootFolder, $this->shareManager, $this->view, $filesMetadataManager);
}
public function testSearchFilename(): void {
@@ -259,8 +244,8 @@ class FileSearchBackendTest extends TestCase {
$this->search->search($query);
}
- private function getBasicQuery($type, $property, $value = null) {
- $scope = new \SearchDAV\Query\Scope('/', 'infinite');
+ private function getBasicQuery(string $type, string $property, int|string|null $value = null) {
+ $scope = new Scope('/', 'infinite');
$scope->path = '/';
$from = [$scope];
$orderBy = [];
@@ -268,12 +253,12 @@ class FileSearchBackendTest extends TestCase {
if (is_null($value)) {
$where = new Operator(
$type,
- [new \SearchDAV\Query\Literal($property)]
+ [new Literal($property)]
);
} else {
$where = new Operator(
$type,
- [new SearchPropertyDefinition($property, true, true, true), new \SearchDAV\Query\Literal($value)]
+ [new SearchPropertyDefinition($property, true, true, true), new Literal($value)]
);
}
$limit = new Limit();
@@ -346,11 +331,11 @@ class FileSearchBackendTest extends TestCase {
[
new Operator(
Operator::OPERATION_EQUAL,
- [new SearchPropertyDefinition('{DAV:}getcontenttype', true, true, true), new \SearchDAV\Query\Literal('image/png')]
+ [new SearchPropertyDefinition('{DAV:}getcontenttype', true, true, true), new Literal('image/png')]
),
new Operator(
Operator::OPERATION_EQUAL,
- [new SearchPropertyDefinition(FilesPlugin::OWNER_ID_PROPERTYNAME, true, true, true), new \SearchDAV\Query\Literal($this->user->getUID())]
+ [new SearchPropertyDefinition(FilesPlugin::OWNER_ID_PROPERTYNAME, true, true, true), new Literal($this->user->getUID())]
),
]
);
@@ -379,7 +364,7 @@ class FileSearchBackendTest extends TestCase {
$innerOperator = new Operator(
Operator::OPERATION_EQUAL,
- [new SearchPropertyDefinition('{DAV:}getcontenttype', true, true, true), new \SearchDAV\Query\Literal('image/png')]
+ [new SearchPropertyDefinition('{DAV:}getcontenttype', true, true, true), new Literal('image/png')]
);
// 5 child operators
$level1Operator = new Operator(
@@ -420,4 +405,17 @@ class FileSearchBackendTest extends TestCase {
$this->expectException(\InvalidArgumentException::class);
$this->search->search($query);
}
+
+ public function testPreloadPropertyFor(): void {
+ $node1 = $this->createMock(File::class);
+ $node2 = $this->createMock(Directory::class);
+ $nodes = [$node1, $node2];
+ $requestProperties = ['{DAV:}getcontenttype', '{DAV:}getlastmodified'];
+
+ $this->server->expects($this->once())
+ ->method('emit')
+ ->with('preloadProperties', [$nodes, $requestProperties]);
+
+ $this->search->preloadPropertyFor($nodes, $requestProperties);
+ }
}
diff --git a/apps/dav/tests/unit/Files/MultipartRequestParserTest.php b/apps/dav/tests/unit/Files/MultipartRequestParserTest.php
index 3458708b23b..dc0e884f07c 100644
--- a/apps/dav/tests/unit/Files/MultipartRequestParserTest.php
+++ b/apps/dav/tests/unit/Files/MultipartRequestParserTest.php
@@ -1,61 +1,68 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
-namespace OCA\DAV\Tests\unit\DAV;
+namespace OCA\DAV\Tests\unit\Files;
use OCA\DAV\BulkUpload\MultipartRequestParser;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
+use Sabre\HTTP\RequestInterface;
use Test\TestCase;
class MultipartRequestParserTest extends TestCase {
- protected LoggerInterface $logger;
+ protected LoggerInterface&MockObject $logger;
protected function setUp(): void {
+ parent::setUp();
$this->logger = $this->createMock(LoggerInterface::class);
}
- private function getValidBodyObject() {
+ private static function getValidBodyObject(): array {
return [
[
- "headers" => [
- "Content-Length" => 7,
- "X-File-MD5" => "4f2377b4d911f7ec46325fe603c3af03",
- "X-File-Path" => "/coucou.txt"
+ 'headers' => [
+ 'Content-Length' => 7,
+ 'X-File-MD5' => '4f2377b4d911f7ec46325fe603c3af03',
+ 'OC-Checksum' => 'md5:4f2377b4d911f7ec46325fe603c3af03',
+ 'X-File-Path' => '/coucou.txt'
],
- "content" => "Coucou\n"
+ 'content' => "Coucou\n"
]
];
}
- private function getMultipartParser(array $parts, array $headers = [], string $boundary = "boundary_azertyuiop"): MultipartRequestParser {
- $request = $this->getMockBuilder('Sabre\HTTP\RequestInterface')
+ private function getMultipartParser(array $parts, array $headers = [], string $boundary = 'boundary_azertyuiop'): MultipartRequestParser {
+ /** @var RequestInterface&MockObject $request */
+ $request = $this->getMockBuilder(RequestInterface::class)
->disableOriginalConstructor()
->getMock();
- $headers = array_merge(['Content-Type' => 'multipart/related; boundary='.$boundary], $headers);
+ $headers = array_merge(['Content-Type' => 'multipart/related; boundary=' . $boundary], $headers);
$request->expects($this->any())
->method('getHeader')
->willReturnCallback(function (string $key) use (&$headers) {
return $headers[$key];
});
- $body = "";
+ $body = '';
foreach ($parts as $part) {
- $body .= '--'.$boundary."\r\n";
+ $body .= '--' . $boundary . "\r\n";
foreach ($part['headers'] as $headerKey => $headerPart) {
- $body .= $headerKey.": ".$headerPart."\r\n";
+ $body .= $headerKey . ': ' . $headerPart . "\r\n";
}
$body .= "\r\n";
- $body .= $part['content']."\r\n";
+ $body .= $part['content'] . "\r\n";
}
- $body .= '--'.$boundary."--";
+ $body .= '--' . $boundary . '--';
$stream = fopen('php://temp', 'r+');
fwrite($stream, $body);
@@ -73,8 +80,9 @@ class MultipartRequestParserTest extends TestCase {
* Test validation of the request's body type
*/
public function testBodyTypeValidation(): void {
- $bodyStream = "I am not a stream, but pretend to be";
- $request = $this->getMockBuilder('Sabre\HTTP\RequestInterface')
+ $bodyStream = 'I am not a stream, but pretend to be';
+ /** @var RequestInterface&MockObject $request */
+ $request = $this->getMockBuilder(RequestInterface::class)
->disableOriginalConstructor()
->getMock();
$request->expects($this->any())
@@ -88,50 +96,91 @@ class MultipartRequestParserTest extends TestCase {
/**
* Test with valid request.
* - valid boundary
- * - valid md5 hash
+ * - valid hash
* - valid content-length
* - valid file content
* - valid file path
*/
public function testValidRequest(): void {
- $multipartParser = $this->getMultipartParser(
- $this->getValidBodyObject()
- );
+ $bodyObject = self::getValidBodyObject();
+ unset($bodyObject['0']['headers']['X-File-MD5']);
+
+ $multipartParser = $this->getMultipartParser($bodyObject);
[$headers, $content] = $multipartParser->parseNextPart();
- $this->assertSame((int)$headers["content-length"], 7, "Content-Length header should be the same as provided.");
- $this->assertSame($headers["x-file-md5"], "4f2377b4d911f7ec46325fe603c3af03", "X-File-MD5 header should be the same as provided.");
- $this->assertSame($headers["x-file-path"], "/coucou.txt", "X-File-Path header should be the same as provided.");
+ $this->assertSame((int)$headers['content-length'], 7, 'Content-Length header should be the same as provided.');
+ $this->assertSame($headers['oc-checksum'], 'md5:4f2377b4d911f7ec46325fe603c3af03', 'OC-Checksum header should be the same as provided.');
+ $this->assertSame($headers['x-file-path'], '/coucou.txt', 'X-File-Path header should be the same as provided.');
+
+ $this->assertSame($content, "Coucou\n", 'Content should be the same');
+ }
- $this->assertSame($content, "Coucou\n", "Content should be the same");
+ /**
+ * Test with valid request.
+ * - valid boundary
+ * - valid md5 hash
+ * - valid content-length
+ * - valid file content
+ * - valid file path
+ */
+ public function testValidRequestWithMd5(): void {
+ $bodyObject = self::getValidBodyObject();
+ unset($bodyObject['0']['headers']['OC-Checksum']);
+
+ $multipartParser = $this->getMultipartParser($bodyObject);
+
+ [$headers, $content] = $multipartParser->parseNextPart();
+
+ $this->assertSame((int)$headers['content-length'], 7, 'Content-Length header should be the same as provided.');
+ $this->assertSame($headers['x-file-md5'], '4f2377b4d911f7ec46325fe603c3af03', 'X-File-MD5 header should be the same as provided.');
+ $this->assertSame($headers['x-file-path'], '/coucou.txt', 'X-File-Path header should be the same as provided.');
+
+ $this->assertSame($content, "Coucou\n", 'Content should be the same');
+ }
+
+ /**
+ * Test with invalid hash.
+ */
+ public function testInvalidHash(): void {
+ $bodyObject = self::getValidBodyObject();
+ $bodyObject['0']['headers']['OC-Checksum'] = 'md5:f2377b4d911f7ec46325fe603c3af03';
+ unset($bodyObject['0']['headers']['X-File-MD5']);
+ $multipartParser = $this->getMultipartParser(
+ $bodyObject
+ );
+
+ $this->expectExceptionMessage('Computed md5 hash is incorrect (4f2377b4d911f7ec46325fe603c3af03).');
+ $multipartParser->parseNextPart();
}
/**
* Test with invalid md5 hash.
*/
public function testInvalidMd5Hash(): void {
- $bodyObject = $this->getValidBodyObject();
- $bodyObject["0"]["headers"]["X-File-MD5"] = "f2377b4d911f7ec46325fe603c3af03";
+ $bodyObject = self::getValidBodyObject();
+ unset($bodyObject['0']['headers']['OC-Checksum']);
+ $bodyObject['0']['headers']['X-File-MD5'] = 'f2377b4d911f7ec46325fe603c3af03';
$multipartParser = $this->getMultipartParser(
$bodyObject
);
- $this->expectExceptionMessage('Computed md5 hash is incorrect.');
+ $this->expectExceptionMessage('Computed md5 hash is incorrect (4f2377b4d911f7ec46325fe603c3af03).');
$multipartParser->parseNextPart();
}
/**
- * Test with a null md5 hash.
+ * Test with a null hash headers.
*/
- public function testNullMd5Hash(): void {
- $bodyObject = $this->getValidBodyObject();
- unset($bodyObject["0"]["headers"]["X-File-MD5"]);
+ public function testNullHash(): void {
+ $bodyObject = self::getValidBodyObject();
+ unset($bodyObject['0']['headers']['OC-Checksum']);
+ unset($bodyObject['0']['headers']['X-File-MD5']);
$multipartParser = $this->getMultipartParser(
$bodyObject
);
- $this->expectExceptionMessage('The X-File-MD5 header must not be null.');
+ $this->expectExceptionMessage('The hash headers must not be null.');
$multipartParser->parseNextPart();
}
@@ -139,8 +188,8 @@ class MultipartRequestParserTest extends TestCase {
* Test with a null Content-Length.
*/
public function testNullContentLength(): void {
- $bodyObject = $this->getValidBodyObject();
- unset($bodyObject["0"]["headers"]["Content-Length"]);
+ $bodyObject = self::getValidBodyObject();
+ unset($bodyObject['0']['headers']['Content-Length']);
$multipartParser = $this->getMultipartParser(
$bodyObject
);
@@ -153,13 +202,13 @@ class MultipartRequestParserTest extends TestCase {
* Test with a lower Content-Length.
*/
public function testLowerContentLength(): void {
- $bodyObject = $this->getValidBodyObject();
- $bodyObject["0"]["headers"]["Content-Length"] = 6;
+ $bodyObject = self::getValidBodyObject();
+ $bodyObject['0']['headers']['Content-Length'] = 6;
$multipartParser = $this->getMultipartParser(
$bodyObject
);
- $this->expectExceptionMessage('Computed md5 hash is incorrect.');
+ $this->expectExceptionMessage('Computed md5 hash is incorrect (41060d3ddfdf63e68fc2bf196f652ee9).');
$multipartParser->parseNextPart();
}
@@ -167,13 +216,13 @@ class MultipartRequestParserTest extends TestCase {
* Test with a higher Content-Length.
*/
public function testHigherContentLength(): void {
- $bodyObject = $this->getValidBodyObject();
- $bodyObject["0"]["headers"]["Content-Length"] = 8;
+ $bodyObject = self::getValidBodyObject();
+ $bodyObject['0']['headers']['Content-Length'] = 8;
$multipartParser = $this->getMultipartParser(
$bodyObject
);
- $this->expectExceptionMessage('Computed md5 hash is incorrect.');
+ $this->expectExceptionMessage('Computed md5 hash is incorrect (0161002bbee6a744f18741b8a914e413).');
$multipartParser->parseNextPart();
}
@@ -181,7 +230,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with wrong boundary in body.
*/
public function testWrongBoundary(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$multipartParser = $this->getMultipartParser(
$bodyObject,
['Content-Type' => 'multipart/related; boundary=boundary_poiuytreza']
@@ -195,7 +244,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with no boundary in request headers.
*/
public function testNoBoundaryInHeader(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$this->expectExceptionMessage('Error while parsing boundary in Content-Type header.');
$this->getMultipartParser(
$bodyObject,
@@ -207,7 +256,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with no boundary in the request's headers.
*/
public function testNoBoundaryInBody(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$multipartParser = $this->getMultipartParser(
$bodyObject,
['Content-Type' => 'multipart/related; boundary=boundary_azertyuiop'],
@@ -222,7 +271,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with a boundary with quotes in the request's headers.
*/
public function testBoundaryWithQuotes(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$multipartParser = $this->getMultipartParser(
$bodyObject,
['Content-Type' => 'multipart/related; boundary="boundary_azertyuiop"'],
@@ -238,7 +287,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with a wrong Content-Type in the request's headers.
*/
public function testWrongContentType(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$this->expectExceptionMessage('Content-Type must be multipart/related');
$this->getMultipartParser(
$bodyObject,
@@ -250,7 +299,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with a wrong key after the content type in the request's headers.
*/
public function testWrongKeyInContentType(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$this->expectExceptionMessage('Boundary is invalid');
$this->getMultipartParser(
$bodyObject,
@@ -262,7 +311,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with a null Content-Type in the request's headers.
*/
public function testNullContentType(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$this->expectExceptionMessage('Content-Type can not be null');
$this->getMultipartParser(
$bodyObject,
diff --git a/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php b/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php
index 9a077e35076..1a7ab7179e1 100644
--- a/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php
+++ b/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php
@@ -1,13 +1,19 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Files\Sharing;
+namespace OCA\DAV\Tests\unit\Files\Sharing;
-use OC\Files\View;
use OCA\DAV\Files\Sharing\FilesDropPlugin;
-use Sabre\DAV\Exception\MethodNotAllowed;
+use OCP\Files\Folder;
+use OCP\Files\NotFoundException;
+use OCP\Share\IAttributes;
+use OCP\Share\IShare;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\DAV\Exception\BadRequest;
use Sabre\DAV\Server;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
@@ -15,51 +21,42 @@ use Test\TestCase;
class FilesDropPluginTest extends TestCase {
- /** @var View|\PHPUnit\Framework\MockObject\MockObject */
- private $view;
-
- /** @var Server|\PHPUnit\Framework\MockObject\MockObject */
- private $server;
-
- /** @var FilesDropPlugin */
- private $plugin;
+ private FilesDropPlugin $plugin;
- /** @var RequestInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
-
- /** @var ResponseInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $response;
+ private Folder&MockObject $node;
+ private IShare&MockObject $share;
+ private Server&MockObject $server;
+ private RequestInterface&MockObject $request;
+ private ResponseInterface&MockObject $response;
protected function setUp(): void {
parent::setUp();
- $this->view = $this->createMock(View::class);
+ $this->node = $this->createMock(Folder::class);
+ $this->node->method('getPath')
+ ->willReturn('/files/token');
+
+ $this->share = $this->createMock(IShare::class);
+ $this->share->expects(self::any())
+ ->method('getNode')
+ ->willReturn($this->node);
$this->server = $this->createMock(Server::class);
$this->plugin = new FilesDropPlugin();
$this->request = $this->createMock(RequestInterface::class);
$this->response = $this->createMock(ResponseInterface::class);
- $this->response->expects($this->never())
- ->method($this->anything());
- }
-
- public function testInitialize(): void {
- $this->server->expects($this->once())
- ->method('on')
- ->with(
- $this->equalTo('beforeMethod:*'),
- $this->equalTo([$this->plugin, 'beforeMethod']),
- $this->equalTo(999)
- );
+ $attributes = $this->createMock(IAttributes::class);
+ $this->share->expects($this->any())
+ ->method('getAttributes')
+ ->willReturn($attributes);
- $this->plugin->initialize($this->server);
+ $this->share
+ ->method('getToken')
+ ->willReturn('token');
}
public function testNotEnabled(): void {
- $this->view->expects($this->never())
- ->method($this->anything());
-
$this->request->expects($this->never())
->method($this->anything());
@@ -68,95 +65,194 @@ class FilesDropPluginTest extends TestCase {
public function testValid(): void {
$this->plugin->enable();
- $this->plugin->setView($this->view);
+ $this->plugin->setShare($this->share);
$this->request->method('getMethod')
->willReturn('PUT');
$this->request->method('getPath')
- ->willReturn('file.txt');
+ ->willReturn('/files/token/file.txt');
$this->request->method('getBaseUrl')
->willReturn('https://example.com');
- $this->view->method('file_exists')
- ->with('/file.txt')
- ->willReturn(false);
+ $this->node->expects(self::once())
+ ->method('getNonExistingName')
+ ->with('file.txt')
+ ->willReturn('file.txt');
$this->request->expects($this->once())
->method('setUrl')
- ->with('https://example.com/file.txt');
+ ->with('https://example.com/files/token/file.txt');
$this->plugin->beforeMethod($this->request, $this->response);
}
public function testFileAlreadyExistsValid(): void {
$this->plugin->enable();
- $this->plugin->setView($this->view);
+ $this->plugin->setShare($this->share);
$this->request->method('getMethod')
->willReturn('PUT');
$this->request->method('getPath')
- ->willReturn('file.txt');
+ ->willReturn('/files/token/file.txt');
$this->request->method('getBaseUrl')
->willReturn('https://example.com');
- $this->view->method('file_exists')
- ->willReturnCallback(function ($path) {
- if ($path === 'file.txt' || $path === '/file.txt') {
- return true;
- } else {
- return false;
- }
- });
+ $this->node->method('getNonExistingName')
+ ->with('file.txt')
+ ->willReturn('file (2).txt');
$this->request->expects($this->once())
->method('setUrl')
- ->with($this->equalTo('https://example.com/file (2).txt'));
+ ->with($this->equalTo('https://example.com/files/token/file (2).txt'));
$this->plugin->beforeMethod($this->request, $this->response);
}
- public function testNoMKCOL(): void {
+ public function testNoMKCOLWithoutNickname(): void {
$this->plugin->enable();
- $this->plugin->setView($this->view);
+ $this->plugin->setShare($this->share);
$this->request->method('getMethod')
->willReturn('MKCOL');
- $this->expectException(MethodNotAllowed::class);
+ $this->expectException(BadRequest::class);
+
+ $this->plugin->beforeMethod($this->request, $this->response);
+ }
+
+ public function testMKCOLWithNickname(): void {
+ $this->plugin->enable();
+ $this->plugin->setShare($this->share);
+
+ $this->request->method('getMethod')
+ ->willReturn('MKCOL');
+
+ $this->request->method('hasHeader')
+ ->with('X-NC-Nickname')
+ ->willReturn(true);
+ $this->request->method('getHeader')
+ ->with('X-NC-Nickname')
+ ->willReturn('nickname');
+
+ $this->expectNotToPerformAssertions();
$this->plugin->beforeMethod($this->request, $this->response);
}
- public function testNoSubdirPut(): void {
+ public function testSubdirPut(): void {
$this->plugin->enable();
- $this->plugin->setView($this->view);
+ $this->plugin->setShare($this->share);
$this->request->method('getMethod')
->willReturn('PUT');
+ $this->request->method('hasHeader')
+ ->with('X-NC-Nickname')
+ ->willReturn(true);
+ $this->request->method('getHeader')
+ ->with('X-NC-Nickname')
+ ->willReturn('nickname');
+
$this->request->method('getPath')
- ->willReturn('folder/file.txt');
+ ->willReturn('/files/token/folder/file.txt');
$this->request->method('getBaseUrl')
->willReturn('https://example.com');
- $this->view->method('file_exists')
- ->willReturnCallback(function ($path) {
- if ($path === 'file.txt' || $path === '/file.txt') {
- return true;
- } else {
- return false;
- }
- });
+ $nodeName = $this->createMock(Folder::class);
+ $nodeFolder = $this->createMock(Folder::class);
+ $nodeFolder->expects(self::once())
+ ->method('getPath')
+ ->willReturn('/files/token/nickname/folder');
+ $nodeFolder->method('getNonExistingName')
+ ->with('file.txt')
+ ->willReturn('file.txt');
+ $nodeName->expects(self::once())
+ ->method('get')
+ ->with('folder')
+ ->willThrowException(new NotFoundException());
+ $nodeName->expects(self::once())
+ ->method('newFolder')
+ ->with('folder')
+ ->willReturn($nodeFolder);
+
+ $this->node->expects(self::once())
+ ->method('get')
+ ->willThrowException(new NotFoundException());
+ $this->node->expects(self::once())
+ ->method('newFolder')
+ ->with('nickname')
+ ->willReturn($nodeName);
$this->request->expects($this->once())
->method('setUrl')
- ->with($this->equalTo('https://example.com/file (2).txt'));
+ ->with($this->equalTo('https://example.com/files/token/nickname/folder/file.txt'));
$this->plugin->beforeMethod($this->request, $this->response);
}
+
+ public function testRecursiveFolderCreation(): void {
+ $this->plugin->enable();
+ $this->plugin->setShare($this->share);
+
+ $this->request->method('getMethod')
+ ->willReturn('PUT');
+ $this->request->method('hasHeader')
+ ->with('X-NC-Nickname')
+ ->willReturn(true);
+ $this->request->method('getHeader')
+ ->with('X-NC-Nickname')
+ ->willReturn('nickname');
+
+ $this->request->method('getPath')
+ ->willReturn('/files/token/folder/subfolder/file.txt');
+ $this->request->method('getBaseUrl')
+ ->willReturn('https://example.com');
+
+ $this->request->expects($this->once())
+ ->method('setUrl')
+ ->with($this->equalTo('https://example.com/files/token/nickname/folder/subfolder/file.txt'));
+
+ $subfolder = $this->createMock(Folder::class);
+ $subfolder->expects(self::once())
+ ->method('getNonExistingName')
+ ->with('file.txt')
+ ->willReturn('file.txt');
+ $subfolder->expects(self::once())
+ ->method('getPath')
+ ->willReturn('/files/token/nickname/folder/subfolder');
+
+ $folder = $this->createMock(Folder::class);
+ $folder->expects(self::once())
+ ->method('get')
+ ->with('subfolder')
+ ->willReturn($subfolder);
+
+ $nickname = $this->createMock(Folder::class);
+ $nickname->expects(self::once())
+ ->method('get')
+ ->with('folder')
+ ->willReturn($folder);
+
+ $this->node->method('get')
+ ->with('nickname')
+ ->willReturn($nickname);
+ $this->plugin->beforeMethod($this->request, $this->response);
+ }
+
+ public function testOnMkcol(): void {
+ $this->plugin->enable();
+ $this->plugin->setShare($this->share);
+
+ $this->response->expects($this->once())
+ ->method('setStatus')
+ ->with(201);
+
+ $response = $this->plugin->onMkcol($this->request, $this->response);
+ $this->assertFalse($response);
+ }
}
diff --git a/apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php b/apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php
index 7b517c93d5d..8519dca7126 100644
--- a/apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php
+++ b/apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php
@@ -6,24 +6,22 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\Listener;
+namespace OCA\DAV\Tests\unit\Listener;
use OCA\DAV\CalDAV\Activity\Backend as ActivityBackend;
use OCA\DAV\CalDAV\Activity\Provider\Event;
use OCA\DAV\DAV\Sharing\Plugin as SharingPlugin;
use OCA\DAV\Events\CalendarDeletedEvent;
-use OCA\DAV\Events\CalendarObjectDeletedEvent;
use OCA\DAV\Listener\ActivityUpdaterListener;
+use OCP\Calendar\Events\CalendarObjectDeletedEvent;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Test\TestCase;
class ActivityUpdaterListenerTest extends TestCase {
- /** @var ActivityBackend|MockObject */
- private $activityBackend;
- /** @var LoggerInterface|MockObject */
- private $logger;
+ private ActivityBackend&MockObject $activityBackend;
+ private LoggerInterface&MockObject $logger;
private ActivityUpdaterListener $listener;
protected function setUp(): void {
@@ -38,9 +36,7 @@ class ActivityUpdaterListenerTest extends TestCase {
);
}
- /**
- * @dataProvider dataForTestHandleCalendarObjectDeletedEvent
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataForTestHandleCalendarObjectDeletedEvent')]
public function testHandleCalendarObjectDeletedEvent(int $calendarId, array $calendarData, array $shares, array $objectData, bool $createsActivity): void {
$event = new CalendarObjectDeletedEvent($calendarId, $calendarData, $shares, $objectData);
$this->logger->expects($this->once())->method('debug')->with(
@@ -55,16 +51,14 @@ class ActivityUpdaterListenerTest extends TestCase {
$this->listener->handle($event);
}
- public function dataForTestHandleCalendarObjectDeletedEvent(): array {
+ public static function dataForTestHandleCalendarObjectDeletedEvent(): array {
return [
[1, [], [], [], true],
[1, [], [], ['{' . SharingPlugin::NS_NEXTCLOUD . '}deleted-at' => 120], false],
];
}
- /**
- * @dataProvider dataForTestHandleCalendarDeletedEvent
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataForTestHandleCalendarDeletedEvent')]
public function testHandleCalendarDeletedEvent(int $calendarId, array $calendarData, array $shares, bool $createsActivity): void {
$event = new CalendarDeletedEvent($calendarId, $calendarData, $shares);
$this->logger->expects($this->once())->method('debug')->with(
@@ -77,7 +71,7 @@ class ActivityUpdaterListenerTest extends TestCase {
$this->listener->handle($event);
}
- public function dataForTestHandleCalendarDeletedEvent(): array {
+ public static function dataForTestHandleCalendarDeletedEvent(): array {
return [
[1, [], [], true],
[1, ['{' . SharingPlugin::NS_NEXTCLOUD . '}deleted-at' => 120], [], false],
diff --git a/apps/dav/tests/unit/Listener/CalendarContactInteractionListenerTest.php b/apps/dav/tests/unit/Listener/CalendarContactInteractionListenerTest.php
index f11438858d7..dc3dce8a62f 100644
--- a/apps/dav/tests/unit/Listener/CalendarContactInteractionListenerTest.php
+++ b/apps/dav/tests/unit/Listener/CalendarContactInteractionListenerTest.php
@@ -6,12 +6,12 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\Listener;
+namespace OCA\DAV\Tests\unit\Listener;
use OCA\DAV\Connector\Sabre\Principal;
-use OCA\DAV\Events\CalendarObjectCreatedEvent;
use OCA\DAV\Events\CalendarShareUpdatedEvent;
use OCA\DAV\Listener\CalendarContactInteractionListener;
+use OCP\Calendar\Events\CalendarObjectCreatedEvent;
use OCP\Contacts\Events\ContactInteractedWithEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventDispatcher;
@@ -23,24 +23,12 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class CalendarContactInteractionListenerTest extends TestCase {
-
- /** @var IEventDispatcher|MockObject */
- private $eventDispatcher;
-
- /** @var IUserSession|MockObject */
- private $userSession;
-
- /** @var Principal|MockObject */
- private $principalConnector;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
-
- /** @var IMailer|MockObject */
- private $mailer;
-
- /** @var CalendarContactInteractionListener */
- private $listener;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private IUserSession&MockObject $userSession;
+ private Principal&MockObject $principalConnector;
+ private LoggerInterface&MockObject $logger;
+ private IMailer&MockObject $mailer;
+ private CalendarContactInteractionListener $listener;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/Listener/OutOfOfficeListenerTest.php b/apps/dav/tests/unit/Listener/OutOfOfficeListenerTest.php
index e1f474678b0..971d113b742 100644
--- a/apps/dav/tests/unit/Listener/OutOfOfficeListenerTest.php
+++ b/apps/dav/tests/unit/Listener/OutOfOfficeListenerTest.php
@@ -7,7 +7,7 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\Listener;
+namespace OCA\DAV\Tests\unit\Listener;
use DateTimeImmutable;
use InvalidArgumentException;
@@ -27,7 +27,6 @@ use OCP\User\Events\OutOfOfficeChangedEvent;
use OCP\User\Events\OutOfOfficeClearedEvent;
use OCP\User\Events\OutOfOfficeScheduledEvent;
use OCP\User\IOutOfOfficeData;
-use OCP\UserStatus\IManager;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\NotFound;
@@ -42,11 +41,10 @@ use Test\TestCase;
*/
class OutOfOfficeListenerTest extends TestCase {
- private ServerFactory|MockObject $serverFactory;
- private IConfig|MockObject $appConfig;
- private LoggerInterface|MockObject $loggerInterface;
- private MockObject|TimezoneService $timezoneService;
- private IManager|MockObject $manager;
+ private ServerFactory&MockObject $serverFactory;
+ private IConfig&MockObject $appConfig;
+ private LoggerInterface&MockObject $loggerInterface;
+ private TimezoneService&MockObject $timezoneService;
private OutOfOfficeListener $listener;
protected function setUp(): void {
@@ -56,14 +54,12 @@ class OutOfOfficeListenerTest extends TestCase {
$this->appConfig = $this->createMock(IConfig::class);
$this->timezoneService = $this->createMock(TimezoneService::class);
$this->loggerInterface = $this->createMock(LoggerInterface::class);
- $this->manager = $this->createMock(IManager::class);
$this->listener = new OutOfOfficeListener(
$this->serverFactory,
$this->appConfig,
$this->timezoneService,
$this->loggerInterface,
- $this->manager
);
}
@@ -202,7 +198,7 @@ class OutOfOfficeListenerTest extends TestCase {
->willReturn($calendar);
$calendar->expects(self::once())
->method('createFile')
- ->willReturnCallback(function ($name, $data) {
+ ->willReturnCallback(function ($name, $data): void {
$vcalendar = Reader::read($data);
if (!($vcalendar instanceof VCalendar)) {
throw new InvalidArgumentException('Calendar data should be a VCALENDAR');
@@ -352,7 +348,7 @@ class OutOfOfficeListenerTest extends TestCase {
->willThrowException(new NotFound());
$calendar->expects(self::once())
->method('createFile')
- ->willReturnCallback(function ($name, $data) {
+ ->willReturnCallback(function ($name, $data): void {
$vcalendar = Reader::read($data);
if (!($vcalendar instanceof VCalendar)) {
throw new InvalidArgumentException('Calendar data should be a VCALENDAR');
@@ -419,7 +415,7 @@ class OutOfOfficeListenerTest extends TestCase {
->willReturn($eventNode);
$eventNode->expects(self::once())
->method('put')
- ->willReturnCallback(function ($data) {
+ ->willReturnCallback(function ($data): void {
$vcalendar = Reader::read($data);
if (!($vcalendar instanceof VCalendar)) {
throw new InvalidArgumentException('Calendar data should be a VCALENDAR');
@@ -453,8 +449,6 @@ class OutOfOfficeListenerTest extends TestCase {
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
- $this->manager->expects(self::never())
- ->method('revertUserStatus');
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
@@ -483,8 +477,6 @@ class OutOfOfficeListenerTest extends TestCase {
->method('getNodeForPath')
->with('/home/calendar')
->willThrowException(new NotFound('nope'));
- $this->manager->expects(self::never())
- ->method('revertUserStatus');
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
@@ -522,8 +514,6 @@ class OutOfOfficeListenerTest extends TestCase {
->method('getChild')
->with('personal-1')
->willThrowException(new NotFound('nope'));
- $this->manager->expects(self::never())
- ->method('revertUserStatus');
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
@@ -565,8 +555,6 @@ class OutOfOfficeListenerTest extends TestCase {
$calendar->expects(self::once())
->method('getChild')
->willThrowException(new NotFound());
- $this->manager->expects(self::never())
- ->method('revertUserStatus');
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
diff --git a/apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php b/apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php
index 1cebf199d29..1852d2709c1 100644
--- a/apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php
+++ b/apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php
@@ -1,13 +1,18 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\DAV\Migration;
+namespace OCA\DAV\Tests\unit\DAV\Migration;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Migration\CalDAVRemoveEmptyValue;
+use OCP\IDBConnection;
use OCP\Migration\IOutput;
+use OCP\Server;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\VObject\InvalidDataException;
use Test\TestCase;
@@ -19,18 +24,10 @@ use Test\TestCase;
* @group DB
*/
class CalDAVRemoveEmptyValueTest extends TestCase {
-
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $logger;
-
- /** @var CalDavBackend|\PHPUnit\Framework\MockObject\MockObject */
- private $backend;
-
- /** @var IOutput|\PHPUnit\Framework\MockObject\MockObject */
- private $output;
-
- /** @var string */
- private $invalid = 'BEGIN:VCALENDAR
+ private LoggerInterface&MockObject $logger;
+ private CalDavBackend&MockObject $backend;
+ private IOutput&MockObject $output;
+ private string $invalid = 'BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Apple Inc.//Mac OS X 10.11.2//EN
CALSCALE:GREGORIAN
@@ -50,8 +47,7 @@ CREATED;VALUE=:20151214T091032Z
END:VEVENT
END:VCALENDAR';
- /** @var string */
- private $valid = 'BEGIN:VCALENDAR
+ private string $valid = 'BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Apple Inc.//Mac OS X 10.11.2//EN
CALSCALE:GREGORIAN
@@ -80,14 +76,14 @@ END:VCALENDAR';
}
public function testRunAllValid(): void {
- /** @var CalDAVRemoveEmptyValue|\PHPUnit\Framework\MockObject\MockObject $step */
+ /** @var CalDAVRemoveEmptyValue&MockObject $step */
$step = $this->getMockBuilder(CalDAVRemoveEmptyValue::class)
->setConstructorArgs([
- \OC::$server->getDatabaseConnection(),
+ Server::get(IDBConnection::class),
$this->backend,
$this->logger
])
- ->setMethods(['getInvalidObjects'])
+ ->onlyMethods(['getInvalidObjects'])
->getMock();
$step->expects($this->once())
@@ -104,14 +100,14 @@ END:VCALENDAR';
}
public function testRunInvalid(): void {
- /** @var CalDAVRemoveEmptyValue|\PHPUnit\Framework\MockObject\MockObject $step */
+ /** @var CalDAVRemoveEmptyValue&MockObject $step */
$step = $this->getMockBuilder(CalDAVRemoveEmptyValue::class)
->setConstructorArgs([
- \OC::$server->getDatabaseConnection(),
+ Server::get(IDBConnection::class),
$this->backend,
$this->logger
])
- ->setMethods(['getInvalidObjects'])
+ ->onlyMethods(['getInvalidObjects'])
->getMock();
$step->expects($this->once())
@@ -147,14 +143,14 @@ END:VCALENDAR';
}
public function testRunValid(): void {
- /** @var CalDAVRemoveEmptyValue|\PHPUnit\Framework\MockObject\MockObject $step */
+ /** @var CalDAVRemoveEmptyValue&MockObject $step */
$step = $this->getMockBuilder(CalDAVRemoveEmptyValue::class)
->setConstructorArgs([
- \OC::$server->getDatabaseConnection(),
+ Server::get(IDBConnection::class),
$this->backend,
$this->logger
])
- ->setMethods(['getInvalidObjects'])
+ ->onlyMethods(['getInvalidObjects'])
->getMock();
$step->expects($this->once())
@@ -189,14 +185,14 @@ END:VCALENDAR';
}
public function testRunStillInvalid(): void {
- /** @var CalDAVRemoveEmptyValue|\PHPUnit\Framework\MockObject\MockObject $step */
+ /** @var CalDAVRemoveEmptyValue&MockObject $step */
$step = $this->getMockBuilder(CalDAVRemoveEmptyValue::class)
->setConstructorArgs([
- \OC::$server->getDatabaseConnection(),
+ Server::get(IDBConnection::class),
$this->backend,
$this->logger
])
- ->setMethods(['getInvalidObjects'])
+ ->onlyMethods(['getInvalidObjects'])
->getMock();
$step->expects($this->once())
diff --git a/apps/dav/tests/unit/Migration/CreateSystemAddressBookStepTest.php b/apps/dav/tests/unit/Migration/CreateSystemAddressBookStepTest.php
new file mode 100644
index 00000000000..667d2e39d3a
--- /dev/null
+++ b/apps/dav/tests/unit/Migration/CreateSystemAddressBookStepTest.php
@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\Migration;
+
+use OCA\DAV\CardDAV\SyncService;
+use OCA\DAV\Migration\CreateSystemAddressBookStep;
+use OCP\Migration\IOutput;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+
+class CreateSystemAddressBookStepTest extends TestCase {
+
+ private SyncService&MockObject $syncService;
+ private CreateSystemAddressBookStep $step;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->syncService = $this->createMock(SyncService::class);
+
+ $this->step = new CreateSystemAddressBookStep(
+ $this->syncService,
+ );
+ }
+
+ public function testGetName(): void {
+ $name = $this->step->getName();
+
+ self::assertEquals('Create system address book', $name);
+ }
+
+ public function testRun(): void {
+ $output = $this->createMock(IOutput::class);
+
+ $this->step->run($output);
+
+ $this->addToAssertionCount(1);
+ }
+
+}
diff --git a/apps/dav/tests/unit/Migration/RefreshWebcalJobRegistrarTest.php b/apps/dav/tests/unit/Migration/RefreshWebcalJobRegistrarTest.php
index bf4c60b3cf1..8e7bf366cbf 100644
--- a/apps/dav/tests/unit/Migration/RefreshWebcalJobRegistrarTest.php
+++ b/apps/dav/tests/unit/Migration/RefreshWebcalJobRegistrarTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -12,17 +14,13 @@ use OCP\DB\IResult;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class RefreshWebcalJobRegistrarTest extends TestCase {
- /** @var IDBConnection | \PHPUnit\Framework\MockObject\MockObject */
- private $db;
-
- /** @var IJobList | \PHPUnit\Framework\MockObject\MockObject */
- private $jobList;
-
- /** @var RefreshWebcalJobRegistrar */
- private $migration;
+ private IDBConnection&MockObject $db;
+ private IJobList&MockObject $jobList;
+ private RefreshWebcalJobRegistrar $migration;
protected function setUp(): void {
parent::setUp();
@@ -80,35 +78,37 @@ class RefreshWebcalJobRegistrarTest extends TestCase {
$this->jobList->expects($this->exactly(3))
->method('has')
- ->withConsecutive(
+ ->willReturnMap([
[RefreshWebcalJob::class, [
'principaluri' => 'foo1',
'uri' => 'bar1',
- ]],
+ ], false],
[RefreshWebcalJob::class, [
'principaluri' => 'foo2',
'uri' => 'bar2',
- ]],
+ ], true ],
[RefreshWebcalJob::class, [
'principaluri' => 'foo3',
'uri' => 'bar3',
- ]])
- ->willReturnOnConsecutiveCalls(
- false,
- true,
- false,
- );
+ ], false],
+ ]);
+
+ $calls = [
+ [RefreshWebcalJob::class, [
+ 'principaluri' => 'foo1',
+ 'uri' => 'bar1',
+ ]],
+ [RefreshWebcalJob::class, [
+ 'principaluri' => 'foo3',
+ 'uri' => 'bar3',
+ ]]
+ ];
$this->jobList->expects($this->exactly(2))
->method('add')
- ->withConsecutive(
- [RefreshWebcalJob::class, [
- 'principaluri' => 'foo1',
- 'uri' => 'bar1',
- ]],
- [RefreshWebcalJob::class, [
- 'principaluri' => 'foo3',
- 'uri' => 'bar3',
- ]]);
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$output->expects($this->once())
->method('info')
diff --git a/apps/dav/tests/unit/Migration/RegenerateBirthdayCalendarsTest.php b/apps/dav/tests/unit/Migration/RegenerateBirthdayCalendarsTest.php
index e2ac45526d2..6f681badb8b 100644
--- a/apps/dav/tests/unit/Migration/RegenerateBirthdayCalendarsTest.php
+++ b/apps/dav/tests/unit/Migration/RegenerateBirthdayCalendarsTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -10,18 +12,13 @@ use OCA\DAV\Migration\RegenerateBirthdayCalendars;
use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
use OCP\Migration\IOutput;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class RegenerateBirthdayCalendarsTest extends TestCase {
-
- /** @var IJobList | \PHPUnit\Framework\MockObject\MockObject */
- private $jobList;
-
- /** @var IConfig | \PHPUnit\Framework\MockObject\MockObject */
- private $config;
-
- /** @var RegenerateBirthdayCalendars */
- private $migration;
+ private IJobList&MockObject $jobList;
+ private IConfig&MockObject $config;
+ private RegenerateBirthdayCalendars $migration;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/Migration/RemoveDeletedUsersCalendarSubscriptionsTest.php b/apps/dav/tests/unit/Migration/RemoveDeletedUsersCalendarSubscriptionsTest.php
index a3daf1c918a..a9758470573 100644
--- a/apps/dav/tests/unit/Migration/RemoveDeletedUsersCalendarSubscriptionsTest.php
+++ b/apps/dav/tests/unit/Migration/RemoveDeletedUsersCalendarSubscriptionsTest.php
@@ -22,23 +22,10 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class RemoveDeletedUsersCalendarSubscriptionsTest extends TestCase {
- /**
- * @var IDBConnection|MockObject
- */
- private $dbConnection;
- /**
- * @var IUserManager|MockObject
- */
- private $userManager;
-
- /**
- * @var IOutput|MockObject
- */
- private $output;
- /**
- * @var RemoveDeletedUsersCalendarSubscriptions
- */
- private $migration;
+ private IDBConnection&MockObject $dbConnection;
+ private IUserManager&MockObject $userManager;
+ private IOutput&MockObject $output;
+ private RemoveDeletedUsersCalendarSubscriptions $migration;
protected function setUp(): void {
@@ -58,13 +45,7 @@ class RemoveDeletedUsersCalendarSubscriptionsTest extends TestCase {
);
}
- /**
- * @dataProvider dataTestRun
- * @param array $subscriptions
- * @param array $userExists
- * @param int $deletions
- * @throws \Exception
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataTestRun')]
public function testRun(array $subscriptions, array $userExists, int $deletions): void {
$qb = $this->createMock(IQueryBuilder::class);
@@ -132,21 +113,28 @@ class RemoveDeletedUsersCalendarSubscriptionsTest extends TestCase {
$this->migration->run($this->output);
}
- public function dataTestRun(): array {
+ public static function dataTestRun(): array {
return [
[[], [], 0],
- [[[
- 'id' => 1,
- 'principaluri' => 'users/principals/foo1',
- ],
+ [
[
- 'id' => 2,
- 'principaluri' => 'users/principals/bar1',
+ [
+ 'id' => 1,
+ 'principaluri' => 'users/principals/foo1',
+ ],
+ [
+ 'id' => 2,
+ 'principaluri' => 'users/principals/bar1',
+ ],
+ [
+ 'id' => 3,
+ 'principaluri' => 'users/principals/bar1',
+ ],
+ [],
],
- [
- 'id' => 3,
- 'principaluri' => 'users/principals/bar1',
- ]], ['foo1' => true, 'bar1' => false], 2]
+ ['foo1' => true, 'bar1' => false],
+ 2
+ ],
];
}
}
diff --git a/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningNodeTest.php b/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningNodeTest.php
index 0979aff8a81..4f04aebb3e8 100644
--- a/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningNodeTest.php
+++ b/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningNodeTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,15 +9,13 @@ namespace OCA\DAV\Tests\unit\Provisioning\Apple;
use OCA\DAV\Provisioning\Apple\AppleProvisioningNode;
use OCP\AppFramework\Utility\ITimeFactory;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\PropPatch;
use Test\TestCase;
class AppleProvisioningNodeTest extends TestCase {
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
-
- /** @var AppleProvisioningNode */
- private $node;
+ private ITimeFactory&MockObject $timeFactory;
+ private AppleProvisioningNode $node;
protected function setUp(): void {
parent::setUp();
@@ -28,7 +28,6 @@ class AppleProvisioningNodeTest extends TestCase {
$this->assertEquals('apple-provisioning.mobileconfig', $this->node->getName());
}
-
public function testSetName(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->expectExceptionMessage('Renaming apple-provisioning.mobileconfig is forbidden');
@@ -55,7 +54,7 @@ class AppleProvisioningNodeTest extends TestCase {
$this->assertEquals([
'{DAV:}getcontentlength' => 42,
- '{DAV:}getlastmodified' => 'Sat, 01 Jan 2000 00:00:00 +0000',
+ '{DAV:}getlastmodified' => 'Sat, 01 Jan 2000 00:00:00 GMT',
], $this->node->getProperties([]));
}
diff --git a/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningPluginTest.php b/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningPluginTest.php
index dbb399ea7a6..58e588aa68d 100644
--- a/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningPluginTest.php
+++ b/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningPluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -12,40 +14,27 @@ use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\DAV\Server;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
use Test\TestCase;
class AppleProvisioningPluginTest extends TestCase {
- /** @var \Sabre\DAV\Server|\PHPUnit\Framework\MockObject\MockObject */
- protected $server;
-
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- protected $userSession;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- protected $urlGenerator;
-
- /** @var ThemingDefaults|\PHPUnit\Framework\MockObject\MockObject */
- protected $themingDefaults;
-
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- protected $request;
-
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
- protected $l10n;
-
- /** @var \Sabre\HTTP\RequestInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $sabreRequest;
-
- /** @var \Sabre\HTTP\ResponseInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $sabreResponse;
-
- /** @var AppleProvisioningPlugin */
- protected $plugin;
+ protected Server&MockObject $server;
+ protected IUserSession&MockObject $userSession;
+ protected IURLGenerator&MockObject $urlGenerator;
+ protected ThemingDefaults&MockObject $themingDefaults;
+ protected IRequest&MockObject $request;
+ protected IL10N&MockObject $l10n;
+ protected RequestInterface&MockObject $sabreRequest;
+ protected ResponseInterface&MockObject $sabreResponse;
+ protected AppleProvisioningPlugin $plugin;
protected function setUp(): void {
parent::setUp();
- $this->server = $this->createMock(\Sabre\DAV\Server::class);
+ $this->server = $this->createMock(Server::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->themingDefaults = $this->createMock(ThemingDefaults::class);
@@ -62,12 +51,12 @@ class AppleProvisioningPluginTest extends TestCase {
}
);
- $this->sabreRequest = $this->createMock(\Sabre\HTTP\RequestInterface::class);
- $this->sabreResponse = $this->createMock(\Sabre\HTTP\ResponseInterface::class);
+ $this->sabreRequest = $this->createMock(RequestInterface::class);
+ $this->sabreResponse = $this->createMock(ResponseInterface::class);
}
public function testInitialize(): void {
- $server = $this->createMock(\Sabre\DAV\Server::class);
+ $server = $this->createMock(Server::class);
$plugin = new AppleProvisioningPlugin($this->userSession,
$this->urlGenerator, $this->themingDefaults, $this->request, $this->l10n,
@@ -149,24 +138,25 @@ class AppleProvisioningPluginTest extends TestCase {
$this->l10n->expects($this->exactly(2))
->method('t')
- ->withConsecutive(
- ['Configures a CalDAV account'],
- ['Configures a CardDAV account'],
- )
- ->willReturnOnConsecutiveCalls(
- 'LocalizedConfiguresCalDAV',
- 'LocalizedConfiguresCardDAV',
- );
+ ->willReturnMap([
+ ['Configures a CalDAV account', [], 'LocalizedConfiguresCalDAV'],
+ ['Configures a CardDAV account', [], 'LocalizedConfiguresCardDAV'],
+ ]);
$this->sabreResponse->expects($this->once())
->method('setStatus')
->with(200);
+
+ $calls = [
+ ['Content-Disposition', 'attachment; filename="userName-apple-provisioning.mobileconfig"'],
+ ['Content-Type', 'application/xml; charset=utf-8'],
+ ];
$this->sabreResponse->expects($this->exactly(2))
->method('setHeader')
- ->withConsecutive(
- ['Content-Disposition', 'attachment; filename="userName-apple-provisioning.mobileconfig"'],
- ['Content-Type', 'application/xml; charset=utf-8'],
- );
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$this->sabreResponse->expects($this->once())
->method('setBody')
->with(<<<EOF
diff --git a/apps/dav/tests/unit/Search/ContactsSearchProviderTest.php b/apps/dav/tests/unit/Search/ContactsSearchProviderTest.php
index bfc57dc61d7..f4dc13a5c06 100644
--- a/apps/dav/tests/unit/Search/ContactsSearchProviderTest.php
+++ b/apps/dav/tests/unit/Search/ContactsSearchProviderTest.php
@@ -17,43 +17,34 @@ use OCP\IUser;
use OCP\Search\ISearchQuery;
use OCP\Search\SearchResult;
use OCP\Search\SearchResultEntry;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Reader;
use Test\TestCase;
class ContactsSearchProviderTest extends TestCase {
-
- /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */
- private $appManager;
-
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
- private $l10n;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
-
- /** @var CardDavBackend|\PHPUnit\Framework\MockObject\MockObject */
- private $backend;
-
- /** @var ContactsSearchProvider */
- private $provider;
-
- private $vcardTest0 = 'BEGIN:VCARD'.PHP_EOL.
- 'VERSION:3.0'.PHP_EOL.
- 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN'.PHP_EOL.
- 'UID:Test'.PHP_EOL.
- 'FN:FN of Test'.PHP_EOL.
- 'N:Test;;;;'.PHP_EOL.
- 'EMAIL:forrestgump@example.com'.PHP_EOL.
- 'END:VCARD';
-
- private $vcardTest1 = 'BEGIN:VCARD'.PHP_EOL.
- 'VERSION:3.0'.PHP_EOL.
- 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN'.PHP_EOL.
- 'PHOTO;ENCODING=b;TYPE=image/jpeg:'.PHP_EOL.
- 'UID:Test2'.PHP_EOL.
- 'FN:FN of Test2'.PHP_EOL.
- 'N:Test2;;;;'.PHP_EOL.
- 'END:VCARD';
+ private IAppManager&MockObject $appManager;
+ private IL10N&MockObject $l10n;
+ private IURLGenerator&MockObject $urlGenerator;
+ private CardDavBackend&MockObject $backend;
+ private ContactsSearchProvider $provider;
+
+ private string $vcardTest0 = 'BEGIN:VCARD' . PHP_EOL
+ . 'VERSION:3.0' . PHP_EOL
+ . 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL
+ . 'UID:Test' . PHP_EOL
+ . 'FN:FN of Test' . PHP_EOL
+ . 'N:Test;;;;' . PHP_EOL
+ . 'EMAIL:forrestgump@example.com' . PHP_EOL
+ . 'END:VCARD';
+
+ private string $vcardTest1 = 'BEGIN:VCARD' . PHP_EOL
+ . 'VERSION:3.0' . PHP_EOL
+ . 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL
+ . 'PHOTO;ENCODING=b;TYPE=image/jpeg:' . PHP_EOL
+ . 'UID:Test2' . PHP_EOL
+ . 'FN:FN of Test2' . PHP_EOL
+ . 'N:Test2;;;;' . PHP_EOL
+ . 'END:VCARD';
protected function setUp(): void {
parent::setUp();
@@ -174,7 +165,7 @@ class ContactsSearchProviderTest extends TestCase {
$this->urlGenerator,
$this->backend,
])
- ->setMethods([
+ ->onlyMethods([
'getDavUrlForContact',
'getDeepLinkToContactsApp',
'generateSubline',
@@ -191,11 +182,10 @@ class ContactsSearchProviderTest extends TestCase {
->willReturn('subline');
$provider->expects($this->exactly(2))
->method('getDeepLinkToContactsApp')
- ->withConsecutive(
- ['addressbook-uri-99', 'Test'],
- ['addressbook-uri-123', 'Test2']
- )
- ->willReturn('deep-link-to-contacts');
+ ->willReturnMap([
+ ['addressbook-uri-99', 'Test', 'deep-link-to-contacts'],
+ ['addressbook-uri-123', 'Test2', 'deep-link-to-contacts'],
+ ]);
$actual = $provider->search($user, $query);
$data = $actual->jsonSerialize();
diff --git a/apps/dav/tests/unit/Search/EventsSearchProviderTest.php b/apps/dav/tests/unit/Search/EventsSearchProviderTest.php
index d194b7fa7c6..d5d536fd201 100644
--- a/apps/dav/tests/unit/Search/EventsSearchProviderTest.php
+++ b/apps/dav/tests/unit/Search/EventsSearchProviderTest.php
@@ -18,204 +18,196 @@ use OCP\Search\IFilter;
use OCP\Search\ISearchQuery;
use OCP\Search\SearchResult;
use OCP\Search\SearchResultEntry;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Reader;
use Test\TestCase;
class EventsSearchProviderTest extends TestCase {
- /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */
- private $appManager;
-
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
- private $l10n;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
-
- /** @var CalDavBackend|\PHPUnit\Framework\MockObject\MockObject */
- private $backend;
-
- /** @var EventsSearchProvider */
- private $provider;
+ private IAppManager&MockObject $appManager;
+ private IL10N&MockObject $l10n;
+ private IURLGenerator&MockObject $urlGenerator;
+ private CalDavBackend&MockObject $backend;
+ private EventsSearchProvider $provider;
// NO SUMMARY
- private $vEvent0 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN'.PHP_EOL.
- 'CALSCALE:GREGORIAN'.PHP_EOL.
- 'BEGIN:VEVENT'.PHP_EOL.
- 'CREATED:20161004T144433Z'.PHP_EOL.
- 'UID:85560E76-1B0D-47E1-A735-21625767FCA4'.PHP_EOL.
- 'DTEND;VALUE=DATE:20161008'.PHP_EOL.
- 'TRANSP:TRANSPARENT'.PHP_EOL.
- 'DTSTART;VALUE=DATE:20161005'.PHP_EOL.
- 'DTSTAMP:20161004T144437Z'.PHP_EOL.
- 'SEQUENCE:0'.PHP_EOL.
- 'END:VEVENT'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vEvent0 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20161004T144433Z' . PHP_EOL
+ . 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL
+ . 'DTEND;VALUE=DATE:20161008' . PHP_EOL
+ . 'TRANSP:TRANSPARENT' . PHP_EOL
+ . 'DTSTART;VALUE=DATE:20161005' . PHP_EOL
+ . 'DTSTAMP:20161004T144437Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// TIMED SAME DAY
- private $vEvent1 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'PRODID:-//Tests//'.PHP_EOL.
- 'CALSCALE:GREGORIAN'.PHP_EOL.
- 'BEGIN:VTIMEZONE'.PHP_EOL.
- 'TZID:Europe/Berlin'.PHP_EOL.
- 'BEGIN:DAYLIGHT'.PHP_EOL.
- 'TZOFFSETFROM:+0100'.PHP_EOL.
- 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU'.PHP_EOL.
- 'DTSTART:19810329T020000'.PHP_EOL.
- 'TZNAME:GMT+2'.PHP_EOL.
- 'TZOFFSETTO:+0200'.PHP_EOL.
- 'END:DAYLIGHT'.PHP_EOL.
- 'BEGIN:STANDARD'.PHP_EOL.
- 'TZOFFSETFROM:+0200'.PHP_EOL.
- 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU'.PHP_EOL.
- 'DTSTART:19961027T030000'.PHP_EOL.
- 'TZNAME:GMT+1'.PHP_EOL.
- 'TZOFFSETTO:+0100'.PHP_EOL.
- 'END:STANDARD'.PHP_EOL.
- 'END:VTIMEZONE'.PHP_EOL.
- 'BEGIN:VEVENT'.PHP_EOL.
- 'CREATED:20160809T163629Z'.PHP_EOL.
- 'UID:0AD16F58-01B3-463B-A215-FD09FC729A02'.PHP_EOL.
- 'DTEND;TZID=Europe/Berlin:20160816T100000'.PHP_EOL.
- 'TRANSP:OPAQUE'.PHP_EOL.
- 'SUMMARY:Test Europe Berlin'.PHP_EOL.
- 'DTSTART;TZID=Europe/Berlin:20160816T090000'.PHP_EOL.
- 'DTSTAMP:20160809T163632Z'.PHP_EOL.
- 'SEQUENCE:0'.PHP_EOL.
- 'END:VEVENT'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vEvent1 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Tests//' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VTIMEZONE' . PHP_EOL
+ . 'TZID:Europe/Berlin' . PHP_EOL
+ . 'BEGIN:DAYLIGHT' . PHP_EOL
+ . 'TZOFFSETFROM:+0100' . PHP_EOL
+ . 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' . PHP_EOL
+ . 'DTSTART:19810329T020000' . PHP_EOL
+ . 'TZNAME:GMT+2' . PHP_EOL
+ . 'TZOFFSETTO:+0200' . PHP_EOL
+ . 'END:DAYLIGHT' . PHP_EOL
+ . 'BEGIN:STANDARD' . PHP_EOL
+ . 'TZOFFSETFROM:+0200' . PHP_EOL
+ . 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' . PHP_EOL
+ . 'DTSTART:19961027T030000' . PHP_EOL
+ . 'TZNAME:GMT+1' . PHP_EOL
+ . 'TZOFFSETTO:+0100' . PHP_EOL
+ . 'END:STANDARD' . PHP_EOL
+ . 'END:VTIMEZONE' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20160809T163629Z' . PHP_EOL
+ . 'UID:0AD16F58-01B3-463B-A215-FD09FC729A02' . PHP_EOL
+ . 'DTEND;TZID=Europe/Berlin:20160816T100000' . PHP_EOL
+ . 'TRANSP:OPAQUE' . PHP_EOL
+ . 'SUMMARY:Test Europe Berlin' . PHP_EOL
+ . 'DTSTART;TZID=Europe/Berlin:20160816T090000' . PHP_EOL
+ . 'DTSTAMP:20160809T163632Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// TIMED DIFFERENT DAY
- private $vEvent2 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'PRODID:-//Tests//'.PHP_EOL.
- 'CALSCALE:GREGORIAN'.PHP_EOL.
- 'BEGIN:VTIMEZONE'.PHP_EOL.
- 'TZID:Europe/Berlin'.PHP_EOL.
- 'BEGIN:DAYLIGHT'.PHP_EOL.
- 'TZOFFSETFROM:+0100'.PHP_EOL.
- 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU'.PHP_EOL.
- 'DTSTART:19810329T020000'.PHP_EOL.
- 'TZNAME:GMT+2'.PHP_EOL.
- 'TZOFFSETTO:+0200'.PHP_EOL.
- 'END:DAYLIGHT'.PHP_EOL.
- 'BEGIN:STANDARD'.PHP_EOL.
- 'TZOFFSETFROM:+0200'.PHP_EOL.
- 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU'.PHP_EOL.
- 'DTSTART:19961027T030000'.PHP_EOL.
- 'TZNAME:GMT+1'.PHP_EOL.
- 'TZOFFSETTO:+0100'.PHP_EOL.
- 'END:STANDARD'.PHP_EOL.
- 'END:VTIMEZONE'.PHP_EOL.
- 'BEGIN:VEVENT'.PHP_EOL.
- 'CREATED:20160809T163629Z'.PHP_EOL.
- 'UID:0AD16F58-01B3-463B-A215-FD09FC729A02'.PHP_EOL.
- 'DTEND;TZID=Europe/Berlin:20160817T100000'.PHP_EOL.
- 'TRANSP:OPAQUE'.PHP_EOL.
- 'SUMMARY:Test Europe Berlin'.PHP_EOL.
- 'DTSTART;TZID=Europe/Berlin:20160816T090000'.PHP_EOL.
- 'DTSTAMP:20160809T163632Z'.PHP_EOL.
- 'SEQUENCE:0'.PHP_EOL.
- 'END:VEVENT'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vEvent2 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Tests//' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VTIMEZONE' . PHP_EOL
+ . 'TZID:Europe/Berlin' . PHP_EOL
+ . 'BEGIN:DAYLIGHT' . PHP_EOL
+ . 'TZOFFSETFROM:+0100' . PHP_EOL
+ . 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' . PHP_EOL
+ . 'DTSTART:19810329T020000' . PHP_EOL
+ . 'TZNAME:GMT+2' . PHP_EOL
+ . 'TZOFFSETTO:+0200' . PHP_EOL
+ . 'END:DAYLIGHT' . PHP_EOL
+ . 'BEGIN:STANDARD' . PHP_EOL
+ . 'TZOFFSETFROM:+0200' . PHP_EOL
+ . 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' . PHP_EOL
+ . 'DTSTART:19961027T030000' . PHP_EOL
+ . 'TZNAME:GMT+1' . PHP_EOL
+ . 'TZOFFSETTO:+0100' . PHP_EOL
+ . 'END:STANDARD' . PHP_EOL
+ . 'END:VTIMEZONE' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20160809T163629Z' . PHP_EOL
+ . 'UID:0AD16F58-01B3-463B-A215-FD09FC729A02' . PHP_EOL
+ . 'DTEND;TZID=Europe/Berlin:20160817T100000' . PHP_EOL
+ . 'TRANSP:OPAQUE' . PHP_EOL
+ . 'SUMMARY:Test Europe Berlin' . PHP_EOL
+ . 'DTSTART;TZID=Europe/Berlin:20160816T090000' . PHP_EOL
+ . 'DTSTAMP:20160809T163632Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// ALL-DAY ONE-DAY
- private $vEvent3 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN'.PHP_EOL.
- 'CALSCALE:GREGORIAN'.PHP_EOL.
- 'BEGIN:VEVENT'.PHP_EOL.
- 'CREATED:20161004T144433Z'.PHP_EOL.
- 'UID:85560E76-1B0D-47E1-A735-21625767FCA4'.PHP_EOL.
- 'DTEND;VALUE=DATE:20161006'.PHP_EOL.
- 'TRANSP:TRANSPARENT'.PHP_EOL.
- 'DTSTART;VALUE=DATE:20161005'.PHP_EOL.
- 'DTSTAMP:20161004T144437Z'.PHP_EOL.
- 'SEQUENCE:0'.PHP_EOL.
- 'END:VEVENT'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vEvent3 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20161004T144433Z' . PHP_EOL
+ . 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL
+ . 'DTEND;VALUE=DATE:20161006' . PHP_EOL
+ . 'TRANSP:TRANSPARENT' . PHP_EOL
+ . 'DTSTART;VALUE=DATE:20161005' . PHP_EOL
+ . 'DTSTAMP:20161004T144437Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// ALL-DAY MULTIPLE DAYS
- private $vEvent4 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN'.PHP_EOL.
- 'CALSCALE:GREGORIAN'.PHP_EOL.
- 'BEGIN:VEVENT'.PHP_EOL.
- 'CREATED:20161004T144433Z'.PHP_EOL.
- 'UID:85560E76-1B0D-47E1-A735-21625767FCA4'.PHP_EOL.
- 'DTEND;VALUE=DATE:20161008'.PHP_EOL.
- 'TRANSP:TRANSPARENT'.PHP_EOL.
- 'DTSTART;VALUE=DATE:20161005'.PHP_EOL.
- 'DTSTAMP:20161004T144437Z'.PHP_EOL.
- 'SEQUENCE:0'.PHP_EOL.
- 'END:VEVENT'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vEvent4 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20161004T144433Z' . PHP_EOL
+ . 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL
+ . 'DTEND;VALUE=DATE:20161008' . PHP_EOL
+ . 'TRANSP:TRANSPARENT' . PHP_EOL
+ . 'DTSTART;VALUE=DATE:20161005' . PHP_EOL
+ . 'DTSTAMP:20161004T144437Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// DURATION
- private $vEvent5 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN'.PHP_EOL.
- 'CALSCALE:GREGORIAN'.PHP_EOL.
- 'BEGIN:VEVENT'.PHP_EOL.
- 'CREATED:20161004T144433Z'.PHP_EOL.
- 'UID:85560E76-1B0D-47E1-A735-21625767FCA4'.PHP_EOL.
- 'DURATION:P5D'.PHP_EOL.
- 'TRANSP:TRANSPARENT'.PHP_EOL.
- 'DTSTART;VALUE=DATE:20161005'.PHP_EOL.
- 'DTSTAMP:20161004T144437Z'.PHP_EOL.
- 'SEQUENCE:0'.PHP_EOL.
- 'END:VEVENT'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vEvent5 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20161004T144433Z' . PHP_EOL
+ . 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL
+ . 'DURATION:P5D' . PHP_EOL
+ . 'TRANSP:TRANSPARENT' . PHP_EOL
+ . 'DTSTART;VALUE=DATE:20161005' . PHP_EOL
+ . 'DTSTAMP:20161004T144437Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// NO DTEND - DATE
- private $vEvent6 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN'.PHP_EOL.
- 'CALSCALE:GREGORIAN'.PHP_EOL.
- 'BEGIN:VEVENT'.PHP_EOL.
- 'CREATED:20161004T144433Z'.PHP_EOL.
- 'UID:85560E76-1B0D-47E1-A735-21625767FCA4'.PHP_EOL.
- 'TRANSP:TRANSPARENT'.PHP_EOL.
- 'DTSTART;VALUE=DATE:20161005'.PHP_EOL.
- 'DTSTAMP:20161004T144437Z'.PHP_EOL.
- 'SEQUENCE:0'.PHP_EOL.
- 'END:VEVENT'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vEvent6 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20161004T144433Z' . PHP_EOL
+ . 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL
+ . 'TRANSP:TRANSPARENT' . PHP_EOL
+ . 'DTSTART;VALUE=DATE:20161005' . PHP_EOL
+ . 'DTSTAMP:20161004T144437Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// NO DTEND - DATE-TIME
- private $vEvent7 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'PRODID:-//Tests//'.PHP_EOL.
- 'CALSCALE:GREGORIAN'.PHP_EOL.
- 'BEGIN:VTIMEZONE'.PHP_EOL.
- 'TZID:Europe/Berlin'.PHP_EOL.
- 'BEGIN:DAYLIGHT'.PHP_EOL.
- 'TZOFFSETFROM:+0100'.PHP_EOL.
- 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU'.PHP_EOL.
- 'DTSTART:19810329T020000'.PHP_EOL.
- 'TZNAME:GMT+2'.PHP_EOL.
- 'TZOFFSETTO:+0200'.PHP_EOL.
- 'END:DAYLIGHT'.PHP_EOL.
- 'BEGIN:STANDARD'.PHP_EOL.
- 'TZOFFSETFROM:+0200'.PHP_EOL.
- 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU'.PHP_EOL.
- 'DTSTART:19961027T030000'.PHP_EOL.
- 'TZNAME:GMT+1'.PHP_EOL.
- 'TZOFFSETTO:+0100'.PHP_EOL.
- 'END:STANDARD'.PHP_EOL.
- 'END:VTIMEZONE'.PHP_EOL.
- 'BEGIN:VEVENT'.PHP_EOL.
- 'CREATED:20160809T163629Z'.PHP_EOL.
- 'UID:0AD16F58-01B3-463B-A215-FD09FC729A02'.PHP_EOL.
- 'TRANSP:OPAQUE'.PHP_EOL.
- 'SUMMARY:Test Europe Berlin'.PHP_EOL.
- 'DTSTART;TZID=Europe/Berlin:20160816T090000'.PHP_EOL.
- 'DTSTAMP:20160809T163632Z'.PHP_EOL.
- 'SEQUENCE:0'.PHP_EOL.
- 'END:VEVENT'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vEvent7 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Tests//' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VTIMEZONE' . PHP_EOL
+ . 'TZID:Europe/Berlin' . PHP_EOL
+ . 'BEGIN:DAYLIGHT' . PHP_EOL
+ . 'TZOFFSETFROM:+0100' . PHP_EOL
+ . 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' . PHP_EOL
+ . 'DTSTART:19810329T020000' . PHP_EOL
+ . 'TZNAME:GMT+2' . PHP_EOL
+ . 'TZOFFSETTO:+0200' . PHP_EOL
+ . 'END:DAYLIGHT' . PHP_EOL
+ . 'BEGIN:STANDARD' . PHP_EOL
+ . 'TZOFFSETFROM:+0200' . PHP_EOL
+ . 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' . PHP_EOL
+ . 'DTSTART:19961027T030000' . PHP_EOL
+ . 'TZNAME:GMT+1' . PHP_EOL
+ . 'TZOFFSETTO:+0100' . PHP_EOL
+ . 'END:STANDARD' . PHP_EOL
+ . 'END:VTIMEZONE' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20160809T163629Z' . PHP_EOL
+ . 'UID:0AD16F58-01B3-463B-A215-FD09FC729A02' . PHP_EOL
+ . 'TRANSP:OPAQUE' . PHP_EOL
+ . 'SUMMARY:Test Europe Berlin' . PHP_EOL
+ . 'DTSTART;TZID=Europe/Berlin:20160816T090000' . PHP_EOL
+ . 'DTSTAMP:20160809T163632Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
protected function setUp(): void {
parent::setUp();
@@ -327,19 +319,19 @@ class EventsSearchProviderTest extends TestCase {
'calendarid' => 99,
'calendartype' => CalDavBackend::CALENDAR_TYPE_CALENDAR,
'uri' => 'event0.ics',
- 'calendardata' => $this->vEvent0,
+ 'calendardata' => self::$vEvent0,
],
[
'calendarid' => 123,
'calendartype' => CalDavBackend::CALENDAR_TYPE_CALENDAR,
'uri' => 'event1.ics',
- 'calendardata' => $this->vEvent1,
+ 'calendardata' => self::$vEvent1,
],
[
'calendarid' => 1337,
'calendartype' => CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION,
'uri' => 'event2.ics',
- 'calendardata' => $this->vEvent2,
+ 'calendardata' => self::$vEvent2,
]
]);
@@ -350,7 +342,7 @@ class EventsSearchProviderTest extends TestCase {
$this->urlGenerator,
$this->backend,
])
- ->setMethods([
+ ->onlyMethods([
'getDeepLinkToCalendarApp',
'generateSubline',
])
@@ -361,12 +353,11 @@ class EventsSearchProviderTest extends TestCase {
->willReturn('subline');
$provider->expects($this->exactly(3))
->method('getDeepLinkToCalendarApp')
- ->withConsecutive(
- ['principals/users/john.doe', 'calendar-uri-99', 'event0.ics'],
- ['principals/users/john.doe', 'calendar-uri-123', 'event1.ics'],
- ['principals/users/john.doe', 'subscription-uri-1337', 'event2.ics']
- )
- ->willReturn('deep-link-to-calendar');
+ ->willReturnMap([
+ ['principals/users/john.doe', 'calendar-uri-99', 'event0.ics', 'deep-link-to-calendar'],
+ ['principals/users/john.doe', 'calendar-uri-123', 'event1.ics', 'deep-link-to-calendar'],
+ ['principals/users/john.doe', 'subscription-uri-1337', 'event2.ics', 'deep-link-to-calendar']
+ ]);
$actual = $provider->search($user, $query);
$data = $actual->jsonSerialize();
@@ -427,12 +418,7 @@ class EventsSearchProviderTest extends TestCase {
$this->assertEquals('absolute-url-to-route', $actual);
}
- /**
- * @param string $ics
- * @param string $expectedSubline
- *
- * @dataProvider generateSublineDataProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('generateSublineDataProvider')]
public function testGenerateSubline(string $ics, string $expectedSubline): void {
$vCalendar = Reader::read($ics, Reader::OPTION_FORGIVING);
$eventComponent = $vCalendar->VEVENT;
@@ -450,15 +436,15 @@ class EventsSearchProviderTest extends TestCase {
$this->assertEquals($expectedSubline, $actual);
}
- public function generateSublineDataProvider(): array {
+ public static function generateSublineDataProvider(): array {
return [
- [$this->vEvent1, '08-16 09:00 - 10:00'],
- [$this->vEvent2, '08-16 09:00 - 08-17 10:00'],
- [$this->vEvent3, '10-05'],
- [$this->vEvent4, '10-05 - 10-07'],
- [$this->vEvent5, '10-05 - 10-09'],
- [$this->vEvent6, '10-05'],
- [$this->vEvent7, '08-16 09:00 - 09:00'],
+ [self::$vEvent1, '08-16 09:00 - 10:00'],
+ [self::$vEvent2, '08-16 09:00 - 08-17 10:00'],
+ [self::$vEvent3, '10-05'],
+ [self::$vEvent4, '10-05 - 10-07'],
+ [self::$vEvent5, '10-05 - 10-09'],
+ [self::$vEvent6, '10-05'],
+ [self::$vEvent7, '08-16 09:00 - 09:00'],
];
}
}
diff --git a/apps/dav/tests/unit/Search/TasksSearchProviderTest.php b/apps/dav/tests/unit/Search/TasksSearchProviderTest.php
index 18b6f0a5930..7f9a2842de9 100644
--- a/apps/dav/tests/unit/Search/TasksSearchProviderTest.php
+++ b/apps/dav/tests/unit/Search/TasksSearchProviderTest.php
@@ -17,89 +17,80 @@ use OCP\IUser;
use OCP\Search\ISearchQuery;
use OCP\Search\SearchResult;
use OCP\Search\SearchResultEntry;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Reader;
use Test\TestCase;
class TasksSearchProviderTest extends TestCase {
-
- /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */
- private $appManager;
-
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
- private $l10n;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
-
- /** @var CalDavBackend|\PHPUnit\Framework\MockObject\MockObject */
- private $backend;
-
- /** @var TasksSearchProvider */
- private $provider;
+ private IAppManager&MockObject $appManager;
+ private IL10N&MockObject $l10n;
+ private IURLGenerator&MockObject $urlGenerator;
+ private CalDavBackend&MockObject $backend;
+ private TasksSearchProvider $provider;
// NO DUE NOR COMPLETED NOR SUMMARY
- private $vTodo0 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'PRODID:TEST'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'BEGIN:VTODO'.PHP_EOL.
- 'UID:20070313T123432Z-456553@example.com'.PHP_EOL.
- 'DTSTAMP:20070313T123432Z'.PHP_EOL.
- 'STATUS:NEEDS-ACTION'.PHP_EOL.
- 'END:VTODO'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vTodo0 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'PRODID:TEST' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'BEGIN:VTODO' . PHP_EOL
+ . 'UID:20070313T123432Z-456553@example.com' . PHP_EOL
+ . 'DTSTAMP:20070313T123432Z' . PHP_EOL
+ . 'STATUS:NEEDS-ACTION' . PHP_EOL
+ . 'END:VTODO' . PHP_EOL
+ . 'END:VCALENDAR';
// DUE AND COMPLETED
- private $vTodo1 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'PRODID:TEST'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'BEGIN:VTODO'.PHP_EOL.
- 'UID:20070313T123432Z-456553@example.com'.PHP_EOL.
- 'DTSTAMP:20070313T123432Z'.PHP_EOL.
- 'COMPLETED:20070707T100000Z'.PHP_EOL.
- 'DUE;VALUE=DATE:20070501'.PHP_EOL.
- 'SUMMARY:Task title'.PHP_EOL.
- 'STATUS:NEEDS-ACTION'.PHP_EOL.
- 'END:VTODO'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vTodo1 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'PRODID:TEST' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'BEGIN:VTODO' . PHP_EOL
+ . 'UID:20070313T123432Z-456553@example.com' . PHP_EOL
+ . 'DTSTAMP:20070313T123432Z' . PHP_EOL
+ . 'COMPLETED:20070707T100000Z' . PHP_EOL
+ . 'DUE;VALUE=DATE:20070501' . PHP_EOL
+ . 'SUMMARY:Task title' . PHP_EOL
+ . 'STATUS:NEEDS-ACTION' . PHP_EOL
+ . 'END:VTODO' . PHP_EOL
+ . 'END:VCALENDAR';
// COMPLETED ONLY
- private $vTodo2 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'PRODID:TEST'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'BEGIN:VTODO'.PHP_EOL.
- 'UID:20070313T123432Z-456553@example.com'.PHP_EOL.
- 'DTSTAMP:20070313T123432Z'.PHP_EOL.
- 'COMPLETED:20070707T100000Z'.PHP_EOL.
- 'SUMMARY:Task title'.PHP_EOL.
- 'STATUS:NEEDS-ACTION'.PHP_EOL.
- 'END:VTODO'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vTodo2 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'PRODID:TEST' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'BEGIN:VTODO' . PHP_EOL
+ . 'UID:20070313T123432Z-456553@example.com' . PHP_EOL
+ . 'DTSTAMP:20070313T123432Z' . PHP_EOL
+ . 'COMPLETED:20070707T100000Z' . PHP_EOL
+ . 'SUMMARY:Task title' . PHP_EOL
+ . 'STATUS:NEEDS-ACTION' . PHP_EOL
+ . 'END:VTODO' . PHP_EOL
+ . 'END:VCALENDAR';
// DUE DATE
- private $vTodo3 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'PRODID:TEST'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'BEGIN:VTODO'.PHP_EOL.
- 'UID:20070313T123432Z-456553@example.com'.PHP_EOL.
- 'DTSTAMP:20070313T123432Z'.PHP_EOL.
- 'DUE;VALUE=DATE:20070501'.PHP_EOL.
- 'SUMMARY:Task title'.PHP_EOL.
- 'STATUS:NEEDS-ACTION'.PHP_EOL.
- 'END:VTODO'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vTodo3 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'PRODID:TEST' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'BEGIN:VTODO' . PHP_EOL
+ . 'UID:20070313T123432Z-456553@example.com' . PHP_EOL
+ . 'DTSTAMP:20070313T123432Z' . PHP_EOL
+ . 'DUE;VALUE=DATE:20070501' . PHP_EOL
+ . 'SUMMARY:Task title' . PHP_EOL
+ . 'STATUS:NEEDS-ACTION' . PHP_EOL
+ . 'END:VTODO' . PHP_EOL
+ . 'END:VCALENDAR';
// DUE DATETIME
- private $vTodo4 = 'BEGIN:VCALENDAR'.PHP_EOL.
- 'PRODID:TEST'.PHP_EOL.
- 'VERSION:2.0'.PHP_EOL.
- 'BEGIN:VTODO'.PHP_EOL.
- 'UID:20070313T123432Z-456553@example.com'.PHP_EOL.
- 'DTSTAMP:20070313T123432Z'.PHP_EOL.
- 'DUE:20070709T130000Z'.PHP_EOL.
- 'SUMMARY:Task title'.PHP_EOL.
- 'STATUS:NEEDS-ACTION'.PHP_EOL.
- 'END:VTODO'.PHP_EOL.
- 'END:VCALENDAR';
+ private static string $vTodo4 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'PRODID:TEST' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'BEGIN:VTODO' . PHP_EOL
+ . 'UID:20070313T123432Z-456553@example.com' . PHP_EOL
+ . 'DTSTAMP:20070313T123432Z' . PHP_EOL
+ . 'DUE:20070709T130000Z' . PHP_EOL
+ . 'SUMMARY:Task title' . PHP_EOL
+ . 'STATUS:NEEDS-ACTION' . PHP_EOL
+ . 'END:VTODO' . PHP_EOL
+ . 'END:VCALENDAR';
protected function setUp(): void {
parent::setUp();
@@ -204,19 +195,19 @@ class TasksSearchProviderTest extends TestCase {
'calendarid' => 99,
'calendartype' => CalDavBackend::CALENDAR_TYPE_CALENDAR,
'uri' => 'todo0.ics',
- 'calendardata' => $this->vTodo0,
+ 'calendardata' => self::$vTodo0,
],
[
'calendarid' => 123,
'calendartype' => CalDavBackend::CALENDAR_TYPE_CALENDAR,
'uri' => 'todo1.ics',
- 'calendardata' => $this->vTodo1,
+ 'calendardata' => self::$vTodo1,
],
[
'calendarid' => 1337,
'calendartype' => CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION,
'uri' => 'todo2.ics',
- 'calendardata' => $this->vTodo2,
+ 'calendardata' => self::$vTodo2,
]
]);
@@ -227,7 +218,7 @@ class TasksSearchProviderTest extends TestCase {
$this->urlGenerator,
$this->backend,
])
- ->setMethods([
+ ->onlyMethods([
'getDeepLinkToTasksApp',
'generateSubline',
])
@@ -238,12 +229,11 @@ class TasksSearchProviderTest extends TestCase {
->willReturn('subline');
$provider->expects($this->exactly(3))
->method('getDeepLinkToTasksApp')
- ->withConsecutive(
- ['calendar-uri-99', 'todo0.ics'],
- ['calendar-uri-123', 'todo1.ics'],
- ['subscription-uri-1337', 'todo2.ics']
- )
- ->willReturn('deep-link-to-tasks');
+ ->willReturnMap([
+ ['calendar-uri-99', 'todo0.ics', 'deep-link-to-tasks'],
+ ['calendar-uri-123', 'todo1.ics', 'deep-link-to-tasks'],
+ ['subscription-uri-1337', 'todo2.ics', 'deep-link-to-tasks']
+ ]);
$actual = $provider->search($user, $query);
$data = $actual->jsonSerialize();
@@ -292,37 +282,32 @@ class TasksSearchProviderTest extends TestCase {
->willReturn('link-to-route-tasks.index');
$this->urlGenerator->expects($this->once())
->method('getAbsoluteURL')
- ->with('link-to-route-tasks.index#/calendars/uri-john.doe/tasks/task-uri.ics')
- ->willReturn('absolute-url-link-to-route-tasks.index#/calendars/uri-john.doe/tasks/task-uri.ics');
+ ->with('link-to-route-tasks.indexcalendars/uri-john.doe/tasks/task-uri.ics')
+ ->willReturn('absolute-url-link-to-route-tasks.indexcalendars/uri-john.doe/tasks/task-uri.ics');
$actual = self::invokePrivate($this->provider, 'getDeepLinkToTasksApp', ['uri-john.doe', 'task-uri.ics']);
- $this->assertEquals('absolute-url-link-to-route-tasks.index#/calendars/uri-john.doe/tasks/task-uri.ics', $actual);
+ $this->assertEquals('absolute-url-link-to-route-tasks.indexcalendars/uri-john.doe/tasks/task-uri.ics', $actual);
}
- /**
- * @param string $ics
- * @param string $expectedSubline
- *
- * @dataProvider generateSublineDataProvider
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('generateSublineDataProvider')]
public function testGenerateSubline(string $ics, string $expectedSubline): void {
$vCalendar = Reader::read($ics, Reader::OPTION_FORGIVING);
$taskComponent = $vCalendar->VTODO;
$this->l10n->method('t')->willReturnArgument(0);
- $this->l10n->method('l')->willReturnArgument('');
+ $this->l10n->method('l')->willReturnArgument(0);
$actual = self::invokePrivate($this->provider, 'generateSubline', [$taskComponent]);
$this->assertEquals($expectedSubline, $actual);
}
- public function generateSublineDataProvider(): array {
+ public static function generateSublineDataProvider(): array {
return [
- [$this->vTodo0, ''],
- [$this->vTodo1, 'Completed on %s'],
- [$this->vTodo2, 'Completed on %s'],
- [$this->vTodo3, 'Due on %s'],
- [$this->vTodo4, 'Due on %s by %s'],
+ [self::$vTodo0, ''],
+ [self::$vTodo1, 'Completed on %s'],
+ [self::$vTodo2, 'Completed on %s'],
+ [self::$vTodo3, 'Due on %s'],
+ [self::$vTodo4, 'Due on %s by %s'],
];
}
}
diff --git a/apps/dav/tests/unit/ServerTest.php b/apps/dav/tests/unit/ServerTest.php
index 16e0a5b80aa..9ffe86d3053 100644
--- a/apps/dav/tests/unit/ServerTest.php
+++ b/apps/dav/tests/unit/ServerTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -19,10 +20,8 @@ use OCP\IRequest;
*/
class ServerTest extends \Test\TestCase {
- /**
- * @dataProvider providesUris
- */
- public function test($uri, array $plugins): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesUris')]
+ public function test(string $uri, array $plugins): void {
/** @var IRequest | \PHPUnit\Framework\MockObject\MockObject $r */
$r = $this->createMock(IRequest::class);
$r->expects($this->any())->method('getRequestUri')->willReturn($uri);
@@ -33,7 +32,7 @@ class ServerTest extends \Test\TestCase {
$this->assertNotNull($s->server->getPlugin($plugin));
}
}
- public function providesUris() {
+ public static function providesUris(): array {
return [
'principals' => ['principals/users/admin', ['caldav', 'oc-resource-sharing', 'carddav']],
'calendars' => ['calendars/admin', ['caldav', 'oc-resource-sharing']],
diff --git a/apps/dav/tests/unit/Service/AbsenceServiceTest.php b/apps/dav/tests/unit/Service/AbsenceServiceTest.php
index 1bc5f53f18c..c16c715d5c2 100644
--- a/apps/dav/tests/unit/Service/AbsenceServiceTest.php
+++ b/apps/dav/tests/unit/Service/AbsenceServiceTest.php
@@ -7,7 +7,7 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\dav\tests\unit\Service;
+namespace OCA\DAV\Tests\unit\Service;
use DateTimeImmutable;
use DateTimeZone;
@@ -24,25 +24,16 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUser;
use OCP\User\Events\OutOfOfficeChangedEvent;
use OCP\User\Events\OutOfOfficeScheduledEvent;
+use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class AbsenceServiceTest extends TestCase {
private AbsenceService $absenceService;
-
- /** @var MockObject|AbsenceMapper */
- private $absenceMapper;
-
- /** @var MockObject|IEventDispatcher */
- private $eventDispatcher;
-
- /** @var MockObject|IJobList */
- private $jobList;
-
- /** @var MockObject|TimezoneService */
- private $timezoneService;
-
- /** @var MockObject|ITimeFactory */
- private $timeFactory;
+ private AbsenceMapper&MockObject $absenceMapper;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private IJobList&MockObject $jobList;
+ private TimezoneService&MockObject $timezoneService;
+ private ITimeFactory&MockObject $timeFactory;
protected function setUp(): void {
parent::setUp();
@@ -62,7 +53,7 @@ class AbsenceServiceTest extends TestCase {
);
}
- public function testCreateAbsenceEmitsScheduledEvent() {
+ public function testCreateAbsenceEmitsScheduledEvent(): void {
$tz = new DateTimeZone('Europe/Berlin');
$user = $this->createMock(IUser::class);
$user->method('getUID')
@@ -117,7 +108,7 @@ class AbsenceServiceTest extends TestCase {
);
}
- public function testUpdateAbsenceEmitsChangedEvent() {
+ public function testUpdateAbsenceEmitsChangedEvent(): void {
$tz = new DateTimeZone('Europe/Berlin');
$user = $this->createMock(IUser::class);
$user->method('getUID')
@@ -181,7 +172,7 @@ class AbsenceServiceTest extends TestCase {
);
}
- public function testCreateAbsenceSchedulesBothJobs() {
+ public function testCreateAbsenceSchedulesBothJobs(): void {
$tz = new DateTimeZone('Europe/Berlin');
$startDateString = '2023-01-05';
$startDate = new DateTimeImmutable($startDateString, $tz);
@@ -230,7 +221,7 @@ class AbsenceServiceTest extends TestCase {
);
}
- public function testCreateAbsenceSchedulesOnlyEndJob() {
+ public function testCreateAbsenceSchedulesOnlyEndJob(): void {
$tz = new DateTimeZone('Europe/Berlin');
$endDateString = '2023-01-10';
$endDate = new DateTimeImmutable($endDateString, $tz);
@@ -271,7 +262,7 @@ class AbsenceServiceTest extends TestCase {
);
}
- public function testCreateAbsenceSchedulesNoJob() {
+ public function testCreateAbsenceSchedulesNoJob(): void {
$tz = new DateTimeZone('Europe/Berlin');
$user = $this->createMock(IUser::class);
$user->method('getUID')
@@ -306,7 +297,7 @@ class AbsenceServiceTest extends TestCase {
);
}
- public function testUpdateAbsenceSchedulesBothJobs() {
+ public function testUpdateAbsenceSchedulesBothJobs(): void {
$tz = new DateTimeZone('Europe/Berlin');
$startDateString = '2023-01-05';
$startDate = new DateTimeImmutable($startDateString, $tz);
@@ -362,7 +353,7 @@ class AbsenceServiceTest extends TestCase {
);
}
- public function testUpdateSchedulesOnlyEndJob() {
+ public function testUpdateSchedulesOnlyEndJob(): void {
$tz = new DateTimeZone('Europe/Berlin');
$endDateString = '2023-01-10';
$endDate = new DateTimeImmutable($endDateString, $tz);
@@ -410,7 +401,7 @@ class AbsenceServiceTest extends TestCase {
);
}
- public function testUpdateAbsenceSchedulesNoJob() {
+ public function testUpdateAbsenceSchedulesNoJob(): void {
$tz = new DateTimeZone('Europe/Berlin');
$user = $this->createMock(IUser::class);
$user->method('getUID')
diff --git a/apps/dav/tests/unit/Service/ExampleContactServiceTest.php b/apps/dav/tests/unit/Service/ExampleContactServiceTest.php
new file mode 100644
index 00000000000..027b66a6fb2
--- /dev/null
+++ b/apps/dav/tests/unit/Service/ExampleContactServiceTest.php
@@ -0,0 +1,194 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\Service;
+
+use OCA\DAV\CardDAV\CardDavBackend;
+use OCA\DAV\Service\ExampleContactService;
+use OCP\App\IAppManager;
+use OCP\AppFramework\Services\IAppConfig;
+use OCP\Files\AppData\IAppDataFactory;
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\Files\SimpleFS\ISimpleFolder;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Uid\Uuid;
+use Test\TestCase;
+
+class ExampleContactServiceTest extends TestCase {
+ protected ExampleContactService $service;
+ protected CardDavBackend&MockObject $cardDav;
+ protected IAppManager&MockObject $appManager;
+ protected IAppDataFactory&MockObject $appDataFactory;
+ protected LoggerInterface&MockObject $logger;
+ protected IAppConfig&MockObject $appConfig;
+ protected IAppData&MockObject $appData;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->cardDav = $this->createMock(CardDavBackend::class);
+ $this->appDataFactory = $this->createMock(IAppDataFactory::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->appConfig = $this->createMock(IAppConfig::class);
+
+ $this->appData = $this->createMock(IAppData::class);
+ $this->appDataFactory->method('get')
+ ->with('dav')
+ ->willReturn($this->appData);
+
+ $this->service = new ExampleContactService(
+ $this->appDataFactory,
+ $this->appConfig,
+ $this->logger,
+ $this->cardDav,
+ );
+ }
+
+ public function testCreateDefaultContactWithInvalidCard(): void {
+ // Invalid vCard missing required FN property
+ $vcardContent = "BEGIN:VCARD\nVERSION:3.0\nEND:VCARD";
+ $this->appConfig->method('getAppValueBool')
+ ->with('enableDefaultContact', true)
+ ->willReturn(true);
+ $folder = $this->createMock(ISimpleFolder::class);
+ $file = $this->createMock(ISimpleFile::class);
+ $file->method('getContent')->willReturn($vcardContent);
+ $folder->method('getFile')->willReturn($file);
+ $this->appData->method('getFolder')->willReturn($folder);
+
+ $this->logger->expects($this->once())
+ ->method('error')
+ ->with('Default contact is invalid', $this->anything());
+
+ $this->cardDav->expects($this->never())
+ ->method('createCard');
+
+ $this->service->createDefaultContact(123);
+ }
+
+ public function testUidAndRevAreUpdated(): void {
+ $originalUid = 'original-uid';
+ $originalRev = '20200101T000000Z';
+ $vcardContent = "BEGIN:VCARD\nVERSION:3.0\nFN:Test User\nUID:$originalUid\nREV:$originalRev\nEND:VCARD";
+
+ $this->appConfig->method('getAppValueBool')
+ ->with('enableDefaultContact', true)
+ ->willReturn(true);
+ $folder = $this->createMock(ISimpleFolder::class);
+ $file = $this->createMock(ISimpleFile::class);
+ $file->method('getContent')->willReturn($vcardContent);
+ $folder->method('getFile')->willReturn($file);
+ $this->appData->method('getFolder')->willReturn($folder);
+
+ $capturedCardData = null;
+ $this->cardDav->expects($this->once())
+ ->method('createCard')
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->callback(function ($cardData) use (&$capturedCardData) {
+ $capturedCardData = $cardData;
+ return true;
+ }),
+ $this->anything()
+ )->willReturn(null);
+
+ $this->service->createDefaultContact(123);
+
+ $vcard = \Sabre\VObject\Reader::read($capturedCardData);
+ $this->assertNotEquals($originalUid, $vcard->UID->getValue());
+ $this->assertTrue(Uuid::isValid($vcard->UID->getValue()));
+ $this->assertNotEquals($originalRev, $vcard->REV->getValue());
+ }
+
+ public function testDefaultContactFileDoesNotExist(): void {
+ $this->appConfig->method('getAppValueBool')
+ ->with('enableDefaultContact', true)
+ ->willReturn(true);
+ $this->appData->method('getFolder')->willThrowException(new NotFoundException());
+
+ $this->cardDav->expects($this->never())
+ ->method('createCard');
+
+ $this->service->createDefaultContact(123);
+ }
+
+ public function testUidAndRevAreAddedIfMissing(): void {
+ $vcardContent = "BEGIN:VCARD\nVERSION:3.0\nFN:Test User\nEND:VCARD";
+
+ $this->appConfig->method('getAppValueBool')
+ ->with('enableDefaultContact', true)
+ ->willReturn(true);
+ $folder = $this->createMock(ISimpleFolder::class);
+ $file = $this->createMock(ISimpleFile::class);
+ $file->method('getContent')->willReturn($vcardContent);
+ $folder->method('getFile')->willReturn($file);
+ $this->appData->method('getFolder')->willReturn($folder);
+
+ $capturedCardData = 'new-card-data';
+
+ $this->cardDav
+ ->expects($this->once())
+ ->method('createCard')
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->callback(function ($cardData) use (&$capturedCardData) {
+ $capturedCardData = $cardData;
+ return true;
+ }),
+ $this->anything()
+ );
+
+ $this->service->createDefaultContact(123);
+ $vcard = \Sabre\VObject\Reader::read($capturedCardData);
+
+ $this->assertNotNull($vcard->REV);
+ $this->assertNotNull($vcard->UID);
+ $this->assertTrue(Uuid::isValid($vcard->UID->getValue()));
+ }
+
+ public function testDefaultContactIsNotCreatedIfEnabled(): void {
+ $this->appConfig->method('getAppValueBool')
+ ->with('enableDefaultContact', true)
+ ->willReturn(false);
+ $this->logger->expects($this->never())
+ ->method('error');
+ $this->cardDav->expects($this->never())
+ ->method('createCard');
+
+ $this->service->createDefaultContact(123);
+ }
+
+ public static function provideDefaultContactEnableData(): array {
+ return [[true], [false]];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('provideDefaultContactEnableData')]
+ public function testIsDefaultContactEnabled(bool $enabled): void {
+ $this->appConfig->expects(self::once())
+ ->method('getAppValueBool')
+ ->with('enableDefaultContact', true)
+ ->willReturn($enabled);
+
+ $this->assertEquals($enabled, $this->service->isDefaultContactEnabled());
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('provideDefaultContactEnableData')]
+ public function testSetDefaultContactEnabled(bool $enabled): void {
+ $this->appConfig->expects(self::once())
+ ->method('setAppValueBool')
+ ->with('enableDefaultContact', $enabled);
+
+ $this->service->setDefaultContactEnabled($enabled);
+ }
+}
diff --git a/apps/dav/tests/unit/Service/ExampleEventServiceTest.php b/apps/dav/tests/unit/Service/ExampleEventServiceTest.php
new file mode 100644
index 00000000000..0f423624fb8
--- /dev/null
+++ b/apps/dav/tests/unit/Service/ExampleEventServiceTest.php
@@ -0,0 +1,196 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\Service;
+
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\Service\ExampleEventService;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\Files\SimpleFS\ISimpleFolder;
+use OCP\IAppConfig;
+use OCP\IL10N;
+use OCP\Security\ISecureRandom;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+class ExampleEventServiceTest extends TestCase {
+ private ExampleEventService $service;
+
+ private CalDavBackend&MockObject $calDavBackend;
+ private ISecureRandom&MockObject $random;
+ private ITimeFactory&MockObject $time;
+ private IAppData&MockObject $appData;
+ private IAppConfig&MockObject $appConfig;
+ private IL10N&MockObject $l10n;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->calDavBackend = $this->createMock(CalDavBackend::class);
+ $this->random = $this->createMock(ISecureRandom::class);
+ $this->time = $this->createMock(ITimeFactory::class);
+ $this->appData = $this->createMock(IAppData::class);
+ $this->appConfig = $this->createMock(IAppConfig::class);
+ $this->l10n = $this->createMock(IL10N::class);
+
+ $this->l10n->method('t')
+ ->willReturnArgument(0);
+
+ $this->service = new ExampleEventService(
+ $this->calDavBackend,
+ $this->random,
+ $this->time,
+ $this->appData,
+ $this->appConfig,
+ $this->l10n,
+ );
+ }
+
+ public static function provideCustomEventData(): array {
+ return [
+ [file_get_contents(__DIR__ . '/../test_fixtures/example-event.ics')],
+ [file_get_contents(__DIR__ . '/../test_fixtures/example-event-with-attendees.ics')],
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('provideCustomEventData')]
+ public function testCreateExampleEventWithCustomEvent($customEventIcs): void {
+ $this->appConfig->expects(self::once())
+ ->method('getValueBool')
+ ->with('dav', 'create_example_event', true)
+ ->willReturn(true);
+
+ $exampleEventFolder = $this->createMock(ISimpleFolder::class);
+ $this->appData->expects(self::once())
+ ->method('getFolder')
+ ->with('example_event')
+ ->willReturn($exampleEventFolder);
+ $exampleEventFile = $this->createMock(ISimpleFile::class);
+ $exampleEventFolder->expects(self::once())
+ ->method('getFile')
+ ->with('example_event.ics')
+ ->willReturn($exampleEventFile);
+ $exampleEventFile->expects(self::once())
+ ->method('getContent')
+ ->willReturn($customEventIcs);
+
+ $this->random->expects(self::once())
+ ->method('generate')
+ ->with(32, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
+ ->willReturn('RANDOM-UID');
+
+ $now = new \DateTimeImmutable('2025-01-21T00:00:00Z');
+ $this->time->expects(self::exactly(2))
+ ->method('now')
+ ->willReturn($now);
+
+ $expectedIcs = file_get_contents(__DIR__ . '/../test_fixtures/example-event-expected.ics');
+ $this->calDavBackend->expects(self::once())
+ ->method('createCalendarObject')
+ ->with(1000, 'RANDOM-UID.ics', $expectedIcs);
+
+ $this->service->createExampleEvent(1000);
+ }
+
+ public function testCreateExampleEventWithDefaultEvent(): void {
+ $this->appConfig->expects(self::once())
+ ->method('getValueBool')
+ ->with('dav', 'create_example_event', true)
+ ->willReturn(true);
+
+ $this->appData->expects(self::once())
+ ->method('getFolder')
+ ->with('example_event')
+ ->willThrowException(new NotFoundException());
+
+ $this->random->expects(self::once())
+ ->method('generate')
+ ->with(32, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
+ ->willReturn('RANDOM-UID');
+
+ $now = new \DateTimeImmutable('2025-01-21T00:00:00Z');
+ $this->time->expects(self::exactly(3))
+ ->method('now')
+ ->willReturn($now);
+
+ $expectedIcs = file_get_contents(__DIR__ . '/../test_fixtures/example-event-default-expected.ics');
+ $this->calDavBackend->expects(self::once())
+ ->method('createCalendarObject')
+ ->with(1000, 'RANDOM-UID.ics', $expectedIcs);
+
+ $this->service->createExampleEvent(1000);
+ }
+
+ public function testCreateExampleWhenDisabled(): void {
+ $this->appConfig->expects(self::once())
+ ->method('getValueBool')
+ ->with('dav', 'create_example_event', true)
+ ->willReturn(false);
+
+ $this->calDavBackend->expects(self::never())
+ ->method('createCalendarObject');
+
+ $this->service->createExampleEvent(1000);
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('provideCustomEventData')]
+ public function testGetExampleEventWithCustomEvent($customEventIcs): void {
+ $exampleEventFolder = $this->createMock(ISimpleFolder::class);
+ $this->appData->expects(self::once())
+ ->method('getFolder')
+ ->with('example_event')
+ ->willReturn($exampleEventFolder);
+ $exampleEventFile = $this->createMock(ISimpleFile::class);
+ $exampleEventFolder->expects(self::once())
+ ->method('getFile')
+ ->with('example_event.ics')
+ ->willReturn($exampleEventFile);
+ $exampleEventFile->expects(self::once())
+ ->method('getContent')
+ ->willReturn($customEventIcs);
+
+ $this->random->expects(self::once())
+ ->method('generate')
+ ->with(32, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
+ ->willReturn('RANDOM-UID');
+
+ $now = new \DateTimeImmutable('2025-01-21T00:00:00Z');
+ $this->time->expects(self::exactly(2))
+ ->method('now')
+ ->willReturn($now);
+
+ $expectedIcs = file_get_contents(__DIR__ . '/../test_fixtures/example-event-expected.ics');
+ $actualIcs = $this->service->getExampleEvent()->getIcs();
+ $this->assertEquals($expectedIcs, $actualIcs);
+ }
+
+ public function testGetExampleEventWithDefault(): void {
+ $this->appData->expects(self::once())
+ ->method('getFolder')
+ ->with('example_event')
+ ->willThrowException(new NotFoundException());
+
+ $this->random->expects(self::once())
+ ->method('generate')
+ ->with(32, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
+ ->willReturn('RANDOM-UID');
+
+ $now = new \DateTimeImmutable('2025-01-21T00:00:00Z');
+ $this->time->expects(self::exactly(3))
+ ->method('now')
+ ->willReturn($now);
+
+ $expectedIcs = file_get_contents(__DIR__ . '/../test_fixtures/example-event-default-expected.ics');
+ $actualIcs = $this->service->getExampleEvent()->getIcs();
+ $this->assertEquals($expectedIcs, $actualIcs);
+ }
+}
diff --git a/apps/dav/tests/unit/Service/UpcomingEventsServiceTest.php b/apps/dav/tests/unit/Service/UpcomingEventsServiceTest.php
new file mode 100644
index 00000000000..fdfe37d8918
--- /dev/null
+++ b/apps/dav/tests/unit/Service/UpcomingEventsServiceTest.php
@@ -0,0 +1,89 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\DAV\Service;
+
+use DateTimeImmutable;
+use OCA\DAV\CalDAV\UpcomingEventsService;
+use OCP\App\IAppManager;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Calendar\ICalendarQuery;
+use OCP\Calendar\IManager;
+use OCP\IURLGenerator;
+use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+
+class UpcomingEventsServiceTest extends TestCase {
+
+ private IManager&MockObject $calendarManager;
+ private ITimeFactory&MockObject $timeFactory;
+ private IUserManager&MockObject $userManager;
+ private IAppManager&MockObject $appManager;
+ private IURLGenerator&MockObject $urlGenerator;
+ private UpcomingEventsService $service;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->calendarManager = $this->createMock(IManager::class);
+ $this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->appManager = $this->createMock(IAppManager::class);
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
+
+ $this->service = new UpcomingEventsService(
+ $this->calendarManager,
+ $this->timeFactory,
+ $this->userManager,
+ $this->appManager,
+ $this->urlGenerator,
+ );
+ }
+
+ public function testGetEventsByLocation(): void {
+ $now = new DateTimeImmutable('2024-07-08T18:20:20Z');
+ $this->timeFactory->method('now')
+ ->willReturn($now);
+ $query = $this->createMock(ICalendarQuery::class);
+ $this->appManager->method('isEnabledForUser')->willReturn(false);
+ $this->calendarManager->method('newQuery')
+ ->with('principals/users/user1')
+ ->willReturn($query);
+ $query->expects(self::once())
+ ->method('addSearchProperty')
+ ->with('LOCATION');
+ $query->expects(self::once())
+ ->method('setSearchPattern')
+ ->with('https://cloud.example.com/call/123');
+ $this->calendarManager->expects(self::once())
+ ->method('searchForPrincipal')
+ ->with($query)
+ ->willReturn([
+ [
+ 'uri' => 'ev1',
+ 'calendar-key' => '1',
+ 'calendar-uri' => 'personal',
+ 'objects' => [
+ 0 => [
+ 'DTSTART' => [
+ new DateTimeImmutable('now'),
+ ],
+ ],
+ ],
+ ],
+ ]);
+
+ $events = $this->service->getEvents('user1', 'https://cloud.example.com/call/123');
+
+ self::assertCount(1, $events);
+ $event1 = $events[0];
+ self::assertEquals('ev1', $event1->getUri());
+ }
+}
diff --git a/apps/dav/tests/unit/Settings/CalDAVSettingsTest.php b/apps/dav/tests/unit/Settings/CalDAVSettingsTest.php
index 46a8db6f3eb..032759d64b7 100644
--- a/apps/dav/tests/unit/Settings/CalDAVSettingsTest.php
+++ b/apps/dav/tests/unit/Settings/CalDAVSettingsTest.php
@@ -1,11 +1,14 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\DAV\Settings;
+namespace OCA\DAV\Tests\unit\DAV\Settings;
use OCA\DAV\Settings\CalDAVSettings;
+use OCP\App\IAppManager;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig;
@@ -14,16 +17,10 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CalDAVSettingsTest extends TestCase {
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var IInitialState|MockObject */
- private $initialState;
-
- /** @var IURLGenerator|MockObject */
- private $urlGenerator;
-
+ private IConfig&MockObject $config;
+ private IInitialState&MockObject $initialState;
+ private IURLGenerator&MockObject $urlGenerator;
+ private IAppManager&MockObject $appManager;
private CalDAVSettings $settings;
protected function setUp(): void {
@@ -32,42 +29,59 @@ class CalDAVSettingsTest extends TestCase {
$this->config = $this->createMock(IConfig::class);
$this->initialState = $this->createMock(IInitialState::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
- $this->settings = new CalDAVSettings($this->config, $this->initialState, $this->urlGenerator);
+ $this->appManager = $this->createMock(IAppManager::class);
+ $this->settings = new CalDAVSettings($this->config, $this->initialState, $this->urlGenerator, $this->appManager);
}
public function testGetForm(): void {
$this->config->method('getAppValue')
- ->withConsecutive(
- ['dav', 'sendInvitations', 'yes'],
- ['dav', 'generateBirthdayCalendar', 'yes'],
- ['dav', 'sendEventReminders', 'yes'],
- ['dav', 'sendEventRemindersToSharedUsers', 'yes'],
- ['dav', 'sendEventRemindersPush', 'yes'],
- )
- ->will($this->onConsecutiveCalls('yes', 'no', 'yes', 'yes', 'yes'));
+ ->willReturnMap([
+ ['dav', 'sendInvitations', 'yes', 'yes'],
+ ['dav', 'generateBirthdayCalendar', 'yes', 'no'],
+ ['dav', 'sendEventReminders', 'yes', 'yes'],
+ ['dav', 'sendEventRemindersToSharedUsers', 'yes', 'yes'],
+ ['dav', 'sendEventRemindersPush', 'yes', 'yes'],
+ ]);
$this->urlGenerator
->expects($this->once())
->method('linkToDocs')
->with('user-sync-calendars')
->willReturn('Some docs URL');
+
+ $calls = [
+ ['userSyncCalendarsDocUrl', 'Some docs URL'],
+ ['sendInvitations', true],
+ ['generateBirthdayCalendar', false],
+ ['sendEventReminders', true],
+ ['sendEventRemindersToSharedUsers', true],
+ ['sendEventRemindersPush', true],
+ ];
$this->initialState->method('provideInitialState')
- ->withConsecutive(
- ['userSyncCalendarsDocUrl', 'Some docs URL'],
- ['sendInvitations', true],
- ['generateBirthdayCalendar', false],
- ['sendEventReminders', true],
- ['sendEventRemindersToSharedUsers', true],
- ['sendEventRemindersPush', true],
- );
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$result = $this->settings->getForm();
$this->assertInstanceOf(TemplateResponse::class, $result);
}
public function testGetSection(): void {
+ $this->appManager->expects(self::once())
+ ->method('isBackendRequired')
+ ->with(IAppManager::BACKEND_CALDAV)
+ ->willReturn(true);
$this->assertEquals('groupware', $this->settings->getSection());
}
+ public function testGetSectionWithoutCaldavBackend(): void {
+ $this->appManager->expects(self::once())
+ ->method('isBackendRequired')
+ ->with(IAppManager::BACKEND_CALDAV)
+ ->willReturn(false);
+ $this->assertEquals(null, $this->settings->getSection());
+ }
+
public function testGetPriority(): void {
$this->assertEquals(10, $this->settings->getPriority());
}
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php b/apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php
index 308950cef34..39342811377 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,35 +9,34 @@
namespace OCA\DAV\Tests\unit\SystemTag;
use OC\SystemTag\SystemTag;
+use OCA\DAV\SystemTag\SystemTagMappingNode;
use OCP\IUser;
use OCP\SystemTag\ISystemTag;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagNotFoundException;
+use PHPUnit\Framework\MockObject\MockObject;
class SystemTagMappingNodeTest extends \Test\TestCase {
- private ISystemTagManager $tagManager;
- private ISystemTagObjectMapper $tagMapper;
- private IUser $user;
+ private ISystemTagManager&MockObject $tagManager;
+ private ISystemTagObjectMapper&MockObject $tagMapper;
+ private IUser&MockObject $user;
protected function setUp(): void {
parent::setUp();
- $this->tagManager = $this->getMockBuilder(ISystemTagManager::class)
- ->getMock();
- $this->tagMapper = $this->getMockBuilder(ISystemTagObjectMapper::class)
- ->getMock();
- $this->user = $this->getMockBuilder(IUser::class)
- ->getMock();
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
+ $this->tagMapper = $this->createMock(ISystemTagObjectMapper::class);
+ $this->user = $this->createMock(IUser::class);
}
public function getMappingNode($tag = null, array $writableNodeIds = []) {
if ($tag === null) {
- $tag = new SystemTag(1, 'Test', true, true);
+ $tag = new SystemTag('1', 'Test', true, true);
}
- return new \OCA\DAV\SystemTag\SystemTagMappingNode(
+ return new SystemTagMappingNode(
$tag,
- 123,
+ '123',
'files',
$this->user,
$this->tagManager,
@@ -46,7 +46,7 @@ class SystemTagMappingNodeTest extends \Test\TestCase {
}
public function testGetters(): void {
- $tag = new SystemTag(1, 'Test', true, false);
+ $tag = new SystemTag('1', 'Test', true, false);
$node = $this->getMappingNode($tag);
$this->assertEquals('1', $node->getName());
$this->assertEquals($tag, $node->getSystemTag());
@@ -92,24 +92,22 @@ class SystemTagMappingNodeTest extends \Test\TestCase {
$node->delete();
}
- public function tagNodeDeleteProviderPermissionException() {
+ public static function tagNodeDeleteProviderPermissionException(): array {
return [
[
// cannot unassign invisible tag
- new SystemTag(1, 'Original', false, true),
+ new SystemTag('1', 'Original', false, true),
'Sabre\DAV\Exception\NotFound',
],
[
// cannot unassign non-assignable tag
- new SystemTag(1, 'Original', true, false),
+ new SystemTag('1', 'Original', true, false),
'Sabre\DAV\Exception\Forbidden',
],
];
}
- /**
- * @dataProvider tagNodeDeleteProviderPermissionException
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('tagNodeDeleteProviderPermissionException')]
public function testDeleteTagExpectedException(ISystemTag $tag, $expectedException): void {
$this->tagManager->expects($this->any())
->method('canUserSeeTag')
@@ -140,7 +138,7 @@ class SystemTagMappingNodeTest extends \Test\TestCase {
// assuming the tag existed at the time the node was created,
// but got deleted concurrently in the database
- $tag = new SystemTag(1, 'Test', true, true);
+ $tag = new SystemTag('1', 'Test', true, true);
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
->with($tag)
@@ -152,7 +150,7 @@ class SystemTagMappingNodeTest extends \Test\TestCase {
$this->tagMapper->expects($this->once())
->method('unassignTags')
->with(123, 'files', 1)
- ->will($this->throwException(new TagNotFoundException()));
+ ->willThrowException(new TagNotFoundException());
$this->getMappingNode($tag, [123])->delete();
}
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagNodeTest.php b/apps/dav/tests/unit/SystemTag/SystemTagNodeTest.php
index 82aa81674df..594b5e15db6 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagNodeTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagNodeTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,54 +9,48 @@
namespace OCA\DAV\Tests\unit\SystemTag;
use OC\SystemTag\SystemTag;
+use OCA\DAV\SystemTag\SystemTagNode;
use OCP\IUser;
use OCP\SystemTag\ISystemTag;
use OCP\SystemTag\ISystemTagManager;
+use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagAlreadyExistsException;
use OCP\SystemTag\TagNotFoundException;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\Forbidden;
class SystemTagNodeTest extends \Test\TestCase {
-
- /**
- * @var \OCP\SystemTag\ISystemTagManager|\PHPUnit\Framework\MockObject\MockObject
- */
- private $tagManager;
-
- /**
- * @var \OCP\IUser
- */
- private $user;
+ private ISystemTagManager&MockObject $tagManager;
+ private ISystemTagObjectMapper&MockObject $tagMapper;
+ private IUser&MockObject $user;
protected function setUp(): void {
parent::setUp();
- $this->tagManager = $this->getMockBuilder(ISystemTagManager::class)
- ->getMock();
- $this->user = $this->getMockBuilder(IUser::class)
- ->getMock();
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
+ $this->tagMapper = $this->createMock(ISystemTagObjectMapper::class);
+ $this->user = $this->createMock(IUser::class);
}
protected function getTagNode($isAdmin = true, $tag = null) {
if ($tag === null) {
- $tag = new SystemTag(1, 'Test', true, true);
+ $tag = new SystemTag('1', 'Test', true, true);
}
- return new \OCA\DAV\SystemTag\SystemTagNode(
+ return new SystemTagNode(
$tag,
$this->user,
$isAdmin,
- $this->tagManager
+ $this->tagManager,
+ $this->tagMapper,
);
}
- public function adminFlagProvider() {
+ public static function adminFlagProvider(): array {
return [[true], [false]];
}
- /**
- * @dataProvider adminFlagProvider
- */
- public function testGetters($isAdmin): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('adminFlagProvider')]
+ public function testGetters(bool $isAdmin): void {
$tag = new SystemTag('1', 'Test', true, true);
$node = $this->getTagNode($isAdmin, $tag);
$this->assertEquals('1', $node->getName());
@@ -69,33 +64,31 @@ class SystemTagNodeTest extends \Test\TestCase {
$this->getTagNode()->setName('2');
}
- public function tagNodeProvider() {
+ public static function tagNodeProvider(): array {
return [
// admin
[
true,
- new SystemTag(1, 'Original', true, true),
- ['Renamed', true, true]
+ new SystemTag('1', 'Original', true, true),
+ ['Renamed', true, true, null]
],
[
true,
- new SystemTag(1, 'Original', true, true),
- ['Original', false, false]
+ new SystemTag('1', 'Original', true, true),
+ ['Original', false, false, null]
],
// non-admin
[
// renaming allowed
false,
- new SystemTag(1, 'Original', true, true),
- ['Rename', true, true]
+ new SystemTag('1', 'Original', true, true),
+ ['Rename', true, true, '0082c9']
],
];
}
- /**
- * @dataProvider tagNodeProvider
- */
- public function testUpdateTag($isAdmin, ISystemTag $originalTag, $changedArgs): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('tagNodeProvider')]
+ public function testUpdateTag(bool $isAdmin, ISystemTag $originalTag, array $changedArgs): void {
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
->with($originalTag)
@@ -106,56 +99,54 @@ class SystemTagNodeTest extends \Test\TestCase {
->willReturn($originalTag->isUserAssignable() || $isAdmin);
$this->tagManager->expects($this->once())
->method('updateTag')
- ->with(1, $changedArgs[0], $changedArgs[1], $changedArgs[2]);
+ ->with(1, $changedArgs[0], $changedArgs[1], $changedArgs[2], $changedArgs[3]);
$this->getTagNode($isAdmin, $originalTag)
- ->update($changedArgs[0], $changedArgs[1], $changedArgs[2]);
+ ->update($changedArgs[0], $changedArgs[1], $changedArgs[2], $changedArgs[3]);
}
- public function tagNodeProviderPermissionException() {
+ public static function tagNodeProviderPermissionException(): array {
return [
[
// changing permissions not allowed
- new SystemTag(1, 'Original', true, true),
- ['Original', false, true],
+ new SystemTag('1', 'Original', true, true),
+ ['Original', false, true, ''],
'Sabre\DAV\Exception\Forbidden',
],
[
// changing permissions not allowed
- new SystemTag(1, 'Original', true, true),
- ['Original', true, false],
+ new SystemTag('1', 'Original', true, true),
+ ['Original', true, false, ''],
'Sabre\DAV\Exception\Forbidden',
],
[
// changing permissions not allowed
- new SystemTag(1, 'Original', true, true),
- ['Original', false, false],
+ new SystemTag('1', 'Original', true, true),
+ ['Original', false, false, ''],
'Sabre\DAV\Exception\Forbidden',
],
[
// changing non-assignable not allowed
- new SystemTag(1, 'Original', true, false),
- ['Rename', true, false],
+ new SystemTag('1', 'Original', true, false),
+ ['Rename', true, false, ''],
'Sabre\DAV\Exception\Forbidden',
],
[
// changing non-assignable not allowed
- new SystemTag(1, 'Original', true, false),
- ['Original', true, true],
+ new SystemTag('1', 'Original', true, false),
+ ['Original', true, true, ''],
'Sabre\DAV\Exception\Forbidden',
],
[
// invisible tag does not exist
- new SystemTag(1, 'Original', false, false),
- ['Rename', false, false],
+ new SystemTag('1', 'Original', false, false),
+ ['Rename', false, false, ''],
'Sabre\DAV\Exception\NotFound',
],
];
}
- /**
- * @dataProvider tagNodeProviderPermissionException
- */
- public function testUpdateTagPermissionException(ISystemTag $originalTag, $changedArgs, $expectedException = null): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('tagNodeProviderPermissionException')]
+ public function testUpdateTagPermissionException(ISystemTag $originalTag, array $changedArgs, string $expectedException): void {
$this->tagManager->expects($this->any())
->method('canUserSeeTag')
->with($originalTag)
@@ -171,7 +162,7 @@ class SystemTagNodeTest extends \Test\TestCase {
try {
$this->getTagNode(false, $originalTag)
- ->update($changedArgs[0], $changedArgs[1], $changedArgs[2]);
+ ->update($changedArgs[0], $changedArgs[1], $changedArgs[2], $changedArgs[3]);
} catch (\Exception $e) {
$thrown = $e;
}
@@ -183,7 +174,7 @@ class SystemTagNodeTest extends \Test\TestCase {
public function testUpdateTagAlreadyExists(): void {
$this->expectException(\Sabre\DAV\Exception\Conflict::class);
- $tag = new SystemTag(1, 'tag1', true, true);
+ $tag = new SystemTag('1', 'tag1', true, true);
$this->tagManager->expects($this->any())
->method('canUserSeeTag')
->with($tag)
@@ -195,15 +186,15 @@ class SystemTagNodeTest extends \Test\TestCase {
$this->tagManager->expects($this->once())
->method('updateTag')
->with(1, 'Renamed', true, true)
- ->will($this->throwException(new TagAlreadyExistsException()));
- $this->getTagNode(false, $tag)->update('Renamed', true, true);
+ ->willThrowException(new TagAlreadyExistsException());
+ $this->getTagNode(false, $tag)->update('Renamed', true, true, null);
}
public function testUpdateTagNotFound(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $tag = new SystemTag(1, 'tag1', true, true);
+ $tag = new SystemTag('1', 'tag1', true, true);
$this->tagManager->expects($this->any())
->method('canUserSeeTag')
->with($tag)
@@ -215,15 +206,13 @@ class SystemTagNodeTest extends \Test\TestCase {
$this->tagManager->expects($this->once())
->method('updateTag')
->with(1, 'Renamed', true, true)
- ->will($this->throwException(new TagNotFoundException()));
- $this->getTagNode(false, $tag)->update('Renamed', true, true);
+ ->willThrowException(new TagNotFoundException());
+ $this->getTagNode(false, $tag)->update('Renamed', true, true, null);
}
- /**
- * @dataProvider adminFlagProvider
- */
- public function testDeleteTag($isAdmin): void {
- $tag = new SystemTag(1, 'tag1', true, true);
+ #[\PHPUnit\Framework\Attributes\DataProvider('adminFlagProvider')]
+ public function testDeleteTag(bool $isAdmin): void {
+ $tag = new SystemTag('1', 'tag1', true, true);
$this->tagManager->expects($isAdmin ? $this->once() : $this->never())
->method('canUserSeeTag')
->with($tag)
@@ -237,25 +226,23 @@ class SystemTagNodeTest extends \Test\TestCase {
$this->getTagNode($isAdmin, $tag)->delete();
}
- public function tagNodeDeleteProviderPermissionException() {
+ public static function tagNodeDeleteProviderPermissionException(): array {
return [
[
// cannot delete invisible tag
- new SystemTag(1, 'Original', false, true),
+ new SystemTag('1', 'Original', false, true),
'Sabre\DAV\Exception\Forbidden',
],
[
// cannot delete non-assignable tag
- new SystemTag(1, 'Original', true, false),
+ new SystemTag('1', 'Original', true, false),
'Sabre\DAV\Exception\Forbidden',
],
];
}
- /**
- * @dataProvider tagNodeDeleteProviderPermissionException
- */
- public function testDeleteTagPermissionException(ISystemTag $tag, $expectedException): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('tagNodeDeleteProviderPermissionException')]
+ public function testDeleteTagPermissionException(ISystemTag $tag, string $expectedException): void {
$this->tagManager->expects($this->any())
->method('canUserSeeTag')
->with($tag)
@@ -271,7 +258,7 @@ class SystemTagNodeTest extends \Test\TestCase {
public function testDeleteTagNotFound(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $tag = new SystemTag(1, 'tag1', true, true);
+ $tag = new SystemTag('1', 'tag1', true, true);
$this->tagManager->expects($this->any())
->method('canUserSeeTag')
->with($tag)
@@ -279,7 +266,7 @@ class SystemTagNodeTest extends \Test\TestCase {
$this->tagManager->expects($this->once())
->method('deleteTags')
->with('1')
- ->will($this->throwException(new TagNotFoundException()));
+ ->willThrowException(new TagNotFoundException());
$this->getTagNode(true, $tag)->delete();
}
}
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php b/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php
index 51711fc1666..e0c4685c1fb 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -9,8 +10,10 @@ namespace OCA\DAV\Tests\unit\SystemTag;
use OC\SystemTag\SystemTag;
use OCA\DAV\SystemTag\SystemTagNode;
+use OCA\DAV\SystemTag\SystemTagPlugin;
use OCA\DAV\SystemTag\SystemTagsByIdCollection;
use OCA\DAV\SystemTag\SystemTagsObjectMappingCollection;
+use OCP\Files\IRootFolder;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserSession;
@@ -18,74 +21,39 @@ use OCP\SystemTag\ISystemTag;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagAlreadyExistsException;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Tree;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
class SystemTagPluginTest extends \Test\TestCase {
- public const ID_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::ID_PROPERTYNAME;
- public const DISPLAYNAME_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::DISPLAYNAME_PROPERTYNAME;
- public const USERVISIBLE_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::USERVISIBLE_PROPERTYNAME;
- public const USERASSIGNABLE_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::USERASSIGNABLE_PROPERTYNAME;
- public const CANASSIGN_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::CANASSIGN_PROPERTYNAME;
- public const GROUPS_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::GROUPS_PROPERTYNAME;
-
- /**
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var \Sabre\DAV\Tree
- */
- private $tree;
-
- /**
- * @var \OCP\SystemTag\ISystemTagManager
- */
- private $tagManager;
-
- /**
- * @var IGroupManager
- */
- private $groupManager;
-
- /**
- * @var IUserSession
- */
- private $userSession;
-
- /**
- * @var IUser
- */
- private $user;
-
- /**
- * @var \OCA\DAV\SystemTag\SystemTagPlugin
- */
- private $plugin;
-
- /**
- * @var ISystemTagObjectMapper
- */
- private $tagMapper;
+ public const ID_PROPERTYNAME = SystemTagPlugin::ID_PROPERTYNAME;
+ public const DISPLAYNAME_PROPERTYNAME = SystemTagPlugin::DISPLAYNAME_PROPERTYNAME;
+ public const USERVISIBLE_PROPERTYNAME = SystemTagPlugin::USERVISIBLE_PROPERTYNAME;
+ public const USERASSIGNABLE_PROPERTYNAME = SystemTagPlugin::USERASSIGNABLE_PROPERTYNAME;
+ public const CANASSIGN_PROPERTYNAME = SystemTagPlugin::CANASSIGN_PROPERTYNAME;
+ public const GROUPS_PROPERTYNAME = SystemTagPlugin::GROUPS_PROPERTYNAME;
+
+ private \Sabre\DAV\Server $server;
+ private \Sabre\DAV\Tree&MockObject $tree;
+ private ISystemTagManager&MockObject $tagManager;
+ private IGroupManager&MockObject $groupManager;
+ private IUserSession&MockObject $userSession;
+ private IRootFolder&MockObject $rootFolder;
+ private IUser&MockObject $user;
+ private ISystemTagObjectMapper&MockObject $tagMapper;
+ private SystemTagPlugin $plugin;
protected function setUp(): void {
parent::setUp();
- $this->tree = $this->getMockBuilder(Tree::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->tree = $this->createMock(Tree::class);
$this->server = new \Sabre\DAV\Server($this->tree);
- $this->tagManager = $this->getMockBuilder(ISystemTagManager::class)
- ->getMock();
- $this->groupManager = $this->getMockBuilder(IGroupManager::class)
- ->getMock();
- $this->user = $this->getMockBuilder(IUser::class)
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->getMock();
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
+ $this->groupManager = $this->createMock(IGroupManager::class);
+ $this->user = $this->createMock(IUser::class);
+ $this->userSession = $this->createMock(IUserSession::class);
$this->userSession
->expects($this->any())
->method('getUser')
@@ -94,22 +62,24 @@ class SystemTagPluginTest extends \Test\TestCase {
->expects($this->any())
->method('isLoggedIn')
->willReturn(true);
- $this->tagMapper = $this->getMockBuilder(ISystemTagObjectMapper::class)
- ->getMock();
- $this->plugin = new \OCA\DAV\SystemTag\SystemTagPlugin(
+ $this->tagMapper = $this->createMock(ISystemTagObjectMapper::class);
+ $this->rootFolder = $this->createMock(IRootFolder::class);
+
+ $this->plugin = new SystemTagPlugin(
$this->tagManager,
$this->groupManager,
$this->userSession,
+ $this->rootFolder,
$this->tagMapper
);
$this->plugin->initialize($this->server);
}
- public function getPropertiesDataProvider() {
+ public static function getPropertiesDataProvider(): array {
return [
[
- new SystemTag(1, 'Test', true, true),
+ new SystemTag('1', 'Test', true, true),
[],
[
self::ID_PROPERTYNAME,
@@ -127,7 +97,7 @@ class SystemTagPluginTest extends \Test\TestCase {
]
],
[
- new SystemTag(1, 'Test', true, false),
+ new SystemTag('1', 'Test', true, false),
[],
[
self::ID_PROPERTYNAME,
@@ -145,7 +115,7 @@ class SystemTagPluginTest extends \Test\TestCase {
]
],
[
- new SystemTag(1, 'Test', true, false),
+ new SystemTag('1', 'Test', true, false),
['group1', 'group2'],
[
self::ID_PROPERTYNAME,
@@ -157,7 +127,7 @@ class SystemTagPluginTest extends \Test\TestCase {
]
],
[
- new SystemTag(1, 'Test', true, true),
+ new SystemTag('1', 'Test', true, true),
['group1', 'group2'],
[
self::ID_PROPERTYNAME,
@@ -172,10 +142,8 @@ class SystemTagPluginTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider getPropertiesDataProvider
- */
- public function testGetProperties(ISystemTag $systemTag, $groups, $requestedProperties, $expectedProperties): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('getPropertiesDataProvider')]
+ public function testGetProperties(ISystemTag $systemTag, array $groups, array $requestedProperties, array $expectedProperties): void {
$this->user->expects($this->any())
->method('getUID')
->willReturn('admin');
@@ -226,7 +194,7 @@ class SystemTagPluginTest extends \Test\TestCase {
public function testGetPropertiesForbidden(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
- $systemTag = new SystemTag(1, 'Test', true, false);
+ $systemTag = new SystemTag('1', 'Test', true, false);
$requestedProperties = [
self::ID_PROPERTYNAME,
self::GROUPS_PROPERTYNAME,
@@ -265,7 +233,7 @@ class SystemTagPluginTest extends \Test\TestCase {
}
public function testUpdatePropertiesAdmin(): void {
- $systemTag = new SystemTag(1, 'Test', true, false);
+ $systemTag = new SystemTag('1', 'Test', true, false);
$this->user->expects($this->any())
->method('getUID')
->willReturn('admin');
@@ -323,7 +291,7 @@ class SystemTagPluginTest extends \Test\TestCase {
public function testUpdatePropertiesForbidden(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
- $systemTag = new SystemTag(1, 'Test', true, false);
+ $systemTag = new SystemTag('1', 'Test', true, false);
$this->user->expects($this->any())
->method('getUID')
->willReturn('admin');
@@ -364,17 +332,15 @@ class SystemTagPluginTest extends \Test\TestCase {
$propPatch->commit();
}
- public function createTagInsufficientPermissionsProvider() {
+ public static function createTagInsufficientPermissionsProvider(): array {
return [
[true, false, ''],
[false, true, ''],
[true, true, 'group1|group2'],
];
}
- /**
- * @dataProvider createTagInsufficientPermissionsProvider
- */
- public function testCreateNotAssignableTagAsRegularUser($userVisible, $userAssignable, $groups): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('createTagInsufficientPermissionsProvider')]
+ public function testCreateNotAssignableTagAsRegularUser(bool $userVisible, bool $userAssignable, string $groups): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('Not sufficient permissions');
@@ -397,9 +363,7 @@ class SystemTagPluginTest extends \Test\TestCase {
}
$requestData = json_encode($requestData);
- $node = $this->getMockBuilder(SystemTagsByIdCollection::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(SystemTagsByIdCollection::class);
$this->tagManager->expects($this->never())
->method('createTag');
$this->tagManager->expects($this->never())
@@ -410,12 +374,8 @@ class SystemTagPluginTest extends \Test\TestCase {
->with('/systemtags')
->willReturn($node);
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request->expects($this->once())
->method('getPath')
@@ -434,7 +394,7 @@ class SystemTagPluginTest extends \Test\TestCase {
}
public function testCreateTagInByIdCollectionAsRegularUser(): void {
- $systemTag = new SystemTag(1, 'Test', true, false);
+ $systemTag = new SystemTag('1', 'Test', true, false);
$requestData = json_encode([
'name' => 'Test',
@@ -442,9 +402,7 @@ class SystemTagPluginTest extends \Test\TestCase {
'userAssignable' => true,
]);
- $node = $this->getMockBuilder(SystemTagsByIdCollection::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(SystemTagsByIdCollection::class);
$this->tagManager->expects($this->once())
->method('createTag')
->with('Test', true, true)
@@ -455,12 +413,8 @@ class SystemTagPluginTest extends \Test\TestCase {
->with('/systemtags')
->willReturn($node);
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request->expects($this->once())
->method('getPath')
@@ -486,7 +440,7 @@ class SystemTagPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
- public function createTagProvider() {
+ public static function createTagProvider(): array {
return [
[true, false, ''],
[false, false, ''],
@@ -494,10 +448,8 @@ class SystemTagPluginTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider createTagProvider
- */
- public function testCreateTagInByIdCollection($userVisible, $userAssignable, $groups): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('createTagProvider')]
+ public function testCreateTagInByIdCollection(bool $userVisible, bool $userAssignable, string $groups): void {
$this->user->expects($this->once())
->method('getUID')
->willReturn('admin');
@@ -507,7 +459,7 @@ class SystemTagPluginTest extends \Test\TestCase {
->with('admin')
->willReturn(true);
- $systemTag = new SystemTag(1, 'Test', true, false);
+ $systemTag = new SystemTag('1', 'Test', true, false);
$requestData = [
'name' => 'Test',
@@ -519,9 +471,7 @@ class SystemTagPluginTest extends \Test\TestCase {
}
$requestData = json_encode($requestData);
- $node = $this->getMockBuilder(SystemTagsByIdCollection::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(SystemTagsByIdCollection::class);
$this->tagManager->expects($this->once())
->method('createTag')
->with('Test', $userVisible, $userAssignable)
@@ -542,12 +492,8 @@ class SystemTagPluginTest extends \Test\TestCase {
->with('/systemtags')
->willReturn($node);
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request->expects($this->once())
->method('getPath')
@@ -573,7 +519,7 @@ class SystemTagPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
- public function nodeClassProvider() {
+ public static function nodeClassProvider(): array {
return [
['\OCA\DAV\SystemTag\SystemTagsByIdCollection'],
['\OCA\DAV\SystemTag\SystemTagsObjectMappingCollection'],
@@ -590,7 +536,7 @@ class SystemTagPluginTest extends \Test\TestCase {
->with('admin')
->willReturn(true);
- $systemTag = new SystemTag(1, 'Test', true, false);
+ $systemTag = new SystemTag('1', 'Test', true, false);
$requestData = json_encode([
'name' => 'Test',
@@ -598,9 +544,7 @@ class SystemTagPluginTest extends \Test\TestCase {
'userAssignable' => false,
]);
- $node = $this->getMockBuilder(SystemTagsObjectMappingCollection::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(SystemTagsObjectMappingCollection::class);
$this->tagManager->expects($this->once())
->method('createTag')
@@ -616,12 +560,8 @@ class SystemTagPluginTest extends \Test\TestCase {
->method('createFile')
->with(1);
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request->expects($this->once())
->method('getPath')
@@ -651,13 +591,11 @@ class SystemTagPluginTest extends \Test\TestCase {
public function testCreateTagToUnknownNode(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $node = $this->getMockBuilder(SystemTagsObjectMappingCollection::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(SystemTagsObjectMappingCollection::class);
$this->tree->expects($this->any())
->method('getNodeForPath')
- ->will($this->throwException(new \Sabre\DAV\Exception\NotFound()));
+ ->willThrowException(new \Sabre\DAV\Exception\NotFound());
$this->tagManager->expects($this->never())
->method('createTag');
@@ -665,12 +603,8 @@ class SystemTagPluginTest extends \Test\TestCase {
$node->expects($this->never())
->method('createFile');
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request->expects($this->once())
->method('getPath')
@@ -679,10 +613,8 @@ class SystemTagPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
- /**
- * @dataProvider nodeClassProvider
- */
- public function testCreateTagConflict($nodeClass): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('nodeClassProvider')]
+ public function testCreateTagConflict(string $nodeClass): void {
$this->expectException(\Sabre\DAV\Exception\Conflict::class);
$this->user->expects($this->once())
@@ -700,25 +632,19 @@ class SystemTagPluginTest extends \Test\TestCase {
'userAssignable' => false,
]);
- $node = $this->getMockBuilder($nodeClass)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock($nodeClass);
$this->tagManager->expects($this->once())
->method('createTag')
->with('Test', true, false)
- ->will($this->throwException(new TagAlreadyExistsException('Tag already exists')));
+ ->willThrowException(new TagAlreadyExistsException('Tag already exists'));
$this->tree->expects($this->any())
->method('getNodeForPath')
->with('/systemtags')
->willReturn($node);
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request->expects($this->once())
->method('getPath')
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php b/apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php
index db55d82adc9..8f7848452fe 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,67 +9,66 @@
namespace OCA\DAV\Tests\unit\SystemTag;
use OC\SystemTag\SystemTag;
+use OCA\DAV\SystemTag\SystemTagsByIdCollection;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserSession;
use OCP\SystemTag\ISystemTagManager;
+use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagNotFoundException;
+use PHPUnit\Framework\MockObject\MockObject;
class SystemTagsByIdCollectionTest extends \Test\TestCase {
-
- /**
- * @var \OCP\SystemTag\ISystemTagManager
- */
- private $tagManager;
-
- /**
- * @var \OCP\IUser
- */
- private $user;
+ private ISystemTagManager&MockObject $tagManager;
+ private IUser&MockObject $user;
protected function setUp(): void {
parent::setUp();
- $this->tagManager = $this->getMockBuilder(ISystemTagManager::class)
- ->getMock();
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
}
- public function getNode($isAdmin = true) {
- $this->user = $this->getMockBuilder(IUser::class)
- ->getMock();
+ public function getNode(bool $isAdmin = true) {
+ $this->user = $this->createMock(IUser::class);
$this->user->expects($this->any())
->method('getUID')
->willReturn('testuser');
- $userSession = $this->getMockBuilder(IUserSession::class)
- ->getMock();
+
+ /** @var IUserSession&MockObject */
+ $userSession = $this->createMock(IUserSession::class);
$userSession->expects($this->any())
->method('getUser')
->willReturn($this->user);
- $groupManager = $this->getMockBuilder(IGroupManager::class)
- ->getMock();
+
+ /** @var IGroupManager&MockObject */
+ $groupManager = $this->createMock(IGroupManager::class);
$groupManager->expects($this->any())
->method('isAdmin')
->with('testuser')
->willReturn($isAdmin);
- return new \OCA\DAV\SystemTag\SystemTagsByIdCollection(
+
+ /** @var ISystemTagObjectMapper&MockObject */
+ $tagMapper = $this->createMock(ISystemTagObjectMapper::class);
+ return new SystemTagsByIdCollection(
$this->tagManager,
$userSession,
- $groupManager
+ $groupManager,
+ $tagMapper,
);
}
- public function adminFlagProvider() {
+ public static function adminFlagProvider(): array {
return [[true], [false]];
}
-
+
public function testForbiddenCreateFile(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->getNode()->createFile('555');
}
-
+
public function testForbiddenCreateDirectory(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
@@ -76,7 +76,7 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
}
public function testGetChild(): void {
- $tag = new SystemTag(123, 'Test', true, false);
+ $tag = new SystemTag('123', 'Test', true, false);
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
->with($tag)
@@ -94,35 +94,35 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
$this->assertEquals($tag, $childNode->getSystemTag());
}
-
+
public function testGetChildInvalidName(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->tagManager->expects($this->once())
->method('getTagsByIds')
->with(['invalid'])
- ->will($this->throwException(new \InvalidArgumentException()));
+ ->willThrowException(new \InvalidArgumentException());
$this->getNode()->getChild('invalid');
}
-
+
public function testGetChildNotFound(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
$this->tagManager->expects($this->once())
->method('getTagsByIds')
->with(['444'])
- ->will($this->throwException(new TagNotFoundException()));
+ ->willThrowException(new TagNotFoundException());
$this->getNode()->getChild('444');
}
-
+
public function testGetChildUserNotVisible(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $tag = new SystemTag(123, 'Test', false, false);
+ $tag = new SystemTag('123', 'Test', false, false);
$this->tagManager->expects($this->once())
->method('getTagsByIds')
@@ -133,8 +133,8 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
}
public function testGetChildrenAdmin(): void {
- $tag1 = new SystemTag(123, 'One', true, false);
- $tag2 = new SystemTag(456, 'Two', true, true);
+ $tag1 = new SystemTag('123', 'One', true, false);
+ $tag2 = new SystemTag('456', 'Two', true, true);
$this->tagManager->expects($this->once())
->method('getAllTags')
@@ -152,8 +152,8 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
}
public function testGetChildrenNonAdmin(): void {
- $tag1 = new SystemTag(123, 'One', true, false);
- $tag2 = new SystemTag(456, 'Two', true, true);
+ $tag1 = new SystemTag('123', 'One', true, false);
+ $tag2 = new SystemTag('456', 'Two', true, true);
$this->tagManager->expects($this->once())
->method('getAllTags')
@@ -178,18 +178,16 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
$this->assertCount(0, $this->getNode()->getChildren());
}
- public function childExistsProvider() {
+ public static function childExistsProvider(): array {
return [
[true, true],
[false, false],
];
}
- /**
- * @dataProvider childExistsProvider
- */
- public function testChildExists($userVisible, $expectedResult): void {
- $tag = new SystemTag(123, 'One', $userVisible, false);
+ #[\PHPUnit\Framework\Attributes\DataProvider('childExistsProvider')]
+ public function testChildExists(bool $userVisible, bool $expectedResult): void {
+ $tag = new SystemTag('123', 'One', $userVisible, false);
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
->with($tag)
@@ -207,19 +205,19 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
$this->tagManager->expects($this->once())
->method('getTagsByIds')
->with(['123'])
- ->will($this->throwException(new TagNotFoundException()));
+ ->willThrowException(new TagNotFoundException());
$this->assertFalse($this->getNode()->childExists('123'));
}
-
+
public function testChildExistsBadRequest(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->tagManager->expects($this->once())
->method('getTagsByIds')
->with(['invalid'])
- ->will($this->throwException(new \InvalidArgumentException()));
+ ->willThrowException(new \InvalidArgumentException());
$this->getNode()->childExists('invalid');
}
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php b/apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php
index c2e62f73828..5aea1242e2a 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,31 +9,29 @@
namespace OCA\DAV\Tests\unit\SystemTag;
use OC\SystemTag\SystemTag;
+use OCA\DAV\SystemTag\SystemTagsObjectMappingCollection;
use OCP\IUser;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagNotFoundException;
+use PHPUnit\Framework\MockObject\MockObject;
class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
- private ISystemTagManager $tagManager;
- private ISystemTagObjectMapper $tagMapper;
- private IUser $user;
+ private ISystemTagManager&MockObject $tagManager;
+ private ISystemTagObjectMapper&MockObject $tagMapper;
+ private IUser&MockObject $user;
protected function setUp(): void {
parent::setUp();
- $this->tagManager = $this->getMockBuilder(ISystemTagManager::class)
- ->getMock();
- $this->tagMapper = $this->getMockBuilder(ISystemTagObjectMapper::class)
- ->getMock();
-
- $this->user = $this->getMockBuilder(IUser::class)
- ->getMock();
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
+ $this->tagMapper = $this->createMock(ISystemTagObjectMapper::class);
+ $this->user = $this->createMock(IUser::class);
}
- public function getNode(array $writableNodeIds = []) {
- return new \OCA\DAV\SystemTag\SystemTagsObjectMappingCollection(
- 111,
+ public function getNode(array $writableNodeIds = []): SystemTagsObjectMappingCollection {
+ return new SystemTagsObjectMappingCollection(
+ '111',
'files',
$this->user,
$this->tagManager,
@@ -85,7 +84,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
$this->getNode()->createFile('555');
}
- public function permissionsProvider() {
+ public static function permissionsProvider(): array {
return [
// invisible, tag does not exist for user
[false, true, '\Sabre\DAV\Exception\PreconditionFailed'],
@@ -94,10 +93,8 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider permissionsProvider
- */
- public function testAssignTagNoPermission($userVisible, $userAssignable, $expectedException): void {
+ #[\PHPUnit\Framework\Attributes\DataProvider('permissionsProvider')]
+ public function testAssignTagNoPermission(bool $userVisible, bool $userAssignable, string $expectedException): void {
$tag = new SystemTag('1', 'Test', $userVisible, $userAssignable);
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
@@ -132,7 +129,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
$this->tagManager->expects($this->once())
->method('getTagsByIds')
->with(['555'])
- ->will($this->throwException(new TagNotFoundException()));
+ ->willThrowException(new TagNotFoundException());
$this->getNode()->createFile('555');
}
@@ -145,7 +142,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
}
public function testGetChild(): void {
- $tag = new SystemTag(555, 'TheTag', true, false);
+ $tag = new SystemTag('555', 'TheTag', true, false);
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
->with($tag)
@@ -171,7 +168,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
public function testGetChildNonVisible(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $tag = new SystemTag(555, 'TheTag', false, false);
+ $tag = new SystemTag('555', 'TheTag', false, false);
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
->with($tag)
@@ -209,7 +206,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
$this->tagMapper->expects($this->once())
->method('haveTag')
->with([111], 'files', 'badid')
- ->will($this->throwException(new \InvalidArgumentException()));
+ ->willThrowException(new \InvalidArgumentException());
$this->getNode()->getChild('badid');
}
@@ -221,15 +218,15 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
$this->tagMapper->expects($this->once())
->method('haveTag')
->with([111], 'files', '777')
- ->will($this->throwException(new TagNotFoundException()));
+ ->willThrowException(new TagNotFoundException());
$this->getNode()->getChild('777');
}
public function testGetChildren(): void {
- $tag1 = new SystemTag(555, 'TagOne', true, false);
- $tag2 = new SystemTag(556, 'TagTwo', true, true);
- $tag3 = new SystemTag(557, 'InvisibleTag', false, true);
+ $tag1 = new SystemTag('555', 'TagOne', true, false);
+ $tag2 = new SystemTag('556', 'TagTwo', true, true);
+ $tag3 = new SystemTag('557', 'InvisibleTag', false, true);
$this->tagMapper->expects($this->once())
->method('getTagIdsForObjects')
@@ -264,7 +261,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
}
public function testChildExistsWithVisibleTag(): void {
- $tag = new SystemTag(555, 'TagOne', true, false);
+ $tag = new SystemTag('555', 'TagOne', true, false);
$this->tagMapper->expects($this->once())
->method('haveTag')
@@ -285,7 +282,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
}
public function testChildExistsWithInvisibleTag(): void {
- $tag = new SystemTag(555, 'TagOne', false, false);
+ $tag = new SystemTag('555', 'TagOne', false, false);
$this->tagMapper->expects($this->once())
->method('haveTag')
@@ -313,7 +310,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
$this->tagMapper->expects($this->once())
->method('haveTag')
->with([111], 'files', '555')
- ->will($this->throwException(new TagNotFoundException()));
+ ->willThrowException(new TagNotFoundException());
$this->assertFalse($this->getNode()->childExists('555'));
}
@@ -325,7 +322,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
$this->tagMapper->expects($this->once())
->method('haveTag')
->with([111], 'files', '555')
- ->will($this->throwException(new \InvalidArgumentException()));
+ ->willThrowException(new \InvalidArgumentException());
$this->getNode()->childExists('555');
}
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php b/apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php
index b202f340e32..301eb528436 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -7,66 +8,47 @@
*/
namespace OCA\DAV\Tests\unit\SystemTag;
+use OCA\DAV\SystemTag\SystemTagsObjectTypeCollection;
use OCP\Files\Folder;
+use OCP\Files\Node;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserSession;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
+use PHPUnit\Framework\MockObject\MockObject;
class SystemTagsObjectTypeCollectionTest extends \Test\TestCase {
-
- /**
- * @var \OCA\DAV\SystemTag\SystemTagsObjectTypeCollection
- */
- private $node;
-
- /**
- * @var \OCP\SystemTag\ISystemTagManager
- */
- private $tagManager;
-
- /**
- * @var \OCP\SystemTag\ISystemTagObjectMapper
- */
- private $tagMapper;
-
- /**
- * @var \OCP\Files\Folder
- */
- private $userFolder;
+ private ISystemTagManager&MockObject $tagManager;
+ private ISystemTagObjectMapper&MockObject $tagMapper;
+ private Folder&MockObject $userFolder;
+ private SystemTagsObjectTypeCollection $node;
protected function setUp(): void {
parent::setUp();
- $this->tagManager = $this->getMockBuilder(ISystemTagManager::class)
- ->getMock();
- $this->tagMapper = $this->getMockBuilder(ISystemTagObjectMapper::class)
- ->getMock();
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
+ $this->tagMapper = $this->createMock(ISystemTagObjectMapper::class);
- $user = $this->getMockBuilder(IUser::class)
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('testuser');
- $userSession = $this->getMockBuilder(IUserSession::class)
- ->getMock();
+ $userSession = $this->createMock(IUserSession::class);
$userSession->expects($this->any())
->method('getUser')
->willReturn($user);
- $groupManager = $this->getMockBuilder(IGroupManager::class)
- ->getMock();
+ $groupManager = $this->createMock(IGroupManager::class);
$groupManager->expects($this->any())
->method('isAdmin')
->with('testuser')
->willReturn(true);
- $this->userFolder = $this->getMockBuilder(Folder::class)
- ->getMock();
+ $this->userFolder = $this->createMock(Folder::class);
$userFolder = $this->userFolder;
$closure = function ($name) use ($userFolder) {
- $node = $userFolder->getFirstNodeById(intval($name));
+ $node = $userFolder->getFirstNodeById((int)$name);
return $node !== null;
};
$writeAccessClosure = function ($name) use ($userFolder) {
@@ -79,7 +61,7 @@ class SystemTagsObjectTypeCollectionTest extends \Test\TestCase {
return false;
};
- $this->node = new \OCA\DAV\SystemTag\SystemTagsObjectTypeCollection(
+ $this->node = new SystemTagsObjectTypeCollection(
'files',
$this->tagManager,
$this->tagMapper,
@@ -108,7 +90,7 @@ class SystemTagsObjectTypeCollectionTest extends \Test\TestCase {
$this->userFolder->expects($this->once())
->method('getFirstNodeById')
->with('555')
- ->willReturn($this->createMock(\OCP\Files\Node::class));
+ ->willReturn($this->createMock(Node::class));
$childNode = $this->node->getChild('555');
$this->assertInstanceOf('\OCA\DAV\SystemTag\SystemTagsObjectMappingCollection', $childNode);
@@ -137,7 +119,7 @@ class SystemTagsObjectTypeCollectionTest extends \Test\TestCase {
$this->userFolder->expects($this->once())
->method('getFirstNodeById')
->with('123')
- ->willReturn($this->createMock(\OCP\Files\Node::class));
+ ->willReturn($this->createMock(Node::class));
$this->assertTrue($this->node->childExists('123'));
}
diff --git a/apps/dav/tests/unit/Upload/AssemblyStreamTest.php b/apps/dav/tests/unit/Upload/AssemblyStreamTest.php
index 6c380fa3191..ec5d0a9ab5b 100644
--- a/apps/dav/tests/unit/Upload/AssemblyStreamTest.php
+++ b/apps/dav/tests/unit/Upload/AssemblyStreamTest.php
@@ -7,39 +7,51 @@
*/
namespace OCA\DAV\Tests\unit\Upload;
+use OCA\DAV\Upload\AssemblyStream;
use Sabre\DAV\File;
class AssemblyStreamTest extends \Test\TestCase {
- /**
- * @dataProvider providesNodes()
- */
- public function testGetContents($expected, $nodes): void {
- $stream = \OCA\DAV\Upload\AssemblyStream::wrap($nodes);
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesNodes')]
+ public function testGetContents(string $expected, array $nodeData): void {
+ $nodes = [];
+ foreach ($nodeData as $data) {
+ $nodes[] = $this->buildNode(...$data);
+ }
+ $stream = AssemblyStream::wrap($nodes);
$content = stream_get_contents($stream);
$this->assertEquals($expected, $content);
}
- /**
- * @dataProvider providesNodes()
- */
- public function testGetContentsFread($expected, $nodes): void {
- $stream = \OCA\DAV\Upload\AssemblyStream::wrap($nodes);
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesNodes')]
+ public function testGetContentsFread(string $expected, array $nodeData, int $chunkLength = 3): void {
+ $nodes = [];
+ foreach ($nodeData as $data) {
+ $nodes[] = $this->buildNode(...$data);
+ }
+ $stream = AssemblyStream::wrap($nodes);
$content = '';
while (!feof($stream)) {
- $content .= fread($stream, 3);
+ $chunk = fread($stream, $chunkLength);
+ $content .= $chunk;
+ if ($chunkLength !== 3) {
+ $this->assertEquals($chunkLength, strlen($chunk));
+ }
}
$this->assertEquals($expected, $content);
}
- /**
- * @dataProvider providesNodes()
- */
- public function testSeek($expected, $nodes): void {
- $stream = \OCA\DAV\Upload\AssemblyStream::wrap($nodes);
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesNodes')]
+ public function testSeek(string $expected, array $nodeData): void {
+ $nodes = [];
+ foreach ($nodeData as $data) {
+ $nodes[] = $this->buildNode(...$data);
+ }
+
+ $stream = AssemblyStream::wrap($nodes);
$offset = floor(strlen($expected) * 0.6);
if (fseek($stream, $offset) === -1) {
@@ -50,63 +62,75 @@ class AssemblyStreamTest extends \Test\TestCase {
$this->assertEquals(substr($expected, $offset), $content);
}
- public function providesNodes() {
- $data8k = $this->makeData(8192);
- $dataLess8k = $this->makeData(8191);
+ public static function providesNodes(): array {
+ $data8k = self::makeData(8192);
+ $dataLess8k = self::makeData(8191);
$tonofnodes = [];
- $tonofdata = "";
+ $tonofdata = '';
for ($i = 0; $i < 101; $i++) {
- $thisdata = rand(0, 100); // variable length and content
+ $thisdata = random_int(0, 100); // variable length and content
$tonofdata .= $thisdata;
- array_push($tonofnodes, $this->buildNode($i, $thisdata));
+ $tonofnodes[] = [(string)$i, (string)$thisdata];
}
return[
'one node zero bytes' => [
'', [
- $this->buildNode('0', '')
+ ['0', ''],
]],
'one node only' => [
'1234567890', [
- $this->buildNode('0', '1234567890')
+ ['0', '1234567890'],
]],
'one node buffer boundary' => [
$data8k, [
- $this->buildNode('0', $data8k)
+ ['0', $data8k],
]],
'two nodes' => [
'1234567890', [
- $this->buildNode('1', '67890'),
- $this->buildNode('0', '12345')
+ ['1', '67890'],
+ ['0', '12345'],
]],
'two nodes end on buffer boundary' => [
$data8k . $data8k, [
- $this->buildNode('1', $data8k),
- $this->buildNode('0', $data8k)
+ ['1', $data8k],
+ ['0', $data8k],
]],
'two nodes with one on buffer boundary' => [
$data8k . $dataLess8k, [
- $this->buildNode('1', $dataLess8k),
- $this->buildNode('0', $data8k)
+ ['1', $dataLess8k],
+ ['0', $data8k],
]],
'two nodes on buffer boundary plus one byte' => [
$data8k . 'X' . $data8k, [
- $this->buildNode('1', $data8k),
- $this->buildNode('0', $data8k . 'X')
+ ['1', $data8k],
+ ['0', $data8k . 'X'],
]],
'two nodes on buffer boundary plus one byte at the end' => [
$data8k . $data8k . 'X', [
- $this->buildNode('1', $data8k . 'X'),
- $this->buildNode('0', $data8k)
+ ['1', $data8k . 'X'],
+ ['0', $data8k],
]],
'a ton of nodes' => [
$tonofdata, $tonofnodes
- ]
+ ],
+ 'one read over multiple nodes' => [
+ '1234567890', [
+ ['0', '1234'],
+ ['1', '5678'],
+ ['2', '90'],
+ ], 10],
+ 'two reads over multiple nodes' => [
+ '1234567890', [
+ ['0', '1234'],
+ ['1', '5678'],
+ ['2', '90'],
+ ], 5],
];
}
- private function makeData($count) {
+ private static function makeData(int $count): string {
$data = '';
$base = '1234567890';
$j = 0;
@@ -120,10 +144,10 @@ class AssemblyStreamTest extends \Test\TestCase {
return $data;
}
- private function buildNode($name, $data) {
+ private function buildNode(string $name, string $data) {
$node = $this->getMockBuilder(File::class)
- ->setMethods(['getName', 'get', 'getSize'])
- ->getMockForAbstractClass();
+ ->onlyMethods(['getName', 'get', 'getSize'])
+ ->getMock();
$node->expects($this->any())
->method('getName')
diff --git a/apps/dav/tests/unit/Upload/ChunkingPluginTest.php b/apps/dav/tests/unit/Upload/ChunkingPluginTest.php
index 87feebf5d09..00ed7657dd3 100644
--- a/apps/dav/tests/unit/Upload/ChunkingPluginTest.php
+++ b/apps/dav/tests/unit/Upload/ChunkingPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2017 ownCloud GmbH
@@ -10,40 +11,24 @@ namespace OCA\DAV\Tests\unit\Upload;
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Upload\ChunkingPlugin;
use OCA\DAV\Upload\FutureFile;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\NotFound;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
use Test\TestCase;
class ChunkingPluginTest extends TestCase {
- /**
- * @var \Sabre\DAV\Server | \PHPUnit\Framework\MockObject\MockObject
- */
- private $server;
-
- /**
- * @var \Sabre\DAV\Tree | \PHPUnit\Framework\MockObject\MockObject
- */
- private $tree;
-
- /**
- * @var ChunkingPlugin
- */
- private $plugin;
- /** @var RequestInterface | \PHPUnit\Framework\MockObject\MockObject */
- private $request;
- /** @var ResponseInterface | \PHPUnit\Framework\MockObject\MockObject */
- private $response;
+ private \Sabre\DAV\Server&MockObject $server;
+ private \Sabre\DAV\Tree&MockObject $tree;
+ private ChunkingPlugin $plugin;
+ private RequestInterface&MockObject $request;
+ private ResponseInterface&MockObject $response;
protected function setUp(): void {
parent::setUp();
- $this->server = $this->getMockBuilder('\Sabre\DAV\Server')
- ->disableOriginalConstructor()
- ->getMock();
- $this->tree = $this->getMockBuilder('\Sabre\DAV\Tree')
- ->disableOriginalConstructor()
- ->getMock();
+ $this->server = $this->createMock('\Sabre\DAV\Server');
+ $this->tree = $this->createMock('\Sabre\DAV\Tree');
$this->server->tree = $this->tree;
$this->plugin = new ChunkingPlugin();
@@ -78,14 +63,10 @@ class ChunkingPluginTest extends TestCase {
$this->tree->expects($this->exactly(2))
->method('getNodeForPath')
- ->withConsecutive(
- ['source'],
- ['target'],
- )
- ->willReturnOnConsecutiveCalls(
- $sourceNode,
- $targetNode,
- );
+ ->willReturnMap([
+ ['source', $sourceNode],
+ ['target', $targetNode],
+ ]);
$this->response->expects($this->never())
->method('setStatus');
@@ -98,16 +79,20 @@ class ChunkingPluginTest extends TestCase {
->method('getSize')
->willReturn(4);
+ $calls = [
+ ['source', $sourceNode],
+ ['target', new NotFound()],
+ ];
$this->tree->expects($this->exactly(2))
->method('getNodeForPath')
- ->withConsecutive(
- ['source'],
- ['target'],
- )
- ->willReturnOnConsecutiveCalls(
- $sourceNode,
- $this->throwException(new NotFound()),
- );
+ ->willReturnCallback(function (string $path) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertSame($expected[0], $path);
+ if ($expected[1] instanceof \Throwable) {
+ throw $expected[1];
+ }
+ return $expected[1];
+ });
$this->tree->expects($this->any())
->method('nodeExists')
->with('target')
@@ -132,17 +117,21 @@ class ChunkingPluginTest extends TestCase {
->method('getSize')
->willReturn(4);
-
+ $calls = [
+ ['source', $sourceNode],
+ ['target', new NotFound()],
+ ];
$this->tree->expects($this->exactly(2))
->method('getNodeForPath')
- ->withConsecutive(
- ['source'],
- ['target'],
- )
- ->willReturnOnConsecutiveCalls(
- $sourceNode,
- $this->throwException(new NotFound()),
- );
+ ->willReturnCallback(function (string $path) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertSame($expected[0], $path);
+ if ($expected[1] instanceof \Throwable) {
+ throw $expected[1];
+ }
+ return $expected[1];
+ });
+
$this->tree->expects($this->any())
->method('nodeExists')
->with('target')
@@ -175,17 +164,21 @@ class ChunkingPluginTest extends TestCase {
->method('getSize')
->willReturn(3);
-
+ $calls = [
+ ['source', $sourceNode],
+ ['target', new NotFound()],
+ ];
$this->tree->expects($this->exactly(2))
->method('getNodeForPath')
- ->withConsecutive(
- ['source'],
- ['target'],
- )
- ->willReturnOnConsecutiveCalls(
- $sourceNode,
- $this->throwException(new NotFound()),
- );
+ ->willReturnCallback(function (string $path) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertSame($expected[0], $path);
+ if ($expected[1] instanceof \Throwable) {
+ throw $expected[1];
+ }
+ return $expected[1];
+ });
+
$this->request->expects($this->once())
->method('getHeader')
->with('OC-Total-Length')
diff --git a/apps/dav/tests/unit/Upload/FutureFileTest.php b/apps/dav/tests/unit/Upload/FutureFileTest.php
index 9ec455a9595..1409df937c0 100644
--- a/apps/dav/tests/unit/Upload/FutureFileTest.php
+++ b/apps/dav/tests/unit/Upload/FutureFileTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,6 +9,7 @@
namespace OCA\DAV\Tests\unit\Upload;
use OCA\DAV\Connector\Sabre\Directory;
+use OCA\DAV\Upload\FutureFile;
class FutureFileTest extends \Test\TestCase {
public function testGetContentType(): void {
@@ -44,17 +46,17 @@ class FutureFileTest extends \Test\TestCase {
public function testDelete(): void {
$d = $this->getMockBuilder(Directory::class)
->disableOriginalConstructor()
- ->setMethods(['delete'])
+ ->onlyMethods(['delete'])
->getMock();
$d->expects($this->once())
->method('delete');
- $f = new \OCA\DAV\Upload\FutureFile($d, 'foo.txt');
+ $f = new FutureFile($d, 'foo.txt');
$f->delete();
}
-
+
public function testPut(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
@@ -62,7 +64,7 @@ class FutureFileTest extends \Test\TestCase {
$f->put('');
}
-
+
public function testSetName(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
@@ -70,13 +72,10 @@ class FutureFileTest extends \Test\TestCase {
$f->setName('');
}
- /**
- * @return \OCA\DAV\Upload\FutureFile
- */
- private function mockFutureFile() {
+ private function mockFutureFile(): FutureFile {
$d = $this->getMockBuilder(Directory::class)
->disableOriginalConstructor()
- ->setMethods(['getETag', 'getLastModified', 'getChildren'])
+ ->onlyMethods(['getETag', 'getLastModified', 'getChildren'])
->getMock();
$d->expects($this->any())
@@ -91,6 +90,6 @@ class FutureFileTest extends \Test\TestCase {
->method('getChildren')
->willReturn([]);
- return new \OCA\DAV\Upload\FutureFile($d, 'foo.txt');
+ return new FutureFile($d, 'foo.txt');
}
}
diff --git a/apps/dav/tests/unit/Upload/UploadAutoMkcolPluginTest.php b/apps/dav/tests/unit/Upload/UploadAutoMkcolPluginTest.php
new file mode 100644
index 00000000000..baae839c8da
--- /dev/null
+++ b/apps/dav/tests/unit/Upload/UploadAutoMkcolPluginTest.php
@@ -0,0 +1,133 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\Tests\unit\Upload;
+
+use Generator;
+use OCA\DAV\Upload\UploadAutoMkcolPlugin;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\DAV\ICollection;
+use Sabre\DAV\INode;
+use Sabre\DAV\Server;
+use Sabre\DAV\Tree;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use Test\TestCase;
+
+class UploadAutoMkcolPluginTest extends TestCase {
+
+ private Tree&MockObject $tree;
+ private RequestInterface&MockObject $request;
+ private ResponseInterface&MockObject $response;
+
+ public static function dataMissingHeaderShouldReturnTrue(): Generator {
+ yield 'missing X-NC-WebDAV-Auto-Mkcol header' => [null];
+ yield 'empty X-NC-WebDAV-Auto-Mkcol header' => [''];
+ yield 'invalid X-NC-WebDAV-Auto-Mkcol header' => ['enable'];
+ }
+
+ public function testBeforeMethodWithRootNodeNotAnICollectionShouldReturnTrue(): void {
+ $this->request->method('getHeader')->willReturn('1');
+ $this->request->expects(self::once())
+ ->method('getPath')
+ ->willReturn('/non-relevant/path.txt');
+ $this->tree->expects(self::once())
+ ->method('nodeExists')
+ ->with('/non-relevant')
+ ->willReturn(false);
+
+ $mockNode = $this->getMockBuilder(INode::class);
+ $this->tree->expects(self::once())
+ ->method('getNodeForPath')
+ ->willReturn($mockNode);
+
+ $return = $this->plugin->beforeMethod($this->request, $this->response);
+ $this->assertTrue($return);
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataMissingHeaderShouldReturnTrue')]
+ public function testBeforeMethodWithMissingHeaderShouldReturnTrue(?string $header): void {
+ $this->request->expects(self::once())
+ ->method('getHeader')
+ ->with('X-NC-WebDAV-Auto-Mkcol')
+ ->willReturn($header);
+
+ $this->request->expects(self::never())
+ ->method('getPath');
+
+ $return = $this->plugin->beforeMethod($this->request, $this->response);
+ self::assertTrue($return);
+ }
+
+ public function testBeforeMethodWithExistingPathShouldReturnTrue(): void {
+ $this->request->method('getHeader')->willReturn('1');
+ $this->request->expects(self::once())
+ ->method('getPath')
+ ->willReturn('/files/user/deep/image.jpg');
+ $this->tree->expects(self::once())
+ ->method('nodeExists')
+ ->with('/files/user/deep')
+ ->willReturn(true);
+
+ $this->tree->expects(self::never())
+ ->method('getNodeForPath');
+
+ $return = $this->plugin->beforeMethod($this->request, $this->response);
+ self::assertTrue($return);
+ }
+
+ public function testBeforeMethodShouldSucceed(): void {
+ $this->request->method('getHeader')->willReturn('1');
+ $this->request->expects(self::once())
+ ->method('getPath')
+ ->willReturn('/files/user/my/deep/path/image.jpg');
+ $this->tree->expects(self::once())
+ ->method('nodeExists')
+ ->with('/files/user/my/deep/path')
+ ->willReturn(false);
+
+ $mockNode = $this->createMock(ICollection::class);
+ $this->tree->expects(self::once())
+ ->method('getNodeForPath')
+ ->with('/files')
+ ->willReturn($mockNode);
+ $mockNode->expects(self::exactly(4))
+ ->method('childExists')
+ ->willReturnMap([
+ ['user', true],
+ ['my', true],
+ ['deep', false],
+ ['path', false],
+ ]);
+ $mockNode->expects(self::exactly(2))
+ ->method('createDirectory');
+ $mockNode->expects(self::exactly(4))
+ ->method('getChild')
+ ->willReturn($mockNode);
+
+ $return = $this->plugin->beforeMethod($this->request, $this->response);
+ self::assertTrue($return);
+ }
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $server = $this->createMock(Server::class);
+ $this->tree = $this->createMock(Tree::class);
+
+ $server->tree = $this->tree;
+ $this->plugin = new UploadAutoMkcolPlugin();
+
+ $this->request = $this->createMock(RequestInterface::class);
+ $this->response = $this->createMock(ResponseInterface::class);
+ $server->httpRequest = $this->request;
+ $server->httpResponse = $this->response;
+
+ $this->plugin->initialize($server);
+ }
+}
diff --git a/apps/dav/tests/unit/bootstrap.php b/apps/dav/tests/unit/bootstrap.php
index 61dbda35ae2..ee76bb6677b 100644
--- a/apps/dav/tests/unit/bootstrap.php
+++ b/apps/dav/tests/unit/bootstrap.php
@@ -1,18 +1,21 @@
<?php
+declare(strict_types=1);
+
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
+
+use OCP\App\IAppManager;
+use OCP\Server;
+
if (!defined('PHPUNIT_RUN')) {
define('PHPUNIT_RUN', 1);
}
-require_once __DIR__.'/../../../../lib/base.php';
-
-\OC::$composerAutoloader->addPsr4('Test\\', OC::$SERVERROOT . '/tests/lib/', true);
-
-\OC_App::loadApp('dav');
+require_once __DIR__ . '/../../../../lib/base.php';
+require_once __DIR__ . '/../../../../tests/autoload.php';
-OC_Hook::clear();
+Server::get(IAppManager::class)->loadApp('dav');
diff --git a/apps/dav/tests/unit/phpunit.xml b/apps/dav/tests/unit/phpunit.xml
index 0d08d8fe5d6..c85d07c6fcb 100644
--- a/apps/dav/tests/unit/phpunit.xml
+++ b/apps/dav/tests/unit/phpunit.xml
@@ -26,4 +26,3 @@
<log type="coverage-clover" target="./clover.xml"/>
</logging>
</phpunit>
-
diff --git a/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-1.ics b/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-1.ics
new file mode 100644
index 00000000000..e76ac3c9b2f
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-1.ics
@@ -0,0 +1,17 @@
+BEGIN:VCALENDAR
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+VERSION:2.0
+BEGIN:VEVENT
+CREATED:20240507T105946Z
+LAST-MODIFIED:20240507T121113Z
+DTSTAMP:20240507T121113Z
+UID:07514c7b-1014-425c-b1b8-2c35ab0eea1d
+SUMMARY:Event A
+RRULE:FREQ=YEARLY
+DTSTART;TZID=Europe/Berlin:20240101T101500
+DTEND;TZID=Europe/Berlin:20240101T111500
+TRANSP:OPAQUE
+X-MOZ-GENERATION:4
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-2.ics b/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-2.ics
new file mode 100644
index 00000000000..fe948321d51
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-2.ics
@@ -0,0 +1,17 @@
+BEGIN:VCALENDAR
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+VERSION:2.0
+BEGIN:VEVENT
+CREATED:20240507T110122Z
+LAST-MODIFIED:20240507T121120Z
+DTSTAMP:20240507T121120Z
+UID:67cf8134-ff10-49a7-913d-acfeda463db6
+SUMMARY:Event B
+RRULE:FREQ=YEARLY
+DTSTART;TZID=Europe/Berlin:20240101T123000
+DTEND;TZID=Europe/Berlin:20240101T133000
+TRANSP:OPAQUE
+X-MOZ-GENERATION:4
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-3.ics b/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-3.ics
new file mode 100644
index 00000000000..de7765b28d2
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-3.ics
@@ -0,0 +1,17 @@
+BEGIN:VCALENDAR
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+VERSION:2.0
+BEGIN:VEVENT
+CREATED:20240507T120352Z
+LAST-MODIFIED:20240507T121128Z
+DTSTAMP:20240507T121128Z
+UID:59090ca1-e52b-447f-8e08-491d1da729fa
+SUMMARY:Event C
+RRULE:FREQ=YEARLY
+DTSTART;TZID=Europe/Berlin:20240101T151000
+DTEND;TZID=Europe/Berlin:20240101T161000
+TRANSP:OPAQUE
+X-MOZ-GENERATION:2
+SEQUENCE:1
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-4.ics b/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-4.ics
new file mode 100644
index 00000000000..b4d2f752c0a
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-4.ics
@@ -0,0 +1,17 @@
+BEGIN:VCALENDAR
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+VERSION:2.0
+BEGIN:VEVENT
+CREATED:20240507T120414Z
+LAST-MODIFIED:20240507T121134Z
+DTSTAMP:20240507T121134Z
+UID:b1814d32-9adf-4518-8535-37f2c037f423
+SUMMARY:Event D
+RRULE:FREQ=YEARLY
+DTSTART;TZID=Europe/Berlin:20240101T164500
+DTEND;TZID=Europe/Berlin:20240101T171500
+TRANSP:OPAQUE
+SEQUENCE:2
+X-MOZ-GENERATION:3
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-5.ics b/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-5.ics
new file mode 100644
index 00000000000..1cd8b7ebf13
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-5.ics
@@ -0,0 +1,14 @@
+BEGIN:VCALENDAR
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+VERSION:2.0
+BEGIN:VEVENT
+CREATED:20240507T122221Z
+LAST-MODIFIED:20240507T122237Z
+DTSTAMP:20240507T122237Z
+UID:19c4e049-0b09-4101-a2ad-061a837e6a5e
+SUMMARY:Cake Tasting
+DTSTART;TZID=Europe/Berlin:20240509T151500
+DTEND;TZID=Europe/Berlin:20240509T171500
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-6.ics b/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-6.ics
new file mode 100644
index 00000000000..6c24d534281
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/caldav-search-limit-timerange-6.ics
@@ -0,0 +1,15 @@
+BEGIN:VCALENDAR
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+VERSION:2.0
+BEGIN:VEVENT
+CREATED:20240507T122246Z
+LAST-MODIFIED:20240507T175258Z
+DTSTAMP:20240507T175258Z
+UID:60a7d310-aa7b-4974-8a8a-ff9339367e1d
+SUMMARY:Pasta Day
+DTSTART;TZID=Europe/Berlin:20240514T123000
+DTEND;TZID=Europe/Berlin:20240514T133000
+TRANSP:OPAQUE
+X-MOZ-GENERATION:2
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/caldav-search-missing-start-1.ics b/apps/dav/tests/unit/test_fixtures/caldav-search-missing-start-1.ics
new file mode 100644
index 00000000000..a7865eaf5ef
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/caldav-search-missing-start-1.ics
@@ -0,0 +1,14 @@
+BEGIN:VCALENDAR
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+VERSION:2.0
+BEGIN:VEVENT
+CREATED:20240507T122246Z
+LAST-MODIFIED:20240507T175258Z
+DTSTAMP:20240507T175258Z
+UID:39e1b04f-d1cc-4622-bf97-11c38e070f43
+SUMMARY:Missing DTSTART 1
+DTEND;TZID=Europe/Berlin:20240514T133000
+TRANSP:OPAQUE
+X-MOZ-GENERATION:2
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/caldav-search-missing-start-2.ics b/apps/dav/tests/unit/test_fixtures/caldav-search-missing-start-2.ics
new file mode 100644
index 00000000000..4a33f2b1c8a
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/caldav-search-missing-start-2.ics
@@ -0,0 +1,14 @@
+BEGIN:VCALENDAR
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+VERSION:2.0
+BEGIN:VEVENT
+CREATED:20240507T122246Z
+LAST-MODIFIED:20240507T175258Z
+DTSTAMP:20240507T175258Z
+UID:12413feb-4b8c-4e95-ae7f-9ec4f42f3348
+SUMMARY:Missing DTSTART 2
+DTEND;TZID=Europe/Berlin:20240514T133000
+TRANSP:OPAQUE
+X-MOZ-GENERATION:2
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics b/apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics
new file mode 100644
index 00000000000..09606ca5ee4
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics
@@ -0,0 +1,20 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Sabre//Sabre VObject 4.5.6//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+UID:RANDOM-UID
+DTSTAMP:20250121T000000Z
+SUMMARY:Example event - open me!
+DTSTART:20250128T100000Z
+DTEND:20250128T110000Z
+DESCRIPTION:Welcome to Nextcloud Calendar!\n\nThis is a sample event - expl
+ ore the flexibility of planning with Nextcloud Calendar by making any edit
+ s you want!\n\nWith Nextcloud Calendar\, you can:\n- Create\, edit\, and m
+ anage events effortlessly.\n- Create multiple calendars and share them wit
+ h teammates\, friends\, or family.\n- Check availability and display your
+ busy times to others.\n- Seamlessly integrate with apps and devices via Ca
+ lDAV.\n- Customize your experience: schedule recurring events\, adjust not
+ ifications and other settings.
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics.license b/apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics.license
new file mode 100644
index 00000000000..23e2d6b1908
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/tests/unit/test_fixtures/example-event-expected.ics b/apps/dav/tests/unit/test_fixtures/example-event-expected.ics
new file mode 100644
index 00000000000..f9dfc37718e
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event-expected.ics
@@ -0,0 +1,18 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//IDN nextcloud.com//Calendar app 5.2.0-dev.1//EN
+BEGIN:VEVENT
+CREATED:20250128T091147Z
+DTSTAMP:20250128T091507Z
+LAST-MODIFIED:20250128T091507Z
+SEQUENCE:2
+STATUS:CONFIRMED
+SUMMARY:Welcome!
+DESCRIPTION:Welcome!!!
+LOCATION:Test
+UID:RANDOM-UID
+DTSTART:20250128T100000Z
+DTEND:20250128T110000Z
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/example-event-expected.ics.license b/apps/dav/tests/unit/test_fixtures/example-event-expected.ics.license
new file mode 100644
index 00000000000..23e2d6b1908
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event-expected.ics.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics b/apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics
new file mode 100644
index 00000000000..8018552f2a5
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics
@@ -0,0 +1,21 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//IDN nextcloud.com//Calendar app 5.2.0-dev.1//EN
+BEGIN:VEVENT
+CREATED:20250128T091147Z
+DTSTAMP:20250128T091507Z
+LAST-MODIFIED:20250128T091507Z
+SEQUENCE:2
+UID:3b4df6a8-84df-43d5-baf9-377b43390b70
+DTSTART;VALUE=DATE:20250130
+DTEND;VALUE=DATE:20250131
+STATUS:CONFIRMED
+SUMMARY:Welcome!
+DESCRIPTION:Welcome!!!
+LOCATION:Test
+ATTENDEE;CN=user a;CUTYPE=INDIVIDUAL;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICI
+ PANT;RSVP=TRUE;LANGUAGE=en;SCHEDULE-STATUS=1.1:mailto:usera@imap.localhost
+ORGANIZER;CN=Admin Account:mailto:admin@imap.localhost
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics.license b/apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics.license
new file mode 100644
index 00000000000..23e2d6b1908
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/tests/unit/test_fixtures/example-event.ics b/apps/dav/tests/unit/test_fixtures/example-event.ics
new file mode 100644
index 00000000000..6fc1848ea52
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event.ics
@@ -0,0 +1,18 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//IDN nextcloud.com//Calendar app 5.2.0-dev.1//EN
+BEGIN:VEVENT
+CREATED:20250128T091147Z
+DTSTAMP:20250128T091507Z
+LAST-MODIFIED:20250128T091507Z
+SEQUENCE:2
+UID:3b4df6a8-84df-43d5-baf9-377b43390b70
+STATUS:CONFIRMED
+SUMMARY:Welcome!
+DESCRIPTION:Welcome!!!
+LOCATION:Test
+DTSTART:20250204T100000Z
+DTEND:20250204T110000Z
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/example-event.ics.license b/apps/dav/tests/unit/test_fixtures/example-event.ics.license
new file mode 100644
index 00000000000..23e2d6b1908
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event.ics.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+SPDX-License-Identifier: AGPL-3.0-or-later