diff options
author | Daniel Rudolf <github.com@daniel-rudolf.de> | 2020-05-13 16:52:56 +0300 |
---|---|---|
committer | Daniel Rudolf <github.com@daniel-rudolf.de> | 2020-05-13 16:52:56 +0300 |
commit | 5cb784bde78ff90ade25eab21cb718cff6d2c688 (patch) | |
tree | fcb1a32a30bc6b9039f90952557df84f8d6a4b56 /tests | |
parent | 44a24353fe1ae1a0c6abbf1e1b8d0ccfc088746b (diff) |
Add PHPUnit tests for talk:room:* commands
Signed-off-by: Daniel Rudolf <github.com@daniel-rudolf.de>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/php/Command/Room/AddTest.php | 326 | ||||
-rw-r--r-- | tests/php/Command/Room/CreateTest.php | 371 | ||||
-rw-r--r-- | tests/php/Command/Room/DeleteTest.php | 145 | ||||
-rw-r--r-- | tests/php/Command/Room/DemoteTest.php | 246 | ||||
-rw-r--r-- | tests/php/Command/Room/PromoteTest.php | 230 | ||||
-rw-r--r-- | tests/php/Command/Room/RemoveTest.php | 210 | ||||
-rw-r--r-- | tests/php/Command/Room/RoomMockContainer.php | 222 | ||||
-rw-r--r-- | tests/php/Command/Room/TRoomCommandTest.php | 121 | ||||
-rw-r--r-- | tests/php/Command/Room/UpdateTest.php | 349 |
9 files changed, 2220 insertions, 0 deletions
diff --git a/tests/php/Command/Room/AddTest.php b/tests/php/Command/Room/AddTest.php new file mode 100644 index 000000000..50d4be722 --- /dev/null +++ b/tests/php/Command/Room/AddTest.php @@ -0,0 +1,326 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2020 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\Talk\Tests\php\Command\Room; + +use OCA\Talk\Command\Room\Add; +use OCA\Talk\Exceptions\RoomNotFoundException; +use OCA\Talk\Manager; +use OCA\Talk\Participant; +use OCA\Talk\Room; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException; +use Symfony\Component\Console\Tester\CommandTester; +use Test\TestCase; + +class AddTest extends TestCase { + use TRoomCommandTest; + + /** @var Add */ + private $command; + + /** @var Manager|MockObject */ + private $manager; + + /** @var RoomMockContainer */ + private $roomMockContainer; + + public function setUp(): void { + parent::setUp(); + + $this->manager = $this->createMock(Manager::class); + $this->command = new Add($this->manager); + + $this->roomMockContainer = new RoomMockContainer($this); + + $this->registerUserManagerMock(); + $this->registerGroupManagerMock(); + + $this->createTestUserMocks(); + $this->createTestGroupMocks(); + } + + public function testMissingArguments(): void { + $this->manager->expects($this->never()) + ->method('getRoomByToken'); + + $this->expectException(ConsoleRuntimeException::class); + $this->expectExceptionMessage('Not enough arguments (missing: "token").'); + + $tester = new CommandTester($this->command); + $tester->execute([]); + } + + /** + * @dataProvider validProvider + */ + public function testValid(array $input, array $expectedRoomData, array $initialRoomData): void { + $this->manager->expects($this->once()) + ->method('getRoomByToken') + ->willReturnCallback(function (string $token) use ($initialRoomData): Room { + if ($token !== $initialRoomData['token']) { + throw new RoomNotFoundException(); + } + + return $this->roomMockContainer->create($initialRoomData); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals("Users successfully added to room.\n", $tester->getDisplay()); + + $this->assertEquals($expectedRoomData, $this->roomMockContainer->getRoomData()); + } + + public function validProvider(): array { + return [ + [ + [ + 'token' => '__test-room', + ], + RoomMockContainer::prepareRoomData([]), + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--user' => ['user1'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--user' => ['user1', 'user2'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--user' => ['user2'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'token' => '__test-room', + '--user' => ['user3'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::OWNER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ['userId' => 'user3', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::OWNER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'token' => '__test-room', + '--group' => ['group1'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--group' => ['group1', 'group2'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ['userId' => 'user3', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--group' => ['group1'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'token' => '__test-room', + '--group' => ['group1', 'group2'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::OWNER], + ['userId' => 'user4', 'participantType' => Participant::MODERATOR], + ['userId' => 'user2', 'participantType' => Participant::USER], + ['userId' => 'user3', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::OWNER], + ['userId' => 'user4', 'participantType' => Participant::MODERATOR], + ], + ]), + ], + [ + [ + 'token' => '__test-room', + '--group' => ['group1'], + '--user' => ['user4'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user4', 'participantType' => Participant::USER], + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--group' => ['group1'], + '--user' => ['user4'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::MODERATOR], + ['userId' => 'user3', 'participantType' => Participant::USER], + ['userId' => 'user4', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::MODERATOR], + ['userId' => 'user3', 'participantType' => Participant::USER], + ], + ]), + ], + ]; + } + + /** + * @dataProvider invalidProvider + */ + public function testInvalid(array $input, string $expectedOutput, array $initialRoomData): void { + $this->manager->expects($this->once()) + ->method('getRoomByToken') + ->willReturnCallback(function (string $token) use ($initialRoomData): Room { + if ($token !== $initialRoomData['token']) { + throw new RoomNotFoundException(); + } + + return $this->roomMockContainer->create($initialRoomData); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals($expectedOutput, $tester->getDisplay()); + } + + public function invalidProvider(): array { + return [ + [ + [ + 'token' => '__test-invalid', + ], + "Room not found.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + ], + "Room is no group call.\n", + RoomMockContainer::prepareRoomData([ + 'type' => Room::ONE_TO_ONE_CALL, + ]), + ], + [ + [ + 'token' => '__test-room', + '--user' => ['user1','invalid'] + ], + "User 'invalid' not found.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--group' => ['group1','invalid'] + ], + "Group 'invalid' not found.\n", + RoomMockContainer::prepareRoomData([]), + ], + ]; + } +} diff --git a/tests/php/Command/Room/CreateTest.php b/tests/php/Command/Room/CreateTest.php new file mode 100644 index 000000000..e835fb9ce --- /dev/null +++ b/tests/php/Command/Room/CreateTest.php @@ -0,0 +1,371 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2020 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\Talk\Tests\php\Command\Room; + +use OCA\Talk\Command\Room\Create; +use OCA\Talk\Manager; +use OCA\Talk\Participant; +use OCA\Talk\Room; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException; +use Symfony\Component\Console\Tester\CommandTester; +use Test\TestCase; + +class CreateTest extends TestCase { + use TRoomCommandTest; + + /** @var Create */ + private $command; + + /** @var Manager|MockObject */ + private $manager; + + /** @var RoomMockContainer */ + private $roomMockContainer; + + public function setUp(): void { + parent::setUp(); + + $this->manager = $this->createMock(Manager::class); + $this->command = new Create($this->manager); + + $this->roomMockContainer = new RoomMockContainer($this); + + $this->registerUserManagerMock(); + $this->registerGroupManagerMock(); + + $this->createTestUserMocks(); + $this->createTestGroupMocks(); + } + + public function testMissingArguments(): void { + $this->manager->expects($this->never()) + ->method('createGroupRoom'); + + $this->manager->expects($this->never()) + ->method('createPublicRoom'); + + $this->expectException(ConsoleRuntimeException::class); + $this->expectExceptionMessage('Not enough arguments (missing: "name").'); + + $tester = new CommandTester($this->command); + $tester->execute([]); + } + + /** + * @dataProvider validProvider + */ + public function testValid(array $input, array $expectedRoomData): void { + $this->manager + ->method('createGroupRoom') + ->willReturnCallback(function (string $name = ''): Room { + return $this->roomMockContainer->create(['name' => $name, 'type' => Room::GROUP_CALL]); + }); + + $this->manager + ->method('createPublicRoom') + ->willReturnCallback(function (string $name = ''): Room { + return $this->roomMockContainer->create(['name' => $name, 'type' => Room::PUBLIC_CALL]); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals("Room successfully created.\n", $tester->getDisplay()); + + $this->assertEquals($expectedRoomData, $this->roomMockContainer->getRoomData()); + } + + public function validProvider(): array { + return [ + [ + [ + 'name' => 'PHPUnit Test Room', + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--public' => true, + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'type' => Room::PUBLIC_CALL, + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--readonly' => true, + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'readOnly' => Room::READ_ONLY, + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--public' => true, + '--password' => 'my-secret-password', + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'type' => Room::PUBLIC_CALL, + 'password' => 'my-secret-password', + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--user' => ['user1'], + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--user' => ['user1', 'user2'], + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--user' => ['user1', 'user2'], + '--moderator' => ['user2'], + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::MODERATOR], + ], + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--user' => ['user1', 'user2', 'user3'], + '--moderator' => ['user2', 'user3'], + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::MODERATOR], + ['userId' => 'user3', 'participantType' => Participant::MODERATOR], + ], + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--user' => ['user1', 'user2'], + '--owner' => 'user2', + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::OWNER], + ], + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--group' => ['group1'], + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--group' => ['group1', 'group2'], + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ['userId' => 'user3', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--group' => ['group1'], + '--user' => ['user4'], + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'participants' => [ + ['userId' => 'user4', 'participantType' => Participant::USER], + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--group' => ['group1'], + '--moderator' => ['user1'], + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::MODERATOR], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--group' => ['group1'], + '--owner' => 'user1', + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room', + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::OWNER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + ]; + } + + /** + * @dataProvider invalidProvider + */ + public function testInvalid(array $input, string $expectedOutput): void { + $this->manager + ->method('createGroupRoom') + ->willReturnCallback(function (string $name = ''): Room { + return $this->roomMockContainer->create(['name' => $name, 'type' => Room::GROUP_CALL]); + }); + + $this->manager + ->method('createPublicRoom') + ->willReturnCallback(function (string $name = ''): Room { + return $this->roomMockContainer->create(['name' => $name, 'type' => Room::PUBLIC_CALL]); + }); + + $this->roomMockContainer->registerCallback(function (object $room) { + /** @var Room|MockObject $room */ + $room->expects($this->once()) + ->method('deleteRoom'); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals($expectedOutput, $tester->getDisplay()); + } + + public function invalidProvider(): array { + return [ + [ + [ + 'name' => '', + ], + "Invalid room name.\n", + ], + [ + [ + 'name' => ' ', + ], + "Invalid room name.\n", + ], + [ + [ + 'name' => str_repeat('x', 256), + ], + "Invalid room name.\n", + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--password' => 'my-secret-password', + ], + "Unable to add password protection to private room.\n", + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--user' => ['user1','invalid'], + ], + "User 'invalid' not found.\n", + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--group' => ['group1','invalid'], + ], + "Group 'invalid' not found.\n", + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--user' => ['user1'], + '--moderator' => ['user2'], + ], + "User 'user2' is no participant.\n", + ], + [ + [ + 'name' => 'PHPUnit Test Room', + '--user' => ['user1'], + '--owner' => 'user2', + ], + "User 'user2' is no participant.\n", + ], + ]; + } +} diff --git a/tests/php/Command/Room/DeleteTest.php b/tests/php/Command/Room/DeleteTest.php new file mode 100644 index 000000000..1d546d313 --- /dev/null +++ b/tests/php/Command/Room/DeleteTest.php @@ -0,0 +1,145 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2020 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\Talk\Tests\php\Command\Room; + +use OCA\Talk\Command\Room\Delete; +use OCA\Talk\Exceptions\RoomNotFoundException; +use OCA\Talk\Manager; +use OCA\Talk\Room; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException; +use Symfony\Component\Console\Tester\CommandTester; +use Test\TestCase; + +class DeleteTest extends TestCase { + use TRoomCommandTest; + + /** @var Delete */ + private $command; + + /** @var Manager|MockObject */ + private $manager; + + /** @var RoomMockContainer */ + private $roomMockContainer; + + public function setUp(): void { + parent::setUp(); + + $this->manager = $this->createMock(Manager::class); + $this->command = new Delete($this->manager); + + $this->roomMockContainer = new RoomMockContainer($this); + } + + public function testMissingArguments(): void { + $this->manager->expects($this->never()) + ->method('getRoomByToken'); + + $this->expectException(ConsoleRuntimeException::class); + $this->expectExceptionMessage('Not enough arguments (missing: "token").'); + + $tester = new CommandTester($this->command); + $tester->execute([]); + } + + /** + * @dataProvider validProvider + */ + public function testValid(array $input, array $initialRoomData): void { + $this->manager->expects($this->once()) + ->method('getRoomByToken') + ->willReturnCallback(function (string $token) use ($initialRoomData): Room { + if ($token !== $initialRoomData['token']) { + throw new RoomNotFoundException(); + } + + return $this->roomMockContainer->create($initialRoomData); + }); + + $this->roomMockContainer->registerCallback(function (object $room) { + /** @var Room|MockObject $room */ + $room->expects($this->once()) + ->method('deleteRoom'); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals("Room successfully deleted.\n", $tester->getDisplay()); + } + + public function validProvider(): array { + return [ + [ + [ + 'token' => '__test-room', + ], + RoomMockContainer::prepareRoomData([]), + ], + ]; + } + + /** + * @dataProvider invalidProvider + */ + public function testInvalid(array $input, string $expectedOutput, array $initialRoomData): void { + $this->manager->expects($this->once()) + ->method('getRoomByToken') + ->willReturnCallback(function (string $token) use ($initialRoomData): Room { + if ($token !== $initialRoomData['token']) { + throw new RoomNotFoundException(); + } + + return $this->roomMockContainer->create($initialRoomData); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals($expectedOutput, $tester->getDisplay()); + } + + public function invalidProvider(): array { + return [ + [ + [ + 'token' => '__test-invalid', + ], + "Room not found.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + ], + "Room is no group call.\n", + RoomMockContainer::prepareRoomData([ + 'type' => Room::ONE_TO_ONE_CALL, + ]), + ], + ]; + } +} diff --git a/tests/php/Command/Room/DemoteTest.php b/tests/php/Command/Room/DemoteTest.php new file mode 100644 index 000000000..33eef4e31 --- /dev/null +++ b/tests/php/Command/Room/DemoteTest.php @@ -0,0 +1,246 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2020 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\Talk\Tests\php\Command\Room; + +use OCA\Talk\Command\Room\Demote; +use OCA\Talk\Exceptions\RoomNotFoundException; +use OCA\Talk\Manager; +use OCA\Talk\Participant; +use OCA\Talk\Room; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException; +use Symfony\Component\Console\Tester\CommandTester; +use Test\TestCase; + +class DemoteTest extends TestCase { + use TRoomCommandTest; + + /** @var Demote */ + private $command; + + /** @var Manager|MockObject */ + private $manager; + + /** @var RoomMockContainer */ + private $roomMockContainer; + + public function setUp(): void { + parent::setUp(); + + $this->manager = $this->createMock(Manager::class); + $this->command = new Demote($this->manager); + + $this->roomMockContainer = new RoomMockContainer($this); + + $this->registerUserManagerMock(); + $this->registerGroupManagerMock(); + + $this->createTestUserMocks(); + $this->createTestGroupMocks(); + } + + public function testMissingArguments(): void { + $this->manager->expects($this->never()) + ->method('getRoomByToken'); + + $this->expectException(ConsoleRuntimeException::class); + $this->expectExceptionMessage('Not enough arguments (missing: "token, participant").'); + + $tester = new CommandTester($this->command); + $tester->execute([]); + } + + public function testMissingArgumentParticipant(): void { + $this->manager->expects($this->never()) + ->method('getRoomByToken'); + + $this->expectException(ConsoleRuntimeException::class); + $this->expectExceptionMessage('Not enough arguments (missing: "participant").'); + + $tester = new CommandTester($this->command); + $tester->execute([ + 'token' => '__test-room', + ]); + } + + /** + * @dataProvider validProvider + */ + public function testValid(array $input, array $expectedRoomData, array $initialRoomData): void { + $this->manager->expects($this->once()) + ->method('getRoomByToken') + ->willReturnCallback(function (string $token) use ($initialRoomData): Room { + if ($token !== $initialRoomData['token']) { + throw new RoomNotFoundException(); + } + + return $this->roomMockContainer->create($initialRoomData); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals("Participants successfully demoted to regular users.\n", $tester->getDisplay()); + + $this->assertEquals($expectedRoomData, $this->roomMockContainer->getRoomData()); + } + + public function validProvider(): array { + return [ + [ + [ + 'token' => '__test-room', + 'participant' => ['user1'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::MODERATOR], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'token' => '__test-room', + 'participant' => ['user1', 'user2'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::MODERATOR], + ['userId' => 'user2', 'participantType' => Participant::MODERATOR], + ], + ]), + ], + [ + [ + 'token' => '__test-room', + 'participant' => ['user1'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::OWNER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::OWNER], + ], + ]), + ], + [ + [ + 'token' => '__test-room', + 'participant' => ['user1'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ], + ]), + ], + ]; + } + + /** + * @dataProvider invalidProvider + */ + public function testInvalid(array $input, string $expectedOutput, array $initialRoomData): void { + $this->manager->expects($this->once()) + ->method('getRoomByToken') + ->willReturnCallback(function (string $token) use ($initialRoomData): Room { + if ($token !== $initialRoomData['token']) { + throw new RoomNotFoundException(); + } + + return $this->roomMockContainer->create($initialRoomData); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals($expectedOutput, $tester->getDisplay()); + } + + public function invalidProvider(): array { + return [ + [ + [ + 'token' => '__test-invalid', + 'participant' => [''], + ], + "Room not found.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + 'participant' => [''], + ], + "Room is no group call.\n", + RoomMockContainer::prepareRoomData([ + 'type' => Room::ONE_TO_ONE_CALL, + ]), + ], + [ + [ + 'token' => '__test-room', + 'participant' => ['user1','invalid'] + ], + "User 'user1' is no participant.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + 'participant' => ['user1','invalid'] + ], + "User 'invalid' is no participant.\n", + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + ]; + } +} diff --git a/tests/php/Command/Room/PromoteTest.php b/tests/php/Command/Room/PromoteTest.php new file mode 100644 index 000000000..49b8913f7 --- /dev/null +++ b/tests/php/Command/Room/PromoteTest.php @@ -0,0 +1,230 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2020 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\Talk\Tests\php\Command\Room; + +use OCA\Talk\Command\Room\Promote; +use OCA\Talk\Exceptions\RoomNotFoundException; +use OCA\Talk\Manager; +use OCA\Talk\Participant; +use OCA\Talk\Room; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException; +use Symfony\Component\Console\Tester\CommandTester; +use Test\TestCase; + +class PromoteTest extends TestCase { + use TRoomCommandTest; + + /** @var Promote */ + private $command; + + /** @var Manager|MockObject */ + private $manager; + + /** @var RoomMockContainer */ + private $roomMockContainer; + + public function setUp(): void { + parent::setUp(); + + $this->manager = $this->createMock(Manager::class); + $this->command = new Promote($this->manager); + + $this->roomMockContainer = new RoomMockContainer($this); + + $this->registerUserManagerMock(); + $this->registerGroupManagerMock(); + + $this->createTestUserMocks(); + $this->createTestGroupMocks(); + } + + public function testMissingArguments(): void { + $this->manager->expects($this->never()) + ->method('getRoomByToken'); + + $this->expectException(ConsoleRuntimeException::class); + $this->expectExceptionMessage('Not enough arguments (missing: "token, participant").'); + + $tester = new CommandTester($this->command); + $tester->execute([]); + } + + public function testMissingArgumentParticipant(): void { + $this->manager->expects($this->never()) + ->method('getRoomByToken'); + + $this->expectException(ConsoleRuntimeException::class); + $this->expectExceptionMessage('Not enough arguments (missing: "participant").'); + + $tester = new CommandTester($this->command); + $tester->execute([ + 'token' => '__test-room', + ]); + } + + /** + * @dataProvider validProvider + */ + public function testValid(array $input, array $expectedRoomData, array $initialRoomData): void { + $this->manager->expects($this->once()) + ->method('getRoomByToken') + ->willReturnCallback(function (string $token) use ($initialRoomData): Room { + if ($token !== $initialRoomData['token']) { + throw new RoomNotFoundException(); + } + + return $this->roomMockContainer->create($initialRoomData); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals("Participants successfully promoted to moderators.\n", $tester->getDisplay()); + + $this->assertEquals($expectedRoomData, $this->roomMockContainer->getRoomData()); + } + + public function validProvider(): array { + return [ + [ + [ + 'token' => '__test-room', + 'participant' => ['user1'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::MODERATOR], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'token' => '__test-room', + 'participant' => ['user1', 'user2'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::MODERATOR], + ['userId' => 'user2', 'participantType' => Participant::MODERATOR], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'token' => '__test-room', + 'participant' => ['user1'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::OWNER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::OWNER], + ], + ]), + ], + ]; + } + + /** + * @dataProvider invalidProvider + */ + public function testInvalid(array $input, string $expectedOutput, array $initialRoomData): void { + $this->manager->expects($this->once()) + ->method('getRoomByToken') + ->willReturnCallback(function (string $token) use ($initialRoomData): Room { + if ($token !== $initialRoomData['token']) { + throw new RoomNotFoundException(); + } + + return $this->roomMockContainer->create($initialRoomData); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals($expectedOutput, $tester->getDisplay()); + } + + public function invalidProvider(): array { + return [ + [ + [ + 'token' => '__test-invalid', + 'participant' => [''], + ], + "Room not found.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + 'participant' => [''], + ], + "Room is no group call.\n", + RoomMockContainer::prepareRoomData([ + 'type' => Room::ONE_TO_ONE_CALL, + ]), + ], + [ + [ + 'token' => '__test-room', + 'participant' => ['user1','invalid'] + ], + "User 'user1' is no participant.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + 'participant' => ['user1','invalid'] + ], + "User 'invalid' is no participant.\n", + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + ]; + } +} diff --git a/tests/php/Command/Room/RemoveTest.php b/tests/php/Command/Room/RemoveTest.php new file mode 100644 index 000000000..5b9580508 --- /dev/null +++ b/tests/php/Command/Room/RemoveTest.php @@ -0,0 +1,210 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2020 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\Talk\Tests\php\Command\Room; + +use OCA\Talk\Command\Room\Remove; +use OCA\Talk\Exceptions\RoomNotFoundException; +use OCA\Talk\Manager; +use OCA\Talk\Participant; +use OCA\Talk\Room; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException; +use Symfony\Component\Console\Tester\CommandTester; +use Test\TestCase; + +class RemoveTest extends TestCase { + use TRoomCommandTest; + + /** @var Remove */ + private $command; + + /** @var Manager|MockObject */ + private $manager; + + /** @var RoomMockContainer */ + private $roomMockContainer; + + public function setUp(): void { + parent::setUp(); + + $this->manager = $this->createMock(Manager::class); + $this->command = new Remove($this->manager); + + $this->roomMockContainer = new RoomMockContainer($this); + + $this->registerUserManagerMock(); + $this->registerGroupManagerMock(); + + $this->createTestUserMocks(); + $this->createTestGroupMocks(); + } + + public function testMissingArguments(): void { + $this->manager->expects($this->never()) + ->method('getRoomByToken'); + + $this->expectException(ConsoleRuntimeException::class); + $this->expectExceptionMessage('Not enough arguments (missing: "token, user").'); + + $tester = new CommandTester($this->command); + $tester->execute([]); + } + + public function testMissingArgumentUser(): void { + $this->manager->expects($this->never()) + ->method('getRoomByToken'); + + $this->expectException(ConsoleRuntimeException::class); + $this->expectExceptionMessage('Not enough arguments (missing: "user").'); + + $tester = new CommandTester($this->command); + $tester->execute([ + 'token' => '__test-room', + ]); + } + + /** + * @dataProvider validProvider + */ + public function testValid(array $input, array $expectedRoomData, array $initialRoomData): void { + $this->manager->expects($this->once()) + ->method('getRoomByToken') + ->willReturnCallback(function (string $token) use ($initialRoomData): Room { + if ($token !== $initialRoomData['token']) { + throw new RoomNotFoundException(); + } + + return $this->roomMockContainer->create($initialRoomData); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals("Users successfully removed from room.\n", $tester->getDisplay()); + + $this->assertEquals($expectedRoomData, $this->roomMockContainer->getRoomData()); + } + + public function validProvider(): array { + return [ + [ + [ + 'token' => '__test-room', + 'user' => ['user1'], + ], + RoomMockContainer::prepareRoomData([]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'token' => '__test-room', + 'user' => ['user1', 'user2'], + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user3', 'participantType' => Participant::USER], + ['userId' => 'user4', 'participantType' => Participant::MODERATOR], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ['userId' => 'user3', 'participantType' => Participant::USER], + ['userId' => 'user4', 'participantType' => Participant::MODERATOR], + ], + ]), + ], + ]; + } + + /** + * @dataProvider invalidProvider + */ + public function testInvalid(array $input, string $expectedOutput, array $initialRoomData): void { + $this->manager->expects($this->once()) + ->method('getRoomByToken') + ->willReturnCallback(function (string $token) use ($initialRoomData): Room { + if ($token !== $initialRoomData['token']) { + throw new RoomNotFoundException(); + } + + return $this->roomMockContainer->create($initialRoomData); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals($expectedOutput, $tester->getDisplay()); + } + + public function invalidProvider(): array { + return [ + [ + [ + 'token' => '__test-invalid', + 'user' => [''], + ], + "Room not found.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + 'user' => [''], + ], + "Room is no group call.\n", + RoomMockContainer::prepareRoomData([ + 'type' => Room::ONE_TO_ONE_CALL, + ]), + ], + [ + [ + 'token' => '__test-room', + 'user' => ['user1','invalid'] + ], + "User 'user1' is no participant.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + 'user' => ['user1','invalid'] + ], + "User 'invalid' is no participant.\n", + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + ]; + } +} diff --git a/tests/php/Command/Room/RoomMockContainer.php b/tests/php/Command/Room/RoomMockContainer.php new file mode 100644 index 000000000..de7e7ef5a --- /dev/null +++ b/tests/php/Command/Room/RoomMockContainer.php @@ -0,0 +1,222 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2020 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\Talk\Tests\php\Command\Room; + +use InvalidArgumentException; +use OCA\Talk\Exceptions\ParticipantNotFoundException; +use OCA\Talk\Participant; +use OCA\Talk\Room; +use OCP\IUser; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +class RoomMockContainer +{ + /** @var TestCase */ + private $testCase; + + /** @var callable[] */ + private $callbacks = []; + + /** @var Room|null */ + private $room; + + /** @var array|null */ + private $roomData; + + /** @var Participant[] */ + private $participants = []; + + /** @var array[] */ + private $participantData = []; + + public function __construct(TestCase $testCase) + { + $this->testCase = $testCase; + } + + public function create(array $data = []): Room { + if ($this->room !== null) { + throw new InvalidArgumentException(__METHOD__ . ' must not be called multiple times.'); + } + + /** @var Room|MockObject $room */ + $room = $this->createMock(Room::class); + + $this->room = $room; + $this->roomData = self::prepareRoomData($data); + + // simple getter + foreach (['token', 'name', 'type', 'readOnly'] as $key) { + $room->method('get' . ucfirst($key)) + ->willReturnCallback(function () use ($key) { + return $this->roomData[$key]; + }); + } + + // simple setter + foreach (['name', 'type', 'readOnly', 'password'] as $key) { + $room->method('set' . ucfirst($key)) + ->willReturnCallback(function ($value) use ($key): bool { + $this->roomData[$key] = $value; + return true; + }); + } + + // password + $room->method('hasPassword') + ->willReturnCallback(function (): bool { + return $this->roomData['password'] !== ''; + }); + + $room->method('verifyPassword') + ->willReturnCallback(function (string $password): array { + return [ + 'result' => in_array($this->roomData['password'], ['', $password], true), + 'url' => '', + ]; + }); + + // participants + $room->method('getParticipants') + ->willReturnCallback(function (): array { + return $this->participants; + }); + + $room->method('getParticipant') + ->willReturnCallback(function (?string $userId): Participant { + if (in_array($userId, [null, ''], true)) { + throw new ParticipantNotFoundException('Not a user'); + } + if (!isset($this->participants[$userId])) { + throw new ParticipantNotFoundException('User is not a participant'); + } + + return $this->participants[$userId]; + }); + + $room->method('addUsers') + ->willReturnCallback(function (array ...$participants): void { + foreach ($participants as $participant) { + $userId = $participant['userId']; + $participantType = $participant['participantType'] ?? Participant::USER; + + $this->createParticipant($userId, ['participantType' => $participantType]); + } + }); + + $room->method('removeUser') + ->willReturnCallback(function (IUser $user): void { + $this->removeParticipant($user->getUID()); + }); + + $room->method('setParticipantType') + ->willReturnCallback(function (Participant $participant, int $participantType): void { + $userId = $participant->getUser(); + $this->updateParticipant($userId, ['participantType' => $participantType]); + }); + + // add participants + foreach ($this->roomData['participants'] as $participant) { + $userId = $participant['userId']; + $participantType = $participant['participantType'] ?? Participant::USER; + + $this->createParticipant($userId, ['participantType' => $participantType]); + } + + unset($this->roomData['participants']); + + // execute callbacks + foreach ($this->callbacks as $callback) { + $callback($room); + } + + return $room; + } + + protected function createParticipant(string $userId, array $data): Participant { + /** @var Participant|MockObject $participant */ + $participant = $this->createMock(Participant::class); + + $this->participants[$userId] = $participant; + $this->participantData[$userId] = ['userId' => $userId] + $data; + + $participant->method('getUser') + ->willReturnCallback(function () use ($userId): string { + return $this->participantData[$userId]['userId']; + }); + + $participant->method('getParticipantType') + ->willReturnCallback(function () use ($userId): int { + return $this->participantData[$userId]['participantType']; + }); + + return $participant; + } + + protected function updateParticipant(string $userId, array $data): void { + $this->participantData[$userId] = array_merge($this->participantData[$userId], $data); + } + + protected function removeParticipant(string $userId): void { + unset($this->participants[$userId], $this->participantData[$userId]); + } + + public function registerCallback(callable $callback): void { + $this->callbacks[] = $callback; + } + + protected function createMock(string $originalClassName): MockObject { + return $this->testCase->getMockBuilder($originalClassName) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning() + ->disallowMockingUnknownTypes() + ->disableAutoReturnValueGeneration() + ->getMock(); + } + + public function getRoom(): ?Room { + return $this->room; + } + + public function getRoomData(): ?array { + $participants = array_values($this->participantData); + return $this->roomData + ['participants' => $participants]; + } + + public static function prepareRoomData(array $data): array { + $data += [ + 'token' => '__test-room', + 'name' => 'PHPUnit Test Room', + 'type' => Room::GROUP_CALL, + 'readOnly' => Room::READ_WRITE, + 'password' => '', + 'participants' => [], + ]; + + return $data; + } +} diff --git a/tests/php/Command/Room/TRoomCommandTest.php b/tests/php/Command/Room/TRoomCommandTest.php new file mode 100644 index 000000000..790edc982 --- /dev/null +++ b/tests/php/Command/Room/TRoomCommandTest.php @@ -0,0 +1,121 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2020 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\Talk\Tests\php\Command\Room; + +use OCP\IGroup; +use OCP\IGroupManager; +use OCP\IUser; +use OCP\IUserManager; +use PHPUnit\Framework\MockObject\MockObject; + +trait TRoomCommandTest +{ + /** @var IUser[] */ + private $userMocks; + + /** @var IGroup[] */ + private $groupMocks; + + protected function registerUserManagerMock(): void { + /** @var IUserManager|MockObject $userManager */ + $userManager = $this->createMock(IUserManager::class); + + $userManager->method('get') + ->willReturnCallback([$this, 'getUserMock']); + + $this->overwriteService(IUserManager::class, $userManager); + } + + protected function createTestUserMocks(): void { + $this->createUserMock('user1'); + $this->createUserMock('user2'); + $this->createUserMock('user3'); + $this->createUserMock('user4'); + $this->createUserMock('other'); + } + + public function getUserMock(string $uid): ?IUser { + return $this->userMocks[$uid] ?? null; + } + + protected function createUserMock(string $uid): IUser { + /** @var IUser|MockObject $user */ + $user = $this->createMock(IUser::class); + + $this->userMocks[$uid] = $user; + + $user->method('getUID') + ->willReturn($uid); + + return $user; + } + + protected function registerGroupManagerMock(): void { + /** @var IGroupManager|MockObject $groupManager */ + $groupManager = $this->createMock(IGroupManager::class); + + $groupManager->method('get') + ->willReturnCallback([$this, 'getGroupMock']); + + $this->overwriteService(IGroupManager::class, $groupManager); + } + + protected function createTestGroupMocks(): void { + $this->createGroupMock('group1', ['user1', 'user2']); + $this->createGroupMock('group2', ['user2', 'user3']); + $this->createGroupMock('other', ['other']); + } + + public function getGroupMock(string $gid): ?IGroup { + return $this->groupMocks[$gid] ?? null; + } + + protected function createGroupMock(string $gid, array $userIds): IGroup { + /** @var IGroup|MockObject $group */ + $group = $this->createMock(IGroup::class); + + $this->groupMocks[$gid] = $group; + + $group->method('getGID') + ->willReturn($gid); + + $group->method('getUsers') + ->willReturnCallback(function () use ($userIds) { + return array_map([$this, 'getUserMock'], $userIds); + }); + + return $group; + } + + protected function createMock($originalClassName): MockObject { + return $this->getMockBuilder($originalClassName) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning() + ->disallowMockingUnknownTypes() + ->disableAutoReturnValueGeneration() + ->getMock(); + } +} diff --git a/tests/php/Command/Room/UpdateTest.php b/tests/php/Command/Room/UpdateTest.php new file mode 100644 index 000000000..c160901f0 --- /dev/null +++ b/tests/php/Command/Room/UpdateTest.php @@ -0,0 +1,349 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2020 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\Talk\Tests\php\Command\Room; + +use OCA\Talk\Command\Room\Update; +use OCA\Talk\Exceptions\RoomNotFoundException; +use OCA\Talk\Manager; +use OCA\Talk\Participant; +use OCA\Talk\Room; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Exception\RuntimeException as ConsoleRuntimeException; +use Symfony\Component\Console\Tester\CommandTester; +use Test\TestCase; + +class UpdateTest extends TestCase { + use TRoomCommandTest; + + /** @var Update */ + private $command; + + /** @var Manager|MockObject */ + private $manager; + + /** @var RoomMockContainer */ + private $roomMockContainer; + + public function setUp(): void { + parent::setUp(); + + $this->manager = $this->createMock(Manager::class); + $this->command = new Update($this->manager); + + $this->roomMockContainer = new RoomMockContainer($this); + + $this->registerUserManagerMock(); + $this->registerGroupManagerMock(); + + $this->createTestUserMocks(); + $this->createTestGroupMocks(); + } + + public function testMissingArguments(): void { + $this->manager->expects($this->never()) + ->method('getRoomByToken'); + + $this->expectException(ConsoleRuntimeException::class); + $this->expectExceptionMessage('Not enough arguments (missing: "token").'); + + $tester = new CommandTester($this->command); + $tester->execute([]); + } + + /** + * @dataProvider validProvider + */ + public function testValid(array $input, array $expectedRoomData, array $initialRoomData): void { + $this->manager->expects($this->once()) + ->method('getRoomByToken') + ->willReturnCallback(function (string $token) use ($initialRoomData): Room { + if ($token !== $initialRoomData['token']) { + throw new RoomNotFoundException(); + } + + return $this->roomMockContainer->create($initialRoomData); + }); + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals("Room successfully updated.\n", $tester->getDisplay()); + + $this->assertEquals($expectedRoomData, $this->roomMockContainer->getRoomData()); + } + + public function validProvider(): array + { + return [ + [ + [ + 'token' => '__test-room', + ], + RoomMockContainer::prepareRoomData([]), + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--name' => 'PHPUnit Test Room 2' + ], + RoomMockContainer::prepareRoomData([ + 'name' => 'PHPUnit Test Room 2', + ]), + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--public' => '1' + ], + RoomMockContainer::prepareRoomData([ + 'type' => Room::PUBLIC_CALL, + ]), + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--public' => '0' + ], + RoomMockContainer::prepareRoomData([]), + RoomMockContainer::prepareRoomData([ + 'type' => Room::PUBLIC_CALL, + ]), + ], + [ + [ + 'token' => '__test-room', + '--readonly' => '1' + ], + RoomMockContainer::prepareRoomData([ + 'readOnly' => Room::READ_ONLY, + ]), + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--readonly' => '0' + ], + RoomMockContainer::prepareRoomData([]), + RoomMockContainer::prepareRoomData([ + 'readOnly' => Room::READ_ONLY, + ]), + ], + [ + [ + 'token' => '__test-room', + '--readonly' => '1' + ], + RoomMockContainer::prepareRoomData([ + 'readOnly' => Room::READ_ONLY, + ]), + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--password' => 'my-secret-password' + ], + RoomMockContainer::prepareRoomData([ + 'type' => Room::PUBLIC_CALL, + 'password' => 'my-secret-password', + ]), + RoomMockContainer::prepareRoomData([ + 'type' => Room::PUBLIC_CALL, + ]), + ], + [ + [ + 'token' => '__test-room', + '--password' => '' + ], + RoomMockContainer::prepareRoomData([ + 'type' => Room::PUBLIC_CALL, + ]), + RoomMockContainer::prepareRoomData([ + 'type' => Room::PUBLIC_CALL, + 'password' => 'my-secret-password', + ]), + ], + [ + [ + 'token' => '__test-room', + '--owner' => 'user1' + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::OWNER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'token' => '__test-room', + '--owner' => 'user2' + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::OWNER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::OWNER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + [ + [ + 'token' => '__test-room', + '--owner' => '' + ], + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::USER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + RoomMockContainer::prepareRoomData([ + 'participants' => [ + ['userId' => 'user1', 'participantType' => Participant::OWNER], + ['userId' => 'user2', 'participantType' => Participant::USER], + ], + ]), + ], + ]; + } + + /** + * @dataProvider invalidProvider + */ + public function testInvalid(array $input, string $expectedOutput, array $initialRoomData = null): void { + if ($initialRoomData !== null) { + $this->manager->expects($this->once()) + ->method('getRoomByToken') + ->willReturnCallback(function (string $token) use ($initialRoomData): Room { + if ($token !== $initialRoomData['token']) { + throw new RoomNotFoundException(); + } + + return $this->roomMockContainer->create($initialRoomData); + }); + } else { + $this->manager->expects($this->never()) + ->method('getRoomByToken'); + } + + $tester = new CommandTester($this->command); + $tester->execute($input); + + $this->assertEquals($expectedOutput, $tester->getDisplay()); + } + + public function invalidProvider(): array { + return [ + [ + [ + 'token' => '__test-room', + '--public' => '', + ], + "Invalid value for option \"--public\" given.\n", + ], + [ + [ + 'token' => '__test-room', + '--readonly' => '', + ], + "Invalid value for option \"--readonly\" given.\n", + ], + [ + [ + 'token' => '__test-invalid', + ], + "Room not found.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + ], + "Room is no group call.\n", + RoomMockContainer::prepareRoomData([ + 'type' => Room::ONE_TO_ONE_CALL, + ]), + ], + [ + [ + 'token' => '__test-room', + '--name' => '', + ], + "Invalid room name.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--name' => ' ', + ], + "Invalid room name.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--name' => str_repeat('x', 256), + ], + "Invalid room name.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--password' => 'my-secret-password', + ], + "Unable to add password protection to private room.\n", + RoomMockContainer::prepareRoomData([]), + ], + [ + [ + 'token' => '__test-room', + '--owner' => 'invalid', + ], + "User 'invalid' is no participant.\n", + RoomMockContainer::prepareRoomData([]), + ], + ]; + } +} |