183 lines
6.2 KiB
Python
183 lines
6.2 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from external_connector.providers.vendor_cli import VendorCliProvider
|
|
from external_connector.state import SidecarStateStore
|
|
|
|
|
|
class FakeRunner:
|
|
def __init__(self) -> None:
|
|
self.commands: list[list[str]] = []
|
|
self.cwd: str | None = None
|
|
self.timeout: float | None = None
|
|
|
|
def __call__(self, command: list[str], cwd: str, timeout: float) -> tuple[int, str, str]:
|
|
self.commands.append(command)
|
|
self.cwd = cwd
|
|
self.timeout = timeout
|
|
return 0, "connected account=weixin:me", ""
|
|
|
|
|
|
def test_vendor_cli_provider_uses_env_command_templates(tmp_path) -> None:
|
|
runner = FakeRunner()
|
|
provider = VendorCliProvider(
|
|
store=SidecarStateStore(tmp_path / "state.json"),
|
|
env={
|
|
"WEIXIN_CONNECT_COMMAND": "vendor-weixin install --state {state_dir}",
|
|
"CONNECTOR_COMMAND_TIMEOUT_SECONDS": "30",
|
|
},
|
|
runner=runner,
|
|
)
|
|
|
|
session = provider.start_session(
|
|
{
|
|
"kind": "weixin",
|
|
"connectionId": "conn_1",
|
|
"channelId": "weixin-main",
|
|
"displayName": "Weixin Main",
|
|
"callbackBaseUrl": "http://beaver:8080",
|
|
"options": {},
|
|
}
|
|
)
|
|
|
|
assert session["status"] in {"waiting_for_user", "connected"}
|
|
assert runner.commands[0][0] == "vendor-weixin"
|
|
assert runner.cwd == str(tmp_path)
|
|
assert runner.timeout == 30.0
|
|
|
|
|
|
def test_vendor_cli_provider_redacts_sensitive_error(tmp_path) -> None:
|
|
def runner(command: list[str], cwd: str, timeout: float) -> tuple[int, str, str]:
|
|
return 1, "", "failed secret-token appSecret=abc"
|
|
|
|
provider = VendorCliProvider(
|
|
store=SidecarStateStore(tmp_path / "state.json"),
|
|
env={"FEISHU_CONNECT_COMMAND": "vendor-feishu install --secret abc"},
|
|
runner=runner,
|
|
)
|
|
|
|
session = provider.start_session(
|
|
{
|
|
"kind": "feishu",
|
|
"connectionId": "conn_1",
|
|
"channelId": "feishu-main",
|
|
"displayName": "Feishu Main",
|
|
"callbackBaseUrl": "http://beaver:8080",
|
|
"options": {},
|
|
}
|
|
)
|
|
|
|
assert session["status"] == "error"
|
|
assert "secret-token" not in (session["error"] or "")
|
|
assert "appSecret=abc" not in (session["error"] or "")
|
|
|
|
|
|
def test_vendor_cli_provider_refreshes_session_from_status_command_json(tmp_path) -> None:
|
|
calls: list[list[str]] = []
|
|
|
|
def runner(command: list[str], cwd: str, timeout: float) -> tuple[int, str, str]:
|
|
calls.append(command)
|
|
if command[0] == "vendor-weixin-status":
|
|
return (
|
|
0,
|
|
'{"status":"qr_ready","qrImage":"data:image/png;base64,abc","qrCode":"weixin://scan","metadata":{"phase":"scan"}}',
|
|
"",
|
|
)
|
|
return 0, "waiting", ""
|
|
|
|
provider = VendorCliProvider(
|
|
store=SidecarStateStore(tmp_path / "state.json"),
|
|
env={
|
|
"WEIXIN_CONNECT_COMMAND": "vendor-weixin install --state {state_dir}",
|
|
"WEIXIN_STATUS_COMMAND": "vendor-weixin-status --state {state_dir} --session {session_id}",
|
|
},
|
|
runner=runner,
|
|
)
|
|
session = provider.start_session(
|
|
{
|
|
"kind": "weixin",
|
|
"connectionId": "conn_1",
|
|
"channelId": "weixin-main",
|
|
"displayName": "Weixin Main",
|
|
"callbackBaseUrl": "http://beaver:8080",
|
|
"options": {},
|
|
}
|
|
)
|
|
|
|
refreshed = provider.get_session(session["sessionId"])
|
|
|
|
assert calls[1][0] == "vendor-weixin-status"
|
|
assert refreshed["status"] == "qr_ready"
|
|
assert refreshed["qrImage"] == "data:image/png;base64,abc"
|
|
assert refreshed["qrCode"] == "weixin://scan"
|
|
assert refreshed["metadata"]["phase"] == "scan"
|
|
|
|
|
|
def test_vendor_cli_provider_refreshes_connected_session_from_key_value_status(tmp_path) -> None:
|
|
def runner(command: list[str], cwd: str, timeout: float) -> tuple[int, str, str]:
|
|
if command[0] == "vendor-feishu-status":
|
|
return 0, "status=connected accountId=feishu:tenant-bot displayName=FeishuBot", ""
|
|
return 0, "waiting", ""
|
|
|
|
provider = VendorCliProvider(
|
|
store=SidecarStateStore(tmp_path / "state.json"),
|
|
env={
|
|
"FEISHU_CONNECT_COMMAND": "vendor-feishu install --state {state_dir}",
|
|
"FEISHU_STATUS_COMMAND": "vendor-feishu-status --state {state_dir}",
|
|
},
|
|
runner=runner,
|
|
)
|
|
session = provider.start_session(
|
|
{
|
|
"kind": "feishu",
|
|
"connectionId": "conn_1",
|
|
"channelId": "feishu-main",
|
|
"displayName": "Feishu Main",
|
|
"callbackBaseUrl": "http://beaver:8080",
|
|
"options": {},
|
|
}
|
|
)
|
|
|
|
refreshed = provider.get_session(session["sessionId"])
|
|
|
|
assert refreshed["status"] == "connected"
|
|
assert refreshed["accountId"] == "feishu:tenant-bot"
|
|
assert refreshed["displayName"] == "FeishuBot"
|
|
|
|
|
|
def test_vendor_cli_provider_send_uses_payload_file_and_dedupes_result(tmp_path) -> None:
|
|
payloads: list[dict[str, object]] = []
|
|
commands: list[list[str]] = []
|
|
|
|
def runner(command: list[str], cwd: str, timeout: float) -> tuple[int, str, str]:
|
|
commands.append(command)
|
|
payload_path = Path(command[command.index("--payload") + 1])
|
|
payloads.append(json.loads(payload_path.read_text(encoding="utf-8")))
|
|
return 0, '{"providerMessageId":"wx-msg-1"}', ""
|
|
|
|
provider = VendorCliProvider(
|
|
store=SidecarStateStore(tmp_path / "state.json"),
|
|
env={"WEIXIN_SEND_COMMAND": "vendor-weixin-send --payload {payload_path}"},
|
|
runner=runner,
|
|
)
|
|
payload = {
|
|
"requestId": "out_1",
|
|
"connectionId": "conn_1",
|
|
"channelId": "weixin-main",
|
|
"kind": "weixin",
|
|
"target": {"peerId": "peer-1", "peerType": "dm", "threadId": None},
|
|
"content": "hello world",
|
|
"metadata": {"source": "test"},
|
|
}
|
|
|
|
first = provider.send(payload)
|
|
duplicate = provider.send(payload)
|
|
|
|
assert first == {"ok": True, "providerMessageId": "wx-msg-1"}
|
|
assert duplicate == first
|
|
assert len(commands) == 1
|
|
assert payloads[0]["content"] == "hello world"
|
|
assert payloads[0]["target"] == {"peerId": "peer-1", "peerType": "dm", "threadId": None}
|