validator = new DueDateValidator(); } #[Test] public function acceptsValidFutureSchoolDay(): void { $now = new DateTimeImmutable('2026-03-12 10:00:00'); // Jeudi $dueDate = new DateTimeImmutable('2026-03-16'); // Lundi $calendar = $this->createEmptyCalendar(); $this->validator->valider($dueDate, $now, $calendar); $this->addToAssertionCount(1); } #[Test] public function rejectsPastDate(): void { $now = new DateTimeImmutable('2026-03-12 10:00:00'); $dueDate = new DateTimeImmutable('2026-03-11'); $calendar = $this->createEmptyCalendar(); $this->expectException(DateEcheanceInvalideException::class); $this->expectExceptionMessageMatches('/futur/'); $this->validator->valider($dueDate, $now, $calendar); } #[Test] public function rejectsTodayDate(): void { $now = new DateTimeImmutable('2026-03-12 10:00:00'); $dueDate = new DateTimeImmutable('2026-03-12'); $calendar = $this->createEmptyCalendar(); $this->expectException(DateEcheanceInvalideException::class); $this->expectExceptionMessageMatches('/futur/'); $this->validator->valider($dueDate, $now, $calendar); } #[Test] public function acceptsTomorrowDate(): void { $now = new DateTimeImmutable('2026-03-12 10:00:00'); // Jeudi $dueDate = new DateTimeImmutable('2026-03-13'); // Vendredi $calendar = $this->createEmptyCalendar(); $this->validator->valider($dueDate, $now, $calendar); $this->addToAssertionCount(1); } #[Test] public function rejectsWeekendDate(): void { $now = new DateTimeImmutable('2026-03-12 10:00:00'); $dueDate = new DateTimeImmutable('2026-03-14'); // Samedi $calendar = $this->createEmptyCalendar(); $this->expectException(DateEcheanceInvalideException::class); $this->expectExceptionMessageMatches('/weekend/'); $this->validator->valider($dueDate, $now, $calendar); } #[Test] public function rejectsHolidayDate(): void { $now = new DateTimeImmutable('2026-03-12 10:00:00'); $dueDate = new DateTimeImmutable('2026-04-06'); // Lundi $calendar = $this->createCalendarWithVacation( new DateTimeImmutable('2026-04-04'), new DateTimeImmutable('2026-04-19'), 'Vacances de printemps', ); $this->expectException(DateEcheanceInvalideException::class); $this->expectExceptionMessageMatches('/Vacances de printemps/'); $this->validator->valider($dueDate, $now, $calendar); } private function createEmptyCalendar(): SchoolCalendar { return SchoolCalendar::reconstitute( tenantId: TenantId::fromString('550e8400-e29b-41d4-a716-446655440001'), academicYearId: AcademicYearId::fromString('550e8400-e29b-41d4-a716-446655440002'), zone: null, entries: [], ); } private function createCalendarWithVacation( DateTimeImmutable $start, DateTimeImmutable $end, string $label, ): SchoolCalendar { return SchoolCalendar::reconstitute( tenantId: TenantId::fromString('550e8400-e29b-41d4-a716-446655440001'), academicYearId: AcademicYearId::fromString('550e8400-e29b-41d4-a716-446655440002'), zone: null, entries: [ new CalendarEntry( id: CalendarEntryId::generate(), type: CalendarEntryType::VACATION, startDate: $start, endDate: $end, label: $label, ), ], ); } }