Пример #1
0
    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()
Пример #2
0
    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)
Пример #3
0
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)
Пример #4
0
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)
Пример #7
0
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)
Пример #8
0
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": []
                }]
            }
        }
Пример #9
0
    def setUp(self) -> None:
        self.auth = Auth()
        self.auth.login()
        self.api = Api(self.auth)

        self.file_path = "tests/resources/test_file.txt"
Пример #10
0
    def setUp(self) -> None:
        self.auth = Auth()
        self.auth.login()
        self.api = Api(self.auth)

        self.random_folder_name = uuid.uuid1()