Exemplo n.º 1
0
def test_integration_get_filtered_list(app, example_schema, example_model):
    class ExampleFiltersSchema(filters_schema.FilterSchema):
        basic = filters_schema.FilterField()
        listed = filters_schema.ListFilterField()
        dumb_name = filters_schema.FilterField(attribute='renamed')
        integer = filters_schema.FilterField(type_=fields.Int)
        skipped_filter = filters_schema.FilterField()

    class ExampleListView(resources.ResourceList):
        schema = example_schema
        filter_schema = ExampleFiltersSchema()

        applied_filters = {}

        def read_many(self, filters, sorting, pagination):
            self.applied_filters.update(filters)
            return []

    application_api = api.Api(app)
    application_api.route(ExampleListView, 'example_list', '/examples/')
    response = app.test_client().get(
        '/examples/?filter[basic]=text&filter[listed]=first,second&filter[dumb-name]=another&filter[integer]=3',
        headers=JSONAPI_HEADERS)
    assert response.status_code == 200
    assert ExampleListView.applied_filters == {
        'basic': 'text',
        'listed': ['first', 'second'],
        'renamed': 'another',
        'integer': 3,
    }
Exemplo n.º 2
0
def test_integration_get_filtered_list(app, example_schema, example_model):
    class ExampleListView(resources.ResourceList):
        schema = example_schema
        filter_schema = filters_schema.FilterSchema({
            'basic':
            filters_schema.FilterField(),
            'listed':
            filters_schema.ListFilterField(),
            'renamed':
            filters_schema.FilterField(field_name='dumb-name'),
            'integer':
            filters_schema.FilterField(parse_value=int),
            'skipped_filter':
            filters_schema.FilterField(),
        })

        applied_filters = []

        def read_many(self, filters):
            self.applied_filters.append(filters)
            return []

    application_api = api.Api(app)
    application_api.route(ExampleListView, 'example_list', '/examples/')
    response = app.test_client().get(
        '/examples/?filter[basic]=text&filter[listed]=first,second&filter[dumb-name]=another&filter[integer]=3',
        headers=JSONAPI_HEADERS)
    assert response.status_code == 200
    assert ExampleListView.applied_filters == [{
        'basic': 'text',
        'listed': ['first', 'second'],
        'renamed': 'another',
        'integer': 3,
    }]
Exemplo n.º 3
0
def test_creating_view_with_dynamic_schema(app, example_schema, example_model):
    class ExampleDetailView(resources.ResourceDetail):
        def read(self, id):
            return example_model(id=id, body='Gwynbelidd')

    application_api = api.Api(app)
    application_api.route(ExampleDetailView,
                          'example_detail',
                          '/examples/<id>/',
                          view_kwargs={'schema': example_schema})
    response = app.test_client().get(
        '/examples/f60717a3-7dc2-4f1a-bdf4-f2804c3127a4/',
        headers=JSONAPI_HEADERS)
    result = json.loads(response.data.decode())
    assert result == {
        'data': {
            'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
            'type': 'example',
            'attributes': {
                'body': 'Gwynbelidd'
            }
        },
        'jsonapi': {
            'version': '1.0'
        }
    }
Exemplo n.º 4
0
def test_integration_patch_with_empty_response(app, example_schema,
                                               example_model):
    class ExampleDetailView(resources.ResourceDetail):
        schema = example_schema

        def update(self, id, data):
            pass

    json_data = json.dumps({
        'data': {
            'type': 'example',
            'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
            'attributes': {
                'body': "Nice body.",
            }
        }
    })
    application_api = api.Api(app)
    application_api.route(ExampleDetailView, 'example_list', '/examples/<id>/')
    response = app.test_client().patch(
        '/examples/f60717a3-7dc2-4f1a-bdf4-f2804c3127a4/',
        headers=JSONAPI_HEADERS,
        data=json_data,
    )
    assert response.status_code == 204
    assert response.data == b''
