repository = new AgentRepository($db); $this->tickets = new TicketRepository($db); $this->recordingsStorageDir = sys_get_temp_dir() . '/monitor-agent-controller-recordings-' . uniqid(); $this->recordings = new VoiceRecordingRepository($db, $this->recordingsStorageDir); $this->controller = new AgentController($this->repository, $this->recordings); } protected function tearDown(): void { if (is_dir($this->recordingsStorageDir)) { foreach (glob($this->recordingsStorageDir . '/*') ?: [] as $file) { unlink($file); } rmdir($this->recordingsStorageDir); } } public function testMeReturnsAuthenticatedAgentWithoutApiKeyHash(): void { $this->repository->register('Alice', 'entwickler'); $ops = $this->repository->register('OPs', 'ops'); $response = $this->controller->me(Request::create('GET', '/api/v1/agents/me'), $ops['agent']); self::assertSame(200, $response->status); self::assertSame($ops['agent']['id'], $response->body()['agent']['id']); self::assertArrayNotHasKey('api_key_hash', $response->body()['agent']); } public function testRegisterRejectsMissingDisplayName(): void { $response = $this->controller->register(Request::create('POST', '/api/v1/agents', body: ['role' => 'entwickler'])); self::assertSame(422, $response->status); } public function testRegisterRejectsUnknownRole(): void { $response = $this->controller->register(Request::create('POST', '/api/v1/agents', body: [ 'display_name' => 'Alice', 'role' => 'ceo', ])); self::assertSame(422, $response->status); } public function testRegisterReturns201WithApiKey(): void { $response = $this->controller->register(Request::create('POST', '/api/v1/agents', body: [ 'display_name' => 'Alice', 'role' => 'entwickler', ])); self::assertSame(201, $response->status); self::assertArrayHasKey('api_key', $response->body()); self::assertArrayNotHasKey('api_key_hash', $response->body()['agent']); } public function testActivityRejectsMismatchedAgentId(): void { $registration = $this->repository->register('Alice', 'entwickler'); $other = $this->repository->register('Bob', 'qa'); $response = $this->controller->activity( Request::create('POST', '/x', body: ['state' => 'working']), ['id' => (string) $other['agent']['id']], $registration['agent'] ); self::assertSame(403, $response->status); } public function testActivityRejectsMissingState(): void { $registration = $this->repository->register('Alice', 'entwickler'); $response = $this->controller->activity( Request::create('POST', '/x', body: []), ['id' => (string) $registration['agent']['id']], $registration['agent'] ); self::assertSame(422, $response->status); } public function testActivityUpdatesOwnState(): void { $registration = $this->repository->register('Alice', 'entwickler'); $ticketId = (int) $this->tickets->create(['title' => 'Testticket'])['id']; $response = $this->controller->activity( Request::create('POST', '/x', body: ['state' => 'working', 'current_ticket' => $ticketId]), ['id' => (string) $registration['agent']['id']], $registration['agent'] ); self::assertSame(200, $response->status); self::assertSame('working', $response->body()['agent']['state']); self::assertSame($ticketId, $response->body()['agent']['current_ticket_id']); } public function testIndexListsAgents(): void { $this->repository->register('Alice', 'entwickler'); $response = $this->controller->index(Request::create('GET', '/api/v1/agents')); self::assertCount(1, $response->body()['agents']); } /** * Issue #85: der Zaehler auf dem Schreibtisch haengt an diesem Feld - GET /api/v1/agents * reichert jeden Agenten um die Anzahl offener Sprachaufnahmen an. */ public function testIndexIncludesPendingRecordingsCount(): void { $registration = $this->repository->register('Alice', 'entwickler'); $agentId = (int) $registration['agent']['id']; $done = $this->recordings->store($agentId, 'a', 'audio/webm'); $this->recordings->store($agentId, 'b', 'audio/webm'); $this->recordings->markDone((int) $done['id']); $response = $this->controller->index(Request::create('GET', '/api/v1/agents')); self::assertSame(1, $response->body()['agents'][0]['pending_recordings']); } public function testIndexDefaultsPendingRecordingsToZero(): void { $this->repository->register('Alice', 'entwickler'); $response = $this->controller->index(Request::create('GET', '/api/v1/agents')); self::assertSame(0, $response->body()['agents'][0]['pending_recordings']); } }