forked from Zakaria/hermes-agent
Hermes-agent
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
"""End-to-end integration test for the destructive-slash inline-skip path.
|
||||
|
||||
Drives ``HermesCLI.process_command("/reset now")`` against a minimal stand-in
|
||||
and verifies:
|
||||
|
||||
1. ``new_session`` was invoked (the command actually ran)
|
||||
2. ``_prompt_text_input_modal`` was NOT invoked (modal bypassed)
|
||||
3. The skip token did not leak into the session title
|
||||
|
||||
This is the regression test for issue #30768 — the inline-skip escape hatch
|
||||
must work without ever touching the modal, on every platform.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
def _make_cli_stub():
|
||||
"""Build a minimal HermesCLI-shaped object that can run ``process_command``
|
||||
for the destructive-slash branches without spinning up a real TUI."""
|
||||
from cli import HermesCLI
|
||||
|
||||
new_session_calls = []
|
||||
|
||||
def _capture_new_session(self_, title=None, silent=False):
|
||||
new_session_calls.append({"title": title, "silent": silent})
|
||||
|
||||
self_ = SimpleNamespace(
|
||||
_app=None,
|
||||
_prompt_text_input_modal=lambda **_kw: (_ for _ in ()).throw(
|
||||
AssertionError("modal must not be invoked when inline-skip token present")
|
||||
),
|
||||
new_session=lambda **kw: _capture_new_session(self_, **kw),
|
||||
# Stub out side-effects the destructive-slash branches reach for.
|
||||
console=SimpleNamespace(clear=lambda: None),
|
||||
compact=False,
|
||||
model="stub-model",
|
||||
session_id="stub-session",
|
||||
enabled_toolsets=[],
|
||||
_pending_title=None,
|
||||
_session_db=None,
|
||||
)
|
||||
# Bind the methods we need under test.
|
||||
self_._split_destructive_skip = HermesCLI._split_destructive_skip
|
||||
self_._confirm_destructive_slash = HermesCLI._confirm_destructive_slash.__get__(
|
||||
self_, type(self_)
|
||||
)
|
||||
self_.process_command = HermesCLI.process_command.__get__(self_, type(self_))
|
||||
return self_, new_session_calls
|
||||
|
||||
|
||||
def test_reset_now_invokes_new_session_without_modal():
|
||||
"""``/reset now`` runs ``new_session`` and never touches the modal."""
|
||||
self_, calls = _make_cli_stub()
|
||||
|
||||
with patch(
|
||||
"cli.load_cli_config",
|
||||
return_value={"approvals": {"destructive_slash_confirm": True}},
|
||||
):
|
||||
self_.process_command("/reset now")
|
||||
|
||||
assert calls, "new_session was never invoked"
|
||||
# The /new branch passes title=None when there's no non-skip remainder.
|
||||
assert calls[0]["title"] is None
|
||||
|
||||
|
||||
def test_new_yes_with_title_preserves_title():
|
||||
"""``/new --yes My Session`` runs ``new_session(title='My Session')``."""
|
||||
self_, calls = _make_cli_stub()
|
||||
|
||||
with patch(
|
||||
"cli.load_cli_config",
|
||||
return_value={"approvals": {"destructive_slash_confirm": True}},
|
||||
):
|
||||
self_.process_command("/new --yes My Session")
|
||||
|
||||
assert calls, "new_session was never invoked"
|
||||
assert calls[0]["title"] == "My Session"
|
||||
|
||||
|
||||
def test_new_without_skip_token_still_consults_modal():
|
||||
"""``/new My Session`` (no skip token) must reach the modal.
|
||||
|
||||
Sanity check that we haven't accidentally short-circuited the normal path.
|
||||
"""
|
||||
from cli import HermesCLI
|
||||
|
||||
new_session_calls = []
|
||||
modal_calls = []
|
||||
|
||||
def _capture_new_session(self_, title=None, silent=False):
|
||||
new_session_calls.append({"title": title, "silent": silent})
|
||||
|
||||
def _record_modal(**kw):
|
||||
modal_calls.append(kw)
|
||||
# Simulate user cancelling so new_session is not called.
|
||||
return "3"
|
||||
|
||||
self_ = SimpleNamespace(
|
||||
_app=None,
|
||||
_prompt_text_input_modal=_record_modal,
|
||||
new_session=lambda **kw: _capture_new_session(self_, **kw),
|
||||
console=SimpleNamespace(clear=lambda: None),
|
||||
compact=False,
|
||||
model="stub-model",
|
||||
session_id="stub-session",
|
||||
enabled_toolsets=[],
|
||||
_pending_title=None,
|
||||
_session_db=None,
|
||||
)
|
||||
self_._split_destructive_skip = HermesCLI._split_destructive_skip
|
||||
self_._normalize_slash_confirm_choice = HermesCLI._normalize_slash_confirm_choice.__get__(
|
||||
self_, type(self_)
|
||||
)
|
||||
self_._confirm_destructive_slash = HermesCLI._confirm_destructive_slash.__get__(
|
||||
self_, type(self_)
|
||||
)
|
||||
self_.process_command = HermesCLI.process_command.__get__(self_, type(self_))
|
||||
|
||||
with patch(
|
||||
"cli.load_cli_config",
|
||||
return_value={"approvals": {"destructive_slash_confirm": True}},
|
||||
):
|
||||
self_.process_command("/new My Session")
|
||||
|
||||
assert modal_calls, "modal must be reached when no skip token is present"
|
||||
assert not new_session_calls, "user cancelled — new_session must not run"
|
||||
Reference in New Issue
Block a user