#!/usr/bin/env python3 # -*- coding: utf-8 -*- """AIProviderService Ollama-first / Gemini fallback contract.""" from services.ai_provider import AIProviderService from services.gemini_service import GeminiResponse from services.ollama_service import OllamaResponse def test_default_provider_gemini_is_forced_to_ollama(): service = AIProviderService(default_provider="gemini") assert service.default_provider == "ollama" def test_requested_gemini_still_uses_ollama_first(monkeypatch): service = AIProviderService(default_provider="ollama") monkeypatch.setattr( service._ollama, "generate_sales_copy", lambda **_kw: OllamaResponse(True, "ollama copy", "llama3.1:8b"), ) monkeypatch.setattr( service._gemini, "generate_sales_copy", lambda **_kw: (_ for _ in ()).throw(AssertionError("Gemini 不應在 Ollama 成功時被呼叫")), ) result = service.generate_sales_copy("測試商品", provider="gemini") assert result.success is True assert result.provider == "ollama" assert result.content == "ollama copy" def test_gemini_is_called_only_after_ollama_failure(monkeypatch): monkeypatch.setenv("GEMINI_API_HARD_DISABLED", "false") monkeypatch.setenv("GEMINI_FALLBACK_ENABLED", "true") service = AIProviderService(default_provider="ollama") monkeypatch.setattr( service._ollama, "generate_sales_copy", lambda **_kw: OllamaResponse(False, "", "llama3.1:8b", error="ollama down"), ) monkeypatch.setattr( service._gemini, "generate_sales_copy", lambda **_kw: GeminiResponse(True, "gemini fallback", "gemini-2.5-flash"), ) result = service.generate_sales_copy("測試商品") assert result.success is True assert result.provider == "gemini" assert result.content == "gemini fallback" def test_status_never_recommends_gemini_as_primary_provider(): service = AIProviderService(default_provider="ollama") assert service._get_recommended_provider( ollama_ok=False, gemini_ok=True, elephant_ok=False, ) == "none"