File size: 3,787 Bytes
9aa5185 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | """Tests for non-interactive setup and first-run headless behavior."""
from argparse import Namespace
from unittest.mock import patch
import pytest
def _make_setup_args(**overrides):
return Namespace(
non_interactive=overrides.get("non_interactive", False),
section=overrides.get("section", None),
reset=overrides.get("reset", False),
)
def _make_chat_args(**overrides):
return Namespace(
continue_last=overrides.get("continue_last", None),
resume=overrides.get("resume", None),
model=overrides.get("model", None),
provider=overrides.get("provider", None),
toolsets=overrides.get("toolsets", None),
verbose=overrides.get("verbose", False),
query=overrides.get("query", None),
worktree=overrides.get("worktree", False),
yolo=overrides.get("yolo", False),
pass_session_id=overrides.get("pass_session_id", False),
quiet=overrides.get("quiet", False),
checkpoints=overrides.get("checkpoints", False),
)
class TestNonInteractiveSetup:
"""Verify setup paths exit cleanly in headless/non-interactive environments."""
def test_non_interactive_flag_skips_wizard(self, capsys):
"""--non-interactive should print guidance and not enter the wizard."""
from hermes_cli.setup import run_setup_wizard
args = _make_setup_args(non_interactive=True)
with (
patch("hermes_cli.setup.ensure_hermes_home"),
patch("hermes_cli.setup.load_config", return_value={}),
patch("hermes_cli.setup.get_hermes_home", return_value="/tmp/.hermes"),
patch("hermes_cli.auth.get_active_provider", side_effect=AssertionError("wizard continued")),
patch("builtins.input", side_effect=AssertionError("input should not be called")),
):
run_setup_wizard(args)
out = capsys.readouterr().out
assert "hermes config set model.provider custom" in out
def test_no_tty_skips_wizard(self, capsys):
"""When stdin has no TTY, the setup wizard should print guidance and return."""
from hermes_cli.setup import run_setup_wizard
args = _make_setup_args(non_interactive=False)
with (
patch("hermes_cli.setup.ensure_hermes_home"),
patch("hermes_cli.setup.load_config", return_value={}),
patch("hermes_cli.setup.get_hermes_home", return_value="/tmp/.hermes"),
patch("hermes_cli.auth.get_active_provider", side_effect=AssertionError("wizard continued")),
patch("sys.stdin") as mock_stdin,
patch("builtins.input", side_effect=AssertionError("input should not be called")),
):
mock_stdin.isatty.return_value = False
run_setup_wizard(args)
out = capsys.readouterr().out
assert "hermes config set model.provider custom" in out
def test_chat_first_run_headless_skips_setup_prompt(self, capsys):
"""Bare `hermes` should not prompt for input when no provider exists and stdin is headless."""
from hermes_cli.main import cmd_chat
args = _make_chat_args()
with (
patch("hermes_cli.main._has_any_provider_configured", return_value=False),
patch("hermes_cli.main.cmd_setup") as mock_setup,
patch("sys.stdin") as mock_stdin,
patch("builtins.input", side_effect=AssertionError("input should not be called")),
):
mock_stdin.isatty.return_value = False
with pytest.raises(SystemExit) as exc:
cmd_chat(args)
assert exc.value.code == 1
mock_setup.assert_not_called()
out = capsys.readouterr().out
assert "hermes config set model.provider custom" in out
|