Files
zk-data-agent/tests/test_remote_slash_commands.py
T

110 lines
4.2 KiB
Python

"""Tests for remote/bridge slash commands ported from the npm source.
Covers /bridge (aliases /remote-control, /rc) and /remote-setup
(alias /web-setup).
"""
from __future__ import annotations
import json
import tempfile
import unittest
from pathlib import Path
from unittest import mock
from src.agent_runtime import LocalCodingAgent
from src.agent_types import AgentRuntimeConfig, ModelConfig
def _make_agent(tmp_dir: str) -> LocalCodingAgent:
return LocalCodingAgent(
model_config=ModelConfig(model='test-model'),
runtime_config=AgentRuntimeConfig(cwd=Path(tmp_dir)),
)
class BridgeCommandTest(unittest.TestCase):
def test_reports_unsupported_status(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
agent = _make_agent(tmp)
out = agent.run('/bridge').final_output
self.assertIn('not implemented', out.lower())
self.assertIn('No active local remote connection', out)
def test_remote_control_alias(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
agent = _make_agent(tmp)
out = agent.run('/remote-control').final_output
self.assertIn('Remote-control bridge', out)
def test_rc_alias(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
agent = _make_agent(tmp)
out = agent.run('/rc').final_output
self.assertIn('Remote-control bridge', out)
def test_named_lookup_misses_unknown_profile(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
agent = _make_agent(tmp)
out = agent.run('/bridge nope').final_output
self.assertIn('No matching remote profile for "nope"', out)
def test_named_lookup_matches_known_profile(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
(Path(tmp) / '.remote.json').write_text(json.dumps({
'profiles': [
{'name': 'edge', 'mode': 'ssh', 'target': 'user@edge.example'},
],
}), encoding='utf-8')
agent = _make_agent(tmp)
out = agent.run('/bridge edge').final_output
self.assertIn('Matched remote profile "edge"', out)
self.assertIn('user@edge.example', out)
class RemoteSetupCommandTest(unittest.TestCase):
def test_includes_web_url(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
agent = _make_agent(tmp)
out = agent.run('/remote-setup').final_output
self.assertIn('https://claude.ai/code', out)
self.assertIn('GitHub CLI', out)
def test_web_setup_alias(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
agent = _make_agent(tmp)
out = agent.run('/web-setup').final_output
self.assertIn('https://claude.ai/code', out)
def test_handles_missing_gh(self) -> None:
with mock.patch('shutil.which', return_value=None):
with tempfile.TemporaryDirectory() as tmp:
agent = _make_agent(tmp)
out = agent.run('/remote-setup').final_output
self.assertIn('not_installed', out)
self.assertIn('cli.github.com', out)
def test_handles_authenticated_gh(self) -> None:
fake = mock.Mock(returncode=0, stdout='Logged in to github.com as octo', stderr='')
with mock.patch('shutil.which', return_value='/usr/bin/gh'), \
mock.patch('subprocess.run', return_value=fake):
with tempfile.TemporaryDirectory() as tmp:
agent = _make_agent(tmp)
out = agent.run('/remote-setup').final_output
self.assertIn('authenticated', out)
self.assertIn('gh auth token', out)
def test_handles_unauthenticated_gh(self) -> None:
fake = mock.Mock(returncode=1, stdout='', stderr='You are not logged into any GitHub hosts')
with mock.patch('shutil.which', return_value='/usr/bin/gh'), \
mock.patch('subprocess.run', return_value=fake):
with tempfile.TemporaryDirectory() as tmp:
agent = _make_agent(tmp)
out = agent.run('/remote-setup').final_output
self.assertIn('not_authenticated', out)
self.assertIn('gh auth login', out)
if __name__ == '__main__':
unittest.main()