def test_get_one_to_one_pk(self): """ Ensures JSON API compliant build of one-to-one primary key relationship field """ response = self.client.get('/yellow_dwarf/1') jsonapi_document = api_utils.resource_to_jsonapi_document(response.data) relationships = jsonapi_document['data']['relationships'] one_to_one_star = {'star': {'data': {'type': 'stars', 'id': '1'}}} self.assertEqual(one_to_one_star, relationships)
def test_get_many_to_one_pk(self): """ Ensures JSON API compliant build of many-to-one primary key field. In Django, this type of model relationship is represented by the ``ForeignKey`` field that has its ``many`` argument set to ``False``, which is the default. """ response = self.client.get('/planets/3') jsonapi_document = api_utils.resource_to_jsonapi_document(response.data) relationships = jsonapi_document['data']['relationships'] many_to_one_star_data = {'data': {'type': 'stars', 'id': '1'}} self.assertEqual(many_to_one_star_data, relationships['system-star'])
def test_get_one_to_one_with_included(self): """ Ensures JSON API compliant build of one-to-one serialized relationship field """ response = self.client.get('/yellow_dwarf_with_included/1') jsonapi_document = api_utils.resource_to_jsonapi_document(response.data) relationships = jsonapi_document['data']['relationships'] one_to_one_star = {'star': {'data': {'type': 'stars', 'id': '1'}}} self.assertEqual(one_to_one_star, relationships) included_star = [{"type": "stars", "id": "1", "attributes": {"galaxy-name": "Via Lactea", "name": "Sun"}}] included = jsonapi_document['included'] self.assertEqual(included_star, included)
def test_get_many_to_many_pk(self): """ Ensures JSON API compliant build of many-to-many primary key field. In Django, this type of model relationship is represented by the ``ForeignKey`` field that has its ``many`` argument set to ``True``. """ response = self.client.get('/planets/3') jsonapi_document = api_utils.resource_to_jsonapi_document(response.data) relationships = jsonapi_document['data']['relationships'] many_to_many_planet_neighbors_data = {"data": [ {"type": "planets", "id": "2"}, {"type": "planets", "id": "4"} ]} self.assertEqual(many_to_many_planet_neighbors_data, relationships['neighbors'])
def test_get_many_to_many_with_included(self): """ Ensures JSON API compliant build of many-to-many serialized relationship field. In Django, this type of model relationship is represented by the ``ForeignKey`` field that has its ``many`` argument set to ``True``. """ response = self.client.get('/planets_with_included/3') print(response.content.decode()) jsonapi_document = api_utils.resource_to_jsonapi_document(response.data) relationships = jsonapi_document['data']['relationships'] many_to_many_planet_neighbors_data = {"data": [ {"type": "planets", "id": "2"}, {"type": "planets", "id": "4"} ]} self.assertEqual(many_to_many_planet_neighbors_data, relationships['neighbors']) included = jsonapi_document['included'] self.assertEqual(included, EARTH_INCLUDED)
def test_valid_jsonapi_name(self): """ From the JSON API specification: All member names used in a JSON API document MUST be treated as case-sensitive by clients and servers, and they MUST meet all of the following conditions: Member names MUST contain at least one character. Member names MUST contain only the allowed characters listed below. Member names MUST start and end with a "globally allowed character", as defined below. To enable an easy mapping of member names to URLs, it is RECOMMENDED that member names use only non-reserved, URL safe characters specified in RFC 3986. """ response = self.client.get('/planets/3') jsonapi_document = api_utils.resource_to_jsonapi_document(response.data) # TODO globally allowed character test and only allowed character test for member_name in jsonapi_document: self.assertTrue(len(member_name))
def test_get_many_to_one_with_included(self): """ Ensures JSON API compliant build of many-to-one serialized relationship field. In Django, this type of model relationship is represented by the ``ForeignKey`` field that has its ``many`` argument set to ``False``, which is the default. """ response = self.client.get('/planets_with_included/1') jsonapi_document = api_utils.resource_to_jsonapi_document(response.data) relationships = jsonapi_document['data']['relationships'] many_to_one_star_data = {'data': {'type': 'stars', 'id': '1'}} self.assertEqual(many_to_one_star_data, relationships['system-star']) sun_elements = [("id", "1"), ("type", "stars"), ("attributes", {"galaxy-name": "Via Lactea", "name": "Sun"})] sun = OrderedDict(sun_elements) included = jsonapi_document['included'] included_star = None for model in included: if model['type'] == 'stars': included_star = model self.assertEqual(included_star, sun)
def test_valid_resource_format_for_get(self): """ Ensures resources contain at least the following top-level members: ``id`` and ``type`` From the JSON API specification: A "resource identifier object" is an object that identifies an individual resource. A "resource identifier object" MUST contain type and id members. A "resource identifier object" MAY also include a meta member, whose value is a meta object that contains non-standard meta-information. This test is only for GET calls - the id member is not required when the resource object originates at the client and represents a new resource to be created on the server. """ response = self.client.get('/planets/3') jsonapi_document = api_utils.resource_to_jsonapi_document(response.data) main_data = jsonapi_document['data'] self.assertTrue('id' in main_data and 'type' in main_data, msg='Does not comply with JSON API ' 'resource identifier format {0}:'.format(main_data)) relationships = jsonapi_document['data']['relationships'] for relationship_key in relationships: relationship = relationships[relationship_key] relationship_data = relationship['data'] # handle list relationship if isinstance(relationship_data, list): for resource_identifier in relationship_data: self.assertTrue('id' in resource_identifier and 'type' in resource_identifier, msg='Does not comply with JSON API ' 'resource identifier format {0}:'.format(resource_identifier)) # test single resource object else: self.assertTrue('id' in relationship_data and 'type' in relationship_data, msg='Does not comply with JSON API ' 'resource identifier format {0}:'.format(relationship_data))
def test_string_identifier(self): """ Ensures string identifiers. From the JSON API specification: *"The values of the id and type members MUST be strings."* """ response = self.client.get('/planets/3') jsonapi_document = api_utils.resource_to_jsonapi_document(response.data) identifier = jsonapi_document['data']['id'] self.assertTrue(isinstance(identifier, str)) relationships = jsonapi_document['data']['relationships'] for relationship_key in relationships: relationship = relationships[relationship_key] relationship_data = relationship['data'] # handle list relationship if isinstance(relationship_data, list): for resource_identifier in relationship_data: self.assertTrue(isinstance(resource_identifier['id'], str)) # test single resource object else: self.assertTrue(isinstance(relationship_data['id'], str))