BL / tests /test_schema_validation.py
youssefboutaleb's picture
Clean up dead code and add client CRM integration architecture guide
4124165
Raw History Blame Contribute Delete
1.99 kB
from __future__ import annotations
import json
from pathlib import Path
import pytest
from bl_ocr.domain.schema_validation import (
SchemaError,
build_validator,
schema_errors,
)
PROJECT_ROOT = Path(__file__).resolve().parents[1]
def _schema() -> dict:
return json.loads((PROJECT_ROOT / "schema.json").read_text(encoding="utf-8"))
def _example() -> dict:
return json.loads((PROJECT_ROOT / "example.json").read_text(encoding="utf-8"))
def test_valid_example_has_no_errors():
validator = build_validator(_schema())
assert schema_errors(_example(), validator) == []
def test_extra_key_is_rejected():
annotation = _example()
annotation["products"][0]["_repaired"] = "note" # provenance must never appear inside
errors = schema_errors(annotation, _schema())
assert any(e.validator == "additionalProperties" for e in errors)
def test_quantity_above_bound_is_rejected():
annotation = _example()
annotation["products"][0]["quantity"]["value"] = 2000
errors = schema_errors(annotation, _schema())
assert any(e.validator == "maximum" for e in errors)
def test_null_value_is_accepted():
annotation = _example()
annotation["products"][0]["expiry_date"]["value"] = None
assert schema_errors(annotation, _schema()) == []
def test_missing_required_product_field_is_rejected():
annotation = _example()
del annotation["products"][0]["pharmacist_price_ttc"]
errors = schema_errors(annotation, _schema())
assert any(e.validator == "required" for e in errors)
def test_errors_are_structured_and_limited():
annotation = _example()
annotation["products"][0]["quantity"]["value"] = "not-a-number"
errors = schema_errors(annotation, _schema(), limit=5)
assert len(errors) <= 5
assert all({"path", "message", "validator"} == set(e.as_dict()) for e in errors)
def test_invalid_schema_raises():
with pytest.raises(SchemaError):
build_validator({"type": "not-a-real-type"})