diff --git a/tests/unit/test_core.py b/tests/unit/test_core.py new file mode 100644 index 0000000..16118e3 --- /dev/null +++ b/tests/unit/test_core.py @@ -0,0 +1,188 @@ +"""Unit tests for the validation engine.""" + +import pytest + +from envschema.schema import Schema, EnvVar, EnvVarType +from envschema.core import ValidationEngine, ValidationResult + + +class TestValidationResult: + """Tests for ValidationResult.""" + + def test_valid_result(self): + result = ValidationResult(is_valid=True) + assert result.is_valid is True + assert result.missing_required == [] + assert result.type_errors == [] + assert result.pattern_errors == [] + assert result.warnings == [] + + def test_result_to_dict(self): + result = ValidationResult(is_valid=True) + d = result.to_dict() + assert d["is_valid"] is True + assert d["missing_required"] == [] + + +class TestValidationEngine: + """Tests for ValidationEngine.""" + + def test_validate_empty_env(self): + schema = Schema(envvars=[]) + engine = ValidationEngine(schema) + result = engine.validate({}) + assert result.is_valid is True + + def test_validate_missing_required(self): + schema = Schema( + envvars=[ + EnvVar(name="REQUIRED_VAR", required=True), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({}) + assert result.is_valid is False + assert "REQUIRED_VAR" in result.missing_required + + def test_validate_present_required(self): + schema = Schema( + envvars=[ + EnvVar(name="REQUIRED_VAR", required=True), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({"REQUIRED_VAR": "value"}) + assert result.is_valid is True + + def test_validate_optional_missing(self): + schema = Schema( + envvars=[ + EnvVar(name="OPTIONAL_VAR", required=False), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({}) + assert result.is_valid is True + + def test_validate_with_default(self): + schema = Schema( + envvars=[ + EnvVar(name="VAR_WITH_DEFAULT", required=False, default="default_value"), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({}) + assert result.is_valid is True + + def test_validate_string_type(self): + schema = Schema( + envvars=[ + EnvVar(name="STRING_VAR", type=EnvVarType.STRING), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({"STRING_VAR": "any value"}) + assert result.is_valid is True + + def test_validate_integer_type_valid(self): + schema = Schema( + envvars=[ + EnvVar(name="INT_VAR", type=EnvVarType.INTEGER), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({"INT_VAR": "42"}) + assert result.is_valid is True + + def test_validate_integer_type_invalid(self): + schema = Schema( + envvars=[ + EnvVar(name="INT_VAR", type=EnvVarType.INTEGER), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({"INT_VAR": "not_a_number"}) + assert result.is_valid is False + assert len(result.type_errors) == 1 + assert result.type_errors[0].var_name == "INT_VAR" + + def test_validate_boolean_type_valid(self): + schema = Schema( + envvars=[ + EnvVar(name="BOOL_VAR", type=EnvVarType.BOOLEAN), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({"BOOL_VAR": "true"}) + assert result.is_valid is True + + def test_validate_boolean_type_invalid(self): + schema = Schema( + envvars=[ + EnvVar(name="BOOL_VAR", type=EnvVarType.BOOLEAN), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({"BOOL_VAR": "maybe"}) + assert result.is_valid is False + + def test_validate_list_type_valid(self): + schema = Schema( + envvars=[ + EnvVar(name="LIST_VAR", type=EnvVarType.LIST), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({"LIST_VAR": "a,b,c"}) + assert result.is_valid is True + + def test_validate_list_type_invalid(self): + schema = Schema( + envvars=[ + EnvVar(name="LIST_VAR", type=EnvVarType.LIST), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({"LIST_VAR": "single_value"}) + assert result.is_valid is False + + def test_validate_pattern_match(self): + schema = Schema( + envvars=[ + EnvVar(name="PATTERN_VAR", type=EnvVarType.STRING, pattern=r"^[A-Z]+$"), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({"PATTERN_VAR": "VALID"}) + assert result.is_valid is True + + def test_validate_pattern_no_match(self): + schema = Schema( + envvars=[ + EnvVar(name="PATTERN_VAR", type=EnvVarType.STRING, pattern=r"^[A-Z]+$"), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({"PATTERN_VAR": "invalid"}) + assert result.is_valid is False + + def test_validate_extra_var_warning(self): + schema = Schema( + envvars=[ + EnvVar(name="KNOWN_VAR", type=EnvVarType.STRING), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({"KNOWN_VAR": "value", "UNKNOWN_VAR": "other"}) + assert result.is_valid is True + assert "Unknown environment variable: UNKNOWN_VAR" in result.warnings + + def test_validate_case_insensitive(self): + schema = Schema( + envvars=[ + EnvVar(name="TEST_VAR", required=True), + ] + ) + engine = ValidationEngine(schema) + result = engine.validate({"test_var": "value"}) + assert result.is_valid is True \ No newline at end of file