AutoRpa/rpa_yisaiqi/tests/test_runtime_shell.py

76 lines
2.4 KiB
Python

import json
from rpa_yisaiqi.callback_client import StateCenterClient
from rpa_yisaiqi.runtime.errors import LoginFailed, NodeError
from rpa_yisaiqi.runtime.shell import execute_node
class FakeHttp:
def __init__(self, responses=None):
self.requests = []
self.responses = list(responses or [{"ok": True}, {"ok": True, "next_node": "PRODUCT_MATCH"}])
def __call__(self, request, timeout):
body = json.loads(request.data.decode("utf-8")) if request.data else None
self.requests.append({
"url": request.full_url,
"method": request.get_method(),
"body": body,
})
return FakeResponse(self.responses.pop(0))
class FakeResponse:
def __init__(self, payload):
self.payload = payload
def __enter__(self):
return self
def __exit__(self, exc_type, exc, tb):
return False
def read(self):
return json.dumps(self.payload).encode("utf-8")
def test_execute_node_starts_then_completes_with_runner_payload():
http = FakeHttp()
client = StateCenterClient("http://state-center:8000", "dev-agent-token", opener=http)
result = execute_node(
client,
"JOB-1",
"ORDER_FETCH",
lambda: {"summary": {"orderCount": 1}, "businessRefs": {}},
attempt_no=1,
)
assert result["next_node"] == "PRODUCT_MATCH"
assert [req["url"].rsplit("/", 1)[-1] for req in http.requests] == ["start", "complete"]
assert http.requests[1]["body"]["summary"] == {"orderCount": 1}
assert http.requests[1]["body"]["attemptNo"] == 1
def test_execute_node_maps_login_failure_to_fail_callback():
http = FakeHttp([{"ok": True}, {"ok": True, "job_status": "FAILED_RETRYABLE"}])
client = StateCenterClient("http://state-center:8000", "dev-agent-token", opener=http)
def failing():
raise LoginFailed("登录失败")
result = execute_node(client, "JOB-1", "ORDER_FETCH", failing)
assert result["job_status"] == "FAILED_RETRYABLE"
assert http.requests[1]["url"].endswith("/fail")
assert http.requests[1]["body"]["errorCode"] == "SYS_LOGIN_FAIL"
assert http.requests[1]["body"]["retryable"] is True
assert http.requests[1]["body"]["routeRole"] == "OPS"
def test_node_error_carries_default_ui_code():
exc = NodeError("元素找不到")
assert exc.error_code == "UI_ELEMENT_NOT_FOUND"
assert exc.retryable is False
assert exc.route_role == "OPS"