'uploader1', 'password' => 'password1'], ['username' => 'uploader2', 'password' => 'password2'], ]); } private function authHeader(string $username = 'uploader1', string $password = 'password1'): array { return [ 'Authorization' => 'Basic ' . base64_encode($username . ':' . $password), ]; } public function test_upload_requires_basic_auth(): void { Config::set('file_links.enabled', true); $response = $this->postJson('/api/files/upload', [ 'file' => UploadedFile::fake()->create('sample.txt', 1), ]); $response->assertUnauthorized(); $response->assertHeader('WWW-Authenticate', 'Basic realm="File Upload"'); } public function test_upload_accepts_second_basic_auth_user(): void { Storage::fake('local'); Config::set('file_links.enabled', true); Config::set('file_links.disk', 'local'); Config::set('file_links.directory', 'temporary-links'); $response = $this->withHeaders($this->authHeader('uploader2', 'password2'))->postJson( '/api/files/upload', ['file' => UploadedFile::fake()->create('sample.txt', 1)] ); $response->assertOk(); $response->assertJsonStructure(['path', 'expiresAt', 'url']); } public function test_upload_is_unavailable_when_feature_is_disabled(): void { Config::set('file_links.enabled', false); $response = $this->withHeaders($this->authHeader())->postJson( '/api/files/upload', ['file' => UploadedFile::fake()->create('sample.txt', 1)] ); $response->assertNotFound(); } public function test_it_uploads_file_and_downloads_it_via_temporary_signed_link(): void { Storage::fake('local'); Config::set('file_links.enabled', true); Config::set('file_links.disk', 'local'); Config::set('file_links.directory', 'temporary-links'); $response = $this->withHeaders($this->authHeader())->postJson( '/api/files/upload', ['file' => UploadedFile::fake()->create('sample.txt', 1)] ); $response->assertOk(); $response->assertJsonStructure(['path', 'expiresAt', 'url']); $path = $response->json('path'); Storage::disk('local')->assertExists($path); $url = $response->json('url'); $parts = parse_url($url); $routePath = $parts['path']; if (isset($parts['query'])) { $routePath .= '?' . $parts['query']; } $downloadResponse = $this->get($routePath); $downloadResponse->assertOk(); $downloadResponse->assertHeader('content-disposition'); } }