diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..540b27f --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,110 @@ +"""Unit tests for CLI interface.""" + +import os +import tempfile +from pathlib import Path +from unittest.mock import patch, MagicMock + +import pytest +from click.testing import CliRunner + +from dev_env_sync.cli.main import cli, get_default_config_path, load_config +from dev_env_sync import __version__ + + +class TestCLI: + """Tests for CLI interface.""" + + @pytest.fixture + def runner(self): + """Create a CLI runner.""" + return CliRunner() + + def test_version_command(self, runner): + """Test version command.""" + result = runner.invoke(cli, ["version"]) + + assert result.exit_code == 0 + assert __version__ in result.output + + def test_platforms_command(self, runner): + """Test platforms command.""" + result = runner.invoke(cli, ["platforms"]) + + assert result.exit_code == 0 + assert "Current Platform" in result.output + assert "Supported Platforms" in result.output + assert "Linux" in result.output + assert "macOS" in result.output + assert "WSL" in result.output + + def test_status_command_no_config(self, runner): + """Test status command without configuration.""" + result = runner.invoke(cli, ["status"]) + + assert result.exit_code == 0 + assert "Platform:" in result.output + + def test_sync_command_no_config(self, runner): + """Test sync command without configuration.""" + result = runner.invoke(cli, ["sync"]) + + assert result.exit_code != 0 + assert "No configuration file found" in result.output + + def test_init_command(self, runner, temp_dir): + """Test init command.""" + output_file = temp_dir / "test-config.yml" + + result = runner.invoke(cli, ["init", "-o", str(output_file)]) + + assert result.exit_code == 0 + assert "Sample configuration written to" in result.output + assert output_file.exists() + + def test_verbose_flag(self, runner): + """Test verbose flag.""" + result = runner.invoke(cli, ["--verbose", "version"]) + + assert result.exit_code == 0 + + def test_dry_run_flag(self, runner, temp_dir): + """Test dry-run flag with config.""" + config_file = temp_dir / ".dev-env-sync.yml" + config_file.write_text('version: "1.0"\nname: "Test"') + + with patch('dev_env_sync.cli.main.get_default_config_path', return_value=str(config_file)): + result = runner.invoke(cli, ["--dry-run", "status"]) + + assert result.exit_code == 0 + assert "DRY-RUN MODE" in result.output + + +class TestConfigPathResolution: + """Tests for configuration path resolution.""" + + def test_get_default_config_path_env(self, temp_dir, monkeypatch): + """Test getting config path from environment variable.""" + config_file = temp_dir / "test-config.yml" + config_file.write_text("version: '1.0'") + + monkeypatch.setenv("DEV_ENV_SYNC_CONFIG", str(config_file)) + + path = get_default_config_path() + + assert path == str(config_file) + + def test_load_config_success(self, sample_config_yaml, temp_dir): + """Test loading configuration successfully.""" + config_file = temp_dir / "config.yml" + config_file.write_text(sample_config_yaml) + + config = load_config(str(config_file)) + + assert config is not None + assert config.version == "1.0" + + def test_load_config_nonexistent(self): + """Test loading nonexistent configuration.""" + with pytest.raises(Exception): + load_config("/nonexistent/config.yml")