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.
107 lines
3.4 KiB
PHP
107 lines
3.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Unit\Scolarite\Application\Query\GetTeacherStatisticsOverview;
|
|
|
|
use App\Scolarite\Application\Port\PeriodFinder;
|
|
use App\Scolarite\Application\Port\PeriodInfo;
|
|
use App\Scolarite\Application\Query\GetTeacherStatisticsOverview\GetTeacherStatisticsOverviewHandler;
|
|
use App\Scolarite\Application\Query\GetTeacherStatisticsOverview\GetTeacherStatisticsOverviewQuery;
|
|
use App\Scolarite\Infrastructure\ReadModel\InMemoryTeacherStatisticsReader;
|
|
use App\Shared\Domain\Tenant\TenantId;
|
|
use DateTimeImmutable;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class GetTeacherStatisticsOverviewHandlerTest extends TestCase
|
|
{
|
|
private const string TEACHER_ID = '550e8400-e29b-41d4-a716-446655440010';
|
|
private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440001';
|
|
|
|
private InMemoryTeacherStatisticsReader $reader;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->reader = new InMemoryTeacherStatisticsReader();
|
|
}
|
|
|
|
#[Test]
|
|
public function itReturnsEmptyWhenNoPeriodFound(): void
|
|
{
|
|
$handler = $this->createHandler(periodInfo: null);
|
|
|
|
$result = $handler(new GetTeacherStatisticsOverviewQuery(
|
|
teacherId: self::TEACHER_ID,
|
|
tenantId: self::TENANT_ID,
|
|
));
|
|
|
|
self::assertSame([], $result);
|
|
}
|
|
|
|
#[Test]
|
|
public function itReturnsClassOverviewDtos(): void
|
|
{
|
|
$this->reader->feedClassesSummary([
|
|
[
|
|
'classId' => 'class-1',
|
|
'className' => '6ème A',
|
|
'subjectId' => 'subject-1',
|
|
'subjectName' => 'Mathématiques',
|
|
'evaluationCount' => 3,
|
|
'studentCount' => 25,
|
|
'average' => 12.5,
|
|
'successRate' => 72.0,
|
|
],
|
|
[
|
|
'classId' => 'class-2',
|
|
'className' => '5ème B',
|
|
'subjectId' => 'subject-1',
|
|
'subjectName' => 'Mathématiques',
|
|
'evaluationCount' => 2,
|
|
'studentCount' => 28,
|
|
'average' => 10.8,
|
|
'successRate' => 57.0,
|
|
],
|
|
]);
|
|
|
|
$handler = $this->createHandler(periodInfo: $this->currentPeriod());
|
|
|
|
$result = $handler(new GetTeacherStatisticsOverviewQuery(
|
|
teacherId: self::TEACHER_ID,
|
|
tenantId: self::TENANT_ID,
|
|
));
|
|
|
|
self::assertCount(2, $result);
|
|
self::assertSame('6ème A', $result[0]->className);
|
|
self::assertSame(12.5, $result[0]->average);
|
|
self::assertSame(72.0, $result[0]->successRate);
|
|
self::assertSame('5ème B', $result[1]->className);
|
|
}
|
|
|
|
private function createHandler(?PeriodInfo $periodInfo): GetTeacherStatisticsOverviewHandler
|
|
{
|
|
$periodFinder = new class($periodInfo) implements PeriodFinder {
|
|
public function __construct(private readonly ?PeriodInfo $info)
|
|
{
|
|
}
|
|
|
|
public function findForDate(DateTimeImmutable $date, TenantId $tenantId): ?PeriodInfo
|
|
{
|
|
return $this->info;
|
|
}
|
|
};
|
|
|
|
return new GetTeacherStatisticsOverviewHandler($this->reader, $periodFinder);
|
|
}
|
|
|
|
private function currentPeriod(): PeriodInfo
|
|
{
|
|
return new PeriodInfo(
|
|
periodId: 'period-1',
|
|
startDate: new DateTimeImmutable('2026-01-05'),
|
|
endDate: new DateTimeImmutable('2026-03-31'),
|
|
);
|
|
}
|
|
}
|