- Add typing for most of the services, controllers and mappers - Add api doc for mappers - Use vendor-bin for psalm - Use attributes for controllers - Fix upload of attachments Signed-off-by: Carl Schwan <carl.schwan@nextcloud.com>
499 lines
14 KiB
PHP
499 lines
14 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
|
*
|
|
* @author Julius Härtl <jus@bitgrid.net>
|
|
*
|
|
* @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\Deck\Activity;
|
|
|
|
use OCA\Deck\Db\AclMapper;
|
|
use OCA\Deck\Db\Assignment;
|
|
use OCA\Deck\Db\Attachment;
|
|
use OCA\Deck\Db\Board;
|
|
use OCA\Deck\Db\BoardMapper;
|
|
use OCA\Deck\Db\Card;
|
|
use OCA\Deck\Db\CardMapper;
|
|
use OCA\Deck\Db\Label;
|
|
use OCA\Deck\Db\Stack;
|
|
use OCA\Deck\Db\StackMapper;
|
|
use OCA\Deck\Service\PermissionService;
|
|
use OCP\Activity\IEvent;
|
|
use OCP\Activity\IManager;
|
|
use OCP\IL10N;
|
|
use OCP\IUser;
|
|
use OCP\L10N\IFactory;
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class ActivityManagerTest extends TestCase {
|
|
|
|
/** @var ActivityManager */
|
|
private $activityManager;
|
|
/** @var IManager|MockObject */
|
|
private $manager;
|
|
/** @var PermissionService|MockObject */
|
|
private $permissionService;
|
|
/** @var BoardMapper|MockObject */
|
|
private $boardMapper;
|
|
/** @var CardMapper|MockObject */
|
|
private $cardMapper;
|
|
/** @var StackMapper|MockObject */
|
|
private $stackMapper;
|
|
/** @var AclMapper|MockObject */
|
|
private $aclMapper;
|
|
/** @var IFactory|MockObject */
|
|
private $l10nFactory;
|
|
/** @var IL10N|MockObject */
|
|
private $l10n;
|
|
/** @var string */
|
|
private $userId = 'admin';
|
|
|
|
public function setUp(): void {
|
|
$this->manager = $this->createMock(IManager::class);
|
|
$this->permissionService = $this->createMock(PermissionService::class);
|
|
$this->boardMapper = $this->createMock(BoardMapper::class);
|
|
$this->cardMapper = $this->createMock(CardMapper::class);
|
|
$this->stackMapper = $this->createMock(StackMapper::class);
|
|
$this->aclMapper = $this->createMock(AclMapper::class);
|
|
$this->l10nFactory = $this->createMock(IFactory::class);
|
|
$this->l10n = $this->createMock(IL10N::class);
|
|
$this->activityManager = new ActivityManager(
|
|
$this->manager,
|
|
$this->permissionService,
|
|
$this->boardMapper,
|
|
$this->cardMapper,
|
|
$this->stackMapper,
|
|
$this->aclMapper,
|
|
$this->l10nFactory,
|
|
$this->userId
|
|
);
|
|
}
|
|
|
|
public function testGetActivityFormatOwn() {
|
|
$managerClass = new \ReflectionClass(ActivityManager::class);
|
|
$this->l10n->expects(self::any())
|
|
->method('t')
|
|
->will($this->returnCallback(function ($s) {
|
|
return $s;
|
|
}));
|
|
$this->l10nFactory->method('get')
|
|
->with('deck', 'cz')
|
|
->willReturn($this->l10n);
|
|
|
|
foreach ($managerClass->getConstants() as $constant => $value) {
|
|
if (str_starts_with($constant, 'SUBJECT')) {
|
|
$format = $this->activityManager->getActivityFormat('cz', $value, [], false);
|
|
if ($format !== '') {
|
|
$this->assertStringContainsString('{user}', $format);
|
|
} else {
|
|
self::addWarning('No activity string found for ' . $constant);
|
|
}
|
|
$format = $this->activityManager->getActivityFormat('cz', $value, [], true);
|
|
if ($format !== '') {
|
|
$this->assertStringStartsWith('You', $format);
|
|
} else {
|
|
self::addWarning('No own activity string found for ' . $constant);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private function expectEventCreation($subject, $subjectParams) {
|
|
$event = $this->createMock(IEvent::class);
|
|
$this->manager->expects(self::once())
|
|
->method('generateEvent')
|
|
->willReturn($event);
|
|
$event->expects(self::once())->method('setApp')->willReturn($event);
|
|
$event->expects(self::once())->method('setType')->willReturn($event);
|
|
$event->expects(self::once())->method('setAuthor')->willReturn($event);
|
|
$event->expects(self::once())->method('setObject')->willReturn($event);
|
|
$event->expects(self::once())->method('setSubject')->with($subject, $subjectParams)->willReturn($event);
|
|
$event->expects(self::once())->method('setTimestamp')->willReturn($event);
|
|
return $event;
|
|
}
|
|
|
|
public function testCreateEvent() {
|
|
$board = new Board();
|
|
$board->setId(123);
|
|
$board->setTitle('');
|
|
$this->boardMapper->expects(self::once())
|
|
->method('find')
|
|
->willReturn($board);
|
|
$event = $this->expectEventCreation(ActivityManager::SUBJECT_BOARD_CREATE, [
|
|
'author' => 'admin'
|
|
]);
|
|
$actual = $this->invokePrivate($this->activityManager, 'createEvent', [
|
|
ActivityManager::DECK_OBJECT_BOARD,
|
|
$board,
|
|
ActivityManager::SUBJECT_BOARD_CREATE
|
|
]);
|
|
$this->assertEquals($event, $actual);
|
|
}
|
|
|
|
public function testCreateEventDescription() {
|
|
$board = new Board();
|
|
$board->setId(123);
|
|
$board->setTitle('');
|
|
$this->boardMapper->expects(self::once())
|
|
->method('find')
|
|
->willReturn($board);
|
|
|
|
$card = Card::fromRow([
|
|
'id' => 123,
|
|
'title' => 'My card',
|
|
'description' => str_repeat('A', 1000),
|
|
'stackId' => 42,
|
|
]);
|
|
$this->cardMapper->expects(self::any())
|
|
->method('find')
|
|
->willReturn($card);
|
|
|
|
$stack = Stack::fromRow([
|
|
'boardId' => 123,
|
|
]);
|
|
$this->stackMapper->expects(self::any())
|
|
->method('find')
|
|
->with(42)
|
|
->willReturn($stack);
|
|
|
|
$expectedCard = $card->jsonSerialize();
|
|
unset($expectedCard['description']);
|
|
$event = $this->expectEventCreation(ActivityManager::SUBJECT_CARD_UPDATE_DESCRIPTION, [
|
|
'card' => $expectedCard,
|
|
'stack' => $stack->jsonSerialize(),
|
|
'board' => $board->jsonSerialize(),
|
|
'diff' => true,
|
|
'author' => 'admin',
|
|
'after' => str_repeat('C', 2000),
|
|
]);
|
|
|
|
$actual = $this->invokePrivate($this->activityManager, 'createEvent', [
|
|
ActivityManager::DECK_OBJECT_CARD,
|
|
$card,
|
|
ActivityManager::SUBJECT_CARD_UPDATE_DESCRIPTION,
|
|
[
|
|
'before' => str_repeat('B', 2000),
|
|
'after' => str_repeat('C', 2000)
|
|
],
|
|
]);
|
|
$this->assertEquals($event, $actual);
|
|
}
|
|
|
|
public function testCreateEventLongDescription() {
|
|
$board = new Board();
|
|
$board->setId(123);
|
|
$board->setTitle('');
|
|
$this->boardMapper->expects(self::once())
|
|
->method('find')
|
|
->willReturn($board);
|
|
|
|
$card = new Card();
|
|
$card->setDescription(str_repeat('A', 5000));
|
|
$card->setTitle('My card');
|
|
$card->setId(123);
|
|
$card->setStackId(42);
|
|
$this->cardMapper->expects(self::any())
|
|
->method('find')
|
|
->willReturn($card);
|
|
|
|
$stack = Stack::fromRow([
|
|
'boardId' => 123,
|
|
]);
|
|
$this->stackMapper->expects(self::any())
|
|
->method('find')
|
|
->willReturn($stack);
|
|
|
|
$expectedCard = $card->jsonSerialize();
|
|
unset($expectedCard['description']);
|
|
$event = $this->expectEventCreation(ActivityManager::SUBJECT_CARD_UPDATE_DESCRIPTION, [
|
|
'card' => $expectedCard,
|
|
'stack' => $stack->jsonSerialize(),
|
|
'board' => $board->jsonSerialize(),
|
|
'diff' => true,
|
|
'author' => 'admin',
|
|
'after' => str_repeat('C', 2000) . '...',
|
|
]);
|
|
|
|
$actual = $this->invokePrivate($this->activityManager, 'createEvent', [
|
|
ActivityManager::DECK_OBJECT_CARD,
|
|
$card,
|
|
ActivityManager::SUBJECT_CARD_UPDATE_DESCRIPTION,
|
|
[
|
|
'before' => str_repeat('B', 5000),
|
|
'after' => str_repeat('C', 5000)
|
|
],
|
|
]);
|
|
$this->assertEquals($event, $actual);
|
|
}
|
|
|
|
public function testCreateEventLabel() {
|
|
$board = Board::fromRow([
|
|
'id' => 123,
|
|
'title' => 'My board'
|
|
]);
|
|
$this->boardMapper->expects(self::once())
|
|
->method('find')
|
|
->willReturn($board);
|
|
|
|
$card = Card::fromParams([]);
|
|
$card->setDescription(str_repeat('A', 5000));
|
|
$card->setTitle('My card');
|
|
$card->setId(123);
|
|
$card->setStackId(42);
|
|
$this->cardMapper->expects(self::any())
|
|
->method('find')
|
|
->willReturn($card);
|
|
|
|
$stack = Stack::fromRow([
|
|
'boardId' => 123,
|
|
]);
|
|
$this->stackMapper->expects(self::any())
|
|
->method('find')
|
|
->willReturn($stack);
|
|
|
|
$event = $this->expectEventCreation(ActivityManager::SUBJECT_CARD_UPDATE_TITLE, [
|
|
'card' => [
|
|
'id' => 123,
|
|
'title' => 'My card',
|
|
'archived' => false,
|
|
],
|
|
'stack' => $stack,
|
|
'board' => $board,
|
|
'author' => 'admin',
|
|
]);
|
|
|
|
$actual = $this->invokePrivate($this->activityManager, 'createEvent', [
|
|
ActivityManager::DECK_OBJECT_CARD,
|
|
$card,
|
|
ActivityManager::SUBJECT_CARD_UPDATE_TITLE
|
|
]);
|
|
$this->assertEquals($event, $actual);
|
|
}
|
|
|
|
public static function dataSendToUsers() {
|
|
return [
|
|
[ActivityManager::DECK_OBJECT_BOARD],
|
|
[ActivityManager::DECK_OBJECT_CARD],
|
|
];
|
|
}
|
|
|
|
private function mockUser($uid) {
|
|
$user = $this->createMock(IUser::class);
|
|
$user->expects(self::any())
|
|
->method('getUID')
|
|
->willReturn($uid);
|
|
return $user;
|
|
}
|
|
/**
|
|
* @dataProvider dataSendToUsers
|
|
*/
|
|
public function testSendToUser($objectType) {
|
|
$users = [
|
|
$this->mockUser('user1'),
|
|
$this->mockUser('user2'),
|
|
];
|
|
$event = $this->createMock(IEvent::class);
|
|
|
|
$event->expects(self::once())
|
|
->method('getObjectType')
|
|
->willReturn($objectType);
|
|
$event->expects(self::once())
|
|
->method('getObjectId')
|
|
->willReturn(1);
|
|
$event->expects(self::exactly(2))
|
|
->method('setAffectedUser')
|
|
->withConsecutive(
|
|
['user1'],
|
|
['user2'],
|
|
)
|
|
->willReturnSelf();
|
|
|
|
$mapper = null;
|
|
switch ($objectType) {
|
|
case ActivityManager::DECK_OBJECT_BOARD:
|
|
$mapper = $this->boardMapper;
|
|
break;
|
|
case ActivityManager::DECK_OBJECT_CARD:
|
|
$mapper = $this->cardMapper;
|
|
break;
|
|
}
|
|
$mapper->expects(self::once())
|
|
->method('findBoardId')
|
|
->willReturn(123);
|
|
$this->permissionService->expects(self::once())
|
|
->method('findUsers')
|
|
->willReturn($users);
|
|
|
|
$this->manager->expects(self::exactly(2))
|
|
->method('publish')
|
|
->with($event);
|
|
$this->invokePrivate($this->activityManager, 'sendToUsers', [$event]);
|
|
}
|
|
|
|
public static function dataFindObjectForEntity() {
|
|
$board = new Board();
|
|
$board->setId(1);
|
|
$stack = new Stack();
|
|
$stack->setBoardId(1);
|
|
$card = new Card();
|
|
$card->setId(3);
|
|
$attachment = new Attachment();
|
|
$attachment->setCardId(3);
|
|
$label = new Label();
|
|
$label->setCardId(3);
|
|
$label->setBoardId(1);
|
|
$assignedUser = new Assignment();
|
|
$assignedUser->setCardId(3);
|
|
|
|
return [
|
|
[ActivityManager::DECK_OBJECT_BOARD, $board],
|
|
[ActivityManager::DECK_OBJECT_BOARD, $stack],
|
|
[ActivityManager::DECK_OBJECT_BOARD, $label],
|
|
[ActivityManager::DECK_OBJECT_CARD, $card],
|
|
[ActivityManager::DECK_OBJECT_CARD, $attachment],
|
|
[ActivityManager::DECK_OBJECT_CARD, $assignedUser],
|
|
[ActivityManager::DECK_OBJECT_CARD, $label],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param $objectType
|
|
* @param $entity
|
|
* @dataProvider dataFindObjectForEntity
|
|
*/
|
|
public function testFindObjectForEntity($objectType, $entity) {
|
|
$board = new Board();
|
|
$board->setId(1);
|
|
$card = new Card();
|
|
$card->setId(3);
|
|
$expected = null;
|
|
if ($objectType === ActivityManager::DECK_OBJECT_BOARD) {
|
|
$this->boardMapper->expects(self::once())
|
|
->method('find')
|
|
->with(1)
|
|
->willReturn($board);
|
|
$expected = $board;
|
|
}
|
|
if ($objectType === ActivityManager::DECK_OBJECT_CARD) {
|
|
$this->cardMapper->expects(self::once())
|
|
->method('find')
|
|
->with(3)
|
|
->willReturn($card);
|
|
$expected = $card;
|
|
}
|
|
$actual = $this->invokePrivate($this->activityManager, 'findObjectForEntity', [$objectType, $entity]);
|
|
$this->assertEquals($expected, $actual);
|
|
}
|
|
|
|
public function testFindDetailsForStack() {
|
|
$stack = new Stack();
|
|
$stack->setId(123);
|
|
$stack->setBoardId(999);
|
|
$board = new Board();
|
|
$board->setId(999);
|
|
$this->stackMapper->expects(self::once())
|
|
->method('find')
|
|
->with(123)
|
|
->willReturn($stack);
|
|
$this->boardMapper->expects(self::once())->method('find')
|
|
->with(999)
|
|
->willReturn($board);
|
|
$this->assertEquals([
|
|
'stack' => $stack,
|
|
'board' => $board
|
|
], $this->invokePrivate($this->activityManager, 'findDetailsForStack', [123]));
|
|
}
|
|
|
|
|
|
public function testFindDetailsForCard() {
|
|
$card = new Card();
|
|
$card->setId(555);
|
|
$card->setStackId(123);
|
|
$stack = new Stack();
|
|
$stack->setId(123);
|
|
$stack->setBoardId(999);
|
|
$board = new Board();
|
|
$board->setId(999);
|
|
$this->cardMapper->expects(self::once())
|
|
->method('find')
|
|
->with(555)
|
|
->willReturn($card);
|
|
$this->stackMapper->expects(self::once())
|
|
->method('find')
|
|
->with(123)
|
|
->willReturn($stack);
|
|
$this->boardMapper->expects(self::once())->method('find')
|
|
->with(999)
|
|
->willReturn($board);
|
|
$this->assertEquals([
|
|
'stack' => $stack,
|
|
'board' => $board,
|
|
'card' => [
|
|
'id' => $card->getId(),
|
|
'title' => $card->getTitle(),
|
|
'archived' => $card->getArchived()
|
|
]
|
|
], $this->invokePrivate($this->activityManager, 'findDetailsForCard', [555]));
|
|
}
|
|
|
|
public function testFindDetailsForAttachment() {
|
|
$attachment = new Attachment();
|
|
$attachment->setId(777);
|
|
$attachment->setCardId(555);
|
|
$card = new Card();
|
|
$card->setId(555);
|
|
$card->setStackId(123);
|
|
$stack = new Stack();
|
|
$stack->setId(123);
|
|
$stack->setBoardId(999);
|
|
$board = new Board();
|
|
$board->setId(999);
|
|
$this->cardMapper->expects(self::once())
|
|
->method('find')
|
|
->with(555)
|
|
->willReturn($card);
|
|
$this->stackMapper->expects(self::once())
|
|
->method('find')
|
|
->with(123)
|
|
->willReturn($stack);
|
|
$this->boardMapper->expects(self::once())->method('find')
|
|
->with(999)
|
|
->willReturn($board);
|
|
$this->assertEquals([
|
|
'stack' => $stack,
|
|
'board' => $board,
|
|
'card' => [
|
|
'id' => $card->getId(),
|
|
'title' => $card->getTitle(),
|
|
'archived' => $card->getArchived()
|
|
],
|
|
'attachment' => $attachment
|
|
], $this->invokePrivate($this->activityManager, 'findDetailsForAttachment', [$attachment]));
|
|
}
|
|
|
|
public function invokePrivate(&$object, $methodName, array $parameters = []) {
|
|
$reflection = new \ReflectionClass(get_class($object));
|
|
$method = $reflection->getMethod($methodName);
|
|
$method->setAccessible(true);
|
|
return $method->invokeArgs($object, $parameters);
|
|
}
|
|
}
|