Add comprehensive test coverage for AttestationController, LegalController, AdminController, AccountController and AnalyticsEvent entity

- AttestationController: fix decodeAndVerifyHash to have max 3 returns, add 11 tests covering all routes (check, ventesRef, ventes) and all decodeAndVerifyHash branches (invalid base64, missing pipe, bad signature, bad JSON, valid hash with/without registered attestation), plus generateHash unit tests with unicode
- LegalController: add 6 tests for RGPD POST routes (rgpdAccess and rgpdDeletion) covering empty fields, data found, and no data found scenarios
- AdminController: add 10 tests for analytics page (all period filters + access denied) and orderTickets endpoint (single ticket PDF, multiple tickets ZIP, order not found, no tickets)
- AccountController: add 17 tests for downloadTicket (success/denied/404), resendTicket (success/denied/404), cancelTicket (success/denied/404), createAccreditation (staff/exposant/empty fields/no categories/invalid type), eventAttestation (with categories/billets/empty selection)
- AnalyticsEvent entity: new test file with 8 tests covering constructor defaults, all getters/setters, nullable fields, and fluent interface

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-04-01 18:41:18 +02:00
parent a139feef07
commit 1b3371cb7f
6 changed files with 1066 additions and 6 deletions

View File

@@ -2226,6 +2226,501 @@ class AccountControllerTest extends WebTestCase
self::assertResponseIsSuccessful();
}
// ---- downloadTicket tests ----
public function testDownloadTicketSuccess(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$category = $this->createCategory($em, $event);
$billet = $this->createBillet($em, $category);
$order = new \App\Entity\BilletBuyer();
$order->setEvent($event);
$order->setFirstName('Jean');
$order->setLastName('Dupont');
$order->setEmail('jean@test.fr');
$order->setOrderNumber('2026-03-21-'.random_int(100, 999));
$order->setTotalHT(1000);
$order->setStatus(\App\Entity\BilletBuyer::STATUS_PAID);
$item = new \App\Entity\BilletBuyerItem();
$item->setBillet($billet);
$item->setBilletName('Test');
$item->setQuantity(1);
$item->setUnitPriceHT(1000);
$order->addItem($item);
$em->persist($order);
$em->flush();
$ticket = new \App\Entity\BilletOrder();
$ticket->setBilletBuyer($order);
$ticket->setBillet($billet);
$ticket->setBilletName('Test');
$ticket->setUnitPriceHT(1000);
$em->persist($ticket);
$em->flush();
$billetOrderService = $this->createMock(\App\Service\BilletOrderService::class);
$billetOrderService->expects(self::once())->method('generatePdf')->willReturn('%PDF-1.4 fake');
static::getContainer()->set(\App\Service\BilletOrderService::class, $billetOrderService);
$client->loginUser($user);
$client->request('GET', '/mon-compte/evenement/'.$event->getId().'/ticket/'.$ticket->getId().'/telecharger');
self::assertResponseIsSuccessful();
self::assertResponseHeaderSame('Content-Type', 'application/pdf');
}
public function testDownloadTicketDeniedForOtherUser(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$owner = $this->createUser(['ROLE_ORGANIZER'], true);
$other = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $owner);
$category = $this->createCategory($em, $event);
$billet = $this->createBillet($em, $category);
$order = new \App\Entity\BilletBuyer();
$order->setEvent($event);
$order->setFirstName('Jean');
$order->setLastName('Dupont');
$order->setEmail('jean@test.fr');
$order->setOrderNumber('2026-03-21-'.random_int(100, 999));
$order->setTotalHT(1000);
$order->setStatus(\App\Entity\BilletBuyer::STATUS_PAID);
$item = new \App\Entity\BilletBuyerItem();
$item->setBillet($billet);
$item->setBilletName('Test');
$item->setQuantity(1);
$item->setUnitPriceHT(1000);
$order->addItem($item);
$em->persist($order);
$em->flush();
$ticket = new \App\Entity\BilletOrder();
$ticket->setBilletBuyer($order);
$ticket->setBillet($billet);
$ticket->setBilletName('Test');
$ticket->setUnitPriceHT(1000);
$em->persist($ticket);
$em->flush();
$client->loginUser($other);
$client->request('GET', '/mon-compte/evenement/'.$event->getId().'/ticket/'.$ticket->getId().'/telecharger');
self::assertResponseStatusCodeSame(403);
}
public function testDownloadTicketNotFound(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$client->loginUser($user);
$client->request('GET', '/mon-compte/evenement/'.$event->getId().'/ticket/999999/telecharger');
self::assertResponseStatusCodeSame(404);
}
// ---- resendTicket tests ----
public function testResendTicketSuccess(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$category = $this->createCategory($em, $event);
$billet = $this->createBillet($em, $category);
$order = new \App\Entity\BilletBuyer();
$order->setEvent($event);
$order->setFirstName('Jean');
$order->setLastName('Dupont');
$order->setEmail('jean@test.fr');
$order->setOrderNumber('2026-03-21-'.random_int(100, 999));
$order->setTotalHT(1000);
$order->setStatus(\App\Entity\BilletBuyer::STATUS_PAID);
$item = new \App\Entity\BilletBuyerItem();
$item->setBillet($billet);
$item->setBilletName('Test');
$item->setQuantity(1);
$item->setUnitPriceHT(1000);
$order->addItem($item);
$em->persist($order);
$em->flush();
$ticket = new \App\Entity\BilletOrder();
$ticket->setBilletBuyer($order);
$ticket->setBillet($billet);
$ticket->setBilletName('Test');
$ticket->setUnitPriceHT(1000);
$em->persist($ticket);
$em->flush();
$billetOrderService = $this->createMock(\App\Service\BilletOrderService::class);
$billetOrderService->expects(self::once())->method('generateAndSendTickets');
static::getContainer()->set(\App\Service\BilletOrderService::class, $billetOrderService);
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/ticket/'.$ticket->getId().'/renvoyer');
self::assertResponseRedirects('/mon-compte/evenement/'.$event->getId().'/modifier?tab=tickets');
}
public function testResendTicketDeniedForOtherUser(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$owner = $this->createUser(['ROLE_ORGANIZER'], true);
$other = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $owner);
$category = $this->createCategory($em, $event);
$billet = $this->createBillet($em, $category);
$order = new \App\Entity\BilletBuyer();
$order->setEvent($event);
$order->setFirstName('Jean');
$order->setLastName('Dupont');
$order->setEmail('jean@test.fr');
$order->setOrderNumber('2026-03-21-'.random_int(100, 999));
$order->setTotalHT(1000);
$order->setStatus(\App\Entity\BilletBuyer::STATUS_PAID);
$item = new \App\Entity\BilletBuyerItem();
$item->setBillet($billet);
$item->setBilletName('Test');
$item->setQuantity(1);
$item->setUnitPriceHT(1000);
$order->addItem($item);
$em->persist($order);
$em->flush();
$ticket = new \App\Entity\BilletOrder();
$ticket->setBilletBuyer($order);
$ticket->setBillet($billet);
$ticket->setBilletName('Test');
$ticket->setUnitPriceHT(1000);
$em->persist($ticket);
$em->flush();
$client->loginUser($other);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/ticket/'.$ticket->getId().'/renvoyer');
self::assertResponseStatusCodeSame(403);
}
public function testResendTicketNotFound(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/ticket/999999/renvoyer');
self::assertResponseStatusCodeSame(404);
}
// ---- cancelTicket tests ----
public function testCancelTicketSuccess(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$category = $this->createCategory($em, $event);
$billet = $this->createBillet($em, $category);
$order = new \App\Entity\BilletBuyer();
$order->setEvent($event);
$order->setFirstName('Jean');
$order->setLastName('Dupont');
$order->setEmail('jean@test.fr');
$order->setOrderNumber('2026-03-21-'.random_int(100, 999));
$order->setTotalHT(1000);
$order->setStatus(\App\Entity\BilletBuyer::STATUS_PAID);
$item = new \App\Entity\BilletBuyerItem();
$item->setBillet($billet);
$item->setBilletName('Test');
$item->setQuantity(1);
$item->setUnitPriceHT(1000);
$order->addItem($item);
$em->persist($order);
$em->flush();
$ticket = new \App\Entity\BilletOrder();
$ticket->setBilletBuyer($order);
$ticket->setBillet($billet);
$ticket->setBilletName('Test');
$ticket->setUnitPriceHT(1000);
$em->persist($ticket);
$em->flush();
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/ticket/'.$ticket->getId().'/annuler');
self::assertResponseRedirects('/mon-compte/evenement/'.$event->getId().'/modifier?tab=tickets');
$em->refresh($ticket);
self::assertSame(\App\Entity\BilletOrder::STATE_INVALID, $ticket->getState());
}
public function testCancelTicketDeniedForOtherUser(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$owner = $this->createUser(['ROLE_ORGANIZER'], true);
$other = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $owner);
$category = $this->createCategory($em, $event);
$billet = $this->createBillet($em, $category);
$order = new \App\Entity\BilletBuyer();
$order->setEvent($event);
$order->setFirstName('Jean');
$order->setLastName('Dupont');
$order->setEmail('jean@test.fr');
$order->setOrderNumber('2026-03-21-'.random_int(100, 999));
$order->setTotalHT(1000);
$order->setStatus(\App\Entity\BilletBuyer::STATUS_PAID);
$item = new \App\Entity\BilletBuyerItem();
$item->setBillet($billet);
$item->setBilletName('Test');
$item->setQuantity(1);
$item->setUnitPriceHT(1000);
$order->addItem($item);
$em->persist($order);
$em->flush();
$ticket = new \App\Entity\BilletOrder();
$ticket->setBilletBuyer($order);
$ticket->setBillet($billet);
$ticket->setBilletName('Test');
$ticket->setUnitPriceHT(1000);
$em->persist($ticket);
$em->flush();
$client->loginUser($other);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/ticket/'.$ticket->getId().'/annuler');
self::assertResponseStatusCodeSame(403);
}
public function testCancelTicketNotFound(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/ticket/999999/annuler');
self::assertResponseStatusCodeSame(404);
}
// ---- createAccreditation tests ----
public function testCreateAccreditationStaffSuccess(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$category = $this->createCategory($em, $event);
$billetOrderService = $this->createMock(\App\Service\BilletOrderService::class);
$billetOrderService->expects(self::once())->method('generateOrderTickets');
$billetOrderService->expects(self::once())->method('generateAndSendTickets');
static::getContainer()->set(\App\Service\BilletOrderService::class, $billetOrderService);
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/accreditation', [
'accreditation_type' => 'staff',
'first_name' => 'Alice',
'last_name' => 'Martin',
'email' => 'alice@test.fr',
]);
self::assertResponseRedirects('/mon-compte/evenement/'.$event->getId().'/modifier?tab=invitations');
}
public function testCreateAccreditationExposantSuccess(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$category = $this->createCategory($em, $event);
$billetOrderService = $this->createMock(\App\Service\BilletOrderService::class);
$billetOrderService->expects(self::once())->method('generateOrderTickets');
$billetOrderService->expects(self::once())->method('generateAndSendTickets');
static::getContainer()->set(\App\Service\BilletOrderService::class, $billetOrderService);
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/accreditation', [
'accreditation_type' => 'exposant',
'first_name' => 'Bob',
'last_name' => 'Durand',
'email' => 'bob@test.fr',
]);
self::assertResponseRedirects('/mon-compte/evenement/'.$event->getId().'/modifier?tab=invitations');
}
public function testCreateAccreditationEmptyFields(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$category = $this->createCategory($em, $event);
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/accreditation', [
'accreditation_type' => 'staff',
'first_name' => '',
'last_name' => '',
'email' => '',
]);
self::assertResponseRedirects('/mon-compte/evenement/'.$event->getId().'/modifier?tab=invitations');
}
public function testCreateAccreditationNoCategories(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
// No category created
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/accreditation', [
'accreditation_type' => 'staff',
'first_name' => 'Alice',
'last_name' => 'Martin',
'email' => 'alice@test.fr',
]);
self::assertResponseRedirects('/mon-compte/evenement/'.$event->getId().'/modifier?tab=invitations');
}
public function testCreateAccreditationInvalidTypeDefaultsToStaff(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$category = $this->createCategory($em, $event);
$billetOrderService = $this->createMock(\App\Service\BilletOrderService::class);
$billetOrderService->expects(self::once())->method('generateOrderTickets');
$billetOrderService->expects(self::once())->method('generateAndSendTickets');
static::getContainer()->set(\App\Service\BilletOrderService::class, $billetOrderService);
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/accreditation', [
'accreditation_type' => 'invalid_type',
'first_name' => 'Alice',
'last_name' => 'Martin',
'email' => 'alice@test.fr',
]);
self::assertResponseRedirects('/mon-compte/evenement/'.$event->getId().'/modifier?tab=invitations');
// Verify the billet was created with 'staff' label (default)
$billets = $em->getRepository(\App\Entity\Billet::class)->findBy(['category' => $category, 'type' => 'staff']);
self::assertNotEmpty($billets);
}
// ---- eventAttestation tests ----
public function testEventAttestationWithCategories(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$category = $this->createCategory($em, $event);
$billet = $this->createBillet($em, $category);
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/attestation', [
'categories' => [$category->getId()],
'mode' => 'simple',
]);
self::assertResponseIsSuccessful();
self::assertResponseHeaderSame('Content-Type', 'application/pdf');
}
public function testEventAttestationWithBillets(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$category = $this->createCategory($em, $event);
$billet = $this->createBillet($em, $category);
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/attestation', [
'billets' => [$billet->getId()],
'mode' => 'detail',
]);
self::assertResponseIsSuccessful();
self::assertResponseHeaderSame('Content-Type', 'application/pdf');
}
public function testEventAttestationEmptySelection(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = $this->createUser(['ROLE_ORGANIZER'], true);
$event = $this->createEvent($em, $user);
$client->loginUser($user);
$client->request('POST', '/mon-compte/evenement/'.$event->getId().'/attestation', [
'categories' => [],
'billets' => [],
]);
self::assertResponseRedirects('/mon-compte/evenement/'.$event->getId().'/modifier?tab=attestation');
}
/**
* @param list<string> $roles
*/

