diff options
Diffstat (limited to 'apps/user_status/tests/Unit')
14 files changed, 676 insertions, 912 deletions
diff --git a/apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php b/apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php index 682151a3f5d..66142082343 100644 --- a/apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php +++ b/apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php @@ -3,43 +3,21 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests\BackgroundJob; use OCA\UserStatus\BackgroundJob\ClearOldStatusesBackgroundJob; use OCA\UserStatus\Db\UserStatusMapper; use OCP\AppFramework\Utility\ITimeFactory; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class ClearOldStatusesBackgroundJobTest extends TestCase { - - /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ - private $time; - - /** @var UserStatusMapper|\PHPUnit\Framework\MockObject\MockObject */ - private $mapper; - - /** @var ClearOldStatusesBackgroundJob */ - private $job; + private ITimeFactory&MockObject $time; + private UserStatusMapper&MockObject $mapper; + private ClearOldStatusesBackgroundJob $job; protected function setUp(): void { parent::setUp(); @@ -50,9 +28,9 @@ class ClearOldStatusesBackgroundJobTest extends TestCase { $this->job = new ClearOldStatusesBackgroundJob($this->time, $this->mapper); } - public function testRun() { + public function testRun(): void { $this->mapper->expects($this->once()) - ->method('clearMessagesOlderThan') + ->method('clearOlderThanClearAt') ->with(1337); $this->mapper->expects($this->once()) ->method('clearStatusesOlderThan') diff --git a/apps/user_status/tests/Unit/CapabilitiesTest.php b/apps/user_status/tests/Unit/CapabilitiesTest.php index 80f6765a694..601fb207df4 100644 --- a/apps/user_status/tests/Unit/CapabilitiesTest.php +++ b/apps/user_status/tests/Unit/CapabilitiesTest.php @@ -3,66 +3,44 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests; use OCA\UserStatus\Capabilities; -use OCA\UserStatus\Service\EmojiService; +use OCP\IEmojiHelper; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class CapabilitiesTest extends TestCase { - - /** @var EmojiService|\PHPUnit\Framework\MockObject\MockObject */ - private $emojiService; - - /** @var Capabilities */ - private $capabilities; + private IEmojiHelper&MockObject $emojiHelper; + private Capabilities $capabilities; protected function setUp(): void { parent::setUp(); - $this->emojiService = $this->createMock(EmojiService::class); - $this->capabilities = new Capabilities($this->emojiService); + $this->emojiHelper = $this->createMock(IEmojiHelper::class); + $this->capabilities = new Capabilities($this->emojiHelper); } - /** - * @param bool $supportsEmojis - * - * @dataProvider getCapabilitiesDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('getCapabilitiesDataProvider')] public function testGetCapabilities(bool $supportsEmojis): void { - $this->emojiService->expects($this->once()) + $this->emojiHelper->expects($this->once()) ->method('doesPlatformSupportEmoji') ->willReturn($supportsEmojis); $this->assertEquals([ 'user_status' => [ 'enabled' => true, + 'restore' => true, 'supports_emoji' => $supportsEmojis, + 'supports_busy' => true, ] ], $this->capabilities->getCapabilities()); } - public function getCapabilitiesDataProvider(): array { + public static function getCapabilitiesDataProvider(): array { return [ [true], [false], diff --git a/apps/user_status/tests/Unit/Connector/UserStatusProviderTest.php b/apps/user_status/tests/Unit/Connector/UserStatusProviderTest.php index bc485a5537c..df6c55488d5 100644 --- a/apps/user_status/tests/Unit/Connector/UserStatusProviderTest.php +++ b/apps/user_status/tests/Unit/Connector/UserStatusProviderTest.php @@ -3,40 +3,20 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests\Connector; use OCA\UserStatus\Connector\UserStatusProvider; use OCA\UserStatus\Db\UserStatus; use OCA\UserStatus\Service\StatusService; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class UserStatusProviderTest extends TestCase { - - /** @var \PHPUnit\Framework\MockObject\MockObject */ - private $service; - - /** @var UserStatusProvider */ - private $provider; + private StatusService&MockObject $service; + private UserStatusProvider $provider; protected function setUp(): void { parent::setUp(); diff --git a/apps/user_status/tests/Unit/Connector/UserStatusTest.php b/apps/user_status/tests/Unit/Connector/UserStatusTest.php index 35f79f9958a..fee9b4e4b89 100644 --- a/apps/user_status/tests/Unit/Connector/UserStatusTest.php +++ b/apps/user_status/tests/Unit/Connector/UserStatusTest.php @@ -3,34 +3,17 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests\Connector; use OCA\UserStatus\Connector\UserStatus; -use Test\TestCase; use OCA\UserStatus\Db; +use Test\TestCase; class UserStatusTest extends TestCase { - public function testUserStatus() { + public function testUserStatus(): void { $status = new Db\UserStatus(); $status->setUserId('user2'); $status->setStatus('away'); @@ -51,7 +34,7 @@ class UserStatusTest extends TestCase { $this->assertEquals('60000', $dateTime->format('U')); } - public function testUserStatusInvisible() { + public function testUserStatusInvisible(): void { $status = new Db\UserStatus(); $status->setUserId('user2'); $status->setStatus('invisible'); diff --git a/apps/user_status/tests/Unit/Controller/PredefinedStatusControllerTest.php b/apps/user_status/tests/Unit/Controller/PredefinedStatusControllerTest.php index 44e3af5c0d2..0f96f41a524 100644 --- a/apps/user_status/tests/Unit/Controller/PredefinedStatusControllerTest.php +++ b/apps/user_status/tests/Unit/Controller/PredefinedStatusControllerTest.php @@ -3,40 +3,20 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests\Controller; use OCA\UserStatus\Controller\PredefinedStatusController; use OCA\UserStatus\Service\PredefinedStatusService; use OCP\IRequest; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class PredefinedStatusControllerTest extends TestCase { - - /** @var PredefinedStatusService|\PHPUnit\Framework\MockObject\MockObject */ - private $service; - - /** @var PredefinedStatusController */ - private $controller; + private PredefinedStatusService&MockObject $service; + private PredefinedStatusController $controller; protected function setUp(): void { parent::setUp(); @@ -44,11 +24,10 @@ class PredefinedStatusControllerTest extends TestCase { $request = $this->createMock(IRequest::class); $this->service = $this->createMock(PredefinedStatusService::class); - $this->controller = new PredefinedStatusController('user_status', $request, - $this->service); + $this->controller = new PredefinedStatusController('user_status', $request, $this->service); } - public function testFindAll() { + public function testFindAll(): void { $this->service->expects($this->once()) ->method('getDefaultStatuses') ->with() diff --git a/apps/user_status/tests/Unit/Controller/StatusesControllerTest.php b/apps/user_status/tests/Unit/Controller/StatusesControllerTest.php index 1dd6c0c4ae1..76d337879c3 100644 --- a/apps/user_status/tests/Unit/Controller/StatusesControllerTest.php +++ b/apps/user_status/tests/Unit/Controller/StatusesControllerTest.php @@ -3,26 +3,9 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests\Controller; use OCA\UserStatus\Controller\StatusesController; @@ -31,15 +14,12 @@ use OCA\UserStatus\Service\StatusService; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\IRequest; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class StatusesControllerTest extends TestCase { - - /** @var StatusService|\PHPUnit\Framework\MockObject\MockObject */ - private $service; - - /** @var StatusesController */ - private $controller; + private StatusService&MockObject $service; + private StatusesController $controller; protected function setUp(): void { parent::setUp(); diff --git a/apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php b/apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php index fbf86ba92c4..e99290319ed 100644 --- a/apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php +++ b/apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php @@ -3,28 +3,12 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests\Controller; +use OCA\DAV\CalDAV\Status\StatusService as CalendarStatusService; use OCA\UserStatus\Controller\UserStatusController; use OCA\UserStatus\Db\UserStatus; use OCA\UserStatus\Exception\InvalidClearAtException; @@ -36,37 +20,41 @@ use OCA\UserStatus\Service\StatusService; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\OCS\OCSBadRequestException; use OCP\AppFramework\OCS\OCSNotFoundException; -use OCP\ILogger; use OCP\IRequest; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Test\TestCase; use Throwable; class UserStatusControllerTest extends TestCase { - - /** @var ILogger|\PHPUnit\Framework\MockObject\MockObject */ - private $logger; - - /** @var StatusService|\PHPUnit\Framework\MockObject\MockObject */ - private $service; - - /** @var UserStatusController */ - private $controller; + private LoggerInterface&MockObject $logger; + private StatusService&MockObject $statusService; + private CalendarStatusService&MockObject $calendarStatusService; + private UserStatusController $controller; protected function setUp(): void { parent::setUp(); $request = $this->createMock(IRequest::class); $userId = 'john.doe'; - $this->logger = $this->createMock(ILogger::class); - $this->service = $this->createMock(StatusService::class); - - $this->controller = new UserStatusController('user_status', $request, $userId, $this->logger, $this->service); + $this->logger = $this->createMock(LoggerInterface::class); + $this->statusService = $this->createMock(StatusService::class); + $this->calendarStatusService = $this->createMock(CalendarStatusService::class); + + $this->controller = new UserStatusController( + 'user_status', + $request, + $userId, + $this->logger, + $this->statusService, + $this->calendarStatusService, + ); } public function testGetStatus(): void { $userStatus = $this->getUserStatus(); - $this->service->expects($this->once()) + $this->statusService->expects($this->once()) ->method('findByUserId') ->with('john.doe') ->willReturn($userStatus); @@ -85,7 +73,10 @@ class UserStatusControllerTest extends TestCase { } public function testGetStatusDoesNotExist(): void { - $this->service->expects($this->once()) + $this->calendarStatusService->expects(self::once()) + ->method('processCalendarStatus') + ->with('john.doe'); + $this->statusService->expects($this->once()) ->method('findByUserId') ->with('john.doe') ->willThrowException(new DoesNotExistException('')); @@ -96,37 +87,27 @@ class UserStatusControllerTest extends TestCase { $this->controller->getStatus(); } - /** - * @param string $statusType - * @param string|null $statusIcon - * @param string|null $message - * @param int|null $clearAt - * @param bool $expectSuccess - * @param bool $expectException - * @param Throwable|null $exception - * @param bool $expectLogger - * @param string|null $expectedLogMessage - * - * @dataProvider setStatusDataProvider - */ - public function testSetStatus(string $statusType, - ?string $statusIcon, - ?string $message, - ?int $clearAt, - bool $expectSuccess, - bool $expectException, - ?Throwable $exception, - bool $expectLogger, - ?string $expectedLogMessage): void { + #[\PHPUnit\Framework\Attributes\DataProvider('setStatusDataProvider')] + public function testSetStatus( + string $statusType, + ?string $statusIcon, + ?string $message, + ?int $clearAt, + bool $expectSuccess, + bool $expectException, + ?Throwable $exception, + bool $expectLogger, + ?string $expectedLogMessage, + ): void { $userStatus = $this->getUserStatus(); if ($expectException) { - $this->service->expects($this->once()) + $this->statusService->expects($this->once()) ->method('setStatus') ->with('john.doe', $statusType, null, true) ->willThrowException($exception); } else { - $this->service->expects($this->once()) + $this->statusService->expects($this->once()) ->method('setStatus') ->with('john.doe', $statusType, null, true) ->willReturn($userStatus); @@ -158,7 +139,7 @@ class UserStatusControllerTest extends TestCase { } } - public function setStatusDataProvider(): array { + public static function setStatusDataProvider(): array { return [ ['busy', '👨🏽💻', 'Busy developing the status feature', 500, true, false, null, false, null], ['busy', '👨🏽💻', 'Busy developing the status feature', 500, false, true, new InvalidStatusTypeException('Original exception message'), true, @@ -166,33 +147,25 @@ class UserStatusControllerTest extends TestCase { ]; } - /** - * @param string $messageId - * @param int|null $clearAt - * @param bool $expectSuccess - * @param bool $expectException - * @param Throwable|null $exception - * @param bool $expectLogger - * @param string|null $expectedLogMessage - * - * @dataProvider setPredefinedMessageDataProvider - */ - public function testSetPredefinedMessage(string $messageId, - ?int $clearAt, - bool $expectSuccess, - bool $expectException, - ?Throwable $exception, - bool $expectLogger, - ?string $expectedLogMessage): void { + #[\PHPUnit\Framework\Attributes\DataProvider('setPredefinedMessageDataProvider')] + public function testSetPredefinedMessage( + string $messageId, + ?int $clearAt, + bool $expectSuccess, + bool $expectException, + ?Throwable $exception, + bool $expectLogger, + ?string $expectedLogMessage, + ): void { $userStatus = $this->getUserStatus(); if ($expectException) { - $this->service->expects($this->once()) + $this->statusService->expects($this->once()) ->method('setPredefinedMessage') ->with('john.doe', $messageId, $clearAt) ->willThrowException($exception); } else { - $this->service->expects($this->once()) + $this->statusService->expects($this->once()) ->method('setPredefinedMessage') ->with('john.doe', $messageId, $clearAt) ->willReturn($userStatus); @@ -224,7 +197,7 @@ class UserStatusControllerTest extends TestCase { } } - public function setPredefinedMessageDataProvider(): array { + public static function setPredefinedMessageDataProvider(): array { return [ ['messageId-42', 500, true, false, null, false, null], ['messageId-42', 500, false, true, new InvalidClearAtException('Original exception message'), true, @@ -234,53 +207,43 @@ class UserStatusControllerTest extends TestCase { ]; } - /** - * @param string|null $statusIcon - * @param string $message - * @param int|null $clearAt - * @param bool $expectSuccess - * @param bool $expectException - * @param Throwable|null $exception - * @param bool $expectLogger - * @param string|null $expectedLogMessage - * @param bool $expectSuccessAsReset - * - * @dataProvider setCustomMessageDataProvider - */ - public function testSetCustomMessage(?string $statusIcon, - string $message, - ?int $clearAt, - bool $expectSuccess, - bool $expectException, - ?Throwable $exception, - bool $expectLogger, - ?string $expectedLogMessage, - bool $expectSuccessAsReset = false): void { + #[\PHPUnit\Framework\Attributes\DataProvider('setCustomMessageDataProvider')] + public function testSetCustomMessage( + ?string $statusIcon, + string $message, + ?int $clearAt, + bool $expectSuccess, + bool $expectException, + ?Throwable $exception, + bool $expectLogger, + ?string $expectedLogMessage, + bool $expectSuccessAsReset = false, + ): void { $userStatus = $this->getUserStatus(); if ($expectException) { - $this->service->expects($this->once()) + $this->statusService->expects($this->once()) ->method('setCustomMessage') ->with('john.doe', $statusIcon, $message, $clearAt) ->willThrowException($exception); } else { if ($expectSuccessAsReset) { - $this->service->expects($this->never()) + $this->statusService->expects($this->never()) ->method('setCustomMessage'); - $this->service->expects($this->once()) + $this->statusService->expects($this->once()) ->method('clearMessage') ->with('john.doe'); - $this->service->expects($this->once()) + $this->statusService->expects($this->once()) ->method('findByUserId') ->with('john.doe') ->willReturn($userStatus); } else { - $this->service->expects($this->once()) + $this->statusService->expects($this->once()) ->method('setCustomMessage') ->with('john.doe', $statusIcon, $message, $clearAt) ->willReturn($userStatus); - $this->service->expects($this->never()) + $this->statusService->expects($this->never()) ->method('clearMessage'); } } @@ -311,10 +274,11 @@ class UserStatusControllerTest extends TestCase { } } - public function setCustomMessageDataProvider(): array { + public static function setCustomMessageDataProvider(): array { return [ ['👨🏽💻', 'Busy developing the status feature', 500, true, false, null, false, null], - ['👨🏽💻', '', 500, true, false, null, false, null, true], + ['👨🏽💻', '', 500, true, false, null, false, null, false], + ['👨🏽💻', '', 0, true, false, null, false, null, false], ['👨🏽💻', 'Busy developing the status feature', 500, false, true, new InvalidClearAtException('Original exception message'), true, 'New user-status for "john.doe" was rejected due to an invalid clearAt value "500"'], ['👨🏽💻', 'Busy developing the status feature', 500, false, true, new InvalidStatusIconException('Original exception message'), true, @@ -324,17 +288,8 @@ class UserStatusControllerTest extends TestCase { ]; } - public function testClearStatus(): void { - $this->service->expects($this->once()) - ->method('clearStatus') - ->with('john.doe'); - - $response = $this->controller->clearStatus(); - $this->assertEquals([], $response->getData()); - } - public function testClearMessage(): void { - $this->service->expects($this->once()) + $this->statusService->expects($this->once()) ->method('clearMessage') ->with('john.doe'); diff --git a/apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php b/apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php index b6f3b410186..8773b04c95f 100644 --- a/apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php +++ b/apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php @@ -3,68 +3,44 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests\Dashboard; use OCA\UserStatus\Dashboard\UserStatusWidget; -use OCA\UserStatus\Db\UserStatus; use OCA\UserStatus\Service\StatusService; -use OCP\IInitialStateService; +use OCP\AppFramework\Services\IInitialState; +use OCP\IDateTimeFormatter; use OCP\IL10N; -use OCP\IUser; +use OCP\IURLGenerator; use OCP\IUserManager; use OCP\IUserSession; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class UserStatusWidgetTest extends TestCase { - - /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */ - private $l10n; - - /** @var IInitialStateService|\PHPUnit\Framework\MockObject\MockObject */ - private $initialState; - - /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */ - private $userManager; - - /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */ - private $userSession; - - /** @var StatusService|\PHPUnit\Framework\MockObject\MockObject */ - private $service; - - /** @var UserStatusWidget */ - private $widget; + private IL10N&MockObject $l10n; + private IDateTimeFormatter&MockObject $dateTimeFormatter; + private IURLGenerator&MockObject $urlGenerator; + private IInitialState&MockObject $initialState; + private IUserManager&MockObject $userManager; + private IUserSession&MockObject $userSession; + private StatusService&MockObject $service; + private UserStatusWidget $widget; protected function setUp(): void { parent::setUp(); $this->l10n = $this->createMock(IL10N::class); - $this->initialState = $this->createMock(IInitialStateService::class); + $this->dateTimeFormatter = $this->createMock(IDateTimeFormatter::class); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->initialState = $this->createMock(IInitialState::class); $this->userManager = $this->createMock(IUserManager::class); $this->userSession = $this->createMock(IUserSession::class); $this->service = $this->createMock(StatusService::class); - $this->widget = new UserStatusWidget($this->l10n, $this->initialState, $this->userManager, $this->userSession, $this->service); + $this->widget = new UserStatusWidget($this->l10n, $this->dateTimeFormatter, $this->urlGenerator, $this->initialState, $this->userManager, $this->userSession, $this->service); } public function testGetId(): void { @@ -84,178 +60,10 @@ class UserStatusWidgetTest extends TestCase { } public function testGetIconClass(): void { - $this->assertEquals('icon-user-status', $this->widget->getIconClass()); + $this->assertEquals('icon-user-status-dark', $this->widget->getIconClass()); } public function testGetUrl(): void { $this->assertNull($this->widget->getUrl()); } - - public function testLoadNoUserSession(): void { - $this->userSession->expects($this->once()) - ->method('getUser') - ->willReturn(null); - - $this->initialState->expects($this->once()) - ->method('provideInitialState') - ->with('user_status', 'dashboard_data', []); - - $this->service->expects($this->never()) - ->method('findAllRecentStatusChanges'); - - $this->widget->load(); - } - - public function testLoadWithCurrentUser(): void { - $user = $this->createMock(IUser::class); - $user->method('getUid')->willReturn('john.doe'); - $this->userSession->expects($this->once()) - ->method('getUser') - ->willReturn($user); - - $user1 = $this->createMock(IUser::class); - $user1->method('getDisplayName')->willReturn('User No. 1'); - - $this->userManager - ->method('get') - ->willReturnMap([ - ['user_1', $user1], - ['user_2', null], - ['user_3', null], - ['user_4', null], - ['user_5', null], - ['user_6', null], - ['user_7', null], - ]); - - $userStatuses = [ - UserStatus::fromParams([ - 'userId' => 'user_1', - 'status' => 'online', - 'customIcon' => '💻', - 'customMessage' => 'Working', - 'statusTimestamp' => 5000, - ]), - UserStatus::fromParams([ - 'userId' => 'user_2', - 'status' => 'away', - 'customIcon' => '☕️', - 'customMessage' => 'Office Hangout', - 'statusTimestamp' => 6000, - ]), - UserStatus::fromParams([ - 'userId' => 'user_3', - 'status' => 'dnd', - 'customIcon' => null, - 'customMessage' => null, - 'statusTimestamp' => 7000, - ]), - UserStatus::fromParams([ - 'userId' => 'john.doe', - 'status' => 'away', - 'customIcon' => '☕️', - 'customMessage' => 'Office Hangout', - 'statusTimestamp' => 90000, - ]), - UserStatus::fromParams([ - 'userId' => 'user_4', - 'status' => 'dnd', - 'customIcon' => null, - 'customMessage' => null, - 'statusTimestamp' => 7000, - ]), - UserStatus::fromParams([ - 'userId' => 'user_5', - 'status' => 'invisible', - 'customIcon' => '🏝', - 'customMessage' => 'On vacation', - 'statusTimestamp' => 7000, - ]), - UserStatus::fromParams([ - 'userId' => 'user_6', - 'status' => 'offline', - 'customIcon' => null, - 'customMessage' => null, - 'statusTimestamp' => 7000, - ]), - UserStatus::fromParams([ - 'userId' => 'user_7', - 'status' => 'invisible', - 'customIcon' => null, - 'customMessage' => null, - 'statusTimestamp' => 7000, - ]), - ]; - - $this->service->expects($this->once()) - ->method('findAllRecentStatusChanges') - ->with(8, 0) - ->willReturn($userStatuses); - - $this->initialState->expects($this->once()) - ->method('provideInitialState') - ->with('user_status', 'dashboard_data', $this->callback(function ($data): bool { - $this->assertEquals([ - [ - 'userId' => 'user_1', - 'displayName' => 'User No. 1', - 'status' => 'online', - 'icon' => '💻', - 'message' => 'Working', - 'timestamp' => 5000, - ], - [ - 'userId' => 'user_2', - 'displayName' => 'user_2', - 'status' => 'away', - 'icon' => '☕️', - 'message' => 'Office Hangout', - 'timestamp' => 6000, - ], - [ - 'userId' => 'user_3', - 'displayName' => 'user_3', - 'status' => 'dnd', - 'icon' => null, - 'message' => null, - 'timestamp' => 7000, - ], - [ - 'userId' => 'user_4', - 'displayName' => 'user_4', - 'status' => 'dnd', - 'icon' => null, - 'message' => null, - 'timestamp' => 7000, - ], - [ - 'userId' => 'user_5', - 'displayName' => 'user_5', - 'status' => 'offline', - 'icon' => '🏝', - 'message' => 'On vacation', - 'timestamp' => 7000, - ], - [ - 'userId' => 'user_6', - 'displayName' => 'user_6', - 'status' => 'offline', - 'icon' => null, - 'message' => null, - 'timestamp' => 7000, - ], - [ - 'userId' => 'user_7', - 'displayName' => 'user_7', - 'status' => 'offline', - 'icon' => null, - 'message' => null, - 'timestamp' => 7000, - ], - ], $data); - return true; - })); - - $this->widget->load(); - } } diff --git a/apps/user_status/tests/Unit/Db/UserStatusMapperTest.php b/apps/user_status/tests/Unit/Db/UserStatusMapperTest.php index e86cee6d68a..ea4480489c7 100644 --- a/apps/user_status/tests/Unit/Db/UserStatusMapperTest.php +++ b/apps/user_status/tests/Unit/Db/UserStatusMapperTest.php @@ -3,37 +3,19 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests\Db; -use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use OCA\UserStatus\Db\UserStatus; use OCA\UserStatus\Db\UserStatusMapper; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\DB\Exception; use Test\TestCase; class UserStatusMapperTest extends TestCase { - - /** @var UserStatusMapper */ - private $mapper; + private UserStatusMapper $mapper; protected function setUp(): void { parent::setUp(); @@ -147,19 +129,12 @@ class UserStatusMapperTest extends TestCase { $userStatus2->setStatusTimestamp(6000); $userStatus2->setIsUserDefined(false); - $this->expectException(UniqueConstraintViolationException::class); + $this->expectException(Exception::class); $this->mapper->insert($userStatus2); } - /** - * @param string $status - * @param bool $isUserDefined - * @param int $timestamp - * @param bool $expectsClean - * - * @dataProvider clearStatusesOlderThanDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('clearStatusesOlderThanDataProvider')] public function testClearStatusesOlderThan(string $status, bool $isUserDefined, int $timestamp, bool $expectsClean): void { $oldStatus = UserStatus::fromParams([ 'userId' => 'john.doe', @@ -185,8 +160,9 @@ class UserStatusMapperTest extends TestCase { } } - public function clearStatusesOlderThanDataProvider(): array { + public static function clearStatusesOlderThanDataProvider(): array { return [ + ['offline', false, 6000, false], ['online', true, 6000, false], ['online', true, 4000, true], ['online', false, 6000, false], @@ -202,22 +178,16 @@ class UserStatusMapperTest extends TestCase { ]; } - public function testClearMessagesOlderThan(): void { + public function testClearOlderThanClearAt(): void { $this->insertSampleStatuses(); - $this->mapper->clearMessagesOlderThan(55000); + $this->mapper->clearOlderThanClearAt(55000); $allStatuses = $this->mapper->findAll(); - $this->assertCount(3, $allStatuses); + $this->assertCount(2, $allStatuses); - $user1Status = $this->mapper->findByUserId('user1'); - $this->assertEquals('user1', $user1Status->getUserId()); - $this->assertEquals('dnd', $user1Status->getStatus()); - $this->assertEquals(5000, $user1Status->getStatusTimestamp()); - $this->assertEquals(true, $user1Status->getIsUserDefined()); - $this->assertEquals(null, $user1Status->getCustomIcon()); - $this->assertEquals(null, $user1Status->getCustomMessage()); - $this->assertEquals(null, $user1Status->getClearAt()); + $this->expectException(DoesNotExistException::class); + $this->mapper->findByUserId('user1'); } private function insertSampleStatuses(): void { @@ -231,6 +201,7 @@ class UserStatusMapperTest extends TestCase { $userStatus2->setUserId('user1'); $userStatus2->setStatus('dnd'); $userStatus2->setStatusTimestamp(5000); + $userStatus2->setStatusMessageTimestamp(5000); $userStatus2->setIsUserDefined(true); $userStatus2->setCustomIcon('💩'); $userStatus2->setCustomMessage('Do not disturb'); @@ -240,6 +211,7 @@ class UserStatusMapperTest extends TestCase { $userStatus3->setUserId('user2'); $userStatus3->setStatus('away'); $userStatus3->setStatusTimestamp(6000); + $userStatus3->setStatusMessageTimestamp(6000); $userStatus3->setIsUserDefined(false); $userStatus3->setCustomIcon('🏝'); $userStatus3->setCustomMessage('On vacation'); @@ -249,4 +221,112 @@ class UserStatusMapperTest extends TestCase { $this->mapper->insert($userStatus2); $this->mapper->insert($userStatus3); } + + public static function dataCreateBackupStatus(): array { + return [ + [false, false, false], + [true, false, true], + [false, true, false], + [true, true, false], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataCreateBackupStatus')] + public function testCreateBackupStatus(bool $hasStatus, bool $hasBackup, bool $backupCreated): void { + if ($hasStatus) { + $userStatus1 = new UserStatus(); + $userStatus1->setUserId('user1'); + $userStatus1->setStatus('online'); + $userStatus1->setStatusTimestamp(5000); + $userStatus1->setIsUserDefined(true); + $userStatus1->setIsBackup(false); + $userStatus1->setCustomIcon('🚀'); + $userStatus1->setCustomMessage('Current'); + $userStatus1->setClearAt(50000); + $this->mapper->insert($userStatus1); + } + + if ($hasBackup) { + $userStatus1 = new UserStatus(); + $userStatus1->setUserId('_user1'); + $userStatus1->setStatus('online'); + $userStatus1->setStatusTimestamp(5000); + $userStatus1->setIsUserDefined(true); + $userStatus1->setIsBackup(true); + $userStatus1->setCustomIcon('🚀'); + $userStatus1->setCustomMessage('Backup'); + $userStatus1->setClearAt(50000); + $this->mapper->insert($userStatus1); + } + + if ($hasStatus && $hasBackup) { + $this->expectException(Exception::class); + } + + self::assertSame($backupCreated, $this->mapper->createBackupStatus('user1')); + + if ($backupCreated) { + $user1Status = $this->mapper->findByUserId('user1', true); + $this->assertEquals('_user1', $user1Status->getUserId()); + $this->assertEquals(true, $user1Status->getIsBackup()); + $this->assertEquals('Current', $user1Status->getCustomMessage()); + } elseif ($hasBackup) { + $user1Status = $this->mapper->findByUserId('user1', true); + $this->assertEquals('_user1', $user1Status->getUserId()); + $this->assertEquals(true, $user1Status->getIsBackup()); + $this->assertEquals('Backup', $user1Status->getCustomMessage()); + } + } + + public function testRestoreBackupStatuses(): void { + $userStatus1 = new UserStatus(); + $userStatus1->setUserId('_user1'); + $userStatus1->setStatus('online'); + $userStatus1->setStatusTimestamp(5000); + $userStatus1->setIsUserDefined(true); + $userStatus1->setIsBackup(true); + $userStatus1->setCustomIcon('🚀'); + $userStatus1->setCustomMessage('Releasing'); + $userStatus1->setClearAt(50000); + $userStatus1 = $this->mapper->insert($userStatus1); + + $userStatus2 = new UserStatus(); + $userStatus2->setUserId('_user2'); + $userStatus2->setStatus('away'); + $userStatus2->setStatusTimestamp(5000); + $userStatus2->setIsUserDefined(true); + $userStatus2->setIsBackup(true); + $userStatus2->setCustomIcon('💩'); + $userStatus2->setCustomMessage('Do not disturb'); + $userStatus2->setClearAt(50000); + $userStatus2 = $this->mapper->insert($userStatus2); + + $userStatus3 = new UserStatus(); + $userStatus3->setUserId('_user3'); + $userStatus3->setStatus('away'); + $userStatus3->setStatusTimestamp(5000); + $userStatus3->setIsUserDefined(true); + $userStatus3->setIsBackup(true); + $userStatus3->setCustomIcon('🏝️'); + $userStatus3->setCustomMessage('Vacationing'); + $userStatus3->setClearAt(50000); + $this->mapper->insert($userStatus3); + + $this->mapper->restoreBackupStatuses([$userStatus1->getId(), $userStatus2->getId()]); + + $user1Status = $this->mapper->findByUserId('user1', false); + $this->assertEquals('user1', $user1Status->getUserId()); + $this->assertEquals(false, $user1Status->getIsBackup()); + $this->assertEquals('Releasing', $user1Status->getCustomMessage()); + + $user2Status = $this->mapper->findByUserId('user2', false); + $this->assertEquals('user2', $user2Status->getUserId()); + $this->assertEquals(false, $user2Status->getIsBackup()); + $this->assertEquals('Do not disturb', $user2Status->getCustomMessage()); + + $user3Status = $this->mapper->findByUserId('user3', true); + $this->assertEquals('_user3', $user3Status->getUserId()); + $this->assertEquals(true, $user3Status->getIsBackup()); + $this->assertEquals('Vacationing', $user3Status->getCustomMessage()); + } } diff --git a/apps/user_status/tests/Unit/Listener/UserDeletedListenerTest.php b/apps/user_status/tests/Unit/Listener/UserDeletedListenerTest.php index 6267bf1d185..fbcea23338d 100644 --- a/apps/user_status/tests/Unit/Listener/UserDeletedListenerTest.php +++ b/apps/user_status/tests/Unit/Listener/UserDeletedListenerTest.php @@ -3,26 +3,9 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests\Listener; use OCA\UserStatus\Listener\UserDeletedListener; @@ -30,15 +13,12 @@ use OCA\UserStatus\Service\StatusService; use OCP\EventDispatcher\GenericEvent; use OCP\IUser; use OCP\User\Events\UserDeletedEvent; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class UserDeletedListenerTest extends TestCase { - - /** @var StatusService|\PHPUnit\Framework\MockObject\MockObject */ - private $service; - - /** @var UserDeletedListener */ - private $listener; + private StatusService&MockObject $service; + private UserDeletedListener $listener; protected function setUp(): void { parent::setUp(); diff --git a/apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php b/apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php index ff12628ba70..c03eed0089e 100644 --- a/apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php +++ b/apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php @@ -3,78 +3,63 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests\Listener; +use OCA\DAV\CalDAV\Status\StatusService as CalendarStatusService; use OCA\UserStatus\Db\UserStatus; use OCA\UserStatus\Db\UserStatusMapper; -use OCA\UserStatus\Listener\UserDeletedListener; use OCA\UserStatus\Listener\UserLiveStatusListener; +use OCA\UserStatus\Service\StatusService; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Utility\ITimeFactory; use OCP\EventDispatcher\GenericEvent; use OCP\IUser; use OCP\User\Events\UserLiveStatusEvent; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Test\TestCase; class UserLiveStatusListenerTest extends TestCase { + private UserStatusMapper&MockObject $mapper; + private StatusService&MockObject $statusService; + private ITimeFactory&MockObject $timeFactory; + private CalendarStatusService&MockObject $calendarStatusService; - /** @var UserStatusMapper|\PHPUnit\Framework\MockObject\MockObject */ - private $mapper; - - /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ - private $timeFactory; - - /** @var UserDeletedListener */ - private $listener; + private LoggerInterface&MockObject $logger; + private UserLiveStatusListener $listener; protected function setUp(): void { parent::setUp(); $this->mapper = $this->createMock(UserStatusMapper::class); + $this->statusService = $this->createMock(StatusService::class); $this->timeFactory = $this->createMock(ITimeFactory::class); - $this->listener = new UserLiveStatusListener($this->mapper, $this->timeFactory); + $this->calendarStatusService = $this->createMock(CalendarStatusService::class); + $this->logger = $this->createMock(LoggerInterface::class); + + $this->listener = new UserLiveStatusListener( + $this->mapper, + $this->statusService, + $this->timeFactory, + $this->calendarStatusService, + $this->logger, + ); } - /** - * @param string $userId - * @param string $previousStatus - * @param int $previousTimestamp - * @param bool $previousIsUserDefined - * @param string $eventStatus - * @param int $eventTimestamp - * @param bool $expectExisting - * @param bool $expectUpdate - * - * @dataProvider handleEventWithCorrectEventDataProvider - */ - public function testHandleWithCorrectEvent(string $userId, - string $previousStatus, - int $previousTimestamp, - bool $previousIsUserDefined, - string $eventStatus, - int $eventTimestamp, - bool $expectExisting, - bool $expectUpdate): void { + #[\PHPUnit\Framework\Attributes\DataProvider('handleEventWithCorrectEventDataProvider')] + public function testHandleWithCorrectEvent( + string $userId, + string $previousStatus, + int $previousTimestamp, + bool $previousIsUserDefined, + string $eventStatus, + int $eventTimestamp, + bool $expectExisting, + bool $expectUpdate, + ): void { $userStatus = new UserStatus(); if ($expectExisting) { @@ -84,12 +69,12 @@ class UserLiveStatusListenerTest extends TestCase { $userStatus->setStatusTimestamp($previousTimestamp); $userStatus->setIsUserDefined($previousIsUserDefined); - $this->mapper->expects($this->once()) + $this->statusService->expects($this->once()) ->method('findByUserId') ->with($userId) ->willReturn($userStatus); } else { - $this->mapper->expects($this->once()) + $this->statusService->expects($this->once()) ->method('findByUserId') ->with($userId) ->willThrowException(new DoesNotExistException('')); @@ -141,7 +126,7 @@ class UserLiveStatusListenerTest extends TestCase { } } - public function handleEventWithCorrectEventDataProvider(): array { + public static function handleEventWithCorrectEventDataProvider(): array { return [ ['john.doe', 'offline', 0, false, 'online', 5000, true, true], ['john.doe', 'offline', 0, false, 'online', 5000, false, true], diff --git a/apps/user_status/tests/Unit/Service/EmojiServiceTest.php b/apps/user_status/tests/Unit/Service/EmojiServiceTest.php deleted file mode 100644 index e622a7eabcd..00000000000 --- a/apps/user_status/tests/Unit/Service/EmojiServiceTest.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OCA\UserStatus\Tests\Service; - -use OCA\UserStatus\Service\EmojiService; -use OCP\IDBConnection; -use Test\TestCase; - -class EmojiServiceTest extends TestCase { - - /** @var IDBConnection|\PHPUnit\Framework\MockObject\MockObject */ - private $db; - - /** @var EmojiService */ - private $service; - - protected function setUp(): void { - parent::setUp(); - - $this->db = $this->createMock(IDBConnection::class); - $this->service = new EmojiService($this->db); - } - - /** - * @param bool $supports4ByteText - * @param bool $expected - * - * @dataProvider doesPlatformSupportEmojiDataProvider - */ - public function testDoesPlatformSupportEmoji(bool $supports4ByteText, bool $expected): void { - $this->db->expects($this->once()) - ->method('supports4ByteText') - ->willReturn($supports4ByteText); - - $this->assertEquals($expected, $this->service->doesPlatformSupportEmoji()); - } - - /** - * @return array - */ - public function doesPlatformSupportEmojiDataProvider(): array { - return [ - [true, true], - [false, false], - ]; - } - - /** - * @param string $emoji - * @param bool $expected - * - * @dataProvider isValidEmojiDataProvider - */ - public function testIsValidEmoji(string $emoji, bool $expected): void { - $actual = $this->service->isValidEmoji($emoji); - - $this->assertEquals($expected, $actual); - } - - public function isValidEmojiDataProvider(): array { - return [ - ['🏝', true], - ['📱', true], - ['🏢', true], - ['📱📠', false], - ['a', false], - ['0', false], - ['$', false], - // Test some more complex emojis with modifiers and zero-width-joiner - ['👩🏿💻', true], - ['🤷🏼♀️', true], - ['🏳️🌈', true], - ['👨👨👦👦', true], - ['👩❤️👩', true] - ]; - } -} diff --git a/apps/user_status/tests/Unit/Service/PredefinedStatusServiceTest.php b/apps/user_status/tests/Unit/Service/PredefinedStatusServiceTest.php index f0634c7fbe8..78e4a18d9f1 100644 --- a/apps/user_status/tests/Unit/Service/PredefinedStatusServiceTest.php +++ b/apps/user_status/tests/Unit/Service/PredefinedStatusServiceTest.php @@ -3,39 +3,19 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests\Service; use OCA\UserStatus\Service\PredefinedStatusService; use OCP\IL10N; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class PredefinedStatusServiceTest extends TestCase { - - /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */ - protected $l10n; - - /** @var PredefinedStatusService */ - protected $service; + protected IL10N&MockObject $l10n; + protected PredefinedStatusService $service; protected function setUp(): void { parent::setUp(); @@ -46,16 +26,11 @@ class PredefinedStatusServiceTest extends TestCase { } public function testGetDefaultStatuses(): void { - $this->l10n->expects($this->exactly(5)) + $this->l10n->expects($this->exactly(8)) ->method('t') - ->withConsecutive( - ['In a meeting'], - ['Commuting'], - ['Working remotely'], - ['Out sick'], - ['Vacationing'] - ) - ->willReturnArgument(0); + ->willReturnCallback(function ($text, $parameters = []) { + return vsprintf($text, $parameters); + }); $actual = $this->service->getDefaultStatuses(); $this->assertEquals([ @@ -78,6 +53,15 @@ class PredefinedStatusServiceTest extends TestCase { ], ], [ + 'id' => 'be-right-back', + 'icon' => '⏳', + 'message' => 'Be right back', + 'clearAt' => [ + 'type' => 'period', + 'time' => 900, + ], + ], + [ 'id' => 'remote-work', 'icon' => '🏡', 'message' => 'Working remotely', @@ -101,40 +85,43 @@ class PredefinedStatusServiceTest extends TestCase { 'message' => 'Vacationing', 'clearAt' => null, ], + [ + 'id' => 'call', + 'icon' => '💬', + 'message' => 'In a call', + 'clearAt' => null, + 'visible' => false, + ], + [ + 'id' => 'out-of-office', + 'icon' => '🛑', + 'message' => 'Out of office', + 'clearAt' => null, + 'visible' => false, + ], ], $actual); } - /** - * @param string $id - * @param string|null $expectedIcon - * - * @dataProvider getIconForIdDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('getIconForIdDataProvider')] public function testGetIconForId(string $id, ?string $expectedIcon): void { $actual = $this->service->getIconForId($id); $this->assertEquals($expectedIcon, $actual); } - /** - * @return array - */ - public function getIconForIdDataProvider(): array { + public static function getIconForIdDataProvider(): array { return [ ['meeting', '📅'], ['commuting', '🚌'], ['sick-leave', '🤒'], ['vacationing', '🌴'], ['remote-work', '🏡'], + ['be-right-back', '⏳'], + ['call', '💬'], ['unknown-id', null], ]; } - /** - * @param string $id - * @param string|null $expected - * - * @dataProvider getTranslatedStatusForIdDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('getTranslatedStatusForIdDataProvider')] public function testGetTranslatedStatusForId(string $id, ?string $expected): void { $this->l10n->method('t') ->willReturnArgument(0); @@ -143,63 +130,52 @@ class PredefinedStatusServiceTest extends TestCase { $this->assertEquals($expected, $actual); } - /** - * @return array - */ - public function getTranslatedStatusForIdDataProvider(): array { + public static function getTranslatedStatusForIdDataProvider(): array { return [ ['meeting', 'In a meeting'], ['commuting', 'Commuting'], ['sick-leave', 'Out sick'], ['vacationing', 'Vacationing'], ['remote-work', 'Working remotely'], + ['be-right-back', 'Be right back'], + ['call', 'In a call'], ['unknown-id', null], ]; } - /** - * @param string $id - * @param bool $expected - * - * @dataProvider isValidIdDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('isValidIdDataProvider')] public function testIsValidId(string $id, bool $expected): void { $actual = $this->service->isValidId($id); $this->assertEquals($expected, $actual); } - /** - * @return array - */ - public function isValidIdDataProvider(): array { + public static function isValidIdDataProvider(): array { return [ ['meeting', true], ['commuting', true], ['sick-leave', true], ['vacationing', true], ['remote-work', true], + ['be-right-back', true], + ['call', true], ['unknown-id', false], ]; } public function testGetDefaultStatusById(): void { - $this->l10n->expects($this->exactly(5)) + $this->l10n->expects($this->exactly(8)) ->method('t') - ->withConsecutive( - ['In a meeting'], - ['Commuting'], - ['Working remotely'], - ['Out sick'], - ['Vacationing'] - ) - ->willReturnArgument(0); + ->willReturnCallback(function ($text, $parameters = []) { + return vsprintf($text, $parameters); + }); $this->assertEquals([ - 'id' => 'vacationing', - 'icon' => '🌴', - 'message' => 'Vacationing', + 'id' => 'call', + 'icon' => '💬', + 'message' => 'In a call', 'clearAt' => null, - ], $this->service->getDefaultStatusById('vacationing')); + 'visible' => false, + ], $this->service->getDefaultStatusById('call')); } public function testGetDefaultStatusByUnknownId(): void { diff --git a/apps/user_status/tests/Unit/Service/StatusServiceTest.php b/apps/user_status/tests/Unit/Service/StatusServiceTest.php index 1e61f5b09ca..7dfa5b0d064 100644 --- a/apps/user_status/tests/Unit/Service/StatusServiceTest.php +++ b/apps/user_status/tests/Unit/Service/StatusServiceTest.php @@ -3,28 +3,13 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Georg Ehrke - * - * @author Georg Ehrke <oc.list@georgehrke.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\UserStatus\Tests\Service; +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; +use OC\DB\Exceptions\DbalException; use OCA\UserStatus\Db\UserStatus; use OCA\UserStatus\Db\UserStatusMapper; use OCA\UserStatus\Exception\InvalidClearAtException; @@ -32,29 +17,29 @@ use OCA\UserStatus\Exception\InvalidMessageIdException; use OCA\UserStatus\Exception\InvalidStatusIconException; use OCA\UserStatus\Exception\InvalidStatusTypeException; use OCA\UserStatus\Exception\StatusMessageTooLongException; -use OCA\UserStatus\Service\EmojiService; use OCA\UserStatus\Service\PredefinedStatusService; use OCA\UserStatus\Service\StatusService; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Utility\ITimeFactory; +use OCP\DB\Exception; +use OCP\IConfig; +use OCP\IEmojiHelper; +use OCP\IUserManager; +use OCP\UserStatus\IUserStatus; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Test\TestCase; class StatusServiceTest extends TestCase { + private UserStatusMapper&MockObject $mapper; + private ITimeFactory&MockObject $timeFactory; + private PredefinedStatusService&MockObject $predefinedStatusService; + private IEmojiHelper&MockObject $emojiHelper; + private IConfig&MockObject $config; + private IUserManager&MockObject $userManager; + private LoggerInterface&MockObject $logger; - /** @var UserStatusMapper|\PHPUnit\Framework\MockObject\MockObject */ - private $mapper; - - /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ - private $timeFactory; - - /** @var PredefinedStatusService|\PHPUnit\Framework\MockObject\MockObject */ - private $predefinedStatusService; - - /** @var EmojiService|\PHPUnit\Framework\MockObject\MockObject */ - private $emojiService; - - /** @var StatusService */ - private $service; + private StatusService $service; protected function setUp(): void { parent::setUp(); @@ -62,11 +47,25 @@ class StatusServiceTest extends TestCase { $this->mapper = $this->createMock(UserStatusMapper::class); $this->timeFactory = $this->createMock(ITimeFactory::class); $this->predefinedStatusService = $this->createMock(PredefinedStatusService::class); - $this->emojiService = $this->createMock(EmojiService::class); + $this->emojiHelper = $this->createMock(IEmojiHelper::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->config = $this->createMock(IConfig::class); + $this->logger = $this->createMock(LoggerInterface::class); + + $this->config->method('getAppValue') + ->willReturnMap([ + ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'], + ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'] + ]); + $this->service = new StatusService($this->mapper, $this->timeFactory, $this->predefinedStatusService, - $this->emojiService); + $this->emojiHelper, + $this->config, + $this->userManager, + $this->logger, + ); } public function testFindAll(): void { @@ -99,14 +98,53 @@ class StatusServiceTest extends TestCase { ], $this->service->findAllRecentStatusChanges(20, 50)); } - public function testFindByUserId(): void { - $status = $this->createMock(UserStatus::class); - $this->mapper->expects($this->once()) - ->method('findByUserId') - ->with('john.doe') - ->willReturn($status); + public function testFindAllRecentStatusChangesNoEnumeration(): void { + $status1 = $this->createMock(UserStatus::class); + $status2 = $this->createMock(UserStatus::class); - $this->assertEquals($status, $this->service->findByUserId('john.doe')); + $this->mapper->method('findAllRecent') + ->with(20, 50) + ->willReturn([$status1, $status2]); + + // Rebuild $this->service with user enumeration turned off + $this->config = $this->createMock(IConfig::class); + + $this->config->method('getAppValue') + ->willReturnMap([ + ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'no'], + ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'] + ]); + + $this->service = new StatusService($this->mapper, + $this->timeFactory, + $this->predefinedStatusService, + $this->emojiHelper, + $this->config, + $this->userManager, + $this->logger, + ); + + $this->assertEquals([], $this->service->findAllRecentStatusChanges(20, 50)); + + // Rebuild $this->service with user enumeration limited to common groups + $this->config = $this->createMock(IConfig::class); + + $this->config->method('getAppValue') + ->willReturnMap([ + ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'], + ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'yes'] + ]); + + $this->service = new StatusService($this->mapper, + $this->timeFactory, + $this->predefinedStatusService, + $this->emojiHelper, + $this->config, + $this->userManager, + $this->logger, + ); + + $this->assertEquals([], $this->service->findAllRecentStatusChanges(20, 50)); } public function testFindByUserIdDoesNotExist(): void { @@ -183,30 +221,19 @@ class StatusServiceTest extends TestCase { $this->assertNull($status->getMessageId()); } - /** - * @param string $userId - * @param string $status - * @param int|null $statusTimestamp - * @param bool $isUserDefined - * @param bool $expectExisting - * @param bool $expectSuccess - * @param bool $expectTimeFactory - * @param bool $expectException - * @param string|null $expectedExceptionClass - * @param string|null $expectedExceptionMessage - * - * @dataProvider setStatusDataProvider - */ - public function testSetStatus(string $userId, - string $status, - ?int $statusTimestamp, - bool $isUserDefined, - bool $expectExisting, - bool $expectSuccess, - bool $expectTimeFactory, - bool $expectException, - ?string $expectedExceptionClass, - ?string $expectedExceptionMessage): void { + #[\PHPUnit\Framework\Attributes\DataProvider('setStatusDataProvider')] + public function testSetStatus( + string $userId, + string $status, + ?int $statusTimestamp, + bool $isUserDefined, + bool $expectExisting, + bool $expectSuccess, + bool $expectTimeFactory, + bool $expectException, + ?string $expectedExceptionClass, + ?string $expectedExceptionMessage, + ): void { $userStatus = new UserStatus(); if ($expectExisting) { @@ -257,7 +284,7 @@ class StatusServiceTest extends TestCase { } } - public function setStatusDataProvider(): array { + public static function setStatusDataProvider(): array { return [ ['john.doe', 'online', 50, true, true, true, false, false, null, null], ['john.doe', 'online', 50, true, false, true, false, false, null, null], @@ -315,28 +342,18 @@ class StatusServiceTest extends TestCase { ]; } - /** - * @param string $userId - * @param string $messageId - * @param bool $isValidMessageId - * @param int|null $clearAt - * @param bool $expectExisting - * @param bool $expectSuccess - * @param bool $expectException - * @param string|null $expectedExceptionClass - * @param string|null $expectedExceptionMessage - * - * @dataProvider setPredefinedMessageDataProvider - */ - public function testSetPredefinedMessage(string $userId, - string $messageId, - bool $isValidMessageId, - ?int $clearAt, - bool $expectExisting, - bool $expectSuccess, - bool $expectException, - ?string $expectedExceptionClass, - ?string $expectedExceptionMessage): void { + #[\PHPUnit\Framework\Attributes\DataProvider('setPredefinedMessageDataProvider')] + public function testSetPredefinedMessage( + string $userId, + string $messageId, + bool $isValidMessageId, + ?int $clearAt, + bool $expectExisting, + bool $expectSuccess, + bool $expectException, + ?string $expectedExceptionClass, + ?string $expectedExceptionMessage, + ): void { $userStatus = new UserStatus(); if ($expectExisting) { @@ -399,7 +416,7 @@ class StatusServiceTest extends TestCase { } } - public function setPredefinedMessageDataProvider(): array { + public static function setPredefinedMessageDataProvider(): array { return [ ['john.doe', 'sick-leave', true, null, true, true, false, null, null], ['john.doe', 'sick-leave', true, null, false, true, false, null, null], @@ -412,30 +429,19 @@ class StatusServiceTest extends TestCase { ]; } - /** - * @param string $userId - * @param string|null $statusIcon - * @param bool $supportsEmoji - * @param string $message - * @param int|null $clearAt - * @param bool $expectExisting - * @param bool $expectSuccess - * @param bool $expectException - * @param string|null $expectedExceptionClass - * @param string|null $expectedExceptionMessage - * - * @dataProvider setCustomMessageDataProvider - */ - public function testSetCustomMessage(string $userId, - ?string $statusIcon, - bool $supportsEmoji, - string $message, - ?int $clearAt, - bool $expectExisting, - bool $expectSuccess, - bool $expectException, - ?string $expectedExceptionClass, - ?string $expectedExceptionMessage): void { + #[\PHPUnit\Framework\Attributes\DataProvider('setCustomMessageDataProvider')] + public function testSetCustomMessage( + string $userId, + ?string $statusIcon, + bool $supportsEmoji, + string $message, + ?int $clearAt, + bool $expectExisting, + bool $expectSuccess, + bool $expectException, + ?string $expectedExceptionClass, + ?string $expectedExceptionMessage, + ): void { $userStatus = new UserStatus(); if ($expectExisting) { @@ -457,7 +463,7 @@ class StatusServiceTest extends TestCase { ->willThrowException(new DoesNotExistException('')); } - $this->emojiService->method('isValidEmoji') + $this->emojiHelper->method('isValidSingleEmoji') ->with($statusIcon) ->willReturn($supportsEmoji); @@ -496,7 +502,7 @@ class StatusServiceTest extends TestCase { } } - public function setCustomMessageDataProvider(): array { + public static function setCustomMessageDataProvider(): array { return [ ['john.doe', '😁', true, 'Custom message', null, true, true, false, null, null], ['john.doe', '😁', true, 'Custom message', null, false, true, false, null, null], @@ -623,4 +629,200 @@ class StatusServiceTest extends TestCase { $actual = $this->service->removeUserStatus('john.doe'); $this->assertFalse($actual); } + + public function testCleanStatusAutomaticOnline(): void { + $status = new UserStatus(); + $status->setStatus(IUserStatus::ONLINE); + $status->setStatusTimestamp(1337); + $status->setIsUserDefined(false); + + $this->mapper->expects(self::once()) + ->method('update') + ->with($status); + + parent::invokePrivate($this->service, 'cleanStatus', [$status]); + } + + public function testCleanStatusCustomOffline(): void { + $status = new UserStatus(); + $status->setStatus(IUserStatus::OFFLINE); + $status->setStatusTimestamp(1337); + $status->setIsUserDefined(true); + + $this->mapper->expects(self::once()) + ->method('update') + ->with($status); + + parent::invokePrivate($this->service, 'cleanStatus', [$status]); + } + + public function testCleanStatusCleanedAlready(): void { + $status = new UserStatus(); + $status->setStatus(IUserStatus::OFFLINE); + $status->setStatusTimestamp(1337); + $status->setIsUserDefined(false); + + // Don't update the status again and again when no value changed + $this->mapper->expects(self::never()) + ->method('update') + ->with($status); + + parent::invokePrivate($this->service, 'cleanStatus', [$status]); + } + + public function testBackupWorkingHasBackupAlready(): void { + $p = $this->createMock(UniqueConstraintViolationException::class); + $e = DbalException::wrap($p); + $this->mapper->expects($this->once()) + ->method('createBackupStatus') + ->with('john') + ->willThrowException($e); + + $this->assertFalse($this->service->backupCurrentStatus('john')); + } + + public function testBackupThrowsOther(): void { + $e = new Exception('', Exception::REASON_CONNECTION_LOST); + $this->mapper->expects($this->once()) + ->method('createBackupStatus') + ->with('john') + ->willThrowException($e); + + $this->expectException(Exception::class); + $this->service->backupCurrentStatus('john'); + } + + public function testBackup(): void { + $this->mapper->expects($this->once()) + ->method('createBackupStatus') + ->with('john') + ->willReturn(true); + + $this->assertTrue($this->service->backupCurrentStatus('john')); + } + + public function testRevertMultipleUserStatus(): void { + $john = new UserStatus(); + $john->setId(1); + $john->setStatus(IUserStatus::AWAY); + $john->setStatusTimestamp(1337); + $john->setIsUserDefined(false); + $john->setMessageId('call'); + $john->setUserId('john'); + $john->setIsBackup(false); + + $johnBackup = new UserStatus(); + $johnBackup->setId(2); + $johnBackup->setStatus(IUserStatus::ONLINE); + $johnBackup->setStatusTimestamp(1337); + $johnBackup->setIsUserDefined(true); + $johnBackup->setMessageId('hello'); + $johnBackup->setUserId('_john'); + $johnBackup->setIsBackup(true); + + $noBackup = new UserStatus(); + $noBackup->setId(3); + $noBackup->setStatus(IUserStatus::AWAY); + $noBackup->setStatusTimestamp(1337); + $noBackup->setIsUserDefined(false); + $noBackup->setMessageId('call'); + $noBackup->setUserId('nobackup'); + $noBackup->setIsBackup(false); + + $backupOnly = new UserStatus(); + $backupOnly->setId(4); + $backupOnly->setStatus(IUserStatus::ONLINE); + $backupOnly->setStatusTimestamp(1337); + $backupOnly->setIsUserDefined(true); + $backupOnly->setMessageId('hello'); + $backupOnly->setUserId('_backuponly'); + $backupOnly->setIsBackup(true); + + $noBackupDND = new UserStatus(); + $noBackupDND->setId(5); + $noBackupDND->setStatus(IUserStatus::DND); + $noBackupDND->setStatusTimestamp(1337); + $noBackupDND->setIsUserDefined(false); + $noBackupDND->setMessageId('call'); + $noBackupDND->setUserId('nobackupanddnd'); + $noBackupDND->setIsBackup(false); + + $this->mapper->expects($this->once()) + ->method('findByUserIds') + ->with(['john', 'nobackup', 'backuponly', 'nobackupanddnd', '_john', '_nobackup', '_backuponly', '_nobackupanddnd']) + ->willReturn([ + $john, + $johnBackup, + $noBackup, + $backupOnly, + $noBackupDND, + ]); + + $this->mapper->expects($this->once()) + ->method('deleteByIds') + ->with([1, 3, 5]); + + $this->mapper->expects($this->once()) + ->method('restoreBackupStatuses') + ->with([2]); + + $this->service->revertMultipleUserStatus(['john', 'nobackup', 'backuponly', 'nobackupanddnd'], 'call'); + } + + public static function dataSetUserStatus(): array { + return [ + [IUserStatus::MESSAGE_CALENDAR_BUSY, '', false], + + // Call > Meeting + [IUserStatus::MESSAGE_CALENDAR_BUSY, IUserStatus::MESSAGE_CALL, false], + [IUserStatus::MESSAGE_CALL, IUserStatus::MESSAGE_CALENDAR_BUSY, true], + + // Availability > Call&Meeting + [IUserStatus::MESSAGE_CALENDAR_BUSY, IUserStatus::MESSAGE_AVAILABILITY, false], + [IUserStatus::MESSAGE_CALL, IUserStatus::MESSAGE_AVAILABILITY, false], + [IUserStatus::MESSAGE_AVAILABILITY, IUserStatus::MESSAGE_CALENDAR_BUSY, true], + [IUserStatus::MESSAGE_AVAILABILITY, IUserStatus::MESSAGE_CALL, true], + + // Out-of-office > Availability&Call&Meeting + [IUserStatus::MESSAGE_AVAILABILITY, IUserStatus::MESSAGE_OUT_OF_OFFICE, false], + [IUserStatus::MESSAGE_CALENDAR_BUSY, IUserStatus::MESSAGE_OUT_OF_OFFICE, false], + [IUserStatus::MESSAGE_CALL, IUserStatus::MESSAGE_OUT_OF_OFFICE, false], + [IUserStatus::MESSAGE_OUT_OF_OFFICE, IUserStatus::MESSAGE_AVAILABILITY, true], + [IUserStatus::MESSAGE_OUT_OF_OFFICE, IUserStatus::MESSAGE_CALENDAR_BUSY, true], + [IUserStatus::MESSAGE_OUT_OF_OFFICE, IUserStatus::MESSAGE_CALL, true], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataSetUserStatus')] + public function testSetUserStatus(string $messageId, string $oldMessageId, bool $expectedUpdateShortcut): void { + $previous = new UserStatus(); + $previous->setId(1); + $previous->setStatus(IUserStatus::AWAY); + $previous->setStatusTimestamp(1337); + $previous->setIsUserDefined(false); + $previous->setMessageId($oldMessageId); + $previous->setUserId('john'); + $previous->setIsBackup(false); + + $this->mapper->expects($this->once()) + ->method('findByUserId') + ->with('john') + ->willReturn($previous); + + $e = DbalException::wrap($this->createMock(UniqueConstraintViolationException::class)); + $this->mapper->expects($expectedUpdateShortcut ? $this->never() : $this->once()) + ->method('createBackupStatus') + ->willThrowException($e); + + $this->mapper->expects($this->any()) + ->method('update') + ->willReturnArgument(0); + + $this->predefinedStatusService->expects($this->once()) + ->method('isValidId') + ->with($messageId) + ->willReturn(true); + + $this->service->setUserStatus('john', IUserStatus::DND, $messageId, true); + } } |