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; } }