feat(testing): stabilize simulation suite and fix gemini caching

This commit is contained in:
2026-02-25 01:44:46 -05:00
parent fb80ce8c5a
commit c952d2f67b
23 changed files with 784 additions and 596 deletions

View File

@@ -3,12 +3,12 @@ import json
import time
class ApiHookClient:
def __init__(self, base_url="http://127.0.0.1:8999", max_retries=5, retry_delay=2):
def __init__(self, base_url="http://127.0.0.1:8999", max_retries=2, retry_delay=0.1):
self.base_url = base_url
self.max_retries = max_retries
self.retry_delay = retry_delay
def wait_for_server(self, timeout=10):
def wait_for_server(self, timeout=3):
"""
Polls the /status endpoint until the server is ready or timeout is reached.
"""
@@ -18,7 +18,7 @@ class ApiHookClient:
if self.get_status().get('status') == 'ok':
return True
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
time.sleep(0.5)
time.sleep(0.1)
return False
def _make_request(self, method, endpoint, data=None):
@@ -26,12 +26,15 @@ class ApiHookClient:
headers = {'Content-Type': 'application/json'}
last_exception = None
# Lower request timeout for local server
req_timeout = 0.5
for attempt in range(self.max_retries + 1):
try:
if method == 'GET':
response = requests.get(url, timeout=5)
response = requests.get(url, timeout=req_timeout)
elif method == 'POST':
response = requests.post(url, json=data, headers=headers, timeout=5)
response = requests.post(url, json=data, headers=headers, timeout=req_timeout)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
@@ -59,7 +62,7 @@ class ApiHookClient:
"""Checks the health of the hook server."""
url = f"{self.base_url}/status"
try:
response = requests.get(url, timeout=1)
response = requests.get(url, timeout=0.2)
response.raise_for_status()
return response.json()
except Exception:
@@ -111,9 +114,26 @@ class ApiHookClient:
def get_value(self, item):
"""Gets the value of a GUI item via its mapped field."""
try:
# First try direct field querying via POST
res = self._make_request('POST', '/api/gui/value', data={"field": item})
if res and "value" in res:
v = res.get("value")
if v is not None:
return v
except Exception:
pass
try:
# Try GET fallback
res = self._make_request('GET', f'/api/gui/value/{item}')
return res.get("value")
except Exception as e:
if res and "value" in res:
v = res.get("value")
if v is not None:
return v
except Exception:
pass
try:
# Fallback for thinking/live/prior which are in diagnostics
diag = self._make_request('GET', '/api/gui/diagnostics')
if item in diag:
@@ -127,7 +147,9 @@ class ApiHookClient:
key = mapping.get(item)
if key and key in diag:
return diag[key]
return None
except Exception:
pass
return None
def click(self, item, *args, **kwargs):
"""Simulates a click on a GUI button or item."""
@@ -162,7 +184,7 @@ class ApiHookClient:
except Exception:
return []
def wait_for_event(self, event_type, timeout=10):
def wait_for_event(self, event_type, timeout=5):
"""Polls for a specific event type."""
start = time.time()
while time.time() - start < timeout:
@@ -170,9 +192,18 @@ class ApiHookClient:
for ev in events:
if ev.get("type") == event_type:
return ev
time.sleep(1.0)
time.sleep(0.1) # Fast poll
return None
def wait_for_value(self, item, expected, timeout=5):
"""Polls until get_value(item) == expected."""
start = time.time()
while time.time() - start < timeout:
if self.get_value(item) == expected:
return True
time.sleep(0.1) # Fast poll
return False
def reset_session(self):
"""Simulates clicking the 'Reset Session' button in the GUI."""
return self.click("btn_reset")