"""ai/scenario_client.py — voir plan Phase 2, §3 : jamais un vrai appel réseau ici (requests.post/get monkeypatchés), et une configuration incomplète (clé/secret/modèle absents) doit échouer proprement AVANT toute tentative réseau.""" from typing import Any import pytest import ai from ai.scenario_client import generate_image_url def test_generate_image_url_raises_when_not_configured() -> None: try: generate_image_url("un bureau moderne") raise AssertionError("devrait lever ScenarioNotConfiguredError") except ai.ScenarioNotConfiguredError: pass class _FakeResponse: def __init__(self, json_data: Any) -> None: self._json = json_data def raise_for_status(self) -> None: pass def json(self) -> Any: return self._json def test_generate_image_url_polls_until_success_then_returns_the_asset_url(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setenv("SCENARIO_API_KEY", "fake-key") monkeypatch.setenv("SCENARIO_API_SECRET", "fake-secret") monkeypatch.setenv("SCENARIO_MODEL_ID", "fake-model") calls = {"jobs": 0} def fake_post(url: str, auth: Any = None, json: Any = None, timeout: int | None = None) -> Any: assert url.endswith("/generate/txt2img") assert json["prompt"] == "un bureau moderne" assert json["modelId"] == "fake-model" return _FakeResponse({"job": {"jobId": "job_1"}}) def fake_get(url: str, auth: Any = None, timeout: int | None = None) -> Any: if "/jobs/" in url: calls["jobs"] += 1 # Simule un job encore en cours au premier appel, réussi ensuite. status = "running" if calls["jobs"] == 1 else "success" body: dict[str, Any] = {"job": {"status": status}} if status == "success": body["job"]["metadata"] = {"assetIds": ["asset_1"]} return _FakeResponse(body) assert url.endswith("/assets/asset_1") return _FakeResponse({"asset": {"url": "https://scenario.example/final.png"}}) monkeypatch.setattr("ai.scenario_client.requests.post", fake_post) monkeypatch.setattr("ai.scenario_client.requests.get", fake_get) monkeypatch.setattr("ai.scenario_client.time.sleep", lambda s: None) url = generate_image_url("un bureau moderne") assert url == "https://scenario.example/final.png" assert calls["jobs"] == 2 def test_generate_image_url_raises_on_job_failure(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setenv("SCENARIO_API_KEY", "fake-key") monkeypatch.setenv("SCENARIO_API_SECRET", "fake-secret") monkeypatch.setenv("SCENARIO_MODEL_ID", "fake-model") monkeypatch.setattr("ai.scenario_client.requests.post", lambda *a, **k: _FakeResponse({"job": {"jobId": "job_1"}})) monkeypatch.setattr( "ai.scenario_client.requests.get", lambda *a, **k: _FakeResponse({"job": {"status": "failure"}}) ) try: generate_image_url("un bureau") raise AssertionError("devrait lever ScenarioGenerationError") except ai.ScenarioGenerationError: pass