Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
Joas Schilling 2018-02-16 12:51:10 +01:00
Родитель fffb9ac5ca
Коммит e80405d97b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 7076EA9751AACDDA
11 изменённых файлов: 912 добавлений и 4 удалений

Просмотреть файл

@ -15,7 +15,7 @@
<licence>AGPL</licence> <licence>AGPL</licence>
<author>Joas Schilling</author> <author>Joas Schilling</author>
<version>2.2.0</version> <version>2.2.1</version>
<types> <types>
<logging/> <logging/>
@ -30,4 +30,8 @@
<dependencies> <dependencies>
<nextcloud min-version="14" max-version="14" /> <nextcloud min-version="14" max-version="14" />
</dependencies> </dependencies>
<commands>
<command>OCA\Notifications\Command\Generate</command>
</commands>
</info> </info>

Просмотреть файл

@ -27,5 +27,6 @@ return [
['name' => 'Endpoint#deleteAllNotifications', 'url' => '/api/{apiVersion}/notifications', 'verb' => 'DELETE', 'requirements' => ['apiVersion' => 'v(1|2)']], ['name' => 'Endpoint#deleteAllNotifications', 'url' => '/api/{apiVersion}/notifications', 'verb' => 'DELETE', 'requirements' => ['apiVersion' => 'v(1|2)']],
['name' => 'Push#registerDevice', 'url' => '/api/{apiVersion}/push', 'verb' => 'POST', 'requirements' => ['apiVersion' => 'v2']], ['name' => 'Push#registerDevice', 'url' => '/api/{apiVersion}/push', 'verb' => 'POST', 'requirements' => ['apiVersion' => 'v2']],
['name' => 'Push#removeDevice', 'url' => '/api/{apiVersion}/push', 'verb' => 'DELETE', 'requirements' => ['apiVersion' => 'v2']], ['name' => 'Push#removeDevice', 'url' => '/api/{apiVersion}/push', 'verb' => 'DELETE', 'requirements' => ['apiVersion' => 'v2']],
['name' => 'API#generateNotification', 'url' => '/api/{apiVersion}/notifications/{userId}', 'verb' => 'POST', 'requirements' => ['apiVersion' => 'v(1|2)'], 'root' => '/apps/admin_notifications'],
], ],
]; ];

Просмотреть файл

@ -0,0 +1,68 @@
# Admin notifications
Allows admins to generate notifications for users via the console or an HTTP endpoint
## Console command
```
$ sudo -u www-data ./occ notification:generate \
admin "Short message up to 255 characters" \
-l "Optional: longer message with more details, up to 4000 characters"
```
### Help
```
$ sudo -u www-data ./occ notification:generate --help
Usage:
notification:generate [options] [--] <user-id> <short-message>
Arguments:
user-id User ID of the user to notify
short-message Short message to be sent to the user (max. 255 characters)
Options:
-l, --long-message=LONG-MESSAGE Long mesage to be sent to the user (max. 4000 characters) [default: ""]
```
## HTTP request
```
curl -H "OCS-APIREQUEST: true" -X POST \
https://admin:admin@localhost/ocs/v2.php/apps/admin_notifications/api/v1/notifications/admin \
-d "shortMessage=Short message up to 255 characters" \
-d "longMessage=Optional: longer message with more details, up to 4000 characters"
```
### Help
```
curl -H "OCS-APIREQUEST: true" -X POST \
https://<admin-user>:<admin-app-password-token>@<server-url>/ocs/v2.php/apps/admin_notifications/api/v1/notifications/<user-id> \
-d "shortMessage=<short-message>" \
-d "longMessage=<long-message>"
admin-user: User ID of a user with admin priviliges
admin-app-password-token: Password or an "app password" of the "admin-user"
server-url: URL with Webroot of your Nextcloud installation
user-id: User ID of the user to notify
short-message: Short message to be sent to the user (max. 255 characters)
long-message: Long mesage to be sent to the user (max. 4000 characters)
```
### Return codes
Status | Description
------ | -----------
200 | Notification was created successfully
400 | Too long or empty `short-message`, too long `long-message`
404 | Unknown user
500 | Unexpected server error
503 | Instance is in maintenance mode
## Screenshot
Both the occ command and the HTTP request generate the same notification
![Admin notification triggered from console](docs/Screenshot.png)

