tmux-amq/tests/test_cli.py
tegwick 9fcfba3c17
Some checks failed
tamq-ci / test (push) Failing after 7s
feat: display messages as terminal output
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a03397-4d51-7fd1-8ff2-946eb22ea2bc
2026-08-24 22:23:57 +02:00

188 lines
6.4 KiB
Python

import json
from tamq.cli import build_parser, main, normalize_argv
import pytest
def test_help_and_version(capsys):
with pytest.raises(SystemExit) as exc:
main(["--version"])
assert exc.value.code == 0
assert "0.1.0" in capsys.readouterr().out
assert main([]) == 0
assert "usage:" in capsys.readouterr().out
def test_root_help_exposes_repository_shorthand_and_command(capsys):
with pytest.raises(SystemExit) as exc:
main(["--help"])
assert exc.value.code == 0
output = capsys.readouterr().out
assert "tamq [--detach] [--command COMMAND] [--no-display] REPO" in output
assert "With no --command" in output
assert "@TARGET: MESSAGE" in output
def test_attach_delegates_to_tmux(monkeypatch):
calls = []
monkeypatch.delenv("TMUX", raising=False)
monkeypatch.setattr("tamq.cli.subprocess.run", lambda args, check=False: calls.append((args, check)) or type("R", (), {"returncode": 0})())
assert main(["attach", "--session", "demo"]) == 0
assert calls == [(["tmux", "attach-session", "-t", "demo"], False)]
def test_attach_switches_client_when_already_in_tmux(monkeypatch):
calls = []
monkeypatch.setenv("TMUX", "/tmp/tmux,1,0")
monkeypatch.setattr("tamq.cli.subprocess.run", lambda args, check=False: calls.append(args) or type("R", (), {"returncode": 0})())
assert main(["attach"]) == 0
assert calls == [["tmux", "switch-client", "-t", "tamq"]]
def test_start_parser_supports_command_and_cmd_alias():
parser = build_parser()
canonical = parser.parse_args(["start", "--command", "codex --quiet", "a", "b"])
compatibility = parser.parse_args(["start", "--cmd", "claude", "a"])
neutral = parser.parse_args(["start", "a", "b"])
inbox_only = parser.parse_args(["start", "--no-display", "a"])
assert canonical.initial_command == "codex --quiet"
assert canonical.repos == ["a", "b"]
assert compatibility.initial_command == "claude"
assert neutral.initial_command is None
assert inbox_only.no_display is True
def test_repository_first_and_command_first_start_shorthand():
assert normalize_argv(["flex-auth", "audit-core"]) == [
"start",
"flex-auth",
"audit-core",
]
assert normalize_argv(["--command", "codex", "flex-auth"]) == [
"start",
"--command",
"codex",
"flex-auth",
]
assert normalize_argv(["--no-display", "flex-auth"]) == [
"start",
"--no-display",
"flex-auth",
]
assert normalize_argv(["status"]) == ["status"]
assert normalize_argv(["--verbose", "flex-auth", "audit-core"]) == [
"--verbose",
"start",
"flex-auth",
"audit-core",
]
def test_detached_no_service_start_skips_socket_registration(monkeypatch, capsys):
endpoint = type(
"Endpoint",
(),
{
"endpoint_id": "tmux-amq-42",
"instance_key": "tmux-amq-42-boot",
"pid": 42,
"session": "tamq",
"repos": ["a", "b"],
},
)()
class Manager:
def preflight(self, repos, command):
assert repos == ["a", "b"]
assert command is None
return "plan"
def ensure_plan(self, plan, *, tap=True):
assert plan == "plan"
assert tap is False
return endpoint
monkeypatch.setattr("tamq.cli.TmuxManager", Manager)
monkeypatch.setattr("tamq.cli.preflight_runtime_paths", lambda: None)
monkeypatch.setattr("tamq.cli.request", lambda payload: pytest.fail("socket request must not run"))
monkeypatch.setattr("tamq.cli.attach_session", lambda session: pytest.fail("detached start must not attach"))
assert main(["start", "--detach", "--no-service", "a", "b"]) == 0
summary = json.loads(capsys.readouterr().out)
assert summary["service"] is False
assert summary["messaging"] is False
assert summary["repos"] == ["a", "b"]
def test_interactive_no_service_start_attaches(monkeypatch, capsys):
endpoint = type(
"Endpoint",
(),
{
"endpoint_id": "tmux-amq-42",
"instance_key": "tmux-amq-42-boot",
"session": "tamq",
"repos": ["a"],
},
)()
class Manager:
def preflight(self, repos, command):
return "plan"
def ensure_plan(self, plan, *, tap=True):
assert tap is False
return endpoint
attached = []
monkeypatch.setattr("tamq.cli.TmuxManager", Manager)
monkeypatch.setattr("tamq.cli.preflight_runtime_paths", lambda: None)
monkeypatch.setattr("tamq.cli.attach_session", lambda session: attached.append(session) or 0)
assert main(["start", "--no-service", "a"]) == 0
assert attached == ["tamq"]
assert json.loads(capsys.readouterr().out)["repos"] == ["a"]
def test_registration_failure_rolls_back_created_windows(monkeypatch, capsys):
endpoint = type(
"Endpoint",
(),
{
"endpoint_id": "tmux-amq-42",
"instance_key": "tmux-amq-42-boot",
"pid": 42,
"session": "tamq",
"repos": ["a"],
},
)()
rolled_back = []
class Manager:
def preflight(self, repos, command):
return "plan"
def ensure_plan(self, plan, *, tap=True):
assert tap is False
return endpoint
def rollback(self, value):
rolled_back.append(value)
async def failed_registration(payload):
return {"ok": False, "error": "denied"}
monkeypatch.setattr("tamq.cli.TmuxManager", Manager)
monkeypatch.setattr("tamq.cli.preflight_runtime_paths", lambda: None)
monkeypatch.setattr("tamq.cli.ensure_output_service", lambda: True)
monkeypatch.setattr("tamq.cli.request", failed_registration)
assert main(["start", "--detach", "a"]) == 1
assert rolled_back == [endpoint]
assert "endpoint registration failed: denied" in capsys.readouterr().err
def test_tap_requires_explicit_command_and_service(capsys):
assert main(["start", "--tap", "a"]) == 2
assert "--tap requires an explicit --command" in capsys.readouterr().err
assert main(["start", "--tap", "--no-service", "--command", "sh", "a"]) == 2
assert "--tap cannot be combined with --no-service" in capsys.readouterr().err
assert main(["start", "--tap", "--no-display", "--command", "sh", "a"]) == 2
assert "--tap cannot be combined with --no-display" in capsys.readouterr().err