From fee0b8f778e056a14aa920b87c8debc413a1a892 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 28 Nov 2024 08:40:40 +0100 Subject: [PATCH] test(invites): Add unit tests for invite API Signed-off-by: Joas Schilling --- lib/Controller/RoomController.php | 2 +- lib/Exceptions/GuestImportException.php | 2 +- lib/GuestManager.php | 7 +- tests/php/GuestManagerTest.php | 148 ++++++++++++++++++ .../php/data/import-valid-email-and-name.csv | 2 + ...mport-valid-filter-duplicates-by-email.csv | 5 + tests/php/data/import-valid-only-email.csv | 2 + 7 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 tests/php/GuestManagerTest.php create mode 100644 tests/php/data/import-valid-email-and-name.csv create mode 100644 tests/php/data/import-valid-filter-duplicates-by-email.csv create mode 100644 tests/php/data/import-valid-only-email.csv diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index 6c4384bdc04..aabffcba8d4 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -2485,7 +2485,7 @@ public function importEmailsAsParticipants(bool $testRun = false): DataResponse } try { - $data = $this->guestManager->importEmails($this->room, $file, $testRun); + $data = $this->guestManager->importEmails($this->room, $file['tmp_name'], $testRun); return new DataResponse($data); } catch (GuestImportException $e) { return new DataResponse($e->getData(), Http::STATUS_BAD_REQUEST); diff --git a/lib/Exceptions/GuestImportException.php b/lib/Exceptions/GuestImportException.php index e5c780c05a6..a274efc9bb6 100644 --- a/lib/Exceptions/GuestImportException.php +++ b/lib/Exceptions/GuestImportException.php @@ -28,7 +28,7 @@ public function __construct( protected readonly ?int $invites = null, protected readonly ?int $duplicates = null, ) { - parent::__construct(); + parent::__construct($reason); } /** diff --git a/lib/GuestManager.php b/lib/GuestManager.php index 527fd15570c..4446affdd16 100644 --- a/lib/GuestManager.php +++ b/lib/GuestManager.php @@ -84,7 +84,7 @@ public function validateMailAddress(string $email): bool { * @return array{invites: non-negative-int, duplicates: non-negative-int, invalid?: non-negative-int, invalidLines?: list, type?: int<-1, 6>} * @throws GuestImportException */ - public function importEmails(Room $room, $file, bool $testRun): array { + public function importEmails(Room $room, string $filePath, bool $testRun): array { if ($room->getType() === Room::TYPE_ONE_TO_ONE || $room->getType() === Room::TYPE_ONE_TO_ONE_FORMER || $room->getType() === Room::TYPE_NOTE_TO_SELF @@ -93,7 +93,7 @@ public function importEmails(Room $room, $file, bool $testRun): array { throw new GuestImportException(GuestImportException::REASON_ROOM); } - $content = fopen($file['tmp_name'], 'rb'); + $content = fopen($filePath, 'rb'); $details = fgetcsv($content, escape: ''); $emailKey = $nameKey = null; @@ -119,7 +119,8 @@ public function importEmails(Room $room, $file, bool $testRun): array { $participants = $this->participantService->getParticipantsByActorType($room, Attendee::ACTOR_EMAILS); $alreadyInvitedEmails = array_flip(array_map(static fn (Participant $participant): string => $participant->getAttendee()->getInvitedCloudId(), $participants)); - $line = $duplicates = 0; + $line = 1; + $duplicates = 0; $emailsToAdd = $invalidLines = []; while ($details = fgetcsv($content, escape: '')) { $line++; diff --git a/tests/php/GuestManagerTest.php b/tests/php/GuestManagerTest.php new file mode 100644 index 00000000000..9285353fa41 --- /dev/null +++ b/tests/php/GuestManagerTest.php @@ -0,0 +1,148 @@ +talkConfig = $this->createMock(Config::class); + $this->mailer = $this->createMock(IMailer::class); + $this->defaults = $this->createMock(Defaults::class); + $this->userSession = $this->createMock(IUserSession::class); + $this->participantService = $this->createMock(ParticipantService::class); + $this->pollService = $this->createMock(PollService::class); + $this->roomService = $this->createMock(RoomService::class); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->l = $this->createMock(IL10N::class); + $this->dispatcher = $this->createMock(IEventDispatcher::class); + $this->logger = $this->createMock(LoggerInterface::class); + } + + public function getGuestManager(array $methods = []): GuestManager|MockObject { + if (!empty($methods)) { + return $this->getMockBuilder(GuestManager::class) + ->setConstructorArgs([ + $this->talkConfig, + $this->mailer, + $this->defaults, + $this->userSession, + $this->participantService, + $this->pollService, + $this->roomService, + $this->urlGenerator, + $this->l, + $this->dispatcher, + $this->logger, + ]) + ->onlyMethods($methods) + ->getMock(); + } + + $this->guestManager = new GuestManager( + $this->talkConfig, + $this->mailer, + $this->defaults, + $this->userSession, + $this->participantService, + $this->pollService, + $this->roomService, + $this->urlGenerator, + $this->l, + $this->dispatcher, + $this->logger, + ); + } + + public static function dataImportEmails(): array { + return [ + [ + 'import-valid-only-email.csv', + 1, + 0, + [["valid@example.tld", null]], + ], + [ + 'import-valid-email-and-name.csv', + 1, + 0, + [["valid@example.tld", "Name"]], + ], + [ + 'import-valid-filter-duplicates-by-email.csv', + 2, + 1, + [["valid-1@example.tld", "Valid 1"], ["valid-2@example.tld",null]], + GuestImportException::REASON_ROWS, + [4], + ], + ]; + } + + /** + * @dataProvider dataImportEmails + */ + public function testImportEmails(string $fileName, int $invites, int $duplicates, array $invited, ?string $reason = null, array $invalidLines = []): void { + $this->mailer->method('validateMailAddress') + ->willReturnCallback(static fn (string $email): bool => str_starts_with($email, 'valid')); + + $actualInvites = []; + $this->participantService->method('inviteEmailAddress') + ->willReturnCallback(function ($room, $actorId, string $email, ?string $name) use (&$actualInvites): Participant { + $actualInvites[] = [$email, $name]; + return $this->createMock(Participant::class); + }); + + $room = $this->createMock(Room::class); + + try { + $guestManager = $this->getGuestManager(['sendEmailInvitation']); + $data = $guestManager->importEmails($room, __DIR__ . '/data/' . $fileName, false); + } catch (GuestImportException $e) { + if ($reason === null) { + throw $e; + } + + $data = $e->getData(); + $this->assertSame($invalidLines, $data['invalidLines']); + } + + $this->assertSame($invited, $actualInvites); + $this->assertSame($invites, $data['invites'], 'Invites count mismatch'); + $this->assertSame($duplicates, $data['duplicates'], 'Duplicates count mismatch'); + } +} diff --git a/tests/php/data/import-valid-email-and-name.csv b/tests/php/data/import-valid-email-and-name.csv new file mode 100644 index 00000000000..882ba909cda --- /dev/null +++ b/tests/php/data/import-valid-email-and-name.csv @@ -0,0 +1,2 @@ +"name","email" +"Name","valid@example.tld" diff --git a/tests/php/data/import-valid-filter-duplicates-by-email.csv b/tests/php/data/import-valid-filter-duplicates-by-email.csv new file mode 100644 index 00000000000..2178633eac1 --- /dev/null +++ b/tests/php/data/import-valid-filter-duplicates-by-email.csv @@ -0,0 +1,5 @@ +"email","name" +"valid-1@example.tld","Valid 1" +"valid-2@example.tld","valid-2@example.tld" +"invalid","Valid 2" +"valid-1@example.tld","Valid 1 again" diff --git a/tests/php/data/import-valid-only-email.csv b/tests/php/data/import-valid-only-email.csv new file mode 100644 index 00000000000..339e4f8c07a --- /dev/null +++ b/tests/php/data/import-valid-only-email.csv @@ -0,0 +1,2 @@ +"email" +"valid@example.tld"