Просмотреть файл

@ -24,7 +24,7 @@ namespace OCA\Notifications\AppInfo;
use OC\Authentication\Token\IProvider; use OC\Authentication\Token\IProvider;
use OCA\Notifications\App; use OCA\Notifications\App;
use OCA\Notifications\Capabilities; use OCA\Notifications\Capabilities;
use OCA\Notifications\Controller\EndpointController; use OCA\Notifications\Notifier\AdminNotifications;
use OCP\AppFramework\IAppContainer; use OCP\AppFramework\IAppContainer;
use OCP\Util; use OCP\Util;
@ -43,6 +43,7 @@ class Application extends \OCP\AppFramework\App {
public function register() { public function register() {
$this->registerNotificationApp(); $this->registerNotificationApp();
$this->registerAdminNotifications();
$this->registerUserInterface(); $this->registerUserInterface();
} }
@ -52,6 +53,17 @@ class Application extends \OCP\AppFramework\App {
return $container->query(App::class); return $container->query(App::class);
}); });
} }
protected function registerAdminNotifications() {
$this->getContainer()->getServer()->getNotificationManager()->registerNotifier(function() {
return $this->getContainer()->query(AdminNotifications::class);
}, function() {
$l = $this->getContainer()->getServer()->getL10NFactory()->get('notifications');
return [
'id' => 'admin_notifications',
'name' => $l->t('Admin notifications'),
];
});
}
protected function registerUserInterface() { protected function registerUserInterface() {
// Only display the app on index.php except for public shares // Only display the app on index.php except for public shares
@ -66,6 +78,5 @@ class Application extends \OCP\AppFramework\App {
Util::addScript('notifications', 'merged'); Util::addScript('notifications', 'merged');
Util::addStyle('notifications', 'styles'); Util::addStyle('notifications', 'styles');
} }
} }
} }

135
lib/Command/Generate.php Normal file
Просмотреть файл

@ -0,0 +1,135 @@
<?php
/**
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
*
* @author Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Notifications\Command;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Notification\IManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class Generate extends Command {
/** @var ITimeFactory */
protected $timeFactory;
/** @var IUserManager */
protected $userManager;
/** @var IManager */
protected $notificationManager;
/**
* @param ITimeFactory $timeFactory
* @param IUserManager $userManager
* @param IManager $notificationManager
*/
public function __construct(ITimeFactory $timeFactory, IUserManager $userManager, IManager $notificationManager) {
parent::__construct();
$this->timeFactory = $timeFactory;
$this->userManager = $userManager;
$this->notificationManager = $notificationManager;
}
protected function configure() {
$this
->setName('notification:generate')
->setDescription('Generate a notification for the given user')
->addArgument(
'user-id',
InputArgument::REQUIRED,
'User ID of the user to notify'
)
->addArgument(
'short-message',
InputArgument::REQUIRED,
'Short message to be sent to the user (max. 255 characters)'
)
->addOption(
'long-message',
'l',
InputOption::VALUE_REQUIRED,
'Long mesage to be sent to the user (max. 4000 characters)',
''
)
;
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$userId = $input->getArgument('user-id');
$subject = $input->getArgument('short-message');
$message = $input->getOption('long-message');
$user = $this->userManager->get($userId);
if (!$user instanceof IUser) {
$output->writeln('Unknown user');
return 1;
}
if ($subject === '' || strlen($subject) > 255) {
$output->writeln('Too long or empty short-message');
return 1;
}
if ($message !== '' && strlen($message) > 4000) {
$output->writeln('Too long long-message');
return 1;
}
$notification = $this->notificationManager->createNotification();
$time = $this->timeFactory->getTime();
$datetime = new \DateTime();
$datetime->setTimestamp($time);
try {
$notification->setApp('admin_notifications')
->setUser($user->getUID())
->setDateTime($datetime)
->setObject('admin_notifications', dechex($time))
->setSubject('cli', [$subject]);
if ($message !== '') {
$notification->setMessage('cli', [$message]);
}
$this->notificationManager->notify($notification);
} catch (\InvalidArgumentException $e) {
$output->writeln('Error while sending the notification');
return 1;
}
return 0;
}
}

