tenantId->equals(TenantId::fromString(self::TENANT_ID))); self::assertTrue($exception->slotId->equals(ScheduleSlotId::fromString(self::SLOT_ID))); self::assertSame('2026-10-05', $exception->exceptionDate->format('Y-m-d')); self::assertSame(ScheduleExceptionType::CANCELLED, $exception->type); self::assertSame('Grève', $exception->reason); self::assertNull($exception->newTimeSlot); self::assertNull($exception->newRoom); self::assertNull($exception->newTeacherId); self::assertTrue($exception->createdBy->equals(UserId::fromString(self::CREATOR_ID))); } #[Test] public function modifierCreatesAModifiedExceptionWithNewValues(): void { $newTimeSlot = new TimeSlot('10:00', '11:00'); $newTeacherId = UserId::fromString(self::TEACHER_ID); $exception = ScheduleException::modifier( tenantId: TenantId::fromString(self::TENANT_ID), slotId: ScheduleSlotId::fromString(self::SLOT_ID), exceptionDate: new DateTimeImmutable('2026-10-05'), newTimeSlot: $newTimeSlot, newRoom: 'Salle 301', newTeacherId: $newTeacherId, reason: 'Changement de salle', createdBy: UserId::fromString(self::CREATOR_ID), now: new DateTimeImmutable('2026-10-01 10:00:00'), ); self::assertSame(ScheduleExceptionType::MODIFIED, $exception->type); self::assertNotNull($exception->newTimeSlot); self::assertSame('10:00', $exception->newTimeSlot->startTime); self::assertSame('11:00', $exception->newTimeSlot->endTime); self::assertSame('Salle 301', $exception->newRoom); self::assertTrue($exception->newTeacherId->equals($newTeacherId)); } #[Test] public function modifierWithPartialOverridesKeepsNullsForUnchangedFields(): void { $exception = ScheduleException::modifier( tenantId: TenantId::fromString(self::TENANT_ID), slotId: ScheduleSlotId::fromString(self::SLOT_ID), exceptionDate: new DateTimeImmutable('2026-10-05'), newTimeSlot: null, newRoom: 'Salle 302', newTeacherId: null, reason: null, createdBy: UserId::fromString(self::CREATOR_ID), now: new DateTimeImmutable('2026-10-01 10:00:00'), ); self::assertSame(ScheduleExceptionType::MODIFIED, $exception->type); self::assertNull($exception->newTimeSlot); self::assertSame('Salle 302', $exception->newRoom); self::assertNull($exception->newTeacherId); self::assertNull($exception->reason); } #[Test] public function isCancelledReturnsTrueForCancelledType(): void { $exception = ScheduleException::annuler( tenantId: TenantId::fromString(self::TENANT_ID), slotId: ScheduleSlotId::fromString(self::SLOT_ID), exceptionDate: new DateTimeImmutable('2026-10-05'), reason: null, createdBy: UserId::fromString(self::CREATOR_ID), now: new DateTimeImmutable('2026-10-01 10:00:00'), ); self::assertTrue($exception->isCancelled()); self::assertFalse($exception->isModified()); } #[Test] public function isModifiedReturnsTrueForModifiedType(): void { $exception = ScheduleException::modifier( tenantId: TenantId::fromString(self::TENANT_ID), slotId: ScheduleSlotId::fromString(self::SLOT_ID), exceptionDate: new DateTimeImmutable('2026-10-05'), newTimeSlot: new TimeSlot('14:00', '15:00'), newRoom: null, newTeacherId: null, reason: null, createdBy: UserId::fromString(self::CREATOR_ID), now: new DateTimeImmutable('2026-10-01 10:00:00'), ); self::assertTrue($exception->isModified()); self::assertFalse($exception->isCancelled()); } #[Test] public function reconstituteRestoresAllPropertiesWithoutEvents(): void { $id = ScheduleExceptionId::generate(); $tenantId = TenantId::fromString(self::TENANT_ID); $slotId = ScheduleSlotId::fromString(self::SLOT_ID); $newTimeSlot = new TimeSlot('11:00', '12:00'); $newTeacherId = UserId::fromString(self::TEACHER_ID); $createdBy = UserId::fromString(self::CREATOR_ID); $createdAt = new DateTimeImmutable('2026-10-01 10:00:00'); $exception = ScheduleException::reconstitute( id: $id, tenantId: $tenantId, slotId: $slotId, exceptionDate: new DateTimeImmutable('2026-10-05'), type: ScheduleExceptionType::MODIFIED, newTimeSlot: $newTimeSlot, newRoom: 'Salle 303', newTeacherId: $newTeacherId, reason: 'Interversion', createdBy: $createdBy, createdAt: $createdAt, ); self::assertTrue($exception->id->equals($id)); self::assertTrue($exception->tenantId->equals($tenantId)); self::assertTrue($exception->slotId->equals($slotId)); self::assertSame('2026-10-05', $exception->exceptionDate->format('Y-m-d')); self::assertSame(ScheduleExceptionType::MODIFIED, $exception->type); self::assertSame('11:00', $exception->newTimeSlot->startTime); self::assertSame('Salle 303', $exception->newRoom); self::assertTrue($exception->newTeacherId->equals($newTeacherId)); self::assertSame('Interversion', $exception->reason); self::assertTrue($exception->createdBy->equals($createdBy)); self::assertEquals($createdAt, $exception->createdAt); } }