← Files Smart Model RouterARCHIVED FILE
skills/smart-model-routing/tests/test_ui.py
3.63 KB · Oct 4, 2026 · 12:33 UTC
"""Offline UI workflow tests. No Codex process or model request is started."""
from pathlib import Path
import sys
import tempfile
import time
import tkinter as tk
import unittest
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "scripts"))
from app import App
from routing import MODELS, classify
class FakeClient:
def __init__(self, events):
self.events = events
self.calls = []
def request(self, method, params):
self.calls.append((method, params))
if method == "thread/start":
return {"thread": {"id": "ui-thread"}}
if method == "turn/start":
turn = {"id": "ui-turn", "status": "completed"}
# Deliberately complete before the worker handles the RPC response.
self.events.put({"method": "turn/completed", "params": {"threadId": "ui-thread", "turn": turn}})
return {"turn": turn}
return {}
class UiTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory(dir=ROOT)
self.root = tk.Tk()
self.root.withdraw()
self.app = App(self.root, Path(self.temp.name), connect=False)
self.app.workspace.set(str(ROOT))
self.app.client = FakeClient(self.app.events)
self.app.catalog = [{"model": x, "supportedReasoningEfforts": [{"reasoningEffort": e} for e in ("low", "medium", "high", "xhigh")]} for x in MODELS.values()]
def tearDown(self):
self.app.closing = True
self.root.destroy()
self.temp.cleanup()
def settle(self):
deadline = time.monotonic() + 3
while time.monotonic() < deadline:
self.root.update()
if not self.app.busy and self.app.events.empty():
return
time.sleep(.02)
self.fail("UI workflow did not settle")
def test_two_ui_submissions_switch_model_keep_thread(self):
self.app.prompt.insert("1.0", "翻譯這段英文")
self.app.submit()
self.settle()
self.app.prompt.insert("1.0", "調查跨檔案記憶體洩漏")
self.app.submit()
self.settle()
turns = [p for m, p in self.app.client.calls if m == "turn/start"]
self.assertEqual([x["model"] for x in turns], [MODELS["luna"], MODELS["sol"]])
self.assertEqual([x["effort"] for x in turns], ["low", "high"])
self.assertEqual([x["threadId"] for x in turns], ["ui-thread", "ui-thread"])
self.assertEqual(len([1 for m, _ in self.app.client.calls if m == "thread/start"]), 1)
self.assertFalse(self.app.busy)
self.assertIsNone(self.app.turn_id)
def test_busy_blocks_duplicate_submit(self):
self.app.busy = True
self.app.prompt.insert("1.0", "新增功能")
self.app.submit()
self.assertEqual(self.app.client.calls, [])
def test_failure_does_not_retry_or_escalate(self):
self.app.previous = self.app.active_route = classify("翻譯英文")
self.app.busy = True
self.app.handle({"method": "turn/completed", "params": {"turn": {"status": "failed", "error": {"message": "UsageLimitExceeded"}}}})
self.assertEqual(self.app.client.calls, [])
self.assertEqual(self.app.previous.tier, "luna")
self.assertFalse(self.app.busy)
def test_uncertain_submission_disables_new_model_calls(self):
self.app.handle({"method": "router/sendFailed", "params": {"message": "timeout", "uncertain": True}})
self.app.prompt.insert("1.0", "新增功能")
self.app.submit()
self.assertEqual(self.app.client.calls, [])
self.assertFalse(self.app.catalog)
if __name__ == "__main__":
unittest.main(verbosity=2)
SHA-256: 1cc8232b01d9f93611ce5ed7809bbb970172ab8392a9e729811e19a6374701dc