2020-02-04 20:44:06 +00:00
import json
2020-03-05 18:25:28 +00:00
import os
2020-05-07 17:57:24 +00:00
import random
2020-04-19 19:14:10 +00:00
from unittest . mock import patch
2020-02-04 20:44:06 +00:00
2020-05-25 16:29:05 +00:00
from tests . base_test import BaseTest
2020-03-05 18:25:28 +00:00
from crc import session , app
2020-05-04 14:57:09 +00:00
from crc . models . api_models import WorkflowApiSchema , MultiInstanceType , TaskSchema
from crc . models . file import FileModelSchema
2020-04-15 15:13:32 +00:00
from crc . models . workflow import WorkflowStatus
2020-07-28 17:33:38 +00:00
from crc . models . task_event import TaskEventModel
2020-02-04 20:44:06 +00:00
2020-03-11 16:35:37 +00:00
2020-07-14 14:29:25 +00:00
class TestTasksApi ( BaseTest ) :
2020-02-04 20:44:06 +00:00
2020-07-13 15:02:29 +00:00
def assert_options_populated ( self , results , lookup_data_keys ) :
option_keys = [ ' value ' , ' label ' , ' data ' ]
self . assertIsInstance ( results , list )
for result in results :
for option_key in option_keys :
self . assertTrue ( option_key in result , ' should have value, label, and data properties populated ' )
self . assertIsNotNone ( result [ option_key ] , ' %s should not be None ' % option_key )
self . assertIsInstance ( result [ ' data ' ] , dict )
for lookup_data_key in lookup_data_keys :
self . assertTrue ( lookup_data_key in result [ ' data ' ] , ' should have all lookup data columns populated ' )
2020-03-19 21:13:30 +00:00
2020-02-04 20:44:06 +00:00
def test_get_current_user_tasks ( self ) :
self . load_example_data ( )
workflow = self . create_workflow ( ' random_fact ' )
2020-05-06 17:01:38 +00:00
workflow = self . get_workflow_api ( workflow )
task = workflow . next_task
2020-05-15 19:54:53 +00:00
self . assertEqual ( " Task_User_Select_Type " , task . name )
self . assertEqual ( 3 , len ( task . form [ " fields " ] [ 0 ] [ " options " ] ) )
self . assertIsNotNone ( task . documentation )
2020-02-21 17:02:35 +00:00
expected_docs = """ # h1 Heading 8-)
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading
2020-02-20 19:35:21 +00:00
"""
2020-05-15 19:54:53 +00:00
self . assertTrue ( str . startswith ( task . documentation , expected_docs ) )
2020-02-04 20:44:06 +00:00
2020-07-28 17:51:29 +00:00
def test_get_workflow_without_running_engine_steps ( self ) :
2020-07-28 17:33:38 +00:00
# Set up a new workflow
workflow = self . create_workflow ( ' two_forms ' )
# get the first form in the two form workflow.
2020-07-28 17:51:29 +00:00
workflow_api = self . get_workflow_api ( workflow , do_engine_steps = False )
2020-07-28 17:33:38 +00:00
# There should be no task event logs related to the workflow at this point.
task_events = session . query ( TaskEventModel ) . filter ( TaskEventModel . workflow_id == workflow . id ) . all ( )
self . assertEqual ( 0 , len ( task_events ) )
# Since the workflow was not started, the call to read-only should not execute any engine steps the
# current task should be the start event.
self . assertEqual ( " Start " , workflow_api . next_task . name )
2020-07-28 17:51:29 +00:00
def test_get_form_for_previously_completed_task ( self ) :
""" Assure we can look at previously completed steps without moving the token for the workflow. """
2020-07-28 17:33:38 +00:00
2020-02-04 20:44:06 +00:00
def test_two_forms_task ( self ) :
# Set up a new workflow
self . load_example_data ( )
workflow = self . create_workflow ( ' two_forms ' )
# get the first form in the two form workflow.
2020-02-07 16:34:44 +00:00
workflow_api = self . get_workflow_api ( workflow )
2020-02-07 17:36:08 +00:00
self . assertEqual ( ' two_forms ' , workflow_api . workflow_spec_id )
2020-12-14 16:27:38 +00:00
self . assertEqual ( 5 , len ( workflow_api . navigation ) )
2020-05-15 19:54:53 +00:00
self . assertIsNotNone ( workflow_api . next_task . form )
self . assertEqual ( " UserTask " , workflow_api . next_task . type )
self . assertEqual ( " StepOne " , workflow_api . next_task . name )
self . assertEqual ( 1 , len ( workflow_api . next_task . form [ ' fields ' ] ) )
2020-02-04 20:44:06 +00:00
# Complete the form for Step one and post it.
2020-05-15 19:54:53 +00:00
self . complete_form ( workflow , workflow_api . next_task , { " color " : " blue " } )
2020-02-04 20:44:06 +00:00
# Get the next Task
2020-02-07 16:34:44 +00:00
workflow_api = self . get_workflow_api ( workflow )
2020-05-15 19:54:53 +00:00
self . assertEqual ( " StepTwo " , workflow_api . next_task . name )
2020-02-04 20:44:06 +00:00
# Get all user Tasks and check that the data have been saved
2020-05-15 19:54:53 +00:00
task = workflow_api . next_task
self . assertIsNotNone ( task . data )
for val in task . data . values ( ) :
self . assertIsNotNone ( val )
2020-02-04 20:44:06 +00:00
def test_error_message_on_bad_gateway_expression ( self ) :
workflow = self . create_workflow ( ' exclusive_gateway ' )
# get the first form in the two form workflow.
2020-05-15 19:54:53 +00:00
task = self . get_workflow_api ( workflow ) . next_task
self . complete_form ( workflow , task , { " has_bananas " : True } )
2020-02-04 20:44:06 +00:00
def test_workflow_with_parallel_forms ( self ) :
workflow = self . create_workflow ( ' exclusive_gateway ' )
# get the first form in the two form workflow.
2020-05-15 19:54:53 +00:00
task = self . get_workflow_api ( workflow ) . next_task
self . complete_form ( workflow , task , { " has_bananas " : True } )
2020-02-04 20:44:06 +00:00
# Get the next Task
2020-02-07 16:34:44 +00:00
workflow_api = self . get_workflow_api ( workflow )
2020-05-15 19:54:53 +00:00
self . assertEqual ( " Task_Num_Bananas " , workflow_api . next_task . name )
2020-02-07 16:34:44 +00:00
2020-05-14 17:43:23 +00:00
def test_navigation_with_parallel_forms ( self ) :
workflow = self . create_workflow ( ' exclusive_gateway ' )
# get the first form in the two form workflow.
workflow_api = self . get_workflow_api ( workflow )
self . assertIsNotNone ( workflow_api . navigation )
2020-05-15 19:54:53 +00:00
nav = workflow_api . navigation
2020-12-14 16:27:38 +00:00
self . assertEqual ( 4 , len ( nav ) )
2020-12-04 22:56:12 +00:00
self . assertEqual ( " Do You Have Bananas " , nav [ 1 ] . description )
self . assertEqual ( " Bananas? " , nav [ 2 ] . description )
2020-12-14 15:07:19 +00:00
self . assertEqual ( " LIKELY " , nav [ 2 ] . state )
self . assertEqual ( " yes " , nav [ 2 ] . children [ 0 ] . description )
self . assertEqual ( " LIKELY " , nav [ 2 ] . children [ 0 ] . state )
self . assertEqual ( " of Bananas " , nav [ 2 ] . children [ 0 ] . children [ 0 ] . description )
self . assertEqual ( " EndEvent " , nav [ 2 ] . children [ 0 ] . children [ 1 ] . spec_type )
self . assertEqual ( " no " , nav [ 2 ] . children [ 1 ] . description )
self . assertEqual ( " MAYBE " , nav [ 2 ] . children [ 1 ] . state )
self . assertEqual ( " no bananas " , nav [ 2 ] . children [ 1 ] . children [ 0 ] . description )
self . assertEqual ( " EndEvent " , nav [ 2 ] . children [ 1 ] . children [ 1 ] . spec_type )
2020-02-11 01:54:22 +00:00
2020-05-16 19:33:06 +00:00
def test_navigation_with_exclusive_gateway ( self ) :
workflow = self . create_workflow ( ' exclusive_gateway_2 ' )
# get the first form in the two form workflow.
workflow_api = self . get_workflow_api ( workflow )
self . assertIsNotNone ( workflow_api . navigation )
nav = workflow_api . navigation
2020-12-14 16:27:38 +00:00
self . assertEqual ( 7 , len ( nav ) )
2020-12-04 22:56:12 +00:00
self . assertEqual ( " Task 1 " , nav [ 1 ] . description )
self . assertEqual ( " Which Branch? " , nav [ 2 ] . description )
2020-12-14 15:07:19 +00:00
self . assertEqual ( " a " , nav [ 2 ] . children [ 0 ] . description )
self . assertEqual ( " Task 2a " , nav [ 2 ] . children [ 0 ] . children [ 0 ] . description )
self . assertEqual ( " b " , nav [ 2 ] . children [ 1 ] . description )
self . assertEqual ( " Task 2b " , nav [ 2 ] . children [ 1 ] . children [ 0 ] . description )
self . assertEqual ( None , nav [ 3 ] . description )
self . assertEqual ( " Task 3 " , nav [ 4 ] . description )
self . assertEqual ( " EndEvent " , nav [ 5 ] . spec_type )
2020-05-16 19:33:06 +00:00
2020-02-11 01:54:22 +00:00
def test_document_added_to_workflow_shows_up_in_file_list ( self ) :
2020-03-19 21:13:30 +00:00
self . create_reference_document ( )
2020-02-11 01:54:22 +00:00
workflow = self . create_workflow ( ' docx ' )
2020-06-12 17:46:10 +00:00
2020-02-11 01:54:22 +00:00
# get the first form in the two form workflow.
2020-05-15 19:54:53 +00:00
task = self . get_workflow_api ( workflow ) . next_task
2020-02-11 01:54:22 +00:00
data = {
" full_name " : " Buck of the Wild " ,
" date " : " 5/1/2020 " ,
" title " : " Leader of the Pack " ,
" company " : " In the company of wolves " ,
" last_name " : " Mr. Wolf "
}
2020-05-15 19:54:53 +00:00
workflow_api = self . complete_form ( workflow , task , data )
2020-02-25 17:01:25 +00:00
self . assertIsNotNone ( workflow_api . next_task )
2020-05-15 19:54:53 +00:00
self . assertEqual ( " EndEvent_0evb22x " , workflow_api . next_task . name )
2020-02-11 01:54:22 +00:00
self . assertTrue ( workflow_api . status == WorkflowStatus . complete )
2020-03-11 19:27:22 +00:00
rv = self . app . get ( ' /v1.0/file?workflow_id= %i ' % workflow . id , headers = self . logged_in_headers ( ) )
2020-02-11 01:54:22 +00:00
self . assert_success ( rv )
json_data = json . loads ( rv . get_data ( as_text = True ) )
files = FileModelSchema ( many = True ) . load ( json_data , session = session )
2020-02-18 15:14:03 +00:00
self . assertTrue ( len ( files ) == 1 )
2020-06-12 17:46:10 +00:00
2020-04-29 20:07:39 +00:00
# Assure we can still delete the study even when there is a file attached to a workflow.
rv = self . app . delete ( ' /v1.0/study/ %i ' % workflow . study_id , headers = self . logged_in_headers ( ) )
self . assert_success ( rv )
2020-02-25 17:01:25 +00:00
def test_get_documentation_populated_in_end ( self ) :
workflow = self . create_workflow ( ' random_fact ' )
workflow_api = self . get_workflow_api ( workflow )
2020-05-06 17:01:38 +00:00
task = workflow_api . next_task
2020-05-15 19:54:53 +00:00
self . assertEqual ( " Task_User_Select_Type " , task . name )
self . assertEqual ( 3 , len ( task . form [ " fields " ] [ 0 ] [ " options " ] ) )
self . assertIsNotNone ( task . documentation )
self . complete_form ( workflow , workflow_api . next_task , { " type " : " norris " } )
2020-02-25 17:01:25 +00:00
workflow_api = self . get_workflow_api ( workflow )
2020-05-15 19:54:53 +00:00
self . assertEqual ( " EndEvent_0u1cgrf " , workflow_api . next_task . name )
self . assertIsNotNone ( workflow_api . next_task . documentation )
self . assertTrue ( " norris " in workflow_api . next_task . documentation )
2020-03-03 18:50:22 +00:00
2020-03-05 18:25:28 +00:00
def test_load_workflow_from_outdated_spec ( self ) :
# Start the basic two_forms workflow and complete a task.
workflow = self . create_workflow ( ' two_forms ' )
workflow_api = self . get_workflow_api ( workflow )
2020-05-15 19:54:53 +00:00
self . complete_form ( workflow , workflow_api . next_task , { " color " : " blue " } )
2020-03-05 21:45:44 +00:00
self . assertTrue ( workflow_api . is_latest_spec )
2020-03-05 18:25:28 +00:00
2020-03-05 20:35:55 +00:00
# Modify the specification, with a major change that alters the flow and can't be deserialized
# effectively, if it uses the latest spec files.
2020-10-05 21:35:35 +00:00
file_path = os . path . join ( app . root_path , ' .. ' , ' tests ' , ' data ' , ' two_forms ' , ' modified ' , ' two_forms_struc_mod.bpmn ' )
2020-03-05 18:25:28 +00:00
self . replace_file ( " two_forms.bpmn " , file_path )
2020-03-05 20:35:55 +00:00
workflow_api = self . get_workflow_api ( workflow )
self . assertTrue ( workflow_api . spec_version . startswith ( " v1 " ) )
2020-03-05 21:45:44 +00:00
self . assertFalse ( workflow_api . is_latest_spec )
2021-01-19 20:34:46 +00:00
workflow_api = self . restart_workflow_api ( workflow_api , clear_data = True )
2020-03-05 21:45:44 +00:00
self . assertTrue ( workflow_api . spec_version . startswith ( " v2 " ) )
self . assertTrue ( workflow_api . is_latest_spec )
2020-03-11 20:33:18 +00:00
2020-04-27 20:08:23 +00:00
# Assure this hard_reset sticks (added this after a bug was found)
workflow_api = self . get_workflow_api ( workflow )
self . assertTrue ( workflow_api . spec_version . startswith ( " v2 " ) )
self . assertTrue ( workflow_api . is_latest_spec )
2020-04-16 15:07:29 +00:00
def test_manual_task_with_external_documentation ( self ) :
workflow = self . create_workflow ( ' manual_task_with_external_documentation ' )
# get the first form in the two form workflow.
2020-05-15 19:54:53 +00:00
task = self . get_workflow_api ( workflow ) . next_task
workflow_api = self . complete_form ( workflow , task , { " name " : " Dan " } )
2020-04-16 15:07:29 +00:00
2020-04-17 17:30:32 +00:00
workflow = self . get_workflow_api ( workflow )
2020-06-05 18:08:46 +00:00
self . assertEqual ( ' Task_Manual_One ' , workflow . next_task . name )
self . assertEqual ( ' ManualTask ' , workflow_api . next_task . type )
2020-05-15 19:54:53 +00:00
self . assertTrue ( ' Markdown ' in workflow_api . next_task . documentation )
self . assertTrue ( ' Dan ' in workflow_api . next_task . documentation )
2020-04-19 19:14:10 +00:00
2020-04-21 16:07:59 +00:00
def test_bpmn_extension_properties_are_populated ( self ) :
workflow = self . create_workflow ( ' manual_task_with_external_documentation ' )
# get the first form in the two form workflow.
2020-05-15 19:54:53 +00:00
task = self . get_workflow_api ( workflow ) . next_task
2020-06-05 18:08:46 +00:00
self . assertEqual ( " JustAValue " , task . properties [ ' JustAKey ' ] )
2020-04-21 16:07:59 +00:00
2020-04-19 19:14:10 +00:00
@patch ( ' crc.services.protocol_builder.requests.get ' )
def test_multi_instance_task ( self , mock_get ) :
2020-05-25 16:29:05 +00:00
self . load_example_data ( )
2020-05-22 18:37:49 +00:00
# Enable the protocol builder.
2020-05-27 02:42:49 +00:00
app . config [ ' PB_ENABLED ' ] = True
2020-05-22 18:37:49 +00:00
2020-04-19 19:14:10 +00:00
# This depends on getting a list of investigators back from the protocol builder.
mock_get . return_value . ok = True
mock_get . return_value . text = self . protocol_builder_response ( ' investigators.json ' )
workflow = self . create_workflow ( ' multi_instance ' )
# get the first form in the two form workflow.
2020-05-15 19:54:53 +00:00
workflow = self . get_workflow_api ( workflow )
navigation = self . get_workflow_api ( workflow ) . navigation
2020-12-14 16:27:38 +00:00
self . assertEqual ( 5 , len ( navigation ) ) # Start task, form_task, multi_task, end task
2020-06-05 18:08:46 +00:00
self . assertEqual ( " UserTask " , workflow . next_task . type )
self . assertEqual ( MultiInstanceType . sequential . value , workflow . next_task . multi_instance_type )
2020-07-07 21:16:33 +00:00
self . assertEqual ( 5 , workflow . next_task . multi_instance_count )
2020-04-19 19:14:10 +00:00
2020-05-14 17:43:23 +00:00
# Assure that the names for each task are properly updated, so they aren't all the same.
2020-08-04 19:50:29 +00:00
self . assertEqual ( " Primary Investigator " , workflow . next_task . title )
2020-05-14 17:43:23 +00:00
2020-04-22 23:40:40 +00:00
def test_lookup_endpoint_for_task_field_enumerations ( self ) :
workflow = self . create_workflow ( ' enum_options_with_search ' )
# get the first form in the two form workflow.
2020-05-06 17:01:38 +00:00
workflow = self . get_workflow_api ( workflow )
task = workflow . next_task
2020-05-15 19:54:53 +00:00
field_id = task . form [ ' fields ' ] [ 0 ] [ ' id ' ]
2021-03-01 19:54:04 +00:00
rv = self . app . get ( ' /v1.0/workflow/ %i /lookup/ %s / %s ?query= %s &limit=5 ' %
( workflow . id , task . name , field_id , ' c ' ) , # All records with a word that starts with 'c'
2020-04-22 23:40:40 +00:00
headers = self . logged_in_headers ( ) ,
content_type = " application/json " )
self . assert_success ( rv )
results = json . loads ( rv . get_data ( as_text = True ) )
self . assertEqual ( 5 , len ( results ) )
2020-07-13 15:02:29 +00:00
self . assert_options_populated ( results , [ ' CUSTOMER_NUMBER ' , ' CUSTOMER_NAME ' , ' CUSTOMER_CLASS_MEANING ' ] )
2020-04-28 17:48:44 +00:00
2020-06-30 14:00:22 +00:00
def test_lookup_endpoint_for_task_field_using_lookup_entry_id ( self ) :
workflow = self . create_workflow ( ' enum_options_with_search ' )
# get the first form in the two form workflow.
workflow = self . get_workflow_api ( workflow )
task = workflow . next_task
field_id = task . form [ ' fields ' ] [ 0 ] [ ' id ' ]
2021-03-01 19:54:04 +00:00
rv = self . app . get ( ' /v1.0/workflow/ %i /lookup/ %s / %s ?query= %s &limit=5 ' %
( workflow . id , task . name , field_id , ' c ' ) , # All records with a word that starts with 'c'
2020-06-30 14:00:22 +00:00
headers = self . logged_in_headers ( ) ,
content_type = " application/json " )
self . assert_success ( rv )
results = json . loads ( rv . get_data ( as_text = True ) )
self . assertEqual ( 5 , len ( results ) )
2020-07-13 15:02:29 +00:00
self . assert_options_populated ( results , [ ' CUSTOMER_NUMBER ' , ' CUSTOMER_NAME ' , ' CUSTOMER_CLASS_MEANING ' ] )
2021-03-01 19:54:04 +00:00
rv = self . app . get ( ' /v1.0/workflow/ %i /lookup/ %s / %s ?value= %s ' %
( workflow . id , task . name , field_id , results [ 0 ] [ ' value ' ] ) , # All records with a word that starts with 'c'
2020-06-30 14:00:22 +00:00
headers = self . logged_in_headers ( ) ,
content_type = " application/json " )
results = json . loads ( rv . get_data ( as_text = True ) )
self . assertEqual ( 1 , len ( results ) )
2020-07-13 15:02:29 +00:00
self . assert_options_populated ( results , [ ' CUSTOMER_NUMBER ' , ' CUSTOMER_NAME ' , ' CUSTOMER_CLASS_MEANING ' ] )
2020-06-30 14:34:16 +00:00
self . assertNotIn ( ' id ' , results [ 0 ] , " Don ' t include the internal id, that can be very confusing, and should not be used. " )
def test_lookup_endpoint_also_works_for_enum ( self ) :
# Naming here get's a little confusing. fields can be marked as enum or autocomplete.
# In the event of an auto-complete it's a type-ahead search field, for an enum the
# the key/values from the spreadsheet are added directly to the form and it shows up as
# a dropdown. This tests the case of wanting to get additional data when a user selects
2020-07-13 15:02:29 +00:00
# something from a dropdown.
2020-06-30 14:34:16 +00:00
workflow = self . create_workflow ( ' enum_options_from_file ' )
# get the first form in the two form workflow.
workflow = self . get_workflow_api ( workflow )
task = workflow . next_task
field_id = task . form [ ' fields ' ] [ 0 ] [ ' id ' ]
option_id = task . form [ ' fields ' ] [ 0 ] [ ' options ' ] [ 0 ] [ ' id ' ]
2021-03-01 19:54:04 +00:00
rv = self . app . get ( ' /v1.0/workflow/ %i /lookup/ %s / %s ?value= %s ' %
( workflow . id , task . name , field_id , option_id ) , # All records with a word that starts with 'c'
2020-06-30 14:34:16 +00:00
headers = self . logged_in_headers ( ) ,
content_type = " application/json " )
self . assert_success ( rv )
results = json . loads ( rv . get_data ( as_text = True ) )
self . assertEqual ( 1 , len ( results ) )
2020-07-13 15:02:29 +00:00
self . assert_options_populated ( results , [ ' CUSTOMER_NUMBER ' , ' CUSTOMER_NAME ' , ' CUSTOMER_CLASS_MEANING ' ] )
2020-06-30 14:34:16 +00:00
self . assertIsInstance ( results [ 0 ] [ ' data ' ] , dict )
2020-06-30 14:00:22 +00:00
2020-07-14 15:38:48 +00:00
def test_enum_from_task_data ( self ) :
2020-07-13 21:46:28 +00:00
workflow = self . create_workflow ( ' enum_options_from_task_data ' )
# get the first form in the two form workflow.
workflow_api = self . get_workflow_api ( workflow )
task = workflow_api . next_task
workflow_api = self . complete_form ( workflow , task , { ' invitees ' : [
{ ' first_name ' : ' Alistair ' , ' last_name ' : ' Aardvark ' , ' age ' : 43 , ' likes_pie ' : True , ' num_lumps ' : 21 , ' secret_id ' : ' Antimony ' , ' display_name ' : ' Professor Alistair A. Aardvark ' } ,
{ ' first_name ' : ' Berthilda ' , ' last_name ' : ' Binturong ' , ' age ' : 12 , ' likes_pie ' : False , ' num_lumps ' : 34 , ' secret_id ' : ' Beryllium ' , ' display_name ' : ' Dr. Berthilda B. Binturong ' } ,
{ ' first_name ' : ' Chesterfield ' , ' last_name ' : ' Capybara ' , ' age ' : 32 , ' likes_pie ' : True , ' num_lumps ' : 1 , ' secret_id ' : ' Cadmium ' , ' display_name ' : ' The Honorable C. C. Capybara ' } ,
] } )
task = workflow_api . next_task
field_id = task . form [ ' fields ' ] [ 0 ] [ ' id ' ]
options = task . form [ ' fields ' ] [ 0 ] [ ' options ' ]
self . assertEqual ( 3 , len ( options ) )
option_id = options [ 0 ] [ ' id ' ]
self . assertEqual ( ' Professor Alistair A. Aardvark ' , options [ 0 ] [ ' name ' ] )
self . assertEqual ( ' Dr. Berthilda B. Binturong ' , options [ 1 ] [ ' name ' ] )
self . assertEqual ( ' The Honorable C. C. Capybara ' , options [ 2 ] [ ' name ' ] )
self . assertEqual ( ' Alistair ' , options [ 0 ] [ ' data ' ] [ ' first_name ' ] )
self . assertEqual ( ' Berthilda ' , options [ 1 ] [ ' data ' ] [ ' first_name ' ] )
self . assertEqual ( ' Chesterfield ' , options [ 2 ] [ ' data ' ] [ ' first_name ' ] )
2020-05-19 20:11:43 +00:00
def test_lookup_endpoint_for_task_ldap_field_lookup ( self ) :
workflow = self . create_workflow ( ' ldap_lookup ' )
# get the first form
workflow = self . get_workflow_api ( workflow )
task = workflow . next_task
field_id = task . form [ ' fields ' ] [ 0 ] [ ' id ' ]
# lb3dp is a user record in the mock ldap responses for tests.
2021-03-01 19:54:04 +00:00
rv = self . app . get ( ' /v1.0/workflow/ %s /lookup/ %s / %s ?query= %s &limit=5 ' %
( workflow . id , task . name , field_id , ' lb3dp ' ) ,
2020-05-19 20:11:43 +00:00
headers = self . logged_in_headers ( ) ,
content_type = " application/json " )
self . assert_success ( rv )
results = json . loads ( rv . get_data ( as_text = True ) )
2020-07-13 15:02:29 +00:00
self . assert_options_populated ( results , [ ' telephone_number ' , ' affiliation ' , ' uid ' , ' title ' ,
' given_name ' , ' department ' , ' date_cached ' , ' sponsor_type ' ,
' display_name ' , ' email_address ' ] )
2020-05-19 20:11:43 +00:00
self . assertEqual ( 1 , len ( results ) )
2020-05-11 21:04:05 +00:00
2020-04-28 17:48:44 +00:00
def test_sub_process ( self ) :
workflow = self . create_workflow ( ' subprocess ' )
2020-05-15 19:54:53 +00:00
workflow_api = self . get_workflow_api ( workflow )
navigation = workflow_api . navigation
task = workflow_api . next_task
2020-12-14 16:27:38 +00:00
self . assertEqual ( 5 , len ( navigation ) )
2020-06-05 18:08:46 +00:00
self . assertEqual ( " UserTask " , task . type )
self . assertEqual ( " Activity_A " , task . name )
self . assertEqual ( " My Sub Process " , task . process_name )
2020-06-19 12:22:53 +00:00
workflow_api = self . complete_form ( workflow , task , { " FieldA " : " Dan " } )
2020-05-15 19:54:53 +00:00
task = workflow_api . next_task
2020-04-28 17:48:44 +00:00
self . assertIsNotNone ( task )
2020-06-05 18:08:46 +00:00
self . assertEqual ( " Activity_B " , task . name )
self . assertEqual ( " Sub Workflow Example " , task . process_name )
2020-06-19 12:22:53 +00:00
workflow_api = self . complete_form ( workflow , task , { " FieldB " : " Dan " } )
2020-06-05 18:08:46 +00:00
self . assertEqual ( WorkflowStatus . complete , workflow_api . status )
2020-04-28 17:48:44 +00:00
2020-04-28 21:25:53 +00:00
def test_update_task_resets_token ( self ) :
workflow = self . create_workflow ( ' exclusive_gateway ' )
# Start the workflow.
2020-05-15 19:54:53 +00:00
first_task = self . get_workflow_api ( workflow ) . next_task
self . complete_form ( workflow , first_task , { " has_bananas " : True } )
2020-04-28 21:25:53 +00:00
workflow = self . get_workflow_api ( workflow )
2020-06-05 18:08:46 +00:00
self . assertEqual ( ' Task_Num_Bananas ' , workflow . next_task . name )
2020-04-28 21:25:53 +00:00
# Trying to re-submit the initial task, and answer differently, should result in an error.
2020-05-15 19:54:53 +00:00
self . complete_form ( workflow , first_task , { " has_bananas " : False } , error_code = " invalid_state " )
2020-04-28 21:25:53 +00:00
2020-05-04 14:57:09 +00:00
# Go ahead and set the number of bananas.
workflow = self . get_workflow_api ( workflow )
2020-05-15 19:54:53 +00:00
task = workflow . next_task
2020-05-04 14:57:09 +00:00
self . complete_form ( workflow , task , { " num_bananas " : 4 } )
# We are now at the end of the workflow.
2020-04-28 21:25:53 +00:00
# Make the old task the current task.
2020-05-15 19:54:53 +00:00
rv = self . app . put ( ' /v1.0/workflow/ %i /task/ %s /set_token ' % ( workflow . id , first_task . id ) ,
2020-04-28 21:25:53 +00:00
headers = self . logged_in_headers ( ) ,
content_type = " application/json " )
self . assert_success ( rv )
json_data = json . loads ( rv . get_data ( as_text = True ) )
workflow = WorkflowApiSchema ( ) . load ( json_data )
2020-05-15 19:54:53 +00:00
# Assure the Next Task is the one we just reset the token to be on.
2020-06-05 18:08:46 +00:00
self . assertEqual ( " Task_Has_Bananas " , workflow . next_task . name )
2020-05-04 14:57:09 +00:00
# Go ahead and get that workflow one more time, it should still be right.
workflow = self . get_workflow_api ( workflow )
2020-05-15 19:54:53 +00:00
# Assure the Next Task is the one we just reset the token to be on.
2020-06-05 18:08:46 +00:00
self . assertEqual ( " Task_Has_Bananas " , workflow . next_task . name )
2020-05-04 14:57:09 +00:00
2020-04-28 21:25:53 +00:00
# The next task should be a different value.
2020-05-15 19:54:53 +00:00
self . complete_form ( workflow , workflow . next_task , { " has_bananas " : False } )
2020-04-28 21:25:53 +00:00
workflow = self . get_workflow_api ( workflow )
2020-06-05 18:08:46 +00:00
self . assertEqual ( ' Task_Why_No_Bananas ' , workflow . next_task . name )
2020-05-04 14:57:09 +00:00
2020-05-06 14:59:49 +00:00
@patch ( ' crc.services.protocol_builder.requests.get ' )
def test_parallel_multi_instance ( self , mock_get ) :
2020-05-07 17:57:24 +00:00
# Assure we get nine investigators back from the API Call, as set in the investigators.json file.
2020-05-27 02:42:49 +00:00
app . config [ ' PB_ENABLED ' ] = True
2020-05-06 14:59:49 +00:00
mock_get . return_value . ok = True
mock_get . return_value . text = self . protocol_builder_response ( ' investigators.json ' )
self . load_example_data ( )
2020-05-25 16:29:05 +00:00
2020-05-06 14:59:49 +00:00
workflow = self . create_workflow ( ' multi_instance_parallel ' )
2020-05-15 19:54:53 +00:00
workflow_api = self . get_workflow_api ( workflow )
2020-12-14 16:27:38 +00:00
self . assertEqual ( 9 , len ( workflow_api . navigation ) )
2020-12-04 22:56:12 +00:00
ready_items = [ nav for nav in workflow_api . navigation if nav . state == " READY " ]
2020-07-07 21:16:33 +00:00
self . assertEqual ( 5 , len ( ready_items ) )
2020-05-15 19:54:53 +00:00
2020-06-05 18:08:46 +00:00
self . assertEqual ( " UserTask " , workflow_api . next_task . type )
2020-06-26 16:31:15 +00:00
self . assertEqual ( " MultiInstanceTask " , workflow_api . next_task . name )
2020-07-06 16:09:21 +00:00
self . assertEqual ( " Primary Investigator " , workflow_api . next_task . title )
2020-05-06 14:59:49 +00:00
2020-07-07 21:16:33 +00:00
for i in random . sample ( range ( 5 ) , 5 ) :
2020-12-04 22:56:12 +00:00
task_id = ready_items [ i ] . task_id
rv = self . app . put ( ' /v1.0/workflow/ %i /task/ %s /set_token ' % ( workflow . id , task_id ) ,
2020-07-06 16:09:21 +00:00
headers = self . logged_in_headers ( ) ,
content_type = " application/json " )
self . assert_success ( rv )
json_data = json . loads ( rv . get_data ( as_text = True ) )
workflow = WorkflowApiSchema ( ) . load ( json_data )
data = workflow . next_task . data
2020-06-19 12:22:53 +00:00
data [ ' investigator ' ] [ ' email ' ] = " dhf8r@virginia.edu "
2020-12-04 22:56:12 +00:00
self . complete_form ( workflow , workflow . next_task , data )
2020-05-14 21:13:47 +00:00
#tasks = self.get_workflow_api(workflow).user_tasks
2020-05-06 14:59:49 +00:00
workflow = self . get_workflow_api ( workflow )
2020-06-05 18:08:46 +00:00
self . assertEqual ( WorkflowStatus . complete , workflow . status )
2020-05-04 14:57:09 +00:00
2020-07-28 17:33:38 +00:00