operaton-external-task-client-python3 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- examples/__init__.py +0 -0
- examples/bpmn_error_example.py +75 -0
- examples/correlate_message.py +11 -0
- examples/event_subprocess_example.py +50 -0
- examples/examples_auth_basic/__init__.py +0 -0
- examples/examples_auth_basic/fetch_and_execute.py +31 -0
- examples/examples_auth_basic/get_process_instance.py +12 -0
- examples/examples_auth_basic/start_process.py +15 -0
- examples/examples_auth_basic/task_handler_example.py +44 -0
- examples/fetch_and_execute.py +30 -0
- examples/get_process_instance.py +12 -0
- examples/retry_task_example.py +58 -0
- examples/start_process.py +14 -0
- examples/task_handler_example.py +44 -0
- examples/tasks_example.py +36 -0
- operaton/__init__.py +0 -0
- operaton/client/__init__.py +0 -0
- operaton/client/async_external_task_client.py +171 -0
- operaton/client/engine_client.py +180 -0
- operaton/client/external_task_client.py +166 -0
- operaton/client/tests/__init__.py +0 -0
- operaton/client/tests/test_async_external_task_client.py +128 -0
- operaton/client/tests/test_async_external_task_client_auth.py +42 -0
- operaton/client/tests/test_async_external_task_client_bearer.py +43 -0
- operaton/client/tests/test_engine_client.py +228 -0
- operaton/client/tests/test_engine_client_auth.py +231 -0
- operaton/client/tests/test_engine_client_bearer.py +237 -0
- operaton/client/tests/test_external_task_client.py +17 -0
- operaton/client/tests/test_external_task_client_auth.py +19 -0
- operaton/client/tests/test_external_task_client_bearer.py +24 -0
- operaton/external_task/__init__.py +0 -0
- operaton/external_task/async_external_task_executor.py +91 -0
- operaton/external_task/async_external_task_worker.py +181 -0
- operaton/external_task/external_task.py +173 -0
- operaton/external_task/external_task_executor.py +88 -0
- operaton/external_task/external_task_worker.py +92 -0
- operaton/external_task/tests/__init__.py +0 -0
- operaton/external_task/tests/test_async_external_task_executor.py +139 -0
- operaton/external_task/tests/test_async_external_task_worker.py +129 -0
- operaton/external_task/tests/test_external_task.py +106 -0
- operaton/external_task/tests/test_external_task_executor.py +200 -0
- operaton/external_task/tests/test_external_task_worker.py +147 -0
- operaton/process_definition/__init__.py +0 -0
- operaton/process_definition/process_definition_client.py +123 -0
- operaton/process_definition/tests/__init__.py +0 -0
- operaton/process_definition/tests/test_process_definition_client.py +181 -0
- operaton/utils/__init__.py +0 -0
- operaton/utils/auth_basic.py +28 -0
- operaton/utils/auth_bearer.py +28 -0
- operaton/utils/log_utils.py +31 -0
- operaton/utils/response_utils.py +35 -0
- operaton/utils/tests/test_auth_basic.py +30 -0
- operaton/utils/tests/test_auth_bearer.py +27 -0
- operaton/utils/tests/test_response_utils.py +43 -0
- operaton/utils/tests/test_utils.py +21 -0
- operaton/utils/utils.py +14 -0
- operaton/variables/__init__.py +0 -0
- operaton/variables/properties.py +27 -0
- operaton/variables/tests/test_properties.py +20 -0
- operaton/variables/tests/test_variables.py +60 -0
- operaton/variables/variables.py +45 -0
- operaton_external_task_client_python3-1.0.0.dist-info/METADATA +258 -0
- operaton_external_task_client_python3-1.0.0.dist-info/RECORD +66 -0
- operaton_external_task_client_python3-1.0.0.dist-info/WHEEL +5 -0
- operaton_external_task_client_python3-1.0.0.dist-info/licenses/LICENSE +201 -0
- operaton_external_task_client_python3-1.0.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
from http import HTTPStatus
|
|
3
|
+
from unittest import TestCase
|
|
4
|
+
from unittest.mock import patch
|
|
5
|
+
|
|
6
|
+
import responses
|
|
7
|
+
|
|
8
|
+
from operaton.client.engine_client import EngineClient, ENGINE_LOCAL_BASE_URL
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class EngineClientTest(TestCase):
|
|
12
|
+
tenant_id = "6172cdf0-7b32-4460-9da0-ded5107aa977"
|
|
13
|
+
process_key = "PARALLEL_STEPS_EXAMPLE"
|
|
14
|
+
|
|
15
|
+
def setUp(self):
|
|
16
|
+
self.client = EngineClient()
|
|
17
|
+
|
|
18
|
+
@responses.activate
|
|
19
|
+
def test_start_process_success(self):
|
|
20
|
+
resp_payload = {
|
|
21
|
+
"links": [
|
|
22
|
+
{
|
|
23
|
+
"method": "GET",
|
|
24
|
+
"href": "http://localhost:8080/engine-rest/process-instance/cb678be8-9b93-11ea-bad9-0242ac110002",
|
|
25
|
+
"rel": "self"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"id": "cb678be8-9b93-11ea-bad9-0242ac110002",
|
|
29
|
+
"definitionId": "PARALLEL_STEPS_EXAMPLE:1:9b72da83-9b91-11ea-bad9-0242ac110002",
|
|
30
|
+
"businessKey": "123456",
|
|
31
|
+
"caseInstanceId": None,
|
|
32
|
+
"ended": False,
|
|
33
|
+
"suspended": False,
|
|
34
|
+
"tenantId": None
|
|
35
|
+
}
|
|
36
|
+
responses.add(responses.POST, self.client.get_start_process_instance_url(self.process_key, self.tenant_id),
|
|
37
|
+
json=resp_payload, status=HTTPStatus.OK)
|
|
38
|
+
actual_resp_payload = self.client.start_process(self.process_key, {}, self.tenant_id, "123456")
|
|
39
|
+
self.assertDictEqual(resp_payload, actual_resp_payload)
|
|
40
|
+
|
|
41
|
+
@responses.activate
|
|
42
|
+
def test_start_process_not_found_raises_exception(self):
|
|
43
|
+
resp_payload = {
|
|
44
|
+
"type": "RestException",
|
|
45
|
+
"message": "No matching process definition with key: PROCESS_KEY_NOT_EXISTS and tenant-id: tenant_123"
|
|
46
|
+
}
|
|
47
|
+
responses.add(responses.POST,
|
|
48
|
+
self.client.get_start_process_instance_url("PROCESS_KEY_NOT_EXISTS", self.tenant_id),
|
|
49
|
+
status=HTTPStatus.NOT_FOUND, json=resp_payload)
|
|
50
|
+
with self.assertRaises(Exception) as exception_ctx:
|
|
51
|
+
self.client.start_process("PROCESS_KEY_NOT_EXISTS", {}, self.tenant_id)
|
|
52
|
+
|
|
53
|
+
self.assertEqual("received 404 : RestException : "
|
|
54
|
+
"No matching process definition with key: PROCESS_KEY_NOT_EXISTS and tenant-id: tenant_123",
|
|
55
|
+
str(exception_ctx.exception))
|
|
56
|
+
|
|
57
|
+
@responses.activate
|
|
58
|
+
def test_start_process_bad_request_raises_exception(self):
|
|
59
|
+
client = EngineClient()
|
|
60
|
+
expected_message = "Cannot instantiate process definition " \
|
|
61
|
+
"PARALLEL_STEPS_EXAMPLE:1:9b72da83-9b91-11ea-bad9-0242ac110002: " \
|
|
62
|
+
"Cannot convert value '1aa2345' of type 'Integer' to java type java.lang.Integer"
|
|
63
|
+
resp_payload = {
|
|
64
|
+
"type": "InvalidRequestException",
|
|
65
|
+
"message": expected_message
|
|
66
|
+
}
|
|
67
|
+
responses.add(responses.POST, client.get_start_process_instance_url(self.process_key, self.tenant_id),
|
|
68
|
+
status=HTTPStatus.BAD_REQUEST, json=resp_payload)
|
|
69
|
+
with self.assertRaises(Exception) as exception_ctx:
|
|
70
|
+
client.start_process(self.process_key, {"int_var": "1aa2345"}, self.tenant_id)
|
|
71
|
+
|
|
72
|
+
self.assertEqual(f"received 400 : InvalidRequestException : {expected_message}", str(exception_ctx.exception))
|
|
73
|
+
|
|
74
|
+
@responses.activate
|
|
75
|
+
def test_start_process_server_error_raises_exception(self):
|
|
76
|
+
responses.add(responses.POST, self.client.get_start_process_instance_url(self.process_key, self.tenant_id),
|
|
77
|
+
status=HTTPStatus.INTERNAL_SERVER_ERROR)
|
|
78
|
+
with self.assertRaises(Exception) as exception_ctx:
|
|
79
|
+
self.client.start_process(self.process_key, {"int_var": "1aa2345"}, self.tenant_id)
|
|
80
|
+
|
|
81
|
+
self.assertEqual(HTTPStatus.INTERNAL_SERVER_ERROR, exception_ctx.exception.response.status_code)
|
|
82
|
+
self.assertIn("Server Error: Internal Server Error", str(exception_ctx.exception))
|
|
83
|
+
|
|
84
|
+
@responses.activate
|
|
85
|
+
def test_get_process_instance_success(self):
|
|
86
|
+
resp_payload = [
|
|
87
|
+
{
|
|
88
|
+
"links": [],
|
|
89
|
+
"id": "c2c68785-9f42-11ea-a841-0242ac1c0004",
|
|
90
|
+
"definitionId": "PARALLEL_STEPS_EXAMPLE:1:88613042-9f42-11ea-a841-0242ac1c0004",
|
|
91
|
+
"businessKey": None,
|
|
92
|
+
"caseInstanceId": None,
|
|
93
|
+
"ended": False,
|
|
94
|
+
"suspended": False,
|
|
95
|
+
"tenantId": self.tenant_id
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
get_process_instance_url = f"{ENGINE_LOCAL_BASE_URL}/process-instance" \
|
|
99
|
+
f"?processDefinitionKey={self.process_key}" \
|
|
100
|
+
f"&tenantIdIn={self.tenant_id}" \
|
|
101
|
+
f"&variables=intVar_eq_1,strVar_eq_hello"
|
|
102
|
+
responses.add(responses.GET, get_process_instance_url, status=HTTPStatus.OK, json=resp_payload)
|
|
103
|
+
actual_resp_payload = self.client.get_process_instance(process_key=self.process_key,
|
|
104
|
+
variables=["intVar_eq_1", "strVar_eq_hello"],
|
|
105
|
+
tenant_ids=[self.tenant_id])
|
|
106
|
+
self.assertListEqual(resp_payload, actual_resp_payload)
|
|
107
|
+
|
|
108
|
+
@responses.activate
|
|
109
|
+
def test_get_process_instance_bad_request_raises_exception(self):
|
|
110
|
+
expected_message = "Invalid variable comparator specified: XXX"
|
|
111
|
+
resp_payload = {
|
|
112
|
+
"type": "InvalidRequestException",
|
|
113
|
+
"message": expected_message
|
|
114
|
+
}
|
|
115
|
+
get_process_instance_url = f"{ENGINE_LOCAL_BASE_URL}/process-instance" \
|
|
116
|
+
f"?processDefinitionKey={self.process_key}" \
|
|
117
|
+
f"&tenantIdIn={self.tenant_id}" \
|
|
118
|
+
f"&variables=intVar_XXX_1,strVar_eq_hello"
|
|
119
|
+
responses.add(responses.GET, get_process_instance_url, status=HTTPStatus.BAD_REQUEST, json=resp_payload)
|
|
120
|
+
with self.assertRaises(Exception) as exception_ctx:
|
|
121
|
+
self.client.get_process_instance(process_key=self.process_key,
|
|
122
|
+
variables=["intVar_XXX_1", "strVar_eq_hello"],
|
|
123
|
+
tenant_ids=[self.tenant_id])
|
|
124
|
+
|
|
125
|
+
self.assertEqual(f"received 400 : InvalidRequestException : {expected_message}", str(exception_ctx.exception))
|
|
126
|
+
|
|
127
|
+
@responses.activate
|
|
128
|
+
def test_get_process_instance_server_error_raises_exception(self):
|
|
129
|
+
get_process_instance_url = f"{ENGINE_LOCAL_BASE_URL}/process-instance" \
|
|
130
|
+
f"?processDefinitionKey={self.process_key}" \
|
|
131
|
+
f"&tenantIdIn={self.tenant_id}" \
|
|
132
|
+
f"&variables=intVar_XXX_1,strVar_eq_hello"
|
|
133
|
+
responses.add(responses.GET, get_process_instance_url, status=HTTPStatus.INTERNAL_SERVER_ERROR)
|
|
134
|
+
with self.assertRaises(Exception) as exception_ctx:
|
|
135
|
+
self.client.get_process_instance(process_key=self.process_key,
|
|
136
|
+
variables=["intVar_XXX_1", "strVar_eq_hello"],
|
|
137
|
+
tenant_ids=[self.tenant_id])
|
|
138
|
+
|
|
139
|
+
self.assertEqual(HTTPStatus.INTERNAL_SERVER_ERROR, exception_ctx.exception.response.status_code)
|
|
140
|
+
self.assertIn("Server Error: Internal Server Error", str(exception_ctx.exception))
|
|
141
|
+
|
|
142
|
+
@patch('requests.post')
|
|
143
|
+
def test_correlate_message_with_only_message_name(self, mock_post):
|
|
144
|
+
expected_request_payload = {
|
|
145
|
+
"messageName": "CANCEL_MESSAGE",
|
|
146
|
+
"withoutTenantId": True,
|
|
147
|
+
"resultEnabled": True
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
self.client.correlate_message("CANCEL_MESSAGE")
|
|
151
|
+
mock_post.assert_called_with(ENGINE_LOCAL_BASE_URL + "/message",
|
|
152
|
+
json=expected_request_payload,
|
|
153
|
+
headers={'Content-Type': 'application/json'})
|
|
154
|
+
|
|
155
|
+
@patch('requests.post')
|
|
156
|
+
def test_correlate_message_with_business_key(self, mock_post):
|
|
157
|
+
expected_request_payload = {
|
|
158
|
+
"messageName": "CANCEL_MESSAGE",
|
|
159
|
+
"withoutTenantId": True,
|
|
160
|
+
"businessKey": "123456",
|
|
161
|
+
"resultEnabled": True
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
self.client.correlate_message("CANCEL_MESSAGE", business_key="123456")
|
|
165
|
+
mock_post.assert_called_with(ENGINE_LOCAL_BASE_URL + "/message",
|
|
166
|
+
json=expected_request_payload,
|
|
167
|
+
headers={'Content-Type': 'application/json'})
|
|
168
|
+
|
|
169
|
+
@patch('requests.post')
|
|
170
|
+
def test_correlate_message_with_tenant_id(self, mock_post):
|
|
171
|
+
expected_request_payload = {
|
|
172
|
+
"messageName": "CANCEL_MESSAGE",
|
|
173
|
+
"withoutTenantId": False,
|
|
174
|
+
"tenantId": "123456",
|
|
175
|
+
"resultEnabled": True
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
self.client.correlate_message("CANCEL_MESSAGE", tenant_id="123456")
|
|
179
|
+
mock_post.assert_called_with(ENGINE_LOCAL_BASE_URL + "/message",
|
|
180
|
+
json=expected_request_payload,
|
|
181
|
+
headers={'Content-Type': 'application/json'})
|
|
182
|
+
|
|
183
|
+
@responses.activate
|
|
184
|
+
def test_correlate_message_invalid_message_name_raises_exception(self):
|
|
185
|
+
expected_message = "org.operaton.bpm.engine.MismatchingMessageCorrelationException: " \
|
|
186
|
+
"Cannot correlate message 'XXX': No process definition or execution matches the parameters"
|
|
187
|
+
resp_payload = {
|
|
188
|
+
"type": "RestException",
|
|
189
|
+
"message": expected_message
|
|
190
|
+
}
|
|
191
|
+
correlate_msg_url = f"{ENGINE_LOCAL_BASE_URL}/message"
|
|
192
|
+
responses.add(responses.POST, correlate_msg_url, status=HTTPStatus.BAD_REQUEST, json=resp_payload)
|
|
193
|
+
with self.assertRaises(Exception) as exception_ctx:
|
|
194
|
+
self.client.correlate_message(message_name="XXX")
|
|
195
|
+
|
|
196
|
+
self.assertEqual(f"received 400 : RestException : {expected_message}", str(exception_ctx.exception))
|
|
197
|
+
|
|
198
|
+
@responses.activate
|
|
199
|
+
def test_get_process_instance_variable_without_meta(self):
|
|
200
|
+
process_instance_id = "c2c68785-9f42-11ea-a841-0242ac1c0004"
|
|
201
|
+
variable_name = "var1"
|
|
202
|
+
process_instance_var_url = \
|
|
203
|
+
f"{ENGINE_LOCAL_BASE_URL}/process-instance/{process_instance_id}/variables/{variable_name}"
|
|
204
|
+
resp_frame_payload = {"value": None, "valueInfo": {}, "type": ""}
|
|
205
|
+
resp_data_payload = base64.decodebytes(b"operaton")
|
|
206
|
+
process_instance_var_data_url = f"{process_instance_var_url}/data"
|
|
207
|
+
|
|
208
|
+
responses.add(responses.GET, process_instance_var_url, status=HTTPStatus.OK, json=resp_frame_payload)
|
|
209
|
+
responses.add(responses.GET, process_instance_var_data_url, status=HTTPStatus.OK, body=resp_data_payload)
|
|
210
|
+
|
|
211
|
+
resp = self.client.get_process_instance_variable(process_instance_id, variable_name)
|
|
212
|
+
self.assertEqual("operaton\n", resp)
|
|
213
|
+
|
|
214
|
+
@responses.activate
|
|
215
|
+
def test_get_process_instance_variable_with_meta(self):
|
|
216
|
+
process_instance_id = "c2c68785-9f42-11ea-a841-0242ac1c0004"
|
|
217
|
+
variable_name = "var1"
|
|
218
|
+
process_instance_var_url = \
|
|
219
|
+
f"{ENGINE_LOCAL_BASE_URL}/process-instance/{process_instance_id}/variables/{variable_name}"
|
|
220
|
+
resp_frame_payload = {"value": None, "valueInfo": {}, "type": ""}
|
|
221
|
+
resp_data_payload = base64.decodebytes(b"operaton")
|
|
222
|
+
process_instance_var_data_url = f"{process_instance_var_url}/data"
|
|
223
|
+
|
|
224
|
+
responses.add(responses.GET, process_instance_var_url, status=HTTPStatus.OK, json=resp_frame_payload)
|
|
225
|
+
responses.add(responses.GET, process_instance_var_data_url, status=HTTPStatus.OK, body=resp_data_payload)
|
|
226
|
+
|
|
227
|
+
resp = self.client.get_process_instance_variable(process_instance_id, variable_name, True)
|
|
228
|
+
self.assertEqual({"value": "operaton\n", "valueInfo": {}, "type": ""}, resp)
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
from http import HTTPStatus
|
|
3
|
+
from unittest import TestCase
|
|
4
|
+
from unittest.mock import patch
|
|
5
|
+
|
|
6
|
+
import responses
|
|
7
|
+
|
|
8
|
+
from operaton.client.engine_client import EngineClient, ENGINE_LOCAL_BASE_URL
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class EngineClientAuthTest(TestCase):
|
|
12
|
+
tenant_id = "6172cdf0-7b32-4460-9da0-ded5107aa977"
|
|
13
|
+
process_key = "PARALLEL_STEPS_EXAMPLE"
|
|
14
|
+
|
|
15
|
+
def setUp(self):
|
|
16
|
+
self.client = EngineClient(config={"auth_basic": {"username": "demo", "password": "demo"}})
|
|
17
|
+
|
|
18
|
+
@responses.activate
|
|
19
|
+
def test_auth_basic_start_process_success(self):
|
|
20
|
+
resp_payload = {
|
|
21
|
+
"links": [
|
|
22
|
+
{
|
|
23
|
+
"method": "GET",
|
|
24
|
+
"href": "http://localhost:8080/engine-rest/process-instance/cb678be8-9b93-11ea-bad9-0242ac110002",
|
|
25
|
+
"rel": "self"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"id": "cb678be8-9b93-11ea-bad9-0242ac110002",
|
|
29
|
+
"definitionId": "PARALLEL_STEPS_EXAMPLE:1:9b72da83-9b91-11ea-bad9-0242ac110002",
|
|
30
|
+
"businessKey": "123456",
|
|
31
|
+
"caseInstanceId": None,
|
|
32
|
+
"ended": False,
|
|
33
|
+
"suspended": False,
|
|
34
|
+
"tenantId": None
|
|
35
|
+
}
|
|
36
|
+
responses.add(responses.POST, self.client.get_start_process_instance_url(self.process_key, self.tenant_id),
|
|
37
|
+
json=resp_payload, status=HTTPStatus.OK)
|
|
38
|
+
actual_resp_payload = self.client.start_process(self.process_key, {}, self.tenant_id, "123456")
|
|
39
|
+
self.assertDictEqual(resp_payload, actual_resp_payload)
|
|
40
|
+
|
|
41
|
+
@responses.activate
|
|
42
|
+
def test_auth_basic_start_process_not_found_raises_exception(self):
|
|
43
|
+
resp_payload = {
|
|
44
|
+
"type": "RestException",
|
|
45
|
+
"message": "No matching process definition with key: PROCESS_KEY_NOT_EXISTS and tenant-id: tenant_123"
|
|
46
|
+
}
|
|
47
|
+
responses.add(responses.POST,
|
|
48
|
+
self.client.get_start_process_instance_url("PROCESS_KEY_NOT_EXISTS", self.tenant_id),
|
|
49
|
+
status=HTTPStatus.NOT_FOUND, json=resp_payload)
|
|
50
|
+
with self.assertRaises(Exception) as exception_ctx:
|
|
51
|
+
self.client.start_process("PROCESS_KEY_NOT_EXISTS", {}, self.tenant_id)
|
|
52
|
+
|
|
53
|
+
self.assertEqual("received 404 : RestException : "
|
|
54
|
+
"No matching process definition with key: PROCESS_KEY_NOT_EXISTS and tenant-id: tenant_123",
|
|
55
|
+
str(exception_ctx.exception))
|
|
56
|
+
|
|
57
|
+
@responses.activate
|
|
58
|
+
def test_auth_basic_start_process_bad_request_raises_exception(self):
|
|
59
|
+
client = EngineClient()
|
|
60
|
+
expected_message = "Cannot instantiate process definition " \
|
|
61
|
+
"PARALLEL_STEPS_EXAMPLE:1:9b72da83-9b91-11ea-bad9-0242ac110002: " \
|
|
62
|
+
"Cannot convert value '1aa2345' of type 'Integer' to java type java.lang.Integer"
|
|
63
|
+
resp_payload = {
|
|
64
|
+
"type": "InvalidRequestException",
|
|
65
|
+
"message": expected_message
|
|
66
|
+
}
|
|
67
|
+
responses.add(responses.POST, client.get_start_process_instance_url(self.process_key, self.tenant_id),
|
|
68
|
+
status=HTTPStatus.BAD_REQUEST, json=resp_payload)
|
|
69
|
+
with self.assertRaises(Exception) as exception_ctx:
|
|
70
|
+
client.start_process(self.process_key, {"int_var": "1aa2345"}, self.tenant_id)
|
|
71
|
+
|
|
72
|
+
self.assertEqual(f"received 400 : InvalidRequestException : {expected_message}", str(exception_ctx.exception))
|
|
73
|
+
|
|
74
|
+
@responses.activate
|
|
75
|
+
def test_auth_basic_start_process_server_error_raises_exception(self):
|
|
76
|
+
responses.add(responses.POST, self.client.get_start_process_instance_url(self.process_key, self.tenant_id),
|
|
77
|
+
status=HTTPStatus.INTERNAL_SERVER_ERROR)
|
|
78
|
+
with self.assertRaises(Exception) as exception_ctx:
|
|
79
|
+
self.client.start_process(self.process_key, {"int_var": "1aa2345"}, self.tenant_id)
|
|
80
|
+
|
|
81
|
+
self.assertEqual(HTTPStatus.INTERNAL_SERVER_ERROR, exception_ctx.exception.response.status_code)
|
|
82
|
+
self.assertIn("Server Error: Internal Server Error", str(exception_ctx.exception))
|
|
83
|
+
|
|
84
|
+
@responses.activate
|
|
85
|
+
def test_auth_basic_get_process_instance_success(self):
|
|
86
|
+
resp_payload = [
|
|
87
|
+
{
|
|
88
|
+
"links": [],
|
|
89
|
+
"id": "c2c68785-9f42-11ea-a841-0242ac1c0004",
|
|
90
|
+
"definitionId": "PARALLEL_STEPS_EXAMPLE:1:88613042-9f42-11ea-a841-0242ac1c0004",
|
|
91
|
+
"businessKey": None,
|
|
92
|
+
"caseInstanceId": None,
|
|
93
|
+
"ended": False,
|
|
94
|
+
"suspended": False,
|
|
95
|
+
"tenantId": self.tenant_id
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
get_process_instance_url = f"{ENGINE_LOCAL_BASE_URL}/process-instance" \
|
|
99
|
+
f"?processDefinitionKey={self.process_key}" \
|
|
100
|
+
f"&tenantIdIn={self.tenant_id}" \
|
|
101
|
+
f"&variables=intVar_eq_1,strVar_eq_hello"
|
|
102
|
+
responses.add(responses.GET, get_process_instance_url, status=HTTPStatus.OK, json=resp_payload)
|
|
103
|
+
actual_resp_payload = self.client.get_process_instance(process_key=self.process_key,
|
|
104
|
+
variables=["intVar_eq_1", "strVar_eq_hello"],
|
|
105
|
+
tenant_ids=[self.tenant_id])
|
|
106
|
+
self.assertListEqual(resp_payload, actual_resp_payload)
|
|
107
|
+
|
|
108
|
+
@responses.activate
|
|
109
|
+
def test_auth_basic_get_process_instance_bad_request_raises_exception(self):
|
|
110
|
+
expected_message = "Invalid variable comparator specified: XXX"
|
|
111
|
+
resp_payload = {
|
|
112
|
+
"type": "InvalidRequestException",
|
|
113
|
+
"message": expected_message
|
|
114
|
+
}
|
|
115
|
+
get_process_instance_url = f"{ENGINE_LOCAL_BASE_URL}/process-instance" \
|
|
116
|
+
f"?processDefinitionKey={self.process_key}" \
|
|
117
|
+
f"&tenantIdIn={self.tenant_id}" \
|
|
118
|
+
f"&variables=intVar_XXX_1,strVar_eq_hello"
|
|
119
|
+
responses.add(responses.GET, get_process_instance_url, status=HTTPStatus.BAD_REQUEST, json=resp_payload)
|
|
120
|
+
with self.assertRaises(Exception) as exception_ctx:
|
|
121
|
+
self.client.get_process_instance(process_key=self.process_key,
|
|
122
|
+
variables=["intVar_XXX_1", "strVar_eq_hello"],
|
|
123
|
+
tenant_ids=[self.tenant_id])
|
|
124
|
+
|
|
125
|
+
self.assertEqual(f"received 400 : InvalidRequestException : {expected_message}", str(exception_ctx.exception))
|
|
126
|
+
|
|
127
|
+
@responses.activate
|
|
128
|
+
def test_auth_basic_get_process_instance_server_error_raises_exception(self):
|
|
129
|
+
get_process_instance_url = f"{ENGINE_LOCAL_BASE_URL}/process-instance" \
|
|
130
|
+
f"?processDefinitionKey={self.process_key}" \
|
|
131
|
+
f"&tenantIdIn={self.tenant_id}" \
|
|
132
|
+
f"&variables=intVar_XXX_1,strVar_eq_hello"
|
|
133
|
+
responses.add(responses.GET, get_process_instance_url, status=HTTPStatus.INTERNAL_SERVER_ERROR)
|
|
134
|
+
with self.assertRaises(Exception) as exception_ctx:
|
|
135
|
+
self.client.get_process_instance(process_key=self.process_key,
|
|
136
|
+
variables=["intVar_XXX_1", "strVar_eq_hello"],
|
|
137
|
+
tenant_ids=[self.tenant_id])
|
|
138
|
+
|
|
139
|
+
self.assertEqual(HTTPStatus.INTERNAL_SERVER_ERROR, exception_ctx.exception.response.status_code)
|
|
140
|
+
self.assertIn("Server Error: Internal Server Error", str(exception_ctx.exception))
|
|
141
|
+
|
|
142
|
+
@patch('requests.post')
|
|
143
|
+
def test_auth_basic_correlate_message_with_only_message_name(self, mock_post):
|
|
144
|
+
expected_request_payload = {
|
|
145
|
+
"messageName": "CANCEL_MESSAGE",
|
|
146
|
+
"withoutTenantId": True,
|
|
147
|
+
"resultEnabled": True
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
self.client.correlate_message("CANCEL_MESSAGE")
|
|
151
|
+
mock_post.assert_called_with(ENGINE_LOCAL_BASE_URL + "/message",
|
|
152
|
+
json=expected_request_payload,
|
|
153
|
+
headers={'Content-Type': 'application/json',
|
|
154
|
+
'Authorization': 'Basic ZGVtbzpkZW1v'})
|
|
155
|
+
|
|
156
|
+
@patch('requests.post')
|
|
157
|
+
def test_auth_basic_correlate_message_with_business_key(self, mock_post):
|
|
158
|
+
expected_request_payload = {
|
|
159
|
+
"messageName": "CANCEL_MESSAGE",
|
|
160
|
+
"withoutTenantId": True,
|
|
161
|
+
"businessKey": "123456",
|
|
162
|
+
"resultEnabled": True
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
self.client.correlate_message("CANCEL_MESSAGE", business_key="123456")
|
|
166
|
+
mock_post.assert_called_with(ENGINE_LOCAL_BASE_URL + "/message",
|
|
167
|
+
json=expected_request_payload,
|
|
168
|
+
headers={'Content-Type': 'application/json',
|
|
169
|
+
'Authorization': 'Basic ZGVtbzpkZW1v'})
|
|
170
|
+
|
|
171
|
+
@patch('requests.post')
|
|
172
|
+
def test_auth_basic_correlate_message_with_tenant_id(self, mock_post):
|
|
173
|
+
expected_request_payload = {
|
|
174
|
+
"messageName": "CANCEL_MESSAGE",
|
|
175
|
+
"withoutTenantId": False,
|
|
176
|
+
"tenantId": "123456",
|
|
177
|
+
"resultEnabled": True
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
self.client.correlate_message("CANCEL_MESSAGE", tenant_id="123456")
|
|
181
|
+
mock_post.assert_called_with(ENGINE_LOCAL_BASE_URL + "/message",
|
|
182
|
+
json=expected_request_payload,
|
|
183
|
+
headers={'Content-Type': 'application/json',
|
|
184
|
+
'Authorization': 'Basic ZGVtbzpkZW1v'})
|
|
185
|
+
|
|
186
|
+
@responses.activate
|
|
187
|
+
def test_auth_basic_correlate_message_invalid_message_name_raises_exception(self):
|
|
188
|
+
expected_message = "org.operaton.bpm.engine.MismatchingMessageCorrelationException: " \
|
|
189
|
+
"Cannot correlate message 'XXX': No process definition or execution matches the parameters"
|
|
190
|
+
resp_payload = {
|
|
191
|
+
"type": "RestException",
|
|
192
|
+
"message": expected_message
|
|
193
|
+
}
|
|
194
|
+
correlate_msg_url = f"{ENGINE_LOCAL_BASE_URL}/message"
|
|
195
|
+
responses.add(responses.POST, correlate_msg_url, status=HTTPStatus.BAD_REQUEST, json=resp_payload)
|
|
196
|
+
with self.assertRaises(Exception) as exception_ctx:
|
|
197
|
+
self.client.correlate_message(message_name="XXX")
|
|
198
|
+
|
|
199
|
+
self.assertEqual(f"received 400 : RestException : {expected_message}", str(exception_ctx.exception))
|
|
200
|
+
|
|
201
|
+
@responses.activate
|
|
202
|
+
def test_auth_basic_get_process_instance_variable_without_meta(self):
|
|
203
|
+
process_instance_id = "c2c68785-9f42-11ea-a841-0242ac1c0004"
|
|
204
|
+
variable_name = "var1"
|
|
205
|
+
process_instance_var_url = \
|
|
206
|
+
f"{ENGINE_LOCAL_BASE_URL}/process-instance/{process_instance_id}/variables/{variable_name}"
|
|
207
|
+
resp_frame_payload = {"value": None, "valueInfo": {}, "type": ""}
|
|
208
|
+
resp_data_payload = base64.decodebytes(b"operaton")
|
|
209
|
+
process_instance_var_data_url = f"{process_instance_var_url}/data"
|
|
210
|
+
|
|
211
|
+
responses.add(responses.GET, process_instance_var_url, status=HTTPStatus.OK, json=resp_frame_payload)
|
|
212
|
+
responses.add(responses.GET, process_instance_var_data_url, status=HTTPStatus.OK, body=resp_data_payload)
|
|
213
|
+
|
|
214
|
+
resp = self.client.get_process_instance_variable(process_instance_id, variable_name)
|
|
215
|
+
self.assertEqual("operaton\n", resp)
|
|
216
|
+
|
|
217
|
+
@responses.activate
|
|
218
|
+
def test_auth_basic_get_process_instance_variable_with_meta(self):
|
|
219
|
+
process_instance_id = "c2c68785-9f42-11ea-a841-0242ac1c0004"
|
|
220
|
+
variable_name = "var1"
|
|
221
|
+
process_instance_var_url = \
|
|
222
|
+
f"{ENGINE_LOCAL_BASE_URL}/process-instance/{process_instance_id}/variables/{variable_name}"
|
|
223
|
+
resp_frame_payload = {"value": None, "valueInfo": {}, "type": ""}
|
|
224
|
+
resp_data_payload = base64.decodebytes(b"operaton")
|
|
225
|
+
process_instance_var_data_url = f"{process_instance_var_url}/data"
|
|
226
|
+
|
|
227
|
+
responses.add(responses.GET, process_instance_var_url, status=HTTPStatus.OK, json=resp_frame_payload)
|
|
228
|
+
responses.add(responses.GET, process_instance_var_data_url, status=HTTPStatus.OK, body=resp_data_payload)
|
|
229
|
+
|
|
230
|
+
resp = self.client.get_process_instance_variable(process_instance_id, variable_name, True)
|
|
231
|
+
self.assertEqual({"value": "operaton\n", "valueInfo": {}, "type": ""}, resp)
|