aboutsummaryrefslogtreecommitdiffstats
path: root/tests/lib/Calendar
diff options
context:
space:
mode:
Diffstat (limited to 'tests/lib/Calendar')
-rw-r--r--tests/lib/Calendar/CalendarEventBuilderTest.php151
-rw-r--r--tests/lib/Calendar/ManagerTest.php1622
-rw-r--r--tests/lib/Calendar/Resource/ManagerTest.php35
-rw-r--r--tests/lib/Calendar/ResourcesRoomsUpdaterTest.php439
-rw-r--r--tests/lib/Calendar/Room/ManagerTest.php35
5 files changed, 2041 insertions, 241 deletions
diff --git a/tests/lib/Calendar/CalendarEventBuilderTest.php b/tests/lib/Calendar/CalendarEventBuilderTest.php
new file mode 100644
index 00000000000..b01c209cd31
--- /dev/null
+++ b/tests/lib/Calendar/CalendarEventBuilderTest.php
@@ -0,0 +1,151 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\Calendar;
+
+use DateTimeImmutable;
+use InvalidArgumentException;
+use OC\Calendar\CalendarEventBuilder;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Calendar\CalendarEventStatus;
+use OCP\Calendar\ICreateFromString;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+class CalendarEventBuilderTest extends TestCase {
+ private CalendarEventBuilder $calendarEventBuilder;
+ private ITimeFactory&MockObject $timeFactory;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->timeFactory->method('now')
+ ->willReturn(new DateTimeImmutable('20250105T000000Z'));
+
+ $this->calendarEventBuilder = new CalendarEventBuilder(
+ 'event-uid-123',
+ $this->timeFactory,
+ );
+ }
+
+ public function testToIcs(): void {
+ $this->calendarEventBuilder->setStartDate(new DateTimeImmutable('2025-01-05T17:09:58Z'));
+ $this->calendarEventBuilder->setEndDate(new DateTimeImmutable('2025-01-05T17:19:58Z'));
+ $this->calendarEventBuilder->setStatus(CalendarEventStatus::CONFIRMED);
+ $this->calendarEventBuilder->setSummary('My event');
+ $this->calendarEventBuilder->setDescription('Foo bar baz');
+ $this->calendarEventBuilder->setOrganizer('mailto:organizer@domain.tld');
+ $this->calendarEventBuilder->addAttendee('mailto:attendee1@domain.tld');
+ $this->calendarEventBuilder->addAttendee('mailto:attendee2@domain.tld');
+
+ $expected = file_get_contents(\OC::$SERVERROOT . '/tests/data/ics/event-builder-complete.ics');
+ $actual = $this->calendarEventBuilder->toIcs();
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testToIcsWithoutOrganizerAndAttendees(): void {
+ $this->calendarEventBuilder->setStartDate(new DateTimeImmutable('2025-01-05T17:09:58Z'));
+ $this->calendarEventBuilder->setEndDate(new DateTimeImmutable('2025-01-05T17:19:58Z'));
+ $this->calendarEventBuilder->setStatus(CalendarEventStatus::CONFIRMED);
+ $this->calendarEventBuilder->setSummary('My event');
+ $this->calendarEventBuilder->setDescription('Foo bar baz');
+
+ $expected = file_get_contents(\OC::$SERVERROOT . '/tests/data/ics/event-builder-without-attendees.ics');
+ $actual = $this->calendarEventBuilder->toIcs();
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testToIcsWithoutMailtoPrefix(): void {
+ $this->calendarEventBuilder->setStartDate(new DateTimeImmutable('2025-01-05T17:09:58Z'));
+ $this->calendarEventBuilder->setEndDate(new DateTimeImmutable('2025-01-05T17:19:58Z'));
+ $this->calendarEventBuilder->setStatus(CalendarEventStatus::CONFIRMED);
+ $this->calendarEventBuilder->setSummary('My event');
+ $this->calendarEventBuilder->setDescription('Foo bar baz');
+ $this->calendarEventBuilder->setOrganizer('organizer@domain.tld');
+ $this->calendarEventBuilder->addAttendee('attendee1@domain.tld');
+ $this->calendarEventBuilder->addAttendee('attendee2@domain.tld');
+
+ $expected = file_get_contents(\OC::$SERVERROOT . '/tests/data/ics/event-builder-complete.ics');
+ $actual = $this->calendarEventBuilder->toIcs();
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testCreateInCalendar(): void {
+ $this->calendarEventBuilder->setStartDate(new DateTimeImmutable('2025-01-05T17:09:58Z'));
+ $this->calendarEventBuilder->setEndDate(new DateTimeImmutable('2025-01-05T17:19:58Z'));
+ $this->calendarEventBuilder->setStatus(CalendarEventStatus::CONFIRMED);
+ $this->calendarEventBuilder->setSummary('My event');
+ $this->calendarEventBuilder->setDescription('Foo bar baz');
+ $this->calendarEventBuilder->setOrganizer('organizer@domain.tld');
+ $this->calendarEventBuilder->addAttendee('attendee1@domain.tld');
+ $this->calendarEventBuilder->addAttendee('mailto:attendee2@domain.tld');
+
+ $expectedIcs = file_get_contents(\OC::$SERVERROOT . '/tests/data/ics/event-builder-complete.ics');
+ $calendar = $this->createMock(ICreateFromString::class);
+ $calendar->expects(self::once())
+ ->method('createFromString')
+ ->with('event-uid-123.ics', $expectedIcs);
+
+ $actual = $this->calendarEventBuilder->createInCalendar($calendar);
+ $this->assertEquals('event-uid-123.ics', $actual);
+ }
+
+ public function testToIcsWithoutStartDate(): void {
+ $this->calendarEventBuilder->setEndDate(new DateTimeImmutable('2025-01-05T17:19:58Z'));
+ $this->calendarEventBuilder->setSummary('My event');
+ $this->calendarEventBuilder->setDescription('Foo bar baz');
+ $this->calendarEventBuilder->setOrganizer('organizer@domain.tld');
+ $this->calendarEventBuilder->addAttendee('attendee1@domain.tld');
+ $this->calendarEventBuilder->addAttendee('mailto:attendee2@domain.tld');
+
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessageMatches('/start date/i');
+ $this->calendarEventBuilder->toIcs();
+ }
+
+ public function testToIcsWithoutEndDate(): void {
+ $this->calendarEventBuilder->setStartDate(new DateTimeImmutable('2025-01-05T17:09:58Z'));
+ $this->calendarEventBuilder->setSummary('My event');
+ $this->calendarEventBuilder->setDescription('Foo bar baz');
+ $this->calendarEventBuilder->setOrganizer('organizer@domain.tld');
+ $this->calendarEventBuilder->addAttendee('attendee1@domain.tld');
+ $this->calendarEventBuilder->addAttendee('mailto:attendee2@domain.tld');
+
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessageMatches('/end date/i');
+ $this->calendarEventBuilder->toIcs();
+ }
+
+ public function testToIcsWithoutSummary(): void {
+ $this->calendarEventBuilder->setStartDate(new DateTimeImmutable('2025-01-05T17:09:58Z'));
+ $this->calendarEventBuilder->setEndDate(new DateTimeImmutable('2025-01-05T17:19:58Z'));
+ $this->calendarEventBuilder->setDescription('Foo bar baz');
+ $this->calendarEventBuilder->setOrganizer('organizer@domain.tld');
+ $this->calendarEventBuilder->addAttendee('attendee1@domain.tld');
+ $this->calendarEventBuilder->addAttendee('mailto:attendee2@domain.tld');
+
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessageMatches('/summary/i');
+ $this->calendarEventBuilder->toIcs();
+ }
+
+ public function testToIcsWithoutOrganizerWithAttendees(): void {
+ $this->calendarEventBuilder->setStartDate(new DateTimeImmutable('2025-01-05T17:09:58Z'));
+ $this->calendarEventBuilder->setEndDate(new DateTimeImmutable('2025-01-05T17:19:58Z'));
+ $this->calendarEventBuilder->setSummary('My event');
+ $this->calendarEventBuilder->setDescription('Foo bar baz');
+ $this->calendarEventBuilder->addAttendee('attendee1@domain.tld');
+ $this->calendarEventBuilder->addAttendee('mailto:attendee2@domain.tld');
+
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessageMatches('/organizer/i');
+ $this->calendarEventBuilder->toIcs();
+ }
+}
diff --git a/tests/lib/Calendar/ManagerTest.php b/tests/lib/Calendar/ManagerTest.php
index fcf6ab3a588..eeaca0dfeb6 100644
--- a/tests/lib/Calendar/ManagerTest.php
+++ b/tests/lib/Calendar/ManagerTest.php
@@ -1,63 +1,68 @@
<?php
+
/**
- * @copyright 2017, Georg Ehrke <oc.list@georgehrke.com>
- *
- * @author Georg Ehrke <oc.list@georgehrke.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\Calendar;
+use DateTimeImmutable;
use OC\AppFramework\Bootstrap\Coordinator;
+use OC\Calendar\AvailabilityResult;
use OC\Calendar\Manager;
+use OCA\DAV\CalDAV\Auth\CustomPrincipalPlugin;
+use OCA\DAV\Connector\Sabre\Server;
+use OCA\DAV\ServerFactory;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Calendar\ICalendar;
+use OCP\Calendar\ICalendarIsShared;
+use OCP\Calendar\ICalendarIsWritable;
use OCP\Calendar\ICreateFromString;
use OCP\Calendar\IHandleImipMessage;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\Security\ISecureRandom;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
-use Sabre\VObject\Document;
-use Sabre\VObject\Reader;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use Sabre\VObject\Component\VCalendar;
use Test\TestCase;
/*
* This allows us to create Mock object supporting both interfaces
*/
-interface ICreateFromStringAndHandleImipMessage extends ICreateFromString, IHandleImipMessage {
+interface ITestCalendar extends ICreateFromString, IHandleImipMessage, ICalendarIsShared, ICalendarIsWritable {
}
class ManagerTest extends TestCase {
- /** @var Coordinator|MockObject */
+ /** @var Coordinator&MockObject */
private $coordinator;
- /** @var MockObject|ContainerInterface */
+ /** @var ContainerInterface&MockObject */
private $container;
- /** @var MockObject|LoggerInterface */
+ /** @var LoggerInterface&MockObject */
private $logger;
/** @var Manager */
private $manager;
- /** @var ITimeFactory|ITimeFactory&MockObject|MockObject */
+ /** @var ITimeFactory&MockObject */
private $time;
+ /** @var ISecureRandom&MockObject */
+ private ISecureRandom $secureRandom;
+
+ private IUserManager&MockObject $userManager;
+ private ServerFactory&MockObject $serverFactory;
+
+ private VCalendar $vCalendar1a;
+ private VCalendar $vCalendar2a;
+ private VCalendar $vCalendar3a;
+
protected function setUp(): void {
parent::setUp();
@@ -65,19 +70,82 @@ class ManagerTest extends TestCase {
$this->container = $this->createMock(ContainerInterface::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->time = $this->createMock(ITimeFactory::class);
+ $this->secureRandom = $this->createMock(ISecureRandom::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->serverFactory = $this->createMock(ServerFactory::class);
$this->manager = new Manager(
$this->coordinator,
$this->container,
$this->logger,
$this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
);
+
+ // 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->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 Event');
+ $vEvent->add('SEQUENCE', 3);
+ $vEvent->add('STATUS', 'CONFIRMED');
+ $vEvent->add('TRANSP', 'OPAQUE');
+ $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 event for reply
+ $this->vCalendar2a = new VCalendar();
+ /** @var VEvent $vEvent */
+ $vEvent = $this->vCalendar2a->add('VEVENT', []);
+ $vEvent->UID->setValue('dcc733bf-b2b2-41f2-a8cf-550ae4b67aff');
+ $vEvent->add('DTSTART', '20210820');
+ $vEvent->add('DTEND', '20220821');
+ $vEvent->add('SUMMARY', 'berry basket');
+ $vEvent->add('SEQUENCE', 3);
+ $vEvent->add('STATUS', 'CONFIRMED');
+ $vEvent->add('TRANSP', 'OPAQUE');
+ $vEvent->add('ORGANIZER', 'mailto:linus@stardew-tent-living.com', ['CN' => 'admin']);
+ $vEvent->add('ATTENDEE', 'mailto:pierre@general-store.com', [
+ 'CN' => 'pierre@general-store.com',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'PARTSTAT' => 'ACCEPTED',
+ ]);
+
+ // construct calendar with a event for reply
+ $this->vCalendar3a = new VCalendar();
+ /** @var VEvent $vEvent */
+ $vEvent = $this->vCalendar3a->add('VEVENT', []);
+ $vEvent->UID->setValue('dcc733bf-b2b2-41f2-a8cf-550ae4b67aff');
+ $vEvent->add('DTSTART', '20210820');
+ $vEvent->add('DTEND', '20220821');
+ $vEvent->add('SUMMARY', 'berry basket');
+ $vEvent->add('SEQUENCE', 3);
+ $vEvent->add('STATUS', 'CANCELLED');
+ $vEvent->add('TRANSP', 'OPAQUE');
+ $vEvent->add('ORGANIZER', 'mailto:linus@stardew-tent-living.com', ['CN' => 'admin']);
+ $vEvent->add('ATTENDEE', 'mailto:pierre@general-store.com', [
+ 'CN' => 'pierre@general-store.com',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'PARTSTAT' => 'ACCEPTED',
+ ]);
+
}
- /**
- * @dataProvider searchProvider
- */
- public function testSearch($search1, $search2, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('searchProvider')]
+ public function testSearch($search1, $search2, $expected): void {
/** @var ICalendar | MockObject $calendar1 */
$calendar1 = $this->createMock(ICalendar::class);
$calendar1->method('getKey')->willReturn('simple:1');
@@ -101,10 +169,8 @@ class ManagerTest extends TestCase {
$this->assertEquals($expected, $result);
}
- /**
- * @dataProvider searchProvider
- */
- public function testSearchOptions($search1, $search2, $expected) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('searchProvider')]
+ public function testSearchOptions($search1, $search2, $expected): void {
/** @var ICalendar | MockObject $calendar1 */
$calendar1 = $this->createMock(ICalendar::class);
$calendar1->method('getKey')->willReturn('simple:1');
@@ -131,7 +197,7 @@ class ManagerTest extends TestCase {
$this->assertEquals($expected, $result);
}
- public function searchProvider() {
+ public static function searchProvider(): array {
$search1 = [
[
'id' => 1,
@@ -185,7 +251,7 @@ class ManagerTest extends TestCase {
];
}
- public function testRegisterUnregister() {
+ public function testRegisterUnregister(): void {
/** @var ICalendar | MockObject $calendar1 */
$calendar1 = $this->createMock(ICalendar::class);
$calendar1->method('getKey')->willReturn('key1');
@@ -209,7 +275,7 @@ class ManagerTest extends TestCase {
$this->assertContains($calendar2, $result);
}
- public function testGetCalendars() {
+ public function testGetCalendars(): void {
/** @var ICalendar | MockObject $calendar1 */
$calendar1 = $this->createMock(ICalendar::class);
$calendar1->method('getKey')->willReturn('key1');
@@ -233,12 +299,12 @@ class ManagerTest extends TestCase {
$this->assertCount(0, $result);
}
- public function testEnabledIfNot() {
+ public function testEnabledIfNot(): void {
$isEnabled = $this->manager->isEnabled();
$this->assertFalse($isEnabled);
}
- public function testIfEnabledIfSo() {
+ public function testIfEnabledIfSo(): void {
/** @var ICalendar | MockObject $calendar */
$calendar = $this->createMock(ICalendar::class);
$this->manager->registerCalendar($calendar);
@@ -247,120 +313,772 @@ class ManagerTest extends TestCase {
$this->assertTrue($isEnabled);
}
- public function testHandleImipReplyWrongMethod(): void {
- $principalUri = 'principals/user/linus';
- $sender = 'pierre@general-store.com';
- $recipient = 'linus@stardew-tent-living.com';
- $calendarData = $this->getVCalendarReply();
- $calendarData->METHOD = 'REQUEST';
+ public function testHandleImipRequestWithNoCalendars(): void {
+ // construct calendar manager returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message could not be processed because user has no calendars');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ $calendar = $this->vCalendar1a;
+ $calendar->add('METHOD', 'REQUEST');
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $this->logger->expects(self::once())
- ->method('warning');
- $this->time->expects(self::never())
- ->method('getTime');
+ public function testHandleImipRequestWithInvalidData(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('error')
+ ->with('iMip message could not be processed because an error occurred while parsing the iMip message');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, 'Invalid data');
+ // Assert
+ $this->assertFalse($result);
+ }
- $result = $this->manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ public function testHandleImipRequestWithNoMethod(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains an incorrect or invalid method');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ $calendar = $this->vCalendar1a;
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipReplyOrganizerNotRecipient(): void {
- $principalUri = 'principals/user/linus';
- $recipient = 'pierre@general-store.com';
- $sender = 'linus@stardew-tent-living.com';
- $calendarData = $this->getVCalendarReply();
+ public function testHandleImipRequestWithInvalidMethod(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains an incorrect or invalid method');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ $calendar = $this->vCalendar1a;
+ $calendar->add('METHOD', 'CANCEL');
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipRequestWithNoEvent(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains no event');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ $calendar = $this->vCalendar1a;
+ $calendar->add('METHOD', 'REQUEST');
+ $calendar->remove('VEVENT');
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $this->logger->expects(self::once())
- ->method('warning');
- $this->time->expects(self::never())
- ->method('getTime');
+ public function testHandleImipRequestWithNoUid(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains a UID');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ $calendar = $this->vCalendar1a;
+ $calendar->add('METHOD', 'REQUEST');
+ $calendar->VEVENT->remove('UID');
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $result = $this->manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ public function testHandleImipRequestWithNoOrganizer(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains an organizer');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ $calendar = $this->vCalendar1a;
+ $calendar->add('METHOD', 'REQUEST');
+ $calendar->VEVENT->remove('ORGANIZER');
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipReplyDateInThePast(): void {
+ public function testHandleImipRequestWithNoAttendee(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains any attendees');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ $calendar = $this->vCalendar1a;
+ $calendar->add('METHOD', 'REQUEST');
+ $calendar->VEVENT->remove('ATTENDEE');
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipRequestWithInvalidAttendee(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event does not contain a attendee that matches the recipient');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee2@testing.com';
+ $calendar = $this->vCalendar1a;
+ $calendar->add('METHOD', 'REQUEST');
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipRequestWithNoMatch(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ $userCalendar->expects(self::once())
+ ->method('isDeleted')
+ ->willReturn(false);
+ $userCalendar->expects(self::once())
+ ->method('isWritable')
+ ->willReturn(true);
+ $userCalendar->expects(self::once())
+ ->method('isShared')
+ ->willReturn(false);
+ $userCalendar->expects(self::once())
+ ->method('search')
+ ->willReturn([]);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event could not be processed because no corresponding event was found in any calendar');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ $calendar = $this->vCalendar1a;
+ $calendar->add('METHOD', 'REQUEST');
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipRequest(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ $userCalendar->expects(self::once())
+ ->method('isDeleted')
+ ->willReturn(false);
+ $userCalendar->expects(self::once())
+ ->method('isWritable')
+ ->willReturn(true);
+ $userCalendar->expects(self::once())
+ ->method('isShared')
+ ->willReturn(false);
+ $userCalendar->expects(self::once())
+ ->method('search')
+ ->willReturn([['uri' => 'principals/user/attendee1/personal']]);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ $calendar = $this->vCalendar1a;
+ $calendar->add('METHOD', 'REQUEST');
+ // construct user calendar returns
+ $userCalendar->expects(self::once())
+ ->method('handleIMipMessage')
+ ->with('', $calendar->serialize());
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertTrue($result);
+ }
+
+ public function testHandleImipReplyWithNoCalendars(): void {
+ // construct calendar manager returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message could not be processed because user has no calendars');
+ // construct parameters
$principalUri = 'principals/user/linus';
$sender = 'pierre@general-store.com';
$recipient = 'linus@stardew-tent-living.com';
- $calendarData = $this->getVCalendarReply();
- $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past
-
- $this->time->expects(self::once())
- ->method('getTime')
- ->willReturn(time());
-
- $this->logger->expects(self::once())
- ->method('warning');
+ $calendar = $this->vCalendar2a;
+ $calendar->add('METHOD', 'REPLY');
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $result = $this->manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ public function testHandleImipReplyWithInvalidData(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('error')
+ ->with('iMip message could not be processed because an error occurred while parsing the iMip message');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, 'Invalid data');
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipReplyNoCalendars(): void {
- /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */
+ public function testHandleImipReplyWithNoMethod(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
$manager = $this->getMockBuilder(Manager::class)
->setConstructorArgs([
$this->coordinator,
$this->container,
$this->logger,
- $this->time
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
])
- ->setMethods([
- 'getCalendarsForPrincipal'
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains an incorrect or invalid method');
+ // construct parameters
+ $principalUri = 'principals/user/linus';
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $calendar = $this->vCalendar2a;
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipReplyWithInvalidMethod(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
])
+ ->onlyMethods(['getCalendarsForPrincipal'])
->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains an incorrect or invalid method');
+ // construct parameters
$principalUri = 'principals/user/linus';
$sender = 'pierre@general-store.com';
$recipient = 'linus@stardew-tent-living.com';
- $calendarData = $this->getVCalendarReply();
+ $calendar = $this->vCalendar2a;
+ $calendar->add('METHOD', 'UNKNOWN');
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $this->time->expects(self::once())
- ->method('getTime')
- ->willReturn(1628374233);
+ public function testHandleImipReplyWithNoEvent(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
$manager->expects(self::once())
->method('getCalendarsForPrincipal')
- ->willReturn([]);
- $this->logger->expects(self::once())
- ->method('warning');
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains no event');
+ // construct parameters
+ $principalUri = 'principals/user/linus';
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $calendar = $this->vCalendar2a;
+ $calendar->add('METHOD', 'REPLY');
+ $calendar->remove('VEVENT');
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ public function testHandleImipReplyWithNoUid(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains a UID');
+ // construct parameters
+ $principalUri = 'principals/user/linus';
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $calendar = $this->vCalendar2a;
+ $calendar->add('METHOD', 'REPLY');
+ $calendar->VEVENT->remove('UID');
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipReplyEventNotFound(): void {
- /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */
+ public function testHandleImipReplyWithNoOrganizer(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
$manager = $this->getMockBuilder(Manager::class)
->setConstructorArgs([
$this->coordinator,
$this->container,
$this->logger,
- $this->time
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
])
- ->setMethods([
- 'getCalendarsForPrincipal'
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains an organizer');
+ // construct parameters
+ $principalUri = 'principals/user/linus';
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $calendar = $this->vCalendar2a;
+ $calendar->add('METHOD', 'REPLY');
+ $calendar->VEVENT->remove('ORGANIZER');
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipReplyWithNoAttendee(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
])
+ ->onlyMethods(['getCalendarsForPrincipal'])
->getMock();
- $calendar = $this->createMock(ICreateFromStringAndHandleImipMessage::class);
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains any attendees');
+ // construct parameters
$principalUri = 'principals/user/linus';
$sender = 'pierre@general-store.com';
$recipient = 'linus@stardew-tent-living.com';
- $calendarData = $this->getVCalendarReply();
+ $calendar = $this->vCalendar2a;
+ $calendar->add('METHOD', 'REPLY');
+ $calendar->VEVENT->remove('ATTENDEE');
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $this->time->expects(self::once())
- ->method('getTime')
- ->willReturn(1628374233);
+ public function testHandleImipReplyDateInThePast(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
$manager->expects(self::once())
->method('getCalendarsForPrincipal')
- ->willReturn([$calendar]);
- $calendar->expects(self::once())
+ ->willReturn([$userCalendar]);
+ // construct logger and time returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event could not be processed because the event is in the past');
+ $this->time->expects(self::once())
+ ->method('getTime')
+ ->willReturn(time());
+ // construct parameters
+ $principalUri = 'principals/user/linus';
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $calendarData = clone $this->vCalendar2a;
+ $calendarData->add('METHOD', 'REPLY');
+ $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipReplyEventNotFound(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ $userCalendar->expects(self::once())
->method('search')
->willReturn([]);
- $this->logger->expects(self::once())
- ->method('info');
- $calendar->expects(self::never())
- ->method('handleIMipMessage');
-
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct time returns
+ $this->time->expects(self::once())
+ ->method('getTime')
+ ->willReturn(1628374233);
+ // construct parameters
+ $principalUri = 'principals/user/linus';
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $calendarData = clone $this->vCalendar2a;
+ $calendarData->add('METHOD', 'REPLY');
+ // construct logger return
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event could not be processed because no corresponding event was found in any calendar', ['principalUri' => $principalUri, 'eventUid' => $calendarData->VEVENT->UID->getValue()]);
+ // Act
$result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ // Assert
$this->assertFalse($result);
}
@@ -371,17 +1089,21 @@ class ManagerTest extends TestCase {
$this->coordinator,
$this->container,
$this->logger,
- $this->time
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
])
- ->setMethods([
+ ->onlyMethods([
'getCalendarsForPrincipal'
])
->getMock();
- $calendar = $this->createMock(ICreateFromStringAndHandleImipMessage::class);
+ $calendar = $this->createMock(ITestCalendar::class);
$principalUri = 'principals/user/linus';
$sender = 'pierre@general-store.com';
$recipient = 'linus@stardew-tent-living.com';
- $calendarData = $this->getVCalendarReply();
+ $calendarData = clone $this->vCalendar2a;
+ $calendarData->add('METHOD', 'REPLY');
$this->time->expects(self::once())
->method('getTime')
@@ -395,92 +1117,416 @@ class ManagerTest extends TestCase {
$calendar->expects(self::once())
->method('handleIMipMessage')
->with('testname.ics', $calendarData->serialize());
-
+ // Act
$result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ // Assert
$this->assertTrue($result);
}
- public function testHandleImipCancelWrongMethod(): void {
+ public function testHandleImipCancelWithNoCalendars(): void {
+ // construct calendar manager returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message could not be processed because user has no calendars');
+ // construct parameters
$principalUri = 'principals/user/pierre';
$sender = 'linus@stardew-tent-living.com';
$recipient = 'pierre@general-store.com';
$replyTo = null;
- $calendarData = $this->getVCalendarCancel();
- $calendarData->METHOD = 'REQUEST';
-
- $this->logger->expects(self::once())
- ->method('warning');
- $this->time->expects(self::never())
- ->method('getTime');
+ $calendar = $this->vCalendar3a;
+ $calendar->add('METHOD', 'CANCEL');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $result = $this->manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ public function testHandleImipCancelWithInvalidData(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('error')
+ ->with('iMip message could not be processed because an error occurred while parsing the iMip message');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ $replyTo = null;
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, 'Invalid data');
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipCancelAttendeeNotRecipient(): void {
- $principalUri = '/user/admin';
+
+ public function testHandleImipCancelWithNoMethod(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains an incorrect or invalid method');
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
$sender = 'linus@stardew-tent-living.com';
- $recipient = 'leah@general-store.com';
+ $recipient = 'pierre@general-store.com';
$replyTo = null;
- $calendarData = $this->getVCalendarCancel();
+ $calendar = $this->vCalendar3a;
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $this->logger->expects(self::once())
- ->method('warning');
- $this->time->expects(self::never())
- ->method('getTime');
+ public function testHandleImipCancelWithInvalidMethod(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains an incorrect or invalid method');
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
+ $sender = 'linus@stardew-tent-living.com';
+ $recipient = 'pierre@general-store.com';
+ $replyTo = null;
+ $calendar = $this->vCalendar3a;
+ $calendar->add('METHOD', 'UNKNOWN');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $result = $this->manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ public function testHandleImipCancelWithNoEvent(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains no event');
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
+ $sender = 'linus@stardew-tent-living.com';
+ $recipient = 'pierre@general-store.com';
+ $replyTo = null;
+ $calendar = $this->vCalendar3a;
+ $calendar->add('METHOD', 'CANCEL');
+ $calendar->remove('VEVENT');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipCancelDateInThePast(): void {
+ public function testHandleImipCancelWithNoUid(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains a UID');
+ // construct parameters
$principalUri = 'principals/user/pierre';
$sender = 'linus@stardew-tent-living.com';
$recipient = 'pierre@general-store.com';
$replyTo = null;
- $calendarData = $this->getVCalendarCancel();
- $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past
+ $calendar = $this->vCalendar3a;
+ $calendar->add('METHOD', 'CANCEL');
+ $calendar->VEVENT->remove('UID');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $this->time->expects(self::once())
- ->method('getTime')
- ->willReturn(time());
- $this->logger->expects(self::once())
- ->method('warning');
+ public function testHandleImipCancelWithNoOrganizer(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains an organizer');
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
+ $sender = 'linus@stardew-tent-living.com';
+ $recipient = 'pierre@general-store.com';
+ $replyTo = null;
+ $calendar = $this->vCalendar3a;
+ $calendar->add('METHOD', 'CANCEL');
+ $calendar->VEVENT->remove('ORGANIZER');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $result = $this->manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ public function testHandleImipCancelWithNoAttendee(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains any attendees');
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $replyTo = null;
+ $calendar = $this->vCalendar3a;
+ $calendar->add('METHOD', 'CANCEL');
+ $calendar->VEVENT->remove('ATTENDEE');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipCancelNoCalendars(): void {
- /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */
+ public function testHandleImipCancelAttendeeNotRecipient(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
$manager = $this->getMockBuilder(Manager::class)
->setConstructorArgs([
$this->coordinator,
$this->container,
$this->logger,
- $this->time
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
])
- ->setMethods([
- 'getCalendarsForPrincipal'
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event could not be processed because recipient must be an ATTENDEE of this event');
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
+ $sender = 'linus@stardew-tent-living.com';
+ $recipient = 'leah@general-store.com';
+ $replyTo = null;
+ $calendarData = clone $this->vCalendar3a;
+ $calendarData->add('METHOD', 'CANCEL');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipCancelDateInThePast(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
])
+ ->onlyMethods(['getCalendarsForPrincipal'])
->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger and time returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event could not be processed because the event is in the past');
+ $this->time->expects(self::once())
+ ->method('getTime')
+ ->willReturn(time());
+ // construct parameters
$principalUri = 'principals/user/pierre';
$sender = 'linus@stardew-tent-living.com';
$recipient = 'pierre@general-store.com';
$replyTo = null;
- $calendarData = $this->getVCalendarCancel();
+ $calendarData = clone $this->vCalendar3a;
+ $calendarData->add('METHOD', 'CANCEL');
+ $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+ public function testHandleImipCancelEventNotFound(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ $userCalendar->expects(self::once())
+ ->method('search')
+ ->willReturn([]);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct time returns
$this->time->expects(self::once())
->method('getTime')
->willReturn(1628374233);
- $manager->expects(self::once())
- ->method('getCalendarsForPrincipal')
- ->with($principalUri)
- ->willReturn([]);
- $this->logger->expects(self::once())
- ->method('warning');
-
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
+ $sender = 'linus@stardew-tent-living.com';
+ $recipient = 'pierre@general-store.com';
+ $replyTo = null;
+ $calendarData = clone $this->vCalendar3a;
+ $calendarData->add('METHOD', 'CANCEL');
+ // construct logger return
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event could not be processed because no corresponding event was found in any calendar', ['principalUri' => $principalUri, 'eventUid' => $calendarData->VEVENT->UID->getValue()]);
+ // Act
$result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ // Assert
$this->assertFalse($result);
}
@@ -491,18 +1537,23 @@ class ManagerTest extends TestCase {
$this->coordinator,
$this->container,
$this->logger,
- $this->time
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
])
- ->setMethods([
+ ->onlyMethods([
'getCalendarsForPrincipal'
])
->getMock();
+
$principalUri = 'principals/user/pierre';
- $sender = 'clint@stardew-blacksmiths.com';
+ $sender = 'clint@stardew-tent-living.com';
$recipient = 'pierre@general-store.com';
$replyTo = 'linus@stardew-tent-living.com';
- $calendar = $this->createMock(ICreateFromStringAndHandleImipMessage::class);
- $calendarData = $this->getVCalendarCancel();
+ $calendar = $this->createMock(ITestCalendar::class);
+ $calendarData = clone $this->vCalendar3a;
+ $calendarData->add('METHOD', 'CANCEL');
$this->time->expects(self::once())
->method('getTime')
@@ -517,7 +1568,9 @@ class ManagerTest extends TestCase {
$calendar->expects(self::once())
->method('handleIMipMessage')
->with('testname.ics', $calendarData->serialize());
+ // Act
$result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ // Assert
$this->assertTrue($result);
}
@@ -528,9 +1581,12 @@ class ManagerTest extends TestCase {
$this->coordinator,
$this->container,
$this->logger,
- $this->time
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
])
- ->setMethods([
+ ->onlyMethods([
'getCalendarsForPrincipal'
])
->getMock();
@@ -538,8 +1594,9 @@ class ManagerTest extends TestCase {
$sender = 'linus@stardew-tent-living.com';
$recipient = 'pierre@general-store.com';
$replyTo = null;
- $calendar = $this->createMock(ICreateFromStringAndHandleImipMessage::class);
- $calendarData = $this->getVCalendarCancel();
+ $calendar = $this->createMock(ITestCalendar::class);
+ $calendarData = clone $this->vCalendar3a;
+ $calendarData->add('METHOD', 'CANCEL');
$this->time->expects(self::once())
->method('getTime')
@@ -554,65 +1611,224 @@ class ManagerTest extends TestCase {
$calendar->expects(self::once())
->method('handleIMipMessage')
->with('testname.ics', $calendarData->serialize());
+ // Act
$result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ // Assert
$this->assertTrue($result);
}
- private function getVCalendarReply(): Document {
- $data = <<<EOF
-BEGIN:VCALENDAR
-PRODID:-//Nextcloud/Nextcloud CalDAV Server//EN
+ private function getFreeBusyResponse(): string {
+ return <<<EOF
+<?xml version="1.0" encoding="utf-8"?>
+<cal:schedule-response xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.org/ns/" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns">
+ <cal:response>
+ <cal:recipient>
+ <d:href>mailto:admin@imap.localhost</d:href>
+ </cal:recipient>
+ <cal:request-status>2.0;Success</cal:request-status>
+ <cal:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
+PRODID:-//Sabre//Sabre VObject 4.5.6//EN
CALSCALE:GREGORIAN
METHOD:REPLY
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20210820
-DTEND;VALUE=DATE:20220821
-DTSTAMP:20210812T100040Z
-ORGANIZER;CN=admin:mailto:linus@stardew-tent-living.com
-UID:dcc733bf-b2b2-41f2-a8cf-550ae4b67aff
-ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=pierr
- e@general-store.com;X-NUM-GUESTS=0:mailto:pierre@general-store.com
-CREATED:20220812T100021Z
-DESCRIPTION:
-LAST-MODIFIED:20220812T100040Z
-LOCATION:
-SEQUENCE:3
-STATUS:CONFIRMED
-SUMMARY:berry basket
-TRANSP:OPAQUE
-END:VEVENT
+BEGIN:VFREEBUSY
+DTSTART:20250116T060000Z
+DTEND:20250117T060000Z
+DTSTAMP:20250111T125634Z
+FREEBUSY:20250116T060000Z/20250116T230000Z
+FREEBUSY;FBTYPE=BUSY-UNAVAILABLE:20250116T230000Z/20250117T060000Z
+ATTENDEE:mailto:admin@imap.localhost
+UID:6099eab3-9bf1-4c7a-809e-4d46957cc372
+ORGANIZER;CN=admin:mailto:admin@imap.localhost
+END:VFREEBUSY
END:VCALENDAR
-EOF;
- return Reader::read($data);
- }
-
- private function getVCalendarCancel(): Document {
- $data = <<<EOF
-BEGIN:VCALENDAR
-PRODID:-//Nextcloud/Nextcloud CalDAV Server//EN
+</cal:calendar-data>
+ </cal:response>
+ <cal:response>
+ <cal:recipient>
+ <d:href>mailto:empty@imap.localhost</d:href>
+ </cal:recipient>
+ <cal:request-status>2.0;Success</cal:request-status>
+ <cal:calendar-data>BEGIN:VCALENDAR
VERSION:2.0
+PRODID:-//Sabre//Sabre VObject 4.5.6//EN
CALSCALE:GREGORIAN
-METHOD:CANCEL
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20210820
-DTEND;VALUE=DATE:20220821
-DTSTAMP:20210812T100040Z
-ORGANIZER;CN=admin:mailto:linus@stardew-tent-living.com
-UID:dcc733bf-b2b2-41f2-a8cf-550ae4b67aff
-ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=pierr
- e@general-store.com;X-NUM-GUESTS=0:mailto:pierre@general-store.com
-CREATED:20220812T100021Z
-DESCRIPTION:
-LAST-MODIFIED:20220812T100040Z
-LOCATION:
-SEQUENCE:3
-STATUS:CANCELLED
-SUMMARY:berry basket
-TRANSP:OPAQUE
-END:VEVENT
+METHOD:REPLY
+BEGIN:VFREEBUSY
+DTSTART:20250116T060000Z
+DTEND:20250117T060000Z
+DTSTAMP:20250111T125634Z
+ATTENDEE:mailto:empty@imap.localhost
+UID:6099eab3-9bf1-4c7a-809e-4d46957cc372
+ORGANIZER;CN=admin:mailto:admin@imap.localhost
+END:VFREEBUSY
END:VCALENDAR
+</cal:calendar-data>
+ </cal:response>
+ <cal:response>
+ <cal:recipient>
+ <d:href>mailto:user@imap.localhost</d:href>
+ </cal:recipient>
+ <cal:request-status>2.0;Success</cal:request-status>
+ <cal:calendar-data>BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Sabre//Sabre VObject 4.5.6//EN
+CALSCALE:GREGORIAN
+METHOD:REPLY
+BEGIN:VFREEBUSY
+DTSTART:20250116T060000Z
+DTEND:20250117T060000Z
+DTSTAMP:20250111T125634Z
+FREEBUSY:20250116T060000Z/20250116T230000Z
+FREEBUSY;FBTYPE=BUSY-UNAVAILABLE:20250116T230000Z/20250117T060000Z
+ATTENDEE:mailto:user@imap.localhost
+UID:6099eab3-9bf1-4c7a-809e-4d46957cc372
+ORGANIZER;CN=admin:mailto:admin@imap.localhost
+END:VFREEBUSY
+END:VCALENDAR
+</cal:calendar-data>
+ </cal:response>
+ <cal:response>
+ <cal:recipient>
+ <d:href>mailto:nouser@domain.tld</d:href>
+ </cal:recipient>
+ <cal:request-status>3.7;Could not find principal</cal:request-status>
+ </cal:response>
+</cal:schedule-response>
EOF;
- return Reader::read($data);
+ }
+
+ public function testCheckAvailability(): void {
+ $organizer = $this->createMock(IUser::class);
+ $organizer->expects(self::once())
+ ->method('getUID')
+ ->willReturn('admin');
+ $organizer->expects(self::once())
+ ->method('getEMailAddress')
+ ->willReturn('admin@imap.localhost');
+
+ $user1 = $this->createMock(IUser::class);
+ $user2 = $this->createMock(IUser::class);
+
+ $this->userManager->expects(self::exactly(3))
+ ->method('getByEmail')
+ ->willReturnMap([
+ ['user@imap.localhost', [$user1]],
+ ['empty@imap.localhost', [$user2]],
+ ['nouser@domain.tld', []],
+ ]);
+
+ $authPlugin = $this->createMock(CustomPrincipalPlugin::class);
+ $authPlugin->expects(self::once())
+ ->method('setCurrentPrincipal')
+ ->with('principals/users/admin');
+
+ $server = $this->createMock(Server::class);
+ $server->expects(self::once())
+ ->method('getPlugin')
+ ->with('auth')
+ ->willReturn($authPlugin);
+ $server->expects(self::once())
+ ->method('invokeMethod')
+ ->willReturnCallback(function (
+ RequestInterface $request,
+ ResponseInterface $response,
+ bool $sendResponse,
+ ): void {
+ $requestBody = file_get_contents(__DIR__ . '/../../data/ics/free-busy-request.ics');
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals('calendars/admin/outbox', $request->getPath());
+ $this->assertEquals('text/calendar', $request->getHeader('Content-Type'));
+ $this->assertEquals('0', $request->getHeader('Depth'));
+ $this->assertEquals($requestBody, $request->getBodyAsString());
+ $this->assertFalse($sendResponse);
+ $response->setStatus(200);
+ $response->setBody($this->getFreeBusyResponse());
+ });
+
+ $this->serverFactory->expects(self::once())
+ ->method('createAttendeeAvailabilityServer')
+ ->willReturn($server);
+
+ $start = new DateTimeImmutable('2025-01-16T06:00:00Z');
+ $end = new DateTimeImmutable('2025-01-17T06:00:00Z');
+ $actual = $this->manager->checkAvailability($start, $end, $organizer, [
+ 'user@imap.localhost',
+ 'empty@imap.localhost',
+ 'nouser@domain.tld',
+ ]);
+ $expected = [
+ new AvailabilityResult('admin@imap.localhost', false),
+ new AvailabilityResult('empty@imap.localhost', true),
+ new AvailabilityResult('user@imap.localhost', false),
+ ];
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function testCheckAvailabilityWithMailtoPrefix(): void {
+ $organizer = $this->createMock(IUser::class);
+ $organizer->expects(self::once())
+ ->method('getUID')
+ ->willReturn('admin');
+ $organizer->expects(self::once())
+ ->method('getEMailAddress')
+ ->willReturn('admin@imap.localhost');
+
+ $user1 = $this->createMock(IUser::class);
+ $user2 = $this->createMock(IUser::class);
+
+ $this->userManager->expects(self::exactly(3))
+ ->method('getByEmail')
+ ->willReturnMap([
+ ['user@imap.localhost', [$user1]],
+ ['empty@imap.localhost', [$user2]],
+ ['nouser@domain.tld', []],
+ ]);
+
+ $authPlugin = $this->createMock(CustomPrincipalPlugin::class);
+ $authPlugin->expects(self::once())
+ ->method('setCurrentPrincipal')
+ ->with('principals/users/admin');
+
+ $server = $this->createMock(Server::class);
+ $server->expects(self::once())
+ ->method('getPlugin')
+ ->with('auth')
+ ->willReturn($authPlugin);
+ $server->expects(self::once())
+ ->method('invokeMethod')
+ ->willReturnCallback(function (
+ RequestInterface $request,
+ ResponseInterface $response,
+ bool $sendResponse,
+ ): void {
+ $requestBody = file_get_contents(__DIR__ . '/../../data/ics/free-busy-request.ics');
+ $this->assertEquals('POST', $request->getMethod());
+ $this->assertEquals('calendars/admin/outbox', $request->getPath());
+ $this->assertEquals('text/calendar', $request->getHeader('Content-Type'));
+ $this->assertEquals('0', $request->getHeader('Depth'));
+ $this->assertEquals($requestBody, $request->getBodyAsString());
+ $this->assertFalse($sendResponse);
+ $response->setStatus(200);
+ $response->setBody($this->getFreeBusyResponse());
+ });
+
+ $this->serverFactory->expects(self::once())
+ ->method('createAttendeeAvailabilityServer')
+ ->willReturn($server);
+
+ $start = new DateTimeImmutable('2025-01-16T06:00:00Z');
+ $end = new DateTimeImmutable('2025-01-17T06:00:00Z');
+ $actual = $this->manager->checkAvailability($start, $end, $organizer, [
+ 'mailto:user@imap.localhost',
+ 'mailto:empty@imap.localhost',
+ 'mailto:nouser@domain.tld',
+ ]);
+ $expected = [
+ new AvailabilityResult('admin@imap.localhost', false),
+ new AvailabilityResult('empty@imap.localhost', true),
+ new AvailabilityResult('user@imap.localhost', false),
+ ];
+ $this->assertEquals($expected, $actual);
}
}
diff --git a/tests/lib/Calendar/Resource/ManagerTest.php b/tests/lib/Calendar/Resource/ManagerTest.php
index 854f83af845..15977765da7 100644
--- a/tests/lib/Calendar/Resource/ManagerTest.php
+++ b/tests/lib/Calendar/Resource/ManagerTest.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
- *
- * @author Georg Ehrke <oc.list@georgehrke.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\Calendar\Resource;
@@ -30,6 +13,7 @@ use OC\AppFramework\Bootstrap\Coordinator;
use OC\AppFramework\Bootstrap\RegistrationContext;
use OC\AppFramework\Bootstrap\ServiceRegistration;
use OC\Calendar\Resource\Manager;
+use OC\Calendar\ResourcesRoomsUpdater;
use OCP\Calendar\Resource\IBackend;
use OCP\IServerContainer;
use PHPUnit\Framework\MockObject\MockObject;
@@ -42,6 +26,9 @@ class ManagerTest extends TestCase {
/** @var IServerContainer|MockObject */
private $server;
+ /** @var ResourcesRoomsUpdater|MockObject */
+ private $resourcesRoomsUpdater;
+
/** @var Manager */
private $manager;
@@ -50,9 +37,12 @@ class ManagerTest extends TestCase {
$this->coordinator = $this->createMock(Coordinator::class);
$this->server = $this->createMock(IServerContainer::class);
+ $this->resourcesRoomsUpdater = $this->createMock(ResourcesRoomsUpdater::class);
+
$this->manager = new Manager(
$this->coordinator,
$this->server,
+ $this->resourcesRoomsUpdater,
);
}
@@ -143,4 +133,11 @@ class ManagerTest extends TestCase {
self::assertEquals([], $this->manager->getBackends());
}
+
+ public function testUpdate(): void {
+ $this->resourcesRoomsUpdater->expects(self::once())
+ ->method('updateResources');
+
+ $this->manager->update();
+ }
}
diff --git a/tests/lib/Calendar/ResourcesRoomsUpdaterTest.php b/tests/lib/Calendar/ResourcesRoomsUpdaterTest.php
new file mode 100644
index 00000000000..9e54d21fda4
--- /dev/null
+++ b/tests/lib/Calendar/ResourcesRoomsUpdaterTest.php
@@ -0,0 +1,439 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\Calendar;
+
+use OC\Calendar\ResourcesRoomsUpdater;
+use OCA\DAV\CalDAV\CalDavBackend;
+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 Psr\Container\ContainerInterface;
+use Test\TestCase;
+
+interface tmpI extends IResource, IMetadataProvider {
+}
+
+class ResourcesRoomsUpdaterTest extends TestCase {
+ private ResourcesRoomsUpdater $updater;
+
+ /** @var IResourceManager|MockObject */
+ private $resourceManager;
+
+ /** @var IRoomManager|MockObject */
+ private $roomManager;
+
+ /** @var ContainerInterface|MockObject */
+ private $container;
+
+ /** @var CalDavBackend|MockObject */
+ private $calDavBackend;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->resourceManager = $this->createMock(IResourceManager::class);
+ $this->roomManager = $this->createMock(IRoomManager::class);
+ $this->container = $this->createMock(ContainerInterface::class);
+ $this->calDavBackend = $this->createMock(CalDavBackend::class);
+
+ $this->container->method('get')
+ ->willReturnMap([
+ [IResourceManager::class, $this->resourceManager],
+ [IRoomManager::class, $this->roomManager],
+ ]);
+
+ $this->updater = new ResourcesRoomsUpdater(
+ $this->container,
+ 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 testUpdateBoth(): 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')
+ ->willThrowException(new BackendTemporarilyUnavailableException());
+ $backend2->method('getResource')
+ ->willThrowException(new BackendTemporarilyUnavailableException());
+ $backend2->method('getAllResources')
+ ->willThrowException(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->updater->updateResources();
+ $this->updater->updateRooms();
+
+ $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/tests/lib/Calendar/Room/ManagerTest.php b/tests/lib/Calendar/Room/ManagerTest.php
index 9309a3fa0bb..e0f2de970ed 100644
--- a/tests/lib/Calendar/Room/ManagerTest.php
+++ b/tests/lib/Calendar/Room/ManagerTest.php
@@ -3,25 +3,8 @@
declare(strict_types=1);
/**
- * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
- *
- * @author Georg Ehrke <oc.list@georgehrke.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\Calendar\Room;
@@ -29,6 +12,7 @@ namespace Test\Calendar\Room;
use OC\AppFramework\Bootstrap\Coordinator;
use OC\AppFramework\Bootstrap\RegistrationContext;
use OC\AppFramework\Bootstrap\ServiceRegistration;
+use OC\Calendar\ResourcesRoomsUpdater;
use OC\Calendar\Room\Manager;
use OCP\Calendar\Room\IBackend;
use OCP\IServerContainer;
@@ -42,6 +26,9 @@ class ManagerTest extends TestCase {
/** @var IServerContainer|MockObject */
private $server;
+ /** @var ResourcesRoomsUpdater|MockObject */
+ private $resourcesRoomsUpdater;
+
/** @var Manager */
private $manager;
@@ -50,9 +37,12 @@ class ManagerTest extends TestCase {
$this->coordinator = $this->createMock(Coordinator::class);
$this->server = $this->createMock(IServerContainer::class);
+ $this->resourcesRoomsUpdater = $this->createMock(ResourcesRoomsUpdater::class);
+
$this->manager = new Manager(
$this->coordinator,
$this->server,
+ $this->resourcesRoomsUpdater,
);
}
@@ -145,4 +135,11 @@ class ManagerTest extends TestCase {
self::assertEquals([], $this->manager->getBackends());
}
+
+ public function testUpdate(): void {
+ $this->resourcesRoomsUpdater->expects(self::once())
+ ->method('updateRooms');
+
+ $this->manager->update();
+ }
}