Files
temp/features/steps/project_commands_coverage_steps.py
T

478 lines
16 KiB
Python

"""Step definitions for project commands coverage tests."""
from __future__ import annotations
import tempfile
from pathlib import Path
from unittest.mock import MagicMock, patch
from behave import given, then, when
from typer.testing import CliRunner
from cleveragents.cli.commands import project
from cleveragents.core.exceptions import (
CleverAgentsError,
ConfigurationError,
ValidationError,
)
@given("I have a temporary working directory")
def step_temp_working_directory(context):
"""Create a temporary working directory."""
context.temp_dir = tempfile.mkdtemp()
context.original_cwd = Path.cwd()
import os
os.chdir(context.temp_dir)
@given('I create a subdirectory "{dirname}"')
def step_create_subdirectory(context, dirname):
"""Create a subdirectory in the temp directory."""
subdir = Path(context.temp_dir) / dirname
subdir.mkdir(parents=True, exist_ok=True)
context.subdirectory = subdir
@given("I have already initialized a project")
def step_already_initialized(context):
"""Simulate an already initialized project."""
project_dir = Path(context.temp_dir) / ".cleveragents"
project_dir.mkdir(exist_ok=True)
context.existing_project = True
@given("I have an initialized project with stats")
def step_initialized_with_stats(context):
"""Mock an initialized project with statistics."""
context.mock_project = MagicMock()
context.mock_project.name = "test-project"
context.mock_project.path = Path(context.temp_dir)
context.mock_project.created_at = "2024-01-01 10:00:00"
context.mock_stats = {
"plans": 5,
"context_files": 10,
"changes": 25,
"current_plan": "plan-001",
}
@given("there is no initialized project")
def step_no_project(context):
"""Ensure no project exists."""
context.no_project = True
@given("the project service will raise a ValidationError with details")
def step_mock_validation_error(context):
"""Mock project service to raise ValidationError."""
context.mock_error = ValidationError(
"Invalid project name",
details={"name": "contains invalid characters", "path": "does not exist"},
)
@given("the project service will raise a ConfigurationError")
def step_mock_configuration_error(context):
"""Mock project service to raise ConfigurationError."""
context.mock_error = ConfigurationError("Missing required configuration")
@given("the project service will raise a CleverAgentsError")
def step_mock_cleveragents_error(context):
"""Mock project service to raise CleverAgentsError."""
context.mock_error = CleverAgentsError("Generic project error")
@given("the project service will raise an unexpected exception")
def step_mock_unexpected_error(context):
"""Mock project service to raise unexpected exception."""
context.mock_error = Exception("Unexpected error occurred")
@given("the project service will raise a CleverAgentsError on status")
def step_mock_status_error(context):
"""Mock project service to raise error on status."""
context.mock_status_error = CleverAgentsError("Cannot get project status")
@when("I run project init without any parameters")
def step_run_project_init_default(context):
"""Run project init with default parameters."""
runner = CliRunner()
with patch("cleveragents.application.container.get_container") as mock_container:
mock_service = MagicMock()
mock_project = MagicMock()
mock_project.name = Path.cwd().name
mock_project.path = Path.cwd()
mock_service.initialize_project.return_value = mock_project
mock_container.return_value.project_service.return_value = mock_service
result = runner.invoke(project.app, ["init"])
context.result = result
context.mock_service = mock_service
@when('I run project init with name "{name}"')
def step_run_project_init_with_name(context, name):
"""Run project init with custom name."""
runner = CliRunner()
with patch("cleveragents.application.container.get_container") as mock_container:
mock_service = MagicMock()
mock_project = MagicMock()
mock_project.name = name
mock_project.path = Path.cwd()
mock_service.initialize_project.return_value = mock_project
mock_container.return_value.project_service.return_value = mock_service
result = runner.invoke(project.app, ["init", name])
context.result = result
context.project_name = name
@when('I run project init with path "{path}"')
def step_run_project_init_with_path(context, path):
"""Run project init with custom path."""
runner = CliRunner()
with patch("cleveragents.application.container.get_container") as mock_container:
mock_service = MagicMock()
mock_project = MagicMock()
project_path = Path(context.temp_dir) / path
mock_project.name = Path(path).name
mock_project.path = project_path
mock_service.initialize_project.return_value = mock_project
mock_container.return_value.project_service.return_value = mock_service
result = runner.invoke(project.app, ["init", "--path", str(project_path)])
context.result = result
context.project_path = project_path
@when("I execute project init with force option")
def step_execute_project_init_force(context):
"""Run project init with force flag."""
runner = CliRunner()
with patch("cleveragents.application.container.get_container") as mock_container:
mock_service = MagicMock()
mock_project = MagicMock()
mock_project.name = "forced-project"
mock_project.path = Path.cwd()
mock_service.initialize_project.return_value = mock_project
mock_container.return_value.project_service.return_value = mock_service
result = runner.invoke(project.app, ["init", "--force"])
context.result = result
@when("I run project init and it fails with validation error")
def step_run_project_init_validation_error(context):
"""Run project init that fails with ValidationError."""
runner = CliRunner()
with patch("cleveragents.application.container.get_container") as mock_container:
mock_service = MagicMock()
mock_service.initialize_project.side_effect = context.mock_error
mock_container.return_value.project_service.return_value = mock_service
result = runner.invoke(project.app, ["init"])
context.result = result
@when("I run project init and it fails with configuration error")
def step_run_project_init_config_error(context):
"""Run project init that fails with ConfigurationError."""
runner = CliRunner()
with patch("cleveragents.application.container.get_container") as mock_container:
mock_service = MagicMock()
mock_service.initialize_project.side_effect = context.mock_error
mock_container.return_value.project_service.return_value = mock_service
result = runner.invoke(project.app, ["init"])
context.result = result
@when("I run project init and it fails with CleverAgentsError")
def step_run_project_init_cleveragents_error(context):
"""Run project init that fails with CleverAgentsError."""
runner = CliRunner()
with patch("cleveragents.application.container.get_container") as mock_container:
mock_service = MagicMock()
mock_service.initialize_project.side_effect = context.mock_error
mock_container.return_value.project_service.return_value = mock_service
result = runner.invoke(project.app, ["init"])
context.result = result
@when("I run project init and it fails unexpectedly")
def step_run_project_init_unexpected_error(context):
"""Run project init that fails with unexpected error."""
runner = CliRunner()
with patch("cleveragents.application.container.get_container") as mock_container:
mock_service = MagicMock()
mock_service.initialize_project.side_effect = context.mock_error
mock_container.return_value.project_service.return_value = mock_service
result = runner.invoke(project.app, ["init"])
context.result = result
@when("I execute project status command")
def step_execute_project_status(context):
"""Run project status command."""
runner = CliRunner()
with patch("cleveragents.application.container.get_container") as mock_container:
mock_service = MagicMock()
if hasattr(context, "no_project") and context.no_project:
mock_service.get_current_project.return_value = None
elif hasattr(context, "mock_status_error"):
mock_service.get_current_project.side_effect = context.mock_status_error
else:
mock_service.get_current_project.return_value = context.mock_project
mock_service.get_project_stats.return_value = context.mock_stats
mock_container.return_value.project_service.return_value = mock_service
result = runner.invoke(project.app, ["status"])
context.result = result
@when("I execute project status and it fails")
def step_execute_project_status_error(context):
"""Run project status that fails."""
runner = CliRunner()
with patch("cleveragents.application.container.get_container") as mock_container:
mock_service = MagicMock()
mock_service.get_current_project.side_effect = context.mock_status_error
mock_container.return_value.project_service.return_value = mock_service
result = runner.invoke(project.app, ["status"])
context.result = result
@when("I run project list command")
def step_run_project_list(context):
"""Run project list command."""
runner = CliRunner()
result = runner.invoke(project.app, ["list"])
context.result = result
@when("I run project clean command")
def step_run_project_clean(context):
"""Run project clean command."""
runner = CliRunner()
result = runner.invoke(project.app, ["clean"])
context.result = result
@when("I run project clean command with --yes flag")
def step_run_project_clean_yes(context):
"""Run project clean with confirmation."""
runner = CliRunner()
result = runner.invoke(project.app, ["clean", "--yes"])
context.result = result
@then("the project should be initialized in current directory")
def step_check_project_initialized(context):
"""Check project was initialized."""
assert context.result.exit_code == 0
assert "initialized successfully" in context.result.output
@then("the success message should show project name and location")
def step_check_success_message(context):
"""Check success message content."""
assert "Project" in context.result.output
assert "Location:" in context.result.output
@then("the .cleveragents directory should be created")
def step_check_cleveragents_dir(context):
"""Check .cleveragents directory creation."""
# This is mocked, but we check the service was called correctly
assert context.mock_service.initialize_project.called
@then('the project should be initialized with name "{name}"')
def step_check_project_name(context, name):
"""Check project initialized with correct name."""
assert context.result.exit_code == 0
assert name in context.result.output
@then('the success panel should display "{name}"')
def step_check_panel_name(context, name):
"""Check success panel displays name."""
assert name in context.result.output
@then('the project should be initialized in "{dirname}" directory')
def step_check_project_in_dir(context, dirname):
"""Check project initialized in correct directory."""
assert context.result.exit_code == 0
@then('the .cleveragents directory should exist in "{dirname}"')
def step_check_cleveragents_in_dir(context, dirname):
"""Check .cleveragents exists in specified directory."""
# This is mocked, just verify the call happened
assert context.result.exit_code == 0
@then("the project should be reinitialized successfully")
def step_check_reinitialized(context):
"""Check project was reinitialized."""
assert context.result.exit_code == 0
assert "initialized successfully" in context.result.output
@then("no error should be raised")
def step_check_no_error(context):
"""Check no error was raised."""
assert context.result.exit_code == 0
@then("the error message should be displayed in red")
def step_check_error_red(context):
"""Check error displayed in red."""
assert "Validation Error" in context.result.output
@then("the validation error details should be shown")
def step_check_validation_details(context):
"""Check validation error details shown."""
assert "name:" in context.result.output or "path:" in context.result.output
@then("the command should abort with ValidationError")
def step_check_abort_validation(context):
"""Check command aborted with validation error."""
assert context.result.exit_code != 0
@then("the configuration error message should be displayed")
def step_check_config_error(context):
"""Check configuration error displayed."""
assert "Configuration Error" in context.result.output
@then("the command should abort with ConfigurationError")
def step_check_abort_config(context):
"""Check command aborted with config error."""
assert context.result.exit_code != 0
@then("the generic error message should be displayed")
def step_check_generic_error(context):
"""Check generic error displayed."""
assert "Error:" in context.result.output
@then("the command should abort with CleverAgentsError")
def step_check_abort_cleveragents(context):
"""Check command aborted with CleverAgentsError."""
assert context.result.exit_code != 0
@then("the unexpected error message should be displayed")
def step_check_unexpected_error(context):
"""Check unexpected error displayed."""
assert "Unexpected error" in context.result.output
@then("the command should abort with generic exception")
def step_check_abort_generic(context):
"""Check command aborted with generic exception."""
assert context.result.exit_code != 0
@then("the project information should be displayed")
def step_check_project_info(context):
"""Check project info displayed."""
assert "Project Status" in context.result.output
assert "test-project" in context.result.output
@then("the statistics should include plans count")
def step_check_plans_count(context):
"""Check plans count in statistics."""
assert "Plans: 5" in context.result.output
@then("the statistics should include context files count")
def step_check_context_files(context):
"""Check context files count."""
assert "Context Files: 10" in context.result.output
@then("the statistics should include changes count")
def step_check_changes_count(context):
"""Check changes count."""
assert "Total Changes: 25" in context.result.output
@then("the current plan should be shown")
def step_check_current_plan(context):
"""Check current plan shown."""
assert "Current Plan: plan-001" in context.result.output
@then('an error should show "{message}"')
def step_check_error_message(context, message):
"""Check specific error message."""
assert message in context.result.output
@then('it should suggest running "{command}"')
def step_check_suggestion(context, command):
"""Check command suggestion."""
assert command in context.result.output
@then("the error message should be shown")
def step_check_error_shown(context):
"""Check error message shown."""
assert "Error:" in context.result.output
@then("the command should abort")
def step_check_abort(context):
"""Check command aborted."""
assert context.result.exit_code != 0
@then('it should display "{message}"')
def step_check_display_message(context, message):
"""Check specific message displayed."""
assert message in context.result.output
@then("the command should abort regardless of confirmation")
def step_check_abort_regardless(context):
"""Check command aborts even with confirmation."""
assert context.result.exit_code != 0
assert "not yet implemented" in context.result.output