commit
328de0e584
|
@ -19,6 +19,14 @@ def join_uuids(uuids):
|
|||
return hashlib.md5(combined_uuids.encode('utf8')).hexdigest() # make a hash of the hashes
|
||||
|
||||
def verify_token(token, required_scopes):
|
||||
"""
|
||||
Part of the Swagger API permissions for the syncing API
|
||||
The env variable for this is defined in config/default.py
|
||||
|
||||
If you are 'playing' with the swagger interface, you will want to copy the
|
||||
token that is defined there and use it to authenticate the API if you are
|
||||
emulating copying files between systems.
|
||||
"""
|
||||
if token == app.config['API_TOKEN']:
|
||||
return {'scope':['any']}
|
||||
else:
|
||||
|
@ -95,20 +103,44 @@ def get_changed_workflows(remote,as_df=False):
|
|||
|
||||
|
||||
def sync_all_changed_workflows(remote):
|
||||
|
||||
"""
|
||||
Does what it says, gets a list of all workflows that are different between
|
||||
two systems and pulls all of the workflows and files that are different on the
|
||||
remote system. The idea is that we can make the local system 'look' like the remote
|
||||
system for deployment or testing.
|
||||
"""
|
||||
workflowsdf = get_changed_workflows(remote,as_df=True)
|
||||
if len(workflowsdf) ==0:
|
||||
return []
|
||||
workflows = workflowsdf.reset_index().to_dict(orient='records')
|
||||
for workflow in workflows:
|
||||
sync_changed_files(remote,workflow['workflow_spec_id'])
|
||||
sync_changed_files(remote,'REFERENCE_FILES')
|
||||
return [x['workflow_spec_id'] for x in workflows]
|
||||
|
||||
|
||||
def sync_changed_files(remote,workflow_spec_id):
|
||||
# make sure that spec is local before syncing files
|
||||
def file_get(workflow_spec_id,filename):
|
||||
"""
|
||||
Helper function to take care of the special case where we
|
||||
are looking for files that are marked is_reference
|
||||
"""
|
||||
if workflow_spec_id == 'REFERENCE_FILES':
|
||||
currentfile = session.query(FileModel).filter(FileModel.is_reference == True,
|
||||
FileModel.name == filename).first()
|
||||
else:
|
||||
currentfile = session.query(FileModel).filter(FileModel.workflow_spec_id==workflow_spec_id,
|
||||
FileModel.name == filename).first()
|
||||
return currentfile
|
||||
|
||||
specdict = WorkflowSyncService.get_remote_workflow_spec(remote,workflow_spec_id)
|
||||
def create_or_update_local_spec(remote,workflow_spec_id):
|
||||
specdict = WorkflowSyncService.get_remote_workflow_spec(remote, workflow_spec_id)
|
||||
# if we are updating from a master spec, then we want to make sure it is the only
|
||||
# master spec in our local system.
|
||||
if specdict['is_master_spec']:
|
||||
masterspecs = session.query(WorkflowSpecModel).filter(WorkflowSpecModel.is_master_spec == True).all()
|
||||
for masterspec in masterspecs:
|
||||
masterspec.is_master_spec = False
|
||||
session.add(masterspec)
|
||||
|
||||
localspec = session.query(WorkflowSpecModel).filter(WorkflowSpecModel.id == workflow_spec_id).first()
|
||||
if localspec is None:
|
||||
|
@ -120,7 +152,7 @@ def sync_changed_files(remote,workflow_spec_id):
|
|||
localcategory = session.query(WorkflowSpecCategoryModel).filter(WorkflowSpecCategoryModel.name
|
||||
== specdict['category']['name']).first()
|
||||
if localcategory == None:
|
||||
#category doesn't exist - lets make it
|
||||
# category doesn't exist - lets make it
|
||||
localcategory = WorkflowSpecCategoryModel()
|
||||
localcategory.name = specdict['category']['name']
|
||||
localcategory.display_name = specdict['category']['display_name']
|
||||
|
@ -131,9 +163,45 @@ def sync_changed_files(remote,workflow_spec_id):
|
|||
localspec.display_order = specdict['display_order']
|
||||
localspec.display_name = specdict['display_name']
|
||||
localspec.name = specdict['name']
|
||||
localspec.is_master_spec = specdict['is_master_spec']
|
||||
localspec.description = specdict['description']
|
||||
session.add(localspec)
|
||||
|
||||
def update_or_create_current_file(remote,workflow_spec_id,updatefile):
|
||||
currentfile = file_get(workflow_spec_id, updatefile['filename'])
|
||||
if not currentfile:
|
||||
currentfile = FileModel()
|
||||
currentfile.name = updatefile['filename']
|
||||
if workflow_spec_id == 'REFERENCE_FILES':
|
||||
currentfile.workflow_spec_id = None
|
||||
currentfile.is_reference = True
|
||||
else:
|
||||
currentfile.workflow_spec_id = workflow_spec_id
|
||||
|
||||
currentfile.date_created = updatefile['date_created']
|
||||
currentfile.type = updatefile['type']
|
||||
currentfile.primary = updatefile['primary']
|
||||
currentfile.content_type = updatefile['content_type']
|
||||
currentfile.primary_process_id = updatefile['primary_process_id']
|
||||
session.add(currentfile)
|
||||
content = WorkflowSyncService.get_remote_file_by_hash(remote, updatefile['md5_hash'])
|
||||
FileService.update_file(currentfile, content, updatefile['type'])
|
||||
|
||||
|
||||
def sync_changed_files(remote,workflow_spec_id):
|
||||
"""
|
||||
This grabs a list of all files for a workflow_spec that are different between systems,
|
||||
and gets the remote copy of any file that has changed
|
||||
|
||||
We also have a special case for "REFERENCE_FILES" where there is not workflow_spec_id,
|
||||
but all of the files are marked in the database as is_reference - and they need to be
|
||||
handled slightly differently.
|
||||
"""
|
||||
# make sure that spec is local before syncing files
|
||||
if workflow_spec_id != 'REFERENCE_FILES':
|
||||
create_or_update_local_spec(remote,workflow_spec_id)
|
||||
|
||||
|
||||
changedfiles = get_changed_files(remote,workflow_spec_id,as_df=True)
|
||||
if len(changedfiles)==0:
|
||||
return []
|
||||
|
@ -144,8 +212,7 @@ def sync_changed_files(remote,workflow_spec_id):
|
|||
deletefiles = deletefiles.reset_index().to_dict(orient='records')
|
||||
|
||||
for delfile in deletefiles:
|
||||
currentfile = session.query(FileModel).filter(FileModel.workflow_spec_id==workflow_spec_id,
|
||||
FileModel.name == delfile['filename']).first()
|
||||
currentfile = file_get(workflow_spec_id,delfile['filename'])
|
||||
|
||||
# it is more appropriate to archive the file than delete
|
||||
# due to the fact that we might have workflows that are using the
|
||||
|
@ -154,21 +221,7 @@ def sync_changed_files(remote,workflow_spec_id):
|
|||
session.add(currentfile)
|
||||
|
||||
for updatefile in updatefiles:
|
||||
currentfile = session.query(FileModel).filter(FileModel.workflow_spec_id==workflow_spec_id,
|
||||
FileModel.name == updatefile['filename']).first()
|
||||
if not currentfile:
|
||||
currentfile = FileModel()
|
||||
currentfile.name = updatefile['filename']
|
||||
currentfile.workflow_spec_id = workflow_spec_id
|
||||
|
||||
currentfile.date_created = updatefile['date_created']
|
||||
currentfile.type = updatefile['type']
|
||||
currentfile.primary = updatefile['primary']
|
||||
currentfile.content_type = updatefile['content_type']
|
||||
currentfile.primary_process_id = updatefile['primary_process_id']
|
||||
session.add(currentfile)
|
||||
content = WorkflowSyncService.get_remote_file_by_hash(remote,updatefile['md5_hash'])
|
||||
FileService.update_file(currentfile,content,updatefile['type'])
|
||||
update_or_create_current_file(remote,workflow_spec_id,updatefile)
|
||||
session.commit()
|
||||
return [x['filename'] for x in updatefiles]
|
||||
|
||||
|
@ -185,6 +238,13 @@ def get_changed_files(remote,workflow_spec_id,as_df=False):
|
|||
local = get_workflow_spec_files_dataframe(workflow_spec_id).reset_index()
|
||||
local['md5_hash'] = local['md5_hash'].astype('str')
|
||||
remote_files['md5_hash'] = remote_files['md5_hash'].astype('str')
|
||||
if len(local) == 0:
|
||||
remote_files['new'] = True
|
||||
remote_files['location'] = 'remote'
|
||||
if as_df:
|
||||
return remote_files
|
||||
else:
|
||||
return remote_files.reset_index().to_dict(orient='records')
|
||||
|
||||
different = remote_files.merge(local,
|
||||
right_on=['filename','md5_hash'],
|
||||
|
@ -259,8 +319,14 @@ def get_workflow_spec_files_dataframe(workflowid):
|
|||
Return a list of all files for a workflow_spec along with last updated date and a
|
||||
hash so we can determine file differences for a changed workflow on a box.
|
||||
Return a dataframe
|
||||
|
||||
In the special case of "REFERENCE_FILES" we get all of the files that are
|
||||
marked as is_reference
|
||||
"""
|
||||
x = session.query(FileDataModel).join(FileModel).filter(FileModel.workflow_spec_id==workflowid)
|
||||
if workflowid == 'REFERENCE_FILES':
|
||||
x = session.query(FileDataModel).join(FileModel).filter(FileModel.is_reference == True)
|
||||
else:
|
||||
x = session.query(FileDataModel).join(FileModel).filter(FileModel.workflow_spec_id == workflowid)
|
||||
# there might be a cleaner way of getting a data frome from some of the
|
||||
# fields in the ORM - but this works OK
|
||||
filelist = []
|
||||
|
@ -306,7 +372,10 @@ def get_all_spec_state_dataframe():
|
|||
'md5_hash':file.md5_hash,
|
||||
'filename':file.file_model.name,
|
||||
'date_created':file.date_created})
|
||||
df = pd.DataFrame(filelist)
|
||||
if len(filelist) == 0:
|
||||
df = pd.DataFrame(columns=['file_model_id','workflow_spec_id','md5_hash','filename','date_created'])
|
||||
else:
|
||||
df = pd.DataFrame(filelist)
|
||||
|
||||
# If the file list is empty, return an empty data frame
|
||||
if df.empty:
|
||||
|
|
|
@ -108,6 +108,12 @@ class WorkflowService(object):
|
|||
task_api = WorkflowService.spiff_task_to_api_task(
|
||||
task,
|
||||
add_docs_and_forms=True) # Assure we try to process the documentation, and raise those errors.
|
||||
# make sure forms have a form key
|
||||
if hasattr(task_api, 'form') and task_api.form is not None and task_api.form.key == '':
|
||||
raise ApiError(code='missing_form_key',
|
||||
message='Forms must include a Form Key.',
|
||||
task_id=task.id,
|
||||
task_name=task.get_name())
|
||||
WorkflowService.populate_form_with_random_data(task, task_api, required_only)
|
||||
processor.complete_task(task)
|
||||
except WorkflowException as we:
|
||||
|
@ -153,8 +159,12 @@ class WorkflowService(object):
|
|||
if WorkflowService.evaluate_property(Task.FIELD_PROP_HIDE_EXPRESSION, field, task):
|
||||
continue
|
||||
|
||||
# If there is a default value, set it.
|
||||
if hasattr(field,'default_value') and field.default_value:
|
||||
# A task should only have default_value **or** value expression, not both.
|
||||
if field.has_property(Task.FIELD_PROP_VALUE_EXPRESSION) and (hasattr(field, 'default_value') and field.default_value):
|
||||
raise ApiError(code='default value and value_expression',
|
||||
message='This task has both a default_value and value_expression. Please fix this to only have one or the other.')
|
||||
# If we have a default_value or value_expression, try to set the default
|
||||
if field.has_property(Task.FIELD_PROP_VALUE_EXPRESSION) or (hasattr(field, 'default_value') and field.default_value):
|
||||
form_data[field.id] = WorkflowService.get_default_value(field, task)
|
||||
|
||||
# If we are only populating required fields, and this isn't required. stop here.
|
||||
|
@ -488,6 +498,9 @@ class WorkflowService(object):
|
|||
task.form = spiff_task.task_spec.form
|
||||
for i, field in enumerate(task.form.fields):
|
||||
task.form.fields[i] = WorkflowService.process_options(spiff_task, field)
|
||||
# If there is a default value, set it.
|
||||
if field.id not in task.data and WorkflowService.get_default_value(field, spiff_task) is not None:
|
||||
task.data[field.id] = WorkflowService.get_default_value(field, spiff_task)
|
||||
task.documentation = WorkflowService._process_documentation(spiff_task)
|
||||
|
||||
# All ready tasks should have a valid name, and this can be computed for
|
||||
|
|
|
@ -39,7 +39,7 @@ class WorkflowSyncService(object):
|
|||
try:
|
||||
response = requests.get(url,headers={'X-CR-API-KEY':app.config['API_TOKEN']})
|
||||
except:
|
||||
raise ApiError("workflow_sync_error",response.text)
|
||||
raise ApiError("workflow_sync_error",url)
|
||||
if response.ok and response.text:
|
||||
if return_contents:
|
||||
return response.content
|
||||
|
|
|
@ -134,6 +134,15 @@ class BaseTest(unittest.TestCase):
|
|||
|
||||
return dict(Authorization='Bearer ' + user_model.encode_auth_token().decode())
|
||||
|
||||
def delete_example_data(self, use_crc_data=False, use_rrt_data=False):
|
||||
"""
|
||||
delete everything that matters in the local database - this is used to
|
||||
test ground zero copy of workflow specs.
|
||||
"""
|
||||
session.execute("delete from workflow; delete from file_data; delete from file; delete from workflow_spec;")
|
||||
session.commit()
|
||||
|
||||
|
||||
def load_example_data(self, use_crc_data=False, use_rrt_data=False):
|
||||
"""use_crc_data will cause this to load the mammoth collection of documents
|
||||
we built up developing crc, use_rrt_data will do the same for hte rrt project,
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd" xmlns:biodi="http://bpmn.io/schema/dmn/biodi/1.0" id="Definitions_4ddf19d" name="DRD" namespace="http://camunda.org/schema/1.0/dmn">
|
||||
<decision id="Decision_Value_Expression" name="Decision 1">
|
||||
<extensionElements>
|
||||
<biodi:bounds x="157" y="81" width="180" height="80" />
|
||||
</extensionElements>
|
||||
<decisionTable id="decisionTable_1">
|
||||
<input id="input_1" label="User Input">
|
||||
<inputExpression id="inputExpression_1" typeRef="boolean">
|
||||
<text>user_input</text>
|
||||
</inputExpression>
|
||||
</input>
|
||||
<output id="output_1" label="Lookup Output" name="lookup_output" typeRef="string" />
|
||||
<rule id="DecisionRule_1y5u0zy">
|
||||
<inputEntry id="UnaryTests_10u8r2i">
|
||||
<text>True</text>
|
||||
</inputEntry>
|
||||
<outputEntry id="LiteralExpression_1dshav8">
|
||||
<text>'black'</text>
|
||||
</outputEntry>
|
||||
</rule>
|
||||
<rule id="DecisionRule_0pnsbfu">
|
||||
<inputEntry id="UnaryTests_1lasqlz">
|
||||
<text>False</text>
|
||||
</inputEntry>
|
||||
<outputEntry id="LiteralExpression_1nrtq17">
|
||||
<text>'white'</text>
|
||||
</outputEntry>
|
||||
</rule>
|
||||
<rule id="DecisionRule_0ujcwwp">
|
||||
<inputEntry id="UnaryTests_139wk1t">
|
||||
<text></text>
|
||||
</inputEntry>
|
||||
<outputEntry id="LiteralExpression_0emea64">
|
||||
<text>'grey'</text>
|
||||
</outputEntry>
|
||||
</rule>
|
||||
</decisionTable>
|
||||
</decision>
|
||||
</definitions>
|
|
@ -0,0 +1,95 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_889ace0" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
|
||||
<bpmn:process id="Process_a7f16c2" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_02xzhf3</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="Flow_02xzhf3" sourceRef="StartEvent_1" targetRef="Activity_UserInput" />
|
||||
<bpmn:sequenceFlow id="Flow_0d46qnz" sourceRef="Activity_UserInput" targetRef="Activity_DecisionLookup" />
|
||||
<bpmn:sequenceFlow id="Flow_1d7sv9v" sourceRef="Activity_DecisionLookup" targetRef="Activity_PickColor" />
|
||||
<bpmn:userTask id="Activity_UserInput" name="User Input" camunda:formKey="UserInput">
|
||||
<bpmn:extensionElements>
|
||||
<camunda:formData>
|
||||
<camunda:formField id="user_input" label="Select Yes or No" type="boolean" defaultValue="True" />
|
||||
</camunda:formData>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_02xzhf3</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0d46qnz</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
<bpmn:businessRuleTask id="Activity_DecisionLookup" name="Decision Lookup" camunda:resultVariable="lookup_output" camunda:decisionRef="Decision_Value_Expression">
|
||||
<bpmn:incoming>Flow_0d46qnz</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1d7sv9v</bpmn:outgoing>
|
||||
</bpmn:businessRuleTask>
|
||||
<bpmn:userTask id="Activity_PickColor" name="Pick a Color" camunda:formKey="MyFormKey">
|
||||
<bpmn:documentation><h1>Hello {{ lookup_output }}</h1></bpmn:documentation>
|
||||
<bpmn:extensionElements>
|
||||
<camunda:formData>
|
||||
<camunda:formField id="color_select" label="Pick a color" type="enum">
|
||||
<camunda:properties>
|
||||
<camunda:property id="value_expression" value="lookup_output" />
|
||||
</camunda:properties>
|
||||
<camunda:value id="black" name="Black" />
|
||||
<camunda:value id="white" name="White" />
|
||||
<camunda:value id="grey" name="Grey" />
|
||||
<camunda:value id="gray" name="Gray" />
|
||||
</camunda:formField>
|
||||
</camunda:formData>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_1d7sv9v</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_01x96w8</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
<bpmn:sequenceFlow id="Flow_01x96w8" sourceRef="Activity_PickColor" targetRef="Activity_Display_Color" />
|
||||
<bpmn:manualTask id="Activity_Display_Color" name="Display Color">
|
||||
<bpmn:documentation><h1>Hello</h1>
|
||||
<div>You picked {{ color_select.label }}</div></bpmn:documentation>
|
||||
<bpmn:incoming>Flow_01x96w8</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_05tzoiy</bpmn:outgoing>
|
||||
</bpmn:manualTask>
|
||||
<bpmn:endEvent id="Event_074ypt0">
|
||||
<bpmn:incoming>Flow_05tzoiy</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_05tzoiy" sourceRef="Activity_Display_Color" targetRef="Event_074ypt0" />
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_a7f16c2">
|
||||
<bpmndi:BPMNEdge id="Flow_05tzoiy_di" bpmnElement="Flow_05tzoiy">
|
||||
<di:waypoint x="850" y="177" />
|
||||
<di:waypoint x="912" y="177" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_01x96w8_di" bpmnElement="Flow_01x96w8">
|
||||
<di:waypoint x="690" y="177" />
|
||||
<di:waypoint x="750" y="177" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1d7sv9v_di" bpmnElement="Flow_1d7sv9v">
|
||||
<di:waypoint x="530" y="177" />
|
||||
<di:waypoint x="590" y="177" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0d46qnz_di" bpmnElement="Flow_0d46qnz">
|
||||
<di:waypoint x="370" y="177" />
|
||||
<di:waypoint x="430" y="177" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_02xzhf3_di" bpmnElement="Flow_02xzhf3">
|
||||
<di:waypoint x="215" y="177" />
|
||||
<di:waypoint x="270" y="177" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="159" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0xfaikf_di" bpmnElement="Activity_UserInput">
|
||||
<dc:Bounds x="270" y="137" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_16u20va_di" bpmnElement="Activity_DecisionLookup">
|
||||
<dc:Bounds x="430" y="137" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0dpzpf2_di" bpmnElement="Activity_PickColor">
|
||||
<dc:Bounds x="590" y="137" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_157v5xp_di" bpmnElement="Activity_Display_Color">
|
||||
<dc:Bounds x="750" y="137" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_074ypt0_di" bpmnElement="Event_074ypt0">
|
||||
<dc:Bounds x="912" y="159" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd" xmlns:biodi="http://bpmn.io/schema/dmn/biodi/1.0" id="Definitions_4ddf19d" name="DRD" namespace="http://camunda.org/schema/1.0/dmn">
|
||||
<decision id="Decision_Value_Expression" name="Decision 1">
|
||||
<extensionElements>
|
||||
<biodi:bounds x="157" y="81" width="180" height="80" />
|
||||
</extensionElements>
|
||||
<decisionTable id="decisionTable_1">
|
||||
<input id="input_1" label="User Input">
|
||||
<inputExpression id="inputExpression_1" typeRef="boolean">
|
||||
<text>user_input</text>
|
||||
</inputExpression>
|
||||
</input>
|
||||
<output id="output_1" label="Lookup Output" name="lookup_output" typeRef="string" />
|
||||
<rule id="DecisionRule_1y5u0zy">
|
||||
<inputEntry id="UnaryTests_10u8r2i">
|
||||
<text>True</text>
|
||||
</inputEntry>
|
||||
<outputEntry id="LiteralExpression_1dshav8">
|
||||
<text>'black'</text>
|
||||
</outputEntry>
|
||||
</rule>
|
||||
<rule id="DecisionRule_0pnsbfu">
|
||||
<inputEntry id="UnaryTests_1lasqlz">
|
||||
<text>False</text>
|
||||
</inputEntry>
|
||||
<outputEntry id="LiteralExpression_1nrtq17">
|
||||
<text>'white'</text>
|
||||
</outputEntry>
|
||||
</rule>
|
||||
<rule id="DecisionRule_0ujcwwp">
|
||||
<inputEntry id="UnaryTests_139wk1t">
|
||||
<text></text>
|
||||
</inputEntry>
|
||||
<outputEntry id="LiteralExpression_0emea64">
|
||||
<text>'grey'</text>
|
||||
</outputEntry>
|
||||
</rule>
|
||||
</decisionTable>
|
||||
</decision>
|
||||
</definitions>
|
|
@ -0,0 +1,95 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_889ace0" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.2.0">
|
||||
<bpmn:process id="Process_a7f16c2" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_02xzhf3</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="Flow_02xzhf3" sourceRef="StartEvent_1" targetRef="Activity_UserInput" />
|
||||
<bpmn:sequenceFlow id="Flow_0d46qnz" sourceRef="Activity_UserInput" targetRef="Activity_DecisionLookup" />
|
||||
<bpmn:sequenceFlow id="Flow_1d7sv9v" sourceRef="Activity_DecisionLookup" targetRef="Activity_PickColor" />
|
||||
<bpmn:userTask id="Activity_UserInput" name="User Input" camunda:formKey="UserInput">
|
||||
<bpmn:extensionElements>
|
||||
<camunda:formData>
|
||||
<camunda:formField id="user_input" label="Select Yes or No" type="boolean" defaultValue="True" />
|
||||
</camunda:formData>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_02xzhf3</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0d46qnz</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
<bpmn:businessRuleTask id="Activity_DecisionLookup" name="Decision Lookup" camunda:resultVariable="lookup_output" camunda:decisionRef="Decision_Value_Expression">
|
||||
<bpmn:incoming>Flow_0d46qnz</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1d7sv9v</bpmn:outgoing>
|
||||
</bpmn:businessRuleTask>
|
||||
<bpmn:userTask id="Activity_PickColor" name="Pick a Color" camunda:formKey="MyFormKey">
|
||||
<bpmn:documentation><h1>Hello {{ lookup_output }}</h1></bpmn:documentation>
|
||||
<bpmn:extensionElements>
|
||||
<camunda:formData>
|
||||
<camunda:formField id="color_select" label="Pick a color" type="enum" defaultValue="white">
|
||||
<camunda:properties>
|
||||
<camunda:property id="value_expression" value="lookup_output" />
|
||||
</camunda:properties>
|
||||
<camunda:value id="black" name="Black" />
|
||||
<camunda:value id="white" name="White" />
|
||||
<camunda:value id="grey" name="Grey" />
|
||||
<camunda:value id="gray" name="Gray" />
|
||||
</camunda:formField>
|
||||
</camunda:formData>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_1d7sv9v</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_01x96w8</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
<bpmn:sequenceFlow id="Flow_01x96w8" sourceRef="Activity_PickColor" targetRef="Activity_Display_Color" />
|
||||
<bpmn:manualTask id="Activity_Display_Color" name="Display Color">
|
||||
<bpmn:documentation><h1>Hello</h1>
|
||||
<div>You picked {{ color_select.label }}</div></bpmn:documentation>
|
||||
<bpmn:incoming>Flow_01x96w8</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_05tzoiy</bpmn:outgoing>
|
||||
</bpmn:manualTask>
|
||||
<bpmn:endEvent id="Event_074ypt0">
|
||||
<bpmn:incoming>Flow_05tzoiy</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_05tzoiy" sourceRef="Activity_Display_Color" targetRef="Event_074ypt0" />
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_a7f16c2">
|
||||
<bpmndi:BPMNEdge id="Flow_05tzoiy_di" bpmnElement="Flow_05tzoiy">
|
||||
<di:waypoint x="850" y="117" />
|
||||
<di:waypoint x="912" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_01x96w8_di" bpmnElement="Flow_01x96w8">
|
||||
<di:waypoint x="690" y="117" />
|
||||
<di:waypoint x="750" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1d7sv9v_di" bpmnElement="Flow_1d7sv9v">
|
||||
<di:waypoint x="530" y="117" />
|
||||
<di:waypoint x="590" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0d46qnz_di" bpmnElement="Flow_0d46qnz">
|
||||
<di:waypoint x="370" y="117" />
|
||||
<di:waypoint x="430" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_02xzhf3_di" bpmnElement="Flow_02xzhf3">
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="270" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0xfaikf_di" bpmnElement="Activity_UserInput">
|
||||
<dc:Bounds x="270" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_16u20va_di" bpmnElement="Activity_DecisionLookup">
|
||||
<dc:Bounds x="430" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0dpzpf2_di" bpmnElement="Activity_PickColor">
|
||||
<dc:Bounds x="590" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_157v5xp_di" bpmnElement="Activity_Display_Color">
|
||||
<dc:Bounds x="750" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_074ypt0_di" bpmnElement="Event_074ypt0">
|
||||
<dc:Bounds x="912" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_0y2dq4f" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.3">
|
||||
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_0y2dq4f" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.2.0">
|
||||
<bpmn:process id="Process_0tad5ma" name="Set Recipients" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_1synsig</bpmn:outgoing>
|
||||
|
@ -28,7 +28,7 @@ me = ldap()</bpmn:script>
|
|||
<bpmn:outgoing>Flow_08n2npe</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
<bpmn:sequenceFlow id="Flow_11e7jgz" sourceRef="Activity_0f78ek5" targetRef="Event_0izrcj4" />
|
||||
<bpmn:userTask id="Activity_0f78ek5" name="Read UIDs">
|
||||
<bpmn:userTask id="Activity_0f78ek5" name="Read UIDs" camunda:formKey="ReadUIDs">
|
||||
<bpmn:incoming>Flow_1xlrgne</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_11e7jgz</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1v1rp1q" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.2.0">
|
||||
<bpmn:process id="MissingFormID" name="Missing Form ID" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_1dl9zdu</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:endEvent id="EndEvent_0q4qzl9">
|
||||
<bpmn:incoming>SequenceFlow_02vev7n</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_02vev7n" sourceRef="Task_HelloWorld" targetRef="EndEvent_0q4qzl9" />
|
||||
<bpmn:sequenceFlow id="Flow_1dl9zdu" sourceRef="StartEvent_1" targetRef="Activity_GetName" />
|
||||
<bpmn:sequenceFlow id="Flow_1iohvj2" sourceRef="Activity_GetName" targetRef="Task_HelloWorld" />
|
||||
<bpmn:userTask id="Activity_GetName" name="Get Name">
|
||||
<bpmn:extensionElements>
|
||||
<camunda:formData>
|
||||
<camunda:formField id="name" label="Please enter your name" type="string" defaultValue="World" />
|
||||
</camunda:formData>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_1dl9zdu</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1iohvj2</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
<bpmn:manualTask id="Task_HelloWorld" name="Hello World">
|
||||
<bpmn:documentation><h1>Hello {{ name }}</h1></bpmn:documentation>
|
||||
<bpmn:incoming>Flow_1iohvj2</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_02vev7n</bpmn:outgoing>
|
||||
</bpmn:manualTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="MissingFormID">
|
||||
<bpmndi:BPMNEdge id="SequenceFlow_02vev7n_di" bpmnElement="SequenceFlow_02vev7n">
|
||||
<di:waypoint x="580" y="117" />
|
||||
<di:waypoint x="642" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1dl9zdu_di" bpmnElement="Flow_1dl9zdu">
|
||||
<di:waypoint x="188" y="117" />
|
||||
<di:waypoint x="280" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1iohvj2_di" bpmnElement="Flow_1iohvj2">
|
||||
<di:waypoint x="380" y="117" />
|
||||
<di:waypoint x="480" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="EndEvent_0q4qzl9_di" bpmnElement="EndEvent_0q4qzl9">
|
||||
<dc:Bounds x="642" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="152" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_1gbakdp_di" bpmnElement="Activity_GetName">
|
||||
<dc:Bounds x="280" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_11m46jy_di" bpmnElement="Task_HelloWorld">
|
||||
<dc:Bounds x="480" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
|
@ -0,0 +1 @@
|
|||
TEST - This is only a test - TEST
|
|
@ -12,6 +12,27 @@ from crc.models.workflow import WorkflowSpecModel
|
|||
from datetime import datetime
|
||||
from crc.services.file_service import FileService
|
||||
|
||||
def get_random_fact_pos(othersys):
|
||||
"""
|
||||
Make sure we get the 'random_fact' workflow spec
|
||||
no matter what order it is in
|
||||
"""
|
||||
rf2pos = 0
|
||||
for pos in range(len(othersys)):
|
||||
if othersys[pos]['workflow_spec_id'] == 'random_fact':
|
||||
rf2pos = pos
|
||||
return rf2pos
|
||||
|
||||
|
||||
def get_random_fact_2_pos(othersys):
|
||||
"""
|
||||
Makes sure we get the random_fact2.bpmn file no matter what order it is in
|
||||
"""
|
||||
rf2pos = 0
|
||||
for pos in range(len(othersys)):
|
||||
if othersys[pos]['filename'] == 'random_fact2.bpmn':
|
||||
rf2pos = pos
|
||||
return rf2pos
|
||||
|
||||
|
||||
class TestWorkflowSync(BaseTest):
|
||||
|
@ -30,8 +51,9 @@ class TestWorkflowSync(BaseTest):
|
|||
def test_remote_workflow_change(self, mock_get):
|
||||
self.load_example_data()
|
||||
othersys = get_all_spec_state()
|
||||
othersys[1]['date_created'] = str(datetime.now())
|
||||
othersys[1]['md5_hash'] = '12345'
|
||||
rf2pos = get_random_fact_pos(othersys)
|
||||
othersys[rf2pos]['date_created'] = str(datetime.now())
|
||||
othersys[rf2pos]['md5_hash'] = '12345'
|
||||
mock_get.return_value = othersys
|
||||
response = get_changed_workflows('localhost:0000') #endpoint is not used due to mock
|
||||
self.assertIsNotNone(response)
|
||||
|
@ -80,28 +102,27 @@ class TestWorkflowSync(BaseTest):
|
|||
self.assertIsNotNone(response)
|
||||
self.assertEqual(response,[])
|
||||
|
||||
|
||||
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec_files')
|
||||
def test_file_differences(self, mock_get):
|
||||
def test_file_differences_clean_slate(self, mock_get):
|
||||
""" This test is basically for coverage"""
|
||||
self.load_example_data()
|
||||
othersys = get_workflow_spec_files('random_fact')
|
||||
othersys[1]['date_created'] = str(datetime.now())
|
||||
othersys[1]['md5_hash'] = '12345'
|
||||
mock_get.return_value = othersys
|
||||
self.delete_example_data()
|
||||
response = get_changed_files('localhost:0000','random_fact',as_df=False) #endpoint is not used due to mock
|
||||
self.assertIsNotNone(response)
|
||||
self.assertEqual(len(response),1)
|
||||
self.assertEqual(response[0]['filename'], 'random_fact2.bpmn')
|
||||
self.assertEqual(len(response),2)
|
||||
self.assertEqual(response[0]['location'], 'remote')
|
||||
self.assertEqual(response[0]['new'], False)
|
||||
self.assertEqual(response[0]['new'], True)
|
||||
|
||||
|
||||
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec_files')
|
||||
def test_file_differences(self, mock_get):
|
||||
self.load_example_data()
|
||||
othersys = get_workflow_spec_files('random_fact')
|
||||
othersys[1]['date_created'] = str(datetime.now())
|
||||
othersys[1]['md5_hash'] = '12345'
|
||||
rf2pos = get_random_fact_2_pos(othersys)
|
||||
othersys[rf2pos]['date_created'] = str(datetime.now())
|
||||
othersys[rf2pos]['md5_hash'] = '12345'
|
||||
mock_get.return_value = othersys
|
||||
response = get_changed_files('localhost:0000','random_fact',as_df=False) #endpoint is not used due to mock
|
||||
self.assertIsNotNone(response)
|
||||
|
@ -113,19 +134,24 @@ class TestWorkflowSync(BaseTest):
|
|||
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_file_by_hash')
|
||||
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec_files')
|
||||
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec')
|
||||
def test_file_differences(self, workflow_mock, spec_files_mock, file_data_mock):
|
||||
def test_workflow_differences(self, workflow_mock, spec_files_mock, file_data_mock):
|
||||
self.load_example_data()
|
||||
# make a remote workflow that is slightly different from local
|
||||
remote_workflow = get_workflow_specification('random_fact')
|
||||
self.assertEqual(remote_workflow['display_name'],'Random Fact')
|
||||
remote_workflow['description'] = 'This Workflow came from Remote'
|
||||
remote_workflow['display_name'] = 'Remote Workflow'
|
||||
workflow_mock.return_value = remote_workflow
|
||||
# change the remote file date and hash
|
||||
othersys = get_workflow_spec_files('random_fact')
|
||||
othersys[1]['date_created'] = str(datetime.now())
|
||||
othersys[1]['md5_hash'] = '12345'
|
||||
rf2pos = get_random_fact_2_pos(othersys)
|
||||
othersys[rf2pos]['date_created'] = str(datetime.now())
|
||||
othersys[rf2pos]['md5_hash'] = '12345'
|
||||
spec_files_mock.return_value = othersys
|
||||
# actually go get a different file
|
||||
file_data_mock.return_value = self.workflow_sync_response('random_fact2.bpmn')
|
||||
response = sync_changed_files('localhost:0000','random_fact') # endpoint not used due to mock
|
||||
# now make sure that everything gets pulled over
|
||||
self.assertIsNotNone(response)
|
||||
self.assertEqual(len(response),1)
|
||||
self.assertEqual(response[0], 'random_fact2.bpmn')
|
||||
|
@ -137,6 +163,39 @@ class TestWorkflowSync(BaseTest):
|
|||
|
||||
|
||||
|
||||
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_file_by_hash')
|
||||
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec_files')
|
||||
def test_ref_file_differences(self, spec_files_mock, file_data_mock):
|
||||
"""
|
||||
Make sure we copy over a new reference file if it exists
|
||||
"""
|
||||
self.load_example_data()
|
||||
# make a remote workflow that is slightly different from local
|
||||
othersys = get_workflow_spec_files('REFERENCE_FILES')
|
||||
newfile = {'file_model_id':9999,
|
||||
'workflow_spec_id': None,
|
||||
'filename':'test.txt',
|
||||
'type':'txt',
|
||||
'primary':False,
|
||||
'content_type':'text/text',
|
||||
'primary_process_id':None,
|
||||
'date_created':str(datetime.now()),
|
||||
'md5_hash':'12345'
|
||||
}
|
||||
othersys.append(newfile)
|
||||
spec_files_mock.return_value = othersys
|
||||
# actually go get a different file
|
||||
file_data_mock.return_value = self.workflow_sync_response('test.txt')
|
||||
response = sync_changed_files('localhost:0000','REFERENCE_FILES') # endpoint not used due to mock
|
||||
# now make sure that everything gets pulled over
|
||||
self.assertIsNotNone(response)
|
||||
self.assertEqual(len(response),1)
|
||||
self.assertEqual(response[0], 'test.txt')
|
||||
ref_file = FileService.get_reference_file_data('test.txt')
|
||||
self.assertEqual('24a2ab0d-1138-a80a-0b98-ed38894f5a04',str(ref_file.md5_hash))
|
||||
|
||||
|
||||
|
||||
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec_files')
|
||||
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec')
|
||||
def test_file_deleted(self, workflow_mock, spec_files_mock):
|
||||
|
@ -144,7 +203,8 @@ class TestWorkflowSync(BaseTest):
|
|||
remote_workflow = get_workflow_specification('random_fact')
|
||||
workflow_mock.return_value = remote_workflow
|
||||
othersys = get_workflow_spec_files('random_fact')
|
||||
del(othersys[1])
|
||||
rf2pos = get_random_fact_2_pos(othersys)
|
||||
del(othersys[rf2pos])
|
||||
spec_files_mock.return_value = othersys
|
||||
response = sync_changed_files('localhost:0000','random_fact') # endpoint not used due to mock
|
||||
self.assertIsNotNone(response)
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
from tests.base_test import BaseTest
|
||||
import json
|
||||
|
||||
|
||||
class TestWorkflowEnumDefault(BaseTest):
|
||||
|
||||
def test_enum_default_from_value_expression(self):
|
||||
workflow = self.create_workflow('enum_value_expression')
|
||||
|
||||
first_task = self.get_workflow_api(workflow).next_task
|
||||
self.assertEqual('Activity_UserInput', first_task.name)
|
||||
workflow_api = self.get_workflow_api(workflow)
|
||||
|
||||
result = self.complete_form(workflow_api, first_task, {'user_input': True})
|
||||
self.assertIn('user_input', result.next_task.data)
|
||||
self.assertEqual(True, result.next_task.data['user_input'])
|
||||
self.assertIn('lookup_output', result.next_task.data)
|
||||
self.assertEqual('black', result.next_task.data['lookup_output'])
|
||||
|
||||
workflow_api = self.get_workflow_api(workflow)
|
||||
self.assertEqual('Activity_PickColor', self.get_workflow_api(workflow_api).next_task.name)
|
||||
self.assertEqual({'value': 'black', 'label': 'Black'}, workflow_api.next_task.data['color_select'])
|
||||
|
||||
#
|
||||
workflow = self.create_workflow('enum_value_expression')
|
||||
|
||||
first_task = self.get_workflow_api(workflow).next_task
|
||||
self.assertEqual('Activity_UserInput', first_task.name)
|
||||
workflow_api = self.get_workflow_api(workflow)
|
||||
|
||||
result = self.complete_form(workflow_api, first_task, {'user_input': False})
|
||||
self.assertIn('user_input', result.next_task.data)
|
||||
self.assertEqual(False, result.next_task.data['user_input'])
|
||||
self.assertIn('lookup_output', result.next_task.data)
|
||||
self.assertEqual('white', result.next_task.data['lookup_output'])
|
||||
|
||||
workflow_api = self.get_workflow_api(workflow)
|
||||
self.assertEqual('Activity_PickColor', self.get_workflow_api(workflow_api).next_task.name)
|
||||
self.assertEqual({'value': 'white', 'label': 'White'}, workflow_api.next_task.data['color_select'])
|
||||
|
||||
def test_enum_value_expression_and_default(self):
|
||||
spec_model = self.load_test_spec('enum_value_expression_fail')
|
||||
rv = self.app.get('/v1.0/workflow-specification/%s/validate' % spec_model.id, headers=self.logged_in_headers())
|
||||
|
||||
json_data = json.loads(rv.get_data(as_text=True))
|
||||
self.assertEqual(json_data[0]['code'], 'default value and value_expression')
|
|
@ -0,0 +1,13 @@
|
|||
from tests.base_test import BaseTest
|
||||
import json
|
||||
|
||||
|
||||
class TestMissingFormKey(BaseTest):
|
||||
|
||||
def test_missing_form_key(self):
|
||||
|
||||
spec_model = self.load_test_spec('missing_form_key')
|
||||
rv = self.app.get('/v1.0/workflow-specification/%s/validate' % spec_model.id, headers=self.logged_in_headers())
|
||||
json_data = json.loads(rv.get_data(as_text=True))
|
||||
self.assertIn('code', json_data[0])
|
||||
self.assertEqual('missing_form_key', json_data[0]['code'])
|
Loading…
Reference in New Issue