@@ -1,141 +1,185 @@
|
|||||||
"""Tests for the CLI interface."""
|
"""Tests for CLI interface."""
|
||||||
|
|
||||||
|
import tempfile
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import json
|
|
||||||
import pytest
|
import pytest
|
||||||
from click.testing import CliRunner
|
from click.testing import CliRunner
|
||||||
|
|
||||||
from configconverter.cli import main
|
from config_converter.cli import main
|
||||||
|
|
||||||
|
|
||||||
class TestCLI:
|
class TestCLI:
|
||||||
"""Tests for the CLI interface."""
|
"""Tests for CLI commands."""
|
||||||
|
|
||||||
@pytest.fixture
|
def setup_method(self) -> None:
|
||||||
def runner(self):
|
self.runner = CliRunner()
|
||||||
return CliRunner()
|
|
||||||
|
|
||||||
def test_help_command(self, runner):
|
def test_main_help(self) -> None:
|
||||||
result = runner.invoke(main, ["--help"])
|
"""Test main command help."""
|
||||||
|
result = self.runner.invoke(main, ["--help"])
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
assert "convert" in result.output
|
assert "Config Converter" in result.output
|
||||||
assert "validate" in result.output
|
|
||||||
assert "query" in result.output
|
|
||||||
assert "batch" in result.output
|
|
||||||
|
|
||||||
def test_convert_command_help(self, runner):
|
def test_convert_command_help(self) -> None:
|
||||||
result = runner.invoke(main, ["convert", "--help"])
|
"""Test convert command help."""
|
||||||
|
result = self.runner.invoke(main, ["convert", "--help"])
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
assert "--from" in result.output
|
assert "SOURCE" in result.output
|
||||||
assert "--to" in result.output
|
|
||||||
assert "--indent" in result.output
|
|
||||||
|
|
||||||
def test_validate_command_help(self, runner):
|
def test_convert_json_to_yaml(self) -> None:
|
||||||
result = runner.invoke(main, ["validate", "--help"])
|
"""Test converting JSON to YAML."""
|
||||||
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
|
||||||
|
f.write('{"key": "value", "number": 42}')
|
||||||
|
f.flush()
|
||||||
|
source = f.name
|
||||||
|
|
||||||
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
|
||||||
|
output = f.name
|
||||||
|
f.write("")
|
||||||
|
f.flush()
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = self.runner.invoke(main, ["convert", source, "-t", "yaml", "-o", output, "-w"])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
with open(output) as f:
|
||||||
|
content = f.read()
|
||||||
|
assert "key: value" in content
|
||||||
|
finally:
|
||||||
|
Path(source).unlink(missing_ok=True)
|
||||||
|
Path(output).unlink(missing_ok=True)
|
||||||
|
|
||||||
|
def test_convert_yaml_to_toml(self) -> None:
|
||||||
|
"""Test converting YAML to TOML."""
|
||||||
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
|
||||||
|
f.write("key: value\nnumber: 42\n")
|
||||||
|
f.flush()
|
||||||
|
source = f.name
|
||||||
|
|
||||||
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f:
|
||||||
|
output = f.name
|
||||||
|
f.write("")
|
||||||
|
f.flush()
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = self.runner.invoke(main, ["convert", source, "-t", "toml", "-o", output, "-w"])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
with open(output) as f:
|
||||||
|
content = f.read()
|
||||||
|
assert 'key = "value"' in content
|
||||||
|
finally:
|
||||||
|
Path(source).unlink(missing_ok=True)
|
||||||
|
Path(output).unlink(missing_ok=True)
|
||||||
|
|
||||||
|
def test_convert_auto_detect_format(self) -> None:
|
||||||
|
"""Test auto-detection of format from extension."""
|
||||||
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
|
||||||
|
f.write('{"key": "value"}')
|
||||||
|
f.flush()
|
||||||
|
source = f.name
|
||||||
|
|
||||||
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
|
||||||
|
output = f.name
|
||||||
|
f.write("")
|
||||||
|
f.flush()
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = self.runner.invoke(main, ["convert", source, "-t", "yaml", "-o", output, "-w"])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
finally:
|
||||||
|
Path(source).unlink(missing_ok=True)
|
||||||
|
Path(output).unlink(missing_ok=True)
|
||||||
|
|
||||||
|
def test_infer_command(self) -> None:
|
||||||
|
"""Test infer schema command."""
|
||||||
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
|
||||||
|
f.write('{"name": "test", "value": 42}')
|
||||||
|
f.flush()
|
||||||
|
source = f.name
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = self.runner.invoke(main, ["infer", source])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert "object" in result.output
|
||||||
|
finally:
|
||||||
|
Path(source).unlink(missing_ok=True)
|
||||||
|
|
||||||
|
def test_validate_command(self) -> None:
|
||||||
|
"""Test validate command."""
|
||||||
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
|
||||||
|
f.write('{"name": "test", "value": 42}')
|
||||||
|
f.flush()
|
||||||
|
source = f.name
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = self.runner.invoke(main, ["validate", source])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert "passed" in result.output.lower()
|
||||||
|
finally:
|
||||||
|
Path(source).unlink(missing_ok=True)
|
||||||
|
|
||||||
|
def test_generate_ts_command(self) -> None:
|
||||||
|
"""Test generate-ts command."""
|
||||||
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
|
||||||
|
f.write('{"name": "test", "value": 42}')
|
||||||
|
f.flush()
|
||||||
|
source = f.name
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = self.runner.invoke(main, ["generate-ts", source])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert "export interface" in result.output
|
||||||
|
assert "name: string" in result.output
|
||||||
|
finally:
|
||||||
|
Path(source).unlink(missing_ok=True)
|
||||||
|
|
||||||
|
def test_formats_command(self) -> None:
|
||||||
|
"""Test formats command."""
|
||||||
|
result = self.runner.invoke(main, ["formats"])
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
assert "--format" in result.output
|
assert "json" in result.output
|
||||||
assert "--quiet" in result.output
|
assert "yaml" in result.output
|
||||||
|
assert "toml" in result.output
|
||||||
|
assert "ini" in result.output
|
||||||
|
|
||||||
def test_query_command_help(self, runner):
|
def test_batch_command(self) -> None:
|
||||||
result = runner.invoke(main, ["query", "--help"])
|
"""Test batch conversion command."""
|
||||||
assert result.exit_code == 0
|
import os
|
||||||
assert "--format" in result.output
|
import tempfile
|
||||||
assert "--output" in result.output
|
|
||||||
|
|
||||||
def test_convert_json_to_yaml(self, runner):
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
input_data = '{"name": "test", "value": 123}'
|
for i in range(3):
|
||||||
result = runner.invoke(main, ["convert", "--to", "yaml"], input=input_data)
|
json_file = Path(tmpdir) / f"config{i}.json"
|
||||||
assert result.exit_code == 0
|
json_file.write_text(f'{{"key{i}": "value{i}"}}')
|
||||||
assert "name: test" in result.output
|
|
||||||
assert "value: 123" in result.output
|
|
||||||
|
|
||||||
def test_convert_json_to_toml(self, runner):
|
output_dir = Path(tmpdir) / "output"
|
||||||
input_data = '{"name": "test", "value": 123}'
|
output_dir.mkdir()
|
||||||
result = runner.invoke(main, ["convert", "--to", "toml"], input=input_data)
|
|
||||||
assert result.exit_code == 0
|
|
||||||
assert 'name = "test"' in result.output
|
|
||||||
assert "value = 123" in result.output
|
|
||||||
|
|
||||||
def test_convert_yaml_to_json(self, runner):
|
result = self.runner.invoke(main, [
|
||||||
input_data = "name: test\nvalue: 123\n"
|
"batch",
|
||||||
result = runner.invoke(main, ["convert", "--from", "yaml", "--to", "json"], input=input_data)
|
f"{tmpdir}/*.json",
|
||||||
assert result.exit_code == 0
|
"-t", "yaml",
|
||||||
assert "name" in result.output
|
"-o", str(output_dir),
|
||||||
assert "test" in result.output
|
])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
yaml_files = list(output_dir.glob("*.yaml"))
|
||||||
|
assert len(yaml_files) == 3
|
||||||
|
|
||||||
def test_convert_toml_to_yaml(self, runner):
|
def test_color_option(self) -> None:
|
||||||
input_data = 'name = "test"\nvalue = 123\n'
|
"""Test color option."""
|
||||||
result = runner.invoke(main, ["convert", "--from", "toml", "--to", "yaml"], input=input_data)
|
result = self.runner.invoke(main, ["--no-color", "formats"])
|
||||||
assert result.exit_code == 0
|
|
||||||
assert "name: test" in result.output
|
|
||||||
|
|
||||||
def test_validate_valid_json(self, runner):
|
|
||||||
input_data = '{"name": "test"}'
|
|
||||||
result = runner.invoke(main, ["validate"], input=input_data)
|
|
||||||
assert result.exit_code == 0
|
|
||||||
assert "Valid" in result.output
|
|
||||||
|
|
||||||
def test_validate_invalid_json(self, runner):
|
|
||||||
input_data = '{"name": "test",}' # trailing comma - invalid JSON
|
|
||||||
result = runner.invoke(main, ["validate", "--format", "json"], input=input_data)
|
|
||||||
assert result.exit_code != 0
|
|
||||||
|
|
||||||
def test_validate_quiet_mode(self, runner):
|
|
||||||
input_data = '{"name": "test"}'
|
|
||||||
result = runner.invoke(main, ["validate", "--quiet"], input=input_data)
|
|
||||||
assert result.exit_code == 0
|
|
||||||
assert result.output.strip() == ""
|
|
||||||
|
|
||||||
def test_query_simple_key(self, runner):
|
|
||||||
input_data = '{"name": "test", "value": 123}'
|
|
||||||
result = runner.invoke(main, ["query", "name", "-"], input=input_data)
|
|
||||||
assert result.exit_code == 0
|
|
||||||
assert '"test"' in result.output
|
|
||||||
|
|
||||||
def test_query_nested_key(self, runner):
|
|
||||||
input_data = '{"server": {"host": "localhost"}}'
|
|
||||||
result = runner.invoke(main, ["query", "server.host", "-"], input=input_data)
|
|
||||||
assert result.exit_code == 0
|
|
||||||
assert "localhost" in result.output
|
|
||||||
|
|
||||||
def test_query_invalid_expression(self, runner):
|
|
||||||
input_data = '{"name": "test"}'
|
|
||||||
result = runner.invoke(main, ["query", "invalid``", "-"], input=input_data)
|
|
||||||
assert result.exit_code != 0
|
|
||||||
assert "Query Error" in result.output
|
|
||||||
|
|
||||||
def test_format_command(self, runner):
|
|
||||||
input_data = '{"name":"test"}'
|
|
||||||
result = runner.invoke(main, ["format", "--indent", "4"], input=input_data)
|
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
|
|
||||||
def test_format_to_json(self, runner):
|
def test_convert_unsupported_format(self) -> None:
|
||||||
input_data = 'name: test\n'
|
"""Test conversion with unsupported format."""
|
||||||
result = runner.invoke(main, ["format", "--to", "json"], input=input_data)
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
|
||||||
assert result.exit_code == 0
|
f.write('{"key": "value"}')
|
||||||
assert "name" in result.output
|
f.flush()
|
||||||
|
source = f.name
|
||||||
|
|
||||||
def test_version_option(self, runner):
|
try:
|
||||||
result = runner.invoke(main, ["--version"])
|
result = self.runner.invoke(main, ["convert", source, "-t", "unsupported"])
|
||||||
assert result.exit_code == 0
|
assert result.exit_code != 0
|
||||||
assert "1.0.0" in result.output
|
assert "unsupported" in result.output.lower()
|
||||||
|
finally:
|
||||||
def test_convert_with_custom_indent(self, runner):
|
Path(source).unlink(missing_ok=True)
|
||||||
input_data = '{"name": "test", "nested": {"a": 1}}'
|
|
||||||
result = runner.invoke(main, ["convert", "--to", "json", "--indent", "4"], input=input_data)
|
|
||||||
assert result.exit_code == 0
|
|
||||||
assert " " in result.output
|
|
||||||
|
|
||||||
def test_invalid_indent_option(self, runner):
|
|
||||||
input_data = '{"name": "test"}'
|
|
||||||
result = runner.invoke(main, ["convert", "--to", "json", "--indent", "3"], input=input_data)
|
|
||||||
assert result.exit_code != 0
|
|
||||||
|
|
||||||
def test_convert_empty_input(self, runner):
|
|
||||||
result = runner.invoke(main, ["convert", "--to", "json"], input="")
|
|
||||||
assert result.exit_code == 0
|
|
||||||
assert result.output.strip() == ""
|
|
||||||
|
|
||||||
def test_validate_empty_input(self, runner):
|
|
||||||
result = runner.invoke(main, ["validate"], input="")
|
|
||||||
assert result.exit_code == 0
|
|
||||||
assert "Valid" in result.output
|
|
||||||
|
|||||||
Reference in New Issue
Block a user