'test-runware-key', 'services.runware.base_url' => 'https://api.runware.ai/v1', 'ai-editing.providers.runware.model_search_min_chars' => 2, 'ai-editing.providers.runware.model_search_limit' => 25, 'ai-editing.providers.runware.model_search_cache_seconds' => 300, ]); Http::fake([ 'https://api.runware.ai/v1' => Http::response([ 'data' => [ [ 'taskType' => 'modelSearch', 'air' => 'runware:100@1', 'name' => 'Flux Portrait', 'architecture' => 'flux', 'category' => 'photo', 'defaultWidth' => 1216, 'defaultHeight' => 832, 'defaultSteps' => 30, 'defaultCFG' => 3.5, 'minWidth' => 768, 'maxWidth' => 2048, 'widthStep' => 64, 'minHeight' => 512, 'maxHeight' => 2048, 'heightStep' => 64, ], ], ], 200), ]); $service = app(RunwareModelSearchService::class); $options = $service->searchOptions('flux'); $model = $service->findByAir('runware:100@1'); $label = $service->labelForModel('runware:100@1'); $this->assertArrayHasKey('runware:100@1', $options); $this->assertStringContainsString('Flux Portrait', (string) $options['runware:100@1']); $this->assertIsArray($model); $this->assertSame(1216, $model['defaults']['width'] ?? null); $this->assertSame(768, $model['constraints']['min_width'] ?? null); $this->assertIsString($label); $this->assertStringContainsString('runware:100@1', (string) $label); $service->searchOptions('flux'); Http::assertSentCount(2); } public function test_it_returns_empty_results_when_runware_api_key_is_missing(): void { config([ 'services.runware.api_key' => null, ]); $service = app(RunwareModelSearchService::class); $this->assertSame([], $service->search('flux')); $this->assertSame([], $service->searchOptions('flux')); $this->assertNull($service->findByAir('runware:100@1')); } }