diff options
Diffstat (limited to 'apps/dav/tests/unit/Service')
4 files changed, 494 insertions, 24 deletions
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()); + } +} |