Files
OpenJarvis/tests/cli/test_channel_cmd.py
T
Jon Saad-FalconandClaude Opus 4.6 a433740809 Add 30 tests for security/channels coverage gaps and 6 new docs pages
Tests: GuardrailsEngine.stream() async tests, OpenClawChannelBridge listener_loop
tests, channel CLI command tests, FileReadTool sensitive file blocking, ingest_path
sensitive file filtering, SecurityConfig/ChannelConfig config tests. Documentation:
new user guides, architecture pages, and API references for Security and Channels
modules; updated CLAUDE.md, configuration docs, CLI reference, and mkdocs.yml nav.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 03:31:19 +00:00

95 lines
3.3 KiB
Python

"""Tests for the ``jarvis channel`` CLI commands."""
from __future__ import annotations
from unittest import mock
from click.testing import CliRunner
from openjarvis.channels._stubs import ChannelStatus
from openjarvis.cli import cli
def _patch_channel(
list_channels=None,
send_return=True,
status_return=ChannelStatus.DISCONNECTED,
):
"""Return patches for load_config and OpenClawChannelBridge."""
cfg = mock.MagicMock()
cfg.channel.gateway_url = "ws://127.0.0.1:18789/ws"
bridge_instance = mock.MagicMock()
bridge_instance.list_channels.return_value = list_channels or []
bridge_instance.send.return_value = send_return
bridge_instance.status.return_value = status_return
config_patch = mock.patch(
"openjarvis.core.config.load_config", return_value=cfg,
)
bridge_patch = mock.patch(
"openjarvis.channels.openclaw_bridge.OpenClawChannelBridge",
return_value=bridge_instance,
)
return config_patch, bridge_patch, bridge_instance
class TestChannelHelp:
def test_subcommands_in_help(self) -> None:
result = CliRunner().invoke(cli, ["channel", "--help"])
assert result.exit_code == 0
assert "list" in result.output
assert "send" in result.output
assert "status" in result.output
class TestChannelList:
def test_list_with_channels(self) -> None:
config_p, bridge_p, _ = _patch_channel(list_channels=["slack", "discord"])
with config_p, bridge_p:
result = CliRunner().invoke(cli, ["channel", "list"])
assert result.exit_code == 0
assert "slack" in result.output
assert "discord" in result.output
def test_list_no_channels(self) -> None:
config_p, bridge_p, _ = _patch_channel(list_channels=[])
with config_p, bridge_p:
result = CliRunner().invoke(cli, ["channel", "list"])
assert result.exit_code == 0
assert "No channels available" in result.output
def test_list_connection_error(self) -> None:
config_p, bridge_p, inst = _patch_channel()
inst.list_channels.side_effect = ConnectionError("refused")
with config_p, bridge_p:
result = CliRunner().invoke(cli, ["channel", "list"])
assert result.exit_code == 0
assert "Failed" in result.output or "refused" in result.output
class TestChannelSend:
def test_send_success(self) -> None:
config_p, bridge_p, _ = _patch_channel(send_return=True)
with config_p, bridge_p:
result = CliRunner().invoke(cli, ["channel", "send", "slack", "Hello!"])
assert result.exit_code == 0
assert "Message sent" in result.output
def test_send_failure(self) -> None:
config_p, bridge_p, _ = _patch_channel(send_return=False)
with config_p, bridge_p:
result = CliRunner().invoke(cli, ["channel", "send", "slack", "Hello!"])
assert result.exit_code == 0
assert "Failed to send" in result.output
class TestChannelStatus:
def test_status_shows_info(self) -> None:
config_p, bridge_p, _ = _patch_channel(status_return=ChannelStatus.DISCONNECTED)
with config_p, bridge_p:
result = CliRunner().invoke(cli, ["channel", "status"])
assert result.exit_code == 0
assert "disconnected" in result.output
assert "127.0.0.1" in result.output