reader = $this->createMock(PaginatedSubjectsReader::class); $this->cache = new PaginatedQueryCache( new TagAwareAdapter(new ArrayAdapter()), ); $this->handler = new GetSubjectsHandler($this->reader, $this->cache); } #[Test] public function returnsItemsForTenant(): void { $dto = $this->createSubjectDto(); $this->reader->method('findPaginated')->willReturn( new PaginatedResult(items: [$dto], total: 1, page: 1, limit: 30), ); $result = ($this->handler)(new GetSubjectsQuery(tenantId: 'tenant-1', schoolId: 'school-1')); self::assertCount(1, $result->items); self::assertSame(1, $result->total); } #[Test] public function mapsDtoFields(): void { $dto = $this->createSubjectDto(); $this->reader->method('findPaginated')->willReturn( new PaginatedResult(items: [$dto], total: 1, page: 1, limit: 30), ); $result = ($this->handler)(new GetSubjectsQuery(tenantId: 'tenant-1', schoolId: 'school-1')); $item = $result->items[0]; self::assertSame('subject-1', $item->id); self::assertSame('Mathematiques', $item->name); self::assertSame('MATH', $item->code); self::assertSame('#3B82F6', $item->color); self::assertSame('Maths avancees', $item->description); self::assertSame('active', $item->status); self::assertSame(2, $item->teacherCount); self::assertSame(1, $item->classCount); } #[Test] public function paginatesResults(): void { $this->reader->method('findPaginated')->willReturn( new PaginatedResult(items: [], total: 50, page: 2, limit: 10), ); $result = ($this->handler)(new GetSubjectsQuery(tenantId: 'tenant-1', schoolId: 'school-1', page: 2, limit: 10)); self::assertSame(50, $result->total); self::assertSame(2, $result->page); self::assertSame(10, $result->limit); } #[Test] public function cachesResult(): void { $dto = $this->createSubjectDto(); $this->reader->expects(self::once())->method('findPaginated')->willReturn( new PaginatedResult(items: [$dto], total: 1, page: 1, limit: 30), ); $query = new GetSubjectsQuery(tenantId: 'tenant-1', schoolId: 'school-1'); ($this->handler)($query); $result = ($this->handler)($query); self::assertCount(1, $result->items); } #[Test] public function clampsPageToMinimumOne(): void { $this->reader->method('findPaginated')->willReturn( new PaginatedResult(items: [], total: 0, page: 1, limit: 30), ); $result = ($this->handler)(new GetSubjectsQuery(tenantId: 'tenant-1', schoolId: 'school-1', page: -5)); self::assertSame(1, $result->page); } #[Test] public function clampsLimitToMaximumHundred(): void { $this->reader->method('findPaginated')->willReturn( new PaginatedResult(items: [], total: 0, page: 1, limit: 100), ); $result = ($this->handler)(new GetSubjectsQuery(tenantId: 'tenant-1', schoolId: 'school-1', limit: 500)); self::assertSame(100, $result->limit); } private function createSubjectDto(): SubjectDto { return new SubjectDto( id: 'subject-1', name: 'Mathematiques', code: 'MATH', color: '#3B82F6', description: 'Maths avancees', status: 'active', createdAt: new DateTimeImmutable('2026-01-15'), updatedAt: new DateTimeImmutable('2026-01-15'), teacherCount: 2, classCount: 1, ); } }