value, now: $now, ); self::assertTrue($result->tenantId->equals($tenantId)); self::assertTrue($result->competencyEvaluationId->equals($ceId)); self::assertTrue($result->studentId->equals($studentId)); self::assertSame('acquired', $result->levelCode); self::assertEquals($now, $result->createdAt); self::assertEquals($now, $result->updatedAt); } #[Test] public function saisirRecordsEvent(): void { $result = $this->createResult(); $events = $result->pullDomainEvents(); self::assertCount(1, $events); self::assertInstanceOf(ResultatCompetenceSaisi::class, $events[0]); self::assertSame($result->id, $events[0]->resultId); self::assertSame('acquired', $events[0]->levelCode); } #[Test] public function modifierDoesNothingWhenLevelUnchanged(): void { $result = $this->createResult(); $result->pullDomainEvents(); $createdAt = $result->updatedAt; $result->modifier( levelCode: CompetencyLevel::ACQUIRED->value, now: new DateTimeImmutable('2026-04-02 14:00:00'), ); self::assertSame('acquired', $result->levelCode); self::assertEquals($createdAt, $result->updatedAt); self::assertEmpty($result->pullDomainEvents()); } #[Test] public function modifierUpdatesLevelAndRecordsEvent(): void { $result = $this->createResult(); $result->pullDomainEvents(); $modifiedAt = new DateTimeImmutable('2026-04-02 14:00:00'); $result->modifier( levelCode: CompetencyLevel::EXCEEDED->value, now: $modifiedAt, ); self::assertSame('exceeded', $result->levelCode); self::assertEquals($modifiedAt, $result->updatedAt); $events = $result->pullDomainEvents(); self::assertCount(1, $events); self::assertInstanceOf(ResultatCompetenceModifie::class, $events[0]); self::assertSame('acquired', $events[0]->oldLevelCode); self::assertSame('exceeded', $events[0]->newLevelCode); } #[Test] public function reconstituteRestoresAllProperties(): void { $id = StudentCompetencyResultId::generate(); $tenantId = TenantId::fromString(self::TENANT_ID); $ceId = CompetencyEvaluationId::generate(); $studentId = UserId::fromString(self::STUDENT_ID); $createdAt = new DateTimeImmutable('2026-04-01 10:00:00'); $updatedAt = new DateTimeImmutable('2026-04-02 14:00:00'); $result = StudentCompetencyResult::reconstitute( id: $id, tenantId: $tenantId, competencyEvaluationId: $ceId, studentId: $studentId, levelCode: CompetencyLevel::IN_PROGRESS->value, createdAt: $createdAt, updatedAt: $updatedAt, ); self::assertTrue($result->id->equals($id)); self::assertTrue($result->tenantId->equals($tenantId)); self::assertTrue($result->competencyEvaluationId->equals($ceId)); self::assertTrue($result->studentId->equals($studentId)); self::assertSame('in_progress', $result->levelCode); self::assertEquals($createdAt, $result->createdAt); self::assertEquals($updatedAt, $result->updatedAt); self::assertEmpty($result->pullDomainEvents()); } private function createResult(): StudentCompetencyResult { return StudentCompetencyResult::saisir( tenantId: TenantId::fromString(self::TENANT_ID), competencyEvaluationId: CompetencyEvaluationId::generate(), studentId: UserId::fromString(self::STUDENT_ID), levelCode: CompetencyLevel::ACQUIRED->value, now: new DateTimeImmutable('2026-04-01 10:00:00'), ); } }