97f8f56468
Replace getattr(tui_app_module, '_strip_pending_reference_token') with direct attribute access. Ruff B009 flags this as unnecessary because the attribute is a compile-time constant — normal access is equally safe and preferred.
163 lines
5.6 KiB
Python
163 lines
5.6 KiB
Python
"""Behave steps for TUI input mode router."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import shutil
|
|
import tempfile
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
from behave import given, then, when
|
|
from behave.runner import Context
|
|
|
|
from cleveragents.tui import app as tui_app_module
|
|
from cleveragents.tui.input import reference_parser
|
|
from cleveragents.tui.input.modes import InputModeRouter
|
|
from cleveragents.tui.input.reference_parser import parse_references, suggestions
|
|
from cleveragents.tui.input.shell_exec import looks_dangerous
|
|
|
|
|
|
@when('I parse TUI references for "{line}"')
|
|
def step_parse_references(context: Context, line: str) -> None:
|
|
context.tui_ref_result = parse_references(line)
|
|
|
|
|
|
@then('the parsed line should include "{token}"')
|
|
def step_parsed_contains(context: Context, token: str) -> None:
|
|
assert token in context.tui_ref_result.expanded_line
|
|
|
|
|
|
@when('I route TUI input "{line}"')
|
|
def step_route_input(context: Context, line: str) -> None:
|
|
router = InputModeRouter(command_handler=lambda raw: f"ok:/{raw}")
|
|
context.tui_mode_result = router.process(line)
|
|
|
|
|
|
@then('the TUI mode should be "{mode}"')
|
|
def step_mode_equals(context: Context, mode: str) -> None:
|
|
assert context.tui_mode_result.mode.value == mode
|
|
|
|
|
|
@then('the TUI command result should be "{value}"')
|
|
def step_command_result(context: Context, value: str) -> None:
|
|
assert context.tui_mode_result.command_result == value
|
|
|
|
|
|
@then('the TUI shell stdout should contain "{value}"')
|
|
def step_shell_stdout(context: Context, value: str) -> None:
|
|
shell = context.tui_mode_result.shell_result
|
|
assert shell is not None
|
|
assert value in shell.stdout
|
|
|
|
|
|
@then('the TUI shell stderr should contain "{value}"')
|
|
def step_shell_stderr(context: Context, value: str) -> None:
|
|
shell = context.tui_mode_result.shell_result
|
|
assert shell is not None
|
|
assert value in shell.stderr
|
|
|
|
|
|
@when('I check shell danger detection for "{command}"')
|
|
def step_check_shell_danger(context: Context, command: str) -> None:
|
|
context.shell_danger_result = looks_dangerous(command)
|
|
|
|
|
|
@then('shell danger detection result should be "{value}"')
|
|
def step_shell_danger_result(context: Context, value: str) -> None:
|
|
expected = value.strip().lower() == "true"
|
|
assert context.shell_danger_result is expected
|
|
|
|
|
|
@given("a deterministic TUI reference fixture")
|
|
def step_deterministic_tui_reference_fixture(context: Context) -> None:
|
|
fixture_dir = Path(tempfile.mkdtemp())
|
|
(fixture_dir / "README.md").write_text("# fixture\n", encoding="utf-8")
|
|
(fixture_dir / ".git").mkdir(exist_ok=True)
|
|
(fixture_dir / ".git" / "secret.txt").write_text("secret\n", encoding="utf-8")
|
|
context.tui_reference_fixture_dir = fixture_dir
|
|
context.add_cleanup(lambda: shutil.rmtree(str(fixture_dir), ignore_errors=True))
|
|
|
|
|
|
@when("I parse and suggest TUI references using fixture")
|
|
def step_parse_and_suggest_with_fixture(context: Context) -> None:
|
|
context.tui_walk_count = 0
|
|
context.tui_fixture_suggestions = []
|
|
reference_parser._catalog_cache["cwd"] = None
|
|
reference_parser._catalog_cache["created_at"] = 0.0
|
|
reference_parser._catalog_cache["catalog"] = None
|
|
real_walk = os.walk
|
|
|
|
def counting_walk(*args: object, **kwargs: object):
|
|
context.tui_walk_count += 1
|
|
return real_walk(*args, **kwargs)
|
|
|
|
with (
|
|
patch(
|
|
"cleveragents.tui.input.reference_parser.Path.cwd",
|
|
return_value=context.tui_reference_fixture_dir,
|
|
),
|
|
patch(
|
|
"cleveragents.tui.input.reference_parser.os.walk", side_effect=counting_walk
|
|
),
|
|
):
|
|
parse_references("inspect @README.md")
|
|
context.tui_fixture_suggestions = suggestions("secret", category="resource")
|
|
|
|
|
|
@then('TUI walk count should be "{count}"')
|
|
def step_tui_walk_count(context: Context, count: str) -> None:
|
|
assert context.tui_walk_count == int(count)
|
|
|
|
|
|
@then('TUI suggestions should not include "{value}"')
|
|
def step_tui_suggestions_not_include(context: Context, value: str) -> None:
|
|
assert all(
|
|
value not in suggestion for suggestion in context.tui_fixture_suggestions
|
|
)
|
|
|
|
|
|
@when("I check TUI app textual availability flag")
|
|
def step_check_tui_textual_availability(context: Context) -> None:
|
|
context.tui_textual_available = tui_app_module.textual_available()
|
|
|
|
|
|
@then("TUI textual availability should be boolean")
|
|
def step_tui_textual_is_bool(context: Context) -> None:
|
|
assert isinstance(context.tui_textual_available, bool)
|
|
|
|
|
|
@when("I run fallback TUI app")
|
|
def step_run_fallback_tui_app(context: Context) -> None:
|
|
context.tui_fallback_error = None
|
|
fallback = tui_app_module._FallbackCleverAgentsTuiApp(
|
|
command_router=object(), persona_state=object()
|
|
)
|
|
try:
|
|
fallback.run()
|
|
except RuntimeError as exc:
|
|
context.tui_fallback_error = exc
|
|
|
|
|
|
@then('fallback TUI app should fail with "{message}"')
|
|
def step_fallback_tui_fails(context: Context, message: str) -> None:
|
|
assert context.tui_fallback_error is not None
|
|
assert message in str(context.tui_fallback_error)
|
|
|
|
|
|
@given('a TUI prompt value "{value}"')
|
|
def step_set_tui_prompt_value(context: Context, value: str) -> None:
|
|
context.tui_prompt_value = value
|
|
|
|
|
|
@when("I clear pending TUI reference token via escape")
|
|
def step_clear_pending_reference(context: Context) -> None:
|
|
cleanup = tui_app_module._strip_pending_reference_token
|
|
assert callable(cleanup)
|
|
context.tui_prompt_value = cleanup(context.tui_prompt_value)
|
|
|
|
|
|
@then('the TUI prompt value should be "{expected}"')
|
|
def step_assert_tui_prompt_value(context: Context, expected: str) -> None:
|
|
assert context.tui_prompt_value == expected
|