repository = new InMemoryScheduleSlotRepository(); $this->handler = new GetScheduleSlotsHandler($this->repository); } #[Test] public function returnsSlotsFilteredByClass(): void { $this->createSlot(classId: self::CLASS_A, teacherId: self::TEACHER_A); $this->createSlot(classId: self::CLASS_B, teacherId: self::TEACHER_A); $result = ($this->handler)(new GetScheduleSlotsQuery( tenantId: self::TENANT_ID, classId: self::CLASS_A, )); self::assertCount(1, $result); self::assertSame(self::CLASS_A, $result[0]->classId); } #[Test] public function returnsSlotsFilteredByTeacher(): void { $this->createSlot(classId: self::CLASS_A, teacherId: self::TEACHER_A); $this->createSlot(classId: self::CLASS_A, teacherId: self::TEACHER_B, day: DayOfWeek::TUESDAY); $result = ($this->handler)(new GetScheduleSlotsQuery( tenantId: self::TENANT_ID, teacherId: self::TEACHER_A, )); self::assertCount(1, $result); self::assertSame(self::TEACHER_A, $result[0]->teacherId); } #[Test] public function returnsSlotsFilteredByClassAndTeacher(): void { // Classe A, enseignant A $this->createSlot(classId: self::CLASS_A, teacherId: self::TEACHER_A); // Classe A, enseignant B $this->createSlot(classId: self::CLASS_A, teacherId: self::TEACHER_B, day: DayOfWeek::TUESDAY); // Classe B, enseignant A $this->createSlot(classId: self::CLASS_B, teacherId: self::TEACHER_A, day: DayOfWeek::WEDNESDAY); $result = ($this->handler)(new GetScheduleSlotsQuery( tenantId: self::TENANT_ID, classId: self::CLASS_A, teacherId: self::TEACHER_A, )); self::assertCount(1, $result); self::assertSame(self::CLASS_A, $result[0]->classId); self::assertSame(self::TEACHER_A, $result[0]->teacherId); } #[Test] public function returnsEmptyWhenClassAndTeacherDontMatch(): void { $this->createSlot(classId: self::CLASS_A, teacherId: self::TEACHER_A); $result = ($this->handler)(new GetScheduleSlotsQuery( tenantId: self::TENANT_ID, classId: self::CLASS_A, teacherId: self::TEACHER_B, )); self::assertCount(0, $result); } #[Test] public function returnsEmptyWhenNoFilters(): void { $this->createSlot(classId: self::CLASS_A, teacherId: self::TEACHER_A); $result = ($this->handler)(new GetScheduleSlotsQuery( tenantId: self::TENANT_ID, )); self::assertCount(0, $result); } #[Test] public function returnsEmptyForInvalidClassIdUuid(): void { $this->createSlot(classId: self::CLASS_A, teacherId: self::TEACHER_A); $result = ($this->handler)(new GetScheduleSlotsQuery( tenantId: self::TENANT_ID, classId: 'not-a-valid-uuid', )); self::assertCount(0, $result); } #[Test] public function returnsEmptyForInvalidTeacherIdUuid(): void { $this->createSlot(classId: self::CLASS_A, teacherId: self::TEACHER_A); $result = ($this->handler)(new GetScheduleSlotsQuery( tenantId: self::TENANT_ID, teacherId: 'invalid', )); self::assertCount(0, $result); } #[Test] public function teacherFilterReturnsAllClassesForTeacher(): void { $this->createSlot(classId: self::CLASS_A, teacherId: self::TEACHER_A); $this->createSlot(classId: self::CLASS_B, teacherId: self::TEACHER_A, day: DayOfWeek::TUESDAY); $result = ($this->handler)(new GetScheduleSlotsQuery( tenantId: self::TENANT_ID, teacherId: self::TEACHER_A, )); self::assertCount(2, $result); } private function createSlot( string $classId, string $teacherId, DayOfWeek $day = DayOfWeek::MONDAY, ): ScheduleSlot { $slot = ScheduleSlot::creer( tenantId: TenantId::fromString(self::TENANT_ID), classId: ClassId::fromString($classId), subjectId: SubjectId::fromString(self::SUBJECT_ID), teacherId: UserId::fromString($teacherId), dayOfWeek: $day, timeSlot: new TimeSlot('08:00', '09:00'), room: null, isRecurring: true, now: new DateTimeImmutable('2026-03-01 10:00:00'), ); $this->repository->save($slot); return $slot; } }