def __init__(self, base_url=None, username=None, password=None): self.base_url = base_url self.auth = Auth(base_url) self.session_id = self.__get_session_id(username, password) self.api = Api(self.auth) self.submission_folder_name = uuid.uuid1()
def setUp(self) -> None: self.session_id = 'test.session.id' self.auth = MagicMock() self.auth.session_id = self.session_id self.auth.base_url = "http://example.com" self.api = Api(self.auth)
class TestFolderCreation(unittest.TestCase): def setUp(self) -> None: self.auth = Auth() self.auth.login() self.api = Api(self.auth) self.random_folder_name = uuid.uuid1() def tearDown(self) -> None: self.api.delete_file(self.random_folder_name) def test_when_send_folder_creation_request_then_returns_ok_response(self): response = self.api.create_user_sub_folder(self.random_folder_name) self.assertEqual(response.status, HTTPStatus.OK) self.assertFalse(response.json) def test_when_send_folder_structure_creation_request_then_returns_ok_response(self): folder1 = str(uuid.uuid1()) folder2 = str(uuid.uuid1()) self.random_folder_name = '/'.join([folder1, folder2]) expected_user_files_response = [ { "name": folder2, "path": "user/{}".format(folder1), "size": 4096, "type": "DIR" } ] folder_creation_response = self.api.create_user_sub_folder(self.random_folder_name) self.assertEqual(folder_creation_response.status, HTTPStatus.OK) self.assertFalse(folder_creation_response.json) folder_query_response = self.api.get_user_files(folder1) self.assertEqual(folder_query_response.status, HTTPStatus.OK) self.assertEqual(len(folder_query_response.json), 1) self.assertEqual(folder_query_response.json, expected_user_files_response) self.api.delete_file(folder1)
class TestFileUpload(unittest.TestCase): def setUp(self) -> None: self.auth = Auth() self.auth.login() self.api = Api(self.auth) self.file_path = "tests/resources/test_file.txt" def tearDown(self) -> None: self.api.delete_file(os.path.basename(self.file_path)) def test_when_upload_a_file_then_returns_ok_response(self): response = self.api.upload_file(self.file_path) self.assertEqual(response.status, HTTPStatus.OK) self.assertFalse(response.json) def test_when_upload_a_file_to_an_existing_sub_folder_then_returns_ok_response( self): folder1 = str(uuid.uuid1()) folder2 = str(uuid.uuid1()) random_folder_name = '/'.join([folder1, folder2]) folder_creation_response = self.api.create_user_sub_folder( random_folder_name) self.assertEqual(folder_creation_response.status, HTTPStatus.OK) self.assertFalse(folder_creation_response.json) file_upload_response = self.api.upload_file(self.file_path, random_folder_name) self.assertEqual(file_upload_response.status, HTTPStatus.OK) self.assertFalse(file_upload_response.json) self.api.delete_file(folder1)
def setUp(self) -> None: self.auth = Auth() self.auth.login() self.api = Api(self.auth)
class TestSubmitSubmission(unittest.TestCase): def setUp(self) -> None: self.auth = Auth() self.auth.login() self.api = Api(self.auth) def test_when_post_a_submission_without_a_file_then_returns_correct_response( self): metadata = TestUtils.create_metadata_for_submission_without_file() response = self.api.create_submission(metadata) self.assertEqual(response.status, HTTPStatus.OK) response_json = response.json self.assertTrue(response_json) accession_id = response_json['accno'] self.assertTrue(accession_id) self.__clean_up(accession_id) def test_when_query_an_existing_submission_then_returns_correct_response( self): metadata = TestUtils.create_metadata_for_submission_without_file() create_response = self.api.create_submission(metadata) self.assertEqual(create_response.status, HTTPStatus.OK) response_json = create_response.json accession_id = response_json['accno'] get_response = self.api.get_submission(accession_id) self.assertEqual(get_response.status, HTTPStatus.OK) get_response_json = get_response.json self.assertTrue(get_response_json) self.assertEqual(accession_id, get_response_json['accno']) self.__clean_up(accession_id) def test_post_a_submission_with_a_file_in_metadata_but_without_uploading_the_file_then_returns_error_response( self): expected_error_message_for_missing_file = 'Submission validation errors File not found: test_file.txt' metadata_with_file = TestUtils.create_metadata_for_submission_with_a_file( ) with self.assertRaises(RestErrorException) as context: self.api.create_submission(metadata_with_file) self.assertEqual(expected_error_message_for_missing_file, context.exception.message) self.assertEqual(HTTPStatus.BAD_REQUEST, context.exception.status_code) def test_when_post_a_submission_with_a_file_then_returns_correct_response( self): folder1 = 'sub1' txt_folder_name = '{}/txt_files'.format(folder1) self.api.create_user_sub_folder(txt_folder_name) file_path = "tests/resources/test_file.txt" self.api.upload_file(file_path, txt_folder_name) metadata_with_file = TestUtils.create_metadata_for_submission_with_a_file( ) metadata_with_file['section']['files'][0][ 'path'] = txt_folder_name + '/test_file.txt' response = self.api.create_submission(metadata_with_file) self.assertEqual(response.status, HTTPStatus.OK) response_json = response.json self.assertTrue(response_json) accession_id = response_json['accno'] self.assertTrue(accession_id) # clean up the submission and the file self.__clean_up(accession_id) self.api.delete_file(os.path.basename(folder1)) def __clean_up(self, accession_id): self.api.delete_submission(accession_id)
class BioStudies: def __init__(self, base_url=None, username=None, password=None): self.base_url = base_url self.auth = Auth(base_url) self.session_id = self.__get_session_id(username, password) self.api = Api(self.auth) self.submission_folder_name = uuid.uuid1() def create_submission_folder(self): return self.api.create_user_sub_folder(self.submission_folder_name) def upload_file(self, file_path): return self.api.upload_file( file_path, self.submission_folder_name) def send_submission(self, submission: dict): files = self.__get_files_info(submission) if len(files) > 0: self.__process_files(files) response = self.api.create_submission(submission) return response.json['accno'] def get_submission_by_accession(self, accession_id): return self.api.get_submission(accession_id) def update_links_in_submission(self, submission: Submission, study: Entity) -> dict: study_accession = study.get_accession('BioStudies') biostudies_submission = self.get_submission_by_accession(study_accession).json links_section = self.__get_links_section_from_submission(biostudies_submission) self.__update_links_section(links_section, study, submission) return biostudies_submission @staticmethod def __get_links_section_from_submission(submission: dict) -> List: section = submission['section'] return section.setdefault('links', []) def __update_links_section(self, links_section: List, study: Entity, submission: Submission): for entity_type, biostudies_type in BIOSTUDIES_LINK_TYPES.items(): for linked_entity in submission.get_linked_entities(study, entity_type): accession = linked_entity.get_accession(ENTITY_TYPE_SERVICE[entity_type]) if accession and not self.__accession_in_list(links_section, accession): link_to_add = self.__create_link_element(biostudies_type, accession) links_section.append(link_to_add) @staticmethod def __create_link_element(link_type, accession): return { 'url': accession, 'attributes': [ { 'name': 'Type', 'value': link_type } ] } @staticmethod def __accession_in_list(links_section, accession): for element in links_section: element_accession = element.get('url', None) if element_accession and element_accession == accession: return True return False def __get_session_id(self, username, password): return self.__get_auth_response(username, password).session_id def __get_auth_response(self, username, password): return self.auth.login(username, password) @staticmethod def __get_files_info(submission): section = submission["section"] return section["files"] if "files" in section else [] def __process_files(self, files): self.create_submission_folder() for file in files: file_path = file["path"] self.upload_file(file_path)
class TestApi(unittest.TestCase): def setUp(self) -> None: self.session_id = 'test.session.id' self.auth = MagicMock() self.auth.session_id = self.session_id self.auth.base_url = "http://example.com" self.api = Api(self.auth) @patch('biostudiesclient.api.requests.post') def test_when_request_wrong_url_then_returns_not_found_response( self, mock_post): url = 'http://example.com/wrong/path' folder_name = "test_folder" error_response = { "timestamp": "2021-01-18T14:53:09.309+00:00", "status": 404, "error": "Not Found", "message": "", "path": "/not/existing/path" } mock_post.return_value.status_code = HTTPStatus.NOT_FOUND mock_post.return_value.json.return_value = error_response mock_post.return_value.text = error_response mock_post.return_value.url = url with self.assertRaises(RestErrorException) as context: self.api.create_user_sub_folder(folder_name) self.assertEqual(HTTPStatus.NOT_FOUND, context.exception.status_code) self.assertEqual( f'This URL {url} not exists. Please, try to correct the requested URL.', context.exception.message) @patch('biostudiesclient.api.requests.post') def test_when_passing_folder_name_then_folder_created(self, mock_post): folder_name = "test_folder" mock_post.return_value.status_code = HTTPStatus.OK mock_post.return_value.json.return_value = {} response = self.api.create_user_sub_folder(folder_name) self.assertEqual(response.status, HTTPStatus.OK) self.assertFalse(response.json) @patch('biostudiesclient.api.requests.post') def test_when_passing_folder_structure_then_folder_structure_created( self, mock_post): folder1 = str(uuid.uuid1()) folder2 = str(uuid.uuid1()) folder_structure = '/'.join([folder1, folder2]) mock_post.return_value.status_code = HTTPStatus.OK mock_post.return_value.json.return_value = {} response = self.api.create_user_sub_folder(folder_structure) self.assertEqual(response.status, HTTPStatus.OK) self.assertFalse(response.json) @patch('biostudiesclient.api.requests.post') def test_when_passing_incorrect_session_id_then_response_with_error( self, mock_post): mock_post.return_value.status_code = HTTPStatus.INTERNAL_SERVER_ERROR folder_name = "test_folder" self.session_id = 'incorrect.session.id' with self.assertRaises(RestErrorException) as context: self.api.create_user_sub_folder(folder_name) self.assertEqual(HTTPStatus.INTERNAL_SERVER_ERROR, context.exception.status_code) self.assertEqual(TRY_IT_AGAIN_LATER_MESSAGE, context.exception.message) @patch('biostudiesclient.api.requests.post') def test_when_upload_a_file_then_returns_ok_response(self, mock_post): mock_post.return_value.status_code = HTTPStatus.OK mock_post.return_value.json.return_value = {} file_path = "tests/resources/test_file.txt" response = self.api.upload_file(file_path) self.assertEqual(response.status, HTTPStatus.OK) self.assertFalse(response.json) @patch('biostudiesclient.api.requests.post') def test_when_upload_a_file_to_an_existing_sub_folder_then_returns_ok_response( self, mock_post): mock_post.return_value.status_code = HTTPStatus.OK mock_post.return_value.json.return_value = {} file_path = "tests/resources/test_file.txt" folder1 = str(uuid.uuid1()) folder2 = str(uuid.uuid1()) random_folder_name = '/'.join([folder1, folder2]) file_upload_response = self.api.upload_file(file_path, random_folder_name) self.assertEqual(file_upload_response.status, HTTPStatus.OK) self.assertFalse(file_upload_response.json) @patch('biostudiesclient.api.requests.post') def test_when_upload_a_file_with_wrong_header_then_returns_error_response( self, mock_post): expected_error_message = "Current request is not a multipart request" file_path = "tests/resources/test_file.txt" error_response = { "status": "FAIL", "log": { "level": "ERROR", "message": expected_error_message, "subnodes": [] } } mock_post.return_value.status_code = HTTPStatus.BAD_REQUEST mock_post.return_value.json.return_value = error_response mock_post.return_value.text = error_response with self.assertRaises(RestErrorException) as context: self.api.upload_file(file_path) self.assertEqual(HTTPStatus.BAD_REQUEST, context.exception.status_code) self.assertEqual(expected_error_message, context.exception.message) @patch('biostudiesclient.api.requests.get') def test_when_request_user_files_then_returns_correct_response( self, mock_get): user_files_response = self.__get_user_files_response() mock_get.return_value.status_code = HTTPStatus.OK mock_get.return_value.json.return_value = user_files_response mock_get.return_value.text = user_files_response response = self.api.get_user_files() self.assertEqual(response.status, HTTPStatus.OK) self.assertEqual(len(response.json), 4) self.assertEqual(response.json, user_files_response) @patch('biostudiesclient.api.requests.get') def test_when_request_user_files_from_sub_folder_then_returns_correct_response( self, mock_get): user_files_response = self.__get_user_files_response() folder1 = str(uuid.uuid1()) folder2 = str(uuid.uuid1()) random_folder_name = '/'.join([folder1, folder2]) mock_get.return_value.status_code = HTTPStatus.OK mock_get.return_value.json.return_value = user_files_response mock_get.return_value.text = user_files_response response = self.api.get_user_files(random_folder_name) self.assertEqual(response.status, HTTPStatus.OK) self.assertEqual(len(response.json), 4) self.assertEqual(response.json, user_files_response) @patch('biostudiesclient.api.requests.delete') def test_when_delete_user_files_then_returns_correct_response( self, mock_delete): mock_delete.return_value.status_code = HTTPStatus.OK mock_delete.return_value.json.return_value = {} file_name = "test_file.txt" response = self.api.delete_file(file_name) self.assertEqual(response.status, HTTPStatus.OK) self.assertFalse(response.json) # TODO Whenever Biostudies correct their API and returns the correct HTTP Status Code # when a file is not available for deletion then write a test against it # currently they return 200 OK, even if the file not exists @patch('biostudiesclient.api.requests.post') def test_when_post_a_submission_then_returns_correct_response( self, mock_post): submission_response = self.__get_submission_response_without_file() mock_post.return_value.status_code = HTTPStatus.OK mock_post.return_value.json.return_value = submission_response mock_post.return_value.text = submission_response metadata = TestUtils.create_metadata_for_submission_without_file() response = self.api.create_submission(metadata) self.assertEqual(response.status, HTTPStatus.OK) response_json = response.json self.assertTrue(response_json) self.assertEqual(response_json['accno'], submission_response['accno']) @patch('biostudiesclient.api.requests.post') def test_when_post_a_submission_with_not_existing_file_then_returns_error_response( self, mock_post): expected_error_message = "Submission validation errors. File not found: raw_reads_1.xlsx." submission_response = self.__get_submission_response_for_not_existing_file( ) mock_post.return_value.status_code = HTTPStatus.BAD_REQUEST mock_post.return_value.json.return_value = submission_response mock_post.return_value.text = submission_response metadata = TestUtils.create_metadata_for_submission_with_a_file() with self.assertRaises(RestErrorException) as context: self.api.create_submission(metadata) self.assertEqual(HTTPStatus.BAD_REQUEST, context.exception.status_code) self.assertEqual(expected_error_message, context.exception.message) @staticmethod def __get_user_files_response(): return [{ "name": "7f03654c-fb19-4a17-b16b-740d5ad78bd0", "path": "user", "size": 4096, "type": "DIR" }, { "name": "raw_reads_1.xlsx", "path": "user", "size": 19110, "type": "FILE" }, { "name": "fff25c6a-d2d9-496f-aefe-882a2a787ae1", "path": "user", "size": 4096, "type": "DIR" }, { "name": "5200400d-9f45-4c79-83b8-537373fa4c5f", "path": "user", "size": 4096, "type": "DIR" }] @staticmethod def __get_submission_response_without_file(): return { "accno": "S-BSST683", "attributes": [{ "name": "Description", "value": "This is the description of a test phoenix submssion." }, { "name": "Title", "value": "phoenix submission example" }], "section": { "accno": "Project", "type": "Study", "attributes": [{ "name": "Title", "value": "Cells of the adult human heart" }, { "name": "Description", "value": "Cardiovascular disease is the leading cause of death worldwide." }, { "name": "Organism", "value": "H**o sapiens (human)" }, { "name": "alias", "value": "Phoenix-test-1" }], "links": [{ "url": "ABC123", "attributes": [{ "name": "type", "value": "gen" }] }, { "url": "SAMEA7249626", "attributes": [{ "name": "Type", "value": "BioSample" }] }], "subsections": [{ "type": "Author", "attributes": [{ "name": "Name", "value": "John Doe" }] }] } } @staticmethod def __get_submission_response_for_not_existing_file(): return { "status": "FAIL", "log": { "level": "ERROR", "message": "Submission validation errors.", "subnodes": [{ "level": "ERROR", "message": "File not found: raw_reads_1.xlsx.", "subnodes": [] }] } }
def setUp(self) -> None: self.auth = Auth() self.auth.login() self.api = Api(self.auth) self.file_path = "tests/resources/test_file.txt"
def setUp(self) -> None: self.auth = Auth() self.auth.login() self.api = Api(self.auth) self.random_folder_name = uuid.uuid1()