Files
Classeo/backend/tests/Unit/SuperAdmin/Domain/Model/Establishment/EstablishmentTest.php
Mathias STRASSER 3575d095a1
Some checks failed
CI / Backend Tests (push) Has been cancelled
CI / Frontend Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Naming Conventions (push) Has been cancelled
CI / Build Check (push) Has been cancelled
feat: Provisionner automatiquement un nouvel établissement
Lorsqu'un super-admin crée un établissement via l'interface, le système
doit automatiquement créer la base tenant, exécuter les migrations,
créer le premier utilisateur admin et envoyer l'invitation — le tout
de manière asynchrone pour ne pas bloquer la réponse HTTP.

Ce mécanisme rend chaque établissement opérationnel dès sa création
sans intervention manuelle sur l'infrastructure.
2026-04-11 20:41:55 +02:00

163 lines
6.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Unit\SuperAdmin\Domain\Model\Establishment;
use App\Shared\Domain\Tenant\TenantId;
use App\SuperAdmin\Domain\Event\EtablissementCree;
use App\SuperAdmin\Domain\Event\EtablissementDesactive;
use App\SuperAdmin\Domain\Exception\EstablishmentDejaInactifException;
use App\SuperAdmin\Domain\Model\Establishment\Establishment;
use App\SuperAdmin\Domain\Model\Establishment\EstablishmentId;
use App\SuperAdmin\Domain\Model\Establishment\EstablishmentStatus;
use App\SuperAdmin\Domain\Model\SuperAdmin\SuperAdminId;
use DateTimeImmutable;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
final class EstablishmentTest extends TestCase
{
private const string SUPER_ADMIN_ID = '550e8400-e29b-41d4-a716-446655440001';
private const string ESTABLISHMENT_NAME = 'École Alpha';
private const string SUBDOMAIN = 'ecole-alpha';
#[Test]
public function creerCreatesProvisioningEstablishment(): void
{
$establishment = $this->createEstablishment();
self::assertSame(EstablishmentStatus::PROVISIONING, $establishment->status);
self::assertSame(self::ESTABLISHMENT_NAME, $establishment->name);
self::assertSame(self::SUBDOMAIN, $establishment->subdomain);
self::assertNull($establishment->lastActivityAt);
self::assertNotEmpty($establishment->databaseName);
self::assertStringStartsWith('classeo_tenant_', $establishment->databaseName);
}
#[Test]
public function creerRecordsEtablissementCreeEvent(): void
{
$establishment = $this->createEstablishment();
$events = $establishment->pullDomainEvents();
self::assertCount(1, $events);
self::assertInstanceOf(EtablissementCree::class, $events[0]);
self::assertTrue($establishment->id->equals($events[0]->establishmentId));
self::assertTrue($establishment->tenantId->equals($events[0]->tenantId));
self::assertSame(self::ESTABLISHMENT_NAME, $events[0]->name);
self::assertSame(self::SUBDOMAIN, $events[0]->subdomain);
}
#[Test]
public function creerGeneratesTenantIdAndDatabaseName(): void
{
$establishment = $this->createEstablishment();
self::assertInstanceOf(TenantId::class, $establishment->tenantId);
self::assertStringStartsWith('classeo_tenant_', $establishment->databaseName);
}
#[Test]
public function activerChangesStatusToActif(): void
{
$establishment = $this->createEstablishment();
self::assertSame(EstablishmentStatus::PROVISIONING, $establishment->status);
$establishment->activer();
self::assertSame(EstablishmentStatus::ACTIF, $establishment->status);
}
#[Test]
public function desactiverChangesStatusToInactif(): void
{
$establishment = $this->createEstablishment();
$establishment->activer();
$establishment->desactiver(new DateTimeImmutable('2026-02-16 12:00:00'));
self::assertSame(EstablishmentStatus::INACTIF, $establishment->status);
}
#[Test]
public function desactiverRecordsEtablissementDesactiveEvent(): void
{
$establishment = $this->createEstablishment();
$establishment->activer();
$establishment->pullDomainEvents(); // Clear creation event
$establishment->desactiver(new DateTimeImmutable('2026-02-16 12:00:00'));
$events = $establishment->pullDomainEvents();
self::assertCount(1, $events);
self::assertInstanceOf(EtablissementDesactive::class, $events[0]);
}
#[Test]
public function desactiverThrowsWhenAlreadyInactive(): void
{
$establishment = $this->createEstablishment();
$establishment->activer();
$establishment->desactiver(new DateTimeImmutable('2026-02-16 12:00:00'));
$this->expectException(EstablishmentDejaInactifException::class);
$establishment->desactiver(new DateTimeImmutable('2026-02-16 13:00:00'));
}
#[Test]
public function enregistrerActiviteUpdatesLastActivityAt(): void
{
$establishment = $this->createEstablishment();
$activityAt = new DateTimeImmutable('2026-02-16 15:00:00');
$establishment->enregistrerActivite($activityAt);
self::assertEquals($activityAt, $establishment->lastActivityAt);
}
#[Test]
public function reconstituteRestoresAllProperties(): void
{
$id = EstablishmentId::generate();
$tenantId = TenantId::generate();
$createdBy = SuperAdminId::fromString(self::SUPER_ADMIN_ID);
$createdAt = new DateTimeImmutable('2026-01-01 10:00:00');
$lastActivityAt = new DateTimeImmutable('2026-02-16 14:30:00');
$establishment = Establishment::reconstitute(
id: $id,
tenantId: $tenantId,
name: self::ESTABLISHMENT_NAME,
subdomain: self::SUBDOMAIN,
databaseName: 'classeo_tenant_abc123',
status: EstablishmentStatus::ACTIF,
createdAt: $createdAt,
createdBy: $createdBy,
lastActivityAt: $lastActivityAt,
);
self::assertTrue($id->equals($establishment->id));
self::assertTrue($tenantId->equals($establishment->tenantId));
self::assertSame(self::ESTABLISHMENT_NAME, $establishment->name);
self::assertSame(self::SUBDOMAIN, $establishment->subdomain);
self::assertSame('classeo_tenant_abc123', $establishment->databaseName);
self::assertSame(EstablishmentStatus::ACTIF, $establishment->status);
self::assertEquals($createdAt, $establishment->createdAt);
self::assertTrue($createdBy->equals($establishment->createdBy));
self::assertEquals($lastActivityAt, $establishment->lastActivityAt);
self::assertEmpty($establishment->pullDomainEvents());
}
private function createEstablishment(): Establishment
{
return Establishment::creer(
name: self::ESTABLISHMENT_NAME,
subdomain: self::SUBDOMAIN,
adminEmail: 'admin@ecole-alpha.fr',
createdBy: SuperAdminId::fromString(self::SUPER_ADMIN_ID),
createdAt: new DateTimeImmutable('2026-02-16 10:00:00'),
);
}
}