import pytest from src.core.validator import Validator, ValidationError from src.models.request import RequestValidation class TestValidator: def test_validate_no_rules(self): validator = Validator(None) valid, errors = validator.validate(body={"name": "test"}) assert valid assert len(errors) == 0 def test_validate_required_field_missing(self): rules = RequestValidation( body={ "type": "object", "required": ["name", "email"], "properties": {} } ) validator = Validator(rules) valid, errors = validator.validate(body={"name": "test"}) assert not valid assert len(errors) == 1 assert errors[0].field == "email" assert errors[0].location == "body" def test_validate_type_mismatch(self): rules = RequestValidation( body={ "type": "object", "properties": { "age": {"type": "integer"} } } ) validator = Validator(rules) valid, errors = validator.validate(body={"age": "not-a-number"}) assert not valid assert len(errors) >= 1 def test_validate_min_length(self): rules = RequestValidation( body={ "type": "object", "properties": { "username": {"type": "string", "minLength": 3} } } ) validator = Validator(rules) valid, errors = validator.validate(body={"username": "ab"}) assert not valid assert any(e.field == "username" for e in errors) def test_validate_max_length(self): rules = RequestValidation( body={ "type": "object", "properties": { "code": {"type": "string", "maxLength": 5} } } ) validator = Validator(rules) valid, errors = validator.validate(body={"code": "abcdef"}) assert not valid assert any(e.field == "code" for e in errors) def test_validate_minimum(self): rules = RequestValidation( body={ "type": "object", "properties": { "quantity": {"type": "integer", "minimum": 1} } } ) validator = Validator(rules) valid, errors = validator.validate(body={"quantity": 0}) assert not valid assert any(e.field == "quantity" for e in errors) def test_validate_maximum(self): rules = RequestValidation( body={ "type": "object", "properties": { "rating": {"type": "integer", "maximum": 5} } } ) validator = Validator(rules) valid, errors = validator.validate(body={"rating": 10}) assert not valid assert any(e.field == "rating" for e in errors) def test_validate_email_format(self): rules = RequestValidation( body={ "type": "object", "properties": { "email": {"type": "string", "format": "email"} } } ) validator = Validator(rules) valid, errors = validator.validate(body={"email": "invalid-email"}) assert not valid assert any(e.field == "email" for e in errors) def test_validate_valid_email(self): rules = RequestValidation( body={ "type": "object", "properties": { "email": {"type": "string", "format": "email"} } } ) validator = Validator(rules) valid, errors = validator.validate(body={"email": "test@example.com"}) assert valid def test_validate_query_params(self): rules = RequestValidation( query={ "type": "object", "properties": { "page": {"type": "integer", "minimum": 1} } } ) validator = Validator(rules) valid, errors = validator.validate(query={"page": 0}) assert not valid def test_validate_headers(self): rules = RequestValidation( headers={ "type": "object", "properties": { "Authorization": {"type": "string"} } } ) validator = Validator(rules) valid, errors = validator.validate(headers={"Authorization": "Bearer token"}) assert valid def test_format_errors(self): errors = [ ValidationError("email", "Field is required", "body"), ValidationError("name", "Field is required", "body") ] validator = Validator() formatted = validator.format_errors(errors) assert formatted["valid"] is False assert formatted["error_count"] == 2 assert len(formatted["errors"]) == 2 def test_validate_nested_object(self): rules = RequestValidation( body={ "type": "object", "required": ["user", "data"], "properties": { "user": {"type": "object"}, "data": {"type": "object"} } } ) validator = Validator(rules) valid, errors = validator.validate(body={"user": {}}) assert not valid assert any(e.field == "data" for e in errors)