diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..ba235ee --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,167 @@ +"""Integration tests for CLI commands.""" + +import pytest +import json +from pathlib import Path +from typer.testing import CliRunner + +from config_convert.cli import app + + +class TestCLIConvert: + @pytest.fixture + def runner(self): + return CliRunner() + + def test_convert_json_to_yaml(self, runner, tmp_path): + input_file = tmp_path / "input.json" + input_file.write_text('{"name": "test", "value": 123}') + output_file = tmp_path / "output.yaml" + result = runner.invoke(app, ["convert", str(input_file), "--to", "yaml", "-o", str(output_file)]) + assert result.exit_code == 0 + assert output_file.exists() + content = output_file.read_text() + assert "name: test" in content + + def test_convert_yaml_to_json(self, runner, tmp_path): + input_file = tmp_path / "input.yaml" + input_file.write_text("name: test\nvalue: 123") + output_file = tmp_path / "output.json" + result = runner.invoke(app, ["convert", str(input_file), "--from", "yaml", "--to", "json", "-o", str(output_file)]) + assert result.exit_code == 0 + data = json.loads(output_file.read_text()) + assert data == {"name": "test", "value": 123} + + def test_convert_env_to_json(self, runner, tmp_path): + input_file = tmp_path / "input.env" + input_file.write_text("NAME=test\nENABLED=true") + output_file = tmp_path / "output.json" + result = runner.invoke(app, ["convert", str(input_file), "--from", "env", "--to", "json", "-o", str(output_file)]) + assert result.exit_code == 0 + data = json.loads(output_file.read_text()) + assert data["NAME"] == "test" + assert data["ENABLED"] is True + + def test_convert_with_stdin(self, runner, tmp_path): + output_file = tmp_path / "output.json" + result = runner.invoke(app, ["convert", "--stdin", "--from", "json", "--to", "json", "-o", str(output_file)], input='{"name": "stdin-test"}') + assert result.exit_code == 0 + data = json.loads(output_file.read_text()) + assert data["name"] == "stdin-test" + + def test_convert_missing_input(self, runner): + result = runner.invoke(app, ["convert", "--to", "yaml"]) + assert result.exit_code == 2 + + def test_convert_invalid_format(self, runner, tmp_path): + input_file = tmp_path / "input.json" + input_file.write_text("{}") + result = runner.invoke(app, ["convert", str(input_file), "--to", "invalid"]) + assert result.exit_code == 2 + + def test_convert_unsupported_format(self, runner, tmp_path): + input_file = tmp_path / "input.xml" + input_file.write_text("") + result = runner.invoke(app, ["convert", str(input_file), "--to", "yaml"]) + assert result.exit_code == 2 + + +class TestCLIValidate: + @pytest.fixture + def runner(self): + return CliRunner() + + def test_validate_valid_json(self, runner, tmp_path): + input_file = tmp_path / "valid.json" + input_file.write_text('{"name": "test"}') + result = runner.invoke(app, ["validate", str(input_file)]) + assert result.exit_code == 0 + assert "Valid" in result.output + + def test_validate_invalid_json(self, runner, tmp_path): + input_file = tmp_path / "invalid.json" + input_file.write_text("{invalid}") + result = runner.invoke(app, ["validate", str(input_file)]) + assert result.exit_code == 4 + assert "Invalid" in result.output + + def test_validate_valid_yaml(self, runner, tmp_path): + input_file = tmp_path / "valid.yaml" + input_file.write_text("name: test") + result = runner.invoke(app, ["validate", str(input_file)]) + assert result.exit_code == 0 + + def test_validate_with_stdin(self, runner): + result = runner.invoke(app, ["validate", "--stdin", "--format", "json"], input='{"name": "test"}') + assert result.exit_code == 0 + + +class TestCLIFlatten: + @pytest.fixture + def runner(self): + return CliRunner() + + def test_flatten_json_to_env(self, runner, tmp_path): + input_file = tmp_path / "input.json" + input_file.write_text('{"database": {"host": "localhost", "port": 5432}}') + output_file = tmp_path / "output.env" + result = runner.invoke(app, ["flatten", str(input_file), "--format", "env", "-o", str(output_file)]) + assert result.exit_code == 0 + content = output_file.read_text() + assert "database.host=localhost" in content + + def test_flatten_with_custom_format(self, runner, tmp_path): + input_file = tmp_path / "input.json" + input_file.write_text('{"a": {"b": "c"}}') + output_file = tmp_path / "output.json" + result = runner.invoke(app, ["flatten", str(input_file), "--format", "json", "-o", str(output_file)]) + assert result.exit_code == 0 + + +class TestCLIUnflatten: + @pytest.fixture + def runner(self): + return CliRunner() + + def test_unflatten_env_to_json(self, runner, tmp_path): + input_file = tmp_path / "input.env" + input_file.write_text("DATABASE_HOST=localhost\nDATABASE_PORT=5432") + output_file = tmp_path / "output.json" + result = runner.invoke(app, ["unflatten", str(input_file), "--format", "json", "-o", str(output_file)]) + assert result.exit_code == 0 + data = json.loads(output_file.read_text()) + assert data["DATABASE_HOST"] == "localhost" + + +class TestCLISchema: + @pytest.fixture + def runner(self): + return CliRunner() + + def test_generate_schema(self, runner, tmp_path): + input_file = tmp_path / "input.json" + input_file.write_text('{"name": "test", "count": 123}') + output_file = tmp_path / "schema.json" + result = runner.invoke(app, ["schema", str(input_file), "-o", str(output_file)]) + assert result.exit_code == 0 + schema = json.loads(output_file.read_text()) + assert schema["type"] == "object" + + def test_schema_with_stdin(self, runner, tmp_path): + output_file = tmp_path / "schema.json" + result = runner.invoke(app, ["schema", "--stdin", "-o", str(output_file)], input='{"name": "test"}') + assert result.exit_code == 0 + + +class TestCLIFormats: + @pytest.fixture + def runner(self): + return CliRunner() + + def test_formats_command(self, runner): + result = runner.invoke(app, ["formats"]) + assert result.exit_code == 0 + assert "JSON" in result.output + assert "YAML" in result.output + assert "TOML" in result.output + assert "ENV" in result.output