diff options
Diffstat (limited to 'apps/comments/tests/Unit/Notification')
-rw-r--r-- | apps/comments/tests/Unit/Notification/ListenerTest.php | 195 | ||||
-rw-r--r-- | apps/comments/tests/Unit/Notification/NotifierTest.php | 554 |
2 files changed, 749 insertions, 0 deletions
diff --git a/apps/comments/tests/Unit/Notification/ListenerTest.php b/apps/comments/tests/Unit/Notification/ListenerTest.php new file mode 100644 index 00000000000..356a26f23cd --- /dev/null +++ b/apps/comments/tests/Unit/Notification/ListenerTest.php @@ -0,0 +1,195 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Comments\Tests\Unit\Notification; + +use OCA\Comments\Notification\Listener; +use OCP\Comments\CommentsEvent; +use OCP\Comments\IComment; +use OCP\IURLGenerator; +use OCP\IUserManager; +use OCP\Notification\IManager; +use OCP\Notification\INotification; +use PHPUnit\Framework\MockObject\MockObject; +use Test\TestCase; + +class ListenerTest extends TestCase { + protected IManager&MockObject $notificationManager; + protected IUserManager&MockObject $userManager; + protected IURLGenerator&MockObject $urlGenerator; + protected Listener $listener; + + protected function setUp(): void { + parent::setUp(); + + $this->notificationManager = $this->createMock(IManager::class); + $this->userManager = $this->createMock(IUserManager::class); + + $this->listener = new Listener( + $this->notificationManager, + $this->userManager + ); + } + + public static function eventProvider(): array { + return [ + [CommentsEvent::EVENT_ADD, 'notify'], + [CommentsEvent::EVENT_UPDATE, 'notify'], + [CommentsEvent::EVENT_PRE_UPDATE, 'markProcessed'], + [CommentsEvent::EVENT_DELETE, 'markProcessed'] + ]; + } + + /** + * @param string $eventType + * @param string $notificationMethod + */ + #[\PHPUnit\Framework\Attributes\DataProvider('eventProvider')] + public function testEvaluate($eventType, $notificationMethod): void { + /** @var IComment|MockObject $comment */ + $comment = $this->createMock(IComment::class); + $comment->expects($this->any()) + ->method('getObjectType') + ->willReturn('files'); + $comment->expects($this->any()) + ->method('getCreationDateTime') + ->willReturn(new \DateTime()); + $comment->expects($this->once()) + ->method('getMentions') + ->willReturn([ + [ 'type' => 'user', 'id' => 'foobar'], + [ 'type' => 'user', 'id' => 'barfoo'], + [ 'type' => 'user', 'id' => 'foo@bar.com'], + [ 'type' => 'user', 'id' => 'bar@foo.org@foobar.io'], + [ 'type' => 'user', 'id' => '23452-4333-54353-2342'], + [ 'type' => 'user', 'id' => 'yolo'], + ]); + $comment->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn('1234'); + + /** @var CommentsEvent|MockObject $event */ + $event = $this->createMock(CommentsEvent::class); + $event->expects($this->once()) + ->method('getComment') + ->willReturn($comment); + $event->expects(($this->any())) + ->method(('getEvent')) + ->willReturn($eventType); + + /** @var INotification|MockObject $notification */ + $notification = $this->createMock(INotification::class); + $notification->expects($this->any()) + ->method($this->anything()) + ->willReturn($notification); + $notification->expects($this->exactly(6)) + ->method('setUser'); + + $this->notificationManager->expects($this->once()) + ->method('createNotification') + ->willReturn($notification); + $this->notificationManager->expects($this->exactly(6)) + ->method($notificationMethod) + ->with($this->isInstanceOf('\OCP\Notification\INotification')); + + $this->userManager->expects($this->exactly(6)) + ->method('userExists') + ->willReturnMap([ + ['foobar', true], + ['barfoo', true], + ['foo@bar.com', true], + ['bar@foo.org@foobar.io', true], + ['23452-4333-54353-2342', true], + ['yolo', true] + ]); + + $this->listener->evaluate($event); + } + + #[\PHPUnit\Framework\Attributes\DataProvider('eventProvider')] + public function testEvaluateNoMentions(string $eventType): void { + /** @var IComment|MockObject $comment */ + $comment = $this->createMock(IComment::class); + $comment->expects($this->any()) + ->method('getObjectType') + ->willReturn('files'); + $comment->expects($this->any()) + ->method('getCreationDateTime') + ->willReturn(new \DateTime()); + $comment->expects($this->once()) + ->method('getMentions') + ->willReturn([]); + + /** @var CommentsEvent|MockObject $event */ + $event = $this->createMock(CommentsEvent::class); + $event->expects($this->once()) + ->method('getComment') + ->willReturn($comment); + $event->expects(($this->any())) + ->method(('getEvent')) + ->willReturn($eventType); + + $this->notificationManager->expects($this->never()) + ->method('createNotification'); + $this->notificationManager->expects($this->never()) + ->method('notify'); + $this->notificationManager->expects($this->never()) + ->method('markProcessed'); + + $this->userManager->expects($this->never()) + ->method('userExists'); + + $this->listener->evaluate($event); + } + + public function testEvaluateUserDoesNotExist(): void { + /** @var IComment|MockObject $comment */ + $comment = $this->createMock(IComment::class); + $comment->expects($this->any()) + ->method('getObjectType') + ->willReturn('files'); + $comment->expects($this->any()) + ->method('getCreationDateTime') + ->willReturn(new \DateTime()); + $comment->expects($this->once()) + ->method('getMentions') + ->willReturn([[ 'type' => 'user', 'id' => 'foobar']]); + $comment->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn('1234'); + + /** @var CommentsEvent|MockObject $event */ + $event = $this->createMock(CommentsEvent::class); + $event->expects($this->once()) + ->method('getComment') + ->willReturn($comment); + $event->expects(($this->any())) + ->method(('getEvent')) + ->willReturn(CommentsEvent::EVENT_ADD); + + /** @var INotification|MockObject $notification */ + $notification = $this->createMock(INotification::class); + $notification->expects($this->any()) + ->method($this->anything()) + ->willReturn($notification); + $notification->expects($this->never()) + ->method('setUser'); + + $this->notificationManager->expects($this->once()) + ->method('createNotification') + ->willReturn($notification); + $this->notificationManager->expects($this->never()) + ->method('notify'); + + $this->userManager->expects($this->once()) + ->method('userExists') + ->with('foobar') + ->willReturn(false); + + $this->listener->evaluate($event); + } +} diff --git a/apps/comments/tests/Unit/Notification/NotifierTest.php b/apps/comments/tests/Unit/Notification/NotifierTest.php new file mode 100644 index 00000000000..37cad0b43df --- /dev/null +++ b/apps/comments/tests/Unit/Notification/NotifierTest.php @@ -0,0 +1,554 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\Comments\Tests\Unit\Notification; + +use OCA\Comments\Notification\Notifier; +use OCP\Comments\IComment; +use OCP\Comments\ICommentsManager; +use OCP\Comments\NotFoundException; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\Files\Node; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\IUserManager; +use OCP\L10N\IFactory; +use OCP\Notification\AlreadyProcessedException; +use OCP\Notification\INotification; +use OCP\Notification\UnknownNotificationException; +use PHPUnit\Framework\MockObject\MockObject; +use Test\TestCase; + +class NotifierTest extends TestCase { + protected IFactory&MockObject $l10nFactory; + protected IL10N&MockObject $l; + protected IRootFolder&MockObject $folder; + protected ICommentsManager&MockObject $commentsManager; + protected IURLGenerator&MockObject $url; + protected IUserManager&MockObject $userManager; + protected INotification&MockObject $notification; + protected IComment&MockObject $comment; + protected Notifier $notifier; + protected string $lc = 'tlh_KX'; + + protected function setUp(): void { + parent::setUp(); + + $this->l10nFactory = $this->createMock(IFactory::class); + $this->folder = $this->createMock(IRootFolder::class); + $this->commentsManager = $this->createMock(ICommentsManager::class); + $this->url = $this->createMock(IURLGenerator::class); + $this->userManager = $this->createMock(IUserManager::class); + + $this->notifier = new Notifier( + $this->l10nFactory, + $this->folder, + $this->commentsManager, + $this->url, + $this->userManager + ); + + $this->l = $this->createMock(IL10N::class); + $this->l->expects($this->any()) + ->method('t') + ->willReturnCallback(function ($text, $parameters = []) { + return vsprintf($text, $parameters); + }); + + $this->notification = $this->createMock(INotification::class); + $this->comment = $this->createMock(IComment::class); + } + + public function testPrepareSuccess(): void { + $fileName = 'Gre\'thor.odp'; + $displayName = 'Huraga'; + + /** @var Node&MockObject $node */ + $node = $this->createMock(Node::class); + $node + ->expects($this->atLeastOnce()) + ->method('getName') + ->willReturn($fileName); + $node + ->expects($this->atLeastOnce()) + ->method('getPath') + ->willReturn('/you/files/' . $fileName); + + $userFolder = $this->createMock(Folder::class); + $this->folder->expects($this->once()) + ->method('getUserFolder') + ->with('you') + ->willReturn($userFolder); + $userFolder->expects($this->once()) + ->method('getById') + ->with('678') + ->willReturn([$node]); + + $this->notification->expects($this->exactly(2)) + ->method('getUser') + ->willReturn('you'); + $this->notification + ->expects($this->once()) + ->method('getApp') + ->willReturn('comments'); + $this->notification + ->expects($this->once()) + ->method('getSubject') + ->willReturn('mention'); + $this->notification + ->expects($this->once()) + ->method('getSubjectParameters') + ->willReturn(['files', '678']); + $this->notification + ->expects($this->never()) + ->method('setParsedSubject'); + $this->notification + ->expects($this->once()) + ->method('setRichSubject') + ->with('{user} mentioned you in a comment on "{file}"', $this->anything()) + ->willReturnSelf(); + $this->notification + ->expects($this->once()) + ->method('setRichMessage') + ->with('Hi {mention-user1}!', ['mention-user1' => ['type' => 'user', 'id' => 'you', 'name' => 'Your name']]) + ->willReturnSelf(); + $this->notification + ->expects($this->never()) + ->method('setParsedMessage'); + $this->notification + ->expects($this->once()) + ->method('setIcon') + ->with('absolute-image-path') + ->willReturnSelf(); + + $this->url->expects($this->once()) + ->method('imagePath') + ->with('core', 'actions/comment.svg') + ->willReturn('image-path'); + $this->url->expects($this->once()) + ->method('getAbsoluteURL') + ->with('image-path') + ->willReturn('absolute-image-path'); + + $this->l10nFactory + ->expects($this->once()) + ->method('get') + ->willReturn($this->l); + + $this->comment + ->expects($this->any()) + ->method('getActorId') + ->willReturn('huraga'); + $this->comment + ->expects($this->any()) + ->method('getActorType') + ->willReturn('users'); + $this->comment + ->expects($this->any()) + ->method('getMessage') + ->willReturn('Hi @you!'); + $this->comment + ->expects($this->any()) + ->method('getMentions') + ->willReturn([['type' => 'user', 'id' => 'you']]); + $this->comment->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn('1234'); + + $this->commentsManager + ->expects($this->once()) + ->method('get') + ->willReturn($this->comment); + $this->commentsManager + ->expects($this->once()) + ->method('resolveDisplayName') + ->with('user', 'you') + ->willReturn('Your name'); + + $this->userManager + ->expects($this->exactly(2)) + ->method('getDisplayName') + ->willReturnMap([ + ['huraga', $displayName], + ['you', 'You'], + ]); + + $this->notifier->prepare($this->notification, $this->lc); + } + + public function testPrepareSuccessDeletedUser(): void { + $fileName = 'Gre\'thor.odp'; + + /** @var Node|MockObject $node */ + $node = $this->createMock(Node::class); + $node + ->expects($this->atLeastOnce()) + ->method('getName') + ->willReturn($fileName); + $node + ->expects($this->atLeastOnce()) + ->method('getPath') + ->willReturn('/you/files/' . $fileName); + + $userFolder = $this->createMock(Folder::class); + $this->folder->expects($this->once()) + ->method('getUserFolder') + ->with('you') + ->willReturn($userFolder); + $userFolder->expects($this->once()) + ->method('getById') + ->with('678') + ->willReturn([$node]); + + $this->notification->expects($this->exactly(2)) + ->method('getUser') + ->willReturn('you'); + $this->notification + ->expects($this->once()) + ->method('getApp') + ->willReturn('comments'); + $this->notification + ->expects($this->once()) + ->method('getSubject') + ->willReturn('mention'); + $this->notification + ->expects($this->once()) + ->method('getSubjectParameters') + ->willReturn(['files', '678']); + $this->notification + ->expects($this->never()) + ->method('setParsedSubject'); + $this->notification + ->expects($this->once()) + ->method('setRichSubject') + ->with('You were mentioned on "{file}", in a comment by an account that has since been deleted', $this->anything()) + ->willReturnSelf(); + $this->notification + ->expects($this->once()) + ->method('setRichMessage') + ->with('Hi {mention-user1}!', ['mention-user1' => ['type' => 'user', 'id' => 'you', 'name' => 'Your name']]) + ->willReturnSelf(); + $this->notification + ->expects($this->never()) + ->method('setParsedMessage'); + $this->notification + ->expects($this->once()) + ->method('setIcon') + ->with('absolute-image-path') + ->willReturnSelf(); + + $this->url->expects($this->once()) + ->method('imagePath') + ->with('core', 'actions/comment.svg') + ->willReturn('image-path'); + $this->url->expects($this->once()) + ->method('getAbsoluteURL') + ->with('image-path') + ->willReturn('absolute-image-path'); + + $this->l10nFactory + ->expects($this->once()) + ->method('get') + ->willReturn($this->l); + + $this->comment + ->expects($this->any()) + ->method('getActorId') + ->willReturn('huraga'); + $this->comment + ->expects($this->any()) + ->method('getActorType') + ->willReturn(ICommentsManager::DELETED_USER); + $this->comment + ->expects($this->any()) + ->method('getMessage') + ->willReturn('Hi @you!'); + $this->comment + ->expects($this->any()) + ->method('getMentions') + ->willReturn([['type' => 'user', 'id' => 'you']]); + + $this->commentsManager + ->expects($this->once()) + ->method('get') + ->willReturn($this->comment); + $this->commentsManager + ->expects($this->once()) + ->method('resolveDisplayName') + ->with('user', 'you') + ->willReturn('Your name'); + + $this->userManager + ->expects($this->once()) + ->method('getDisplayName') + ->willReturnMap([ + ['huraga', null], + ['you', 'You'], + ]); + + $this->notifier->prepare($this->notification, $this->lc); + } + + + public function testPrepareDifferentApp(): void { + $this->expectException(UnknownNotificationException::class); + + $this->folder + ->expects($this->never()) + ->method('getById'); + + $this->notification + ->expects($this->once()) + ->method('getApp') + ->willReturn('constructions'); + $this->notification + ->expects($this->never()) + ->method('getSubject'); + $this->notification + ->expects($this->never()) + ->method('getSubjectParameters'); + $this->notification + ->expects($this->never()) + ->method('setParsedSubject'); + + $this->l10nFactory + ->expects($this->never()) + ->method('get'); + + $this->commentsManager + ->expects($this->never()) + ->method('get'); + + $this->userManager + ->expects($this->never()) + ->method('getDisplayName'); + + $this->notifier->prepare($this->notification, $this->lc); + } + + + public function testPrepareNotFound(): void { + $this->expectException(UnknownNotificationException::class); + + $this->folder + ->expects($this->never()) + ->method('getById'); + + $this->notification + ->expects($this->once()) + ->method('getApp') + ->willReturn('comments'); + $this->notification + ->expects($this->never()) + ->method('getSubject'); + $this->notification + ->expects($this->never()) + ->method('getSubjectParameters'); + $this->notification + ->expects($this->never()) + ->method('setParsedSubject'); + + $this->l10nFactory + ->expects($this->never()) + ->method('get'); + + $this->commentsManager + ->expects($this->once()) + ->method('get') + ->willThrowException(new NotFoundException()); + + $this->userManager + ->expects($this->never()) + ->method('getDisplayName'); + + $this->notifier->prepare($this->notification, $this->lc); + } + + + public function testPrepareDifferentSubject(): void { + $this->expectException(UnknownNotificationException::class); + + $displayName = 'Huraga'; + + $this->folder + ->expects($this->never()) + ->method('getById'); + + $this->notification + ->expects($this->once()) + ->method('getApp') + ->willReturn('comments'); + $this->notification + ->expects($this->once()) + ->method('getSubject') + ->willReturn('unlike'); + $this->notification + ->expects($this->never()) + ->method('getSubjectParameters'); + $this->notification + ->expects($this->never()) + ->method('setParsedSubject'); + + $this->l + ->expects($this->never()) + ->method('t'); + + $this->l10nFactory + ->expects($this->once()) + ->method('get') + ->willReturn($this->l); + + $this->comment + ->expects($this->any()) + ->method('getActorId') + ->willReturn('huraga'); + $this->comment + ->expects($this->any()) + ->method('getActorType') + ->willReturn('users'); + + $this->commentsManager + ->expects($this->once()) + ->method('get') + ->willReturn($this->comment); + + $this->userManager + ->expects($this->once()) + ->method('getDisplayName') + ->with('huraga') + ->willReturn($displayName); + + $this->notifier->prepare($this->notification, $this->lc); + } + + + public function testPrepareNotFiles(): void { + $this->expectException(UnknownNotificationException::class); + + $displayName = 'Huraga'; + + $this->folder + ->expects($this->never()) + ->method('getById'); + + $this->notification + ->expects($this->once()) + ->method('getApp') + ->willReturn('comments'); + $this->notification + ->expects($this->once()) + ->method('getSubject') + ->willReturn('mention'); + $this->notification + ->expects($this->once()) + ->method('getSubjectParameters') + ->willReturn(['ships', '678']); + $this->notification + ->expects($this->never()) + ->method('setParsedSubject'); + + $this->l + ->expects($this->never()) + ->method('t'); + + $this->l10nFactory + ->expects($this->once()) + ->method('get') + ->willReturn($this->l); + + $this->comment + ->expects($this->any()) + ->method('getActorId') + ->willReturn('huraga'); + $this->comment + ->expects($this->any()) + ->method('getActorType') + ->willReturn('users'); + + $this->commentsManager + ->expects($this->once()) + ->method('get') + ->willReturn($this->comment); + + $this->userManager + ->expects($this->once()) + ->method('getDisplayName') + ->with('huraga') + ->willReturn($displayName); + + $this->notifier->prepare($this->notification, $this->lc); + } + + + public function testPrepareUnresolvableFileID(): void { + $this->expectException(AlreadyProcessedException::class); + + $displayName = 'Huraga'; + + $userFolder = $this->createMock(Folder::class); + $this->folder->expects($this->once()) + ->method('getUserFolder') + ->with('you') + ->willReturn($userFolder); + $userFolder->expects($this->once()) + ->method('getById') + ->with('678') + ->willReturn([]); + + $this->notification->expects($this->once()) + ->method('getUser') + ->willReturn('you'); + $this->notification + ->expects($this->once()) + ->method('getApp') + ->willReturn('comments'); + $this->notification + ->expects($this->once()) + ->method('getSubject') + ->willReturn('mention'); + $this->notification + ->expects($this->once()) + ->method('getSubjectParameters') + ->willReturn(['files', '678']); + $this->notification + ->expects($this->never()) + ->method('setParsedSubject'); + + $this->l + ->expects($this->never()) + ->method('t'); + + $this->l10nFactory + ->expects($this->once()) + ->method('get') + ->willReturn($this->l); + + $this->comment + ->expects($this->any()) + ->method('getActorId') + ->willReturn('huraga'); + $this->comment + ->expects($this->any()) + ->method('getActorType') + ->willReturn('users'); + + $this->commentsManager + ->expects($this->once()) + ->method('get') + ->willReturn($this->comment); + + $this->userManager + ->expects($this->once()) + ->method('getDisplayName') + ->with('huraga') + ->willReturn($displayName); + + $this->notifier->prepare($this->notification, $this->lc); + } +} |