diff options
author | Daniel Rudolf <github.com@daniel-rudolf.de> | 2021-04-16 20:10:14 +0300 |
---|---|---|
committer | Daniel Rudolf <github.com@daniel-rudolf.de> | 2021-04-16 20:10:14 +0300 |
commit | 4d2d973c06aa0e36762286b65a60d83a3064ac40 (patch) | |
tree | aabf5c6201c4e10fbda92a19d02c13e15f82afaa /tests | |
parent | 6d2480df04fa5d411c310e7abf769c2821ab0bcd (diff) |
Add PHPUnit integration tests for polls:share:* commands
Signed-off-by: Daniel Rudolf <github.com@daniel-rudolf.de>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Integration/Command/Share/AddTest.php | 206 | ||||
-rw-r--r-- | tests/Integration/Command/Share/RemoveTest.php | 187 | ||||
-rw-r--r-- | tests/Integration/Command/Share/TShareCommandTest.php | 129 |
3 files changed, 522 insertions, 0 deletions
diff --git a/tests/Integration/Command/Share/AddTest.php b/tests/Integration/Command/Share/AddTest.php new file mode 100644 index 00000000..8d064722 --- /dev/null +++ b/tests/Integration/Command/Share/AddTest.php @@ -0,0 +1,206 @@ +<?php +/** + * @copyright Copyright (c) 2021 Daniel Rudolf <nextcloud.com@daniel-rudolf.de> + * + * @author Daniel Rudolf <nextcloud.com@daniel-rudolf.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\Polls\Tests\Integration\Command\Share; + +use OCA\Polls\Command\Share\Add; +use OCA\Polls\Db\Poll; +use OCA\Polls\Db\Share; +use OCA\Polls\Exceptions\ShareAlreadyExistsException; +use OCA\Polls\Model\Email; +use OCA\Polls\Model\Group; +use OCA\Polls\Model\User; +use OCP\AppFramework\Db\DoesNotExistException; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException; +use Symfony\Component\Console\Tester\CommandTester; + +class AddTest extends TestCase +{ + use TShareCommandTest; + + public function setUp(): void { + parent::setUp(); + + $this->setUpMocks(); + } + + public function testMissingArguments(): void { + $this->pollMapper + ->expects($this->never()) + ->method('find'); + + $this->expectException(ConsoleRuntimeException::class); + $this->expectExceptionMessage('Not enough arguments (missing: "id").'); + + $command = new Add( + $this->pollMapper, + $this->shareMapper, + $this->shareService, + $this->userManager, + $this->groupManager + ); + + $tester = new CommandTester($command); + $tester->execute([]); + } + + public function testPollNotFound(): void { + $pollId = 123; + + $this->pollMapper + ->expects($this->once()) + ->method('find') + ->with($pollId) + ->willReturnCallback(function (int $id): Poll { + throw new DoesNotExistException(''); + }); + + $command = new Add( + $this->pollMapper, + $this->shareMapper, + $this->shareService, + $this->userManager, + $this->groupManager + ); + + $tester = new CommandTester($command); + $tester->execute(['id' => $pollId]); + + $this->assertEquals("Poll not found.\n", $tester->getDisplay()); + } + + /** + * @dataProvider validProvider + */ + public function testValid(array $input, array $pollData): void { + $expectedShareCount = count($pollData['expectedShares']['user']) + + count($pollData['expectedShares']['group']) + + count($pollData['expectedShares']['email']); + $expectedInvitationCount = count($pollData['expectedInvitations']['user']) + + count($pollData['expectedInvitations']['group']) + + count($pollData['expectedInvitations']['email']); + + $expectedInvitationShareTokens = []; + foreach ($pollData['expectedInvitations'] as $type => $shares) { + foreach ($shares as $userId) { + $expectedInvitationShareTokens[] = $this->getShareToken($pollData['pollId'], $type, $userId); + } + } + + $this->pollMapper + ->expects($this->once()) + ->method('find') + ->with($pollData['pollId']) + ->willReturnCallback([$this, 'createPollMock']); + + $this->shareService + ->expects($this->exactly($expectedShareCount)) + ->method('add') + ->with($pollData['pollId'], $this->logicalOr(User::TYPE, Group::TYPE, Email::TYPE), $this->anything()) + ->willReturnCallback(function (int $pollId, string $type, string $userId = '') use ($pollData): Share { + $userIdConstraint = $this->logicalOr(...$pollData['expectedShares'][$type] ?? []); + $userIdConstraint->evaluate($userId); + + if (in_array($userId, $pollData['initialShares'][$type] ?? [])) { + throw new ShareAlreadyExistsException(); + } + + return $this->createShareMock($pollId, $type, $userId); + }); + + $this->shareService + ->expects($this->exactly($expectedInvitationCount)) + ->method('sendInvitation') + ->with($this->logicalOr(...$expectedInvitationShareTokens)); + + $command = new Add( + $this->pollMapper, + $this->shareMapper, + $this->shareService, + $this->userManager, + $this->groupManager + ); + + $tester = new CommandTester($command); + $tester->execute($input); + + $this->assertEquals("Users successfully invited to poll.\n", $tester->getDisplay()); + } + + public function validProvider(): array { + return [ + [ + [ + 'id' => 1, + ], + [ + 'pollId' => 1, + ], + ], + [ + [ + 'id' => 123, + '--user' => ['user1', 'user2'], + '--group' => ['group1'], + '--email' => ['foo@example.com', 'bar@example.com'], + ], + [ + 'pollId' => 123, + 'expectedShares' => [ + 'user' => ['user1', 'user2'], + 'group' => ['group1'], + 'email' => ['foo@example.com', 'bar@example.com'], + ], + 'expectedInvitations' => [ + 'user' => ['user1', 'user2'], + 'group' => ['group1'], + 'email' => ['foo@example.com', 'bar@example.com'], + ], + ], + ], + [ + [ + 'id' => 456, + '--user' => ['user2', 'user3', 'user4'], + '--email' => ['foo@example.com', 'bar@example.com'], + ], + [ + 'pollId' => 456, + 'initialShares' => [ + 'user' => ['user1', 'user2'], + 'email' => ['foo@example.com'], + ], + 'expectedShares' => [ + 'user' => ['user2', 'user3', 'user4'], + 'email' => ['foo@example.com', 'bar@example.com'], + ], + 'expectedInvitations' => [ + 'user' => ['user3', 'user4'], + 'email' => ['bar@example.com'], + ], + ], + ], + ]; + } +} diff --git a/tests/Integration/Command/Share/RemoveTest.php b/tests/Integration/Command/Share/RemoveTest.php new file mode 100644 index 00000000..39960707 --- /dev/null +++ b/tests/Integration/Command/Share/RemoveTest.php @@ -0,0 +1,187 @@ +<?php +/** + * @copyright Copyright (c) 2021 Daniel Rudolf <nextcloud.com@daniel-rudolf.de> + * + * @author Daniel Rudolf <nextcloud.com@daniel-rudolf.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\Polls\Tests\Integration\Command\Share; + +use OCA\Polls\Command\Share\Remove; +use OCA\Polls\Db\Poll; +use OCP\AppFramework\Db\DoesNotExistException; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException; +use Symfony\Component\Console\Tester\CommandTester; + +class RemoveTest extends TestCase +{ + use TShareCommandTest; + + public function setUp(): void { + parent::setUp(); + + $this->setUpMocks(); + } + + public function testMissingArguments(): void { + $this->pollMapper + ->expects($this->never()) + ->method('find'); + + $this->expectException(ConsoleRuntimeException::class); + $this->expectExceptionMessage('Not enough arguments (missing: "id").'); + + $command = new Remove( + $this->pollMapper, + $this->shareMapper, + $this->shareService, + $this->userManager, + $this->groupManager + ); + + $tester = new CommandTester($command); + $tester->execute([]); + } + + public function testPollNotFound(): void { + $pollId = 123; + + $this->pollMapper + ->expects($this->once()) + ->method('find') + ->with($pollId) + ->willReturnCallback(static function (int $id): Poll { + throw new DoesNotExistException(''); + }); + + $command = new Remove( + $this->pollMapper, + $this->shareMapper, + $this->shareService, + $this->userManager, + $this->groupManager + ); + + $tester = new CommandTester($command); + $tester->execute(['id' => $pollId]); + + $this->assertEquals("Poll not found.\n", $tester->getDisplay()); + } + + /** + * @dataProvider validProvider + */ + public function testValid(array $input, array $pollData): void { + $initialShares = []; + $expectedShareCount = 0; + $expectedShareTokens = []; + foreach ($pollData['initialShares'] as $type => $shares) { + foreach ($shares as $userId) { + $initialShares[] = $this->createShareMock($pollData['pollId'], $type, $userId); + + if (in_array($userId, $pollData['expectedShares'][$type])) { + $expectedShareTokens[] = $this->getShareToken($pollData['pollId'], $type, $userId); + $expectedShareCount++; + } + } + } + + $this->pollMapper + ->expects($this->once()) + ->method('find') + ->with($pollData['pollId']) + ->willReturnCallback([$this, 'createPollMock']); + + $this->shareMapper + ->method('findByPoll') + ->with($pollData['pollId']) + ->willReturn($initialShares); + + $this->shareService + ->expects($this->exactly($expectedShareCount)) + ->method('delete') + ->with($this->logicalOr(...$expectedShareTokens)); + + $command = new Remove( + $this->pollMapper, + $this->shareMapper, + $this->shareService, + $this->userManager, + $this->groupManager + ); + + $tester = new CommandTester($command); + $tester->execute($input); + + $this->assertEquals("Poll invitations successfully revoked.\n", $tester->getDisplay()); + } + + public function validProvider(): array { + return [ + [ + [ + 'id' => 1, + ], + [ + 'pollId' => 1, + ], + ], + [ + [ + 'id' => 123, + '--user' => ['user1', 'user2'], + '--group' => ['group1'], + '--email' => ['foo@example.com'], + ], + [ + 'pollId' => 123, + 'initialShares' => [ + 'user' => ['user1', 'user2', 'user3'], + 'group' => ['group1'], + 'email' => ['foo@example.com', 'bar@example.com'], + ], + 'expectedShares' => [ + 'user' => ['user1', 'user2'], + 'group' => ['group1'], + 'email' => ['foo@example.com'], + ], + ], + ], + [ + [ + 'id' => 456, + '--user' => ['user1', 'user2', 'user3', 'user4'], + '--email' => ['foo@example.com', 'bar@example.com'], + ], + [ + 'pollId' => 456, + 'initialShares' => [ + 'user' => ['user2', 'user3'], + 'email' => ['foo@example.com', 'bar@example.com', 'baz@example.com'], + ], + 'expectedShares' => [ + 'user' => ['user2', 'user3'], + 'email' => ['foo@example.com', 'bar@example.com'], + ], + ] + ], + ]; + } +} diff --git a/tests/Integration/Command/Share/TShareCommandTest.php b/tests/Integration/Command/Share/TShareCommandTest.php new file mode 100644 index 00000000..0fdc040d --- /dev/null +++ b/tests/Integration/Command/Share/TShareCommandTest.php @@ -0,0 +1,129 @@ +<?php +/** + * @copyright Copyright (c) 2021 Daniel Rudolf <nextcloud.com@daniel-rudolf.de> + * + * @author Daniel Rudolf <nextcloud.com@daniel-rudolf.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\Polls\Tests\Integration\Command\Share; + +use OCA\Polls\Db\Poll; +use OCA\Polls\Db\PollMapper; +use OCA\Polls\Db\Share; +use OCA\Polls\Db\ShareMapper; +use OCA\Polls\Service\ShareService; +use OCP\IGroupManager; +use OCP\IUserManager; +use PHPUnit\Framework\MockObject\MockObject; + +trait TShareCommandTest { + /** @var PollMapper|MockObject */ + protected $pollMapper; + + /** @var ShareMapper|MockObject */ + protected $shareMapper; + + /** @var ShareService|MockObject */ + protected $shareService; + + /** @var IUserManager|MockObject */ + protected $userManager; + + /** @var IGroupManager|MockObject */ + protected $groupManager; + + /** @var int */ + protected $lastShareId = 0; + + protected function setUpMocks(): void { + $this->pollMapper = $this->createMock(PollMapper::class); + $this->shareMapper = $this->createMock(ShareMapper::class); + $this->shareService = $this->createMock(ShareService::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->groupManager = $this->createMock(IGroupManager::class); + } + + public function createPollMock(int $id): Poll { + /** @var Poll|MockObject $poll */ + $poll = $this->createMock( + Poll::class, + ['getId'] + ); + + $poll->method('getId') + ->willReturn($id); + + return $poll; + } + + public function createShareMock(int $pollId, string $type, string $userId): Share { + /** @var Share|MockObject $share */ + $share = $this->createMock( + Share::class, + ['getId', 'getPollId', 'getType', 'getEmailAddress', 'getToken'], + ['getUserId'] + ); + + $id = ++$this->lastShareId; + $token = $this->getShareToken($pollId, $type, $userId); + + $share->method('getId') + ->willReturn($id); + + $share->method('getPollId') + ->willReturn($pollId); + + $share->method('getType') + ->willReturn($type); + + $share->method('getUserId') + ->willReturn($userId); + + $share->method('getEmailAddress') + ->willReturn($userId); + + $share->method('getToken') + ->willReturn($token); + + return $share; + } + + public function getShareToken(int $pollId, string $type, string $userId): string { + return substr(md5($pollId . '_' . $type . '_' . $userId), 0, 16); + } + + protected function createMock($originalClassName, array $addMethods = null, array $onlyMethods = null): MockObject { + $mockBuilder = $this->getMockBuilder($originalClassName) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning() + ->disallowMockingUnknownTypes() + ->disableAutoReturnValueGeneration(); + + if ($addMethods !== null) { + $mockBuilder->addMethods($addMethods); + } + + if ($onlyMethods !== null) { + $mockBuilder->onlyMethods($onlyMethods); + } + + return $mockBuilder->getMock(); + } +} |