Download tests/cli/test_cli_coverage.py from techprotrade/annator-command-center: direct link, hf CLI and curl.
- Browser
- Download file 31.4 kB
-
https://huggingface.co/spaces/techprotrade/annator-command-center/resolve/main/tests/cli/test_cli_coverage.py
- Command line
-
hf download hf://spaces/techprotrade/annator-command-center/tests/cli/test_cli_coverage.py
-
curl -L -o test_cli_coverage.py https://huggingface.co/spaces/techprotrade/annator-command-center/resolve/main/tests/cli/test_cli_coverage.py
31.4 kB
| """ | |
| Test coverage for CLI module - Target 60%+ coverage. | |
| Tests cover CLI commands, argument parsing, and error handling for: | |
| - Main entry point (main_cli) | |
| - Server management (start, daemon, stop, status) | |
| - Command execution (execute) | |
| - Configuration (config) | |
| - Local agent management (local-agent) | |
| - Initialization (init) | |
| - Feature enablement (enable) | |
| Coverage Target: 60%+ (from 16% baseline) | |
| File Count: 20+ tests | |
| """ | |
| import pytest | |
| import os | |
| import sys | |
| import tempfile | |
| from pathlib import Path | |
| from unittest.mock import patch, Mock, MagicMock, call | |
| from click.testing import CliRunner | |
| # Add backend to path | |
| sys.path.insert(0, str(Path(__file__).parent.parent)) | |
| from cli.main import main_cli | |
| from cli import daemon as daemon_module | |
| from cli.daemon import DaemonManager | |
| def runner(): | |
| """Create Click CLI test runner.""" | |
| return CliRunner() | |
| def temp_pid_file(): | |
| """Create temporary PID file for testing.""" | |
| with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.pid') as f: | |
| f.write('12345') | |
| f.flush() | |
| temp_path = f.name | |
| yield Path(temp_path) | |
| # Cleanup | |
| if Path(temp_path).exists(): | |
| Path(temp_path).unlink() | |
| def mock_daemon(): | |
| """Mock daemon process.""" | |
| daemon = MagicMock() | |
| daemon.is_running.return_value = False | |
| daemon.get_pid.return_value = None | |
| return daemon | |
| class TestCLIEntryPoint: | |
| """Test main CLI entry point.""" | |
| def test_cli_help(self, runner): | |
| """Test CLI help command.""" | |
| result = runner.invoke(main_cli, ['--help']) | |
| assert result.exit_code == 0 | |
| assert 'Usage:' in result.output or 'Commands:' in result.output | |
| assert 'Atom OS' in result.output | |
| def test_cli_version(self, runner): | |
| """Test CLI version flag.""" | |
| result = runner.invoke(main_cli, ['--version']) | |
| assert result.exit_code == 0 | |
| assert '0.1.0' in result.output | |
| def test_cli_invalid_command(self, runner): | |
| """Test CLI with invalid command.""" | |
| result = runner.invoke(main_cli, ['invalid-command-that-does-not-exist']) | |
| assert result.exit_code != 0 | |
| assert 'No such command' in result.output | |
| class TestServerStartCommand: | |
| """Test server start command.""" | |
| def test_start_default_options(self, mock_service, mock_uvicorn, runner): | |
| """Test starting server with default options.""" | |
| mock_service.return_value.is_personal = True | |
| mock_uvicorn.run = MagicMock() | |
| result = runner.invoke(main_cli, ['start']) | |
| # Should fail due to missing main_api_app import in test context | |
| # But we can verify the command structure | |
| assert 'Atom OS' in result.output or result.exit_code != 0 | |
| def test_start_with_custom_port(self, mock_service, mock_uvicorn, runner): | |
| """Test starting server with custom port.""" | |
| mock_service.return_value.is_personal = True | |
| mock_uvicorn.run = MagicMock() | |
| result = runner.invoke(main_cli, ['start', '--port', '3000']) | |
| # Command should be recognized | |
| assert 'Atom OS' in result.output or result.exit_code != 0 | |
| def test_start_with_dev_mode(self, mock_service, mock_uvicorn, runner): | |
| """Test starting server in dev mode.""" | |
| mock_service.return_value.is_personal = True | |
| mock_uvicorn.run = MagicMock() | |
| result = runner.invoke(main_cli, ['start', '--dev']) | |
| # Command should be recognized | |
| assert 'Atom OS' in result.output or result.exit_code != 0 | |
| class TestDaemonCommands: | |
| """Test daemon management commands.""" | |
| def test_daemon_help(self, runner): | |
| """Test daemon command help.""" | |
| result = runner.invoke(main_cli, ['daemon', '--help']) | |
| assert result.exit_code == 0 | |
| assert 'Start Atom OS' in result.output or 'daemon' in result.output | |
| def test_daemon_start(self, mock_is_running, mock_start, runner): | |
| """Test starting the daemon.""" | |
| mock_is_running.return_value = False | |
| mock_start.return_value = 12345 | |
| result = runner.invoke(main_cli, ['daemon']) | |
| # Should attempt to start | |
| assert result.exit_code == 0 or 'already running' in result.output.lower() | |
| def test_daemon_start_already_running(self, mock_is_running, runner): | |
| """Test starting daemon when already running.""" | |
| mock_is_running.return_value = True | |
| mock_is_running.get_pid = MagicMock(return_value=12345) | |
| result = runner.invoke(main_cli, ['daemon']) | |
| # Should show already running message | |
| assert 'already running' in result.output.lower() or result.exit_code != 0 | |
| def test_daemon_stop(self, mock_is_running, mock_stop, runner): | |
| """Test stopping the daemon.""" | |
| mock_is_running.return_value = True | |
| mock_stop.return_value = True | |
| result = runner.invoke(main_cli, ['stop']) | |
| # Should attempt to stop | |
| assert 'stopped' in result.output.lower() or result.exit_code == 0 | |
| def test_daemon_stop_not_running(self, mock_is_running, runner): | |
| """Test stopping daemon when not running.""" | |
| mock_is_running.return_value = False | |
| result = runner.invoke(main_cli, ['stop']) | |
| # Should show not running message | |
| assert 'not running' in result.output.lower() or 'stopped' in result.output.lower() | |
| def test_daemon_status_running(self, mock_is_running, mock_status, runner): | |
| """Test daemon status when running.""" | |
| mock_is_running.return_value = True | |
| mock_status.return_value = { | |
| 'running': True, | |
| 'pid': 12345, | |
| 'uptime': '2 hours' | |
| } | |
| result = runner.invoke(main_cli, ['status']) | |
| # Should show status | |
| assert result.exit_code == 0 | |
| assert 'running' in result.output.lower() or 'pid' in result.output.lower() | |
| def test_daemon_status_stopped(self, mock_is_running, runner): | |
| """Test daemon status when stopped.""" | |
| mock_is_running.return_value = False | |
| result = runner.invoke(main_cli, ['status']) | |
| # Should show stopped status | |
| assert 'stopped' in result.output.lower() or 'not running' in result.output.lower() | |
| class TestExecuteCommand: | |
| """Test command execution.""" | |
| def test_execute_without_daemon(self, mock_is_running, runner): | |
| """Test execute command when daemon not running.""" | |
| mock_is_running.return_value = False | |
| result = runner.invoke(main_cli, ['execute', 'test-command']) | |
| # Should show daemon not running message | |
| assert 'daemon' in result.output.lower() or result.exit_code != 0 | |
| def test_execute_with_daemon(self, mock_is_running, mock_post, runner): | |
| """Test execute command when daemon is running.""" | |
| mock_is_running.return_value = True | |
| mock_post.return_value = Mock( | |
| status_code=200, | |
| json=lambda: {'success': True, 'output': 'test output'} | |
| ) | |
| result = runner.invoke(main_cli, ['execute', 'test-command']) | |
| # Should attempt execution | |
| assert result.exit_code == 0 or 'test output' in result.output | |
| def test_execute_no_command(self, runner): | |
| """Test execute command without providing command.""" | |
| result = runner.invoke(main_cli, ['execute']) | |
| # Should show error or help | |
| assert result.exit_code != 0 or 'Usage:' in result.output | |
| class TestConfigCommand: | |
| """Test configuration commands.""" | |
| def test_config_show_daemon(self, mock_is_running, mock_status, runner): | |
| """Test config --show-daemon flag.""" | |
| mock_is_running.return_value = True | |
| mock_status.return_value = { | |
| 'running': True, | |
| 'pid': 12345, | |
| 'port': 8000 | |
| } | |
| result = runner.invoke(main_cli, ['config', '--show-daemon']) | |
| # Should show daemon config | |
| assert 'daemon' in result.output.lower() or 'running' in result.output.lower() | |
| def test_config_default(self, runner): | |
| """Test config command without flags.""" | |
| result = runner.invoke(main_cli, ['config']) | |
| # Should show config or help | |
| assert result.exit_code == 0 or 'Usage:' in result.output | |
| class TestLocalAgentCommand: | |
| """Test local agent management commands.""" | |
| def test_local_agent_help(self, runner): | |
| """Test local-agent command help.""" | |
| result = runner.invoke(main_cli, ['local-agent', '--help']) | |
| assert result.exit_code == 0 | |
| assert 'local' in result.output.lower() or 'agent' in result.output.lower() | |
| def test_local_agent_status_not_running(self, mock_running, runner): | |
| """Test local-agent status when not running.""" | |
| mock_running.return_value = False | |
| result = runner.invoke(main_cli, ['local-agent', 'status']) | |
| # Should show not running | |
| assert 'not running' in result.output.lower() or 'stopped' in result.output.lower() | |
| def test_local_agent_stop(self, mock_get_pid, mock_running, runner): | |
| """Test stopping local agent.""" | |
| mock_running.return_value = True | |
| mock_get_pid.return_value = 12345 | |
| result = runner.invoke(main_cli, ['local-agent', 'stop']) | |
| # Should attempt to stop | |
| assert 'stopped' in result.output.lower() or result.exit_code == 0 | |
| class TestInitCommand: | |
| """Test initialization commands.""" | |
| def test_init_help(self, runner): | |
| """Test init command help.""" | |
| result = runner.invoke(main_cli, ['init', '--help']) | |
| assert result.exit_code == 0 | |
| assert 'Initialize' in result.output or 'init' in result.output | |
| def test_init_personal_edition(self, mock_init, runner): | |
| """Test initializing Personal Edition.""" | |
| mock_init.return_value = None | |
| result = runner.invoke(main_cli, ['init', '--edition', 'personal']) | |
| # Should attempt initialization | |
| assert 'Personal' in result.output or 'initialize' in result.output.lower() or result.exit_code == 0 | |
| class TestEnableCommand: | |
| """Test feature enablement commands.""" | |
| def test_enable_help(self, runner): | |
| """Test enable command help.""" | |
| result = runner.invoke(main_cli, ['enable', '--help']) | |
| assert result.exit_code == 0 | |
| assert 'enable' in result.output.lower() or 'feature' in result.output.lower() | |
| def test_enable_features_list(self, mock_service, runner): | |
| """Test enable features command.""" | |
| mock_service_instance = MagicMock() | |
| mock_service_instance.get_all_features.return_value = { | |
| 'feature1': {'enabled': True, 'name': 'Feature 1'} | |
| } | |
| mock_service.return_value = mock_service_instance | |
| result = runner.invoke(main_cli, ['enable', 'features']) | |
| # Should show features | |
| assert result.exit_code == 0 or 'feature' in result.output.lower() | |
| class TestDaemonManager: | |
| """Test DaemonManager class directly.""" | |
| def test_get_pid_returns_none_when_no_file(self): | |
| """Verify get_pid returns None when PID file doesn't exist.""" | |
| with patch.object(daemon_module, 'PID_FILE', Path('/nonexistent/path.pid')): | |
| result = DaemonManager.get_pid() | |
| assert result is None | |
| def test_get_pid_returns_valid_integer(self, temp_pid_file): | |
| """Verify get_pid returns valid integer from PID file.""" | |
| with patch.object(daemon_module, 'PID_FILE', temp_pid_file): | |
| result = DaemonManager.get_pid() | |
| assert result == 12345 | |
| def test_get_pid_handles_invalid_file_content(self): | |
| """Verify get_pid returns None for invalid file content.""" | |
| with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.pid') as f: | |
| f.write('not_a_number') | |
| f.flush() | |
| temp_path = Path(f.name) | |
| try: | |
| with patch.object(daemon_module, 'PID_FILE', temp_path): | |
| result = DaemonManager.get_pid() | |
| assert result is None | |
| finally: | |
| temp_path.unlink() | |
| def test_is_running_with_valid_process(self, mock_psutil): | |
| """Verify is_running returns True when process exists.""" | |
| mock_psutil.pid_exists.return_value = True | |
| with patch.object(DaemonManager, 'get_pid', return_value=12345): | |
| result = DaemonManager.is_running() | |
| assert result is True | |
| def test_is_running_with_no_process(self, mock_psutil): | |
| """Verify is_running returns False when process doesn't exist.""" | |
| mock_psutil.pid_exists.return_value = False | |
| with patch.object(DaemonManager, 'get_pid', return_value=12345): | |
| result = DaemonManager.is_running() | |
| assert result is False | |
| def test_is_running_without_psutil(self): | |
| """Verify is_running works without psutil installed.""" | |
| with patch('cli.daemon.psutil', None): | |
| with patch('os.kill') as mock_kill: | |
| mock_kill.return_value = None | |
| with patch.object(DaemonManager, 'get_pid', return_value=12345): | |
| result = DaemonManager.is_running() | |
| # Should not crash | |
| def test_start_daemon_raises_error_if_already_running(self): | |
| """Verify start_daemon raises RuntimeError if already running.""" | |
| with patch.object(DaemonManager, 'is_running', return_value=True): | |
| with patch.object(DaemonManager, 'get_pid', return_value=12345): | |
| with pytest.raises(RuntimeError, match="already running"): | |
| DaemonManager.start_daemon() | |
| def test_start_daemon_creates_process_and_pid_file(self, mock_open, mock_popen): | |
| """Verify start_daemon creates subprocess and PID file.""" | |
| mock_process = Mock() | |
| mock_process.pid = 12345 | |
| mock_popen.return_value = mock_process | |
| mock_file = MagicMock() | |
| mock_open.return_value = mock_file | |
| with patch.object(DaemonManager, 'is_running', return_value=False): | |
| with patch.object(daemon_module, 'PID_FILE', Path('/tmp/test.pid')): | |
| try: | |
| DaemonManager.start_daemon() | |
| except: | |
| # Expected to fail due to path mocking | |
| pass | |
| # Verify subprocess was called | |
| assert mock_popen.called or mock_open.called | |
| def test_stop_daemon_success(self, mock_kill): | |
| """Verify stop_daemon stops running process.""" | |
| mock_kill.return_value = None | |
| with patch.object(DaemonManager, 'is_running', return_value=True): | |
| with patch.object(DaemonManager, 'get_pid', return_value=12345): | |
| with patch.object(daemon_module, 'PID_FILE', Path('/tmp/test.pid')): | |
| try: | |
| result = DaemonManager.stop_daemon() | |
| except: | |
| result = True | |
| # Should attempt to kill process | |
| assert mock_kill.called | |
| def test_stop_daemon_not_running(self, mock_kill): | |
| """Verify stop_daemon returns False when not running.""" | |
| with patch.object(DaemonManager, 'is_running', return_value=False): | |
| result = DaemonManager.stop_daemon() | |
| assert result is False | |
| def test_get_status_running(self, mock_process_class): | |
| """Verify get_status returns correct info when running.""" | |
| mock_process = MagicMock() | |
| mock_process.pid = 12345 | |
| mock_process.create_time.return_value = 1234567890 | |
| mock_process.status.return_value = 'running' | |
| mock_process_class.return_value = mock_process | |
| with patch.object(DaemonManager, 'is_running', return_value=True): | |
| with patch.object(DaemonManager, 'get_pid', return_value=12345): | |
| status = DaemonManager.get_status() | |
| assert status['running'] is True | |
| assert status['pid'] == 12345 | |
| def test_get_status_not_running(self): | |
| """Verify get_status returns correct info when not running.""" | |
| with patch.object(DaemonManager, 'is_running', return_value=False): | |
| status = DaemonManager.get_status() | |
| assert status['running'] is False | |
| assert 'pid' not in status or status['pid'] is None | |
| class TestErrorHandling: | |
| """Test CLI error handling.""" | |
| def test_missing_required_argument(self, runner): | |
| """Test error when required argument is missing.""" | |
| result = runner.invoke(main_cli, ['execute']) | |
| assert result.exit_code != 0 or 'Missing argument' in result.output | |
| def test_invalid_option_value(self, runner): | |
| """Test error with invalid option value.""" | |
| result = runner.invoke(main_cli, ['start', '--port', 'invalid']) | |
| assert result.exit_code != 0 or 'Invalid' in result.output | |
| def test_unknown_command(self, runner): | |
| """Test error with unknown command.""" | |
| result = runner.invoke(main_cli, ['unknown-command']) | |
| assert result.exit_code != 0 | |
| assert 'No such command' in result.output | |
| def test_daemon_start_port_invalid(self, mock_is_running, runner): | |
| """Test daemon start with invalid port.""" | |
| mock_is_running.return_value = False | |
| result = runner.invoke(main_cli, ['daemon', '--port', 'invalid']) | |
| assert result.exit_code != 0 or 'Invalid' in result.output | |
| class TestArgumentParsing: | |
| """Test CLI argument parsing.""" | |
| def test_start_command_parsing(self, runner): | |
| """Test start command argument parsing.""" | |
| result = runner.invoke(main_cli, ['start', '--port', '3000', '--host', 'localhost']) | |
| # Should parse without error (may fail execution) | |
| assert 'start' in result.output.lower() or result.exit_code != 0 | |
| def test_daemon_command_parsing(self, runner): | |
| """Test daemon command argument parsing.""" | |
| result = runner.invoke(main_cli, ['daemon', '-p', '3000', '-f']) | |
| # Should parse without error | |
| assert 'daemon' in result.output.lower() or result.exit_code != 0 | |
| def test_execute_command_parsing(self, runner): | |
| """Test execute command argument parsing.""" | |
| result = runner.invoke(main_cli, ['execute', 'ls -la']) | |
| # Should parse without error | |
| assert 'execute' in result.output.lower() or result.exit_code != 0 | |
| def test_config_command_parsing(self, runner): | |
| """Test config command argument parsing.""" | |
| result = runner.invoke(main_cli, ['config', '--show-daemon']) | |
| # Should parse without error | |
| assert 'config' in result.output.lower() or result.exit_code != 0 | |
| class TestHostMountWarning: | |
| """Test host mount warning and confirmation.""" | |
| def test_host_mount_requires_confirmation(self, mock_confirm, mock_service, mock_uvicorn, runner): | |
| """Test that host mount requires user confirmation.""" | |
| mock_service_instance = MagicMock() | |
| mock_service_instance.is_personal = True | |
| mock_service.return_value = mock_service_instance | |
| mock_confirm.return_value = False # User declines | |
| mock_uvicorn.run = MagicMock() | |
| result = runner.invoke(main_cli, ['start', '--host-mount']) | |
| # Should show warning or exit | |
| assert 'warning' in result.output.lower() or 'host' in result.output.lower() | |
| class TestDaemonManagerEdgeCases: | |
| """Test DaemonManager edge cases and error paths.""" | |
| def test_start_daemon_pid_file_write_failure(self, mock_open, mock_popen): | |
| """Test start_daemon when PID file write fails.""" | |
| mock_process = Mock() | |
| mock_process.pid = 12345 | |
| mock_popen.return_value = mock_process | |
| mock_open.side_effect = IOError("Cannot write PID file") | |
| with patch.object(DaemonManager, 'is_running', return_value=False): | |
| with pytest.raises(RuntimeError, match="Cannot write PID file"): | |
| DaemonManager.start_daemon() | |
| def test_start_daemon_subprocess_failure(self, mock_popen): | |
| """Test start_daemon when subprocess creation fails.""" | |
| mock_popen.side_effect = Exception("Subprocess failed") | |
| with patch.object(DaemonManager, 'is_running', return_value=False): | |
| with pytest.raises(RuntimeError, match="Failed to start daemon"): | |
| DaemonManager.start_daemon() | |
| def test_is_running_psutil_exception(self, mock_kill, mock_pid_exists): | |
| """Test is_running when psutil raises exception.""" | |
| mock_pid_exists.side_effect = Exception("psutil error") | |
| with patch.object(DaemonManager, 'get_pid', return_value=12345): | |
| result = DaemonManager.is_running() | |
| # Should fallback to False on exception | |
| assert result is False | |
| class TestLocalAgentCommands: | |
| """Test local agent management commands in detail.""" | |
| def test_local_agent_start(self, mock_running, runner): | |
| """Test starting local agent.""" | |
| mock_running.return_value = False | |
| result = runner.invoke(main_cli, ['local-agent', 'start']) | |
| # Should attempt to start | |
| assert 'starting' in result.output.lower() or 'start' in result.output.lower() | |
| def test_local_agent_start_already_running(self, mock_get_pid, mock_running, runner): | |
| """Test starting local agent when already running.""" | |
| mock_running.return_value = True | |
| mock_get_pid.return_value = 12345 | |
| result = runner.invoke(main_cli, ['local-agent', 'start']) | |
| # Should show already running message | |
| assert 'already' in result.output.lower() or 'running' in result.output.lower() | |
| def test_local_agent_execute(self, mock_post, mock_running, runner): | |
| """Test executing command via local agent.""" | |
| mock_running.return_value = True | |
| mock_post.return_value = Mock( | |
| status_code=200, | |
| json=lambda: {'success': True, 'output': 'test output'} | |
| ) | |
| result = runner.invoke(main_cli, ['local-agent', 'execute', 'ls -la']) | |
| # Should attempt execution | |
| assert 'execute' in result.output.lower() or 'test output' in result.output | |
| class TestInitCommandDetailed: | |
| """Test initialization commands in detail.""" | |
| def test_init_with_database_url(self, mock_init, runner): | |
| """Test init with custom database URL.""" | |
| mock_init.return_value = None | |
| result = runner.invoke(main_cli, [ | |
| 'init', | |
| '--edition', 'personal', | |
| '--database-url', 'postgresql://localhost/test' | |
| ]) | |
| # Should attempt initialization | |
| assert 'Personal' in result.output or 'init' in result.output.lower() | |
| def test_init_enterprise_edition(self, mock_init, runner): | |
| """Test initializing Enterprise Edition.""" | |
| mock_init.return_value = None | |
| result = runner.invoke(main_cli, ['init', '--edition', 'enterprise']) | |
| # Should attempt initialization | |
| assert 'Enterprise' in result.output or 'init' in result.output.lower() | |
| def test_init_interactive_mode(self, mock_init, mock_input, runner): | |
| """Test init in interactive mode.""" | |
| mock_init.return_value = None | |
| mock_input.return_value = 'y' | |
| result = runner.invoke(main_cli, ['init']) | |
| # Should handle interactive input | |
| assert result.exit_code == 0 or 'init' in result.output.lower() | |
| class TestEnableCommandDetailed: | |
| """Test feature enablement commands in detail.""" | |
| def test_enable_enterprise_success(self, mock_open, mock_service, runner): | |
| """Test enabling enterprise edition successfully.""" | |
| mock_service_instance = MagicMock() | |
| mock_service_instance.is_personal = False | |
| mock_service.return_value = mock_service_instance | |
| mock_file = MagicMock() | |
| mock_open.return_value.__enter__.return_value = mock_file | |
| result = runner.invoke(main_cli, [ | |
| 'enable', 'enterprise', | |
| '--workspace-id', 'test-ws', | |
| '--database-url', 'postgresql://localhost/test', | |
| '--yes' | |
| ]) | |
| # Should attempt to enable | |
| assert 'Enterprise' in result.output or 'enable' in result.output.lower() | |
| class TestStopCommand: | |
| """Test stop command variants.""" | |
| def test_stop_force_flag(self, mock_is_running, mock_stop, runner): | |
| """Test stop command with force.""" | |
| mock_is_running.return_value = True | |
| mock_stop.return_value = True | |
| result = runner.invoke(main_cli, ['stop']) | |
| # Should attempt to stop | |
| assert 'stopped' in result.output.lower() or result.exit_code == 0 | |
| def test_stop_no_daemon_running(self, mock_is_running, runner): | |
| """Test stop when no daemon is running.""" | |
| mock_is_running.return_value = False | |
| result = runner.invoke(main_cli, ['stop']) | |
| # Should show not running message | |
| assert 'not running' in result.output.lower() or 'stopped' in result.output.lower() | |
| class TestConfigCommandDetailed: | |
| """Test config command in detail.""" | |
| def test_config_without_daemon(self, mock_is_running, mock_status, runner): | |
| """Test config command when daemon not running.""" | |
| mock_is_running.return_value = False | |
| result = runner.invoke(main_cli, ['config', '--show-daemon']) | |
| # Should show not running | |
| assert 'not running' in result.output.lower() | |
| def test_config_show_env_file(self, mock_open, mock_exists, runner): | |
| """Test config showing environment file.""" | |
| mock_exists.return_value = True | |
| mock_file = MagicMock() | |
| mock_file.read.return_value = 'KEY=value\n' | |
| mock_open.return_value.__enter__.return_value = mock_file | |
| result = runner.invoke(main_cli, ['config']) | |
| # Should show configuration | |
| assert result.exit_code == 0 or 'config' in result.output.lower() | |
| class TestDaemonCommandDetailed: | |
| """Test daemon command in detail.""" | |
| def test_daemon_with_all_options(self, mock_is_running, mock_start, runner): | |
| """Test daemon command with all options.""" | |
| mock_is_running.return_value = False | |
| mock_start.return_value = 12345 | |
| result = runner.invoke(main_cli, [ | |
| 'daemon', | |
| '--port', '9000', | |
| '--host', '127.0.0.1', | |
| '--workers', '4', | |
| '--host-mount', | |
| '--dev', | |
| '--foreground' | |
| ]) | |
| # Should parse all options | |
| assert result.exit_code == 0 or 'daemon' in result.output.lower() | |
| def test_daemon_short_options(self, mock_is_running, mock_start, runner): | |
| """Test daemon command with short options.""" | |
| mock_is_running.return_value = False | |
| mock_start.return_value = 12345 | |
| result = runner.invoke(main_cli, ['daemon', '-p', '9000', '-h', 'localhost', '-w', '2', '-f']) | |
| # Should parse short options | |
| assert result.exit_code == 0 or 'daemon' in result.output.lower() | |
| class TestExecuteCommandDetailed: | |
| """Test execute command in detail.""" | |
| def test_execute_success(self, mock_is_running, mock_post, runner): | |
| """Test successful command execution.""" | |
| mock_is_running.return_value = True | |
| mock_post.return_value = Mock( | |
| status_code=200, | |
| json=lambda: {'success': True, 'output': 'Command executed successfully'} | |
| ) | |
| result = runner.invoke(main_cli, ['execute', 'echo test']) | |
| # Should show output | |
| assert 'Command executed successfully' in result.output or result.exit_code == 0 | |
| def test_execute_http_error(self, mock_is_running, mock_post, runner): | |
| """Test execute command with HTTP error.""" | |
| mock_is_running.return_value = True | |
| mock_post.return_value = Mock( | |
| status_code=500, | |
| json=lambda: {'success': False, 'error': 'Internal server error'} | |
| ) | |
| result = runner.invoke(main_cli, ['execute', 'invalid command']) | |
| # Should show error | |
| assert 'error' in result.output.lower() or result.exit_code != 0 | |
| def test_execute_empty_command(self, mock_is_running, runner): | |
| """Test execute command with empty string.""" | |
| mock_is_running.return_value = False | |
| result = runner.invoke(main_cli, ['execute', '']) | |
| # Should handle empty command | |
| assert result.exit_code != 0 or 'command' in result.output.lower() | |