Просмотреть файл

@ -0,0 +1,108 @@
<?php
/**
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
*
* @author Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Notifications\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Notification\IManager;
class APIController extends OCSController {
/** @var ITimeFactory */
protected $timeFactory;
/** @var IUserManager */
protected $userManager;
/** @var IManager */
protected $notificationManager;
/**
* @param string $appName
* @param IRequest $request
* @param ITimeFactory $timeFactory
* @param IUserManager $userManager
* @param IManager $notificationManager
*/
public function __construct($appName, IRequest $request, ITimeFactory $timeFactory, IUserManager $userManager, IManager $notificationManager) {
parent::__construct($appName, $request);
$this->timeFactory = $timeFactory;
$this->userManager = $userManager;
$this->notificationManager = $notificationManager;
}
/**
* @param string $userId
* @param string $shortMessage
* @param string $longMessage
* @return DataResponse
*/
public function generateNotification($userId, $shortMessage, $longMessage) {
$shortMessage = (string) $shortMessage;
$longMessage = (string) $longMessage;
$user = $this->userManager->get($userId);
if (!$user instanceof IUser) {
return new DataResponse(null, Http::STATUS_NOT_FOUND);
}
if ($shortMessage === '' || strlen($shortMessage) > 255) {
return new DataResponse(null, Http::STATUS_BAD_REQUEST);
}
if ($longMessage !== '' && strlen($longMessage) > 4000) {
return new DataResponse(null, Http::STATUS_BAD_REQUEST);
}
$notification = $this->notificationManager->createNotification();
$time = $this->timeFactory->getTime();
$datetime = new \DateTime();
$datetime->setTimestamp($time);
try {
$notification->setApp('admin_notifications')
->setUser($user->getUID())
->setDateTime($datetime)
->setObject('admin_notifications', dechex($time))
->setSubject('ocs', [$shortMessage]);
if ($longMessage !== '') {
$notification->setMessage('ocs', [$longMessage]);
}
$this->notificationManager->notify($notification);
} catch (\InvalidArgumentException $e) {
return new DataResponse(null, Http::STATUS_INTERNAL_SERVER_ERROR);
}
return new DataResponse();
}
}

Просмотреть файл

