classRepository = new InMemoryClassRepository(); $this->clock = new class implements Clock { public function now(): DateTimeImmutable { return new DateTimeImmutable('2026-01-31 10:00:00'); } }; } #[Test] public function itCreatesClassSuccessfully(): void { $handler = new CreateClassHandler($this->classRepository, $this->clock); $command = new CreateClassCommand( tenantId: self::TENANT_ID, schoolId: self::SCHOOL_ID, academicYearId: self::ACADEMIC_YEAR_ID, name: '6ème A', level: SchoolLevel::SIXIEME->value, capacity: 30, ); $class = $handler($command); self::assertNotEmpty((string) $class->id); self::assertSame('6ème A', (string) $class->name); self::assertSame(SchoolLevel::SIXIEME, $class->level); self::assertSame(30, $class->capacity); } #[Test] public function itCreatesClassWithNullLevelAndCapacity(): void { $handler = new CreateClassHandler($this->classRepository, $this->clock); $command = new CreateClassCommand( tenantId: self::TENANT_ID, schoolId: self::SCHOOL_ID, academicYearId: self::ACADEMIC_YEAR_ID, name: 'Classe spéciale', level: null, capacity: null, ); $class = $handler($command); self::assertNotEmpty((string) $class->id); self::assertSame('Classe spéciale', (string) $class->name); self::assertNull($class->level); self::assertNull($class->capacity); } #[Test] public function itPersistsClassInRepository(): void { $handler = new CreateClassHandler($this->classRepository, $this->clock); $command = new CreateClassCommand( tenantId: self::TENANT_ID, schoolId: self::SCHOOL_ID, academicYearId: self::ACADEMIC_YEAR_ID, name: '6ème A', level: SchoolLevel::SIXIEME->value, capacity: 30, ); $createdClass = $handler($command); $class = $this->classRepository->get( ClassId::fromString((string) $createdClass->id), ); self::assertSame('6ème A', (string) $class->name); self::assertSame(ClassStatus::ACTIVE, $class->status); self::assertSame(SchoolLevel::SIXIEME, $class->level); self::assertSame(30, $class->capacity); } #[Test] public function itThrowsExceptionWhenClassNameAlreadyExists(): void { $handler = new CreateClassHandler($this->classRepository, $this->clock); $command = new CreateClassCommand( tenantId: self::TENANT_ID, schoolId: self::SCHOOL_ID, academicYearId: self::ACADEMIC_YEAR_ID, name: '6ème A', level: SchoolLevel::SIXIEME->value, capacity: 30, ); // First creation should succeed $handler($command); // Second creation with same name should throw $this->expectException(ClasseDejaExistanteException::class); $this->expectExceptionMessage('Une classe avec le nom "6ème A" existe déjà pour cette année scolaire.'); $handler($command); } #[Test] public function itAllowsSameNameInDifferentTenant(): void { $handler = new CreateClassHandler($this->classRepository, $this->clock); // Create in tenant 1 $command1 = new CreateClassCommand( tenantId: self::TENANT_ID, schoolId: self::SCHOOL_ID, academicYearId: self::ACADEMIC_YEAR_ID, name: '6ème A', level: SchoolLevel::SIXIEME->value, capacity: 30, ); $class1 = $handler($command1); // Create same name in tenant 2 should succeed $command2 = new CreateClassCommand( tenantId: '550e8400-e29b-41d4-a716-446655440099', schoolId: self::SCHOOL_ID, academicYearId: self::ACADEMIC_YEAR_ID, name: '6ème A', level: SchoolLevel::SIXIEME->value, capacity: 30, ); $class2 = $handler($command2); self::assertFalse($class1->id->equals($class2->id)); self::assertSame('6ème A', (string) $class1->name); self::assertSame('6ème A', (string) $class2->name); } #[Test] public function itAllowsSameNameInDifferentAcademicYear(): void { $handler = new CreateClassHandler($this->classRepository, $this->clock); // Create in year 1 $command1 = new CreateClassCommand( tenantId: self::TENANT_ID, schoolId: self::SCHOOL_ID, academicYearId: self::ACADEMIC_YEAR_ID, name: '6ème A', level: SchoolLevel::SIXIEME->value, capacity: 30, ); $class1 = $handler($command1); // Create same name in year 2 should succeed $command2 = new CreateClassCommand( tenantId: self::TENANT_ID, schoolId: self::SCHOOL_ID, academicYearId: '550e8400-e29b-41d4-a716-446655440099', name: '6ème A', level: SchoolLevel::SIXIEME->value, capacity: 30, ); $class2 = $handler($command2); self::assertFalse($class1->id->equals($class2->id)); self::assertSame('6ème A', (string) $class1->name); self::assertSame('6ème A', (string) $class2->name); } }