Files
e-ticket/tests/Controller/AccountControllerTest.php
Serreau Jovann 1f5a9105fa Fix ESLint globals, parseFloat to Number.parseFloat, label for, add AccountController coverage tests
- Add setTimeout, globalThis, navigator, fetch, caches etc to ESLint globals
- Use Number.parseFloat in event-map.js
- Add for attribute to admin events search label
- Add tests: events search, toggle/delete access denied for other user

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 21:25:53 +01:00

797 lines
26 KiB
PHP

<?php
namespace App\Tests\Controller;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class AccountControllerTest extends WebTestCase
{
public function testAccountRedirectsWhenNotAuthenticated(): void
{
$client = static::createClient();
$client->request('GET', '/mon-compte');
self::assertResponseRedirects();
}
public function testAccountReturnsSuccessWhenAuthenticated(): void
{
$client = static::createClient();
$user = $this->createUser();
$client->loginUser($user);
$client->request('GET', '/mon-compte');
self::assertResponseIsSuccessful();
}
public function testAccountTicketsTab(): void
{
$client = static::createClient();
$user = $this->createUser();
$client->loginUser($user);
$client->request('GET', '/mon-compte?tab=tickets');
self::assertResponseIsSuccessful();
}
public function testAccountPurchasesTab(): void
{
$client = static::createClient();
$user = $this->createUser();
$client->loginUser($user);
$client->request('GET', '/mon-compte?tab=purchases');
self::assertResponseIsSuccessful();
}
public function testAccountInvoicesTab(): void
{
$client = static::createClient();
$user = $this->createUser();
$client->loginUser($user);
$client->request('GET', '/mon-compte?tab=invoices');
self::assertResponseIsSuccessful();
}
public function testAccountSettingsTab(): void
{
$client = static::createClient();
$user = $this->createUser();
$client->loginUser($user);
$client->request('GET', '/mon-compte?tab=settings');
self::assertResponseIsSuccessful();
}
public function testAccountSettingsSubmit(): void
{
$client = static::createClient();
$user = $this->createUser();
$client->loginUser($user);
$client->request('POST', '/mon-compte/parametres', [
'first_name' => 'Updated',
'last_name' => 'Name',
'email' => $user->getEmail(),
'phone' => '0699887766',
'address' => '1 rue Test',
'postal_code' => '75001',
'city' => 'Paris',
]);
self::assertResponseRedirects('/mon-compte?tab=settings');
}
public function testOrganizerEventsTab(): void
{
$client = static::createClient();
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$client->loginUser($user);
$client->request('GET', '/mon-compte?tab=events');
self::assertResponseIsSuccessful();
}
public function testOrganizerSubaccountsTab(): void
{
$client = static::createClient();
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$client->loginUser($user);
$client->request('GET', '/mon-compte?tab=subaccounts');
self::assertResponseIsSuccessful();
}
public function testOrganizerPayoutsTab(): void
{
$client = static::createClient();
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$client->loginUser($user);
$client->request('GET', '/mon-compte?tab=payouts');
self::assertResponseIsSuccessful();
}
public function testOrganizerSettingsDisablesNameFields(): void
{
$client = static::createClient();
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$client->loginUser($user);
$client->request('POST', '/mon-compte/parametres', [
'email' => $user->getEmail(),
'phone' => '0699887766',
]);
self::assertResponseRedirects('/mon-compte?tab=settings');
}
public function testOrganizerNotApprovedShowsBlockingMessage(): void
{
$client = static::createClient();
$user = $this->createUser(['ROLE_ORGANIZER'], false);
$client->loginUser($user);
$client->request('GET', '/mon-compte');
self::assertResponseIsSuccessful();
self::assertSelectorTextContains('body', 'en cours de validation');
}
public function testOrganizerDefaultTabIsEvents(): void
{
$client = static::createClient();
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$client->loginUser($user);
$client->request('GET', '/mon-compte');
self::assertResponseIsSuccessful();
}
public function testStripeConnectRedirectsForNonOrganizer(): void
{
$client = static::createClient();
$user = $this->createUser();
$client->loginUser($user);
$client->request('POST', '/mon-compte/stripe-connect');
self::assertResponseRedirects('/mon-compte');
}
public function testOrganizerWithoutStripeShowsSetupMessage(): void
{
$client = static::createClient();
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$client->loginUser($user);
$crawler = $client->request('GET', '/mon-compte');
self::assertResponseIsSuccessful();
self::assertSelectorTextContains('body', 'Configuration Stripe requise');
}
public function testOrganizerWithStripePendingShowsMessage(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$user->setStripeAccountId('acct_pending');
$em->flush();
$client->loginUser($user);
$crawler = $client->request('GET', '/mon-compte');
self::assertResponseIsSuccessful();
self::assertSelectorTextContains('body', 'en cours de verification');
}
public function testOrganizerWithStripeActiveShowsSuccess(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$user->setStripeAccountId('acct_active');
$user->setStripeChargesEnabled(true);
$user->setStripePayoutsEnabled(true);
$em->flush();
$client->loginUser($user);
$crawler = $client->request('GET', '/mon-compte');
self::assertResponseIsSuccessful();
self::assertSelectorTextContains('body', 'Stripe Connect actif');
}
public function testStripeConnectReturn(): void
{
$client = static::createClient();
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$client->loginUser($user);
$client->request('GET', '/stripe/connect/return');
self::assertResponseRedirects('/mon-compte');
}
public function testStripeConnectRefresh(): void
{
$client = static::createClient();
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$client->loginUser($user);
$client->request('GET', '/stripe/connect/refresh');
self::assertResponseRedirects('/mon-compte/stripe-connect');
}
public function testStripeCancelResetsAccount(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$user->setStripeAccountId('acct_cancel');
$em->flush();
$client->loginUser($user);
$client->request('POST', '/mon-compte/stripe-cancel');
self::assertResponseRedirects('/mon-compte');
$em->refresh($user);
self::assertNull($user->getStripeAccountId());
}
public function testCreateSubAccountDeniedForNonOrganizer(): void
{
$client = static::createClient();
$user = $this->createUser();
$client->loginUser($user);
$client->request('POST', '/mon-compte/sous-compte/creer', [
'first_name' => 'Sub',
'last_name' => 'Test',
'email' => 'sub-denied-'.uniqid().'@example.com',
]);
self::assertResponseRedirects('/mon-compte');
}
public function testEditSubAccountDeniedForWrongOrganizer(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$orga1 = $this->createUser(['ROLE_ORGANIZER'], true);
$orga2 = $this->createUser(['ROLE_ORGANIZER'], true);
$sub = new User();
$sub->setEmail('sub-wrong-'.uniqid().'@example.com');
$sub->setFirstName('Sub');
$sub->setLastName('Wrong');
$sub->setPassword('$2y$13$hashed');
$sub->setParentOrganizer($orga1);
$em->persist($sub);
$em->flush();
$client->loginUser($orga2);
$client->request('GET', '/mon-compte/sous-compte/'.$sub->getId());
self::assertResponseStatusCodeSame(403);
}
public function testEditSubAccountSubmitDeniedForWrongOrganizer(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$orga1 = $this->createUser(['ROLE_ORGANIZER'], true);
$orga2 = $this->createUser(['ROLE_ORGANIZER'], true);
$sub = new User();
$sub->setEmail('sub-wrong2-'.uniqid().'@example.com');
$sub->setFirstName('Sub');
$sub->setLastName('Wrong2');
$sub->setPassword('$2y$13$hashed');
$sub->setParentOrganizer($orga1);
$em->persist($sub);
$em->flush();
$client->loginUser($orga2);
$client->request('POST', '/mon-compte/sous-compte/'.$sub->getId().'/modifier', [
'first_name' => 'Hack',
'last_name' => 'Attempt',
'email' => $sub->getEmail(),
'permissions' => ['scanner'],
]);
self::assertResponseStatusCodeSame(403);
}
public function testDeleteSubAccountDeniedForWrongOrganizer(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$orga1 = $this->createUser(['ROLE_ORGANIZER'], true);
$orga2 = $this->createUser(['ROLE_ORGANIZER'], true);
$sub = new User();
$sub->setEmail('sub-wrong3-'.uniqid().'@example.com');
$sub->setFirstName('Sub');
$sub->setLastName('Wrong3');
$sub->setPassword('$2y$13$hashed');
$sub->setParentOrganizer($orga1);
$em->persist($sub);
$em->flush();
$client->loginUser($orga2);
$client->request('POST', '/mon-compte/sous-compte/'.$sub->getId().'/supprimer');
self::assertResponseStatusCodeSame(403);
}
public function testCreateSubAccount(): void
{
$client = static::createClient();
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$mailer = $this->createMock(\App\Service\MailerService::class);
$mailer->expects(self::once())->method('sendEmail');
static::getContainer()->set(\App\Service\MailerService::class, $mailer);
$client->loginUser($user);
$client->request('POST', '/mon-compte/sous-compte/creer', [
'first_name' => 'Sub',
'last_name' => 'Account',
'email' => 'sub-'.uniqid().'@example.com',
'permissions' => ['scanner', 'events'],
]);
self::assertResponseRedirects('/mon-compte?tab=subaccounts');
}
public function testEditSubAccountPage(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$sub = new User();
$sub->setEmail('sub-edit-'.uniqid().'@example.com');
$sub->setFirstName('Sub');
$sub->setLastName('Edit');
$sub->setPassword('$2y$13$hashed');
$sub->setParentOrganizer($user);
$sub->setSubAccountPermissions(['scanner']);
$em->persist($sub);
$em->flush();
$client->loginUser($user);
$client->request('GET', '/mon-compte/sous-compte/'.$sub->getId());
self::assertResponseIsSuccessful();
}
public function testEditSubAccountSubmit(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$sub = new User();
$sub->setEmail('sub-submit-'.uniqid().'@example.com');
$sub->setFirstName('Sub');
$sub->setLastName('Submit');
$sub->setPassword('$2y$13$hashed');
$sub->setParentOrganizer($user);
$sub->setSubAccountPermissions(['scanner']);
$em->persist($sub);
$em->flush();
$client->loginUser($user);
$client->request('POST', '/mon-compte/sous-compte/'.$sub->getId().'/modifier', [
'first_name' => 'Updated',
'last_name' => 'Name',
'email' => $sub->getEmail(),
'permissions' => ['scanner', 'events', 'tickets'],
]);
self::assertResponseRedirects('/mon-compte?tab=subaccounts');
$em->refresh($sub);
self::assertSame('Updated', $sub->getFirstName());
self::assertSame(['scanner', 'events', 'tickets'], $sub->getSubAccountPermissions());
}
public function testDeleteSubAccount(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$sub = new User();
$sub->setEmail('sub-del-'.uniqid().'@example.com');
$sub->setFirstName('Sub');
$sub->setLastName('Delete');
$sub->setPassword('$2y$13$hashed');
$sub->setParentOrganizer($user);
$em->persist($sub);
$em->flush();
$subId = $sub->getId();
$client->loginUser($user);
$client->request('POST', '/mon-compte/sous-compte/'.$subId.'/supprimer');
self::assertResponseRedirects('/mon-compte?tab=subaccounts');
self::assertNull($em->getRepository(User::class)->find($subId));
}
public function testOrganizerSettingsWithLogoUpload(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$client->loginUser($user);
$logoFile = new \Symfony\Component\HttpFoundation\File\UploadedFile(
__DIR__.'/../../public/logo.png',
'logo.png',
'image/png',
null,
true,
);
$client->request('POST', '/mon-compte/parametres', [
'email' => $user->getEmail(),
'phone' => '0699887766',
], ['logo' => $logoFile]);
self::assertResponseRedirects('/mon-compte?tab=settings');
$em->refresh($user);
self::assertNotNull($user->getLogoName());
}
public function testCreateEventPageRequiresOrganizer(): void
{
$client = static::createClient();
$user = $this->createUser();
$client->loginUser($user);
$client->request('GET', '/mon-compte/evenement/creer');
self::assertResponseStatusCodeSame(403);
}
public function testCreateEventPageReturnsSuccess(): void
{
$client = static::createClient();
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$client->loginUser($user);
$client->request('GET', '/mon-compte/evenement/creer');
self::assertResponseIsSuccessful();
}
public function testCreateEventSubmit(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/creer', [
'title' => 'Convention Test',
'description' => 'Un super evenement',
'start_at' => '2026-07-01T10:00',
'end_at' => '2026-07-01T18:00',
'address' => '42 rue de Saint-Quentin',
'zipcode' => '02800',
'city' => 'Beautor',
]);
self::assertResponseRedirects('/mon-compte?tab=events');
$freshEm = static::getContainer()->get(EntityManagerInterface::class);
$event = $freshEm->getRepository(\App\Entity\Event::class)->findOneBy(['title' => 'Convention Test']);
self::assertNotNull($event);
self::assertSame('Un super evenement', $event->getDescription());
self::assertSame('Beautor', $event->getCity());
}
public function testEditEventPageReturnsSuccess(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = new \App\Entity\Event();
$event->setAccount($user);
$event->setTitle('Edit Test');
$event->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
$event->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
$event->setAddress('1 rue test');
$event->setZipcode('75001');
$event->setCity('Paris');
$em->persist($event);
$em->flush();
$client->loginUser($user);
$client->request('GET', '/mon-compte/evenement/'.$event->getId().'/modifier');
self::assertResponseIsSuccessful();
}
public function testEditEventSubmit(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = new \App\Entity\Event();
$event->setAccount($user);
$event->setTitle('Before Edit');
$event->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
$event->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
$event->setAddress('1 rue test');
$event->setZipcode('75001');
$event->setCity('Paris');
$em->persist($event);
$em->flush();
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/modifier', [
'title' => 'After Edit',
'description' => 'Nouvelle description',
'start_at' => '2026-09-01T10:00',
'end_at' => '2026-09-01T18:00',
'address' => '2 rue modif',
'zipcode' => '69001',
'city' => 'Lyon',
'is_online' => '1',
]);
self::assertResponseRedirects('/mon-compte?tab=events');
}
public function testEditEventDeniedForOtherUser(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$owner = $this->createUser(['ROLE_ORGANIZER'], true);
$other = $this->createUser(['ROLE_ORGANIZER'], true);
$event = new \App\Entity\Event();
$event->setAccount($owner);
$event->setTitle('Owner Event');
$event->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
$event->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
$event->setAddress('1 rue');
$event->setZipcode('75001');
$event->setCity('Paris');
$em->persist($event);
$em->flush();
$client->loginUser($other);
$client->request('GET', '/mon-compte/evenement/'.$event->getId().'/modifier');
self::assertResponseStatusCodeSame(403);
}
public function testDeleteEvent(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = new \App\Entity\Event();
$event->setAccount($user);
$event->setTitle('To Delete');
$event->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
$event->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
$event->setAddress('1 rue');
$event->setZipcode('75001');
$event->setCity('Paris');
$em->persist($event);
$em->flush();
$eventId = $event->getId();
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$eventId.'/supprimer');
self::assertResponseRedirects('/mon-compte?tab=events');
}
public function testToggleEventOnline(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$user->setStripeChargesEnabled(true);
$user->setStripePayoutsEnabled(true);
$em->flush();
$event = new \App\Entity\Event();
$event->setAccount($user);
$event->setTitle('Toggle Online');
$event->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
$event->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
$event->setAddress('1 rue');
$event->setZipcode('75001');
$event->setCity('Paris');
$em->persist($event);
$em->flush();
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/en-ligne');
self::assertResponseRedirects('/mon-compte/evenement/'.$event->getId().'/modifier');
}
public function testToggleEventOnlineBlockedWithoutStripe(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = new \App\Entity\Event();
$event->setAccount($user);
$event->setTitle('No Stripe');
$event->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
$event->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
$event->setAddress('1 rue');
$event->setZipcode('75001');
$event->setCity('Paris');
$em->persist($event);
$em->flush();
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/en-ligne');
self::assertResponseRedirects('/mon-compte/evenement/'.$event->getId().'/modifier');
}
public function testToggleEventSecret(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = new \App\Entity\Event();
$event->setAccount($user);
$event->setTitle('Toggle Secret');
$event->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
$event->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
$event->setAddress('1 rue');
$event->setZipcode('75001');
$event->setCity('Paris');
$em->persist($event);
$em->flush();
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/secret');
self::assertResponseRedirects('/mon-compte/evenement/'.$event->getId().'/modifier');
}
public function testEventsSearchReturnsSuccess(): void
{
$client = static::createClient();
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$client->loginUser($user);
$client->request('GET', '/mon-compte?tab=events&q=brocante');
self::assertResponseIsSuccessful();
}
public function testToggleOnlineDeniedForOtherUser(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$owner = $this->createUser(['ROLE_ORGANIZER'], true);
$other = $this->createUser(['ROLE_ORGANIZER'], true);
$event = new \App\Entity\Event();
$event->setAccount($owner);
$event->setTitle('Toggle Denied');
$event->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
$event->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
$event->setAddress('1 rue');
$event->setZipcode('75001');
$event->setCity('Paris');
$em->persist($event);
$em->flush();
$client->loginUser($other);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/en-ligne');
self::assertResponseStatusCodeSame(403);
}
public function testToggleSecretDeniedForOtherUser(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$owner = $this->createUser(['ROLE_ORGANIZER'], true);
$other = $this->createUser(['ROLE_ORGANIZER'], true);
$event = new \App\Entity\Event();
$event->setAccount($owner);
$event->setTitle('Secret Denied');
$event->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
$event->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
$event->setAddress('1 rue');
$event->setZipcode('75001');
$event->setCity('Paris');
$em->persist($event);
$em->flush();
$client->loginUser($other);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/secret');
self::assertResponseStatusCodeSame(403);
}
public function testDeleteEventDeniedForOtherUser(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$owner = $this->createUser(['ROLE_ORGANIZER'], true);
$other = $this->createUser(['ROLE_ORGANIZER'], true);
$event = new \App\Entity\Event();
$event->setAccount($owner);
$event->setTitle('Delete Denied');
$event->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
$event->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
$event->setAddress('1 rue');
$event->setZipcode('75001');
$event->setCity('Paris');
$em->persist($event);
$em->flush();
$client->loginUser($other);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/supprimer');
self::assertResponseStatusCodeSame(403);
}
/**
* @param list<string> $roles
*/
private function createUser(array $roles = [], bool $approved = false): User
{
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = new User();
$user->setEmail('test-account-'.uniqid().'@example.com');
$user->setFirstName('Test');
$user->setLastName('User');
$user->setPassword('$2y$13$hashed');
$user->setRoles($roles);
if ($approved) {
$user->setIsApproved(true);
}
$em->persist($user);
$em->flush();
return $user;
}
}