@ -0,0 +1,77 @@
<?php
/**
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
*
* @author Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Notifications\Notifier;
use OCP\IURLGenerator;
use OCP\L10N\IFactory;
use OCP\Notification\INotification;
use OCP\Notification\INotifier;
class AdminNotifications implements INotifier {
/** @var IFactory */
protected $l10nFactory;
/** @var IURLGenerator */
protected $urlGenerator;
/**
* @param IFactory $l10nFactory
* @param IURLGenerator $urlGenerator
*/
public function __construct(IFactory $l10nFactory, IURLGenerator $urlGenerator) {
$this->l10nFactory = $l10nFactory;
$this->urlGenerator = $urlGenerator;
}
/**
* @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() !== 'admin_notifications') {
throw new \InvalidArgumentException('Unknown app');
}
switch ($notification->getSubject()) {
// Deal with known subjects
case 'cli':
case 'ocs':
$subjectParams = $notification->getSubjectParameters();
$notification->setParsedSubject($subjectParams[0]);
$messageParams = $notification->getMessageParameters();
if (isset($messageParams[0]) && $messageParams[0] !== '') {
$notification->setParsedMessage($messageParams[0]);
}
$notification->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('notifications', 'notifications-dark.svg')));
return $notification;
default:
throw new \InvalidArgumentException('Unknown subject');
}
}
}

Просмотреть файл

@ -37,6 +37,6 @@ class RoutesTest extends TestCase {
$this->assertCount(1, $routes); $this->assertCount(1, $routes);
$this->assertArrayHasKey('ocs', $routes); $this->assertArrayHasKey('ocs', $routes);
$this->assertInternalType('array', $routes['ocs']); $this->assertInternalType('array', $routes['ocs']);
$this->assertCount(6, $routes['ocs']); $this->assertCount(7, $routes['ocs']);
} }
} }

Просмотреть файл

@ -0,0 +1,174 @@
<?php
/**
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
*
* @author Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Notifications\Tests\Unit\Command;
use OCA\Notifications\Command\Generate;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Notification\IManager;
use OCP\Notification\INotification;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class GenerateTest
*
* @package OCA\Notifications\Tests\Unit\Command
* @group DB
*/
class GenerateTest extends \Test\TestCase {
/** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */
protected $timeFactory;
/** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
protected $userManager;
/** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
protected $notificationManager;
/** @var Generate */
protected $command;
protected function setUp() {
parent::setUp();
$this->timeFactory = $this->createMock(ITimeFactory::class);
$this->userManager = $this->createMock(IUserManager::class);
$this->notificationManager = $this->createMock(IManager::class);
$this->command = new Generate(
$this->timeFactory,
$this->userManager,
$this->notificationManager
);
}
public function dataExecute() {
return [
['user', '', '', false, null, false, null, 123, null, 1],
['user', '', '', false, null, false, 'user', 123, null, 1],
['user', str_repeat('a', 256), '', false, null, false, 'user', 123, null, 1],
['user', 'short', '', true, false, false, 'user', 123, '7b', 0],
['user', 'short', str_repeat('a', 4001), false, null, false, 'user', 123, null, 1],
['user', 'short', str_repeat('a', 4000), true, false, true, 'user', 123, '7b', 0],
['user', 'short', 'long', true, true, true, 'user', 123, '7b', 1],
];
}
/**
* @dataProvider dataExecute
* @param string $userId
* @param string $short
* @param string $long
* @param bool $createNotification
* @param bool $notifyThrows
* @param bool $validLong
* @param string|null $user
* @param int $time
* @param string|null $hexTime
* @param int $exitCode
*/
public function testExecute($userId, $short, $long, $createNotification, $notifyThrows, $validLong, $user, $time, $hexTime, $exitCode) {
if ($user !== null) {
$u = $this->createMock(IUser::class);
$u->expects($createNotification ? $this->once() : $this->never())
->method('getUID')
->willReturn($user);
} else {
$u = null;
}
$this->userManager->expects($this->any())
->method('get')
->with($userId)
->willReturn($u);
$this->timeFactory->expects($hexTime === null ? $this->never() : $this->once())
->method('getTime')
->willReturn($time);
if ($createNotification) {
$n = $this->createMock(INotification::class);
$n->expects($this->once())
->method('setApp')
->with('admin_notifications')
->willReturnSelf();
$n->expects($this->once())
->method('setUser')
->with($user)
->willReturnSelf();
$n->expects($this->once())
->method('setDateTime')
->willReturnSelf();
$n->expects($this->once())
->method('setObject')
->with('admin_notifications', $hexTime)
->willReturnSelf();
$n->expects($this->once())
->method('setSubject')
->with('cli', [$short])
->willReturnSelf();
if ($validLong) {
$n->expects($this->once())
->method('setMessage')
->with('cli', [$long])
->willReturnSelf();
} else {
$n->expects($this->never())
->method('setMessage');
}
$this->notificationManager->expects($this->once())
->method('createNotification')
->willReturn($n);
if ($notifyThrows === null) {
$this->notificationManager->expects($this->never())
->method('notify');
} else if ($notifyThrows === false) {
$this->notificationManager->expects($this->once())
->method('notify')
->with($n);
} else if ($notifyThrows === true) {
$this->notificationManager->expects($this->once())
->method('notify')
->willThrowException(new \InvalidArgumentException());
}
}
$input = $this->createMock(InputInterface::class);
$input->expects($this->exactly(2))
->method('getArgument')
->willReturnMap([
['user-id', $userId],
['short-message', $short],
]);
$input->expects($this->exactly(1))
->method('getOption')
->willReturnMap([
['long-message', $long],
]);
$output = $this->createMock(OutputInterface::class);
$return = self::invokePrivate($this->command, 'execute', [$input, $output]);
$this->assertSame($exitCode, $return);
}
}

