def test_patch_relationship_with_unknown_relationship(self): """Patch relationship with unknown relationship returns 404. A RelationshipNotFoundError is raised. """ user = models.User( first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post( title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment( content='This is comment 1', author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) self.session.commit() payload = { 'data': {} } with self.assertRaises(errors.RelationshipNotFoundError) as error: models.serializer.patch_relationship( self.session, payload, 'posts', blog_post.id, 'unknown-relationship') self.assertEqual(error.exception.status_code, 404)
def test_delete_resource_cascade_with_one_many_relationship(self): """Delete a resource with a cascade and one-to-many relationship. Ensure all referencing models are removed. """ user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment(content='This is comment 1', author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) self.session.commit() models.serializer.delete_resource(self.session, {}, 'users', 1) post = self.session.query(models.Post).get(1) comment = self.session.query(models.Comment).get(1) self.assertEqual(post, None) self.assertEqual(comment, None)
def test_post_relationship_with_incompatible_data_model(self): """Post relationship with incompatible data model returns 409. The model type in the payload must match the relationship type. A ValidationError is raised. """ user = models.User( first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post( title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment( content='This is the first comment', author_id=user.id, author=user) self.session.add(comment) self.session.commit() payload = { 'data': [{ 'type': 'users', 'id': user.id }] } with self.assertRaises(errors.ValidationError) as error: models.serializer.post_relationship( self.session, payload, 'posts', blog_post.id, 'comments') expected_detail = 'Incompatible type provided' self.assertEqual(error.exception.detail, expected_detail) self.assertEqual(error.exception.status_code, 409)
def test_patch_relationship_on_to_one_set_resource_to_null_response(self): """Patch relationship of a single resource and set to null returns 200.""" user = models.User( first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post( title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) self.session.commit() payload = { 'data': None } response = models.serializer.patch_relationship( self.session, payload, 'posts', blog_post.id, 'author') expected = { 'data': None, 'jsonapi': { 'version': '1.0' }, 'meta': { 'sqlalchemy_jsonapi_version': __version__ } } actual = response.data self.assertEqual(expected, actual) self.assertEqual(200, response.status_code)
def test_patch_relationship_on_to_many_set_to_empty_response(self): """Patch relationships on many and set to empty returns 200.""" user = models.User( first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post( title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment( content='This is comment 1', author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) self.session.commit() payload = { 'data': [] } response = models.serializer.patch_relationship( self.session, payload, 'posts', blog_post.id, 'comments') expected = { 'data': [], 'jsonapi': { 'version': '1.0' }, 'meta': { 'sqlalchemy_jsonapi_version': __version__ } } actual = response.data self.assertEqual(expected, actual) self.assertEqual(200, response.status_code)
def test_patch_relationship_on_to_one_with_empty_list(self): """Patch relationship on to one with empty list returns 409. A ValidationError is raised. """ user = models.User( first='Sally', last='Smith', password='******', username='******') self.session.add(user) new_user = models.User( first='Bob', last='Joe', password='******', username='******') self.session.add(new_user) blog_post = models.Post( title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) self.session.commit() payload = { 'data': [] } with self.assertRaises(errors.ValidationError) as error: models.serializer.patch_relationship( self.session, payload, 'posts', blog_post.id, 'author') expected_detail = 'Provided data must be a hash.' self.assertEqual(error.exception.detail, expected_detail) self.assertEqual(error.exception.status_code, 409)
def test_post_relationship_with_to_one_relationship(self): """Post relationship with to one relationship returns 409. Cannot post to a to-one relationship. A ValidationError is raised. """ user = models.User( first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post( title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment( content='This is the first comment', author_id=user.id, author=user) self.session.add(comment) self.session.commit() with self.assertRaises(errors.ValidationError) as error: models.serializer.post_relationship( self.session, {}, 'comments', comment.id, 'author') expected_detail = 'Cannot post to to-one relationship' self.assertEqual(error.exception.detail, expected_detail) self.assertEqual(error.exception.status_code, 409)
def test_patch_relationship_on_to_many_set_resources_successful(self): """Patch relationships on many and set resources is successful.""" user = models.User( first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post( title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment( content='This is comment 1', author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) new_comment = models.Comment( content='This is a new comment 2', author_id=user.id, author=user) self.session.add(new_comment) self.session.commit() payload = { 'data': [{ 'type': 'comments', 'id': new_comment.id }] } models.serializer.patch_relationship( self.session, payload, 'posts', blog_post.id, 'comments') self.assertEqual(new_comment.post.id, blog_post.id) self.assertEqual(new_comment.post, blog_post)
def test_post_relationship_with_hash_instead_of_array(self): """Post relalationship with a hash instead of an array returns 409. A ValidationError is raised. """ user = models.User( first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post( title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment( content='This is the first comment', author_id=user.id, author=user) self.session.add(comment) self.session.commit() payload = { 'data': { 'type': 'comments', 'id': comment.id } } with self.assertRaises(errors.ValidationError) as error: models.serializer.post_relationship( self.session, payload, 'posts', blog_post.id, 'comments') expected_detail = '/data must be an array' self.assertEqual(error.exception.detail, expected_detail) self.assertEqual(error.exception.status_code, 409)
def test_post_relationship_with_extra_data_keys(self): """Post relationship with data keys other than 'id' and 'type' results in 404. A BadRequestError is raised. """ user = models.User( first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post( title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment( content='This is the first comment', author_id=user.id, author=user) self.session.add(comment) self.session.commit() payload = { 'data': [{ 'type': 'comments', 'id': comment.id, 'extra-key': 'foo' }] } with self.assertRaises(errors.BadRequestError) as error: models.serializer.post_relationship( self.session, payload, 'posts', blog_post.id, 'comments') expected_detail = 'comments must have type and id keys' self.assertEqual(error.exception.detail, expected_detail) self.assertEqual(error.exception.status_code, 400)
def test_get_relationship_on_to_one(self): """Get a relationship of on to one returns 200.""" user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) self.session.commit() response = models.serializer.get_relationship(self.session, {}, 'posts', blog_post.id, 'author') expected = { 'data': { 'id': 1, 'type': 'users' }, 'jsonapi': { 'version': '1.0' }, 'meta': { 'sqlalchemy_jsonapi_version': '4.0.9' } } actual = response.data self.assertEqual(expected, actual) self.assertEqual(200, response.status_code)
def test_patch_resource_successful(self): """Patch resource is successful""" user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content') self.session.add(blog_post) self.session.commit() payload = { 'data': { 'type': 'posts', 'id': blog_post.id, 'attributes': { 'title': 'This is a new title' }, 'relationships': { 'author': { 'data': { 'type': 'users', 'id': user.id } } } } } models.serializer.patch_resource(self.session, payload, 'posts', blog_post.id) self.assertEqual(blog_post.author.id, user.id) self.assertEqual(blog_post.author, user)
def test_get_related_with_unknown_relationship(self): """Get related resource with unknown relationship returns 404. A RelationshipNotFoundError is raised. """ user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment(content='This is a comment', author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) self.session.commit() with self.assertRaises(errors.RelationshipNotFoundError) as error: models.serializer.get_related(self.session, {}, 'posts', blog_post.id, 'invalid-relationship') self.assertEqual(error.exception.status_code, 404)
def test_get_related_when_related_object_is_null(self): """Get a related object that is null returns 200.""" user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content') self.session.add(blog_post) self.session.commit() response = models.serializer.get_related(self.session, {}, 'posts', blog_post.id, 'author') expected = { 'data': None, 'jsonapi': { 'version': '1.0' }, 'meta': { 'sqlalchemy_jsonapi_version': __version__ } } actual = response.data self.assertEqual(expected, actual) self.assertEqual(200, response.status_code)
def test_get_collection_given_invalid_limit_for_pagination(self): """Get collection given invalid limit for pagination returns 400. A BadRequestError is raised. """ user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) for x in range(10): comment = models.Comment(content='This is comment {0}'.format(x + 1), author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) self.session.commit() with self.assertRaises(errors.BadRequestError) as error: models.serializer.get_collection(self.session, { 'page[offset]': u'5', 'page[limit]': u'foo' }, 'comments') expected_detail = 'Page query parameters must be integers' self.assertEqual(error.exception.detail, expected_detail) self.assertEqual(error.exception.status_code, 400)
def test_patch_relationship_on_to_one_set_to_resource_successful(self): """Patch single relationship successfully updates resource.""" user = models.User( first='Sally', last='Smith', password='******', username='******') self.session.add(user) new_user = models.User( first='Bob', last='Joe', password='******', username='******') self.session.add(new_user) blog_post = models.Post( title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) self.session.commit() payload = { 'data': { 'type': 'users', 'id': new_user.id } } models.serializer.patch_relationship( self.session, payload, 'posts', blog_post.id, 'author') self.assertEqual(blog_post.author.id, new_user.id) self.assertEqual(blog_post.author, new_user)
def test_patch_relationship_on_to_many_with_incompatible_model(self): """Patch relationship on to many with incompatible model returns 409. A ValidationError is raised. """ user = models.User( first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post( title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment( content='This is comment 1', author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) self.session.commit() payload = { 'data': [{ 'type': 'users', 'id': user.id }] } with self.assertRaises(errors.ValidationError) as error: models.serializer.patch_relationship( self.session, payload, 'posts', blog_post.id, 'comments') expected_detail = 'Incompatible Type' self.assertEqual(error.exception.detail, expected_detail) self.assertEqual(error.exception.status_code, 409)
def test_get_collection_response_with_no_query_args(self): """Get collection with no query params returns 200.""" user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment(content='This is a comment', author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) self.session.commit() response = models.serializer.get_collection(self.session, {}, 'comments') expected = { 'data': [{ 'attributes': { 'content': 'This is a comment' }, 'type': 'comments', 'relationships': { 'author': { 'links': { 'related': '/comments/1/author', 'self': '/comments/1/relationships/author' } }, 'post': { 'links': { 'related': '/comments/1/post', 'self': '/comments/1/relationships/post' } } }, 'id': 1 }], 'jsonapi': { 'version': '1.0' }, 'meta': { 'sqlalchemy_jsonapi_version': __version__ }, 'included': [] } actual = response.data self.assertEqual(expected, actual) self.assertEqual(200, response.status_code)
def test_post_relationship_on_to_many_response(self): """Post relationship creates a relationship on many resources returns 200.""" user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment_one = models.Comment(content='This is the first comment', author_id=user.id, author=user) self.session.add(comment_one) comment_two = models.Comment(content='This is the second comment', author_id=user.id, author=user) self.session.add(comment_two) self.session.commit() payload = { 'data': [{ 'type': 'comments', 'id': comment_one.id }, { 'type': 'comments', 'id': comment_two.id }] } response = models.serializer.post_relationship(self.session, payload, 'posts', blog_post.id, 'comments') expected = { 'data': [{ 'type': 'comments', 'id': comment_one.id }, { 'type': 'comments', 'id': comment_two.id }], 'jsonapi': { 'version': '1.0' }, 'meta': { 'sqlalchemy_jsonapi_version': __version__ } } actual = response.data self.assertEqual(expected, actual) self.assertEqual(200, response.status_code)
def test_get_collection_given_an_included_model_that_is_null(self): """Get collection when given a included model that is null returns 200.""" user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content') self.session.add(blog_post) self.session.commit() response = models.serializer.get_collection(self.session, {'include': 'author'}, 'posts') expected = { 'jsonapi': { 'version': '1.0' }, 'data': [{ 'id': 1, 'type': 'posts', 'attributes': { 'title': u'This Is A Title', 'content': u'This is the content' }, 'relationships': { 'author': { 'links': { 'related': '/posts/1/author', 'self': '/posts/1/relationships/author' }, 'data': None }, 'comments': { 'links': { 'related': '/posts/1/comments', 'self': '/posts/1/relationships/comments' } } } }], 'meta': { 'sqlalchemy_jsonapi_version': __version__ }, 'included': [] } actual = response.data self.assertEqual(expected, actual) self.assertEqual(200, response.status_code)
def test_get_relationship_on_to_many(self): """Get a relationship to many resources returns 200.""" user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) for x in range(2): comment = models.Comment(content='This is comment {0}'.format(x + 1), author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) self.session.commit() response = models.serializer.get_relationship(self.session, {}, 'posts', blog_post.id, 'comments') expected = { 'data': [{ 'id': 1, 'type': 'comments' }, { 'id': 2, 'type': 'comments' }], 'jsonapi': { 'version': '1.0' }, 'meta': { 'sqlalchemy_jsonapi_version': '4.0.9' } } actual = response.data self.assertEqual(expected, actual) self.assertEqual(200, response.status_code)
def test_patch_resource_relationship_field_not_found(self): """Patch resource with unknown relationship field returns 400. A BadRequestError is raised. """ user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment(content='This is a comment', author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) self.session.commit() payload = { 'data': { 'type': 'posts', 'id': blog_post.id, 'relationships': { 'nonexistant': { 'data': { 'type': 'users', 'id': user.id } } } } } with self.assertRaises(errors.BadRequestError) as error: models.serializer.patch_resource(self.session, payload, 'posts', blog_post.id) expected_detail = 'nonexistant not relationships for posts.1' self.assertEqual(error.exception.detail, expected_detail) self.assertEqual(error.exception.status_code, 400)
def test_patch_relationship_on_to_one_set_resource_to_null_successful(self): """Patch relationship of single resource and set to null is successful.""" user = models.User( first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post( title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) self.session.commit() payload = { 'data': None } models.serializer.patch_relationship( self.session, payload, 'posts', blog_post.id, 'author') self.assertEqual(blog_post.author, None)
def test_get_collection_when_pagnation_is_out_of_range(self): """Get collection when pagination is out of range returns 200.""" user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) for x in range(10): comment = models.Comment(content='This is comment {0}'.format(x + 1), author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) self.session.commit() response = models.serializer.get_collection(self.session, { 'page[offset]': u'999999', 'page[limit]': u'2' }, 'comments') expected = { 'data': [], 'included': [], 'meta': { 'sqlalchemy_jsonapi_version': __version__ }, 'jsonapi': { 'version': '1.0' } } actual = response.data self.assertEqual(expected, actual) self.assertEqual(200, response.status_code)
def test_patch_resource_with_mismatched_type(self): """Patch resource with mismatched type results in 400. A BadRequestError is raised. """ user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content') self.session.add(blog_post) self.session.commit() payload = { 'data': { 'type': 'comments', 'id': blog_post.id, 'attributes': { 'title': 'This is a new title' }, 'relationships': { 'author': { 'data': { 'type': 'users', 'id': user.id } } } } } with self.assertRaises(errors.BadRequestError) as error: models.serializer.patch_resource(self.session, payload, 'posts', blog_post.id) expected_detail = 'Type does not match' self.assertEqual(error.exception.detail, expected_detail) self.assertEqual(error.exception.status_code, 400)
def test_get_collection_response_with_relationship_for_sorting(self): """Get collection with relationship for sorting results in 409. A NotSortableError is returned. """ user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='Thfsessis Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) self.session.commit() response = models.serializer.get_collection(self.session, {'sort': 'author'}, 'posts') self.assertEquals(409, response.status_code)
def test_post_relationship_on_to_many_success(self): """Post relationship creates a relationship on many resources.""" user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment_one = models.Comment(content='This is the first comment', author_id=user.id, author=user) self.session.add(comment_one) comment_two = models.Comment(content='This is the second comment', author_id=user.id, author=user) self.session.add(comment_two) self.session.commit() payload = { 'data': [{ 'type': 'comments', 'id': comment_one.id }, { 'type': 'comments', 'id': comment_two.id }] } models.serializer.post_relationship(self.session, payload, 'posts', blog_post.id, 'comments') self.assertEqual(comment_one.post.id, blog_post.id) self.assertEqual(comment_one.post, blog_post) self.assertEqual(comment_two.post.id, blog_post.id) self.assertEqual(comment_two.post.id, blog_post.id)
def test_get_collection_response_given_invalid_sort_field(self): """Get collection given an invalid sort field results in 409. A NotSortableError is returned. """ user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) self.session.commit() response = models.serializer.get_collection(self.session, {'sort': 'invalid_field'}, 'posts') expected = 'The requested field posts on type invalid_field is not a sortable field.' self.assertEquals(expected, response.detail) self.assertEquals(409, response.status_code)
def test_get_related_of_to_many(self): """Get many related resource returns a 200.""" user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) for x in (range(2)): comment = models.Comment(content='This is comment {0}'.format(x + 1), author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) self.session.commit() response = models.serializer.get_related(self.session, {}, 'posts', blog_post.id, 'comments') expected = { 'data': [{ 'id': 1, 'type': 'comments', 'included': {}, 'relationships': { 'post': { 'links': { 'self': '/comments/1/relationships/post', 'related': '/comments/1/post' } }, 'author': { 'links': { 'self': '/comments/1/relationships/author', 'related': '/comments/1/author' } } }, 'attributes': { 'content': u'This is comment 1' } }, { 'id': 2, 'type': 'comments', 'included': {}, 'relationships': { 'post': { 'links': { 'self': '/comments/2/relationships/post', 'related': '/comments/2/post' } }, 'author': { 'links': { 'self': '/comments/2/relationships/author', 'related': '/comments/2/author' } } }, 'attributes': { 'content': u'This is comment 2' } }], 'jsonapi': { 'version': '1.0' }, 'meta': { 'sqlalchemy_jsonapi_version': __version__ } } actual = response.data self.assertEqual(expected, actual) self.assertEqual(200, response.status_code)
def test_get_related_of_to_one(self): """Get a related single resource returns a 200. This test is fragile. """ user = models.User(first='Sally', last='Smith', password='******', username='******') self.session.add(user) blog_post = models.Post(title='This Is A Title', content='This is the content', author_id=user.id, author=user) self.session.add(blog_post) comment = models.Comment(content='This is a comment', author_id=user.id, post_id=blog_post.id, author=user, post=blog_post) self.session.add(comment) self.session.commit() response = models.serializer.get_related(self.session, {}, 'posts', blog_post.id, 'author') expected = { 'data': { 'id': 1, 'type': 'users', 'included': {}, 'relationships': { 'comments': { 'links': { 'related': '/users/1/comments', 'self': '/users/1/relationships/comments' } }, 'logs': { 'links': { 'related': '/users/1/logs', 'self': '/users/1/relationships/logs' } }, 'posts': { 'links': { 'related': '/users/1/posts', 'self': '/users/1/relationships/posts' } } }, 'attributes': { 'first': u'Sally', 'last': u'Smith', 'username': u'SallySmith1' } }, 'jsonapi': { 'version': '1.0' }, 'meta': { 'sqlalchemy_jsonapi_version': __version__ } } actual = response.data self.assertEqual(expected, actual) self.assertEqual(200, response.status_code)