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é).
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Administration\Application\Command\AssignRole;
|
||||
|
||||
use App\Administration\Application\Command\AssignRole\AssignRoleCommand;
|
||||
use App\Administration\Application\Command\AssignRole\AssignRoleHandler;
|
||||
use App\Administration\Domain\Exception\RoleDejaAttribueException;
|
||||
use App\Administration\Domain\Exception\UserNotFoundException;
|
||||
use App\Administration\Domain\Model\User\Email;
|
||||
use App\Administration\Domain\Model\User\Role;
|
||||
use App\Administration\Domain\Model\User\User;
|
||||
use App\Administration\Infrastructure\Persistence\InMemory\InMemoryUserRepository;
|
||||
use App\Shared\Domain\Clock;
|
||||
use App\Shared\Domain\Tenant\TenantId;
|
||||
use DateTimeImmutable;
|
||||
use InvalidArgumentException;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class AssignRoleHandlerTest extends TestCase
|
||||
{
|
||||
private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440002';
|
||||
private const string SCHOOL_NAME = 'École Alpha';
|
||||
|
||||
private InMemoryUserRepository $userRepository;
|
||||
private Clock $clock;
|
||||
private AssignRoleHandler $handler;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->userRepository = new InMemoryUserRepository();
|
||||
$this->clock = new class implements Clock {
|
||||
public function now(): DateTimeImmutable
|
||||
{
|
||||
return new DateTimeImmutable('2026-02-07 10:00:00');
|
||||
}
|
||||
};
|
||||
$this->handler = new AssignRoleHandler($this->userRepository, $this->clock);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function assignsRoleSuccessfully(): void
|
||||
{
|
||||
$user = $this->createAndSaveUser(Role::PROF);
|
||||
|
||||
$command = new AssignRoleCommand(
|
||||
userId: (string) $user->id,
|
||||
role: Role::VIE_SCOLAIRE->value,
|
||||
);
|
||||
|
||||
$result = ($this->handler)($command);
|
||||
|
||||
self::assertTrue($result->aLeRole(Role::PROF));
|
||||
self::assertTrue($result->aLeRole(Role::VIE_SCOLAIRE));
|
||||
self::assertCount(2, $result->roles);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function savesUserAfterAssignment(): void
|
||||
{
|
||||
$user = $this->createAndSaveUser(Role::PROF);
|
||||
|
||||
$command = new AssignRoleCommand(
|
||||
userId: (string) $user->id,
|
||||
role: Role::ADMIN->value,
|
||||
);
|
||||
|
||||
($this->handler)($command);
|
||||
|
||||
$found = $this->userRepository->get($user->id);
|
||||
self::assertTrue($found->aLeRole(Role::ADMIN));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function throwsWhenRoleAlreadyAssigned(): void
|
||||
{
|
||||
$user = $this->createAndSaveUser(Role::PROF);
|
||||
|
||||
$command = new AssignRoleCommand(
|
||||
userId: (string) $user->id,
|
||||
role: Role::PROF->value,
|
||||
);
|
||||
|
||||
$this->expectException(RoleDejaAttribueException::class);
|
||||
|
||||
($this->handler)($command);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function throwsWhenUserNotFound(): void
|
||||
{
|
||||
$command = new AssignRoleCommand(
|
||||
userId: '550e8400-e29b-41d4-a716-446655440099',
|
||||
role: Role::PROF->value,
|
||||
);
|
||||
|
||||
$this->expectException(UserNotFoundException::class);
|
||||
|
||||
($this->handler)($command);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function throwsWhenRoleIsInvalid(): void
|
||||
{
|
||||
$user = $this->createAndSaveUser(Role::PROF);
|
||||
|
||||
$command = new AssignRoleCommand(
|
||||
userId: (string) $user->id,
|
||||
role: 'ROLE_INEXISTANT',
|
||||
);
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Rôle invalide');
|
||||
|
||||
($this->handler)($command);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function throwsWhenTenantIdDoesNotMatch(): void
|
||||
{
|
||||
$user = $this->createAndSaveUser(Role::PROF);
|
||||
|
||||
$command = new AssignRoleCommand(
|
||||
userId: (string) $user->id,
|
||||
role: Role::ADMIN->value,
|
||||
tenantId: '550e8400-e29b-41d4-a716-446655440099',
|
||||
);
|
||||
|
||||
$this->expectException(UserNotFoundException::class);
|
||||
|
||||
($this->handler)($command);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function allowsAssignmentWhenTenantIdMatches(): void
|
||||
{
|
||||
$user = $this->createAndSaveUser(Role::PROF);
|
||||
|
||||
$command = new AssignRoleCommand(
|
||||
userId: (string) $user->id,
|
||||
role: Role::ADMIN->value,
|
||||
tenantId: self::TENANT_ID,
|
||||
);
|
||||
|
||||
$result = ($this->handler)($command);
|
||||
|
||||
self::assertTrue($result->aLeRole(Role::ADMIN));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function allowsAssignmentWhenTenantIdIsEmpty(): void
|
||||
{
|
||||
$user = $this->createAndSaveUser(Role::PROF);
|
||||
|
||||
$command = new AssignRoleCommand(
|
||||
userId: (string) $user->id,
|
||||
role: Role::SECRETARIAT->value,
|
||||
tenantId: '',
|
||||
);
|
||||
|
||||
$result = ($this->handler)($command);
|
||||
|
||||
self::assertTrue($result->aLeRole(Role::SECRETARIAT));
|
||||
}
|
||||
|
||||
private function createAndSaveUser(Role $role): User
|
||||
{
|
||||
$user = User::inviter(
|
||||
email: new Email('user@example.com'),
|
||||
role: $role,
|
||||
tenantId: TenantId::fromString(self::TENANT_ID),
|
||||
schoolName: self::SCHOOL_NAME,
|
||||
firstName: 'Jean',
|
||||
lastName: 'Dupont',
|
||||
invitedAt: new DateTimeImmutable('2026-02-01 10:00:00'),
|
||||
);
|
||||
$user->pullDomainEvents();
|
||||
$this->userRepository->save($user);
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user