Exemplo n.º 5
0
def test_integration_create_resource(app, example_schema, example_model):
    class ExampleListView(resources.ResourceList):
        schema = example_schema

        def create(self, *args, **kwargs):
            return example_model(id='f60717a3-7dc2-4f1a-bdf4-f2804c3127a4', body='Nice body.')

    json_data = json.dumps({
        'data': {
            'type': 'example',
            'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
            'attributes': {
                'body': "Nice body.",
            }
        }
    })
    application_api = api.Api(app)
    application_api.route(ExampleListView, 'example_list', '/examples/')
    response = app.test_client().post(
        '/examples/',
        headers=JSONAPI_HEADERS,
        data=json_data,
    )
    assert json.loads(response.data.decode()) == {
        "data": {
            "type": "example",
            "id": "f60717a3-7dc2-4f1a-bdf4-f2804c3127a4",
            "attributes": {
                "body": "Nice body."
            }
        },
        "jsonapi": {
            "version": "1.0"
        }
    }
Exemplo n.º 6
0
def test_integration_get_list_use_schema_instead_of_atomic_schema(app):
    database_simulation.clear()
    application_api = api.Api(app)
    application_api.repository(ParentResourceRepositoryViewSet(), 'parent',
                               '/parents/')
    parent = ParentModel(**{'id': 111})
    database_simulation[parent.id] = parent
    response = app.test_client().get(
        '/parents/',
        headers=JSONAPI_HEADERS,
    )
    result = json.loads(response.data.decode('utf-8'))
    expected = {
        'meta': {
            'count': 1
        },
        'data': [{
            'id': '111',
            'type': 'parent'
        }],
        'jsonapi': {
            'version': '1.0'
        }
    }
    assert expected == result
Exemplo n.º 7
0
def test_integration_get_list(app):
    application_api = api.Api(app)
    application_api.repository(ExampleResourceRepositoryViewSet(), 'example',
                               '/examples/')
    response = app.test_client().get('/examples/', headers=JSONAPI_HEADERS)
    result = json.loads(response.data.decode())
    assert result == {
        'data': [{
            'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
            'type': 'example',
            'attributes': {
                'body': 'heheh'
            }
        }, {
            'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a5',
            'type': 'example',
            'attributes': {
                'body': 'hihi'
            },
        }],
        'jsonapi': {
            'version': '1.0'
        },
        'meta': {
            'count': 2
        }
    }
Exemplo n.º 8
0
def test_integration_create_resource(app):
    application_api = api.Api(app)
    application_api.repository(ExampleResourceRepositoryViewSet(), 'example',
                               '/examples/')

    json_data = json.dumps({
        'data': {
            'type': 'example',
            'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
            'attributes': {
                'body': "Nice body.",
            }
        }
    })
    response = app.test_client().post(
        '/examples/',
        headers=JSONAPI_HEADERS,
        data=json_data,
    )
    assert json.loads(response.data.decode()) == {
        "data": {
            "type": "example",
            "id": "f60717a3-7dc2-4f1a-bdf4-f2804c3127a4",
            "attributes": {
                "body": "Nice body."
            }
        },
        "jsonapi": {
            "version": "1.0"
        }
    }
 def test_invalid_include_parameter_response(self, app):
     application_api = api.Api(app)
     application_api.repository(ParentResourceRepositoryViewSet(), 'parent',
                                '/parents/')
     response = app.test_client().get(
         '/parents/f60717a3-7dc2-4f1a-bdf4-f2804c3127a4/?include=children.children',
         headers=JSONAPI_HEADERS)
     assert response.status_code == http.HTTPStatus.BAD_REQUEST
Exemplo n.º 10
0
def test_bad_get_detail(app):
    database_simulation.clear()
    application_api = api.Api(app)
    application_api.repository(BadResourceRepositoryViewSet(), 'bad', '/bad/')
    response = app.test_client().get(
        '/bad/1/',
        headers=JSONAPI_HEADERS,
    )
    result = json.loads(response.data.decode('utf-8'))
    assert result['errors'][0]['status'] == 500
    assert result['errors'][0]['detail'] == 'Must have an `id` field'
Exemplo n.º 11
0
def test_integration_delete(app):
    application_api = api.Api(app)
    view_set = ExampleResourceRepositoryViewSet()
    application_api.repository(view_set, 'example', '/examples/')
    response = app.test_client().delete(
        '/examples/f60717a3-7dc2-4f1a-bdf4-f2804c3127a4/',
        headers=JSONAPI_HEADERS)
    assert response.status_code == 204
    assert response.data == b''
    assert view_set.repository.deleted_ids == [
        'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4'
    ]
