Files
Classeo/backend/tests/Unit/Administration/Domain/Model/StudentGuardian/StudentGuardianTest.php
Mathias STRASSER 44ebe5e511 feat: Liaison parents-enfants avec gestion des tuteurs
Les parents doivent pouvoir suivre la scolarité de leurs enfants (notes,
emploi du temps, devoirs). Cela nécessite un lien formalisé entre le
compte parent et le compte élève, géré par les administrateurs.

Le lien est établi soit manuellement via l'interface d'administration,
soit automatiquement lors de l'activation du compte parent lorsque
l'invitation inclut un élève cible. Ce lien conditionne l'accès aux
données scolaires de l'enfant (autorisations vérifiées par un voter
dédié).
2026-02-12 08:38:19 +01:00

175 lines
6.5 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Unit\Administration\Domain\Model\StudentGuardian;
use App\Administration\Domain\Event\ParentDelieDEleve;
use App\Administration\Domain\Event\ParentLieAEleve;
use App\Administration\Domain\Model\StudentGuardian\RelationshipType;
use App\Administration\Domain\Model\StudentGuardian\StudentGuardian;
use App\Administration\Domain\Model\StudentGuardian\StudentGuardianId;
use App\Administration\Domain\Model\User\UserId;
use App\Shared\Domain\Tenant\TenantId;
use DateTimeImmutable;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
final class StudentGuardianTest extends TestCase
{
private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440001';
private const string STUDENT_ID = '550e8400-e29b-41d4-a716-446655440002';
private const string GUARDIAN_ID = '550e8400-e29b-41d4-a716-446655440003';
private const string CREATED_BY_ID = '550e8400-e29b-41d4-a716-446655440004';
#[Test]
public function lierCreatesLinkWithAllProperties(): void
{
$studentId = UserId::fromString(self::STUDENT_ID);
$guardianId = UserId::fromString(self::GUARDIAN_ID);
$tenantId = TenantId::fromString(self::TENANT_ID);
$createdBy = UserId::fromString(self::CREATED_BY_ID);
$createdAt = new DateTimeImmutable('2026-02-10 10:00:00');
$link = StudentGuardian::lier(
studentId: $studentId,
guardianId: $guardianId,
relationshipType: RelationshipType::FATHER,
tenantId: $tenantId,
createdAt: $createdAt,
createdBy: $createdBy,
);
self::assertTrue($link->studentId->equals($studentId));
self::assertTrue($link->guardianId->equals($guardianId));
self::assertSame(RelationshipType::FATHER, $link->relationshipType);
self::assertTrue($link->tenantId->equals($tenantId));
self::assertEquals($createdAt, $link->createdAt);
self::assertNotNull($link->createdBy);
self::assertTrue($link->createdBy->equals($createdBy));
}
#[Test]
public function lierRecordsParentLieAEleveEvent(): void
{
$link = $this->createLink();
$events = $link->pullDomainEvents();
self::assertCount(1, $events);
self::assertInstanceOf(ParentLieAEleve::class, $events[0]);
self::assertTrue($events[0]->linkId->equals($link->id));
self::assertTrue($events[0]->studentId->equals($link->studentId));
self::assertTrue($events[0]->guardianId->equals($link->guardianId));
self::assertSame(RelationshipType::FATHER, $events[0]->relationshipType);
self::assertTrue($events[0]->tenantId->equals($link->tenantId));
}
#[Test]
public function lierWithoutCreatedByAllowsNull(): void
{
$link = StudentGuardian::lier(
studentId: UserId::fromString(self::STUDENT_ID),
guardianId: UserId::fromString(self::GUARDIAN_ID),
relationshipType: RelationshipType::MOTHER,
tenantId: TenantId::fromString(self::TENANT_ID),
createdAt: new DateTimeImmutable(),
);
self::assertNull($link->createdBy);
}
#[Test]
public function lierGeneratesUniqueId(): void
{
$link1 = $this->createLink();
$link2 = $this->createLink();
self::assertFalse($link1->id->equals($link2->id));
}
#[Test]
public function reconstituteRestoresAllProperties(): void
{
$id = StudentGuardianId::generate();
$studentId = UserId::fromString(self::STUDENT_ID);
$guardianId = UserId::fromString(self::GUARDIAN_ID);
$tenantId = TenantId::fromString(self::TENANT_ID);
$createdBy = UserId::fromString(self::CREATED_BY_ID);
$createdAt = new DateTimeImmutable('2026-02-10 10:00:00');
$link = StudentGuardian::reconstitute(
id: $id,
studentId: $studentId,
guardianId: $guardianId,
relationshipType: RelationshipType::TUTOR_M,
tenantId: $tenantId,
createdAt: $createdAt,
createdBy: $createdBy,
);
self::assertTrue($link->id->equals($id));
self::assertTrue($link->studentId->equals($studentId));
self::assertTrue($link->guardianId->equals($guardianId));
self::assertSame(RelationshipType::TUTOR_M, $link->relationshipType);
self::assertTrue($link->tenantId->equals($tenantId));
self::assertEquals($createdAt, $link->createdAt);
self::assertNotNull($link->createdBy);
self::assertTrue($link->createdBy->equals($createdBy));
self::assertEmpty($link->pullDomainEvents());
}
#[Test]
public function reconstituteWithNullCreatedBy(): void
{
$link = StudentGuardian::reconstitute(
id: StudentGuardianId::generate(),
studentId: UserId::fromString(self::STUDENT_ID),
guardianId: UserId::fromString(self::GUARDIAN_ID),
relationshipType: RelationshipType::OTHER,
tenantId: TenantId::fromString(self::TENANT_ID),
createdAt: new DateTimeImmutable(),
createdBy: null,
);
self::assertNull($link->createdBy);
}
#[Test]
public function delierRecordsParentDelieDEleveEvent(): void
{
$link = $this->createLink();
$link->pullDomainEvents(); // Drain lier() events
$at = new DateTimeImmutable('2026-02-10 12:00:00');
$link->delier($at);
$events = $link->pullDomainEvents();
self::assertCount(1, $events);
self::assertInstanceOf(ParentDelieDEleve::class, $events[0]);
self::assertTrue($events[0]->linkId->equals($link->id));
self::assertTrue($events[0]->studentId->equals($link->studentId));
self::assertTrue($events[0]->guardianId->equals($link->guardianId));
self::assertTrue($events[0]->tenantId->equals($link->tenantId));
self::assertEquals($at, $events[0]->occurredOn());
}
#[Test]
public function maxGuardiansPerStudentIsTwo(): void
{
self::assertSame(2, StudentGuardian::MAX_GUARDIANS_PER_STUDENT);
}
private function createLink(): StudentGuardian
{
return StudentGuardian::lier(
studentId: UserId::fromString(self::STUDENT_ID),
guardianId: UserId::fromString(self::GUARDIAN_ID),
relationshipType: RelationshipType::FATHER,
tenantId: TenantId::fromString(self::TENANT_ID),
createdAt: new DateTimeImmutable('2026-02-10 10:00:00'),
createdBy: UserId::fromString(self::CREATED_BY_ID),
);
}
}