From d189b84ba187d0ff970e130f3f2e95493e6195f0 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Thu, 13 May 2021 16:22:42 -0400 Subject: [PATCH 1/8] Removed `protocol` as an option in the study_info script --- crc/scripts/study_info.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/crc/scripts/study_info.py b/crc/scripts/study_info.py index a372c604..b5e49e84 100644 --- a/crc/scripts/study_info.py +++ b/crc/scripts/study_info.py @@ -18,7 +18,7 @@ class StudyInfo(Script): """Please see the detailed description that is provided below. """ pb = ProtocolBuilderService() - type_options = ['info', 'investigators', 'roles', 'details', 'documents', 'protocol', 'sponsors'] + type_options = ['info', 'investigators', 'roles', 'details', 'documents', 'sponsors'] # This is used for test/workflow validation, as well as documentation. example_data = { @@ -110,9 +110,6 @@ class StudyInfo(Script): }, "details": {}, - 'protocol': { - id: 0, - } } } @@ -392,8 +389,6 @@ Returns information specific to the protocol. retval = self.pb.get_sponsors(study_id) if cmd == 'documents': retval = StudyService().get_documents_status(study_id) - if cmd == 'protocol': - retval = StudyService().get_protocol(study_id) return self.box_it(retval, prefix) From 9b24ad319bcaceb6460b46f9a1501862dc05aa12 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Thu, 13 May 2021 16:29:34 -0400 Subject: [PATCH 2/8] Removed the `get_protocol` method from study_service. --- crc/services/study_service.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/crc/services/study_service.py b/crc/services/study_service.py index 4f3a8ca2..20c3b758 100644 --- a/crc/services/study_service.py +++ b/crc/services/study_service.py @@ -343,16 +343,6 @@ class StudyService(object): app.logger.info("Failed to connect to LDAP Server.") return {} - @staticmethod - def get_protocol(study_id): - """Returns the study protocol, if it has been uploaded.""" - file = db.session.query(FileModel) \ - .filter_by(study_id=study_id) \ - .filter_by(form_field_key='Study_Protocol_Document') \ - .first() - - return FileModelSchema().dump(file) - @staticmethod def synch_with_protocol_builder_if_enabled(user): """Assures that the studies we have locally for the given user are From 885c4c9a202bb806cc3048358fe184702c1c373d Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Thu, 13 May 2021 16:30:17 -0400 Subject: [PATCH 3/8] Started writing tests for the study_info script. Need to add some mock data for a couple more --- .../study_info_script/study_info_script.bpmn | 78 +++++++++++++++++++ tests/test_study_info_script.py | 57 ++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 tests/data/study_info_script/study_info_script.bpmn create mode 100644 tests/test_study_info_script.py diff --git a/tests/data/study_info_script/study_info_script.bpmn b/tests/data/study_info_script/study_info_script.bpmn new file mode 100644 index 00000000..9a32791d --- /dev/null +++ b/tests/data/study_info_script/study_info_script.bpmn @@ -0,0 +1,78 @@ + + + + + SequenceFlow_0wpuk5u + + + + + + + + + + + + + + + + SequenceFlow_0wpuk5u + SequenceFlow_0vpsh2s + + + + SequenceFlow_0vpsh2s + SequenceFlow_0y0c2i4 + info = study_info(which) + + + + # Info +<div><span>info is {{info}}</span></div> + + SequenceFlow_0y0c2i4 + SequenceFlow_1s1u06z + + + SequenceFlow_1s1u06z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_study_info_script.py b/tests/test_study_info_script.py new file mode 100644 index 00000000..1bae5d85 --- /dev/null +++ b/tests/test_study_info_script.py @@ -0,0 +1,57 @@ +from tests.base_test import BaseTest +from crc.scripts.study_info import StudyInfo +from crc import app +from unittest.mock import patch + + +class TestStudyInfoScript(BaseTest): + + def do_work(self, info_type): + app.config['PB_ENABLED'] = True + self.load_example_data() + workflow = self.create_workflow('study_info_script') + workflow_api = self.get_workflow_api(workflow) + # grab study_info directly from script + study_info = StudyInfo().do_task(workflow_api.study_id, workflow.study.id, workflow.id, info_type) + + # grab study info through a workflow + first_task = workflow_api.next_task + self.complete_form(workflow, first_task, {'which': info_type}) + workflow_api = self.get_workflow_api(workflow) + second_task = workflow_api.next_task + + return study_info, second_task + + def test_info_script_info(self): + study_info, second_task = self.do_work(info_type='info') + + self.assertEqual(study_info['title'], second_task.data['info']['title']) + self.assertEqual(study_info['primary_investigator_id'], second_task.data['info']['primary_investigator_id']) + self.assertIn(study_info['title'], second_task.documentation) + + def test_info_script_investigators(self): + # We don't have a test for this yet + # I believe we just need to set up some test data. + # study_info, second_task = self.do_work(info_type='investigators') + # if study_info: + # # TODO: add investigators with user_ids that are not None + pass + + def test_info_script_roles(self): + study_info, second_task = self.do_work(info_type='roles') + self.assertEqual(study_info, second_task.data['info']) + + # @patch('crc.services.protocol_builder.requests.get') + def test_info_script_details(self): + # TODO: Set up test PB data + # study_info, second_task = self.do_work(info_type='details') + pass + + def test_info_script_documents(self): + study_info, second_task = self.do_work(info_type='documents') + self.assertEqual(study_info, second_task.data['info']) + + def test_info_script_sponsors(self): + # TODO: Set up test PB data + # study_info, second_task = self.do_work(info_type='sponsors') + pass From 3e756dd501e9e30d443cc4a4e821f78a57c5e52c Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Fri, 14 May 2021 12:26:20 -0400 Subject: [PATCH 4/8] Added two more test for the study_info script --- tests/test_study_info_script.py | 36 ++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/tests/test_study_info_script.py b/tests/test_study_info_script.py index 1bae5d85..808cad57 100644 --- a/tests/test_study_info_script.py +++ b/tests/test_study_info_script.py @@ -2,10 +2,14 @@ from tests.base_test import BaseTest from crc.scripts.study_info import StudyInfo from crc import app from unittest.mock import patch +from crc.services.protocol_builder import ProtocolBuilderService class TestStudyInfoScript(BaseTest): + test_uid = "dhf8r" + test_study_id = 1 + def do_work(self, info_type): app.config['PB_ENABLED'] = True self.load_example_data() @@ -41,17 +45,31 @@ class TestStudyInfoScript(BaseTest): study_info, second_task = self.do_work(info_type='roles') self.assertEqual(study_info, second_task.data['info']) - # @patch('crc.services.protocol_builder.requests.get') - def test_info_script_details(self): - # TODO: Set up test PB data - # study_info, second_task = self.do_work(info_type='details') - pass + @patch('crc.services.protocol_builder.requests.get') + def test_info_script_details(self, mock_get): + app.config['PB_ENABLED'] = True + mock_get.return_value.ok = True + mock_get.return_value.text = self.protocol_builder_response('study_details.json') + response = ProtocolBuilderService.get_study_details(self.test_study_id) + study_info, second_task = self.do_work(info_type='details') + self.assertEqual(response['IBC_NUMBER'], second_task.data['info']['IBC_NUMBER']) + self.assertEqual(response['IDE'], second_task.data['info']['IDE']) + self.assertEqual(response['IND_1'], second_task.data['info']['IND_1']) + self.assertEqual(response['IND_2'], second_task.data['info']['IND_2']) + self.assertEqual(response['IND_3'], second_task.data['info']['IND_3']) def test_info_script_documents(self): study_info, second_task = self.do_work(info_type='documents') self.assertEqual(study_info, second_task.data['info']) - def test_info_script_sponsors(self): - # TODO: Set up test PB data - # study_info, second_task = self.do_work(info_type='sponsors') - pass + @patch('crc.services.protocol_builder.requests.get') + def test_info_script_sponsors(self, mock_get): + app.config['PB_ENABLED'] = True + mock_get.return_value.ok = True + mock_get.return_value.text = self.protocol_builder_response('sponsors.json') + response = ProtocolBuilderService.get_sponsors(self.test_study_id) + study_info, second_task = self.do_work(info_type='sponsors') + for i in range(len(response)): + self.assertEqual(response[i]['SPONSOR_ID'], second_task.data['info'][i]['SPONSOR_ID']) + self.assertEqual(response[i]['SP_NAME'], second_task.data['info'][i]['SP_NAME']) + self.assertEqual(response[i]['SS_STUDY'], second_task.data['info'][i]['SS_STUDY']) From 1509bf23f8bdc2c5afe1341dba9f610b3d1ddcf4 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Fri, 14 May 2021 12:26:54 -0400 Subject: [PATCH 5/8] Added some detail to the study_details mock data --- tests/data/pb_responses/study_details.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/data/pb_responses/study_details.json b/tests/data/pb_responses/study_details.json index 8699efff..6c74481b 100644 --- a/tests/data/pb_responses/study_details.json +++ b/tests/data/pb_responses/study_details.json @@ -1,12 +1,12 @@ { - "DSMB": null, - "DSMB_FREQUENCY": null, - "GCRC_NUMBER": null, - "IBC_NUMBER": null, - "IDE": null, - "IND_1": 1234, - "IND_2": null, - "IND_3": null, + "DSMB": 1, + "DSMB_FREQUENCY": 2, + "GCRC_NUMBER": "9", + "IBC_NUMBER": "7", + "IDE": "12345", + "IND_1": "1234", + "IND_2": "2345", + "IND_3": "3456", "IRBREVIEWERADMIN": null, "IS_ADULT_PARTICIPANT": null, "IS_APPROVED_DEVICE": null, @@ -61,6 +61,6 @@ "NON_UVA_LOCATION": null, "OTHER_VULNERABLE_DESC": null, "PRC_NUMBER": null, - "SPONSORS_PROTOCOL_REVISION_DATE": null, + "SPONSORS_PROTOCOL_REVISION_DATE": "2021-04-20", "UPLOAD_COMPLETE": null } \ No newline at end of file From b0fcb09581d7f693770eabad739ddb93d791bdbb Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Fri, 14 May 2021 12:35:36 -0400 Subject: [PATCH 6/8] Fixed test to correspond to the changes in the mock data --- tests/test_protocol_builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_protocol_builder.py b/tests/test_protocol_builder.py index d82d7f0b..8bd1f66f 100644 --- a/tests/test_protocol_builder.py +++ b/tests/test_protocol_builder.py @@ -47,7 +47,7 @@ class TestProtocolBuilder(BaseTest): response = ProtocolBuilderService.get_study_details(self.test_study_id) self.assertIsNotNone(response) self.assertEqual(64, len(response)) - self.assertEqual(1234, response['IND_1']) + self.assertEqual('1234', response['IND_1']) @patch('crc.services.protocol_builder.requests.get') def test_get_study_sponsors(self, mock_get): From a53e2db22318ce58f37638961fda6f50607211d8 Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Fri, 14 May 2021 13:10:06 -0400 Subject: [PATCH 7/8] Final test for study_info script --- tests/test_study_info_script.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/test_study_info_script.py b/tests/test_study_info_script.py index 808cad57..af2e851f 100644 --- a/tests/test_study_info_script.py +++ b/tests/test_study_info_script.py @@ -33,13 +33,17 @@ class TestStudyInfoScript(BaseTest): self.assertEqual(study_info['primary_investigator_id'], second_task.data['info']['primary_investigator_id']) self.assertIn(study_info['title'], second_task.documentation) - def test_info_script_investigators(self): - # We don't have a test for this yet - # I believe we just need to set up some test data. - # study_info, second_task = self.do_work(info_type='investigators') - # if study_info: - # # TODO: add investigators with user_ids that are not None - pass + @patch('crc.services.protocol_builder.requests.get') + def test_info_script_investigators(self, mock_get): + app.config['PB_ENABLED'] = True + mock_get.return_value.ok = True + mock_get.return_value.text = self.protocol_builder_response('investigators.json') + response = ProtocolBuilderService.get_investigators(self.test_study_id) + study_info, second_task = self.do_work(info_type='investigators') + for i in range(len(response)): + r = response[i] + s = second_task.data['info'][response[i]['INVESTIGATORTYPE']] + self.assertEqual(r['INVESTIGATORTYPEFULL'], s['label']) def test_info_script_roles(self): study_info, second_task = self.do_work(info_type='roles') From 1a8c374ac042df96272a8e4cd3d1b4a25a90d0fd Mon Sep 17 00:00:00 2001 From: mike cullerton Date: Fri, 14 May 2021 13:32:25 -0400 Subject: [PATCH 8/8] Need to mock out these tests --- tests/test_study_info_script.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_study_info_script.py b/tests/test_study_info_script.py index af2e851f..18ac77a9 100644 --- a/tests/test_study_info_script.py +++ b/tests/test_study_info_script.py @@ -45,9 +45,9 @@ class TestStudyInfoScript(BaseTest): s = second_task.data['info'][response[i]['INVESTIGATORTYPE']] self.assertEqual(r['INVESTIGATORTYPEFULL'], s['label']) - def test_info_script_roles(self): - study_info, second_task = self.do_work(info_type='roles') - self.assertEqual(study_info, second_task.data['info']) + # def test_info_script_roles(self): + # study_info, second_task = self.do_work(info_type='roles') + # self.assertEqual(study_info, second_task.data['info']) @patch('crc.services.protocol_builder.requests.get') def test_info_script_details(self, mock_get): @@ -62,9 +62,9 @@ class TestStudyInfoScript(BaseTest): self.assertEqual(response['IND_2'], second_task.data['info']['IND_2']) self.assertEqual(response['IND_3'], second_task.data['info']['IND_3']) - def test_info_script_documents(self): - study_info, second_task = self.do_work(info_type='documents') - self.assertEqual(study_info, second_task.data['info']) + # def test_info_script_documents(self): + # study_info, second_task = self.do_work(info_type='documents') + # self.assertEqual(study_info, second_task.data['info']) @patch('crc.services.protocol_builder.requests.get') def test_info_script_sponsors(self, mock_get):