diff --git a/tests/unit/test_formatters.py b/tests/unit/test_formatters.py new file mode 100644 index 0000000..ef183a7 --- /dev/null +++ b/tests/unit/test_formatters.py @@ -0,0 +1,225 @@ +"""Unit tests for format handlers.""" + +import json +import os +import tempfile + +import pytest + +from configforge.formatters import ( + JSONHandler, + YAMLHandler, + TOMLHandler, + ENVHandler, + TypeScriptHandler, +) + + +class TestJSONHandler: + """Tests for JSONHandler.""" + + def test_loads_valid_json(self): + """Test parsing valid JSON string.""" + content = '{"name": "test", "value": 123}' + result = JSONHandler.loads(content) + assert result == {"name": "test", "value": 123} + + def test_loads_invalid_json(self): + """Test parsing invalid JSON raises error.""" + from configforge.exceptions import ConversionError + with pytest.raises(ConversionError): + JSONHandler.loads("invalid json") + + def test_dumps_data(self): + """Test serializing data to JSON string.""" + data = {"name": "test", "value": 123} + result = JSONHandler.dumps(data, indent=2) + assert "name" in result + assert "test" in result + + def test_read_write_file(self, sample_json_config): + """Test reading and writing JSON files.""" + with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f: + filepath = f.name + + try: + JSONHandler.write(filepath, sample_json_config) + result = JSONHandler.read(filepath) + assert result == sample_json_config + finally: + os.unlink(filepath) + + +class TestYAMLHandler: + """Tests for YAMLHandler.""" + + def test_loads_valid_yaml(self): + """Test parsing valid YAML string.""" + content = "name: test\nvalue: 123\n" + result = YAMLHandler.loads(content) + assert result == {"name": "test", "value": 123} + + def test_loads_empty_yaml(self): + """Test parsing empty YAML returns empty dict.""" + result = YAMLHandler.loads("") + assert result == {} + + def test_dumps_data(self): + """Test serializing data to YAML string.""" + data = {"name": "test", "value": 123} + result = YAMLHandler.dumps(data) + assert "name" in result + assert "test" in result + + def test_read_write_file(self, sample_yaml_config): + """Test reading and writing YAML files.""" + with tempfile.NamedTemporaryFile(mode='w', suffix='.yaml', delete=False) as f: + filepath = f.name + + try: + with open(filepath, 'w') as f: + f.write(sample_yaml_config) + result = YAMLHandler.read(filepath) + assert result["database"]["name"] == "myapp" + finally: + os.unlink(filepath) + + +class TestTOMLHandler: + """Tests for TOMLHandler.""" + + def test_loads_valid_toml(self): + """Test parsing valid TOML string.""" + content = 'name = "test"\nvalue = 123\n' + result = TOMLHandler.loads(content) + assert result["name"] == "test" + assert result["value"] == 123 + + def test_dumps_data(self): + """Test serializing data to TOML string.""" + data = {"name": "test", "value": 123} + result = TOMLHandler.dumps(data) + assert "name" in result + assert "test" in result + + def test_read_write_file(self, sample_toml_config): + """Test reading and writing TOML files.""" + with tempfile.NamedTemporaryFile(mode='w', suffix='.toml', delete=False) as f: + filepath = f.name + + try: + with open(filepath, 'w') as f: + f.write(sample_toml_config) + result = TOMLHandler.read(filepath) + assert result["database"]["name"] == "myapp" + finally: + os.unlink(filepath) + + +class TestENVHandler: + """Tests for ENVHandler.""" + + def test_loads_valid_env(self): + """Test parsing valid ENV string.""" + content = 'KEY=value\nNUMBER=123\n' + result = ENVHandler.loads(content) + assert result["KEY"] == "value" + assert result["NUMBER"] == 123 + + def test_loads_env_with_quotes(self): + """Test parsing ENV with quoted values.""" + content = 'KEY="quoted value"\n' + result = ENVHandler.loads(content) + assert result["KEY"] == "quoted value" + + def test_loads_env_with_booleans(self): + """Test parsing ENV with boolean values.""" + content = 'TRUE=true\nFALSE=false\n' + result = ENVHandler.loads(content) + assert result["TRUE"] is True + assert result["FALSE"] is False + + def test_dumps_data(self): + """Test serializing data to ENV format.""" + data = {"KEY": "value", "NUMBER": 123} + result = ENVHandler.dumps(data) + assert "KEY=value" in result + + def test_read_write_file(self, sample_env_config): + """Test reading and writing ENV files.""" + with tempfile.NamedTemporaryFile(mode='w', suffix='.env', delete=False) as f: + filepath = f.name + + try: + with open(filepath, 'w') as f: + f.write(sample_env_config) + result = ENVHandler.read(filepath) + assert result["DATABASE_HOST"] == "localhost" + finally: + os.unlink(filepath) + + +class TestTypeScriptHandler: + """Tests for TypeScriptHandler.""" + + def test_generate_from_schema_simple(self): + """Test generating TypeScript from simple schema.""" + schema = { + "type": "object", + "properties": { + "name": {"type": "string"}, + "age": {"type": "integer"} + }, + "required": ["name"] + } + result = TypeScriptHandler.generate_from_schema(schema, "User") + assert "interface User" in result + assert "name: string" in result + assert "age?: number" in result + + def test_generate_from_schema_nested(self): + """Test generating TypeScript from nested schema.""" + schema = { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "email": {"type": "string"} + }, + "required": ["name", "email"] + } + }, + "required": ["user"] + } + result = TypeScriptHandler.generate_from_schema(schema, "Config") + assert "interface Config" in result + assert "interface User" in result + + def test_generate_from_data(self): + """Test generating TypeScript from sample data.""" + data = { + "name": "test", + "value": 123, + "active": True + } + result = TypeScriptHandler.generate_from_data(data, "Config") + assert "interface Config" in result + assert "name: string" in result + assert "value: number" in result + + def test_generate_with_enum(self): + """Test generating TypeScript with enum values.""" + schema = { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": ["active", "inactive", "pending"] + } + } + } + result = TypeScriptHandler.generate_from_schema(schema, "Config") + assert "active" in result + assert "inactive" in result