setCompanyName('Asso Test '.uniqid()); $invitation->setFirstName('Jean'); $invitation->setLastName('Dupont'); $invitation->setEmail($email ?? 'invite-'.uniqid().'@example.com'); $invitation->setOffer('basic'); $invitation->setCommissionRate(2.5); $invitation->setStatus($status); $em->persist($invitation); $em->flush(); return $invitation; } // --- viewInvitation --- public function testViewInvitationReturnsSuccess(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em); $client->request('GET', '/invitation/'.$invitation->getToken()); self::assertResponseIsSuccessful(); } public function testViewInvitationMarksAsOpened(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em); self::assertSame(OrganizerInvitation::STATUS_SENT, $invitation->getStatus()); $client->request('GET', '/invitation/'.$invitation->getToken()); $em->refresh($invitation); self::assertSame(OrganizerInvitation::STATUS_OPENED, $invitation->getStatus()); } public function testViewInvitationAlreadyOpenedStaysOpened(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_OPENED); $client->request('GET', '/invitation/'.$invitation->getToken()); self::assertResponseIsSuccessful(); $em->refresh($invitation); self::assertSame(OrganizerInvitation::STATUS_OPENED, $invitation->getStatus()); } public function testViewInvitationInvalidTokenReturns404(): void { $client = static::createClient(); $client->request('GET', '/invitation/invalid-token-that-does-not-exist'); self::assertResponseStatusCodeSame(404); } // --- respondInvitation --- public function testAcceptInvitation(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $mailer = $this->createMock(MailerService::class); $mailer->expects(self::exactly(2))->method('sendEmail'); static::getContainer()->set(MailerService::class, $mailer); $invitation = $this->createInvitation($em); $client->request('POST', '/invitation/'.$invitation->getToken().'/accept'); self::assertResponseIsSuccessful(); $em->refresh($invitation); self::assertSame(OrganizerInvitation::STATUS_ACCEPTED, $invitation->getStatus()); self::assertNotNull($invitation->getRespondedAt()); } public function testRefuseInvitation(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $mailer = $this->createMock(MailerService::class); $mailer->expects(self::once())->method('sendEmail'); static::getContainer()->set(MailerService::class, $mailer); $invitation = $this->createInvitation($em); $client->request('POST', '/invitation/'.$invitation->getToken().'/refuse'); self::assertResponseIsSuccessful(); $em->refresh($invitation); self::assertSame(OrganizerInvitation::STATUS_REFUSED, $invitation->getStatus()); self::assertNotNull($invitation->getRespondedAt()); } public function testAcceptOpenedInvitation(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $mailer = $this->createMock(MailerService::class); $mailer->expects(self::exactly(2))->method('sendEmail'); static::getContainer()->set(MailerService::class, $mailer); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_OPENED); $client->request('POST', '/invitation/'.$invitation->getToken().'/accept'); self::assertResponseIsSuccessful(); $em->refresh($invitation); self::assertSame(OrganizerInvitation::STATUS_ACCEPTED, $invitation->getStatus()); } public function testRespondAlreadyAcceptedReturns404(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_ACCEPTED); $client->request('POST', '/invitation/'.$invitation->getToken().'/accept'); self::assertResponseStatusCodeSame(404); } public function testRespondAlreadyRefusedReturns404(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_REFUSED); $client->request('POST', '/invitation/'.$invitation->getToken().'/refuse'); self::assertResponseStatusCodeSame(404); } public function testRespondInvalidTokenReturns404(): void { $client = static::createClient(); $client->request('POST', '/invitation/invalid-token/accept'); self::assertResponseStatusCodeSame(404); } // --- invitationRegister (GET) --- public function testRegisterPageReturnsSuccess(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_ACCEPTED); $client->request('GET', '/invitation/'.$invitation->getToken().'/inscription'); self::assertResponseIsSuccessful(); } public function testRegisterPageNonAcceptedReturns404(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_SENT); $client->request('GET', '/invitation/'.$invitation->getToken().'/inscription'); self::assertResponseStatusCodeSame(404); } public function testRegisterPageRefusedReturns404(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_REFUSED); $client->request('GET', '/invitation/'.$invitation->getToken().'/inscription'); self::assertResponseStatusCodeSame(404); } public function testRegisterPageRedirectsIfEmailAlreadyExists(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $email = 'existing-'.uniqid().'@example.com'; $existingUser = new User(); $existingUser->setEmail($email); $existingUser->setFirstName('Existing'); $existingUser->setLastName('User'); $existingUser->setPassword('hashed'); $em->persist($existingUser); $em->flush(); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_ACCEPTED, $email); $client->request('GET', '/invitation/'.$invitation->getToken().'/inscription'); self::assertResponseRedirects('/connexion'); } // --- invitationRegister (POST) --- public function testRegisterCreatesUserAndRedirects(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_ACCEPTED); $client->request('POST', '/invitation/'.$invitation->getToken().'/inscription', [ 'first_name' => 'Pierre', 'last_name' => 'Martin', 'password' => 'securepassword123', 'siret' => '12345678901234', 'address' => '10 rue de la Paix', 'postal_code' => '75002', 'city' => 'Paris', 'phone' => '0612345678', ]); self::assertResponseRedirects('/mon-compte'); $user = $em->getRepository(User::class)->findOneBy(['email' => $invitation->getEmail()]); self::assertNotNull($user); self::assertSame('Pierre', $user->getFirstName()); self::assertSame('Martin', $user->getLastName()); self::assertSame($invitation->getCompanyName(), $user->getCompanyName()); self::assertSame('basic', $user->getOffer()); self::assertSame(2.5, $user->getCommissionRate()); self::assertTrue($user->isApproved()); self::assertTrue($user->isVerified()); self::assertContains('ROLE_ORGANIZER', $user->getRoles()); self::assertSame('12345678901234', $user->getSiret()); self::assertSame('Paris', $user->getCity()); } public function testRegisterAutoLoginsUser(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_ACCEPTED); $client->request('POST', '/invitation/'.$invitation->getToken().'/inscription', [ 'first_name' => 'Auto', 'last_name' => 'Login', 'password' => 'securepassword123', ]); self::assertResponseRedirects('/mon-compte'); $client->followRedirect(); self::assertResponseIsSuccessful(); } public function testRegisterWithEmptyFieldsRedirects(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_ACCEPTED); $client->request('POST', '/invitation/'.$invitation->getToken().'/inscription', [ 'first_name' => '', 'last_name' => '', 'password' => '', ]); self::assertResponseRedirects('/invitation/'.$invitation->getToken().'/inscription'); } public function testRegisterWithMissingPasswordRedirects(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_ACCEPTED); $client->request('POST', '/invitation/'.$invitation->getToken().'/inscription', [ 'first_name' => 'Test', 'last_name' => 'User', 'password' => '', ]); self::assertResponseRedirects('/invitation/'.$invitation->getToken().'/inscription'); $user = $em->getRepository(User::class)->findOneBy(['email' => $invitation->getEmail()]); self::assertNull($user); } public function testRegisterWithOptionalFieldsEmpty(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_ACCEPTED); $client->request('POST', '/invitation/'.$invitation->getToken().'/inscription', [ 'first_name' => 'Minimal', 'last_name' => 'User', 'password' => 'securepassword123', 'siret' => '', 'address' => '', 'postal_code' => '', 'city' => '', 'phone' => '', ]); self::assertResponseRedirects('/mon-compte'); $user = $em->getRepository(User::class)->findOneBy(['email' => $invitation->getEmail()]); self::assertNotNull($user); self::assertNull($user->getSiret()); self::assertNull($user->getCity()); self::assertNull($user->getPhone()); } public function testRegisterPostWithDuplicateEmailRedirects(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $email = 'dup-'.uniqid().'@example.com'; $existingUser = new User(); $existingUser->setEmail($email); $existingUser->setFirstName('Existing'); $existingUser->setLastName('User'); $existingUser->setPassword('hashed'); $em->persist($existingUser); $em->flush(); $invitation = $this->createInvitation($em, OrganizerInvitation::STATUS_ACCEPTED, $email); $client->request('POST', '/invitation/'.$invitation->getToken().'/inscription', [ 'first_name' => 'Pierre', 'last_name' => 'Martin', 'password' => 'securepassword123', ]); self::assertResponseRedirects('/connexion'); } // --- Full flow --- public function testFullInvitationFlow(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $mailer = $this->createMock(MailerService::class); static::getContainer()->set(MailerService::class, $mailer); $invitation = $this->createInvitation($em); $token = $invitation->getToken(); $email = $invitation->getEmail(); $companyName = $invitation->getCompanyName(); // Step 1: View invitation (status: sent → opened) $client->request('GET', '/invitation/'.$token); self::assertResponseIsSuccessful(); // Step 2: Accept invitation (status: opened → accepted) $client->request('POST', '/invitation/'.$token.'/accept'); self::assertResponseIsSuccessful(); // Step 3: View registration form $client->request('GET', '/invitation/'.$token.'/inscription'); self::assertResponseIsSuccessful(); // Step 4: Submit registration $client->request('POST', '/invitation/'.$token.'/inscription', [ 'first_name' => 'Jean', 'last_name' => 'Dupont', 'password' => 'motdepasse123', ]); self::assertResponseRedirects('/mon-compte'); // Verify user was created correctly $freshEm = static::getContainer()->get(EntityManagerInterface::class); $user = $freshEm->getRepository(User::class)->findOneBy(['email' => $email]); self::assertNotNull($user); self::assertTrue($user->isApproved()); self::assertTrue($user->isVerified()); self::assertContains('ROLE_ORGANIZER', $user->getRoles()); self::assertSame($companyName, $user->getCompanyName()); } }