Shows real-time stats with color-coded indicators: - Redis: version, memory, hit rate, ops/sec, evicted keys - PostgreSQL: version, db size, connections, cache hit ratio, dead tuples Uses MESSENGER_TRANSPORT_DSN for Redis auth (works in dev and prod). Accessible via /admin/infra with nav link. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1039 lines
34 KiB
PHP
1039 lines
34 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Controller;
|
|
|
|
use App\Entity\Event;
|
|
use App\Entity\User;
|
|
use App\Service\EventIndexService;
|
|
use App\Service\MailerService;
|
|
use App\Service\MeilisearchService;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
|
|
|
class AdminControllerTest extends WebTestCase
|
|
{
|
|
public function testDashboardRedirectsWhenNotAuthenticated(): void
|
|
{
|
|
$client = static::createClient();
|
|
$client->request('GET', '/admin');
|
|
|
|
self::assertResponseRedirects();
|
|
}
|
|
|
|
public function testDashboardDeniedForNonRoot(): void
|
|
{
|
|
$client = static::createClient();
|
|
$user = $this->createUser();
|
|
|
|
$client->loginUser($user);
|
|
$client->request('GET', '/admin');
|
|
|
|
self::assertResponseStatusCodeSame(403);
|
|
}
|
|
|
|
public function testDashboardReturnsSuccessForRoot(): void
|
|
{
|
|
$client = static::createClient();
|
|
$user = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($user);
|
|
$client->request('GET', '/admin');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testUsersPageReturnsSuccessForRoot(): void
|
|
{
|
|
$client = static::createClient();
|
|
$user = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($user);
|
|
$client->request('GET', '/admin/utilisateurs');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testUsersPageDeniedForNonRoot(): void
|
|
{
|
|
$client = static::createClient();
|
|
$user = $this->createUser();
|
|
|
|
$client->loginUser($user);
|
|
$client->request('GET', '/admin/utilisateurs');
|
|
|
|
self::assertResponseStatusCodeSame(403);
|
|
}
|
|
|
|
public function testBuyersPageReturnsSuccessForRoot(): void
|
|
{
|
|
$client = static::createClient();
|
|
$user = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($user);
|
|
$client->request('GET', '/admin/acheteurs');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testBuyersSearchWithQuery(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$meilisearch = $this->createMock(MeilisearchService::class);
|
|
$meilisearch->expects(self::once())->method('search')->willReturn([
|
|
'hits' => [],
|
|
'estimatedTotalHits' => 0,
|
|
]);
|
|
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/acheteurs?q=test');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testSyncMeilisearchWithBuyers(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$buyer = new User();
|
|
$buyer->setEmail('test-sync-'.uniqid().'@example.com');
|
|
$buyer->setFirstName('Sync');
|
|
$buyer->setLastName('Test');
|
|
$buyer->setPassword('$2y$13$hashed');
|
|
$buyer->setIsVerified(true);
|
|
$em->persist($buyer);
|
|
$em->flush();
|
|
|
|
$meilisearch = $this->createMock(MeilisearchService::class);
|
|
$meilisearch->expects(self::exactly(2))->method('createIndexIfNotExists');
|
|
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/sync-meilisearch');
|
|
|
|
self::assertResponseRedirects('/admin');
|
|
}
|
|
|
|
public function testSyncMeilisearchWithOrganizers(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$orga = $this->createOrganizer($em);
|
|
$orga->setIsApproved(true);
|
|
$em->flush();
|
|
|
|
$meilisearch = $this->createMock(MeilisearchService::class);
|
|
$meilisearch->expects(self::exactly(2))->method('createIndexIfNotExists');
|
|
$meilisearch->expects(self::exactly(2))->method('addDocuments');
|
|
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/sync-meilisearch');
|
|
|
|
self::assertResponseRedirects('/admin');
|
|
}
|
|
|
|
public function testBuyersSearchWithMeilisearchError(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$meilisearch = $this->createMock(MeilisearchService::class);
|
|
$meilisearch->method('search')->willThrowException(new \RuntimeException('Meilisearch down'));
|
|
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/acheteurs?q=test');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testBuyersSearchWithResults(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$buyer = new User();
|
|
$buyer->setEmail('test-search-hit-'.uniqid().'@example.com');
|
|
$buyer->setFirstName('Found');
|
|
$buyer->setLastName('User');
|
|
$buyer->setPassword('$2y$13$hashed');
|
|
$buyer->setIsVerified(true);
|
|
$em->persist($buyer);
|
|
$em->flush();
|
|
|
|
$meilisearch = $this->createMock(MeilisearchService::class);
|
|
$meilisearch->method('search')->willReturn([
|
|
'hits' => [['id' => $buyer->getId()]],
|
|
'estimatedTotalHits' => 1,
|
|
]);
|
|
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/acheteurs?q=Found');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testCreateBuyerWithValidData(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$mailer = $this->createMock(MailerService::class);
|
|
$mailer->expects(self::once())->method('sendEmail');
|
|
static::getContainer()->set(MailerService::class, $mailer);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/acheteurs/creer', [
|
|
'first_name' => 'Nouveau',
|
|
'last_name' => 'Acheteur',
|
|
'email' => 'new-buyer-'.uniqid().'@example.com',
|
|
]);
|
|
|
|
self::assertResponseRedirects('/admin/acheteurs');
|
|
}
|
|
|
|
public function testCreateBuyerWithDuplicateEmail(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/acheteurs/creer', [
|
|
'first_name' => 'Dup',
|
|
'last_name' => 'Test',
|
|
'email' => $admin->getEmail(),
|
|
]);
|
|
|
|
self::assertResponseRedirects('/admin/acheteurs');
|
|
}
|
|
|
|
public function testResendVerificationEmail(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$buyer = new User();
|
|
$buyer->setEmail('test-buyer-'.uniqid().'@example.com');
|
|
$buyer->setFirstName('Buyer');
|
|
$buyer->setLastName('Test');
|
|
$buyer->setPassword('$2y$13$hashed');
|
|
$em->persist($buyer);
|
|
$em->flush();
|
|
|
|
$mailer = $this->createMock(MailerService::class);
|
|
$mailer->expects(self::once())->method('sendEmail');
|
|
static::getContainer()->set(MailerService::class, $mailer);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/acheteur/'.$buyer->getId().'/renvoyer-verification');
|
|
|
|
self::assertResponseRedirects('/admin/acheteurs');
|
|
|
|
$em->refresh($buyer);
|
|
self::assertNotNull($buyer->getEmailVerificationToken());
|
|
}
|
|
|
|
public function testResetPasswordSendsEmail(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$buyer = new User();
|
|
$buyer->setEmail('test-reset-admin-'.uniqid().'@example.com');
|
|
$buyer->setFirstName('Reset');
|
|
$buyer->setLastName('Test');
|
|
$buyer->setPassword('$2y$13$hashed');
|
|
$buyer->setIsVerified(true);
|
|
$em->persist($buyer);
|
|
$em->flush();
|
|
|
|
$mailer = $this->createMock(MailerService::class);
|
|
$mailer->expects(self::once())->method('sendEmail');
|
|
static::getContainer()->set(MailerService::class, $mailer);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/acheteur/'.$buyer->getId().'/reset-password');
|
|
|
|
self::assertResponseRedirects('/admin/acheteurs');
|
|
}
|
|
|
|
public function testDeleteBuyer(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$buyer = new User();
|
|
$buyer->setEmail('test-delete-'.uniqid().'@example.com');
|
|
$buyer->setFirstName('Delete');
|
|
$buyer->setLastName('Test');
|
|
$buyer->setPassword('$2y$13$hashed');
|
|
$em->persist($buyer);
|
|
$em->flush();
|
|
$buyerId = $buyer->getId();
|
|
|
|
$meilisearch = $this->createMock(MeilisearchService::class);
|
|
$meilisearch->expects(self::once())->method('deleteDocument')->with('buyers', $buyerId);
|
|
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/acheteur/'.$buyerId.'/supprimer');
|
|
|
|
self::assertResponseRedirects('/admin/acheteurs');
|
|
|
|
$deleted = $em->getRepository(User::class)->find($buyerId);
|
|
self::assertNull($deleted);
|
|
}
|
|
|
|
public function testDeleteBuyerMeilisearchFailureDoesNotBlock(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$buyer = new User();
|
|
$buyer->setEmail('test-delete-fail-'.uniqid().'@example.com');
|
|
$buyer->setFirstName('DeleteFail');
|
|
$buyer->setLastName('Test');
|
|
$buyer->setPassword('$2y$13$hashed');
|
|
$em->persist($buyer);
|
|
$em->flush();
|
|
$buyerId = $buyer->getId();
|
|
|
|
$meilisearch = $this->createMock(MeilisearchService::class);
|
|
$meilisearch->method('deleteDocument')->willThrowException(new \RuntimeException('Meilisearch down'));
|
|
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/acheteur/'.$buyerId.'/supprimer');
|
|
|
|
self::assertResponseRedirects('/admin/acheteurs');
|
|
}
|
|
|
|
public function testForceVerification(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$buyer = new User();
|
|
$buyer->setEmail('test-force-'.uniqid().'@example.com');
|
|
$buyer->setFirstName('Force');
|
|
$buyer->setLastName('Test');
|
|
$buyer->setPassword('$2y$13$hashed');
|
|
$em->persist($buyer);
|
|
$em->flush();
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/acheteur/'.$buyer->getId().'/forcer-verification');
|
|
|
|
self::assertResponseRedirects('/admin/acheteurs');
|
|
|
|
$em->refresh($buyer);
|
|
self::assertTrue($buyer->isVerified());
|
|
self::assertNotNull($buyer->getEmailVerifiedAt());
|
|
self::assertNull($buyer->getEmailVerificationToken());
|
|
}
|
|
|
|
public function testOrganizersSearchWithQuery(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$meilisearch = $this->createMock(MeilisearchService::class);
|
|
$meilisearch->expects(self::once())->method('search')->with('organizers')->willReturn([
|
|
'hits' => [],
|
|
'estimatedTotalHits' => 0,
|
|
]);
|
|
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/organisateurs?q=test');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testOrganizersSearchWithError(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$meilisearch = $this->createMock(MeilisearchService::class);
|
|
$meilisearch->method('search')->willThrowException(new \RuntimeException('Meilisearch down'));
|
|
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/organisateurs?q=test');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testOrganizersPagePendingTab(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/organisateurs');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testOrganizersPageApprovedTab(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/organisateurs?tab=approved');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testSiretCheckPage(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/organisateur/'.$orga->getId().'/siret');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testSiretCheckRedirectsIfApproved(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
$orga->setIsApproved(true);
|
|
$em->flush();
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/organisateur/'.$orga->getId().'/siret');
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs');
|
|
}
|
|
|
|
public function testSiretCheckWithoutSiret(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$orga = new User();
|
|
$orga->setEmail('test-no-siret-'.uniqid().'@example.com');
|
|
$orga->setFirstName('No');
|
|
$orga->setLastName('Siret');
|
|
$orga->setPassword('$2y$13$hashed');
|
|
$orga->setRoles(['ROLE_ORGANIZER']);
|
|
$em->persist($orga);
|
|
$em->flush();
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/organisateur/'.$orga->getId().'/siret');
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs');
|
|
}
|
|
|
|
public function testSiretRefresh(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateur/'.$orga->getId().'/siret/refresh');
|
|
|
|
self::assertResponseRedirects('/admin/organisateur/'.$orga->getId().'/siret');
|
|
}
|
|
|
|
public function testEditOrganizerPage(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
$orga->setIsApproved(true);
|
|
$orga->setOffer('free');
|
|
$orga->setCommissionRate(3.0);
|
|
$em->flush();
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/organisateur/'.$orga->getId().'/modifier');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testEditOrganizerSubmit(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
$orga->setIsApproved(true);
|
|
$orga->setOffer('free');
|
|
$orga->setCommissionRate(3.0);
|
|
$em->flush();
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateur/'.$orga->getId().'/modifier', [
|
|
'offer' => 'custom',
|
|
'commission_rate' => '0.5',
|
|
]);
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs?tab=approved');
|
|
|
|
$em->refresh($orga);
|
|
self::assertSame('custom', $orga->getOffer());
|
|
self::assertSame(0.5, $orga->getCommissionRate());
|
|
}
|
|
|
|
public function testEditOrganizerWithLogo(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
$orga->setIsApproved(true);
|
|
$orga->setOffer('basic');
|
|
$orga->setCommissionRate(3.0);
|
|
$em->flush();
|
|
|
|
$logo = new \Symfony\Component\HttpFoundation\File\UploadedFile(
|
|
__DIR__.'/../fixtures/logo.png',
|
|
'logo.png',
|
|
'image/png',
|
|
null,
|
|
true,
|
|
);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateur/'.$orga->getId().'/modifier', [
|
|
'first_name' => $orga->getFirstName(),
|
|
'last_name' => $orga->getLastName(),
|
|
'email' => $orga->getEmail(),
|
|
'company_name' => $orga->getCompanyName(),
|
|
'siret' => $orga->getSiret(),
|
|
'offer' => 'basic',
|
|
'commission_rate' => '3',
|
|
], ['logo' => $logo]);
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs?tab=approved');
|
|
|
|
$em->refresh($orga);
|
|
self::assertNotNull($orga->getLogoName());
|
|
}
|
|
|
|
public function testEditOrganizerRedirectsIfNotApproved(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/organisateur/'.$orga->getId().'/modifier');
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs');
|
|
}
|
|
|
|
public function testApproveOrganizer(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
|
|
$mailer = $this->createMock(MailerService::class);
|
|
$mailer->expects(self::once())->method('sendEmail');
|
|
static::getContainer()->set(MailerService::class, $mailer);
|
|
|
|
$meilisearch = $this->createMock(MeilisearchService::class);
|
|
$meilisearch->expects(self::once())->method('createIndexIfNotExists')->with('organizers');
|
|
$meilisearch->expects(self::once())->method('addDocuments');
|
|
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateur/'.$orga->getId().'/approuver', [
|
|
'offer' => 'basic',
|
|
'commission_rate' => '1.5',
|
|
]);
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs');
|
|
|
|
$em->refresh($orga);
|
|
self::assertTrue($orga->isApproved());
|
|
self::assertSame('basic', $orga->getOffer());
|
|
self::assertSame(1.5, $orga->getCommissionRate());
|
|
}
|
|
|
|
public function testRejectOrganizer(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
$orgaId = $orga->getId();
|
|
|
|
$mailer = $this->createMock(MailerService::class);
|
|
$mailer->expects(self::once())->method('sendEmail');
|
|
static::getContainer()->set(MailerService::class, $mailer);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateur/'.$orgaId.'/refuser', [
|
|
'reason' => 'SIRET invalide, activite non conforme.',
|
|
]);
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs');
|
|
|
|
$deleted = $em->getRepository(User::class)->find($orgaId);
|
|
self::assertNull($deleted);
|
|
}
|
|
|
|
/**
|
|
* @param list<string> $roles
|
|
*/
|
|
private function createUser(array $roles = []): User
|
|
{
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
|
|
$user = new User();
|
|
$user->setEmail('test-admin-'.uniqid().'@example.com');
|
|
$user->setFirstName('Admin');
|
|
$user->setLastName('User');
|
|
$user->setPassword('$2y$13$hashed');
|
|
$user->setRoles($roles);
|
|
|
|
$em->persist($user);
|
|
$em->flush();
|
|
|
|
return $user;
|
|
}
|
|
|
|
public function testEventsPageReturnsSuccess(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/evenements');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testEventsPageWithSearch(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/evenements?q=brocante');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testEventsPageDeniedForNonRoot(): void
|
|
{
|
|
$client = static::createClient();
|
|
$user = $this->createUser();
|
|
|
|
$client->loginUser($user);
|
|
$client->request('GET', '/admin/evenements');
|
|
|
|
self::assertResponseStatusCodeSame(403);
|
|
}
|
|
|
|
private function createOrganizer(EntityManagerInterface $em): User
|
|
{
|
|
$orga = new User();
|
|
$orga->setEmail('test-orga-'.uniqid().'@example.com');
|
|
$orga->setFirstName('Orga');
|
|
$orga->setLastName('Test');
|
|
$orga->setPassword('$2y$13$hashed');
|
|
$orga->setRoles(['ROLE_ORGANIZER']);
|
|
$orga->setIsVerified(true);
|
|
$orga->setCompanyName('Mon Asso');
|
|
$orga->setSiret('12345678901234');
|
|
|
|
$em->persist($orga);
|
|
$em->flush();
|
|
|
|
return $orga;
|
|
}
|
|
|
|
public function testSuspendOrganizer(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
$orga->setIsApproved(true);
|
|
$em->flush();
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateur/'.$orga->getId().'/suspendre');
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs?tab=approved');
|
|
|
|
$em->refresh($orga);
|
|
self::assertTrue($orga->isSuspended());
|
|
}
|
|
|
|
public function testReactivateOrganizer(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
$orga->setIsApproved(true);
|
|
$orga->setIsSuspended(true);
|
|
$em->flush();
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateur/'.$orga->getId().'/suspendre');
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs?tab=approved');
|
|
|
|
$em->refresh($orga);
|
|
self::assertNull($orga->isSuspended());
|
|
}
|
|
|
|
public function testOrdersPage(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/commandes');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testOrdersPageWithFilters(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/commandes?status=paid&q=test');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testLogsPage(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/logs');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testInfraPage(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/infra');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testInfraPageDeniedForNonRoot(): void
|
|
{
|
|
$client = static::createClient();
|
|
$user = $this->createUser();
|
|
|
|
$client->loginUser($user);
|
|
$client->request('GET', '/admin/infra');
|
|
|
|
self::assertResponseStatusCodeSame(403);
|
|
}
|
|
|
|
public function testInviteOrganizerPage(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$mailer = $this->createMock(MailerService::class);
|
|
static::getContainer()->set(MailerService::class, $mailer);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/organisateurs/inviter');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
}
|
|
|
|
public function testInviteOrganizerSubmit(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$mailer = $this->createMock(MailerService::class);
|
|
$mailer->expects(self::once())->method('sendEmail');
|
|
static::getContainer()->set(MailerService::class, $mailer);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateurs/inviter', [
|
|
'company_name' => 'New Asso',
|
|
'first_name' => 'Jean',
|
|
'last_name' => 'Invite',
|
|
'email' => 'invite-admin-'.uniqid().'@example.com',
|
|
'offer' => 'basic',
|
|
'commission_rate' => '2.5',
|
|
]);
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs/inviter');
|
|
}
|
|
|
|
public function testInviteOrganizerEmptyFields(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateurs/inviter', [
|
|
'company_name' => '',
|
|
'first_name' => '',
|
|
'last_name' => '',
|
|
'email' => '',
|
|
]);
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs/inviter');
|
|
}
|
|
|
|
public function testDeleteInvitation(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$invitation = new \App\Entity\OrganizerInvitation();
|
|
$invitation->setCompanyName('Del Asso');
|
|
$invitation->setFirstName('Del');
|
|
$invitation->setLastName('Test');
|
|
$invitation->setEmail('del-'.uniqid().'@example.com');
|
|
$em->persist($invitation);
|
|
$em->flush();
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateurs/invitation/'.$invitation->getId().'/supprimer');
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs/inviter');
|
|
}
|
|
|
|
public function testResendInvitation(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$mailer = $this->createMock(MailerService::class);
|
|
$mailer->expects(self::once())->method('sendEmail');
|
|
static::getContainer()->set(MailerService::class, $mailer);
|
|
|
|
$invitation = new \App\Entity\OrganizerInvitation();
|
|
$invitation->setCompanyName('Resend Asso');
|
|
$invitation->setFirstName('Resend');
|
|
$invitation->setLastName('Test');
|
|
$invitation->setEmail('resend-'.uniqid().'@example.com');
|
|
$invitation->setStatus(\App\Entity\OrganizerInvitation::STATUS_ACCEPTED);
|
|
$em->persist($invitation);
|
|
$em->flush();
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateurs/invitation/'.$invitation->getId().'/renvoyer');
|
|
|
|
self::assertResponseRedirects('/admin/organisateurs/inviter');
|
|
|
|
$freshEm = static::getContainer()->get(EntityManagerInterface::class);
|
|
$updated = $freshEm->getRepository(\App\Entity\OrganizerInvitation::class)->find($invitation->getId());
|
|
self::assertSame(\App\Entity\OrganizerInvitation::STATUS_SENT, $updated->getStatus());
|
|
}
|
|
|
|
public function testDeleteInvitationNotFound(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateurs/invitation/999999/supprimer');
|
|
|
|
self::assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
public function testResendInvitationNotFound(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/organisateurs/invitation/999999/renvoyer');
|
|
|
|
self::assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
public function testExportCsv(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/export/2026/3');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
self::assertStringContainsString('text/csv', $client->getResponse()->headers->get('Content-Type'));
|
|
}
|
|
|
|
public function testExportPdf(): void
|
|
{
|
|
$client = static::createClient();
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('GET', '/admin/export/2026/3/pdf');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
self::assertStringContainsString('application/pdf', $client->getResponse()->headers->get('Content-Type'));
|
|
}
|
|
|
|
private function createEvent(EntityManagerInterface $em, User $organizer): Event
|
|
{
|
|
$event = new Event();
|
|
$event->setAccount($organizer);
|
|
$event->setTitle('Test Event '.uniqid());
|
|
$event->setStartAt(new \DateTimeImmutable('2026-08-01 10:00'));
|
|
$event->setEndAt(new \DateTimeImmutable('2026-08-01 18:00'));
|
|
$event->setAddress('1 rue de la Paix');
|
|
$event->setZipcode('75001');
|
|
$event->setCity('Paris');
|
|
|
|
$em->persist($event);
|
|
$em->flush();
|
|
|
|
return $event;
|
|
}
|
|
|
|
public function testToggleEventOnline(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
$event = $this->createEvent($em, $orga);
|
|
|
|
$eventIndex = $this->createMock(EventIndexService::class);
|
|
$eventIndex->expects(self::once())->method('indexEvent');
|
|
static::getContainer()->set(EventIndexService::class, $eventIndex);
|
|
|
|
self::assertFalse($event->isOnline());
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/evenement/'.$event->getId().'/en-ligne');
|
|
|
|
self::assertResponseRedirects('/admin/evenements');
|
|
|
|
$em->refresh($event);
|
|
self::assertTrue($event->isOnline());
|
|
}
|
|
|
|
public function testToggleEventOffline(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
$event = $this->createEvent($em, $orga);
|
|
$event->setIsOnline(true);
|
|
$em->flush();
|
|
|
|
$eventIndex = $this->createMock(EventIndexService::class);
|
|
$eventIndex->expects(self::once())->method('indexEvent');
|
|
static::getContainer()->set(EventIndexService::class, $eventIndex);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/evenement/'.$event->getId().'/en-ligne');
|
|
|
|
self::assertResponseRedirects('/admin/evenements');
|
|
|
|
$em->refresh($event);
|
|
self::assertFalse($event->isOnline());
|
|
}
|
|
|
|
public function testDeleteEvent(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$admin = $this->createUser(['ROLE_ROOT']);
|
|
$orga = $this->createOrganizer($em);
|
|
$event = $this->createEvent($em, $orga);
|
|
$eventId = $event->getId();
|
|
|
|
$eventIndex = $this->createMock(EventIndexService::class);
|
|
$eventIndex->expects(self::once())->method('removeEvent');
|
|
static::getContainer()->set(EventIndexService::class, $eventIndex);
|
|
|
|
$client->loginUser($admin);
|
|
$client->request('POST', '/admin/evenement/'.$eventId.'/supprimer');
|
|
|
|
self::assertResponseRedirects('/admin/evenements');
|
|
|
|
$deleted = $em->getRepository(Event::class)->find($eventId);
|
|
self::assertNull($deleted);
|
|
}
|
|
|
|
public function testToggleEventOnlineDeniedForNonRoot(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createUser();
|
|
$orga = $this->createOrganizer($em);
|
|
$event = $this->createEvent($em, $orga);
|
|
|
|
$client->loginUser($user);
|
|
$client->request('POST', '/admin/evenement/'.$event->getId().'/en-ligne');
|
|
|
|
self::assertResponseStatusCodeSame(403);
|
|
}
|
|
|
|
public function testDeleteEventDeniedForNonRoot(): void
|
|
{
|
|
$client = static::createClient();
|
|
$em = static::getContainer()->get(EntityManagerInterface::class);
|
|
$user = $this->createUser();
|
|
$orga = $this->createOrganizer($em);
|
|
$event = $this->createEvent($em, $orga);
|
|
|
|
$client->loginUser($user);
|
|
$client->request('POST', '/admin/evenement/'.$event->getId().'/supprimer');
|
|
|
|
self::assertResponseStatusCodeSame(403);
|
|
}
|
|
}
|