diff --git a/tests/test_dataforge_parsers.py b/tests/test_dataforge_parsers.py new file mode 100644 index 0000000..9035b6d --- /dev/null +++ b/tests/test_dataforge_parsers.py @@ -0,0 +1,158 @@ +"""Tests for parsers module.""" + +import json +import os +import tempfile + +import pytest +import yaml + +from dataforge.parsers import ( + detect_format, + detect_format_from_content, + load_data, + parse_content, + dump_data, + SUPPORTED_FORMATS, +) + + +FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "dataforge_fixtures") + + +class TestDetectFormat: + """Tests for format detection.""" + + def test_detect_json(self): + assert detect_format("test.json") == "json" + + def test_detect_yaml(self): + assert detect_format("test.yaml") == "yaml" + assert detect_format("test.yml") == "yaml" + + def test_detect_toml(self): + assert detect_format("test.toml") == "toml" + + def test_detect_unsupported(self): + with pytest.raises(ValueError): + detect_format("test.txt") + + def test_detect_case_insensitive(self): + assert detect_format("test.JSON") == "json" + assert detect_format("test.YAML") == "yaml" + + +class TestDetectFormatFromContent: + """Tests for content-based format detection.""" + + def test_detect_json_object(self): + assert detect_format_from_content('{"name": "test"}') == "json" + + def test_detect_json_array(self): + assert detect_format_from_content('[1, 2, 3]') == "json" + + def test_detect_toml(self): + content = "key = 'value'\nname = 'test'" + assert detect_format_from_content(content) == "toml" + + def test_detect_yaml(self): + content = "key: value\nname: test" + assert detect_format_from_content(content) == "yaml" + + +class TestLoadData: + """Tests for loading data from files.""" + + def test_load_json_file(self): + data = load_data(os.path.join(FIXTURES_DIR, "sample.json")) + assert data["name"] == "test-project" + assert data["version"] == "1.0.0" + + def test_load_yaml_file(self): + data = load_data(os.path.join(FIXTURES_DIR, "sample.yaml")) + assert data["name"] == "test-project" + assert data["version"] == "1.0.0" + + def test_load_toml_file(self): + data = load_data(os.path.join(FIXTURES_DIR, "sample.toml")) + assert data["name"] == "test-project" + assert data["version"] == "1.0.0" + + def test_load_json_string(self): + data = load_data('{"name": "test"}', format="json") + assert data["name"] == "test" + + def test_load_yaml_string(self): + data = load_data("name: test\nvalue: 42", format="yaml") + assert data["name"] == "test" + assert data["value"] == 42 + + +class TestParseContent: + """Tests for parsing content strings.""" + + def test_parse_json(self): + data = parse_content('{"name": "test"}', "json") + assert data["name"] == "test" + + def test_parse_yaml(self): + data = parse_content("name: test\nvalue: 42", "yaml") + assert data["name"] == "test" + assert data["value"] == 42 + + def test_parse_invalid_json(self): + with pytest.raises(json.JSONDecodeError): + parse_content("{invalid}", "json") + + def test_parse_invalid_yaml(self): + with pytest.raises(yaml.YAMLError): + parse_content("invalid: yaml: content:", "yaml") + + +class TestDumpData: + """Tests for dumping data to strings.""" + + def test_dump_json(self): + data = {"name": "test", "value": 42} + result = dump_data(data, "json") + parsed = json.loads(result) + assert parsed["name"] == "test" + assert parsed["value"] == 42 + + def test_dump_yaml(self): + data = {"name": "test", "value": 42} + result = dump_data(data, "yaml") + parsed = yaml.safe_load(result) + assert parsed["name"] == "test" + assert parsed["value"] == 42 + + def test_dump_compact_json(self): + data = {"name": "test"} + result = dump_data(data, "json", indent=None) + assert "\n" not in result + + def test_dump_to_file(self): + data = {"name": "test"} + with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f: + output_path = f.name + try: + dump_data(data, "json", output_path) + with open(output_path, "r") as f: + content = f.read() + parsed = json.loads(content) + assert parsed["name"] == "test" + finally: + os.unlink(output_path) + + +class TestSupportedFormats: + """Tests for supported formats constant.""" + + def test_supported_formats_contains_json(self): + assert "json" in SUPPORTED_FORMATS + + def test_supported_formats_contains_yaml(self): + assert "yaml" in SUPPORTED_FORMATS + + def test_supported_formats_contains_toml(self): + assert "toml" in SUPPORTED_FORMATS