agents = new AgentRepository($db); $this->storageDir = sys_get_temp_dir() . '/monitor-recordings-controller-' . uniqid(); $this->recordings = new VoiceRecordingRepository($db, $this->storageDir); $this->controller = new VoiceRecordingController($this->recordings, $this->agents); $this->tmpUploadFile = sys_get_temp_dir() . '/monitor-upload-' . uniqid(); file_put_contents($this->tmpUploadFile, 'echte audiodaten'); } protected function tearDown(): void { if (file_exists($this->tmpUploadFile)) { unlink($this->tmpUploadFile); } if (is_dir($this->storageDir)) { foreach (glob($this->storageDir . '/*') ?: [] as $file) { unlink($file); } rmdir($this->storageDir); } } /** @return array ein $_FILES-artiges Feld fuer Request::create(). */ private function uploadedAudioField(int $error = UPLOAD_ERR_OK): array { return [ 'name' => 'aufnahme.webm', 'type' => 'audio/webm', 'tmp_name' => $this->tmpUploadFile, 'error' => $error, 'size' => filesize($this->tmpUploadFile), ]; } public function testUploadRejectsUnknownAgent(): void { $response = $this->controller->upload( Request::create('POST', '/x', files: ['audio' => $this->uploadedAudioField()]), ['id' => '999'] ); self::assertSame(404, $response->status); } public function testUploadRejectsMissingFile(): void { $agentId = (int) $this->agents->register('Alice', 'entwickler')['agent']['id']; $response = $this->controller->upload(Request::create('POST', '/x'), ['id' => (string) $agentId]); self::assertSame(422, $response->status); } public function testUploadRejectsTooLargeUploadError(): void { $agentId = (int) $this->agents->register('Alice', 'entwickler')['agent']['id']; $response = $this->controller->upload( Request::create('POST', '/x', files: ['audio' => $this->uploadedAudioField(UPLOAD_ERR_INI_SIZE)]), ['id' => (string) $agentId] ); self::assertSame(413, $response->status); } public function testUploadStoresRecordingForKnownAgent(): void { $agentId = (int) $this->agents->register('Alice', 'entwickler')['agent']['id']; $response = $this->controller->upload( Request::create('POST', '/x', files: ['audio' => $this->uploadedAudioField()]), ['id' => (string) $agentId] ); self::assertSame(201, $response->status); self::assertSame($agentId, $response->body()['recording']['agent_id']); self::assertSame('new', $response->body()['recording']['status']); } public function testIndexRejectsMismatchedAgentId(): void { $registration = $this->agents->register('Alice', 'entwickler'); $other = $this->agents->register('Bob', 'qa'); $response = $this->controller->index( Request::create('GET', '/x'), ['id' => (string) $other['agent']['id']], $registration['agent'] ); self::assertSame(403, $response->status); } public function testIndexListsOwnRecordings(): void { $registration = $this->agents->register('Alice', 'entwickler'); $agentId = (int) $registration['agent']['id']; $this->recordings->store($agentId, 'a', 'audio/webm'); $response = $this->controller->index( Request::create('GET', '/x'), ['id' => (string) $agentId], $registration['agent'] ); self::assertSame(200, $response->status); self::assertCount(1, $response->body()['recordings']); } public function testDownloadRejectsForeignAgent(): void { $registration = $this->agents->register('Alice', 'entwickler'); $other = $this->agents->register('Bob', 'qa'); $recording = $this->recordings->store((int) $other['agent']['id'], 'a', 'audio/webm'); $response = $this->controller->download( Request::create('GET', '/x'), ['id' => (string) $recording['id']], $registration['agent'] ); self::assertSame(403, $response->status); } public function testDownloadReturnsAudioBytesForOwnRecording(): void { $registration = $this->agents->register('Alice', 'entwickler'); $agentId = (int) $registration['agent']['id']; $recording = $this->recordings->store($agentId, 'echte audiodaten', 'audio/webm'); $response = $this->controller->download( Request::create('GET', '/x'), ['id' => (string) $recording['id']], $registration['agent'] ); self::assertSame(200, $response->status); self::assertSame('echte audiodaten', $response->body()); } public function testDownloadReturns404ForUnknownRecording(): void { $registration = $this->agents->register('Alice', 'entwickler'); $response = $this->controller->download( Request::create('GET', '/x'), ['id' => '999'], $registration['agent'] ); self::assertSame(404, $response->status); } public function testMarkProcessedRejectsForeignAgent(): void { $registration = $this->agents->register('Alice', 'entwickler'); $other = $this->agents->register('Bob', 'qa'); $recording = $this->recordings->store((int) $other['agent']['id'], 'a', 'audio/webm'); $response = $this->controller->markProcessed( Request::create('PATCH', '/x', body: ['status' => 'done']), ['id' => (string) $recording['id']], $registration['agent'] ); self::assertSame(403, $response->status); } public function testMarkProcessedRejectsUnsupportedStatus(): void { $registration = $this->agents->register('Alice', 'entwickler'); $agentId = (int) $registration['agent']['id']; $recording = $this->recordings->store($agentId, 'a', 'audio/webm'); $response = $this->controller->markProcessed( Request::create('PATCH', '/x', body: ['status' => 'archived']), ['id' => (string) $recording['id']], $registration['agent'] ); self::assertSame(422, $response->status); } public function testMarkProcessedMarksOwnRecordingDone(): void { $registration = $this->agents->register('Alice', 'entwickler'); $agentId = (int) $registration['agent']['id']; $recording = $this->recordings->store($agentId, 'a', 'audio/webm'); $response = $this->controller->markProcessed( Request::create('PATCH', '/x', body: ['status' => 'done']), ['id' => (string) $recording['id']], $registration['agent'] ); self::assertSame(200, $response->status); self::assertSame('done', $response->body()['recording']['status']); } }