evaluationRepository = new InMemoryEvaluationRepository(); $this->clock = new class implements Clock { public function now(): DateTimeImmutable { return new DateTimeImmutable('2026-03-12 10:00:00'); } }; } #[Test] public function itCreatesEvaluationSuccessfully(): void { $handler = $this->createHandler(affecte: true); $command = $this->createCommand(); $evaluation = $handler($command); self::assertNotEmpty((string) $evaluation->id); self::assertSame(EvaluationStatus::PUBLISHED, $evaluation->status); self::assertSame('Contrôle chapitre 5', $evaluation->title); self::assertSame(20, $evaluation->gradeScale->maxValue); self::assertSame(1.0, $evaluation->coefficient->value); } #[Test] public function itPersistsEvaluationInRepository(): void { $handler = $this->createHandler(affecte: true); $command = $this->createCommand(); $created = $handler($command); $evaluation = $this->evaluationRepository->get( EvaluationId::fromString((string) $created->id), TenantId::fromString(self::TENANT_ID), ); self::assertSame('Contrôle chapitre 5', $evaluation->title); } #[Test] public function itThrowsWhenTeacherNotAffected(): void { $handler = $this->createHandler(affecte: false); $this->expectException(EnseignantNonAffecteException::class); $handler($this->createCommand()); } #[Test] public function itCreatesEvaluationWithCustomGradeScale(): void { $handler = $this->createHandler(affecte: true); $command = $this->createCommand(gradeScale: 10); $evaluation = $handler($command); self::assertSame(10, $evaluation->gradeScale->maxValue); } #[Test] public function itCreatesEvaluationWithCustomCoefficient(): void { $handler = $this->createHandler(affecte: true); $command = $this->createCommand(coefficient: 2.5); $evaluation = $handler($command); self::assertSame(2.5, $evaluation->coefficient->value); } #[Test] public function itThrowsWhenGradeScaleIsInvalid(): void { $handler = $this->createHandler(affecte: true); $this->expectException(BaremeInvalideException::class); $handler($this->createCommand(gradeScale: 0)); } #[Test] public function itThrowsWhenCoefficientIsInvalid(): void { $handler = $this->createHandler(affecte: true); $this->expectException(CoefficientInvalideException::class); $handler($this->createCommand(coefficient: 0.0)); } #[Test] public function itAllowsNullDescription(): void { $handler = $this->createHandler(affecte: true); $command = $this->createCommand(description: null); $evaluation = $handler($command); self::assertNull($evaluation->description); } private function createHandler(bool $affecte): CreateEvaluationHandler { $affectationChecker = new class($affecte) implements EnseignantAffectationChecker { public function __construct(private readonly bool $affecte) { } public function estAffecte(UserId $teacherId, ClassId $classId, SubjectId $subjectId, TenantId $tenantId): bool { return $this->affecte; } }; return new CreateEvaluationHandler( $this->evaluationRepository, $affectationChecker, $this->clock, ); } private function createCommand( ?string $description = 'Évaluation sur les fonctions', int $gradeScale = 20, float $coefficient = 1.0, ): CreateEvaluationCommand { return new CreateEvaluationCommand( tenantId: self::TENANT_ID, classId: self::CLASS_ID, subjectId: self::SUBJECT_ID, teacherId: self::TEACHER_ID, title: 'Contrôle chapitre 5', description: $description, evaluationDate: '2026-04-15', gradeScale: $gradeScale, coefficient: $coefficient, ); } }