forked from cleveragents/cleveragents-core
205 lines
6.9 KiB
Python
205 lines
6.9 KiB
Python
"""Step definitions for CLI coverage tests."""
|
|
|
|
import subprocess
|
|
from unittest.mock import patch
|
|
|
|
from behave import then, when
|
|
from click.exceptions import Exit as ClickExit
|
|
from typer import Exit
|
|
|
|
from cleveragents.cli.main import app, convert_exit_code, main
|
|
|
|
|
|
@when('I run "{command}"')
|
|
def step_run_command(context, command):
|
|
"""Run a CLI command using subprocess."""
|
|
try:
|
|
result = subprocess.run(
|
|
command.split(), capture_output=True, text=True, timeout=5
|
|
)
|
|
context.exit_code = result.returncode
|
|
context.output = result.stdout + result.stderr
|
|
except subprocess.TimeoutExpired:
|
|
context.exit_code = -1
|
|
context.output = "Command timed out"
|
|
except Exception as e:
|
|
context.exit_code = -1
|
|
context.output = str(e)
|
|
|
|
|
|
@then("the command should succeed")
|
|
def step_command_succeeds(context):
|
|
"""Check that command succeeded."""
|
|
assert context.exit_code == 0, f"Expected exit code 0, got {context.exit_code}"
|
|
|
|
|
|
@then("the command should fail with exit code {code:d}")
|
|
def step_command_fails_with_code(context, code):
|
|
"""Check that command failed with specific code."""
|
|
assert context.exit_code == code, (
|
|
f"Expected exit code {code}, got {context.exit_code}"
|
|
)
|
|
|
|
|
|
@then('the output should contain "{text}"')
|
|
def step_output_contains(context, text):
|
|
"""Check that output contains text."""
|
|
assert text in context.output, f"'{text}' not found in output: {context.output}"
|
|
|
|
|
|
@when("I call the main function directly with no args")
|
|
def step_call_main_no_args(context):
|
|
"""Call main function with no arguments."""
|
|
with patch("sys.argv", ["cleveragents"]):
|
|
context.exit_code = main()
|
|
|
|
|
|
@when('I call the main function directly with "{args}"')
|
|
def step_call_main_with_args(context, args):
|
|
"""Call main function with specific arguments."""
|
|
argv = ["cleveragents", *args.split()]
|
|
with patch("sys.argv", argv):
|
|
context.exit_code = main()
|
|
|
|
|
|
@then("it should return {code:d}")
|
|
def step_check_return_code(context, code):
|
|
"""Check the return code."""
|
|
assert context.exit_code == code, f"Expected {code}, got {context.exit_code}"
|
|
|
|
|
|
@when("I run a command that gets interrupted")
|
|
def step_run_interrupted_command(context):
|
|
"""Simulate a command that gets interrupted."""
|
|
with patch("cleveragents.cli.main.app") as mock_app:
|
|
mock_app.side_effect = KeyboardInterrupt()
|
|
context.exit_code = main(["info"])
|
|
|
|
|
|
@then("it should handle the KeyboardInterrupt gracefully")
|
|
def step_check_keyboard_interrupt_handled(context):
|
|
"""Check that KeyboardInterrupt was handled."""
|
|
assert context.exit_code == 130, (
|
|
f"Expected 130 for KeyboardInterrupt, got {context.exit_code}"
|
|
)
|
|
|
|
|
|
@when("I run a command that calls sys.exit(1)")
|
|
def step_run_sys_exit_command(context):
|
|
"""Simulate a command that calls sys.exit."""
|
|
with patch("cleveragents.cli.main.app") as mock_app:
|
|
mock_app.side_effect = SystemExit(1)
|
|
context.exit_code = main(["info"])
|
|
|
|
|
|
@then("it should propagate the exit code correctly")
|
|
def step_check_exit_code_propagated(context):
|
|
"""Check that exit code was propagated."""
|
|
assert context.exit_code == 1, f"Expected 1, got {context.exit_code}"
|
|
|
|
|
|
# Additional steps to increase coverage
|
|
|
|
|
|
@when("I test convert_exit_code with various inputs")
|
|
def step_test_convert_exit_code(context):
|
|
"""Test the convert_exit_code function."""
|
|
context.results = []
|
|
# Test with int
|
|
context.results.append(convert_exit_code(0))
|
|
context.results.append(convert_exit_code(1))
|
|
context.results.append(convert_exit_code(-1))
|
|
# Test with None
|
|
context.results.append(convert_exit_code(None))
|
|
# Test with Exit exception
|
|
context.results.append(convert_exit_code(Exit(2)))
|
|
# Test with ClickExit exception
|
|
context.results.append(convert_exit_code(ClickExit(3)))
|
|
# Test with other object
|
|
context.results.append(convert_exit_code("string"))
|
|
|
|
|
|
@then("convert_exit_code should handle all types correctly")
|
|
def step_check_convert_exit_code(context):
|
|
"""Check convert_exit_code results."""
|
|
expected = [0, 1, -1, 0, 2, 3, 1] # string returns 1, not 0
|
|
assert context.results == expected, f"Expected {expected}, got {context.results}"
|
|
|
|
|
|
@when("I test the CLI app commands")
|
|
def step_test_cli_commands(context):
|
|
"""Test CLI app commands directly."""
|
|
from typer.testing import CliRunner
|
|
|
|
runner = CliRunner()
|
|
|
|
context.results = []
|
|
# Test version
|
|
result = runner.invoke(app, ["--version"])
|
|
context.results.append((result.exit_code, "1.0.0" in result.stdout))
|
|
|
|
# Test help
|
|
result = runner.invoke(app, ["--help"])
|
|
context.results.append((result.exit_code, "Usage" in result.stdout))
|
|
|
|
# Test info
|
|
result = runner.invoke(app, ["info"])
|
|
context.results.append(
|
|
(result.exit_code, "CleverAgents Information" in result.stdout)
|
|
)
|
|
|
|
# Test diagnostics
|
|
result = runner.invoke(app, ["diagnostics"])
|
|
context.results.append(
|
|
(result.exit_code, "CleverAgents Diagnostics" in result.stdout)
|
|
)
|
|
|
|
# Test init (not implemented) - use no args since init doesn't take positional args
|
|
result = runner.invoke(app, ["init"])
|
|
context.results.append((result.exit_code, "not yet implemented" in result.stdout))
|
|
|
|
|
|
@then("all CLI commands should work correctly")
|
|
def step_check_cli_commands(context):
|
|
"""Check CLI command results."""
|
|
for idx, (exit_code, output_check) in enumerate(context.results):
|
|
# The init command is expected to return 1 (not implemented)
|
|
if idx == 4: # The init command is the 5th one (0-indexed)
|
|
assert exit_code == 1, f"Init command should return 1, got {exit_code}"
|
|
else:
|
|
assert exit_code == 0, f"Command {idx} failed with exit code {exit_code}"
|
|
assert output_check, f"Command {idx} output check failed"
|
|
|
|
|
|
@when("I test exception handling in main")
|
|
def step_test_exception_handling(context):
|
|
"""Test exception handling in main function."""
|
|
context.results = []
|
|
|
|
# Test CleverAgentsError
|
|
from cleveragents.core.exceptions import CleverAgentsError
|
|
|
|
with patch("cleveragents.cli.main.app") as mock_app:
|
|
mock_app.side_effect = CleverAgentsError("Test error")
|
|
result = main(["info"])
|
|
context.results.append(result)
|
|
|
|
# Test generic Exception
|
|
with patch("cleveragents.cli.main.app") as mock_app:
|
|
mock_app.side_effect = Exception("Generic error")
|
|
result = main(["info"])
|
|
context.results.append(result)
|
|
|
|
# Test Exit with code
|
|
with patch("cleveragents.cli.main.app") as mock_app:
|
|
mock_app.side_effect = Exit(5)
|
|
result = main(["info"])
|
|
context.results.append(result)
|
|
|
|
|
|
@then("exception handling should return correct codes")
|
|
def step_check_exception_handling(context):
|
|
"""Check exception handling results."""
|
|
expected = [1, 1, 5]
|
|
assert context.results == expected, f"Expected {expected}, got {context.results}"
|