"""Helper script for cli_global_options.robot integration tests. Each sub-command verifies one end-to-end behaviour of the new global CLI options (--data-dir, --config-path, -v) introduced by issue #6785. """ from __future__ import annotations import os import sys import tempfile from pathlib import Path from unittest.mock import patch # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def _invoke(args: list[str]) -> tuple[int, str]: """Invoke the Typer app and return (exit_code, combined_output).""" from typer.testing import CliRunner from cleveragents.cli.main import app runner = CliRunner() result = runner.invoke(app, args, catch_exceptions=True) output = result.output or "" return result.exit_code, output # --------------------------------------------------------------------------- # Test cases (sub-commands) # --------------------------------------------------------------------------- def test_data_dir_accepted() -> None: with tempfile.TemporaryDirectory() as tmp: code, output = _invoke(["--data-dir", tmp, "version"]) assert code == 0, f"Expected exit 0, got {code}. Output: {output}" print("cli-global-options-data-dir-accepted-ok") def test_config_path_accepted() -> None: with tempfile.NamedTemporaryFile(suffix=".toml", delete=False) as tmp: tmp.write(b"# test config\n") tmp_path = tmp.name try: code, output = _invoke(["--config-path", tmp_path, "version"]) assert code == 0, f"Expected exit 0, got {code}. Output: {output}" print("cli-global-options-config-path-accepted-ok") finally: os.unlink(tmp_path) def test_verbosity_accepted() -> None: code, output = _invoke(["-v", "version"]) assert code == 0, f"Expected exit 0, got {code}. Output: {output}" print("cli-global-options-verbosity-accepted-ok") def test_combined_options() -> None: with tempfile.TemporaryDirectory() as tmp_dir: with tempfile.NamedTemporaryFile(suffix=".toml", delete=False) as tmp_cfg: tmp_cfg.write(b"# test\n") tmp_cfg_path = tmp_cfg.name try: code, output = _invoke( [ "--data-dir", tmp_dir, "--config-path", tmp_cfg_path, "version", ] ) assert code == 0, f"Expected exit 0, got {code}. Output: {output}" print("cli-global-options-combined-ok") finally: os.unlink(tmp_cfg_path) def test_data_dir_override() -> None: """Verify --data-dir sets CLEVERAGENTS_DATA_DIR env var during invocation.""" with tempfile.TemporaryDirectory() as tmp: code, output = _invoke(["--data-dir", tmp, "version"]) assert code == 0, f"Expected exit 0, got {code}. Output: {output}" # Verify the env var was set to (or derived from) the tmp dir env_val = os.environ.get("CLEVERAGENTS_DATA_DIR") if env_val: resolved_env = str(Path(env_val).resolve()) resolved_tmp = str(Path(tmp).resolve()) assert resolved_env == resolved_tmp, ( f"CLEVERAGENTS_DATA_DIR={env_val!r} != {tmp!r}" ) print("cli-global-options-data-dir-override-ok") def test_config_path_override() -> None: """Verify --config-path sets CLEVERAGENTS_CONFIG_PATH env var during invocation.""" with tempfile.NamedTemporaryFile(suffix=".toml", delete=False) as tmp: tmp.write(b"# test\n") tmp_path = tmp.name try: code, output = _invoke(["--config-path", tmp_path, "version"]) assert code == 0, f"Expected exit 0, got {code}. Output: {output}" env_val = os.environ.get("CLEVERAGENTS_CONFIG_PATH") if env_val: assert str(Path(env_val).resolve()) == str(Path(tmp_path).resolve()), ( f"CLEVERAGENTS_CONFIG_PATH={env_val!r} != {tmp_path!r}" ) print("cli-global-options-config-path-override-ok") finally: os.unlink(tmp_path) def test_verbosity_levels() -> None: """Verify the verbosity count → log level mapping.""" from unittest.mock import MagicMock from cleveragents.cli.formatting import OutputFormat from cleveragents.cli.main import main_callback expected_levels = { 0: "CRITICAL", 1: "ERROR", 2: "WARNING", 3: "INFO", 4: "DEBUG", 5: "DEBUG", } for count, expected in expected_levels.items(): captured_levels: list[str] = [] def _make_capture(levels: list[str]): # type: ignore[no-untyped-def] def _capture(*, env: str = "development", log_level: str = "INFO") -> None: levels.append(log_level) return _capture mock_ctx = MagicMock() mock_ctx.obj = {} with patch( "cleveragents.config.logging.configure_structlog", side_effect=_make_capture(captured_levels), ): main_callback( ctx=mock_ctx, version=None, # type: ignore[arg-type] show_secrets=False, fmt=OutputFormat.RICH, data_dir=None, config_path=None, verbose=count, ) assert captured_levels, f"configure_structlog not called for count={count}" actual = captured_levels[-1].upper() assert actual == expected, ( f"verbose={count}: expected log_level={expected!r}, got {actual!r}" ) print("cli-global-options-verbosity-levels-ok") # --------------------------------------------------------------------------- # Entry point # --------------------------------------------------------------------------- _COMMANDS: dict[str, object] = { "data-dir-accepted": test_data_dir_accepted, "config-path-accepted": test_config_path_accepted, "verbosity-accepted": test_verbosity_accepted, "combined-options": test_combined_options, "data-dir-override": test_data_dir_override, "config-path-override": test_config_path_override, "verbosity-levels": test_verbosity_levels, } if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: helper_cli_global_options.py ", file=sys.stderr) sys.exit(1) cmd = sys.argv[1] fn = _COMMANDS.get(cmd) if fn is None: print(f"Unknown command: {cmd}", file=sys.stderr) sys.exit(1) try: fn() # type: ignore[call-arg] except Exception as exc: print(f"FAILED: {exc}", file=sys.stderr) import traceback traceback.print_exc(file=sys.stderr) sys.exit(1)