"""Tests for CLI commands.""" import json import os import tempfile import pytest from click.testing import CliRunner from dataforge.cli import main from dataforge.commands import convert, validate, batch_validate, typecheck FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "dataforge_fixtures") class TestConvertCommand: """Tests for convert command.""" def test_convert_json_to_yaml(self): runner = CliRunner() input_file = os.path.join(FIXTURES_DIR, "sample.json") with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: output_file = f.name try: result = runner.invoke(convert, [input_file, output_file, "--to", "yaml"]) assert result.exit_code == 0 with open(output_file, "r") as f: content = f.read() assert "name:" in content assert "test-project" in content finally: os.unlink(output_file) def test_convert_yaml_to_toml(self): runner = CliRunner() input_file = os.path.join(FIXTURES_DIR, "sample.yaml") with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f: output_file = f.name try: result = runner.invoke(convert, [input_file, output_file, "--to", "toml"]) assert result.exit_code == 0 with open(output_file, "r") as f: content = f.read() assert "name =" in content finally: os.unlink(output_file) def test_convert_with_explicit_format(self): runner = CliRunner() input_file = os.path.join(FIXTURES_DIR, "sample.json") with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: output_file = f.name try: result = runner.invoke(convert, [input_file, output_file, "--from", "json", "--to", "yaml"]) assert result.exit_code == 0 finally: os.unlink(output_file) def test_convert_invalid_format(self): runner = CliRunner() input_file = os.path.join(FIXTURES_DIR, "sample.json") with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f: output_file = f.name try: result = runner.invoke(convert, [input_file, output_file, "--to", "invalid"]) assert result.exit_code != 0 finally: os.unlink(output_file) def test_convert_compact_output(self): runner = CliRunner() input_file = os.path.join(FIXTURES_DIR, "sample.json") with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f: output_file = f.name try: result = runner.invoke(convert, [input_file, output_file, "--to", "json", "--indent", "0"]) assert result.exit_code == 0 with open(output_file, "r") as f: content = f.read() assert "\n" not in content finally: os.unlink(output_file) class TestValidateCommand: """Tests for validate command.""" def test_validate_valid_file(self): runner = CliRunner() input_file = os.path.join(FIXTURES_DIR, "sample.json") schema_file = os.path.join(FIXTURES_DIR, "valid_schema.json") result = runner.invoke(validate, [input_file, "--schema", schema_file]) assert result.exit_code == 0 assert "passed" in result.output def test_validate_invalid_file(self): runner = CliRunner() schema_file = os.path.join(FIXTURES_DIR, "valid_schema.json") with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f: json.dump({"name": "test", "version": "invalid"}, f) invalid_file = f.name try: result = runner.invoke(validate, [invalid_file, "--schema", schema_file]) assert result.exit_code != 0 finally: os.unlink(invalid_file) def test_validate_without_schema(self): runner = CliRunner() input_file = os.path.join(FIXTURES_DIR, "sample.json") result = runner.invoke(validate, [input_file]) assert result.exit_code == 0 def test_validate_quiet_mode(self): runner = CliRunner() input_file = os.path.join(FIXTURES_DIR, "sample.json") schema_file = os.path.join(FIXTURES_DIR, "valid_schema.json") result = runner.invoke(validate, [input_file, "--schema", schema_file, "--quiet"]) assert result.exit_code == 0 assert "passed" not in result.output class TestBatchValidateCommand: """Tests for batch validate command.""" def test_batch_validate_multiple_files(self): runner = CliRunner() schema_file = os.path.join(FIXTURES_DIR, "valid_schema.json") input_files = [ os.path.join(FIXTURES_DIR, "sample.json"), os.path.join(FIXTURES_DIR, "sample.yaml"), ] result = runner.invoke(batch_validate, ["--schema", schema_file, *input_files]) assert result.exit_code == 0 assert "Valid" in result.output or "valid" in result.output def test_batch_validate_pattern(self): runner = CliRunner() schema_file = os.path.join(FIXTURES_DIR, "valid_schema.json") json_file = os.path.join(FIXTURES_DIR, "sample.json") result = runner.invoke(batch_validate, ["--schema", schema_file, json_file]) assert result.exit_code == 0 class TestTypeCheckCommand: """Tests for typecheck command.""" def test_typecheck_simple_file(self): runner = CliRunner() input_file = os.path.join(FIXTURES_DIR, "sample.json") result = runner.invoke(typecheck, [input_file]) assert result.exit_code == 0 assert "object" in result.output def test_typecheck_infer_schema(self): runner = CliRunner() input_file = os.path.join(FIXTURES_DIR, "sample.json") result = runner.invoke(typecheck, [input_file, "--infer"]) assert result.exit_code == 0 assert '"type"' in result.output or "'type'" in result.output def test_typecheck_quiet_mode(self): runner = CliRunner() input_file = os.path.join(FIXTURES_DIR, "sample.json") result = runner.invoke(typecheck, [input_file, "--quiet"]) assert result.exit_code == 0 class TestMainCLI: """Tests for main CLI entry point.""" def test_main_help(self): runner = CliRunner() result = runner.invoke(main, ["--help"]) assert result.exit_code == 0 assert "DataForge" in result.output assert "convert" in result.output assert "validate" in result.output def test_main_version(self): runner = CliRunner() result = runner.invoke(main, ["--version"]) assert result.exit_code == 0 assert "1.0.0" in result.output