"""Helper script for invariant_cli.robot smoke tests. Each subcommand is a self-contained check that prints a sentinel on success. """ from __future__ import annotations import sys from pathlib import Path from unittest.mock import patch _SRC = str(Path(__file__).resolve().parents[1] / "src") if _SRC not in sys.path: sys.path.insert(0, _SRC) from typer.testing import CliRunner # noqa: E402 from cleveragents.application.services.invariant_service import ( # noqa: E402 InvariantService, ) from cleveragents.cli.commands.invariant import app as invariant_app # noqa: E402 runner = CliRunner() def _fresh_service() -> InvariantService: """Create a fresh in-memory service for each test.""" return InvariantService() # --------------------------------------------------------------------------- # Subcommands # --------------------------------------------------------------------------- def add_global() -> None: svc = _fresh_service() with patch("cleveragents.cli.commands.invariant._get_service", return_value=svc): result = runner.invoke( invariant_app, ["add", "--global", "Never delete production data"] ) if result.exit_code == 0 and "Invariant added" in result.stdout: print("invariant-add-global-ok") else: print(f"FAIL: exit={result.exit_code} out={result.stdout}") sys.exit(1) def add_project() -> None: svc = _fresh_service() with patch("cleveragents.cli.commands.invariant._get_service", return_value=svc): result = runner.invoke( invariant_app, ["add", "--project", "myapp", "All API changes need tests"] ) if result.exit_code == 0 and "Invariant added" in result.stdout: print("invariant-add-project-ok") else: print(f"FAIL: exit={result.exit_code} out={result.stdout}") sys.exit(1) def add_plan() -> None: svc = _fresh_service() with patch("cleveragents.cli.commands.invariant._get_service", return_value=svc): result = runner.invoke( invariant_app, ["add", "--plan", "01TESTPLANID00000000000000", "Use Python 3.13"], ) if result.exit_code == 0 and "Invariant added" in result.stdout: print("invariant-add-plan-ok") else: print(f"FAIL: exit={result.exit_code} out={result.stdout}") sys.exit(1) def add_action() -> None: svc = _fresh_service() with patch("cleveragents.cli.commands.invariant._get_service", return_value=svc): result = runner.invoke( invariant_app, ["add", "--action", "local/code-coverage", "Min 80% coverage"], ) if result.exit_code == 0 and "Invariant added" in result.stdout: print("invariant-add-action-ok") else: print(f"FAIL: exit={result.exit_code} out={result.stdout}") sys.exit(1) def list_empty() -> None: svc = _fresh_service() with patch("cleveragents.cli.commands.invariant._get_service", return_value=svc): result = runner.invoke(invariant_app, ["list"]) if result.exit_code == 0 and "No invariants found" in result.stdout: print("invariant-list-empty-ok") else: print(f"FAIL: exit={result.exit_code} out={result.stdout}") sys.exit(1) def list_filter() -> None: svc = _fresh_service() svc.add_invariant("Global rule", scope=_scope("global"), source_name="system") svc.add_invariant("Project rule", scope=_scope("project"), source_name="myapp") with patch("cleveragents.cli.commands.invariant._get_service", return_value=svc): result = runner.invoke(invariant_app, ["list", "--global"]) if result.exit_code == 0 and "Global rule" in result.stdout: print("invariant-list-filter-ok") else: print(f"FAIL: exit={result.exit_code} out={result.stdout}") sys.exit(1) def remove() -> None: svc = _fresh_service() inv = svc.add_invariant( "To be removed", scope=_scope("global"), source_name="system" ) with patch("cleveragents.cli.commands.invariant._get_service", return_value=svc): result = runner.invoke(invariant_app, ["remove", "--yes", inv.id]) if result.exit_code == 0 and "Invariant removed" in result.stdout: print("invariant-remove-ok") else: print(f"FAIL: exit={result.exit_code} out={result.stdout}") sys.exit(1) def scope_conflict() -> None: svc = _fresh_service() with patch("cleveragents.cli.commands.invariant._get_service", return_value=svc): result = runner.invoke( invariant_app, ["add", "--global", "--project", "myapp", "Conflicting scopes"], ) # Should fail with a bad parameter error if result.exit_code != 0: print("invariant-scope-conflict-ok") else: print(f"FAIL: exit={result.exit_code} out={result.stdout}") sys.exit(1) def list_json() -> None: svc = _fresh_service() svc.add_invariant("JSON test rule", scope=_scope("global"), source_name="system") with patch("cleveragents.cli.commands.invariant._get_service", return_value=svc): result = runner.invoke(invariant_app, ["list", "--format", "json"]) if result.exit_code == 0: # Verify output is valid JSON-like output = result.stdout.strip() if "JSON test rule" in output: print("invariant-list-json-ok") return print(f"FAIL: exit={result.exit_code} out={result.stdout}") sys.exit(1) def _scope(name: str): from cleveragents.domain.models.core.invariant import InvariantScope return InvariantScope(name) # --------------------------------------------------------------------------- # Dispatcher # --------------------------------------------------------------------------- COMMANDS = { "add-global": add_global, "add-project": add_project, "add-plan": add_plan, "add-action": add_action, "list-empty": list_empty, "list-filter": list_filter, "remove": remove, "scope-conflict": scope_conflict, "list-json": list_json, } if __name__ == "__main__": cmd = sys.argv[1] if len(sys.argv) > 1 else None if cmd not in COMMANDS: print(f"Unknown command: {cmd}", file=sys.stderr) print(f"Available: {', '.join(sorted(COMMANDS))}", file=sys.stderr) sys.exit(2) COMMANDS[cmd]()