createEvaluation(); self::assertSame(EvaluationStatus::PUBLISHED, $evaluation->status); } #[Test] public function creerRecordsEvaluationCreeeEvent(): void { $evaluation = $this->createEvaluation(); $events = $evaluation->pullDomainEvents(); self::assertCount(1, $events); self::assertInstanceOf(EvaluationCreee::class, $events[0]); self::assertSame($evaluation->id, $events[0]->evaluationId); } #[Test] public function creerSetsAllProperties(): void { $tenantId = TenantId::fromString(self::TENANT_ID); $classId = ClassId::fromString(self::CLASS_ID); $subjectId = SubjectId::fromString(self::SUBJECT_ID); $teacherId = UserId::fromString(self::TEACHER_ID); $evaluationDate = new DateTimeImmutable('2026-04-15'); $now = new DateTimeImmutable('2026-03-12 10:00:00'); $gradeScale = new GradeScale(20); $coefficient = new Coefficient(1.5); $evaluation = Evaluation::creer( tenantId: $tenantId, classId: $classId, subjectId: $subjectId, teacherId: $teacherId, title: 'Contrôle chapitre 5', description: 'Évaluation sur les fonctions', evaluationDate: $evaluationDate, gradeScale: $gradeScale, coefficient: $coefficient, now: $now, ); self::assertTrue($evaluation->tenantId->equals($tenantId)); self::assertTrue($evaluation->classId->equals($classId)); self::assertTrue($evaluation->subjectId->equals($subjectId)); self::assertTrue($evaluation->teacherId->equals($teacherId)); self::assertSame('Contrôle chapitre 5', $evaluation->title); self::assertSame('Évaluation sur les fonctions', $evaluation->description); self::assertEquals($evaluationDate, $evaluation->evaluationDate); self::assertSame(20, $evaluation->gradeScale->maxValue); self::assertSame(1.5, $evaluation->coefficient->value); self::assertSame(EvaluationStatus::PUBLISHED, $evaluation->status); self::assertEquals($now, $evaluation->createdAt); self::assertEquals($now, $evaluation->updatedAt); } #[Test] public function creerAllowsNullDescription(): void { $evaluation = Evaluation::creer( tenantId: TenantId::fromString(self::TENANT_ID), classId: ClassId::fromString(self::CLASS_ID), subjectId: SubjectId::fromString(self::SUBJECT_ID), teacherId: UserId::fromString(self::TEACHER_ID), title: 'Évaluation sans description', description: null, evaluationDate: new DateTimeImmutable('2026-04-15'), gradeScale: new GradeScale(20), coefficient: new Coefficient(1.0), now: new DateTimeImmutable('2026-03-12 10:00:00'), ); self::assertNull($evaluation->description); } #[Test] public function modifierUpdatesFieldsAndRecordsEvent(): void { $evaluation = $this->createEvaluation(); $evaluation->pullDomainEvents(); $modifiedAt = new DateTimeImmutable('2026-03-13 14:00:00'); $newDate = new DateTimeImmutable('2026-04-20'); $newCoefficient = new Coefficient(2.0); $evaluation->modifier( title: 'Titre modifié', description: 'Nouvelle description', coefficient: $newCoefficient, evaluationDate: $newDate, gradeScale: null, hasGrades: false, now: $modifiedAt, ); self::assertSame('Titre modifié', $evaluation->title); self::assertSame('Nouvelle description', $evaluation->description); self::assertSame(2.0, $evaluation->coefficient->value); self::assertEquals($newDate, $evaluation->evaluationDate); self::assertEquals($modifiedAt, $evaluation->updatedAt); $events = $evaluation->pullDomainEvents(); self::assertCount(1, $events); self::assertInstanceOf(EvaluationModifiee::class, $events[0]); self::assertSame($evaluation->id, $events[0]->evaluationId); } #[Test] public function modifierAllowsGradeScaleChangeWhenNoGrades(): void { $evaluation = $this->createEvaluation(); $evaluation->pullDomainEvents(); $newGradeScale = new GradeScale(10); $evaluation->modifier( title: $evaluation->title, description: $evaluation->description, coefficient: $evaluation->coefficient, evaluationDate: $evaluation->evaluationDate, gradeScale: $newGradeScale, hasGrades: false, now: new DateTimeImmutable('2026-03-13 14:00:00'), ); self::assertSame(10, $evaluation->gradeScale->maxValue); } #[Test] public function modifierBlocksGradeScaleChangeWhenGradesExist(): void { $evaluation = $this->createEvaluation(); $this->expectException(BaremeNonModifiableException::class); $evaluation->modifier( title: $evaluation->title, description: $evaluation->description, coefficient: $evaluation->coefficient, evaluationDate: $evaluation->evaluationDate, gradeScale: new GradeScale(10), hasGrades: true, now: new DateTimeImmutable('2026-03-13 14:00:00'), ); } #[Test] public function modifierThrowsWhenDeleted(): void { $evaluation = $this->createEvaluation(); $evaluation->supprimer(new DateTimeImmutable('2026-03-13')); $this->expectException(EvaluationDejaSupprimeeException::class); $evaluation->modifier( title: 'Titre', description: null, coefficient: new Coefficient(1.0), evaluationDate: new DateTimeImmutable('2026-04-20'), gradeScale: null, hasGrades: false, now: new DateTimeImmutable('2026-03-14'), ); } #[Test] public function supprimerChangesStatusAndRecordsEvent(): void { $evaluation = $this->createEvaluation(); $evaluation->pullDomainEvents(); $deletedAt = new DateTimeImmutable('2026-03-14 08:00:00'); $evaluation->supprimer($deletedAt); self::assertSame(EvaluationStatus::DELETED, $evaluation->status); self::assertEquals($deletedAt, $evaluation->updatedAt); $events = $evaluation->pullDomainEvents(); self::assertCount(1, $events); self::assertInstanceOf(EvaluationSupprimee::class, $events[0]); self::assertSame($evaluation->id, $events[0]->evaluationId); } #[Test] public function supprimerThrowsWhenAlreadyDeleted(): void { $evaluation = $this->createEvaluation(); $evaluation->supprimer(new DateTimeImmutable('2026-03-14')); $this->expectException(EvaluationDejaSupprimeeException::class); $evaluation->supprimer(new DateTimeImmutable('2026-03-15')); } #[Test] public function reconstituteRestoresAllPropertiesWithoutEvents(): void { $id = EvaluationId::generate(); $tenantId = TenantId::fromString(self::TENANT_ID); $classId = ClassId::fromString(self::CLASS_ID); $subjectId = SubjectId::fromString(self::SUBJECT_ID); $teacherId = UserId::fromString(self::TEACHER_ID); $evaluationDate = new DateTimeImmutable('2026-04-15'); $createdAt = new DateTimeImmutable('2026-03-12 10:00:00'); $updatedAt = new DateTimeImmutable('2026-03-13 14:00:00'); $gradeScale = new GradeScale(20); $coefficient = new Coefficient(1.5); $evaluation = Evaluation::reconstitute( id: $id, tenantId: $tenantId, classId: $classId, subjectId: $subjectId, teacherId: $teacherId, title: 'Contrôle chapitre 5', description: 'Évaluation sur les fonctions', evaluationDate: $evaluationDate, gradeScale: $gradeScale, coefficient: $coefficient, status: EvaluationStatus::PUBLISHED, createdAt: $createdAt, updatedAt: $updatedAt, ); self::assertTrue($evaluation->id->equals($id)); self::assertTrue($evaluation->tenantId->equals($tenantId)); self::assertTrue($evaluation->classId->equals($classId)); self::assertTrue($evaluation->subjectId->equals($subjectId)); self::assertTrue($evaluation->teacherId->equals($teacherId)); self::assertSame('Contrôle chapitre 5', $evaluation->title); self::assertSame('Évaluation sur les fonctions', $evaluation->description); self::assertEquals($evaluationDate, $evaluation->evaluationDate); self::assertSame(20, $evaluation->gradeScale->maxValue); self::assertSame(1.5, $evaluation->coefficient->value); self::assertSame(EvaluationStatus::PUBLISHED, $evaluation->status); self::assertEquals($createdAt, $evaluation->createdAt); self::assertEquals($updatedAt, $evaluation->updatedAt); self::assertEmpty($evaluation->pullDomainEvents()); } private function createEvaluation(): Evaluation { return Evaluation::creer( tenantId: TenantId::fromString(self::TENANT_ID), classId: ClassId::fromString(self::CLASS_ID), subjectId: SubjectId::fromString(self::SUBJECT_ID), teacherId: UserId::fromString(self::TEACHER_ID), title: 'Contrôle chapitre 5', description: 'Évaluation sur les fonctions', evaluationDate: new DateTimeImmutable('2026-04-15'), gradeScale: new GradeScale(20), coefficient: new Coefficient(1.0), now: new DateTimeImmutable('2026-03-12 10:00:00'), ); } }