Exemplo n.º 12
0
def test_integration_create_nested_resource(app):
    application_api = api.Api(app)
    application_api.repository(ParentResourceRepositoryViewSet(), 'parent', '/parents/')

    json_data = json.dumps({
        'data': {
            'type': 'parent',
            'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
            'relationships': {
                'descendant': {
                    'data': [
                        {
                            'type': 'descendant',
                            'attributes': {
                                'name': 'Olga',
                                '__id__': '_tem_id_3344'
                            },
                            'id': 'f60717a3-7dc2-0000-0000-f2804c3127a4'
                        }
                    ]
                }
            }
        }
    })
    response = app.test_client().post(
        '/parents/',
        headers=JSONAPI_HEADERS,
        data=json_data,
    )
    result = json.loads(response.data.decode('utf-8'))
    expected = {
        "data": {
            "id": "f60717a3-7dc2-4f1a-bdf4-f2804c3127a4",
            "type": "parent",
            "relationships": {
                "descendant": {
                    "data":
                        [
                            {
                                "id": "f60717a3-7dc2-0000-0000-f2804c3127a4",
                                "type": "descendant",
                                "attributes": {
                                    "__id__": "_tem_id_3344",
                                    "name": "Olga"
                                }
                            }
                        ]
                }
            }
        },
        "jsonapi": {"version": "1.0"}
    }
    assert expected == result
Exemplo n.º 13
0
def test_integration_get_list_with_pagination(app, example_schema, example_model):
    class ExampleListView(resources.ResourceList):
        schema = example_schema

        def read_many(self, filters, pagination):
            return [
                example_model(id='f60717a3-7dc2-4f1a-bdf4-f2804c3127a4', body='heheh'),
                example_model(id='f60717a3-7dc2-4f1a-bdf4-f2804c3127a5', body='hihi'),
            ]

        def get_count(self, filters):
            return 5

    application_api = api.Api(app)
    application_api.route(ExampleListView, 'example_list', '/examples/')
    response = app.test_client().get(
        '/examples/?page[size]=2&page[number]=1',
        headers=JSONAPI_HEADERS
    )
    result = json.loads(response.data.decode())
    assert response.status_code == 200
    assert result == {
        'data': [
            {
                'type': 'example',
                'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
                'attributes': {
                    'body': 'heheh'
                }
            },
            {
                'type': 'example',
                'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a5',
                'attributes': {
                    'body': 'hihi'
                }
            }
        ],
        'links': {
            'self': 'http://localhost/examples/?page[size]=2&page[number]=1',
            'first': 'http://localhost/examples/?page[size]=2&page[number]=1',
            'previous': None,
            'next': 'http://localhost/examples/?page[size]=2&page[number]=2',
            'last': 'http://localhost/examples/?page[size]=2&page[number]=3'
        },
        'meta': {
            'count': 2
        },
        'jsonapi': {
            'version': '1.0'
        }
    }
Exemplo n.º 14
0
 def test_get_parent_detail_with_include_data(self, app):
     application_api = api.Api(app)
     application_api.repository(ParentResourceRepositoryViewSet(), 'parent', '/parents/')
     response = app.test_client().get(
         '/parents/f60717a3-7dc2-4f1a-bdf4-f2804c3127a4/?include=children',
         headers=JSONAPI_HEADERS
     )
     result = json.loads(response.data.decode('utf-8'))
     result['included'].sort(key=lambda x: x['attributes']['name'])
     expected = {
        'data': {
           'attributes': {
              'name': 'Adam'
           },
           'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
           'relationships': {
              'children': {
                 'data': [
                    {
                       'id': mock.ANY,
                       'type': 'childs'
                    },
                    {
                       'id': mock.ANY,
                       'type': 'childs'
                    }
                 ]
              }
           },
           'type': 'parents'
        },
        'included': [
            {
                'attributes': {
                    'name': 'Abel'
                },
                'id': mock.ANY,
                'type': 'childs'
            },
            {
                'attributes': {
                    'name': 'Cain'
                },
                'id': mock.ANY,
                'type': 'childs'
            },
        ],
        'jsonapi': {
           'version': '1.0'
        }
     }
     assert expected == result
