createMock(EmployeeRepository::class); $mock->method('getAll')->willReturn($allData); $mock->method('getBySlug')->willReturnCallback( fn(string $slug) => $singleData[$slug] ?? null ); return $mock; } private function captureOutput(callable $fn): string { ob_start(); $fn(); return ob_get_clean(); } // --- Index Tests --- public function testIndexReturnsSuccessWithEmployees(): void { $employees = [ ['slug' => 'daedalus', 'name' => 'Daedalus'], ['slug' => 'talos', 'name' => 'Talos'], ]; $repo = $this->createMockRepo($employees); $controller = new EmployeeController($repo); $output = $this->captureOutput(fn() => $controller->index()); $json = json_decode($output, true); $this->assertTrue($json['success']); $this->assertCount(2, $json['data']); $this->assertSame(2, $json['count']); } public function testIndexReturnsEmptyArray(): void { $repo = $this->createMockRepo([]); $controller = new EmployeeController($repo); $output = $this->captureOutput(fn() => $controller->index()); $json = json_decode($output, true); $this->assertTrue($json['success']); $this->assertSame([], $json['data']); $this->assertSame(0, $json['count']); } // --- Show Tests --- public function testShowReturnsEmployee(): void { $employee = ['slug' => 'talos', 'name' => 'Talos', 'role' => 'Backend Engineering']; $repo = $this->createMockRepo([], ['talos' => $employee]); $controller = new EmployeeController($repo); $output = $this->captureOutput(fn() => $controller->show('talos')); $json = json_decode($output, true); $this->assertTrue($json['success']); $this->assertSame('Talos', $json['data']['name']); } public function testShowReturns404ForMissing(): void { $repo = $this->createMockRepo([], []); $controller = new EmployeeController($repo); $output = $this->captureOutput(fn() => $controller->show('nonexistent')); $json = json_decode($output, true); $this->assertFalse($json['success']); $this->assertStringContainsString('not found', $json['error']); } public function testShowRejects400ForInvalidSlug(): void { $repo = $this->createMockRepo(); $controller = new EmployeeController($repo); // Slug with uppercase $output = $this->captureOutput(fn() => $controller->show('INVALID')); $json = json_decode($output, true); $this->assertFalse($json['success']); $this->assertStringContainsString('Invalid slug', $json['error']); } public function testShowRejectsSlugWithSpecialChars(): void { $repo = $this->createMockRepo(); $controller = new EmployeeController($repo); $output = $this->captureOutput(fn() => $controller->show('sql;injection')); $json = json_decode($output, true); $this->assertFalse($json['success']); } public function testShowRejectsEmptySlug(): void { $repo = $this->createMockRepo(); $controller = new EmployeeController($repo); $output = $this->captureOutput(fn() => $controller->show('')); $json = json_decode($output, true); $this->assertFalse($json['success']); } public function testShowAcceptsValidSlugFormats(): void { $employee = ['slug' => 'test-user-1', 'name' => 'Test']; $repo = $this->createMockRepo([], ['test-user-1' => $employee]); $controller = new EmployeeController($repo); $output = $this->captureOutput(fn() => $controller->show('test-user-1')); $json = json_decode($output, true); $this->assertTrue($json['success']); } }