Просмотреть файл

@ -0,0 +1,168 @@
<?php
/**
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
*
* @author Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Notifications\Tests\Unit\Controller;
use OCA\Notifications\Controller\APIController;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Notification\IManager;
use OCP\Notification\INotification;
/**
* Class APIControllerTest
*
* @package OCA\Notifications\Tests\Unit\Controller
* @group DB
*/
class APIControllerTest extends \Test\TestCase {
/** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */
protected $timeFactory;
/** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
protected $userManager;
/** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
protected $notificationManager;
/** @var APIController */
protected $controller;
protected function setUp() {
parent::setUp();
/** @var IRequest|\PHPUnit_Framework_MockObject_MockObject $request */
$request = $this->createMock(IRequest::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
$this->userManager = $this->createMock(IUserManager::class);
$this->notificationManager = $this->createMock(IManager::class);
$this->controller = new APIController(
'notifications',
$request,
$this->timeFactory,
$this->userManager,
$this->notificationManager
);
}
public function dataGenerateNotification() {
return [
['user', '', '', false, null, false, null, 123, null, Http::STATUS_NOT_FOUND],
['user', '', '', false, null, false, 'user', 123, null, Http::STATUS_BAD_REQUEST],
['user', null, '', false, null, false, 'user', 123, null, Http::STATUS_BAD_REQUEST],
['user', str_repeat('a', 256), '', false, null, false, 'user', 123, null, Http::STATUS_BAD_REQUEST],
['user', 'short', '', true, false, false, 'user', 123, '7b', Http::STATUS_OK],
['user', 'short', str_repeat('a', 4001), false, null, false, 'user', 123, null, Http::STATUS_BAD_REQUEST],
['user', 'short', str_repeat('a', 4000), true, false, true, 'user', 123, '7b', Http::STATUS_OK],
['user', 'short', 'long', true, true, true, 'user', 123, '7b', Http::STATUS_INTERNAL_SERVER_ERROR],
];
}
/**
* @dataProvider dataGenerateNotification
* @param string $userId
* @param string $short
* @param string $long
* @param bool $createNotification
* @param bool $notifyThrows
* @param bool $validLong
* @param string|null $user
* @param int $time
* @param string|null $hexTime
* @param int $statusCode
*/
public function testGenerateNotification($userId, $short, $long, $createNotification, $notifyThrows, $validLong, $user, $time, $hexTime, $statusCode) {
if ($user !== null) {
$u = $this->createMock(IUser::class);
$u->expects($createNotification ? $this->once() : $this->never())
->method('getUID')
->willReturn($user);
} else {
$u = null;
}
$this->userManager->expects($this->any())
->method('get')
->with($userId)
->willReturn($u);
$this->timeFactory->expects($hexTime === null ? $this->never() : $this->once())
->method('getTime')
->willReturn($time);
if ($createNotification) {
$n = $this->createMock(INotification::class);
$n->expects($this->once())
->method('setApp')
->with('admin_notifications')
->willReturnSelf();
$n->expects($this->once())
->method('setUser')
->with($user)
->willReturnSelf();
$n->expects($this->once())
->method('setDateTime')
->willReturnSelf();
$n->expects($this->once())
->method('setObject')
->with('admin_notifications', $hexTime)
->willReturnSelf();
$n->expects($this->once())
->method('setSubject')
->with('ocs', [$short])
->willReturnSelf();
if ($validLong) {
$n->expects($this->once())
->method('setMessage')
->with('ocs', [$long])
->willReturnSelf();
} else {
$n->expects($this->never())
->method('setMessage');
}
$this->notificationManager->expects($this->once())
->method('createNotification')
->willReturn($n);
if ($notifyThrows === null) {
$this->notificationManager->expects($this->never())
->method('notify');
} else if ($notifyThrows === false) {
$this->notificationManager->expects($this->once())
->method('notify')
->with($n);
} else if ($notifyThrows === true) {
$this->notificationManager->expects($this->once())
->method('notify')
->willThrowException(new \InvalidArgumentException());
}
}
$response = $this->controller->generateNotification($userId, $short, $long);
$this->assertInstanceOf(DataResponse::class, $response);
$this->assertSame($statusCode, $response->getStatus());
}
}

Просмотреть файл

@ -0,0 +1,162 @@
<?php
/**
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
*
* @author Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Notifications\Tests\Unit\Notifier;
use OCA\Notifications\Notifier\AdminNotifications;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\L10N\IFactory;
use OCP\Notification\INotification;
class NotifierTest extends \Test\TestCase {
/** @var AdminNotifications */
protected $notifier;
/** @var IFactory|\PHPUnit_Framework_MockObject_MockObject */
protected $factory;
/** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
protected $urlGenerator;
/** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
protected $l;
protected function setUp() {
parent::setUp();
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->l = $this->createMock(IL10N::class);
$this->l->expects($this->any())
->method('t')
->willReturnCallback(function($string, $args) {
return vsprintf($string, $args);
});
$this->factory = $this->createMock(IFactory::class);
$this->factory->expects($this->any())
->method('get')
->willReturn($this->l);
$this->notifier = new AdminNotifications(
$this->factory,
$this->urlGenerator
);
}
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage Unknown app
*/
public function testPrepareWrongApp() {
/** @var INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
->method('getApp')
->willReturn('notifications');
$notification->expects($this->never())
->method('getSubject');
$this->notifier->prepare($notification, 'en');
}
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage Unknown subject
*/
public function testPrepareWrongSubject() {
/** @var INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
->method('getApp')
->willReturn('admin_notifications');
$notification->expects($this->once())
->method('getSubject')
->willReturn('wrong subject');
$this->notifier->prepare($notification, 'en');
}
public function dataPrepare() {
return [
['ocs', ['subject'], ['message'], true],
];
}
/**
* @dataProvider dataPrepare
*
* @param string $subject
* @param array $subjectParams
* @param array $messageParams
* @param bool $setMessage
*/
public function testPrepare($subject, $subjectParams, $messageParams, $setMessage) {
/** @var INotification|\PHPUnit_Framework_MockObject_MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
->method('getApp')
->willReturn('admin_notifications');
$notification->expects($this->once())
->method('getSubject')
->willReturn($subject);
$notification->expects($this->once())
->method('getSubjectParameters')
->willReturn($subjectParams);
$notification->expects($this->once())
->method('getMessageParameters')
->willReturn($messageParams);
$notification->expects($this->once())
->method('setParsedSubject')
->with($subjectParams[0])
->willReturnSelf();
if ($setMessage) {
$notification->expects($this->once())
->method('setParsedMessage')
->with($messageParams[0])
->willReturnSelf();
} else {
$notification->expects($this->never())
->method('setParsedMessage');
}
$this->urlGenerator->expects($this->once())
->method('imagePath')
->with('notifications', 'notifications-dark.svg')
->willReturn('icon-url');
$this->urlGenerator->expects($this->once())
->method('getAbsoluteURL')
->with('icon-url')
->willReturn('absolute-icon-url');
$notification->expects($this->once())
->method('setIcon')
->with('absolute-icon-url')
->willReturnSelf();
$return = $this->notifier->prepare($notification, 'en');
$this->assertEquals($notification, $return);
}
}