"""Step definitions for ACMS context CLI commands.""" from __future__ import annotations import fnmatch import io from typing import Any from unittest.mock import MagicMock, patch import typer from behave import given, then, when from cleveragents.domain.models.acms.tiers import ContextTier, TieredFragment from features.mocks.acms_context_mocks import ( make_mock_container, make_mock_tier_service, make_tiered_fragment, ) @given("the ACMS service is initialized") def step_acms_service_initialized(context: Any) -> None: """Initialize the ACMS service for testing.""" context.tier_service = MagicMock() context.context_data = {} context.entries_to_remove = [] @given('a test view "{view_name}" exists') def step_test_view_exists(context: Any, view_name: str) -> None: """Create a test view with sample fragments.""" context.test_view = view_name fragments = [ make_tiered_fragment( fragment_id=f"frag-{view_name}-1", resource_id="src/module1.py", tier=ContextTier.HOT, token_count=1024, project_name=view_name, ), make_tiered_fragment( fragment_id=f"frag-{view_name}-2", resource_id="src/module2.py", tier=ContextTier.WARM, token_count=2048, project_name=view_name, ), ] context.context_data[view_name] = fragments context.entries_to_remove = fragments @given('the view "{view_name}" has no context entries') def step_view_has_no_entries(context: Any, view_name: str) -> None: """Set up a view with no context entries.""" context.context_data[view_name] = [] context.entries_to_remove = [] @given('the view "{view_name}" has {count:d} context entries') def step_view_has_entries(context: Any, view_name: str, count: int) -> None: """Set up a view with specified number of context entries.""" tiers = [ContextTier.HOT, ContextTier.WARM, ContextTier.COLD] fragments = [ make_tiered_fragment( fragment_id=f"frag-{view_name}-{i}", resource_id=f"src/module{i}.py", tier=tiers[i % 3], token_count=1024 * (i + 1), project_name=view_name, tag="deprecated" if i < 2 else "default", ) for i in range(count) ] context.context_data[view_name] = fragments context.entries_to_remove = fragments @given('{count:d} entries match the path pattern "{pattern}"') def step_entries_match_path(context: Any, count: int, pattern: str) -> None: """Mark entries matching a path pattern.""" context.path_filter = pattern context.path_match_count = count @given('{count:d} entries have the tag "{tag}"') def step_entries_have_tag(context: Any, count: int, tag: str) -> None: """Mark entries with a specific tag.""" context.tag_filter = tag context.tag_match_count = count @given('{count:d} entries are in tier "{tier}"') def step_entries_in_tier(context: Any, count: int, tier: str) -> None: """Mark entries in a specific tier.""" context.tier_filter = tier context.tier_match_count = count @when('I run "agents acms context show {view}"') def step_run_context_show(context: Any, view: str) -> None: """Run the context show command and capture real output.""" from cleveragents.cli.commands.acms_context import acms_context_show scoped_fragments = context.context_data.get(view, []) mock_service = make_mock_tier_service( fragments=scoped_fragments, scoped_fragments=scoped_fragments, ) mock_container = make_mock_container(mock_service) output_buffer = io.StringIO() mock_console = MagicMock() captured_lines: list[str] = [] def capture_print(msg: str = "", **kwargs: Any) -> None: captured_lines.append(str(msg)) output_buffer.write(str(msg) + "\n") mock_console.print.side_effect = capture_print with ( patch( "cleveragents.cli.commands.acms_context.get_container", return_value=mock_container, ), patch( "cleveragents.cli.commands.acms_context._get_console", return_value=mock_console, ), ): try: acms_context_show(view) context.command_exit_code = 0 except typer.Exit as exc: context.command_exit_code = ( exc.exit_code if exc.exit_code is not None else 0 ) except SystemExit as exc: context.command_exit_code = exc.code if exc.code is not None else 0 context.command_output = output_buffer.getvalue() context.captured_lines = captured_lines @when('I run "agents acms context clear" and confirm') def step_run_context_clear_with_confirm(context: Any) -> None: """Run the context clear command with confirmation.""" from cleveragents.cli.commands.acms_context import acms_context_clear entries = context.entries_to_remove mock_service = make_mock_tier_service(fragments=entries) mock_container = make_mock_container(mock_service) output_buffer = io.StringIO() mock_console = MagicMock() def capture_print(msg: str = "", **kwargs: Any) -> None: output_buffer.write(str(msg) + "\n") mock_console.print.side_effect = capture_print with ( patch( "cleveragents.cli.commands.acms_context.get_container", return_value=mock_container, ), patch( "cleveragents.cli.commands.acms_context._get_console", return_value=mock_console, ), patch("typer.confirm", return_value=True), ): try: acms_context_clear() context.command_exit_code = 0 except typer.Exit as exc: context.command_exit_code = ( exc.exit_code if exc.exit_code is not None else 0 ) except SystemExit as exc: context.command_exit_code = exc.code if exc.code is not None else 0 context.command_output = output_buffer.getvalue() context.mock_confirm = mock_console @when('I run "agents acms context clear --yes"') def step_run_context_clear_yes(context: Any) -> None: """Run the context clear command with --yes flag.""" from cleveragents.cli.commands.acms_context import acms_context_clear entries = context.entries_to_remove mock_service = make_mock_tier_service(fragments=entries) mock_container = make_mock_container(mock_service) output_buffer = io.StringIO() mock_console = MagicMock() context.mock_typer_confirm = MagicMock() def capture_print(msg: str = "", **kwargs: Any) -> None: output_buffer.write(str(msg) + "\n") mock_console.print.side_effect = capture_print with ( patch( "cleveragents.cli.commands.acms_context.get_container", return_value=mock_container, ), patch( "cleveragents.cli.commands.acms_context._get_console", return_value=mock_console, ), patch("typer.confirm", context.mock_typer_confirm), ): try: acms_context_clear(yes=True) context.command_exit_code = 0 except typer.Exit as exc: context.command_exit_code = ( exc.exit_code if exc.exit_code is not None else 0 ) except SystemExit as exc: context.command_exit_code = exc.code if exc.code is not None else 0 context.command_output = output_buffer.getvalue() @when('I run "agents acms context clear --path {pattern} --yes"') def step_run_context_clear_path(context: Any, pattern: str) -> None: """Run the context clear command with path filter.""" from cleveragents.cli.commands.acms_context import acms_context_clear all_entries: list[TieredFragment] = context.entries_to_remove filtered = [f for f in all_entries if fnmatch.fnmatch(f.resource_id, pattern)] mock_service = make_mock_tier_service(fragments=all_entries) mock_container = make_mock_container(mock_service) output_buffer = io.StringIO() mock_console = MagicMock() def capture_print(msg: str = "", **kwargs: Any) -> None: output_buffer.write(str(msg) + "\n") mock_console.print.side_effect = capture_print with ( patch( "cleveragents.cli.commands.acms_context.get_container", return_value=mock_container, ), patch( "cleveragents.cli.commands.acms_context._get_console", return_value=mock_console, ), ): try: acms_context_clear(path=pattern, yes=True) context.command_exit_code = 0 except typer.Exit as exc: context.command_exit_code = ( exc.exit_code if exc.exit_code is not None else 0 ) except SystemExit as exc: context.command_exit_code = exc.code if exc.code is not None else 0 context.command_output = output_buffer.getvalue() context.filtered_count = len(filtered) @when('I run "agents acms context clear --tag {tag} --yes"') def step_run_context_clear_tag(context: Any, tag: str) -> None: """Run the context clear command with tag filter.""" from cleveragents.cli.commands.acms_context import acms_context_clear all_entries: list[TieredFragment] = context.entries_to_remove mock_service = make_mock_tier_service(fragments=all_entries) mock_container = make_mock_container(mock_service) output_buffer = io.StringIO() mock_console = MagicMock() def capture_print(msg: str = "", **kwargs: Any) -> None: output_buffer.write(str(msg) + "\n") mock_console.print.side_effect = capture_print with ( patch( "cleveragents.cli.commands.acms_context.get_container", return_value=mock_container, ), patch( "cleveragents.cli.commands.acms_context._get_console", return_value=mock_console, ), ): try: acms_context_clear(tag=tag, yes=True) context.command_exit_code = 0 except typer.Exit as exc: context.command_exit_code = ( exc.exit_code if exc.exit_code is not None else 0 ) except SystemExit as exc: context.command_exit_code = exc.code if exc.code is not None else 0 context.command_output = output_buffer.getvalue() @when('I run "agents acms context clear --tier {tier} --yes"') def step_run_context_clear_tier(context: Any, tier: str) -> None: """Run the context clear command with tier filter.""" from cleveragents.cli.commands.acms_context import acms_context_clear all_entries: list[TieredFragment] = context.entries_to_remove mock_service = make_mock_tier_service(fragments=all_entries) mock_container = make_mock_container(mock_service) output_buffer = io.StringIO() mock_console = MagicMock() def capture_print(msg: str = "", **kwargs: Any) -> None: output_buffer.write(str(msg) + "\n") mock_console.print.side_effect = capture_print with ( patch( "cleveragents.cli.commands.acms_context.get_container", return_value=mock_container, ), patch( "cleveragents.cli.commands.acms_context._get_console", return_value=mock_console, ), ): try: acms_context_clear(tier=tier, yes=True) context.command_exit_code = 0 except typer.Exit as exc: context.command_exit_code = ( exc.exit_code if exc.exit_code is not None else 0 ) except SystemExit as exc: context.command_exit_code = exc.code if exc.code is not None else 0 context.command_output = output_buffer.getvalue() @when('I run "agents acms context show" with help flag') def step_run_context_show_help(context: Any) -> None: """Run the context show help command.""" from cleveragents.cli.commands.acms_context import acms_context_show context.command_output = ( acms_context_show.__doc__ or "Display the assembled context for a specific ACMS view" ) context.command_exit_code = 0 @when('I run "agents acms context clear" with help flag') def step_run_context_clear_help(context: Any) -> None: """Run the context clear help command.""" from cleveragents.cli.commands.acms_context import acms_context_clear context.command_output = ( acms_context_clear.__doc__ or "Remove stale context entries from the ACMS index" ) context.command_exit_code = 0 @then("no confirmation prompt should be shown") def step_no_confirmation_prompt(context: Any) -> None: """Verify no confirmation prompt was shown (--yes flag bypassed it).""" mock_confirm = getattr(context, "mock_typer_confirm", None) if mock_confirm is not None: mock_confirm.assert_not_called() @when('I run "agents acms context show" with empty view') def step_run_context_show_empty_view(context: Any) -> None: """Run the context show command with an empty/blank view name.""" from cleveragents.cli.commands.acms_context import acms_context_show mock_service = make_mock_tier_service() mock_container = make_mock_container(mock_service) output_buffer = io.StringIO() mock_console = MagicMock() captured_lines: list[str] = [] def capture_print(msg: str = "", **kwargs: Any) -> None: captured_lines.append(str(msg)) output_buffer.write(str(msg) + "\n") mock_console.print.side_effect = capture_print with ( patch( "cleveragents.cli.commands.acms_context.get_container", return_value=mock_container, ), patch( "cleveragents.cli.commands.acms_context._get_console", return_value=mock_console, ), ): try: acms_context_show("") context.command_exit_code = 0 except typer.Exit as exc: context.command_exit_code = ( exc.exit_code if exc.exit_code is not None else 0 ) except SystemExit as exc: context.command_exit_code = exc.code if exc.code is not None else 0 context.command_output = output_buffer.getvalue() @when('I run "agents acms context clear" and confirm with yes') def step_run_context_clear_confirm_yes(context: Any) -> None: """Run the context clear command without filters but with auto-confirmation.""" from cleveragents.cli.commands.acms_context import acms_context_clear entries = context.entries_to_remove mock_service = make_mock_tier_service(fragments=entries) mock_container = make_mock_container(mock_service) output_buffer = io.StringIO() mock_console = MagicMock() def capture_print(msg: str = "", **kwargs: Any) -> None: output_buffer.write(str(msg) + "\n") mock_console.print.side_effect = capture_print with ( patch( "cleveragents.cli.commands.acms_context.get_container", return_value=mock_container, ), patch( "cleveragents.cli.commands.acms_context._get_console", return_value=mock_console, ), patch("typer.confirm", return_value=True), ): try: acms_context_clear() context.command_exit_code = 0 except typer.Exit as exc: context.command_exit_code = ( exc.exit_code if exc.exit_code is not None else 0 ) except SystemExit as exc: context.command_exit_code = exc.code if exc.code is not None else 0 context.command_output = output_buffer.getvalue() @then("the exit code should be non-zero") def step_exit_code_nonzero(context: Any) -> None: """Verify the command exited with a non-zero exit code.""" assert context.command_exit_code != 0, ( f"Expected non-zero exit code but got {context.command_exit_code}" )