diff options
author | Arthur Schiwon <blizzz@owncloud.com> | 2016-05-09 10:02:07 +0200 |
---|---|---|
committer | Arthur Schiwon <blizzz@arthur-schiwon.de> | 2016-10-07 17:11:19 +0200 |
commit | e1073cf442613ac92878c8ded30a33db35b30e14 (patch) | |
tree | 43bf514650829b6a4684cb564c62b3785f60b188 /apps/comments | |
parent | 9e7824f3edcb498447915a396e93678ddb6f5768 (diff) | |
download | nextcloud-server-e1073cf442613ac92878c8ded30a33db35b30e14.tar.gz nextcloud-server-e1073cf442613ac92878c8ded30a33db35b30e14.zip |
Notificacations for simple @-mentioning in comments
(WIP) notify user when mentioned in comments
Fix doc, and create absolute URL for as notification link.
PSR-4 compatibility changes
also move notification creation to comments app
Do not notify yourself
unit test for controller and application
smaller fixes
- translatable app name
- remove doubles in mention array
- micro perf optimization
- display name: special label for deleted users, keep user id for users that could not be fetched from userManager
Comment Notification-Listener Unit Test
fix email adresses
remove notification when triggering comment was deleted
add and adjust tests
add missing @license tags
simplify NotificationsController registration
appinfo simplification, php docs
make string easier to translate
adjust test
replace dispatcher-based listeners with a registration method and interface
safer to not pass optional data parameter to setSubject for marking as processed. ID and mention suffices
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
update comment
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
Diffstat (limited to 'apps/comments')
-rw-r--r-- | apps/comments/appinfo/app.php | 31 | ||||
-rw-r--r-- | apps/comments/appinfo/routes.php | 28 | ||||
-rw-r--r-- | apps/comments/lib/AppInfo/Application.php | 35 | ||||
-rw-r--r-- | apps/comments/lib/Controller/Notifications.php | 138 | ||||
-rw-r--r-- | apps/comments/lib/EventHandler.php | 78 | ||||
-rw-r--r-- | apps/comments/lib/Notification/Listener.php | 130 | ||||
-rw-r--r-- | apps/comments/lib/Notification/Notifier.php | 115 | ||||
-rw-r--r-- | apps/comments/tests/Unit/AppInfo/ApplicationTest.php | 65 | ||||
-rw-r--r-- | apps/comments/tests/Unit/Controller/NotificationsTest.php | 162 | ||||
-rw-r--r-- | apps/comments/tests/Unit/EventHandlerTest.php | 152 | ||||
-rw-r--r-- | apps/comments/tests/Unit/Notification/ListenerTest.php | 360 | ||||
-rw-r--r-- | apps/comments/tests/Unit/Notification/NotifierTest.php | 499 |
12 files changed, 1783 insertions, 10 deletions
diff --git a/apps/comments/appinfo/app.php b/apps/comments/appinfo/app.php index df41bdfa32d..771b35d9c6a 100644 --- a/apps/comments/appinfo/app.php +++ b/apps/comments/appinfo/app.php @@ -41,22 +41,33 @@ $activityManager = \OC::$server->getActivityManager(); $activityManager->registerExtension(function() { $application = new \OCP\AppFramework\App('comments'); /** @var \OCA\Comments\Activity\Extension $extension */ - $extension = $application->getContainer()->query('OCA\Comments\Activity\Extension'); + $extension = $application->getContainer()->query(\OCA\Comments\Activity\Extension::class); return $extension; }); -$managerListener = function(\OCP\Comments\CommentsEvent $event) use ($activityManager) { - $application = new \OCP\AppFramework\App('comments'); - /** @var \OCA\Comments\Activity\Listener $listener */ - $listener = $application->getContainer()->query('OCA\Comments\Activity\Listener'); - $listener->commentEvent($event); -}; - -$eventDispatcher->addListener(\OCP\Comments\CommentsEvent::EVENT_ADD, $managerListener); - $eventDispatcher->addListener(\OCP\Comments\CommentsEntityEvent::EVENT_ENTITY, function(\OCP\Comments\CommentsEntityEvent $event) { $event->addEntityCollection('files', function($name) { $nodes = \OC::$server->getUserFolder()->getById(intval($name)); return !empty($nodes); }); }); + +$notificationManager = \OC::$server->getNotificationManager(); +$notificationManager->registerNotifier( + function() { + $application = new \OCP\AppFramework\App('comments'); + return $application->getContainer()->query(\OCA\Comments\Notification\Notifier::class); + }, + function () { + $l = \OC::$server->getL10N('comments'); + return ['id' => 'comments', 'name' => $l->t('Comments')]; + } +); + +$commentsManager = \OC::$server->getCommentsManager(); +$commentsManager->registerEventHandler(function () { + $application = new \OCP\AppFramework\App('comments'); + /** @var \OCA\Comments\Activity\Extension $extension */ + $handler = $application->getContainer()->query(\OCA\Comments\EventHandler::class); + return $handler; +}); diff --git a/apps/comments/appinfo/routes.php b/apps/comments/appinfo/routes.php new file mode 100644 index 00000000000..ab751ddb2a2 --- /dev/null +++ b/apps/comments/appinfo/routes.php @@ -0,0 +1,28 @@ +<?php + +/** + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @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/> + * + */ + +use \OCA\Comments\AppInfo\Application; + +$application = new Application(); +$application->registerRoutes($this, ['routes' => [ + ['name' => 'Notifications#view', 'url' => '/notifications/view/{id}', 'verb' => 'GET'], +]]); diff --git a/apps/comments/lib/AppInfo/Application.php b/apps/comments/lib/AppInfo/Application.php new file mode 100644 index 00000000000..f168779cd0d --- /dev/null +++ b/apps/comments/lib/AppInfo/Application.php @@ -0,0 +1,35 @@ +<?php + +/** + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @license GNU AGPL version 3 or any later version + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +namespace OCA\Comments\AppInfo; + +use OCA\Comments\Controller\Notifications; +use OCP\AppFramework\App; + +class Application extends App { + + public function __construct (array $urlParams = array()) { + parent::__construct('comments', $urlParams); + $container = $this->getContainer(); + + $container->registerAlias('NotificationsController', Notifications::class); + } +} diff --git a/apps/comments/lib/Controller/Notifications.php b/apps/comments/lib/Controller/Notifications.php new file mode 100644 index 00000000000..f76f1605345 --- /dev/null +++ b/apps/comments/lib/Controller/Notifications.php @@ -0,0 +1,138 @@ +<?php + +/** + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @license GNU AGPL version 3 or any later version + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Comments\Controller; + +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\AppFramework\Http\RedirectResponse; +use OCP\AppFramework\Http\Response; +use OCP\Comments\IComment; +use OCP\Comments\ICommentsManager; +use OCP\Files\Folder; +use OCP\IRequest; +use OCP\IURLGenerator; +use OCP\IUserSession; +use OCP\Notification\IManager; + +/** + * Class Notifications + * + * @package OCA\Comments\Controller + */ +class Notifications extends Controller { + /** @var Folder */ + protected $folder; + + /** @var ICommentsManager */ + protected $commentsManager; + + /** @var IURLGenerator */ + protected $urlGenerator; + + /** @var IManager */ + protected $notificationManager; + + /** @var IUserSession */ + protected $userSession; + + /** + * Notifications constructor. + * + * @param string $appName + * @param IRequest $request + * @param ICommentsManager $commentsManager + * @param Folder $folder + * @param IURLGenerator $urlGenerator + * @param IManager $notificationManager + * @param IUserSession $userSession + */ + public function __construct( + $appName, + IRequest $request, + ICommentsManager $commentsManager, + Folder $folder, + IURLGenerator $urlGenerator, + IManager $notificationManager, + IUserSession $userSession + ) { + parent::__construct($appName, $request); + $this->commentsManager = $commentsManager; + $this->folder = $folder; + $this->urlGenerator = $urlGenerator; + $this->notificationManager = $notificationManager; + $this->userSession = $userSession; + } + + /** + * @NoAdminRequired + * @NoCSRFRequired + * + * @param string $id the comment ID + * @return Response + */ + public function view($id) { + try { + $comment = $this->commentsManager->get($id); + if($comment->getObjectType() !== 'files') { + return new NotFoundResponse(); + } + $files = $this->folder->getById($comment->getObjectId()); + if(count($files) === 0) { + $this->markProcessed($comment); + return new NotFoundResponse(); + } + + $dir = $this->folder->getRelativePath($files[0]->getParent()->getPath()); + $url = $this->urlGenerator->linkToRouteAbsolute( + 'files.view.index', + [ + 'dir' => $dir, + 'scrollto' => $files[0]->getName() + ] + ); + + $this->markProcessed($comment); + + return new RedirectResponse($url); + } catch (\Exception $e) { + return new NotFoundResponse(); + } + } + + /** + * Marks the notification about a comment as processed + * @param IComment $comment + */ + protected function markProcessed(IComment $comment) { + $user = $this->userSession->getUser(); + if(is_null($user)) { + return; + } + $notification = $this->notificationManager->createNotification(); + $notification->setApp('comments') + ->setObject('comment', $comment->getId()) + ->setSubject('mention') + ->setUser($user->getUID()); + $this->notificationManager->markProcessed($notification); + } +} diff --git a/apps/comments/lib/EventHandler.php b/apps/comments/lib/EventHandler.php new file mode 100644 index 00000000000..a32bb8ffa71 --- /dev/null +++ b/apps/comments/lib/EventHandler.php @@ -0,0 +1,78 @@ +<?php + +/** + * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Comments; + +use OCA\Comments\Activity\Listener as ActivityListener; +use OCA\Comments\AppInfo\Application; +use OCA\Comments\Notification\Listener as NotificationListener; +use OCP\Comments\CommentsEvent; +use OCP\Comments\ICommentsEventHandler; + +/** + * Class EventHandler + * + * @package OCA\Comments + */ +class EventHandler implements ICommentsEventHandler { + + /** @var Application */ + protected $app; + + public function __construct(Application $app) { + $this->app = $app; + } + + /** + * @param CommentsEvent $event + */ + public function handle(CommentsEvent $event) { + if($event->getComment()->getObjectType() !== 'files') { + // this is a 'files'-specific Handler + return; + } + + if( $event->getEvent() === CommentsEvent::EVENT_ADD + && $event instanceof CommentsEvent + ) { + $this->onAdd($event); + return; + } + } + + /** + * @param CommentsEvent $event + */ + private function onAdd(CommentsEvent $event) { + $c = $this->app->getContainer(); + + /** @var NotificationListener $notificationListener */ + $notificationListener = $c->query(NotificationListener::class); + $notificationListener->evaluate($event); + + /** @var ActivityListener $listener */ + $activityListener = $c->query(ActivityListener::class); + $activityListener->commentEvent($event); + } +} diff --git a/apps/comments/lib/Notification/Listener.php b/apps/comments/lib/Notification/Listener.php new file mode 100644 index 00000000000..5e979fd9bf0 --- /dev/null +++ b/apps/comments/lib/Notification/Listener.php @@ -0,0 +1,130 @@ +<?php +/** + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @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\Comments\Notification; + +use OCP\Comments\CommentsEvent; +use OCP\Comments\IComment; +use OCP\IURLGenerator; +use OCP\IUserManager; +use OCP\Notification\IManager; + +class Listener { + /** @var IManager */ + protected $notificationManager; + + /** @var IUserManager */ + protected $userManager; + + /** @var IURLGenerator */ + protected $urlGenerator; + + /** + * Listener constructor. + * + * @param IManager $notificationManager + * @param IUserManager $userManager + * @param IURLGenerator $urlGenerator + */ + public function __construct( + IManager $notificationManager, + IUserManager $userManager, + IURLGenerator $urlGenerator + ) { + + $this->notificationManager = $notificationManager; + $this->userManager = $userManager; + $this->urlGenerator = $urlGenerator; + } + + /** + * @param CommentsEvent $event + */ + public function evaluate(CommentsEvent $event) { + $comment = $event->getComment(); + + if($comment->getObjectType() !== 'files') { + // comments App serves files only, other object types/apps need to + // register their own ICommentsEventHandler and trigger notifications + return; + } + + $mentions = $this->extractMentions($comment->getMessage()); + if(empty($mentions)) { + // no one to notify + return; + } + + $notification = $this->instantiateNotification($comment); + + foreach($mentions as $mention) { + $user = substr($mention, 1); // @username → username + if( ($comment->getActorType() === 'users' && $user === $comment->getActorId()) + || !$this->userManager->userExists($user) + ) { + // do not notify unknown users or yourself + continue; + } + + $notification->setUser($user); + if($event->getEvent() === CommentsEvent::EVENT_DELETE) { + $this->notificationManager->markProcessed($notification); + } else { + $this->notificationManager->notify($notification); + } + } + } + + /** + * creates a notification instance and fills it with comment data + * + * @param IComment $comment + * @return \OCP\Notification\INotification + */ + public function instantiateNotification(IComment $comment) { + $notification = $this->notificationManager->createNotification(); + $notification + ->setApp('comments') + ->setObject('comment', $comment->getId()) + ->setSubject('mention', [ $comment->getObjectType(), $comment->getObjectId() ]) + ->setDateTime($comment->getCreationDateTime()) + ->setLink($this->urlGenerator->linkToRouteAbsolute( + 'comments.Notifications.view', + ['id' => $comment->getId()]) + ); + + return $notification; + } + + /** + * extracts @-mentions out of a message body. + * + * @param string $message + * @return string[] containing the mentions, e.g. ['@alice', '@bob'] + */ + public function extractMentions($message) { + $ok = preg_match_all('/\B@[a-z0-9_\-@\.\']+/i', $message, $mentions); + if(!$ok || !isset($mentions[0]) || !is_array($mentions[0])) { + return []; + } + return array_unique($mentions[0]); + } +} diff --git a/apps/comments/lib/Notification/Notifier.php b/apps/comments/lib/Notification/Notifier.php new file mode 100644 index 00000000000..df05f297301 --- /dev/null +++ b/apps/comments/lib/Notification/Notifier.php @@ -0,0 +1,115 @@ +<?php +/** + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @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\Comments\Notification; + +use OCP\Comments\ICommentsManager; +use OCP\Comments\NotFoundException; +use OCP\Files\Folder; +use OCP\IUserManager; +use OCP\L10N\IFactory; +use OCP\Notification\INotification; +use OCP\Notification\INotifier; + +class Notifier implements INotifier { + + /** @var IFactory */ + protected $l10nFactory; + + /** @var Folder */ + protected $userFolder; + + /** @var ICommentsManager */ + protected $commentsManager; + + /** @var IUserManager */ + protected $userManager; + + public function __construct( + IFactory $l10nFactory, + Folder $userFolder, + ICommentsManager $commentsManager, + IUserManager $userManager + ) { + $this->l10nFactory = $l10nFactory; + $this->userFolder = $userFolder; + $this->commentsManager = $commentsManager; + $this->userManager = $userManager; + } + + /** + * @param INotification $notification + * @param string $languageCode The code of the language that should be used to prepare the notification + * @return INotification + * @throws \InvalidArgumentException When the notification was not prepared by a notifier + */ + public function prepare(INotification $notification, $languageCode) { + if($notification->getApp() !== 'comments') { + throw new \InvalidArgumentException(); + } + try { + $comment = $this->commentsManager->get($notification->getObjectId()); + } catch(NotFoundException $e) { + // needs to be converted to InvalidArgumentException, otherwise none Notifications will be shown at all + throw new \InvalidArgumentException('Comment not found', 0, $e); + } + $l = $this->l10nFactory->get('comments', $languageCode); + $displayName = $comment->getActorId(); + $isDeletedActor = $comment->getActorType() === ICommentsManager::DELETED_USER; + if($comment->getActorType() === 'users') { + $commenter = $this->userManager->get($comment->getActorId()); + if(!is_null($commenter)) { + $displayName = $commenter->getDisplayName(); + } + } + switch($notification->getSubject()) { + case 'mention': + $parameters = $notification->getSubjectParameters(); + if($parameters[0] !== 'files') { + throw new \InvalidArgumentException('Unsupported comment object'); + } + $nodes = $this->userFolder->getById($parameters[1]); + if(empty($nodes)) { + throw new \InvalidArgumentException('Cannot resolve file id to Node instance'); + } + $fileName = $nodes[0]->getName(); + if($isDeletedActor) { + $subject = (string) $l->t( + 'You were mentioned in a comment on "%s" by a now deleted user.', + [ $fileName ] + ); + } else { + $subject = (string) $l->t( + 'You were mentioned in a comment on "%s" by %s.', + [ $fileName, $displayName ] + ); + } + $notification->setParsedSubject($subject); + + return $notification; + break; + + default: + throw new \InvalidArgumentException('Invalid subject'); + } + + } +} diff --git a/apps/comments/tests/Unit/AppInfo/ApplicationTest.php b/apps/comments/tests/Unit/AppInfo/ApplicationTest.php new file mode 100644 index 00000000000..c11d7857496 --- /dev/null +++ b/apps/comments/tests/Unit/AppInfo/ApplicationTest.php @@ -0,0 +1,65 @@ +<?php +/** + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @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\Comments\Tests\Unit\AppInfo; + +use OCA\Comments\AppInfo\Application; +use Test\TestCase; + +/** + * Class ApplicationTest + * + * @group DB + * + * @package OCA\Comments\Tests\Unit\AppInfo + */ +class ApplicationTest extends TestCase { + protected function setUp() { + parent::setUp(); + \OC::$server->getUserManager()->createUser('dummy', '456'); + \OC::$server->getUserSession()->setUser(\OC::$server->getUserManager()->get('dummy')); + } + + protected function tearDown() { + \OC::$server->getUserManager()->get('dummy')->delete(); + parent::tearDown(); + } + + public function test() { + $app = new Application(); + $c = $app->getContainer(); + + // assert service instances in the container are properly setup + $s = $c->query('NotificationsController'); + $this->assertInstanceOf('OCA\Comments\Controller\Notifications', $s); + + $services = [ + 'OCA\Comments\Activity\Extension', + 'OCA\Comments\Activity\Listener', + 'OCA\Comments\Notification\Listener' + ]; + + foreach($services as $service) { + $s = $c->query($service); + $this->assertInstanceOf($service, $s); + } + } +} diff --git a/apps/comments/tests/Unit/Controller/NotificationsTest.php b/apps/comments/tests/Unit/Controller/NotificationsTest.php new file mode 100644 index 00000000000..5ab39788213 --- /dev/null +++ b/apps/comments/tests/Unit/Controller/NotificationsTest.php @@ -0,0 +1,162 @@ +<?php +/** + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @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\Comments\Tests\Unit\Controller; + +use OCA\Comments\Controller\Notifications; +use OCP\Comments\NotFoundException; +use Test\TestCase; + +class NotificationsTest extends TestCase { + /** @var \OCA\Comments\Controller\Notifications */ + protected $notificationsController; + + /** @var \OCP\Comments\ICommentsManager|\PHPUnit_Framework_MockObject_MockObject */ + protected $commentsManager; + + /** @var \OCP\Files\Folder|\PHPUnit_Framework_MockObject_MockObject */ + protected $folder; + + /** @var \OCP\IUserSession|\PHPUnit_Framework_MockObject_MockObject */ + protected $session; + + /** @var \OCP\Notification\IManager|\PHPUnit_Framework_MockObject_MockObject */ + protected $notificationManager; + + protected function setUp() { + parent::setUp(); + + $this->commentsManager = $this->getMockBuilder('\OCP\Comments\ICommentsManager')->getMock(); + $this->folder = $this->getMockBuilder('\OCP\Files\Folder')->getMock(); + $this->session = $this->getMockBuilder('\OCP\IUserSession')->getMock(); + $this->notificationManager = $this->getMockBuilder('\OCP\Notification\IManager')->getMock(); + + $this->notificationsController = new Notifications( + 'comments', + $this->getMockBuilder('\OCP\IRequest')->getMock(), + $this->commentsManager, + $this->folder, + $this->getMockBuilder('\OCP\IURLGenerator')->getMock(), + $this->notificationManager, + $this->session + ); + } + + public function testViewSuccess() { + $comment = $this->getMockBuilder('\OCP\Comments\IComment')->getMock(); + $comment->expects($this->any()) + ->method('getObjectType') + ->will($this->returnValue('files')); + + $this->commentsManager->expects($this->any()) + ->method('get') + ->with('42') + ->will($this->returnValue($comment)); + + $file = $this->getMockBuilder('\OCP\Files\Node')->getMock(); + $file->expects($this->once()) + ->method('getParent') + ->will($this->returnValue($this->getMockBuilder('\OCP\Files\Folder')->getMock())); + + $this->folder->expects($this->once()) + ->method('getById') + ->will($this->returnValue([$file])); + + $this->session->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($this->getMockBuilder('\OCP\IUser')->getMock())); + + $notification = $this->getMockBuilder('\OCP\Notification\INotification')->getMock(); + $notification->expects($this->any()) + ->method($this->anything()) + ->will($this->returnValue($notification)); + + $this->notificationManager->expects($this->once()) + ->method('createNotification') + ->will($this->returnValue($notification)); + $this->notificationManager->expects($this->once()) + ->method('markProcessed') + ->with($notification); + + $response = $this->notificationsController->view('42'); + $this->assertInstanceOf('\OCP\AppFramework\Http\RedirectResponse', $response); + } + + public function testViewInvalidComment() { + $this->commentsManager->expects($this->any()) + ->method('get') + ->with('42') + ->will($this->throwException(new NotFoundException())); + + $file = $this->getMockBuilder('\OCP\Files\Node')->getMock(); + $file->expects($this->never()) + ->method('getParent'); + + $this->folder->expects($this->never()) + ->method('getById'); + + $this->session->expects($this->never()) + ->method('getUser'); + + $this->notificationManager->expects($this->never()) + ->method('createNotification'); + $this->notificationManager->expects($this->never()) + ->method('markProcessed'); + + $response = $this->notificationsController->view('42'); + $this->assertInstanceOf('\OCP\AppFramework\Http\NotFoundResponse', $response); + } + + public function testViewNoFile() { + $comment = $this->getMockBuilder('\OCP\Comments\IComment')->getMock(); + $comment->expects($this->any()) + ->method('getObjectType') + ->will($this->returnValue('files')); + + $this->commentsManager->expects($this->any()) + ->method('get') + ->with('42') + ->will($this->returnValue($comment)); + + $this->folder->expects($this->once()) + ->method('getById') + ->will($this->returnValue([])); + + $this->session->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($this->getMockBuilder('\OCP\IUser')->getMock())); + + $notification = $this->getMockBuilder('\OCP\Notification\INotification')->getMock(); + $notification->expects($this->any()) + ->method($this->anything()) + ->will($this->returnValue($notification)); + + $this->notificationManager->expects($this->once()) + ->method('createNotification') + ->will($this->returnValue($notification)); + $this->notificationManager->expects($this->once()) + ->method('markProcessed') + ->with($notification); + + $response = $this->notificationsController->view('42'); + $this->assertInstanceOf('\OCP\AppFramework\Http\NotFoundResponse', $response); + } +} diff --git a/apps/comments/tests/Unit/EventHandlerTest.php b/apps/comments/tests/Unit/EventHandlerTest.php new file mode 100644 index 00000000000..7a630329974 --- /dev/null +++ b/apps/comments/tests/Unit/EventHandlerTest.php @@ -0,0 +1,152 @@ +<?php +/** + * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Comments\Tests\Unit\Notification; + +use OCA\Comments\AppInfo\Application; +use OCA\Comments\EventHandler; +use OCP\Comments\CommentsEvent; +use OCP\Comments\IComment; +use OCA\Comments\Activity\Listener as ActivityListener; +use OCA\Comments\Notification\Listener as NotificationListener; +use OCP\IContainer; +use Test\TestCase; + +class EventHandlerTest extends TestCase { + /** @var EventHandler */ + protected $eventHandler; + + /** @var Application|\PHPUnit_Framework_MockObject_MockObject */ + protected $app; + + protected function setUp() { + parent::setUp(); + + $this->app = $this->getMockBuilder(Application::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->eventHandler = new EventHandler($this->app); + } + + public function testNotFiles() { + /** @var IComment|\PHPUnit_Framework_MockObject_MockObject $comment */ + $comment = $this->getMockBuilder(IComment::class)->getMock(); + $comment->expects($this->once()) + ->method('getObjectType') + ->willReturn('smiles'); + + /** @var CommentsEvent|\PHPUnit_Framework_MockObject_MockObject $event */ + $event = $this->getMockBuilder(CommentsEvent::class) + ->disableOriginalConstructor() + ->getMock(); + $event->expects($this->once()) + ->method('getComment') + ->willReturn($comment); + $event->expects($this->never()) + ->method('getEvent'); + + $this->eventHandler->handle($event); + } + + public function notHandledProvider() { + return [ + [CommentsEvent::EVENT_DELETE], + [CommentsEvent::EVENT_UPDATE] + ]; + } + + /** + * @dataProvider notHandledProvider + * @param $eventType + */ + public function testNotHandled($eventType) { + /** @var IComment|\PHPUnit_Framework_MockObject_MockObject $comment */ + $comment = $this->getMockBuilder(IComment::class)->getMock(); + $comment->expects($this->once()) + ->method('getObjectType') + ->willReturn('files'); + + /** @var CommentsEvent|\PHPUnit_Framework_MockObject_MockObject $event */ + $event = $this->getMockBuilder(CommentsEvent::class) + ->disableOriginalConstructor() + ->getMock(); + $event->expects($this->once()) + ->method('getComment') + ->willReturn($comment); + $event->expects($this->once()) + ->method('getEvent') + ->willReturn($eventType); + + // further processing does not happen, because $event methods cannot be + // access more than once. + $this->eventHandler->handle($event); + } + + public function testHandled() { + /** @var IComment|\PHPUnit_Framework_MockObject_MockObject $comment */ + $comment = $this->getMockBuilder(IComment::class)->getMock(); + $comment->expects($this->once()) + ->method('getObjectType') + ->willReturn('files'); + + /** @var CommentsEvent|\PHPUnit_Framework_MockObject_MockObject $event */ + $event = $this->getMockBuilder(CommentsEvent::class) + ->disableOriginalConstructor() + ->getMock(); + $event->expects($this->atLeastOnce()) + ->method('getComment') + ->willReturn($comment); + $event->expects($this->atLeastOnce()) + ->method('getEvent') + ->willReturn(CommentsEvent::EVENT_ADD); + + $notificationListener = $this->getMockBuilder(NotificationListener::class) + ->disableOriginalConstructor() + ->getMock(); + $notificationListener->expects($this->once()) + ->method('evaluate') + ->with($event); + + $activityListener = $this->getMockBuilder(ActivityListener::class) + ->disableOriginalConstructor() + ->getMock(); + $activityListener->expects($this->once()) + ->method('commentEvent') + ->with($event); + + /** @var IContainer|\PHPUnit_Framework_MockObject_MockObject $c */ + $c = $this->getMockBuilder(IContainer::class)->getMock(); + $c->expects($this->exactly(2)) + ->method('query') + ->withConsecutive([NotificationListener::class], [ActivityListener::class]) + ->willReturnOnConsecutiveCalls($notificationListener, $activityListener); + + $this->app->expects($this->once()) + ->method('getContainer') + ->willReturn($c); + + $this->eventHandler->handle($event); + } + +} diff --git a/apps/comments/tests/Unit/Notification/ListenerTest.php b/apps/comments/tests/Unit/Notification/ListenerTest.php new file mode 100644 index 00000000000..98a0375e49a --- /dev/null +++ b/apps/comments/tests/Unit/Notification/ListenerTest.php @@ -0,0 +1,360 @@ +<?php +/** + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @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\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 Test\TestCase; + +class ListenerTest extends TestCase { + /** @var IManager|\PHPUnit_Framework_MockObject_MockObject */ + protected $notificationManager; + + /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */ + protected $userManager; + + /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */ + protected $urlGenerator; + + /** @var Listener */ + protected $listener; + + protected function setUp() { + parent::setUp(); + + $this->notificationManager = $this->getMockBuilder('\OCP\Notification\IManager')->getMock(); + $this->userManager = $this->getMockBuilder('\OCP\IUserManager')->getMock(); + $this->urlGenerator = $this->getMockBuilder('OCP\IURLGenerator')->getMock(); + + $this->listener = new Listener( + $this->notificationManager, + $this->userManager, + $this->urlGenerator + ); + } + + public function eventProvider() { + return [ + [CommentsEvent::EVENT_ADD, 'notify'], + [CommentsEvent::EVENT_DELETE, 'markProcessed'] + ]; + } + + /** + * @dataProvider eventProvider + * @param string $eventType + * @param string $notificationMethod + */ + public function testEvaluate($eventType, $notificationMethod) { + $message = '@foobar and @barfoo you should know, @foo@bar.com is valid' . + ' and so is @bar@foo.org@foobar.io I hope that clarifies everything.' . + ' cc @23452-4333-54353-2342 @yolo!'; + + /** @var IComment|\PHPUnit_Framework_MockObject_MockObject $comment */ + $comment = $this->getMockBuilder('\OCP\Comments\IComment')->getMock(); + $comment->expects($this->any()) + ->method('getObjectType') + ->will($this->returnValue('files')); + $comment->expects($this->any()) + ->method('getCreationDateTime') + ->will($this->returnValue(new \DateTime())); + $comment->expects($this->once()) + ->method('getMessage') + ->will($this->returnValue($message)); + + /** @var CommentsEvent|\PHPUnit_Framework_MockObject_MockObject $event */ + $event = $this->getMockBuilder('\OCP\Comments\CommentsEvent') + ->disableOriginalConstructor() + ->getMock(); + $event->expects($this->once()) + ->method('getComment') + ->will($this->returnValue($comment)); + $event->expects(($this->any())) + ->method(('getEvent')) + ->will($this->returnValue($eventType)); + + /** @var INotification|\PHPUnit_Framework_MockObject_MockObject $notification */ + $notification = $this->getMockBuilder('\OCP\Notification\INotification')->getMock(); + $notification->expects($this->any()) + ->method($this->anything()) + ->will($this->returnValue($notification)); + $notification->expects($this->exactly(6)) + ->method('setUser'); + + $this->notificationManager->expects($this->once()) + ->method('createNotification') + ->will($this->returnValue($notification)); + $this->notificationManager->expects($this->exactly(6)) + ->method($notificationMethod) + ->with($this->isInstanceOf('\OCP\Notification\INotification')); + + $this->userManager->expects($this->exactly(6)) + ->method('userExists') + ->withConsecutive( + ['foobar'], + ['barfoo'], + ['foo@bar.com'], + ['bar@foo.org@foobar.io'], + ['23452-4333-54353-2342'], + ['yolo'] + ) + ->will($this->returnValue(true)); + + $this->listener->evaluate($event); + } + + /** + * @dataProvider eventProvider + * @param string $eventType + */ + public function testEvaluateNoMentions($eventType) { + $message = 'a boring comment without mentions'; + + /** @var IComment|\PHPUnit_Framework_MockObject_MockObject $comment */ + $comment = $this->getMockBuilder('\OCP\Comments\IComment')->getMock(); + $comment->expects($this->any()) + ->method('getObjectType') + ->will($this->returnValue('files')); + $comment->expects($this->any()) + ->method('getCreationDateTime') + ->will($this->returnValue(new \DateTime())); + $comment->expects($this->once()) + ->method('getMessage') + ->will($this->returnValue($message)); + + /** @var CommentsEvent|\PHPUnit_Framework_MockObject_MockObject $event */ + $event = $this->getMockBuilder('\OCP\Comments\CommentsEvent') + ->disableOriginalConstructor() + ->getMock(); + $event->expects($this->once()) + ->method('getComment') + ->will($this->returnValue($comment)); + $event->expects(($this->any())) + ->method(('getEvent')) + ->will($this->returnValue($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 testUnsupportedCommentObjectType() { + /** @var IComment|\PHPUnit_Framework_MockObject_MockObject $comment */ + $comment = $this->getMockBuilder('\OCP\Comments\IComment')->getMock(); + $comment->expects($this->once()) + ->method('getObjectType') + ->will($this->returnValue('vcards')); + $comment->expects($this->never()) + ->method('getMessage'); + + /** @var CommentsEvent|\PHPUnit_Framework_MockObject_MockObject $event */ + $event = $this->getMockBuilder('\OCP\Comments\CommentsEvent') + ->disableOriginalConstructor() + ->getMock(); + $event->expects($this->once()) + ->method('getComment') + ->will($this->returnValue($comment)); + $event->expects(($this->any())) + ->method(('getEvent')) + ->will($this->returnValue(CommentsEvent::EVENT_ADD)); + + $this->listener->evaluate($event); + } + + public function testEvaluateUserDoesNotExist() { + $message = '@foobar bla bla bla'; + + /** @var IComment|\PHPUnit_Framework_MockObject_MockObject $comment */ + $comment = $this->getMockBuilder('\OCP\Comments\IComment')->getMock(); + $comment->expects($this->any()) + ->method('getObjectType') + ->will($this->returnValue('files')); + $comment->expects($this->any()) + ->method('getCreationDateTime') + ->will($this->returnValue(new \DateTime())); + $comment->expects($this->once()) + ->method('getMessage') + ->will($this->returnValue($message)); + + /** @var CommentsEvent|\PHPUnit_Framework_MockObject_MockObject $event */ + $event = $this->getMockBuilder('\OCP\Comments\CommentsEvent') + ->disableOriginalConstructor() + ->getMock(); + $event->expects($this->once()) + ->method('getComment') + ->will($this->returnValue($comment)); + $event->expects(($this->any())) + ->method(('getEvent')) + ->will($this->returnValue(CommentsEvent::EVENT_ADD)); + + /** @var INotification|\PHPUnit_Framework_MockObject_MockObject $notification */ + $notification = $this->getMockBuilder('\OCP\Notification\INotification')->getMock(); + $notification->expects($this->any()) + ->method($this->anything()) + ->will($this->returnValue($notification)); + $notification->expects($this->never()) + ->method('setUser'); + + $this->notificationManager->expects($this->once()) + ->method('createNotification') + ->will($this->returnValue($notification)); + $this->notificationManager->expects($this->never()) + ->method('notify'); + + $this->userManager->expects($this->once()) + ->method('userExists') + ->withConsecutive( + ['foobar'] + ) + ->will($this->returnValue(false)); + + $this->listener->evaluate($event); + } + + /** + * @dataProvider eventProvider + * @param string $eventType + * @param string $notificationMethod + */ + public function testEvaluateOneMentionPerUser($eventType, $notificationMethod) { + $message = '@foobar bla bla bla @foobar'; + + /** @var IComment|\PHPUnit_Framework_MockObject_MockObject $comment */ + $comment = $this->getMockBuilder('\OCP\Comments\IComment')->getMock(); + $comment->expects($this->any()) + ->method('getObjectType') + ->will($this->returnValue('files')); + $comment->expects($this->any()) + ->method('getCreationDateTime') + ->will($this->returnValue(new \DateTime())); + $comment->expects($this->once()) + ->method('getMessage') + ->will($this->returnValue($message)); + + /** @var CommentsEvent|\PHPUnit_Framework_MockObject_MockObject $event */ + $event = $this->getMockBuilder('\OCP\Comments\CommentsEvent') + ->disableOriginalConstructor() + ->getMock(); + $event->expects($this->once()) + ->method('getComment') + ->will($this->returnValue($comment)); + $event->expects(($this->any())) + ->method(('getEvent')) + ->will($this->returnValue($eventType)); + + /** @var INotification|\PHPUnit_Framework_MockObject_MockObject $notification */ + $notification = $this->getMockBuilder('\OCP\Notification\INotification')->getMock(); + $notification->expects($this->any()) + ->method($this->anything()) + ->will($this->returnValue($notification)); + $notification->expects($this->once()) + ->method('setUser'); + + $this->notificationManager->expects($this->once()) + ->method('createNotification') + ->will($this->returnValue($notification)); + $this->notificationManager->expects($this->once()) + ->method($notificationMethod) + ->with($this->isInstanceOf('\OCP\Notification\INotification')); + + $this->userManager->expects($this->once()) + ->method('userExists') + ->withConsecutive( + ['foobar'] + ) + ->will($this->returnValue(true)); + + $this->listener->evaluate($event); + } + + /** + * @dataProvider eventProvider + * @param string $eventType + */ + public function testEvaluateNoSelfMention($eventType) { + $message = '@foobar bla bla bla'; + + /** @var IComment|\PHPUnit_Framework_MockObject_MockObject $comment */ + $comment = $this->getMockBuilder('\OCP\Comments\IComment')->getMock(); + $comment->expects($this->any()) + ->method('getObjectType') + ->will($this->returnValue('files')); + $comment->expects($this->any()) + ->method('getActorType') + ->will($this->returnValue('users')); + $comment->expects($this->any()) + ->method('getActorId') + ->will($this->returnValue('foobar')); + $comment->expects($this->any()) + ->method('getCreationDateTime') + ->will($this->returnValue(new \DateTime())); + $comment->expects($this->once()) + ->method('getMessage') + ->will($this->returnValue($message)); + + /** @var CommentsEvent|\PHPUnit_Framework_MockObject_MockObject $event */ + $event = $this->getMockBuilder('\OCP\Comments\CommentsEvent') + ->disableOriginalConstructor() + ->getMock(); + $event->expects($this->once()) + ->method('getComment') + ->will($this->returnValue($comment)); + $event->expects(($this->any())) + ->method(('getEvent')) + ->will($this->returnValue($eventType)); + + /** @var INotification|\PHPUnit_Framework_MockObject_MockObject $notification */ + $notification = $this->getMockBuilder('\OCP\Notification\INotification')->getMock(); + $notification->expects($this->any()) + ->method($this->anything()) + ->will($this->returnValue($notification)); + $notification->expects($this->never()) + ->method('setUser'); + + $this->notificationManager->expects($this->once()) + ->method('createNotification') + ->will($this->returnValue($notification)); + $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); + } + +} diff --git a/apps/comments/tests/Unit/Notification/NotifierTest.php b/apps/comments/tests/Unit/Notification/NotifierTest.php new file mode 100644 index 00000000000..f3cc0153ab1 --- /dev/null +++ b/apps/comments/tests/Unit/Notification/NotifierTest.php @@ -0,0 +1,499 @@ +<?php +/** + * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +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\Node; +use OCP\IL10N; +use OCP\IUser; +use OCP\IUserManager; +use OCP\L10N\IFactory; +use OCP\Notification\INotification; +use Test\TestCase; + +class NotifierTest extends TestCase { + + /** @var Notifier */ + protected $notifier; + + /** @var IFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $l10nFactory; + + /** @var Folder|\PHPUnit_Framework_MockObject_MockObject */ + protected $folder; + + /** @var ICommentsManager|\PHPUnit_Framework_MockObject_MockObject */ + protected $commentsManager; + + /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */ + protected $userManager; + + + /** @var string */ + protected $lc = 'tlh_KX'; + + /** @var INotification|\PHPUnit_Framework_MockObject_MockObject */ + protected $notification; + + /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ + protected $l; + + /** @var IComment|\PHPUnit_Framework_MockObject_MockObject */ + protected $comment; + + protected function setUp() { + parent::setUp(); + + $this->l10nFactory = $this->getMockBuilder('OCP\L10N\IFactory')->getMock(); + $this->folder = $this->getMockBuilder('OCP\Files\Folder')->getMock(); + $this->commentsManager = $this->getMockBuilder('OCP\Comments\ICommentsManager')->getMock(); + $this->userManager = $this->getMockBuilder('OCP\IUserManager')->getMock(); + + $this->notifier = new Notifier( + $this->l10nFactory, + $this->folder, + $this->commentsManager, + $this->userManager + ); + + $this->l = $this->getMockBuilder('OCP\IL10N')->getMock(); + $this->notification = $this->getMockBuilder('OCP\Notification\INotification')->getMock(); + $this->comment = $this->getMockBuilder('OCP\Comments\IComment')->getMock(); + } + + public function testPrepareSuccess() { + $fileName = 'Gre\'thor.odp'; + $displayName = 'Huraga'; + $message = 'You were mentioned in a comment on "Gre\'thor.odp" by Huraga.'; + + /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->getMockBuilder('OCP\IUser')->getMock(); + $user->expects($this->once()) + ->method('getDisplayName') + ->willReturn($displayName); + + /** @var Node|\PHPUnit_Framework_MockObject_MockObject */ + $node = $this->getMockBuilder('OCP\Files\Node')->getMock(); + $node + ->expects($this->once()) + ->method('getName') + ->willReturn($fileName); + + $this->folder + ->expects($this->once()) + ->method('getById') + ->with('678') + ->willReturn([$node]); + + $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->once()) + ->method('setParsedSubject') + ->with($message); + + $this->l + ->expects($this->once()) + ->method('t') + ->with('You were mentioned in a comment on "%s" by %s.', [$fileName, $displayName]) + ->willReturn($message); + + $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('get') + ->with('huraga') + ->willReturn($user); + + $this->notifier->prepare($this->notification, $this->lc); + } + + public function testPrepareSuccessDeletedUser() { + $fileName = 'Gre\'thor.odp'; + $displayName = 'a now deleted user'; + $message = 'You were mentioned in a comment on "Gre\'thor.odp" by a now deleted user.'; + + /** @var Node|\PHPUnit_Framework_MockObject_MockObject */ + $node = $this->getMockBuilder('OCP\Files\Node')->getMock(); + $node + ->expects($this->once()) + ->method('getName') + ->willReturn($fileName); + + $this->folder + ->expects($this->once()) + ->method('getById') + ->with('678') + ->willReturn([$node]); + + $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->once()) + ->method('setParsedSubject') + ->with($message); + + $this->l + ->expects($this->once()) + ->method('t') + ->with('You were mentioned in a comment on "%s" by a now deleted user.', [ $fileName ]) + ->willReturn($message); + + $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->commentsManager + ->expects(($this->once())) + ->method('get') + ->willReturn($this->comment); + + $this->userManager + ->expects($this->never()) + ->method('get'); + + $this->notifier->prepare($this->notification, $this->lc); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testPrepareDifferentApp() { + $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('get'); + + $this->notifier->prepare($this->notification, $this->lc); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testPrepareNotFound() { + $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('get'); + + $this->notifier->prepare($this->notification, $this->lc); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testPrepareDifferentSubject() { + $displayName = 'Huraga'; + + /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->getMockBuilder('OCP\IUser')->getMock(); + $user->expects($this->once()) + ->method('getDisplayName') + ->willReturn($displayName); + + $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('get') + ->with('huraga') + ->willReturn($user); + + $this->notifier->prepare($this->notification, $this->lc); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testPrepareNotFiles() { + $displayName = 'Huraga'; + + /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->getMockBuilder('OCP\IUser')->getMock(); + $user->expects($this->once()) + ->method('getDisplayName') + ->willReturn($displayName); + + $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('get') + ->with('huraga') + ->willReturn($user); + + $this->notifier->prepare($this->notification, $this->lc); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testPrepareUnresolvableFileID() { + $displayName = 'Huraga'; + + /** @var IUser|\PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->getMockBuilder('OCP\IUser')->getMock(); + $user->expects($this->once()) + ->method('getDisplayName') + ->willReturn($displayName); + + $this->folder + ->expects($this->once()) + ->method('getById') + ->with('678') + ->willReturn([]); + + $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('get') + ->with('huraga') + ->willReturn($user); + + $this->notifier->prepare($this->notification, $this->lc); + } + +} |