createReplacement(); $resource = TeacherReplacementResource::fromDomain($replacement); self::assertSame((string) $replacement->id, $resource->id); self::assertSame(self::REPLACED_TEACHER_ID, $resource->replacedTeacherId); self::assertSame(self::REPLACEMENT_TEACHER_ID, $resource->replacementTeacherId); self::assertSame('2026-03-01', $resource->startDate); self::assertSame('2026-03-31', $resource->endDate); self::assertSame('active', $resource->status); self::assertSame('Congé maladie', $resource->reason); self::assertEquals($replacement->createdAt, $resource->createdAt); self::assertNull($resource->endedAt); } #[Test] public function fromDomainMapsClassSubjectPairs(): void { $replacement = $this->createReplacement(); $resource = TeacherReplacementResource::fromDomain($replacement); self::assertCount(1, $resource->classes); self::assertSame(self::CLASS_ID, $resource->classes[0]['classId']); self::assertSame(self::SUBJECT_ID, $resource->classes[0]['subjectId']); } #[Test] public function fromDomainPreservesEndedAtWhenTerminated(): void { $replacement = $this->createReplacement(); $endedAt = new DateTimeImmutable('2026-03-20 14:00:00'); $replacement->terminer($endedAt); $resource = TeacherReplacementResource::fromDomain($replacement); self::assertSame('ended', $resource->status); self::assertEquals($endedAt, $resource->endedAt); } #[Test] public function fromDtoCreatesCorrectResource(): void { $startDate = new DateTimeImmutable('2026-03-01'); $endDate = new DateTimeImmutable('2026-03-31'); $dto = new ReplacementDto( id: '550e8400-e29b-41d4-a716-446655440050', replacedTeacherId: self::REPLACED_TEACHER_ID, replacementTeacherId: self::REPLACEMENT_TEACHER_ID, startDate: $startDate, endDate: $endDate, status: ReplacementStatus::ACTIVE->value, classes: [ ['classId' => self::CLASS_ID, 'subjectId' => self::SUBJECT_ID], ], reason: 'Formation', ); $resource = TeacherReplacementResource::fromDto($dto); self::assertSame('550e8400-e29b-41d4-a716-446655440050', $resource->id); self::assertSame(self::REPLACED_TEACHER_ID, $resource->replacedTeacherId); self::assertSame(self::REPLACEMENT_TEACHER_ID, $resource->replacementTeacherId); self::assertSame('2026-03-01', $resource->startDate); self::assertSame('2026-03-31', $resource->endDate); self::assertSame('active', $resource->status); self::assertSame('Formation', $resource->reason); self::assertCount(1, $resource->classes); self::assertSame(self::CLASS_ID, $resource->classes[0]['classId']); self::assertSame(self::SUBJECT_ID, $resource->classes[0]['subjectId']); } #[Test] public function fromDtoPreservesNullReason(): void { $dto = new ReplacementDto( id: '550e8400-e29b-41d4-a716-446655440050', replacedTeacherId: self::REPLACED_TEACHER_ID, replacementTeacherId: self::REPLACEMENT_TEACHER_ID, startDate: new DateTimeImmutable('2026-03-01'), endDate: new DateTimeImmutable('2026-03-31'), status: ReplacementStatus::ACTIVE->value, classes: [], reason: null, ); $resource = TeacherReplacementResource::fromDto($dto); self::assertNull($resource->reason); } private function createReplacement(): TeacherReplacement { return TeacherReplacement::designer( tenantId: TenantId::fromString(self::TENANT_ID), replacedTeacherId: UserId::fromString(self::REPLACED_TEACHER_ID), replacementTeacherId: UserId::fromString(self::REPLACEMENT_TEACHER_ID), startDate: new DateTimeImmutable('2026-03-01'), endDate: new DateTimeImmutable('2026-03-31'), classes: [ new ClassSubjectPair( ClassId::fromString(self::CLASS_ID), SubjectId::fromString(self::SUBJECT_ID), ), ], reason: 'Congé maladie', createdBy: UserId::fromString(self::CREATED_BY_ID), now: new DateTimeImmutable('2026-02-15 10:00:00'), ); } }