Some checks failed
CI / test (3.10) (push) Successful in 9m38s
CI / test (3.11) (push) Successful in 9m46s
CI / test (3.12) (push) Successful in 9m37s
CI / test (3.9) (push) Successful in 9m42s
CI / lint (push) Failing after 4m44s
CI / type-check (push) Failing after 4m52s
CI / build (push) Has been skipped
Release / release (push) Failing after 4m49s
Release / release-pypi (push) Has been skipped
177 lines
5.5 KiB
Python
177 lines
5.5 KiB
Python
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)
|