View File

@@ -2,7 +2,11 @@
namespace App\Tests\Controller;
use App\Entity\Billet;
use App\Entity\BilletBuyer;
use App\Entity\BilletBuyerItem;
use App\Entity\BilletOrder;
use App\Entity\Category;
use App\Entity\Event;
use App\Entity\User;
use App\Service\BilletOrderService;
@@ -1120,4 +1124,223 @@ class AdminControllerTest extends WebTestCase
self::assertResponseStatusCodeSame(403);
}
public function testAnalyticsDefaultPeriod(): void
{
$client = static::createClient();
$admin = $this->createUser(['ROLE_ROOT']);
$client->loginUser($admin);
$client->request('GET', '/admin/analytics');
self::assertResponseIsSuccessful();
}
public function testAnalyticsPeriodToday(): void
{
$client = static::createClient();
$admin = $this->createUser(['ROLE_ROOT']);
$client->loginUser($admin);
$client->request('GET', '/admin/analytics?period=today');
self::assertResponseIsSuccessful();
}
public function testAnalyticsPeriod30d(): void
{
$client = static::createClient();
$admin = $this->createUser(['ROLE_ROOT']);
$client->loginUser($admin);
$client->request('GET', '/admin/analytics?period=30d');
self::assertResponseIsSuccessful();
}
public function testAnalyticsPeriodAll(): void
{
$client = static::createClient();
$admin = $this->createUser(['ROLE_ROOT']);
$client->loginUser($admin);
$client->request('GET', '/admin/analytics?period=all');
self::assertResponseIsSuccessful();
}
public function testAnalyticsDeniedForNonRoot(): void
{
$client = static::createClient();
$user = $this->createUser();
$client->loginUser($user);
$client->request('GET', '/admin/analytics');
self::assertResponseStatusCodeSame(403);
}
public function testOrderTicketsSingleTicketReturnsPdf(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$admin = $this->createUser(['ROLE_ROOT']);
$orga = $this->createOrganizer($em);
$event = $this->createEvent($em, $orga);
$category = new Category();
$category->setName('Test');
$category->setEvent($event);
$category->setPosition(0);
$category->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
$category->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
$em->persist($category);
$billet = new Billet();
$billet->setName('Test');
$billet->setCategory($category);
$billet->setPriceHT(1000);
$em->persist($billet);
$order = new BilletBuyer();
$order->setEvent($event);
$order->setFirstName('Jean');
$order->setLastName('Test');
$order->setEmail('jean@test.fr');
$order->setOrderNumber('2026-'.uniqid());
$order->setTotalHT(1000);
$order->setStatus(BilletBuyer::STATUS_PAID);
$em->persist($order);
$item = new BilletBuyerItem();
$item->setBillet($billet);
$item->setBilletName('Test');
$item->setQuantity(1);
$item->setUnitPriceHT(1000);
$order->addItem($item);
$em->persist($item);
$ticket = new BilletOrder();
$ticket->setBilletBuyer($order);
$ticket->setBillet($billet);
$ticket->setBilletName('Test');
$ticket->setUnitPriceHT(1000);
$em->persist($ticket);
$em->flush();
$billetOrderService = $this->createMock(BilletOrderService::class);
$billetOrderService->expects(self::once())->method('generatePdf')->willReturn('%PDF-1.4 dummy');
static::getContainer()->set(BilletOrderService::class, $billetOrderService);
$client->loginUser($admin);
$client->request('GET', '/admin/commandes/'.$order->getId().'/billets');
self::assertResponseIsSuccessful();
self::assertStringContainsString('application/pdf', $client->getResponse()->headers->get('Content-Type'));
}
public function testOrderTicketsMultipleTicketsReturnsZip(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$admin = $this->createUser(['ROLE_ROOT']);
$orga = $this->createOrganizer($em);
$event = $this->createEvent($em, $orga);
$category = new Category();
$category->setName('Test');
$category->setEvent($event);
$category->setPosition(0);
$category->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
$category->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
$em->persist($category);
$billet = new Billet();
$billet->setName('Test');
$billet->setCategory($category);
$billet->setPriceHT(1000);
$em->persist($billet);
$order = new BilletBuyer();
$order->setEvent($event);
$order->setFirstName('Jean');
$order->setLastName('Test');
$order->setEmail('jean@test.fr');
$order->setOrderNumber('2026-'.uniqid());
$order->setTotalHT(2000);
$order->setStatus(BilletBuyer::STATUS_PAID);
$em->persist($order);
$item = new BilletBuyerItem();
$item->setBillet($billet);
$item->setBilletName('Test');
$item->setQuantity(2);
$item->setUnitPriceHT(1000);
$order->addItem($item);
$em->persist($item);
$ticket1 = new BilletOrder();
$ticket1->setBilletBuyer($order);
$ticket1->setBillet($billet);
$ticket1->setBilletName('Test');
$ticket1->setUnitPriceHT(1000);
$em->persist($ticket1);
$ticket2 = new BilletOrder();
$ticket2->setBilletBuyer($order);
$ticket2->setBillet($billet);
$ticket2->setBilletName('Test');
$ticket2->setUnitPriceHT(1000);
$em->persist($ticket2);
$em->flush();
$billetOrderService = $this->createMock(BilletOrderService::class);
$billetOrderService->expects(self::exactly(2))->method('generatePdf')->willReturn('%PDF-1.4 dummy');
static::getContainer()->set(BilletOrderService::class, $billetOrderService);
$client->loginUser($admin);
$client->request('GET', '/admin/commandes/'.$order->getId().'/billets');
self::assertResponseIsSuccessful();
self::assertStringContainsString('application/zip', $client->getResponse()->headers->get('Content-Type'));
}
public function testOrderTicketsNotFound(): void
{
$client = static::createClient();
$admin = $this->createUser(['ROLE_ROOT']);
$client->loginUser($admin);
$client->request('GET', '/admin/commandes/999999/billets');
self::assertResponseStatusCodeSame(404);
}
public function testOrderTicketsNoTickets(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$admin = $this->createUser(['ROLE_ROOT']);
$orga = $this->createOrganizer($em);
$event = $this->createEvent($em, $orga);
$order = new BilletBuyer();
$order->setEvent($event);
$order->setFirstName('Jean');
$order->setLastName('Test');
$order->setEmail('jean@test.fr');
$order->setOrderNumber('2026-'.uniqid());
$order->setTotalHT(1000);
$order->setStatus(BilletBuyer::STATUS_PAID);
$em->persist($order);
$em->flush();
$client->loginUser($admin);
$client->request('GET', '/admin/commandes/'.$order->getId().'/billets');
self::assertResponseStatusCodeSame(404);
}
}

