async def test_resource(): info = fondat.openapi.Info(title="title", version="version") root = Root() resource = openapi_resource(resource=root, info=info) result = await resource.get() validate(result, fondat.openapi.OpenAPI) assert generate_openapi(resource=root, info=info) == result
def test_generic_range(): Range = Annotated[list[Optional[T]], MinLen(2), MaxLen(2)] IntRange = Range[int] validate([1, 2], IntRange) validate([None, 2], IntRange) validate([1, None], IntRange) with pytest.raises(ValidationError): validate(["1", 2], IntRange) with pytest.raises(ValidationError): validate([1, 2, 3], IntRange)
def test_literal_bool_int(): l = Literal[2, 3, True] validate(2, l) validate(3, l) validate(True, l) with pytest.raises(ValidationError): validate(1, l)
async def test_nested_containers(): @resource class R1: @operation async def get(self) -> str: return "str" c1 = container_resource({"r1": R1()}) c2 = container_resource({"c1": c1}) info = fondat.openapi.Info(title="title", version="version") doc = generate_openapi(resource=c2, info=info) validate(doc, fondat.openapi.OpenAPI) c1_r1 = doc.paths.get("/c1/r1") assert c1_r1 is not None assert c1_r1.get is not None js = get_codec(JSON, fondat.openapi.OpenAPI).encode(doc)
def test_float_min_success(): validate(1.1, Annotated[float, MinValue(1.0)])
def test_float_type_success(): validate(123.45, float)
def test_int_max_error(): with pytest.raises(ValidationError): validate(5, Annotated[int, MaxValue(4)])
def test_int_minerror(): with pytest.raises(ValidationError): validate(1, Annotated[int, MinValue(2)])
def test_int_type_error(): with pytest.raises(ValidationError): validate(123.45, int)
def test_typeddict_optional(): TD = TypedDict("TD", {"a": Optional[str]}) validate(dict(a=None), TD)
def test_literal_int_float(): l = Literal[1, 2, 3] with pytest.raises(ValidationError): validate(1.0, l)
def test_literal_int_bool(): l = Literal[1, 2, 3] with pytest.raises(ValidationError): validate(True, l)
def test_literal_not_match(): l = Literal["a", "b", "c"] with pytest.raises(ValidationError): validate("d", l)
def test_literal_match(): l = Literal["a", "b", "c"] validate("a", l) validate("b", l) validate("c", l)
def test_str_max_length_error(): with pytest.raises(ValidationError): validate("1234567", Annotated[str, MaxLen(6)])
def test_typeddict_total_false(): class TD(TypedDict, total=False): l: str validate(dict(), TD)
def test_str_pattern_error(): with pytest.raises(ValidationError): validate("ghi", Annotated[str, Pattern(r"^def$")])
def test_str_pattern_success(): validate("abc", Annotated[str, Pattern(r"^abc$")])
def test_int_type_success(): validate(123, int)
def test_dataclass_success(): DC = make_dataclass("DC", [("a", str)]) validate(DC(a="b"), DC)
def test_int_min_success(): validate(2, Annotated[int, MinValue(1)])
def test_dataclass_error(): DC = make_dataclass("DC", [("c", int)]) with pytest.raises(ValidationError): validate(DC(c="str"), DC)
def test_int_max_success(): validate(2, Annotated[int, MaxValue(3)])
def test_typeddict_success(): TD = TypedDict("TD", a=str) validate(dict(a="b"), TD)
def test_int_reject_bool(): with pytest.raises(ValidationError): validate(True, int)
def test_typeddict_error(): TD = TypedDict("TD", c=int) with pytest.raises(ValidationError): validate(dict(c="str"), TD)
def test_float_type_error(): with pytest.raises(ValidationError): validate("123.45", float)
def test_typeddict_total_success(): TD = TypedDict("TD", e=float) validate(dict(e=1.2), TD)
async def _validate(self, value: table.schema): """Validate value; raise ValidationError if invalid.""" validate(value, table.schema)
def test_typeddict_total_error(): TD = TypedDict("TD", f=str) with pytest.raises(ValidationError): validate(dict(), TD)