def _navigate_to_previous_items(self, expected_items, json_response): for expected_item in expected_items: self.assertIn('links', json_response, msg='No links found in answer') previous_link = get_link(json_response['links'], 'previous') self.assertIsNotNone( previous_link, msg=f'No previous link found in links: {json_response["links"]}' ) self.assertIn('href', previous_link, msg=f'Previous link has no href: {previous_link}') response = self.client.get(previous_link['href']) json_response = response.json() self.assertStatusCode(200, response) self.assertEqual(1, len(json_response['features']), msg="More than one item found") self.assertEqual(expected_item, json_response['features'][0]['id']) # Make sure there is no previous link self.assertIn('links', json_response, msg='No links found in answer') self.assertIsNone(get_link(json_response['links'], 'previous'), msg='Should not have previous link') return json_response
def test_get_pagination(self): limit = 1 query = { "ids": ','.join([ self.items[1]['name'], self.items[4]['name'], self.items[6]['name'] ]), "limit": limit } response = self.client.get(self.path, query) self.assertStatusCode(200, response) json_data = response.json() self.assertEqual(len(json_data['features']), limit) # get the next link next_link = get_link(json_data['links'], 'next') self.assertIsNotNone(next_link, msg='No next link found') self.assertEqual(next_link.get('method', 'GET'), 'GET') self.assertNotIn('body', next_link) self.assertNotIn('merge', next_link) # Get the next page query_next = query.copy() response = self.client.get(next_link['href']) self.assertStatusCode(200, response) json_data_next = response.json() self.assertEqual(len(json_data_next['features']), limit) # make sure the next page is different than the original self.assertNotEqual( json_data['features'], json_data_next['features'], msg='Next page should not be the same as the first one') # get the previous link previous_link = get_link(json_data_next['links'], 'previous') self.assertIsNotNone(previous_link, msg='No previous link found') self.assertEqual(previous_link.get('method', 'GET'), 'GET') self.assertNotIn('body', previous_link) self.assertNotIn('merge', previous_link) # Get the previous page response = self.client.get(previous_link['href']) self.assertStatusCode(200, response) json_data_previous = response.json() self.assertEqual(len(json_data_previous['features']), limit) # make sure the previous data is identical to the first page self.assertEqual( json_data_previous['features'], json_data['features'], msg='previous page should be the same as the first one')
def _check_stac_links(self, parent_path, expected, current): # sort links by rel expected = list(sorted(expected, key=lambda link: link['rel'])) current = list(sorted(current, key=lambda link: link['rel'])) logger.debug('Expected links:\n%s', pformat(expected)) logger.debug('Current links:\n%s', pformat(current)) for i, link in enumerate(expected): path = f'{parent_path}.{i}' current_link = get_link(current, link['rel']) self.assertIsNotNone( current_link, msg=f'{path}: Link {link} is missing in current links {current}' ) for key, value in link.items(): self.assertIn( key, current_link, msg=f'key {key} is missing in current link {current_link}') if key == 'href': self.assertEqual( urlparse(value).path, urlparse(current_link[key]).path, msg= f'{path}[{key}]: value does not match in link {current_link}' ) else: self.assertEqual( value, current_link[key], msg= f'{path}[{key}]: value does not match in link {current_link}' )
def test_item_deserialization_update(self): original_sample = self.data_factory.create_item_sample( collection=self.collection.model, sample='item-1', ) sample = self.data_factory.create_item_sample( collection=self.collection.model, sample='item-2', name=original_sample["name"]) serializer = ItemSerializer(original_sample.model, data=sample.get_json('deserialize')) serializer.is_valid(raise_exception=True) item = serializer.save() # mock a request needed for the serialization of links context = { 'request': api_request_mocker.get( f'{STAC_BASE_V}/collections/{self.collection["name"]}/items/{sample["name"]}' ) } serializer = ItemSerializer(item, context=context) python_native = serializer.data self.check_stac_item(sample.json, python_native, self.collection["name"]) self.assertIsNone(get_link(python_native['links'], 'describedBy'), msg='Link describedBy was not removed in update')
def test_collection_deserialization_update_existing(self): # Create a collection collection = self.data_factory.create_collection_sample( sample='collection-1').model # Get a new samples based on another sample sample = self.data_factory.create_collection_sample( sample='collection-4', name=collection.name) context = { 'request': api_request_mocker.get( f'{STAC_BASE_V}/collections/{collection.name}') } serializer = CollectionSerializer(collection, data=sample.get_json('deserialize'), context=context) serializer.is_valid(raise_exception=True) collection = serializer.save() # serialize the object and test it against the one above # mock a request needed for the serialization of links serializer = CollectionSerializer(collection, context=context) python_native = serializer.data self.check_stac_collection(sample.json, python_native) self.assertNotIn('providers', python_native, msg='Providers have not been removed') self.assertIn('links', python_native, msg='Generated links missing') self.assertIsNone(get_link(python_native['links'], 'describedBy'), msg='User link describedBy have not been removed')
def _get_check_link(self, links, rel, endpoint): link = get_link(links, rel) self.assertIsNotNone(link, msg=f'Pagination {rel} link missing') self.assertTrue(isinstance(link['href'], str), msg='href is not a string') self.assertTrue(link['href'].startswith( f'http://testserver/api/stac/v0.9/{endpoint}?cursor='), msg='Invalid href link pagination string') return link
def get_success_headers(self, data): try: return { 'Location': get_link(data['links'], 'self', raise_exception=True)['href'] } except KeyError as err: logger.error( 'Failed to set the Location header for item creation: %s', err) return {}
def test_pagination(self): # pylint: disable=too-many-locals items = self.factory.create_item_samples(3, self.collections[0].model, db_create=True) asset = self.factory.create_asset_sample(items[0].model, db_create=True) for i in range(1, 4): AssetUpload.objects.create( asset=asset.model, upload_id=f'upload-{i}', status=AssetUpload.Status.ABORTED, checksum_multihash=get_sha256_multihash(b'upload-%d' % i), number_parts=2, ended=utc_aware(datetime.utcnow()), md5_parts=['md5-%d-1' % i, 'md5-%d-2' % i]) for endpoint, result_attribute in [ ('collections', 'collections'), (f'collections/{self.collections[0]["name"]}/items', 'features'), (f'collections/{self.collections[0]["name"]}/items/{items[0]["name"]}/' f'assets/{asset["name"]}/uploads', 'uploads') ]: with self.subTest(endpoint=endpoint): # Page 1: response = self.client.get( f"/{STAC_BASE_V}/{endpoint}?limit=1") self.assertStatusCode(200, response) page_1 = response.json() # Make sure previous link is not present self.assertIsNone( get_link(page_1['links'], 'previous'), msg='Pagination previous link present for initial query') # Get and check next link next_link_2 = self._get_check_link(page_1['links'], 'next', endpoint) # PAGE 2: # Read the next page page_2 = self._read_link(next_link_2, 'next', [page_1], result_attribute) # get and check next link next_link_3 = self._get_check_link(page_2['links'], 'next', endpoint) # Get and check previous link previous_link_1 = self._get_check_link(page_2['links'], 'previous', endpoint) # PAGE 3: # Read the next page page_3 = self._read_link(next_link_3, 'next', [page_1, page_2], result_attribute) # Make sure next link is not present self.assertIsNone( get_link(page_3['links'], 'next'), msg='Pagination next link present for last page') # Get and check previous link previous_link_2 = self._get_check_link(page_3['links'], 'previous', endpoint) # Navigate back with previous links # PAGE: 2 _page_2 = self._read_link(previous_link_2, 'previous', [page_1, page_3], result_attribute) self.assertEqual( page_2[result_attribute], _page_2[result_attribute], msg= "Previous link for page 2 is not equal to next link to page 2" ) # get and check next link _next_link_3 = self._get_check_link(_page_2['links'], 'next', endpoint) # Get and check previous link _previous_link_1 = self._get_check_link( _page_2['links'], 'previous', endpoint) # PAGE 1: _page_1 = self._read_link(_previous_link_1, 'previous', [_page_2, page_2, page_3], result_attribute) self.assertEqual( page_1[result_attribute], _page_1[result_attribute], msg= "Previous link for page 1 is not equal to initial page 1")
def test_pagination(self): response = self.client.get(f"/{STAC_BASE_V}/collections?limit=1") json_data = response.json() self.assertEqual(200, response.status_code, msg=get_http_error_description(json_data)) # Check next link next_link = get_link(json_data['links'], 'next') self.assertIsNotNone(next_link, msg='Pagination next link missing') self.assertTrue(isinstance(next_link['href'], str), msg='href is not a string') self.assertTrue(next_link['href'].startswith( 'http://testserver/api/stac/v0.9/collections?cursor='), msg='Invalid href link pagination string') # Check previous link previous_link = get_link(json_data['links'], 'previous') self.assertIsNone( previous_link, msg='Pagination previous link present for initial query') # Get the next page response = self.client.get(next_link['href'].replace( 'http://testserver', '')) json_data = response.json() self.assertEqual(200, response.status_code, msg=get_http_error_description(json_data)) # Check next link next_link = get_link(json_data['links'], 'next') self.assertIsNotNone(next_link, msg='Pagination next link missing') self.assertTrue(isinstance(next_link['href'], str), msg='href is not a string') self.assertTrue(next_link['href'].startswith( 'http://testserver/api/stac/v0.9/collections?cursor='), msg='Invalid href link pagination string') # Check previous link previous_link = get_link(json_data['links'], 'previous') self.assertIsNotNone(previous_link, msg='Pagination previous link is missing') self.assertTrue(isinstance(previous_link['href'], str), msg='href is not a string') self.assertTrue(previous_link['href'].startswith( 'http://testserver/api/stac/v0.9/collections?cursor='), msg='Invalid href link pagination string') # Get the next page response = self.client.get(next_link['href'].replace( 'http://testserver', '')) json_data = response.json() self.assertEqual(200, response.status_code, msg=get_http_error_description(json_data)) # Check next link next_link = get_link(json_data['links'], 'next') self.assertIsNone(next_link, msg='Pagination next link is present') # Check previous link previous_link = get_link(json_data['links'], 'previous') self.assertIsNotNone(previous_link, msg='Pagination previous link is missing') self.assertTrue(isinstance(previous_link['href'], str), msg='href is not a string') self.assertTrue(previous_link['href'].startswith( 'http://testserver/api/stac/v0.9/collections?cursor='), msg='Invalid href link pagination string')
def test_post_pagination(self): limit = 1 query = { "query": { "title": { "startsWith": self.title_for_query } }, "limit": limit } response = self.client.post(self.path, data=query, content_type="application/json") self.assertStatusCode(200, response) json_data = response.json() self.assertEqual(len(json_data['features']), limit) # get the next link next_link = get_link(json_data['links'], 'next') self.assertIsNotNone(next_link, msg='No next link found') self.assertEqual(next_link.get('method', 'POST'), 'POST') self.assertIn('body', next_link) self.assertIn('merge', next_link) # Get the next page query_next = query.copy() if next_link['merge'] and next_link['body']: query_next.update(next_link['body']) response = self.client.post(next_link['href'], data=query_next, content_type="application/json") self.assertStatusCode(200, response) json_data_next = response.json() self.assertEqual(len(json_data_next['features']), limit) # make sure the next page is different than the original self.assertNotEqual( json_data['features'], json_data_next['features'], msg='Next page should not be the same as the first one') # get the previous link previous_link = get_link(json_data_next['links'], 'previous') self.assertIsNotNone(previous_link, msg='No previous link found') self.assertEqual(previous_link.get('method', 'POST'), 'POST') self.assertIn('body', previous_link) self.assertIn('merge', previous_link) # Get the previous page query_previous = query.copy() if previous_link['merge'] and previous_link['body']: query_previous.update(previous_link['body']) response = self.client.post(previous_link['href'], data=query_previous, content_type="application/json") self.assertStatusCode(200, response) json_data_previous = response.json() self.assertEqual(len(json_data_previous['features']), limit) # make sure the previous data is identical to the first page self.assertEqual( json_data_previous['features'], json_data['features'], msg='previous page should be the same as the first one')