2020-03-27 12:29:31 +00:00
|
|
|
import json
|
2020-05-07 17:57:24 +00:00
|
|
|
from unittest.mock import patch
|
2020-03-27 12:29:31 +00:00
|
|
|
|
2020-05-25 16:29:05 +00:00
|
|
|
from tests.base_test import BaseTest
|
|
|
|
|
2020-05-27 02:42:49 +00:00
|
|
|
from crc import session, app
|
2020-03-27 12:29:31 +00:00
|
|
|
from crc.api.common import ApiErrorSchema
|
2020-05-07 17:57:24 +00:00
|
|
|
from crc.models.protocol_builder import ProtocolBuilderStudySchema
|
2020-05-25 16:29:05 +00:00
|
|
|
from crc.models.workflow import WorkflowSpecModel
|
2020-05-30 19:37:04 +00:00
|
|
|
from crc.services.workflow_service import WorkflowService
|
2020-03-27 12:29:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TestWorkflowSpecValidation(BaseTest):
|
|
|
|
|
|
|
|
def validate_workflow(self, workflow_name):
|
|
|
|
spec_model = self.load_test_spec(workflow_name)
|
|
|
|
rv = self.app.get('/v1.0/workflow-specification/%s/validate' % spec_model.id, headers=self.logged_in_headers())
|
|
|
|
self.assert_success(rv)
|
|
|
|
json_data = json.loads(rv.get_data(as_text=True))
|
|
|
|
return ApiErrorSchema(many=True).load(json_data)
|
|
|
|
|
2020-05-22 18:37:49 +00:00
|
|
|
def test_successful_validation_of_test_workflows(self):
|
2020-05-27 02:42:49 +00:00
|
|
|
app.config['PB_ENABLED'] = False # Assure this is disabled.
|
2020-05-30 19:37:04 +00:00
|
|
|
self.load_example_data()
|
2020-03-27 12:29:31 +00:00
|
|
|
self.assertEqual(0, len(self.validate_workflow("parallel_tasks")))
|
|
|
|
self.assertEqual(0, len(self.validate_workflow("decision_table")))
|
|
|
|
self.assertEqual(0, len(self.validate_workflow("docx")))
|
|
|
|
self.assertEqual(0, len(self.validate_workflow("exclusive_gateway")))
|
|
|
|
self.assertEqual(0, len(self.validate_workflow("file_upload_form")))
|
|
|
|
self.assertEqual(0, len(self.validate_workflow("random_fact")))
|
|
|
|
self.assertEqual(0, len(self.validate_workflow("study_details")))
|
|
|
|
self.assertEqual(0, len(self.validate_workflow("two_forms")))
|
|
|
|
|
2020-05-07 17:57:24 +00:00
|
|
|
@patch('crc.services.protocol_builder.ProtocolBuilderService.get_investigators') # mock_studies
|
|
|
|
@patch('crc.services.protocol_builder.ProtocolBuilderService.get_required_docs') # mock_docs
|
|
|
|
@patch('crc.services.protocol_builder.ProtocolBuilderService.get_study_details') # mock_details
|
|
|
|
@patch('crc.services.protocol_builder.ProtocolBuilderService.get_studies') # mock_studies
|
2020-05-25 16:29:05 +00:00
|
|
|
def test_successful_validation_of_crc_workflows(self, mock_studies, mock_details, mock_docs, mock_investigators):
|
2020-05-07 17:57:24 +00:00
|
|
|
|
|
|
|
# Mock Protocol Builder responses
|
|
|
|
studies_response = self.protocol_builder_response('user_studies.json')
|
|
|
|
mock_studies.return_value = ProtocolBuilderStudySchema(many=True).loads(studies_response)
|
|
|
|
details_response = self.protocol_builder_response('study_details.json')
|
|
|
|
mock_details.return_value = json.loads(details_response)
|
|
|
|
docs_response = self.protocol_builder_response('required_docs.json')
|
|
|
|
mock_docs.return_value = json.loads(docs_response)
|
|
|
|
investigators_response = self.protocol_builder_response('investigators.json')
|
|
|
|
mock_investigators.return_value = json.loads(investigators_response)
|
|
|
|
|
2020-05-25 16:29:05 +00:00
|
|
|
self.load_example_data(use_crc_data=True)
|
2020-05-27 02:42:49 +00:00
|
|
|
app.config['PB_ENABLED'] = True
|
2020-05-30 22:43:20 +00:00
|
|
|
self.validate_all_loaded_workflows()
|
|
|
|
|
|
|
|
def test_successful_validation_of_rrt_workflows(self):
|
|
|
|
self.load_example_data(use_rrt_data=True)
|
|
|
|
self.validate_all_loaded_workflows()
|
|
|
|
|
|
|
|
def validate_all_loaded_workflows(self):
|
2020-03-27 12:29:31 +00:00
|
|
|
workflows = session.query(WorkflowSpecModel).all()
|
|
|
|
errors = []
|
|
|
|
for w in workflows:
|
|
|
|
rv = self.app.get('/v1.0/workflow-specification/%s/validate' % w.id,
|
|
|
|
headers=self.logged_in_headers())
|
|
|
|
self.assert_success(rv)
|
|
|
|
json_data = json.loads(rv.get_data(as_text=True))
|
|
|
|
errors.extend(ApiErrorSchema(many=True).load(json_data))
|
|
|
|
self.assertEqual(0, len(errors), json.dumps(errors))
|
|
|
|
|
2020-05-30 22:43:20 +00:00
|
|
|
|
2020-03-27 12:29:31 +00:00
|
|
|
def test_invalid_expression(self):
|
2020-05-30 19:37:04 +00:00
|
|
|
self.load_example_data()
|
2020-03-27 12:29:31 +00:00
|
|
|
errors = self.validate_workflow("invalid_expression")
|
2020-05-30 22:43:20 +00:00
|
|
|
self.assertEqual(2, len(errors))
|
2020-06-03 21:34:27 +00:00
|
|
|
self.assertEqual("workflow_validation_exception", errors[0]['code'])
|
2020-04-06 22:15:32 +00:00
|
|
|
self.assertEqual("ExclusiveGateway_003amsm", errors[0]['task_id'])
|
|
|
|
self.assertEqual("Has Bananas Gateway", errors[0]['task_name'])
|
|
|
|
self.assertEqual("invalid_expression.bpmn", errors[0]['file_name'])
|
2020-05-30 22:43:20 +00:00
|
|
|
self.assertEqual('When populating all fields ... ExclusiveGateway_003amsm: Error evaluating expression \'this_value_does_not_exist==true\', '
|
2020-05-11 21:04:05 +00:00
|
|
|
'name \'this_value_does_not_exist\' is not defined', errors[0]["message"])
|
2020-05-30 19:37:04 +00:00
|
|
|
self.assertIsNotNone(errors[0]['task_data'])
|
|
|
|
self.assertIn("has_bananas", errors[0]['task_data'])
|
2020-03-27 12:29:31 +00:00
|
|
|
|
|
|
|
def test_validation_error(self):
|
2020-05-30 19:37:04 +00:00
|
|
|
self.load_example_data()
|
2020-03-27 12:29:31 +00:00
|
|
|
errors = self.validate_workflow("invalid_spec")
|
2020-05-30 22:43:20 +00:00
|
|
|
self.assertEqual(2, len(errors))
|
2020-04-06 22:15:32 +00:00
|
|
|
self.assertEqual("workflow_validation_error", errors[0]['code'])
|
|
|
|
self.assertEqual("StartEvent_1", errors[0]['task_id'])
|
|
|
|
self.assertEqual("invalid_spec.bpmn", errors[0]['file_name'])
|
2020-03-27 12:29:31 +00:00
|
|
|
|
|
|
|
def test_invalid_script(self):
|
2020-05-30 19:37:04 +00:00
|
|
|
self.load_example_data()
|
2020-03-27 12:29:31 +00:00
|
|
|
errors = self.validate_workflow("invalid_script")
|
2020-05-30 22:43:20 +00:00
|
|
|
self.assertEqual(2, len(errors))
|
2020-06-03 21:34:27 +00:00
|
|
|
self.assertEqual("workflow_validation_exception", errors[0]['code'])
|
2020-03-27 12:29:31 +00:00
|
|
|
self.assertTrue("NoSuchScript" in errors[0]['message'])
|
2020-04-06 22:15:32 +00:00
|
|
|
self.assertEqual("Invalid_Script_Task", errors[0]['task_id'])
|
|
|
|
self.assertEqual("An Invalid Script Reference", errors[0]['task_name'])
|
|
|
|
self.assertEqual("invalid_script.bpmn", errors[0]['file_name'])
|
2020-05-30 19:37:04 +00:00
|
|
|
|
|
|
|
def test_repeating_sections_correctly_populated(self):
|
|
|
|
self.load_example_data()
|
|
|
|
spec_model = self.load_test_spec('repeat_form')
|
|
|
|
final_data = WorkflowService.test_spec(spec_model.id)
|
|
|
|
self.assertIsNotNone(final_data)
|
2020-05-30 21:21:57 +00:00
|
|
|
self.assertIn('cats', final_data)
|
|
|
|
|
|
|
|
def test_required_fields(self):
|
|
|
|
self.load_example_data()
|
|
|
|
spec_model = self.load_test_spec('required_fields')
|
|
|
|
final_data = WorkflowService.test_spec(spec_model.id)
|
|
|
|
self.assertIsNotNone(final_data)
|
|
|
|
self.assertIn('string_required', final_data)
|
|
|
|
self.assertIn('string_not_required', final_data)
|
|
|
|
|
|
|
|
final_data = WorkflowService.test_spec(spec_model.id, required_only=True)
|
|
|
|
self.assertIsNotNone(final_data)
|
|
|
|
self.assertIn('string_required', final_data)
|
|
|
|
self.assertNotIn('string_not_required', final_data)
|