Exemplo n.º 15
0
def test_bad_data_get_detail(app):
    database_simulation.clear()
    application_api = api.Api(app)
    application_api.repository(BadDataResourceRepositoryViewSet(), 'bad',
                               '/bad/')
    model = BadDataModel(**{'id': 111, 'number': 1})
    database_simulation[model.id] = model
    response = app.test_client().get(
        '/bad/111/',
        headers=JSONAPI_HEADERS,
    )
    result = json.loads(response.data.decode('utf-8'))
    assert result['errors'][0]['status'] == 500
    assert result['errors'][0][
        'detail'] == "'int' object has no attribute 'isoformat'"
Exemplo n.º 16
0
def test_sorting(app, example_schema):
    class ExampleRepository(repositories.ResourceRepository):
        pass

    class ExampleListView(resource_repository_views.ResourceRepositoryViewSet):
        schema = example_schema
        repository = ExampleRepository

    api.Api(app).repository(ExampleListView(), 'example', '/examples/')
    get_list_mock = mock.MagicMock()
    with mock.patch(
            'flask_jsonapi.resource_repositories.repositories.ResourceRepository.get_list',
            get_list_mock):
        app.test_client().get('/examples/?sort=body', headers=JSONAPI_HEADERS)
    get_list_mock.assert_called_once_with({}, ('body', ), {})
Exemplo n.º 17
0
def test_integration_get_nested_resource(app):
    database_simulation.clear()
    application_api = api.Api(app)
    application_api.repository(ParentResourceRepositoryViewSet(), 'parent', '/parents/')

    response = app.test_client().get(
        '/parents/',
        headers=JSONAPI_HEADERS,
    )
    result = json.loads(response.data.decode('utf-8'))
    expected = {
        "data": [],
        "meta": {"count": 0},
        "jsonapi": {"version": "1.0"},
    }
    assert expected == result
Exemplo n.º 18
0
def test_bad_data_get_detail(app):
    database_simulation.clear()
    application_api = api.Api(app)
    application_api.repository(BadDataResourceRepositoryViewSet(), 'bad',
                               '/bad/')
    model = BadDataModel(**{'id': 111, 'number': 1})
    database_simulation[model.id] = model
    response = app.test_client().get(
        '/bad/111/',
        headers=JSONAPI_HEADERS,
    )
    result = json.loads(response.data.decode('utf-8'))
    assert result['errors'][0]['status'] == 500
    assert result['errors'][0]['detail'] == 'marshmallow.ValidationError'
    assert result['errors'][0]['source'] == {
        'number': ['"1" cannot be formatted as a datetime.']
    }
Exemplo n.º 19
0
def test_integration_delete(app, example_schema, example_model):

    class ExampleDetailView(resources.ResourceDetail):
        schema = example_schema
        deleted_ids = []

        def destroy(self, id):
            self.deleted_ids.append(id)

    application_api = api.Api(app)
    application_api.route(ExampleDetailView, 'example_detail', '/examples/<id>/')
    response = app.test_client().delete(
        '/examples/f60717a3-7dc2-4f1a-bdf4-f2804c3127a4/',
        headers=JSONAPI_HEADERS
    )
    assert response.status_code == 204
    assert response.data == b''
    assert ExampleDetailView.deleted_ids == ['f60717a3-7dc2-4f1a-bdf4-f2804c3127a4']