View File

@@ -2,6 +2,9 @@
namespace App\Tests\Controller;
use App\Controller\AttestationController;
use App\Entity\Attestation;
use App\Entity\Event;
use App\Entity\Payout;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
@@ -44,4 +47,179 @@ class AttestationControllerTest extends WebTestCase
self::assertResponseIsSuccessful();
self::assertSelectorTextContains('body', 'Attestation introuvable');
}
public function testVentesRefWithValidReference(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$user = new User();
$user->setEmail('test-vref-'.uniqid().'@example.com');
$user->setFirstName('Test');
$user->setLastName('User');
$user->setPassword('$2y$13$hashed');
$em->persist($user);
$event = new Event();
$event->setAccount($user);
$event->setTitle('Test Event');
$event->setStartAt(new \DateTimeImmutable('+1 day'));
$event->setEndAt(new \DateTimeImmutable('+2 days'));
$event->setAddress('123 Rue Test');
$event->setZipcode('75001');
$event->setCity('Paris');
$em->persist($event);
$reference = 'REF-'.uniqid();
$payload = ['event' => 'Test Event', 'total' => 5000];
$attestation = new Attestation($reference, 'sig_'.uniqid(), $event, $user, 10, $payload);
$em->persist($attestation);
$em->flush();
$client->request('GET', '/attestation/ventes/r/'.$reference);
self::assertResponseIsSuccessful();
}
public function testVentesRefWithInvalidReference(): void
{
$client = static::createClient();
$client->request('GET', '/attestation/ventes/r/INVALID_REF');
self::assertResponseIsSuccessful();
self::assertSelectorTextContains('body', 'introuvable');
}
public function testVentesWithValidHash(): void
{
$client = static::createClient();
$appSecret = static::getContainer()->getParameter('kernel.secret');
$data = ['event' => 'Test Event', 'total' => 5000];
$hash = AttestationController::generateHash($data, $appSecret);
$client->request('GET', '/attestation/ventes/'.$hash);
self::assertResponseIsSuccessful();
}
public function testVentesWithValidHashAndRegisteredAttestation(): void
{
$client = static::createClient();
$em = static::getContainer()->get(EntityManagerInterface::class);
$appSecret = static::getContainer()->getParameter('kernel.secret');
$user = new User();
$user->setEmail('test-vreg-'.uniqid().'@example.com');
$user->setFirstName('Test');
$user->setLastName('User');
$user->setPassword('$2y$13$hashed');
$em->persist($user);
$event = new Event();
$event->setAccount($user);
$event->setTitle('Test Event');
$event->setStartAt(new \DateTimeImmutable('+1 day'));
$event->setEndAt(new \DateTimeImmutable('+2 days'));
$event->setAddress('123 Rue Test');
$event->setZipcode('75001');
$event->setCity('Paris');
$em->persist($event);
$data = ['event' => 'Registered Event', 'total' => 8000];
$json = json_encode($data, \JSON_UNESCAPED_UNICODE);
$signatureHash = hash_hmac('sha256', $json, $appSecret);
$attestation = new Attestation('REF-'.uniqid(), $signatureHash, $event, $user, 20, $data);
$em->persist($attestation);
$em->flush();
$hash = AttestationController::generateHash($data, $appSecret);
$client->request('GET', '/attestation/ventes/'.$hash);
self::assertResponseIsSuccessful();
}
public function testVentesWithInvalidBase64(): void
{
$client = static::createClient();
$client->request('GET', '/attestation/ventes/!!!invalid-base64!!!');
self::assertResponseIsSuccessful();
self::assertSelectorTextContains('body', 'introuvable');
}
public function testVentesWithMissingPipeSeparator(): void
{
$client = static::createClient();
$hash = rtrim(strtr(base64_encode('no-pipe-here'), '+/', '-_'), '=');
$client->request('GET', '/attestation/ventes/'.$hash);
self::assertResponseIsSuccessful();
self::assertSelectorTextContains('body', 'introuvable');
}
public function testVentesWithInvalidSignature(): void
{
$client = static::createClient();
$json = json_encode(['event' => 'Test'], \JSON_UNESCAPED_UNICODE);
$hash = rtrim(strtr(base64_encode('invalidsignature|'.$json), '+/', '-_'), '=');
$client->request('GET', '/attestation/ventes/'.$hash);
self::assertResponseIsSuccessful();
self::assertSelectorTextContains('body', 'introuvable');
}
public function testVentesWithInvalidJsonPayload(): void
{
$client = static::createClient();
$appSecret = static::getContainer()->getParameter('kernel.secret');
$invalidJson = '{invalid json}';
$signature = hash_hmac('sha256', $invalidJson, $appSecret);
$hash = rtrim(strtr(base64_encode($signature.'|'.$invalidJson), '+/', '-_'), '=');
$client->request('GET', '/attestation/ventes/'.$hash);
self::assertResponseIsSuccessful();
self::assertSelectorTextContains('body', 'introuvable');
}
public function testGenerateHash(): void
{
$data = ['key' => 'value', 'amount' => 1000];
$secret = 'test-secret';
$hash = AttestationController::generateHash($data, $secret);
self::assertNotEmpty($hash);
self::assertMatchesRegularExpression('/^[A-Za-z0-9\-_]+$/', $hash);
$decoded = base64_decode(strtr($hash, '-_', '+/'), true);
self::assertNotFalse($decoded);
$parts = explode('|', $decoded, 2);
self::assertCount(2, $parts);
[$signature, $jsonPayload] = $parts;
$expectedSignature = hash_hmac('sha256', $jsonPayload, $secret);
self::assertTrue(hash_equals($expectedSignature, $signature));
self::assertSame($data, json_decode($jsonPayload, true));
}
public function testGenerateHashWithUnicodeData(): void
{
$data = ['name' => 'Événement été', 'city' => 'Zürich'];
$secret = 'test-secret';
$hash = AttestationController::generateHash($data, $secret);
$decoded = base64_decode(strtr($hash, '-_', '+/'), true);
$parts = explode('|', $decoded, 2);
self::assertStringContainsString('Événement été', $parts[1]);
self::assertStringContainsString('Zürich', $parts[1]);
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Tests\Controller;
use App\Service\RgpdService;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class LegalControllerTest extends WebTestCase
@@ -61,4 +62,84 @@ class LegalControllerTest extends WebTestCase
self::assertResponseIsSuccessful();
}
public function testRgpdAccessEmptyFields(): void
{
$client = static::createClient();
$client->request('POST', '/rgpd/acces', ['ip' => '', 'email' => '']);
self::assertResponseRedirects('/rgpd');
}
public function testRgpdAccessWithDataFound(): void
{
$client = static::createClient();
$mock = $this->createMock(RgpdService::class);
$mock->method('handleAccessRequest')
->with('192.168.1.1', 'test@example.com')
->willReturn(['found' => true, 'count' => 5]);
static::getContainer()->set(RgpdService::class, $mock);
$client->request('POST', '/rgpd/acces', ['ip' => '192.168.1.1', 'email' => 'test@example.com']);
self::assertResponseRedirects('/rgpd');
}
public function testRgpdAccessWithNoData(): void
{
$client = static::createClient();
$mock = $this->createMock(RgpdService::class);
$mock->method('handleAccessRequest')
->with('192.168.1.1', 'test@example.com')
->willReturn(['found' => false, 'count' => 0]);
static::getContainer()->set(RgpdService::class, $mock);
$client->request('POST', '/rgpd/acces', ['ip' => '192.168.1.1', 'email' => 'test@example.com']);
self::assertResponseRedirects('/rgpd');
}
public function testRgpdDeletionEmptyFields(): void
{
$client = static::createClient();
$client->request('POST', '/rgpd/suppression', ['ip' => '', 'email' => '']);
self::assertResponseRedirects('/rgpd');
}
public function testRgpdDeletionWithDataFound(): void
{
$client = static::createClient();
$mock = $this->createMock(RgpdService::class);
$mock->method('handleDeletionRequest')
->with('192.168.1.1', 'test@example.com')
->willReturn(['found' => true, 'count' => 3]);
static::getContainer()->set(RgpdService::class, $mock);
$client->request('POST', '/rgpd/suppression', ['ip' => '192.168.1.1', 'email' => 'test@example.com']);
self::assertResponseRedirects('/rgpd');
}
public function testRgpdDeletionWithNoData(): void
{
$client = static::createClient();
$mock = $this->createMock(RgpdService::class);
$mock->method('handleDeletionRequest')
->with('192.168.1.1', 'test@example.com')
->willReturn(['found' => false, 'count' => 0]);
static::getContainer()->set(RgpdService::class, $mock);
$client->request('POST', '/rgpd/suppression', ['ip' => '192.168.1.1', 'email' => 'test@example.com']);
self::assertResponseRedirects('/rgpd');
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace App\Tests\Entity;
use App\Entity\AnalyticsEvent;
use App\Entity\AnalyticsUniqId;
use PHPUnit\Framework\TestCase;
class AnalyticsEventTest extends TestCase
{
public function testConstructor(): void
{
$event = new AnalyticsEvent();
self::assertNull($event->getId());
self::assertSame('page_view', $event->getEventName());
self::assertNull($event->getTitle());
self::assertNull($event->getReferrer());
self::assertInstanceOf(\DateTimeImmutable::class, $event->getCreatedAt());
}
public function testSetEventName(): void
{
$event = new AnalyticsEvent();
$result = $event->setEventName('click');
self::assertSame('click', $event->getEventName());
self::assertSame($event, $result);
}
public function testSetUrl(): void
{
$event = new AnalyticsEvent();
$result = $event->setUrl('https://example.com/page');
self::assertSame('https://example.com/page', $event->getUrl());
self::assertSame($event, $result);
}
public function testSetTitle(): void
{
$event = new AnalyticsEvent();
$result = $event->setTitle('My Page');
self::assertSame('My Page', $event->getTitle());
self::assertSame($event, $result);
}
public function testSetTitleNull(): void
{
$event = new AnalyticsEvent();
$event->setTitle('My Page');
$result = $event->setTitle(null);
self::assertNull($event->getTitle());
self::assertSame($event, $result);
}
public function testSetReferrer(): void
{
$event = new AnalyticsEvent();
$result = $event->setReferrer('https://google.com');
self::assertSame('https://google.com', $event->getReferrer());
self::assertSame($event, $result);
}
public function testSetReferrerNull(): void
{
$event = new AnalyticsEvent();
$event->setReferrer('https://google.com');
$result = $event->setReferrer(null);
self::assertNull($event->getReferrer());
self::assertSame($event, $result);
}
public function testSetVisitor(): void
{
$visitor = $this->createMock(AnalyticsUniqId::class);
$event = new AnalyticsEvent();
$result = $event->setVisitor($visitor);
self::assertSame($visitor, $event->getVisitor());
self::assertSame($event, $result);
}
}