import pytest
from models import MCPResponse
from services.state.external_changes_scanner import external_changes_scanner
from services.state.external_changes_scanner import ExternalChangesState
from .test_helpers import DummyContext
@pytest.mark.asyncio
async def test_refresh_unity_recovers_from_retry_disconnect(monkeypatch):
"""
Option A: if Unity disconnects and the transport returns hint=retry, refresh_unity(wait_for_ready=true)
should poll readiness and then return success + clear external dirty.
"""
from services.tools.refresh_unity import refresh_unity
ctx = DummyContext()
ctx.set_state("unity_instance", "UnityMCPTests@cc8756d4cce0805a")
# Seed dirty state
inst = "UnityMCPTests@cc8756d4cce0805a"
external_changes_scanner._states[inst] = ExternalChangesState(dirty=True, dirty_since_unix_ms=1)
async def fake_send_with_unity_instance(send_fn, unity_instance, command_type, params, **kwargs):
if command_type == "refresh_unity":
return {"success": False, "error": "disconnected", "hint": "retry"}
elif command_type == "get_editor_state":
return {"success": True, "data": {"advice": {"ready_for_tools": True}}}
raise ValueError(f"Unexpected command: {command_type}")
import services.tools.refresh_unity as refresh_mod
monkeypatch.setattr(refresh_mod.unity_transport, "send_with_unity_instance", fake_send_with_unity_instance)
resp = await refresh_unity(ctx, wait_for_ready=True)
payload = resp.model_dump() if hasattr(resp, "model_dump") else resp
assert payload["success"] is True
assert payload.get("data", {}).get("recovered_from_disconnect") is True
# Dirty should be cleared
assert external_changes_scanner._states[inst].dirty is False