Exemplo n.º 20
0
def test_integration_create_resource_invalid_input(app, example_schema, example_model):
    class TestSchema(marshmallow_jsonapi.Schema):
        id = fields.UUID()
        f1 = fields.Str(required=True)
        f2 = fields.Str(required=True)

        class Meta:
            type_ = 'test'
            strict = True

    class ExampleListView(resources.ResourceList):
        schema = TestSchema

        def create(self, *args, **kwargs):
            return example_model(id='f60717a3-7dc2-4f1a-bdf4-f2804c3127a4', body='Nice body.')

    json_data = json.dumps({
        'data': {
            'type': 'test',
        }
    })
    application_api = api.Api(app)
    application_api.route(ExampleListView, 'example_list', '/examples/')
    response = app.test_client().post(
        '/examples/',
        headers=JSONAPI_HEADERS,
        data=json_data,
    )
    result = json.loads(response.data.decode())
    assert result == {
        'errors': mock.ANY,
        "jsonapi": {
            "version": "1.0"
        }
    }
    assert list(sorted(result['errors'], key=lambda x: x['source']['pointer'])) == [
        {
            'detail': 'Missing data for required field.',
            'source': {'pointer': '/data/attributes/f1'}
        }, {
            'detail': 'Missing data for required field.',
            'source': {'pointer': '/data/attributes/f2'}
        }
    ]
Exemplo n.º 21
0
def test_integration_bad_content_type_header(app, example_schema, example_model):
    class ExampleListView(resources.ResourceList):
        schema = example_schema

    application_api = api.Api(app)
    application_api.route(ExampleListView, 'example_list', '/examples/')
    response = app.test_client().post('/examples/', headers={'accept': 'application/vnd.api+json'})
    assert response.status_code == 415
    assert json.loads(response.data.decode()) == {
        'errors': [{
            'detail': 'Content-Type header must be application/vnd.api+json',
            'source': '',
            'status': 415,
            'title': 'InvalidRequestHeader'
        }],
        'jsonapi': {
            'version': '1.0'
        },
    }
Exemplo n.º 22
0
def test_integration_selective_decorator_not_decorated_method(app):
    application_api = api.Api(app)
    application_api.repository(ExampleDecoratedResourceRepositoryViewSet(),
                               'example', '/examples/')
    response = app.test_client().get(
        '/examples/f60717a3-7dc2-4f1a-bdf4-f2804c3127a4/',
        headers=JSONAPI_HEADERS)
    result = json.loads(response.data.decode())
    assert result == {
        'data': {
            'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
            'type': 'example',
            'attributes': {
                'body': 'Gwynbelidd'
            }
        },
        'jsonapi': {
            'version': '1.0'
        }
    }
Exemplo n.º 23
0
def test_create_with_missing_data(app):
    application_api = api.Api(app)
    application_api.repository(TomatoRepositoryViewSet(), 'tomatoes',
                               '/tomatoes/')

    json_data = json.dumps({
        'data': {
            'type': 'tomato',
            'id': '61042c6f-0c83-4c26-aa74-2cfbd025879a',
        }
    })
    response = app.test_client().post(
        '/tomatoes/',
        headers=JSONAPI_HEADERS,
        data=json_data,
    )
    result = json.loads(response.data.decode('utf-8'))
    errors = result['errors']
    assert errors[0]['detail'] in 'Missing data for required field.'
    assert errors[0]['source'] == {'pointer': '/data/attributes/name'}
Exemplo n.º 24
0
def test_integration_get_list(app, example_schema, example_model):
    class ExampleListView(resources.ResourceList):
        schema = example_schema

        def read_many(self, filters, pagination):
            return [
                example_model(id='f60717a3-7dc2-4f1a-bdf4-f2804c3127a4', body='heheh'),
                example_model(id='f60717a3-7dc2-4f1a-bdf4-f2804c3127a5', body='hihi'),
            ]

    application_api = api.Api(app)
    application_api.route(ExampleListView, 'example_list', '/examples/')
    response = app.test_client().get(
        '/examples/',
        headers=JSONAPI_HEADERS
    )
    result = json.loads(response.data.decode())
    assert response.status_code == 200
    assert result == {
        'data': [
            {
                'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
                'type': 'example',
                'attributes': {
                    'body': 'heheh'
                }
            }, {
                'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a5',
                'type': 'example',
                'attributes': {
                    'body': 'hihi'
                },
            }
        ],
        'jsonapi': {
            'version': '1.0'
        },
        'meta': {
            'count': 2
        }
    }
 def test_get_parent_detail_without_include_data(self, app):
     application_api = api.Api(app)
     application_api.repository(ParentResourceRepositoryViewSet(), 'parent',
                                '/parents/')
     response = app.test_client().get(
         '/parents/f60717a3-7dc2-4f1a-bdf4-f2804c3127a4/',
         headers=JSONAPI_HEADERS)
     result = json.loads(response.data.decode())
     expected = {
         'data': {
             'type': 'parents',
             'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
             'attributes': {
                 'name': 'Adam'
             }
         },
         'jsonapi': {
             'version': '1.0'
         }
     }
     assert expected == result
