"""Step definitions for system.py coverage boost.""" from __future__ import annotations import os import tempfile from pathlib import Path from unittest.mock import MagicMock, patch from behave import given, then, when from behave.runner import Context def _mock_settings(**overrides): """Create mock settings with sensible defaults.""" tmpdir = tempfile.mkdtemp() s = MagicMock() s.database_url = overrides.get("database_url", f"sqlite:///{tmpdir}/test.db") s.data_dir = overrides.get("data_dir", Path(tmpdir)) s.config_path = overrides.get("config_path", Path(tmpdir) / "config.toml") s.log_dir = overrides.get("log_dir", Path(tmpdir) / "nonexistent_logs") s.default_automation_profile = "auto" s.has_provider_configured = MagicMock(return_value=False) s.configured_providers = [] s.debug_enabled = False return s @given("a system module for coverage testing") def step_system_module(context: Context) -> None: context.result_data = None context.exception = None @when("I call git_sha with git not on path") def step_git_sha_unavailable(context: Context) -> None: from cleveragents.cli.commands.system import _git_sha with patch( "cleveragents.cli.commands.system.subprocess.run", side_effect=FileNotFoundError("git not found"), ): context.result_data = _git_sha() @then('the git sha should be "{expected}"') def step_assert_git_sha(context: Context, expected: str) -> None: assert context.result_data == expected @when("I call dep_version for a missing package") def step_dep_version_missing(context: Context) -> None: from cleveragents.cli.commands.system import _dep_version context.result_data = _dep_version("nonexistent-package-xyz-99999") @then('the dep version should be "{expected}"') def step_assert_dep_version(context: Context, expected: str) -> None: assert context.result_data == expected @when("I call build_info_data with no database file") def step_info_no_db(context: Context) -> None: from cleveragents.cli.commands.system import build_info_data tmpdir = tempfile.mkdtemp() ms = _mock_settings( database_url=f"sqlite:///{tmpdir}/nonexistent.db", log_dir=Path(tmpdir) / "logs", ) with patch("cleveragents.config.settings.get_settings", return_value=ms): context.result_data = build_info_data() @then('the info data should contain db_size as "{expected}"') def step_assert_db_size(context: Context, expected: str) -> None: assert context.result_data["storage"]["db_size"] == expected @when("I call build_info_data with no log directory") def step_info_no_log_dir(context: Context) -> None: from cleveragents.cli.commands.system import build_info_data tmpdir = tempfile.mkdtemp() ms = _mock_settings( database_url=f"sqlite:///{tmpdir}/nonexistent.db", log_dir=Path(tmpdir) / "nonexistent_logs_dir", ) with patch("cleveragents.config.settings.get_settings", return_value=ms): context.result_data = build_info_data() @then('the info data should contain logs as "{expected}"') def step_assert_logs(context: Context, expected: str) -> None: assert context.result_data["storage"]["logs"] == expected @when("I call check_data_dir with non-existent directory") def step_check_data_dir_nonexistent(context: Context) -> None: from cleveragents.cli.commands.system import _check_data_dir ms = _mock_settings(data_dir=Path("/nonexistent/data/dir/xyz99")) with patch("cleveragents.config.settings.get_settings", return_value=ms): context.result_data = _check_data_dir() @then("the check result should have WARN status") def step_assert_warn(context: Context) -> None: from cleveragents.cli.commands.system import CheckStatus assert context.result_data["status"] == CheckStatus.WARN @when("I call check_database with postgres URL") def step_check_db_postgres(context: Context) -> None: from cleveragents.cli.commands.system import _check_database ms = _mock_settings(database_url="postgresql://localhost/test") with patch("cleveragents.config.settings.get_settings", return_value=ms): context.result_data = _check_database() @then('the check result should have OK status and details "{expected}"') def step_assert_ok_details(context: Context, expected: str) -> None: from cleveragents.cli.commands.system import CheckStatus assert context.result_data["status"] == CheckStatus.OK assert context.result_data["details"] == expected @when("I call check_database with sqlite and non-writable parent") def step_check_db_nonwritable(context: Context) -> None: from cleveragents.cli.commands.system import _check_database ms = _mock_settings(database_url="sqlite:////nonexistent/parent/dir/test.db") with patch("cleveragents.config.settings.get_settings", return_value=ms): context.result_data = _check_database() @then("the check result should have ERROR status") def step_assert_error(context: Context) -> None: from cleveragents.cli.commands.system import CheckStatus assert context.result_data["status"] == CheckStatus.ERROR @when("I call check_file_permissions with non-existent directory") def step_check_perms_nonexistent(context: Context) -> None: from cleveragents.cli.commands.system import _check_file_permissions ms = _mock_settings(data_dir=Path("/nonexistent/data/dir/xyz99")) with patch("cleveragents.config.settings.get_settings", return_value=ms): context.result_data = _check_file_permissions() @when("I call check_file_permissions with read-only directory") def step_check_perms_readonly(context: Context) -> None: from cleveragents.cli.commands.system import _check_file_permissions tmpdir = tempfile.mkdtemp() ms = _mock_settings(data_dir=Path(tmpdir)) original_access = os.access def mock_access(p, mode): p_str = str(p) if tmpdir in p_str: return mode == os.R_OK return original_access(p, mode) with ( patch("cleveragents.config.settings.get_settings", return_value=ms), patch("cleveragents.cli.commands.system.os.access", side_effect=mock_access), ): context.result_data = _check_file_permissions() @then("the file perm result status should not be OK") def step_assert_not_ok(context: Context) -> None: from cleveragents.cli.commands.system import CheckStatus assert context.result_data["status"] != CheckStatus.OK @when("I call check_git with git unavailable") def step_check_git_unavailable(context: Context) -> None: from cleveragents.cli.commands.system import _check_git with patch( "cleveragents.cli.commands.system.subprocess.run", side_effect=FileNotFoundError("git"), ): context.result_data = _check_git() @when("I call render_version_rich with sample data") def step_render_version_rich(context: Context) -> None: from cleveragents.cli.commands.system import render_version_rich data = { "version": "1.0.0", "channel": "stable", "python": "3.13.0", "build_date": "2025-01-01", "commit": "abc1234", "schema": "1.0", "platform": "Linux", "dependencies": {"typer": "0.9.0", "rich": "13.0.0"}, } try: render_version_rich(data) context.exception = None except Exception as e: context.exception = e @then("no system exception should be raised") def step_no_system_exception(context: Context) -> None: assert context.exception is None @when("I call render_info_rich with sample data") def step_render_info_rich(context: Context) -> None: from cleveragents.cli.commands.system import render_info_rich data = { "data_dir": "/tmp/data", "config_path": "/tmp/config.toml", "database": "sqlite:///test.db", "server_mode": "disabled", "platform": "Linux", "automation": "auto", "providers_configured": 0, "debug_mode": False, "storage": {"db_size": "1.0 MB", "logs": "0.5 MB"}, } try: render_info_rich(data) context.exception = None except Exception as e: context.exception = e @when("I call render_diagnostics_rich with error data") def step_render_diag_errors(context: Context) -> None: from cleveragents.cli.commands.system import CheckStatus, render_diagnostics_rich data = { "checks": [ {"name": "Config file", "status": CheckStatus.OK, "details": "ok"}, {"name": "Database", "status": CheckStatus.ERROR, "details": "missing"}, ], "summary": { "total": 2, "ok": 1, "warnings": 0, "errors": 1, "duration_s": 0.01, }, "recommendations": ["Fix database"], "has_errors": True, "has_warnings": False, } try: render_diagnostics_rich(data) context.exception = None except Exception as e: context.exception = e @when("I call render_diagnostics_rich with warning data") def step_render_diag_warnings(context: Context) -> None: from cleveragents.cli.commands.system import CheckStatus, render_diagnostics_rich data = { "checks": [ {"name": "Config", "status": CheckStatus.OK, "details": "ok"}, {"name": "Disk", "status": CheckStatus.WARN, "details": "low"}, ], "summary": { "total": 2, "ok": 1, "warnings": 1, "errors": 0, "duration_s": 0.01, }, "recommendations": [], "has_errors": False, "has_warnings": True, } try: render_diagnostics_rich(data) context.exception = None except Exception as e: context.exception = e @when("I call render_diagnostics_rich with all OK data") def step_render_diag_ok(context: Context) -> None: from cleveragents.cli.commands.system import CheckStatus, render_diagnostics_rich data = { "checks": [ {"name": "Config", "status": CheckStatus.OK, "details": "ok"}, {"name": "DB", "status": CheckStatus.OK, "details": "ok"}, ], "summary": { "total": 2, "ok": 2, "warnings": 0, "errors": 0, "duration_s": 0.01, }, "recommendations": [], "has_errors": False, "has_warnings": False, } try: render_diagnostics_rich(data) context.exception = None except Exception as e: context.exception = e