Translation system: - Add LibreTranslate container (dev + prod), CPU-only, no port exposed, FR/EN/ES/DE/IT - Create app:translate command: reads *.fr.yaml, translates incrementally, preserves placeholders - Makefile: make trans / make trans_prod (stops container after translation) - Ansible: start libretranslate -> translate -> stop during deploy - Prod container restart: "no" (only runs during deploy) - .gitignore: ignore generated *.en/es/de/it.yaml files - 11 tests for TranslateCommand (API unreachable, empty, incremental, obsolete keys, placeholders, fallback) Test coverage improvements: - OrderController: event ended (400), invalid cart JSON, invalid email, stock zero (4 new tests) - AccountController: finance stats all statuses (paid/pending/refunded/cancelled), soldCounts (2 new tests) - JS cart: checkout without error elements, hide error on retry, stock polling edge cases (singular, no label, qty zero, unknown billet) (8 new tests) - JS editor: comment node sanitization (1 new test) - JS tabs: missing panel, generated id, parent null, click no-panel (5 new tests) Code duplication fixes: - MeilisearchConsistencyCommand: extract diffAndReport() method (was duplicated 3x) - Email templates: extract _order_items_table.html.twig partial (shared by notification + cancelled) - SonarQube: exclude src/Entity/** from CPD (getters/setters duplication) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
633 lines
23 KiB
PHP
633 lines
23 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Controller;
|
|
|
|
use App\Entity\Billet;
|
|
use App\Entity\BilletBuyer;
|
|
use App\Entity\BilletBuyerItem;
|
|
use App\Entity\Category;
|
|
use App\Entity\Event;
|
|
use App\Entity\User;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
|
|
|
class OrderControllerTest extends WebTestCase
|
|
{
|
|
private function createOrga(EntityManagerInterface $em): User
|
|
{
|
|
$user = new User();
|
|
$user->setEmail('orga-order-'.uniqid().'@test.fr');
|
|
$user->setFirstName('Orga');
|
|
$user->setLastName('Test');
|
|
$user->setPassword('hashed');
|
|
$user->setRoles(['ROLE_ORGANIZER']);
|
|
$user->setIsApproved(true);
|
|
$user->setIsVerified(true);
|
|
$user->setCompanyName('Asso Test');
|
|
$user->setStripeAccountId('acct_test');
|
|
$em->persist($user);
|
|
|
|
return $user;
|
|
}
|
|
|
|
private function createEventWithBillet(EntityManagerInterface $em, User $user): array
|
|
{
|
|
$event = new Event();
|
|
$event->setAccount($user);
|
|
$event->setTitle('Order 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');
|
|
$event->setIsOnline(true);
|
|
$em->persist($event);
|
|
|
|
$category = new Category();
|
|
$category->setName('Cat');
|
|
$category->setEvent($event);
|
|
$category->setStartAt(new \DateTimeImmutable('-1 day'));
|
|
$category->setEndAt(new \DateTimeImmutable('+30 days'));
|
|
$em->persist($category);
|
|
|
|
$billet = new Billet();
|
|
$billet->setName('Entree');
|
|
$billet->setCategory($category);
|
|
$billet->setPriceHT(1500);
|
|
$billet->setQuantity(10);
|
|
$em->persist($billet);
|
|
|
|
$em->flush();
|
|
|
|
return [$event, $billet];
|
|
}
|
|
|
|
private function createOrder(EntityManagerInterface $em, Event $event, Billet $billet, ?User $user = null): BilletBuyer
|
|
{
|
|
$count = $em->getRepository(BilletBuyer::class)->count([]) + 1;
|
|
$order = new BilletBuyer();
|
|
$order->setEvent($event);
|
|
$order->setFirstName('Jean');
|
|
$order->setLastName('Dupont');
|
|
$order->setEmail('jean@test.fr');
|
|
$order->setOrderNumber('2026-03-21-'.$count);
|
|
$order->setTotalHT(1500);
|
|
if ($user) {
|
|
$order->setUser($user);
|
|
}
|
|
|
|
$item = new BilletBuyerItem();
|
|
$item->setBillet($billet);
|
|
$item->setBilletName('Entree');
|
|
$item->setQuantity(1);
|
|
$item->setUnitPriceHT(1500);
|
|
$order->addItem($item);
|
|
|
|
$em->persist($order);
|
|
$em->flush();
|
|
|
|
return $order;
|
|
}
|
|
|
|
// === CREATE ===
|
|
|
|
public function testCreateOrderNotFound(): void
|
|
{
|
|
$client = static::createClient();
|
|
$client->request('POST', '/evenement/999999/commander', [], [], ['CONTENT_TYPE' => 'application/json'], '[]');
|
|
self::assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
public function testCreateOrderEmptyCart(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event] = $this->createEventWithBillet($em, $user);
|
|
|
|
$client->request('POST', '/evenement/'.$event->getId().'/commander', [], [], ['CONTENT_TYPE' => 'application/json'], '[]');
|
|
self::assertResponseIsSuccessful();
|
|
|
|
$data = json_decode($client->getResponse()->getContent(), true);
|
|
self::assertArrayHasKey('redirect', $data);
|
|
}
|
|
|
|
public function testCreateOrderAsGuest(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
|
|
$client->request('POST', '/evenement/'.$event->getId().'/commander', [], [], ['CONTENT_TYPE' => 'application/json'], json_encode([
|
|
['billetId' => $billet->getId(), 'qty' => 2],
|
|
]));
|
|
|
|
self::assertResponseIsSuccessful();
|
|
$data = json_decode($client->getResponse()->getContent(), true);
|
|
self::assertStringContainsString('/commande/', $data['redirect']);
|
|
self::assertStringContainsString('/informations', $data['redirect']);
|
|
}
|
|
|
|
public function testCreateOrderAsLoggedUser(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
|
|
$buyer = new User();
|
|
$buyer->setEmail('buyer-'.uniqid().'@test.fr');
|
|
$buyer->setFirstName('Buyer');
|
|
$buyer->setLastName('Test');
|
|
$buyer->setPassword('hashed');
|
|
$em->persist($buyer);
|
|
$em->flush();
|
|
|
|
$client->loginUser($buyer);
|
|
$client->request('POST', '/evenement/'.$event->getId().'/commander', [], [], ['CONTENT_TYPE' => 'application/json'], json_encode([
|
|
['billetId' => $billet->getId(), 'qty' => 1],
|
|
]));
|
|
|
|
self::assertResponseIsSuccessful();
|
|
$data = json_decode($client->getResponse()->getContent(), true);
|
|
self::assertStringContainsString('/paiement', $data['redirect']);
|
|
}
|
|
|
|
public function testCreateOrderInvalidBillet(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event] = $this->createEventWithBillet($em, $user);
|
|
|
|
$client->request('POST', '/evenement/'.$event->getId().'/commander', [], [], ['CONTENT_TYPE' => 'application/json'], json_encode([
|
|
['billetId' => 999999, 'qty' => 1],
|
|
]));
|
|
|
|
self::assertResponseIsSuccessful();
|
|
$data = json_decode($client->getResponse()->getContent(), true);
|
|
self::assertArrayHasKey('redirect', $data);
|
|
}
|
|
|
|
public function testCreateOrderNotBuyableBillet(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event] = $this->createEventWithBillet($em, $user);
|
|
|
|
$notBuyable = new Billet();
|
|
$notBuyable->setName('Not Buyable');
|
|
$notBuyable->setCategory($em->getRepository(Category::class)->findOneBy(['event' => $event]));
|
|
$notBuyable->setPriceHT(500);
|
|
$notBuyable->setNotBuyable(true);
|
|
$em->persist($notBuyable);
|
|
$em->flush();
|
|
|
|
$client->request('POST', '/evenement/'.$event->getId().'/commander', [], [], ['CONTENT_TYPE' => 'application/json'], json_encode([
|
|
['billetId' => $notBuyable->getId(), 'qty' => 1],
|
|
]));
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testCreateOrderExceedsQuantity(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
|
|
$client->request('POST', '/evenement/'.$event->getId().'/commander', [], [], ['CONTENT_TYPE' => 'application/json'], json_encode([
|
|
['billetId' => $billet->getId(), 'qty' => 999],
|
|
]));
|
|
|
|
self::assertResponseIsSuccessful();
|
|
$data = json_decode($client->getResponse()->getContent(), true);
|
|
self::assertStringContainsString('/informations', $data['redirect']);
|
|
}
|
|
|
|
// === GUEST ===
|
|
|
|
public function testGuestPageNotFound(): void
|
|
{
|
|
$client = static::createClient();
|
|
$client->request('GET', '/commande/999999/informations');
|
|
self::assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
public function testGuestPageRenders(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
|
|
$client->request('GET', '/commande/'.$order->getId().'/informations');
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testGuestSubmitEmptyFields(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
|
|
$client->request('POST', '/commande/'.$order->getId().'/informations', [
|
|
'first_name' => '',
|
|
'last_name' => '',
|
|
'email' => '',
|
|
]);
|
|
|
|
self::assertResponseRedirects('/commande/'.$order->getId().'/informations');
|
|
}
|
|
|
|
public function testGuestSubmitSuccess(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
|
|
$order = new BilletBuyer();
|
|
$order->setEvent($event);
|
|
$order->setTotalHT(1500);
|
|
$order->setOrderNumber('2026-03-21-'.random_int(100, 999));
|
|
$item = new BilletBuyerItem();
|
|
$item->setBillet($billet);
|
|
$item->setBilletName('Test');
|
|
$item->setQuantity(1);
|
|
$item->setUnitPriceHT(1500);
|
|
$order->addItem($item);
|
|
$em->persist($order);
|
|
$em->flush();
|
|
|
|
$client->request('POST', '/commande/'.$order->getId().'/informations', [
|
|
'first_name' => 'Jean',
|
|
'last_name' => 'Dupont',
|
|
'email' => 'jean@test.fr',
|
|
]);
|
|
|
|
self::assertResponseRedirects('/commande/'.$order->getId().'/paiement');
|
|
}
|
|
|
|
public function testGuestRedirectsIfUserSet(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
|
|
$buyer = new User();
|
|
$buyer->setEmail('buyer-guest-'.uniqid().'@test.fr');
|
|
$buyer->setFirstName('B');
|
|
$buyer->setLastName('T');
|
|
$buyer->setPassword('hashed');
|
|
$em->persist($buyer);
|
|
|
|
$order = $this->createOrder($em, $event, $billet, $buyer);
|
|
|
|
$client->request('GET', '/commande/'.$order->getId().'/informations');
|
|
self::assertResponseRedirects('/commande/'.$order->getId().'/paiement');
|
|
}
|
|
|
|
// === PAYMENT ===
|
|
|
|
public function testPaymentNotFound(): void
|
|
{
|
|
$client = static::createClient();
|
|
$client->request('GET', '/commande/999999/paiement');
|
|
self::assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
public function testPaymentRedirectsIfNoName(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
|
|
$order = new BilletBuyer();
|
|
$order->setEvent($event);
|
|
$order->setTotalHT(1500);
|
|
$order->setOrderNumber('2026-03-21-'.random_int(100, 999));
|
|
$em->persist($order);
|
|
$em->flush();
|
|
|
|
$client->request('GET', '/commande/'.$order->getId().'/paiement');
|
|
self::assertResponseRedirects('/commande/'.$order->getId().'/informations');
|
|
}
|
|
|
|
public function testPaymentRendersWithStripe(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
|
|
$client->request('GET', '/commande/'.$order->getId().'/paiement');
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testPaymentNotFoundWithoutStripeAccount(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
|
|
$user = new User();
|
|
$user->setEmail('no-stripe-'.uniqid().'@test.fr');
|
|
$user->setFirstName('No');
|
|
$user->setLastName('Stripe');
|
|
$user->setPassword('hashed');
|
|
$user->setRoles(['ROLE_ORGANIZER']);
|
|
$user->setIsApproved(true);
|
|
$user->setIsVerified(true);
|
|
$em->persist($user);
|
|
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
|
|
$client->request('GET', '/commande/'.$order->getId().'/paiement');
|
|
self::assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
// === SUCCESS ===
|
|
|
|
public function testSuccessNotFound(): void
|
|
{
|
|
$client = static::createClient();
|
|
$client->request('GET', '/commande/999999/confirmation');
|
|
self::assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
public function testSuccessRenders(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
|
|
$client->request('GET', '/commande/'.$order->getId().'/confirmation');
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testSuccessFailed(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
|
|
$client->request('GET', '/commande/'.$order->getId().'/confirmation?redirect_status=failed');
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testSuccessSucceeded(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
|
|
$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->request('GET', '/commande/'.$order->getId().'/confirmation?redirect_status=succeeded');
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
// === PUBLIC ORDER ===
|
|
|
|
public function testPublicOrderNotFound(): void
|
|
{
|
|
$client = static::createClient();
|
|
$client->request('GET', '/ma-commande/2026-03-21-999/invalidtoken');
|
|
self::assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
public function testPublicOrderRenders(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
|
|
$client->request('GET', '/ma-commande/'.$order->getOrderNumber().'/'.$order->getAccessToken());
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
// === INVOICE ===
|
|
|
|
public function testInvoiceNotFound(): void
|
|
{
|
|
$client = static::createClient();
|
|
$client->request('GET', '/ma-commande/2026-03-21-999/invalidtoken/facture');
|
|
self::assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
public function testInvoiceNotPaid(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
|
|
$client->request('GET', '/ma-commande/'.$order->getOrderNumber().'/'.$order->getAccessToken().'/facture');
|
|
self::assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
public function testInvoiceSuccess(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
$order->setStatus(BilletBuyer::STATUS_PAID);
|
|
$em->flush();
|
|
|
|
$invoiceService = $this->createMock(\App\Service\InvoiceService::class);
|
|
$invoiceService->expects(self::once())->method('generatePdf')->willReturn('%PDF-1.4 fake');
|
|
static::getContainer()->set(\App\Service\InvoiceService::class, $invoiceService);
|
|
|
|
$client->request('GET', '/ma-commande/'.$order->getOrderNumber().'/'.$order->getAccessToken().'/facture');
|
|
self::assertResponseIsSuccessful();
|
|
self::assertResponseHeaderSame('Content-Type', 'application/pdf');
|
|
}
|
|
|
|
// === DOWNLOAD TICKET ===
|
|
|
|
public function testDownloadTicketNotFoundOrder(): void
|
|
{
|
|
$client = static::createClient();
|
|
$client->request('GET', '/ma-commande/2026-03-21-999/badtoken/billet/ETICKET-AAAA-BBBB-CCCC');
|
|
self::assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
public function testDownloadTicketNotFoundTicket(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
|
|
$client->request('GET', '/ma-commande/'.$order->getOrderNumber().'/'.$order->getAccessToken().'/billet/ETICKET-ZZZZ-ZZZZ-ZZZZ');
|
|
self::assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
public function testDownloadTicketSuccess(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
|
|
$ticket = new \App\Entity\BilletOrder();
|
|
$ticket->setBilletBuyer($order);
|
|
$ticket->setBillet($billet);
|
|
$ticket->setBilletName('Entree');
|
|
$ticket->setUnitPriceHT(1500);
|
|
$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->request('GET', '/ma-commande/'.$order->getOrderNumber().'/'.$order->getAccessToken().'/billet/'.$ticket->getReference());
|
|
self::assertResponseIsSuccessful();
|
|
self::assertResponseHeaderSame('Content-Type', 'application/pdf');
|
|
}
|
|
|
|
// === CREATE with qty <= 0 ===
|
|
|
|
public function testCreateOrderZeroQty(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
|
|
$client->request('POST', '/evenement/'.$event->getId().'/commander', [], [], ['CONTENT_TYPE' => 'application/json'], json_encode([
|
|
['billetId' => $billet->getId(), 'qty' => 0],
|
|
]));
|
|
|
|
self::assertResponseIsSuccessful();
|
|
$data = json_decode($client->getResponse()->getContent(), true);
|
|
self::assertArrayHasKey('redirect', $data);
|
|
}
|
|
|
|
public function testCreateOrderEventEnded(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
|
|
$event = new Event();
|
|
$event->setAccount($user);
|
|
$event->setTitle('Past Event');
|
|
$event->setStartAt(new \DateTimeImmutable('-2 days'));
|
|
$event->setEndAt(new \DateTimeImmutable('-1 day'));
|
|
$event->setAddress('1 rue');
|
|
$event->setZipcode('75001');
|
|
$event->setCity('Paris');
|
|
$event->setIsOnline(true);
|
|
$em->persist($event);
|
|
$em->flush();
|
|
|
|
$client->request('POST', '/evenement/'.$event->getId().'/commander', [], [], ['CONTENT_TYPE' => 'application/json'], json_encode([
|
|
['billetId' => 1, 'qty' => 1],
|
|
]));
|
|
|
|
self::assertResponseStatusCodeSame(400);
|
|
$data = json_decode($client->getResponse()->getContent(), true);
|
|
self::assertStringContainsString('termine', $data['error']);
|
|
}
|
|
|
|
public function testCreateOrderInvalidCartStructure(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event] = $this->createEventWithBillet($em, $user);
|
|
|
|
$client->request('POST', '/evenement/'.$event->getId().'/commander', [], [], ['CONTENT_TYPE' => 'application/json'], json_encode([
|
|
['invalid' => 'data'],
|
|
]));
|
|
|
|
self::assertResponseStatusCodeSame(400);
|
|
}
|
|
|
|
public function testGuestSubmitInvalidEmail(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
[$event, $billet] = $this->createEventWithBillet($em, $user);
|
|
$order = $this->createOrder($em, $event, $billet);
|
|
|
|
$client->request('POST', '/commande/'.$order->getId().'/informations', [
|
|
'first_name' => 'Jean',
|
|
'last_name' => 'Dupont',
|
|
'email' => 'not-an-email',
|
|
]);
|
|
|
|
self::assertResponseRedirects('/commande/'.$order->getId().'/informations');
|
|
}
|
|
|
|
public function testCreateOrderStockZeroSkipsBillet(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createOrga($em);
|
|
|
|
$event = new Event();
|
|
$event->setAccount($user);
|
|
$event->setTitle('Stock Zero 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');
|
|
$event->setIsOnline(true);
|
|
$em->persist($event);
|
|
|
|
$category = new Category();
|
|
$category->setName('Cat');
|
|
$category->setEvent($event);
|
|
$category->setStartAt(new \DateTimeImmutable('-1 day'));
|
|
$category->setEndAt(new \DateTimeImmutable('+30 days'));
|
|
$em->persist($category);
|
|
|
|
$billet = new Billet();
|
|
$billet->setName('Sold Out');
|
|
$billet->setCategory($category);
|
|
$billet->setPriceHT(1500);
|
|
$billet->setQuantity(0);
|
|
$em->persist($billet);
|
|
$em->flush();
|
|
|
|
$client->request('POST', '/evenement/'.$event->getId().'/commander', [], [], ['CONTENT_TYPE' => 'application/json'], json_encode([
|
|
['billetId' => $billet->getId(), 'qty' => 1],
|
|
]));
|
|
|
|
self::assertResponseIsSuccessful();
|
|
$data = json_decode($client->getResponse()->getContent(), true);
|
|
self::assertArrayHasKey('redirect', $data);
|
|
}
|
|
}
|