Exemplo n.º 26
0
def test_integration_selective_decorator_decorated_method(app):
    application_api = api.Api(app)
    application_api.repository(ExampleDecoratedResourceRepositoryViewSet(),
                               'example', '/examples/')

    json_data = json.dumps({
        'data': {
            'type': 'example',
            'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
            'attributes': {
                'body': "Nice body.",
            }
        }
    })
    response = app.test_client().post(
        '/examples/',
        headers=JSONAPI_HEADERS,
        data=json_data,
    )
    result = response.data.decode()
    assert result == 'View decorated!'
Exemplo n.º 27
0
def test_integration_patch_with_empty_response(app, ):
    application_api = api.Api(app)
    view_set = ExampleResourceRepositoryViewSet()
    application_api.repository(view_set, 'example', '/examples/')

    json_data = json.dumps({
        'data': {
            'type': 'example',
            'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
            'attributes': {
                'body': "Nice body.",
            }
        }
    })
    response = app.test_client().patch(
        '/examples/f60717a3-7dc2-4f1a-bdf4-f2804c3127a4/',
        headers=JSONAPI_HEADERS,
        data=json_data,
    )
    assert response.status_code == 204
    assert response.data == b''
Exemplo n.º 28
0
def test_integration_pagination(app, example_schema):
    class ExampleListView(resources.ResourceList):
        schema = example_schema

        applied_pagination = {}

        def read_many(self, filters, sorting, pagination):
            self.applied_pagination.update(pagination)
            return []

        def get_count(self, filters):
            return 0

    application_api = api.Api(app)
    application_api.route(ExampleListView, 'example_list', '/examples/')
    response = app.test_client().get(
        '/examples/?page[size]=100&page[number]=50', headers=JSONAPI_HEADERS)
    assert response.status_code == 200
    assert ExampleListView.applied_pagination == {
        'size': 100,
        'number': 50,
    }
Exemplo n.º 29
0
def test_create_with_invalid_data(app):
    application_api = api.Api(app)
    application_api.repository(TomatoRepositoryViewSet(), 'tomatoes',
                               '/tomatoes/')

    json_data = json.dumps({
        'data': {
            'type': 'tomato',
            'id': 1234,
            'attributes': {
                'name': 'red',
            },
        },
    })
    response = app.test_client().post(
        '/tomatoes/',
        headers=JSONAPI_HEADERS,
        data=json_data,
    )
    result = json.loads(response.data.decode('utf-8'))
    errors = result['errors']
    assert errors[0]['detail'] in 'Not a valid string.'
    assert errors[0]['source'] == {'pointer': '/data/id'}
Exemplo n.º 30
0
def test_integration_patch(app, example_schema, example_model):

    class ExampleDetailView(resources.ResourceDetail):
        schema = example_schema

        def update(self, id, data):
            data.pop('id')
            return example_model(id=id, **data)

    json_data = json.dumps({
        'data': {
            'type': 'example',
            'id': 'f60717a3-7dc2-4f1a-bdf4-f2804c3127a4',
            'attributes': {
                'body': "Nice body.",
            }
        }
    })
    application_api = api.Api(app)
    application_api.route(ExampleDetailView, 'example_list', '/examples/<id>/')
    response = app.test_client().patch(
        '/examples/f60717a3-7dc2-4f1a-bdf4-f2804c3127a4/',
        headers=JSONAPI_HEADERS,
        data=json_data,
    )
    assert json.loads(response.data.decode()) == {
        "data": {
            "type": "example",
            "id": "f60717a3-7dc2-4f1a-bdf4-f2804c3127a4",
            "attributes": {
                "body": "Nice body."
            }
        },
        "jsonapi": {
            "version": "1.0"
        }
    }