Intègre un chat IA capable de manipuler la scène via les mêmes fonctions que l'éditeur manuel (objets, variables, déclencheurs, images générées), avec conversations multiples par écran façon Claude. Corrige au passage le rafraîchissement pjax hors-ordre, l'onglet IA/déclencheurs vide après sélection d'un objet, la comparaison de booléens dans les conditions, et le blocage du glisser-déposer hors du cadre caméra après un redimensionnement de fond par l'IA. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
75 lines
2.8 KiB
Python
75 lines
2.8 KiB
Python
"""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."""
|
|
import ai
|
|
from ai.scenario_client import generate_image_url
|
|
|
|
|
|
def test_generate_image_url_raises_when_not_configured():
|
|
try:
|
|
generate_image_url("un bureau moderne")
|
|
assert False, "devrait lever ScenarioNotConfiguredError"
|
|
except ai.ScenarioNotConfiguredError:
|
|
pass
|
|
|
|
|
|
class _FakeResponse:
|
|
def __init__(self, json_data):
|
|
self._json = json_data
|
|
|
|
def raise_for_status(self):
|
|
pass
|
|
|
|
def json(self):
|
|
return self._json
|
|
|
|
|
|
def test_generate_image_url_polls_until_success_then_returns_the_asset_url(monkeypatch):
|
|
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, auth=None, json=None, timeout=None):
|
|
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, auth=None, timeout=None):
|
|
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 = {"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):
|
|
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")
|
|
assert False, "devrait lever ScenarioGenerationError"
|
|
except ai.ScenarioGenerationError:
|
|
pass
|