def test_bad_top_type(): types = { "articles": { "title": Type(str), }, "people": { "firstName": Type(str), } } response = { "data": { "type": "articles", "id": "1", "attributes": { "title": "JSON:API paints my bikeshed!" }, }, } validator = Validator(top="people", types=types) with pytest.raises(ValidationError): validator.validate(response) validator = Validator(top=["people"], types=types) with pytest.raises(ValidationError): validator.validate(response) validator = Validator(top=["articles"], types=types) with pytest.raises(ValidationError): validator.validate(response) validator = Validator(top="articles", types=types) validator.validate(response) response2 = { "data": [{ "type": "articles", "id": "1", "attributes": { "title": "JSON:API paints my bikeshed!" }, }], } validator = Validator(top="articles", types=types) with pytest.raises(ValidationError): validator.validate(response2) validator = Validator(top=["people"], types=types) with pytest.raises(ValidationError): validator.validate(response2)
def test_include_null_field(): types = { "articles": { "author": Rel("people"), }, "people": { "foo": Type(str), }, } include = { "author": {}, } response = { "data": { "type": "articles", "id": "1", "relationships": { "author": { "links": "foobar", "data": None }, }, } } validator = Validator("articles", types, include=include) msg = validator.validate(deepcopy(response)) assert msg["data"]["author"]["data"] is None
def test_include_field_without_data(): types = { "articles": { "author": Rel("people"), }, "people": { "foo": Type(str), }, } include = { "author": {}, } response = { "data": { "type": "articles", "id": "1", "relationships": { "author": { "links": "foobar" }, }, } } validator = Validator("articles", types) validator.validate(deepcopy(response)) validator = Validator("articles", types, include=include) with pytest.raises(ValidationError): validator.validate(deepcopy(response))
def test_bad_field_type(): types = { "articles": { "title": Type(str), }, } response1 = { "data": { "type": "articles", "id": "1", "attributes": { "title": ["Hello", "world"] }, }, } validator = Validator(top="articles", types=types) with pytest.raises(ValidationError): validator.validate(response1) response2 = { "data": { "type": "articles", "id": "1", "attributes": { "title": None }, }, } validator = Validator(top="articles", types=types) with pytest.raises(ValidationError): validator.validate(response2)
def test_fields_args(): types = { "articles": { "title": Type(str), "comments": Rel(["comments"]) }, "comments": { "foo": Type(str), "bar": Type(str), } } fields = {"articles": ["comments"], "comments": ["foo", "bar"]} validator = Validator(top="foo", types=types, fields=fields) attrs = validator.fields_args() assert set(attrs) == { "fields[articles]=comments", "fields[comments]=foo,bar" }
def test_missing_fields(): types = { "articles": { "title": Type(str), }, } response1 = { "data": { "type": "articles", "id": "1", "attributes": {}, }, } validator = Validator(top="articles", types=types) with pytest.raises(ValidationError): validator.validate(response1) response2 = { "data": { "type": "articles", "id": "1", }, } validator = Validator(top="articles", types=types) with pytest.raises(ValidationError): validator.validate(response2) types_rel = {"articles": {"comments": Rel("comments")}, "comments": {}} response1_rel = { "data": { "type": "articles", "id": "1", }, } validator = Validator(top="articles", types=types_rel) with pytest.raises(ValidationError): validator.validate(response1_rel) response2_rel = { "data": { "type": "articles", "id": "1", "relationships": { "things": { "data": { "type": "comments", "id": "1" } } } }, } validator = Validator(top="articles", types=types_rel) with pytest.raises(ValidationError): validator.validate(response2_rel)
def test_fields_missing_field(): types = { "articles": { "title": Type(str), "body": Type(str), }, } response = { "data": { "type": "articles", "id": "1", "attributes": { "body": "JSON:API paints my bikeshed!" }, }, } fields = {"articles": ["title"]} validator = Validator(top="articles", types=types, fields=fields) with pytest.raises(ValidationError): validator.validate(response)
def test_missing_type(): types = { "articles": { "title": Type(str), }, } response = { "data": { "type": "articles", "id": "1", "attributes": { "title": "JSON:API paints my bikeshed!" }, }, "included": [{ "type": "things", "id": "1", }] } validator = Validator(top="articles", types=types) with pytest.raises(ValidationError): validator.validate(response) other_types = {"things": {}} validator = Validator(top="articles", types=other_types) with pytest.raises(ValidationError): validator.validate(response) full_types = { "articles": { "title": Type(str), }, "things": {} } validator = Validator(top="articles", types=full_types) validator.validate(response)
def test_rel_fields(): types = { "articles": { "title": Type(str), "comments": Rel(["comments"]) }, "comments": { "foo": Type(str), "bar": Type(str), } } response = { "data": { "type": "articles", "id": "1", "relationships": { "comments": { "data": [{ "id": "1", "type": "comments", }] } }, }, "included": [{ "type": "comments", "id": "1", "attributes": { "foo": "baz" } }] } fields = {"articles": ["comments"], "comments": ["foo"]} validator = Validator(top="articles", types=types, fields=fields) res = validator.validate(response) assert res["data"]["comments"]["data"][0]["foo"] == "baz"
def test_fields_work(): types = { "articles": { "title": Type(str), "body": Type(str), }, } response = { "data": { "type": "articles", "id": "1", "attributes": { "title": "JSON:API paints my bikeshed!" }, }, } fields = {"articles": ["title"]} validator = Validator(top="articles", types=types, fields=fields) res = validator.validate(response) assert "title" in res["data"]
def test_missing_includes(): types = { "articles": { "author": Rel("people"), "comments": Rel(["comments"]) }, "people": { "foo": Type(str), }, "comments": { "foo": Type(str), } } include = { "author": {}, "comments": {}, } response_data = { "type": "articles", "id": "1", "relationships": { "author": { "data": { "id": "1", "type": "people", } }, "comments": { "data": [{ "id": "1", "type": "comments", }] } }, } response_1 = { "data": response_data, "included": [{ "id": "1", "type": "comments", "attributes": { "foo": "bar" } }] } response_2 = { "data": response_data, "included": [{ "id": "1", "type": "people", "attributes": { "foo": "bar" } }] } response_3 = { "data": response_data, "included": [ { "id": "1", "type": "people", "attributes": { "foo": "bar" } }, { "id": "1", "type": "comments", "attributes": { "foo": "bar" } } ] } validator = Validator("articles", types, include=include) with pytest.raises(ValidationError): validator.validate(deepcopy(response_1)) with pytest.raises(ValidationError): validator.validate(deepcopy(response_2)) validator.validate(deepcopy(response_3))
from copy import deepcopy from qdjarv import Validator, Type, Rel types = { "articles": { "title": Type(str), "author": Rel("people"), "comments": Rel(["comments"]), }, "people": { "firstName": Type(str), "lastName": Type(str), "twitter": Type(str), }, "comments": { "body": Type(str), "author": Rel("people") } } include = { "author": {}, "comments": {}, } response = { "links": { "self": "http://example.com/articles", "next": "http://example.com/articles?page[offset]=2", "last": "http://example.com/articles?page[offset]=10" },
def do(elem): if elem is None: return elem return Type(elem)