Une application SaaS éducative nécessite une séparation stricte des données entre établissements scolaires. L'architecture multi-tenant par sous-domaine (ecole-alpha.classeo.local) permet cette isolation tout en utilisant une base de code unique. Le choix d'une résolution basée sur les sous-domaines plutôt que sur des headers ou tokens facilite le routage au niveau infrastructure (reverse proxy) et offre une UX plus naturelle où chaque école accède à "son" URL dédiée.
91 lines
2.6 KiB
PHP
91 lines
2.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Unit\Shared\Infrastructure\Tenant;
|
|
|
|
use App\Shared\Infrastructure\Tenant\TenantConfig;
|
|
use App\Shared\Infrastructure\Tenant\TenantContext;
|
|
use App\Shared\Infrastructure\Tenant\TenantId;
|
|
use App\Shared\Infrastructure\Tenant\TenantNotSetException;
|
|
use PHPUnit\Framework\Attributes\CoversClass;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
#[CoversClass(TenantContext::class)]
|
|
final class TenantContextTest extends TestCase
|
|
{
|
|
#[Test]
|
|
public function itCanSetAndRetrieveCurrentTenant(): void
|
|
{
|
|
$tenantId = TenantId::fromString('a1b2c3d4-e5f6-7890-abcd-ef1234567890');
|
|
$config = new TenantConfig(
|
|
tenantId: $tenantId,
|
|
subdomain: 'ecole-alpha',
|
|
databaseUrl: 'postgresql://user:pass@localhost:5432/classeo_alpha',
|
|
);
|
|
|
|
$context = new TenantContext();
|
|
$context->setCurrentTenant($config);
|
|
|
|
self::assertTrue($tenantId->equals($context->getCurrentTenantId()));
|
|
self::assertSame($config, $context->getCurrentTenantConfig());
|
|
}
|
|
|
|
#[Test]
|
|
public function itThrowsExceptionWhenNoTenantIsSet(): void
|
|
{
|
|
$context = new TenantContext();
|
|
|
|
$this->expectException(TenantNotSetException::class);
|
|
|
|
$context->getCurrentTenantId();
|
|
}
|
|
|
|
#[Test]
|
|
public function itThrowsExceptionWhenGettingConfigWithNoTenantSet(): void
|
|
{
|
|
$context = new TenantContext();
|
|
|
|
$this->expectException(TenantNotSetException::class);
|
|
|
|
$context->getCurrentTenantConfig();
|
|
}
|
|
|
|
#[Test]
|
|
public function itCanCheckIfTenantIsSet(): void
|
|
{
|
|
$context = new TenantContext();
|
|
|
|
self::assertFalse($context->hasTenant());
|
|
|
|
$config = new TenantConfig(
|
|
tenantId: TenantId::fromString('a1b2c3d4-e5f6-7890-abcd-ef1234567890'),
|
|
subdomain: 'ecole-alpha',
|
|
databaseUrl: 'postgresql://user:pass@localhost:5432/classeo_alpha',
|
|
);
|
|
$context->setCurrentTenant($config);
|
|
|
|
self::assertTrue($context->hasTenant());
|
|
}
|
|
|
|
#[Test]
|
|
public function itCanClearTenant(): void
|
|
{
|
|
$config = new TenantConfig(
|
|
tenantId: TenantId::fromString('a1b2c3d4-e5f6-7890-abcd-ef1234567890'),
|
|
subdomain: 'ecole-alpha',
|
|
databaseUrl: 'postgresql://user:pass@localhost:5432/classeo_alpha',
|
|
);
|
|
|
|
$context = new TenantContext();
|
|
$context->setCurrentTenant($config);
|
|
|
|
self::assertTrue($context->hasTenant());
|
|
|
|
$context->clear();
|
|
|
|
self::assertFalse($context->hasTenant());
|
|
}
|
|
}
|