diff --git a/spiffworkflow-backend/conftest.py b/spiffworkflow-backend/conftest.py index 17daaaa0..a309ddd2 100644 --- a/spiffworkflow-backend/conftest.py +++ b/spiffworkflow-backend/conftest.py @@ -4,6 +4,7 @@ import shutil import pytest from flask.app import Flask +from flask.testing import FlaskClient from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel from tests.spiffworkflow_backend.helpers.base_test import BaseTest @@ -78,17 +79,35 @@ def with_super_admin_user() -> UserModel: @pytest.fixture() -def setup_process_instances_for_reports() -> list[ProcessInstanceModel]: +def setup_process_instances_for_reports(client: FlaskClient, with_super_admin_user: UserModel) -> list[ProcessInstanceModel]: """Setup_process_instances_for_reports.""" - user = BaseTest.find_or_create_user() + user = with_super_admin_user process_group_id = "runs_without_input" process_model_id = "sample" - load_test_spec(process_group_id=process_group_id, process_model_id=process_model_id) + bpmn_file_name = "sample.bpmn" + bpmn_file_location = "sample" + process_model_identifier = BaseTest().basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + # bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location + ) + + # BaseTest().create_process_group( + # client=client, user=user, process_group_id=process_group_id, display_name=process_group_id + # ) + # process_model_id = "runs_without_input/sample" + # load_test_spec( + # process_model_id=f"{process_group_id}/{process_model_id}", + # process_model_source_directory="sample" + # ) process_instances = [] for data in [kay(), ray(), jay()]: process_instance = ProcessInstanceService.create_process_instance( - process_group_identifier=process_group_id, - process_model_identifier=process_model_id, + # process_group_identifier=process_group_id, + process_model_identifier=process_model_identifier, user=user, ) processor = ProcessInstanceProcessor(process_instance) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml index 335da19f..6bbe4eb1 100755 --- a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml @@ -288,6 +288,36 @@ paths: schema: $ref: "#/components/schemas/ProcessModel" + /process-models/{modified_process_model_id}/files: + parameters: + - name: modified_process_model_id + in: path + required: true + description: The process_model_id, modified to replace slashes (/) + schema: + type: string + post: + operationId: spiffworkflow_backend.routes.process_api_blueprint.add_file_2 + summary: Add a new workflow spec file + tags: + - Process Model Files + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + responses: + "201": + description: Metadata about the uploaded file, but not the file content. + content: + application/json: + schema: + $ref: "#/components/schemas/File" + /process-models/{process_group_id}/{process_model_id}/files: parameters: - name: process_group_id @@ -339,6 +369,56 @@ paths: # items: # $ref: "#/components/schemas/File" + /process-models/{modified_process_model_identifier}: + parameters: + - name: modified_process_model_identifier + in: path + required: true + description: the modified process model id + schema: + type: string + get: + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_show_2 + summary: Returns a single process model + tags: + - Process Models + responses: + "200": + description: Workflow spec. + content: + application/json: + schema: + $ref: "#/components/schemas/ProcessModel" + put: + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_update_2 + summary: Modifies an existing process model with the given parameters. + tags: + - Process Models + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ProcessModel" + responses: + "200": + description: Process model updated successfully. + content: + application/json: + schema: + $ref: "#/components/schemas/ProcessModel" + delete: + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_delete_2 + summary: Removes an existing process model + tags: + - Process Models + responses: + "200": + description: The process model has been removed. + content: + application/json: + schema: + $ref: "#/components/schemas/OkTrue" + /process-models/{process_group_id}/{process_model_id}: parameters: - name: process_group_id @@ -550,6 +630,28 @@ paths: schema: $ref: "#/components/schemas/Workflow" + /process-models/{modified_process_model_id}/process-instances: + parameters: + - name: modified_process_model_id + in: path + required: true + description: The unique id of an existing process model. + schema: + type: string + # process_instance_create + post: + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_create_2 + summary: Creates an process instance from a process model and returns the instance + tags: + - Process Instances + responses: + "201": + description: Workflow generated successfully + content: + application/json: + schema: + $ref: "#/components/schemas/Workflow" + /process-models/{process_group_id}/{process_model_id}/process-instances: parameters: - name: process_group_id @@ -578,6 +680,54 @@ paths: schema: $ref: "#/components/schemas/Workflow" + /process-instances/{process_instance_id}: + parameters: + - name: process_instance_id + in: path + required: true + description: The unique id of an existing process instance. + schema: + type: integer + delete: + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_delete_2 + summary: Deletes a single process instance + tags: + - Process Instances + responses: + "200": + description: The process instance was deleted. + content: + application/json: + schema: + $ref: "#/components/schemas/OkTrue" + + /process-models/{modified_process_model_identifier}/process-instances/{process_instance_id}: + parameters: + - name: modified_process_model_identifier + in: path + required: true + description: The unique id of an existing process model + schema: + type: string + - name: process_instance_id + in: path + required: true + description: The unique id of an existing process instance. + schema: + type: integer + get: + tags: + - Process Instances + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_show_2 + summary: Show information about a process instance + responses: + "200": + description: One Process Instance + content: + application/json: + schema: + $ref: "#/components/schemas/Workflow" + /process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}: parameters: - name: process_group_id @@ -624,6 +774,34 @@ paths: schema: $ref: "#/components/schemas/OkTrue" + /process-instances/{process_instance_id}/run: + parameters: + - name: process_instance_id + in: path + required: true + description: The unique id of an existing process instance. + schema: + type: integer + - name: do_engine_steps + in: query + required: false + description: Defaults to true, can be set to false if you are just looking at the workflow not completeing it. + schema: + type: boolean + # process_instance_run + post: + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_run_2 + summary: Run a process instance + tags: + - Process Instances + responses: + "200": + description: Returns details about the workflows state and current task + content: + application/json: + schema: + $ref: "#/components/schemas/Workflow" + /process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run: parameters: - name: process_group_id @@ -664,6 +842,27 @@ paths: schema: $ref: "#/components/schemas/Workflow" + /process-instances/{process_instance_id}/terminate: + parameters: + - name: process_instance_id + in: path + required: true + description: The unique id of an existing process instance. + schema: + type: integer + post: + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_terminate_2 + summary: Terminate a process instance + tags: + - Process Instances + responses: + "200": + description: Empty ok true response on successful termination. + content: + application/json: + schema: + $ref: "#/components/schemas/OkTrue" + /process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/terminate: parameters: - name: process_group_id @@ -763,6 +962,41 @@ paths: schema: $ref: "#/components/schemas/OkTrue" + /process-models/{modified_process_model_identifier}/process-instances/reports: + parameters: + - name: modified_process_model_identifier + in: path + required: true + description: The unique id of an existing process model + schema: + type: string + - name: page + in: query + required: false + description: The page number to return. Defaults to page 1. + schema: + type: integer + - name: per_page + in: query + required: false + description: The page number to return. Defaults to page 1. + schema: + type: integer + get: + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_report_list_2 + summary: Returns all process instance reports for process model + tags: + - Process Instances + responses: + "200": + description: Workflow. + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Workflow" + /process-models/{process_group_id}/{process_model_id}/process-instances/reports: parameters: - name: process_group_id @@ -816,6 +1050,47 @@ paths: schema: $ref: "#/components/schemas/OkTrue" + /process-models/{modified_process_model_identifier}/process-instances/reports/{report_identifier}: + parameters: + - name: modified_process_model_identifier + in: path + required: true + description: The unique id of an existing process model. + schema: + type: string + - name: report_identifier + in: path + required: true + description: The unique id of an existing report + schema: + type: string + - name: page + in: query + required: false + description: The page number to return. Defaults to page 1. + schema: + type: integer + - name: per_page + in: query + required: false + description: The page number to return. Defaults to page 1. + schema: + type: integer + get: + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_report_show_2 + summary: Returns a report of process instances for a given process model + tags: + - Process Instances + responses: + "200": + description: Workflow. + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Workflow" + /process-models/{process_group_id}/{process_model_id}/process-instances/reports/{report_identifier}: parameters: - name: process_group_id @@ -887,6 +1162,68 @@ paths: schema: $ref: "#/components/schemas/OkTrue" + /process-models/{modified_process_model_id}/files/{file_name}: + parameters: + - name: modified_process_model_id + in: path + required: true + description: The modified process model id + schema: + type: string + - name: file_name + in: path + required: true + description: The id of the spec file + schema: + type: string + get: + operationId: spiffworkflow_backend.routes.process_api_blueprint.get_file_2 + summary: Returns metadata about the file + tags: + - Process Model Files + responses: + "200": + description: Returns the file information requested. + content: + application/json: + schema: + $ref: "#/components/schemas/File" + put: + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_file_update_2 + summary: save the contents to the given file + tags: + - Process Model Files + requestBody: + description: Log Pagination Request + required: false + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + responses: + "200": + description: Metadata about the uploaded file, but not the file content. + content: + application/json: + schema: + $ref: "#/components/schemas/OkTrue" + delete: + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_file_delete_2 + summary: Removes an existing process model file + tags: + - Process Model Files + responses: + "200": + description: The process model has been removed. + content: + application/json: + schema: + $ref: "#/components/schemas/OkTrue" + /process-models/{process_group_id}/{process_model_id}/files/{file_name}: parameters: - name: process_group_id @@ -1199,6 +1536,39 @@ paths: schema: $ref: "#/components/schemas/Workflow" + /process-instances/{process_instance_id}/logs: + parameters: + - name: process_instance_id + in: path + required: true + description: the id of the process instance + schema: + type: integer + - name: page + in: query + required: false + description: The page number to return. Defaults to page 1. + schema: + type: integer + - name: per_page + in: query + required: false + description: The number of items to show per page. Defaults to page 10. + schema: + type: integer + get: + tags: + - Process Instances + operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_log_list_2 + summary: returns a list of logs associated with the process instance + responses: + "200": + description: list of logs + content: + application/json: + schema: + $ref: "#/components/schemas/ProcessInstanceLog" + /process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/logs: parameters: - name: process_group_id diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/testing.yml b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/testing.yml index 333ced14..c678205d 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/testing.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/testing.yml @@ -41,3 +41,15 @@ permissions: users: [testuser4] allowed_permissions: [create, read, update, delete] uri: /v1.0/process-models/finance/* + + finance-admin-model-lanes: + groups: ["Finance Team"] + users: [testuser4] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-models/finance:model_with_lanes/* + + finance-admin-instance-run: + groups: ["Finance Team"] + users: [testuser4] + allowed_permissions: [create, read, update, delete] + uri: /v1.0/process-instances/* diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py index 8f8886bf..35d5d688 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py @@ -80,7 +80,7 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel): """Add_fixtures.""" try: process_model = ProcessModelService().get_process_model( - group_id="sartography-admin", process_model_id="ticket" + process_model_id="sartography-admin/ticket" ) user = UserModel.query.first() columns = [ @@ -224,11 +224,11 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel): ) -> ProcessInstanceReportModel: """Create_with_attributes.""" process_model = ProcessModelService().get_process_model( - group_id=process_group_identifier, process_model_id=process_model_identifier + process_model_id=f"{process_model_identifier}" ) process_instance_report = cls( identifier=identifier, - process_group_identifier=process_model.process_group_id, + process_group_identifier="process_model.process_group_id", process_model_identifier=process_model.id, created_by_id=user.id, report_metadata=report_metadata, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_model.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_model.py index 9558a79b..6ef48722 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_model.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_model.py @@ -29,7 +29,7 @@ class ProcessModelInfo: id: str display_name: str description: str - process_group_id: str = "" + # process_group_id: str = "" process_group: Any | None = None primary_file_name: str | None = None primary_process_id: str | None = None @@ -41,7 +41,7 @@ class ProcessModelInfo: def __post_init__(self) -> None: """__post_init__.""" - self.sort_index = f"{self.process_group_id}:{self.id}" + self.sort_index = self.id def __eq__(self, other: Any) -> bool: """__eq__.""" @@ -67,7 +67,6 @@ class ProcessModelInfoSchema(Schema): primary_file_name = marshmallow.fields.String(allow_none=True) primary_process_id = marshmallow.fields.String(allow_none=True) is_review = marshmallow.fields.Boolean(allow_none=True) - process_group_id = marshmallow.fields.String(allow_none=True) files = marshmallow.fields.List(marshmallow.fields.Nested("FileSchema")) fault_or_suspend_on_exception = marshmallow.fields.String() exception_notification_addresses = marshmallow.fields.List( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py index 06f3d19f..90729ced 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -225,9 +225,10 @@ def process_model_add( status_code=400, ) + process_group_id, _ = os.path.split(process_model_info.id) process_model_service = ProcessModelService() process_group = process_model_service.get_process_group( - process_model_info.process_group_id + process_group_id ) if process_group is None: raise ApiError( @@ -245,14 +246,29 @@ def process_model_add( ) +def process_model_delete_2(modified_process_model_identifier: str) -> flask.wrappers.Response: + process_model_id = modified_process_model_identifier.replace(":", "/") + process_group_id, process_model_id = os.path.split(process_model_id) + return process_model_delete(process_group_id, process_model_id) + + def process_model_delete( process_group_id: str, process_model_id: str ) -> flask.wrappers.Response: """Process_model_delete.""" - ProcessModelService().process_model_delete(process_model_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + ProcessModelService().process_model_delete(process_model_identifier) return Response(json.dumps({"ok": True}), status=200, mimetype="application/json") +def process_model_update_2( + modified_process_model_identifier: str, body: Dict[str, Union[str, bool, int]] +): + process_model_identifier = modified_process_model_identifier.replace(":", "/") + process_group_id, process_model_id = os.path.split(process_model_identifier) + return process_model_update(process_group_id, process_model_id, body) + + def process_model_update( process_group_id: str, process_model_id: str, body: Dict[str, Union[str, bool, int]] ) -> Any: @@ -264,14 +280,24 @@ def process_model_update( if include_item in body } - process_model = get_process_model(process_model_id, process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + process_model = get_process_model(process_model_identifier) ProcessModelService().update_spec(process_model, body_filtered) return ProcessModelInfoSchema().dump(process_model) +def process_model_show_2(modified_process_model_identifier: str) -> Any: + process_model_identifier = modified_process_model_identifier.replace(":", "/") + process_group_id, process_model_id = os.path.split(process_model_identifier) + return process_model_show(process_group_id, process_model_id) + + def process_model_show(process_group_id: str, process_model_id: str) -> Any: """Process_model_show.""" - process_model = get_process_model(process_model_id, process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + process_model = get_process_model(process_model_identifier) + # TODO: Temporary. Should not need the next line once models have correct ids + # process_model.id = process_model_identifier files = sorted(SpecFileService.get_files(process_model)) process_model.files = files process_model_json = ProcessModelInfoSchema().dump(process_model) @@ -304,9 +330,16 @@ def process_model_list( return Response(json.dumps(response_json), status=200, mimetype="application/json") +def get_file_2(modified_process_model_id: str, file_name: str) -> Any: + process_model_id_string = modified_process_model_id.replace(":", "/") + process_group_id, process_model_id = os.path.split(process_model_id_string) + return get_file(process_group_id, process_model_id, file_name) + + def get_file(process_group_id: str, process_model_id: str, file_name: str) -> Any: """Get_file.""" - process_model = get_process_model(process_model_id, process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + process_model = get_process_model(process_model_identifier) files = SpecFileService.get_files(process_model, file_name) if len(files) == 0: raise ApiError( @@ -320,15 +353,25 @@ def get_file(process_group_id: str, process_model_id: str, file_name: str) -> An file_contents = SpecFileService.get_data(process_model, file.name) file.file_contents = file_contents file.process_model_id = process_model.id - file.process_group_id = process_model.process_group_id + # file.process_group_id = process_model.process_group_id return FileSchema().dump(file) +def process_model_file_update_2( + modified_process_model_id: str, + file_name: str +) -> flask.wrappers.Response: + process_model_id = modified_process_model_id.replace(":", "/") + process_group_id, process_model_id = os.path.split(process_model_id) + return process_model_file_update(process_group_id, process_model_id, file_name) + + def process_model_file_update( process_group_id: str, process_model_id: str, file_name: str ) -> flask.wrappers.Response: """Process_model_file_update.""" - process_model = get_process_model(process_model_id, process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + process_model = get_process_model(process_model_identifier) request_file = get_file_from_request() request_file_contents = request_file.stream.read() @@ -352,11 +395,18 @@ def process_model_file_update( return Response(json.dumps({"ok": True}), status=200, mimetype="application/json") +def process_model_file_delete_2(modified_process_model_id, file_name): + process_model_identifier = modified_process_model_id.replace(":", "/") + process_group_id, process_model_id = os.path.split(process_model_identifier) + return process_model_file_delete(process_group_id, process_model_id, file_name) + + def process_model_file_delete( process_group_id: str, process_model_id: str, file_name: str ) -> flask.wrappers.Response: """Process_model_file_delete.""" - process_model = get_process_model(process_model_id, process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + process_model = get_process_model(process_model_identifier) try: SpecFileService.delete_file(process_model, file_name) except FileNotFoundError as exception: @@ -371,9 +421,16 @@ def process_model_file_delete( return Response(json.dumps({"ok": True}), status=200, mimetype="application/json") +def add_file_2(modified_process_model_id: str) -> flask.wrappers.Response: + process_model_id_string = modified_process_model_id.replace(":", "/") + process_group_id, process_model_id = os.path.split(process_model_id_string) + return add_file(process_group_id, process_model_id) + + def add_file(process_group_id: str, process_model_id: str) -> flask.wrappers.Response: """Add_file.""" - process_model = get_process_model(process_model_id, process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + process_model = get_process_model(process_model_identifier) request_file = get_file_from_request() if not request_file.filename: raise ApiError( @@ -388,18 +445,35 @@ def add_file(process_group_id: str, process_model_id: str) -> flask.wrappers.Res file_contents = SpecFileService.get_data(process_model, file.name) file.file_contents = file_contents file.process_model_id = process_model.id - file.process_group_id = process_model.process_group_id + # file.process_group_id = process_model.process_group_id return Response( json.dumps(FileSchema().dump(file)), status=201, mimetype="application/json" ) +def process_instance_create_2( + modified_process_model_id: str +) -> flask.wrappers.Response: + """Create_process_instance.""" + process_model_id = modified_process_model_id.replace(":", "/") + process_instance = ProcessInstanceService.create_process_instance( + process_model_id, g.user + ) + return Response( + json.dumps(ProcessInstanceModelSchema().dump(process_instance)), + status=201, + mimetype="application/json", + ) + + def process_instance_create( process_group_id: str, process_model_id: str ) -> flask.wrappers.Response: """Create_process_instance.""" + # process_model_id = modified_process_model_id.replace(":", "/") + process_model_identifier = f"{process_group_id}/{process_model_id}" process_instance = ProcessInstanceService.create_process_instance( - process_model_id, g.user, process_group_identifier=process_group_id + process_model_identifier, g.user ) return Response( json.dumps(ProcessInstanceModelSchema().dump(process_instance)), @@ -408,6 +482,13 @@ def process_instance_create( ) +def process_instance_run_2( + process_instance_id: int, + do_engine_steps: bool = True, +): + return process_instance_run(None, None, process_instance_id, do_engine_steps) + + def process_instance_run( process_group_id: str, process_model_id: str, @@ -415,6 +496,7 @@ def process_instance_run( do_engine_steps: bool = True, ) -> flask.wrappers.Response: """Process_instance_run.""" + # process_model_id = modified_process_model_id.replace(":", "/") process_instance = ProcessInstanceService().get_process_instance( process_instance_id ) @@ -452,6 +534,12 @@ def process_instance_run( ) +def process_instance_terminate_2( + process_instance_id: int +) -> flask.wrappers.Response: + return process_instance_terminate(None, None, process_instance_id, None) + + def process_instance_terminate( process_group_id: str, process_model_id: str, @@ -495,6 +583,15 @@ def process_instance_resume( return Response(json.dumps({"ok": True}), status=200, mimetype="application/json") +def process_instance_log_list_2( + process_instance_id: str, + page: int = 1, + per_page: int = 100, +) -> flask.wrappers.Response: + print("process_instance_log_list_2") + return process_instance_log_list(None, None, process_instance_id, page, per_page) + + def process_instance_log_list( process_group_id: str, process_model_id: str, @@ -672,7 +769,7 @@ def process_instance_list( process_instance_query = ProcessInstanceModel.query if process_model_identifier is not None and process_group_identifier is not None: process_model = get_process_model( - process_model_identifier, process_group_identifier + f"{process_group_identifier}/{process_model_identifier}", ) process_instance_query = process_instance_query.filter_by( @@ -730,13 +827,20 @@ def process_instance_list( return make_response(jsonify(response_json), 200) +def process_instance_show_2(modified_process_model_identifier: str, process_instance_id: int) -> flask.wrappers.Response: + process_model_identifier = modified_process_model_identifier.replace(":", "/") + process_group_id, process_model_id = os.path.split(process_model_identifier) + return process_instance_show(process_group_id, process_model_id, process_instance_id) + + def process_instance_show( process_group_id: str, process_model_id: str, process_instance_id: int ) -> flask.wrappers.Response: """Create_process_instance.""" + process_model_identifier = f"{process_group_id}/{process_model_id}" process_instance = find_process_instance_by_id_or_raise(process_instance_id) current_version_control_revision = GitService.get_current_revision() - process_model = get_process_model(process_model_id, process_group_id) + process_model = get_process_model(process_model_identifier) if process_model.primary_file_name: if ( @@ -755,6 +859,12 @@ def process_instance_show( return make_response(jsonify(process_instance), 200) +def process_instance_delete_2( + process_instance_id: int +) -> flask.wrappers.Response: + return process_instance_delete(None, None, process_instance_id) + + def process_instance_delete( process_group_id: str, process_model_id: str, process_instance_id: int ) -> flask.wrappers.Response: @@ -769,15 +879,24 @@ def process_instance_delete( return Response(json.dumps({"ok": True}), status=200, mimetype="application/json") +def process_instance_report_list_2( + modified_process_model_identifier: str, page: int = 1, per_page: int = 100 +) -> flask.wrappers.Response: + process_model_identifier = modified_process_model_identifier.replace(":", "/") + process_group_id, process_model_id = os.path.split(process_model_identifier) + return process_instance_report_list(process_group_id, process_model_id, page, per_page) + + def process_instance_report_list( process_group_id: str, process_model_id: str, page: int = 1, per_page: int = 100 ) -> flask.wrappers.Response: """Process_instance_report_list.""" - process_model = get_process_model(process_model_id, process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + # process_model = get_process_model(process_model_identifier) process_instance_reports = ProcessInstanceReportModel.query.filter_by( - process_group_identifier=process_group_id, - process_model_identifier=process_model.id, + # process_group_identifier="process_group_id", + process_model_identifier=process_model_identifier, ).all() return make_response(jsonify(process_instance_reports), 200) @@ -884,6 +1003,17 @@ def authentication_callback( ) +def process_instance_report_show_2( + modified_process_model_identifier: str, + report_identifier: str, + page: int = 1, + per_page: int = 100, +) -> flask.wrappers.Response: + process_model_identifier = modified_process_model_identifier.replace(":", "/") + process_group_id, process_model_id = os.path.split(process_model_identifier) + return process_instance_report_show(process_group_id, process_model_id, report_identifier, page, per_page) + + def process_instance_report_show( process_group_id: str, process_model_id: str, @@ -892,10 +1022,11 @@ def process_instance_report_show( per_page: int = 100, ) -> flask.wrappers.Response: """Process_instance_list.""" - process_model = get_process_model(process_model_id, process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + process_model = get_process_model(process_model_identifier) process_instances = ( - ProcessInstanceModel.query.filter_by(process_model_identifier=process_model.id) + ProcessInstanceModel.query.filter_by(process_model_identifier=process_model_identifier) .order_by( ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore ) @@ -1002,7 +1133,6 @@ def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response process_model = get_process_model( process_instance.process_model_identifier, - process_instance.process_group_identifier, ) form_schema_file_name = "" @@ -1271,12 +1401,12 @@ def get_file_from_request() -> Any: return request_file -def get_process_model(process_model_id: str, process_group_id: str) -> ProcessModelInfo: +def get_process_model(process_model_id: str) -> ProcessModelInfo: """Get_process_model.""" process_model = None try: process_model = ProcessModelService().get_process_model( - process_model_id, group_id=process_group_id + process_model_id ) except ProcessEntityNotFoundError as exception: raise ( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py index 36c66d93..3f1622a4 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py @@ -35,7 +35,7 @@ class ErrorHandlingService: ) -> None: """On unhandled exceptions, set instance.status based on model.fault_or_suspend_on_exception.""" process_model = ProcessModelService().get_process_model( - _processor.process_model_identifier, _processor.process_group_identifier + _processor.process_model_identifier ) if process_model.fault_or_suspend_on_exception == "suspend": self.set_instance_status( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py index 3b23ce1b..2903ff2f 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py @@ -54,18 +54,20 @@ class FileSystemService: @staticmethod def process_group_path_for_spec(spec: ProcessModelInfo) -> str: """Category_path_for_spec.""" - return FileSystemService.process_group_path(spec.process_group_id) + process_group_id, _ = os.path.split(spec.id) + return FileSystemService.process_group_path(process_group_id) @staticmethod def workflow_path(spec: ProcessModelInfo) -> str: """Workflow_path.""" - process_group_path = FileSystemService.process_group_path_for_spec(spec) - return os.path.join(process_group_path, spec.id) + process_model_path = os.path.join(FileSystemService.root_path(), spec.id) + # process_group_path = FileSystemService.process_group_path_for_spec(spec) + return process_model_path @staticmethod - def full_path_to_process_model_file(spec: ProcessModelInfo, file_name: str) -> str: + def full_path_to_process_model_file(spec: ProcessModelInfo) -> str: """Full_path_to_process_model_file.""" - return os.path.join(FileSystemService.workflow_path(spec), file_name) + return os.path.join(FileSystemService.workflow_path(spec), spec.primary_file_name) def next_display_order(self, spec: ProcessModelInfo) -> int: """Next_display_order.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py index da1e6224..216a66a5 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py @@ -120,7 +120,6 @@ class MessageService: process_instance_receive = ProcessInstanceService.create_process_instance( message_triggerable_process_model.process_model_identifier, user, - process_group_identifier=message_triggerable_process_model.process_group_identifier, ) processor_receive = ProcessInstanceProcessor(process_instance_receive) processor_receive.do_engine_steps(save=False) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py index a2fe0d44..15001805 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -264,8 +264,7 @@ class ProcessInstanceProcessor: bpmn_process_spec, subprocesses, ) = ProcessInstanceProcessor.get_process_model_and_subprocesses( - process_instance_model.process_model_identifier, - process_instance_model.process_group_identifier, + process_instance_model.process_model_identifier ) else: bpmn_json_length = len(process_instance_model.bpmn_json.encode("utf-8")) @@ -316,7 +315,7 @@ class ProcessInstanceProcessor: check_sub_specs(test_spec, 5) self.process_model_identifier = process_instance_model.process_model_identifier - self.process_group_identifier = process_instance_model.process_group_identifier + # self.process_group_identifier = process_instance_model.process_group_identifier try: self.bpmn_process_instance = self.__get_bpmn_process_instance( @@ -351,17 +350,17 @@ class ProcessInstanceProcessor: @classmethod def get_process_model_and_subprocesses( - cls, process_model_identifier: str, process_group_identifier: str + cls, process_model_identifier: str ) -> Tuple[BpmnProcessSpec, IdToBpmnProcessSpecMapping]: """Get_process_model_and_subprocesses.""" process_model_info = ProcessModelService().get_process_model( - process_model_identifier, process_group_identifier + process_model_identifier ) if process_model_info is None: raise ( ApiError( "process_model_not_found", - f"The given process model was not found: {process_group_identifier}/{process_model_identifier}.", + f"The given process model was not found: {process_model_identifier}.", ) ) spec_files = SpecFileService.get_files(process_model_info) @@ -369,12 +368,11 @@ class ProcessInstanceProcessor: @classmethod def get_bpmn_process_instance_from_process_model( - cls, process_model_identifier: str, process_group_identifier: str + cls, process_model_identifier: str ) -> BpmnWorkflow: """Get_all_bpmn_process_identifiers_for_process_model.""" (bpmn_process_spec, subprocesses) = cls.get_process_model_and_subprocesses( process_model_identifier, - process_group_identifier, ) return cls.get_bpmn_process_instance_from_workflow_spec( bpmn_process_spec, subprocesses @@ -676,7 +674,7 @@ class ProcessInstanceProcessor: etree_element, ) return FileSystemService.full_path_to_process_model_file( - process_model, process_model.primary_file_name + process_model ) return None @@ -685,6 +683,7 @@ class ProcessInstanceProcessor: bpmn_process_identifier: str, ) -> str: """Bpmn_file_full_path_from_bpmn_process_identifier.""" + db.session.flush() bpmn_process_id_lookup = BpmnProcessIdLookup.query.filter_by( bpmn_process_identifier=bpmn_process_identifier ).first() diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py index 214dc4f7..dab7013e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py @@ -36,7 +36,6 @@ class ProcessInstanceService: def create_process_instance( process_model_identifier: str, user: UserModel, - process_group_identifier: Optional[str] = None, ) -> ProcessInstanceModel: """Get_process_instance_from_spec.""" current_git_revision = GitService.get_current_revision() @@ -44,7 +43,7 @@ class ProcessInstanceService: status=ProcessInstanceStatus.not_started.value, process_initiator=user, process_model_identifier=process_model_identifier, - process_group_identifier=process_group_identifier, + process_group_identifier="", start_in_seconds=round(time.time()), bpmn_version_control_type="git", bpmn_version_control_identifier=current_git_revision, @@ -101,7 +100,7 @@ class ProcessInstanceService: next_task=None, # navigation=navigation, process_model_identifier=processor.process_model_identifier, - process_group_identifier=processor.process_group_identifier, + process_group_identifier="", # total_tasks=len(navigation), completed_tasks=processor.process_instance_model.completed_tasks, updated_at_in_seconds=processor.process_instance_model.updated_at_in_seconds, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py index 4f3d4512..8d65ed91 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py @@ -74,7 +74,7 @@ class ProcessModelService(FileSystemService): def save_process_model(self, process_model: ProcessModelInfo) -> None: """Save_process_model.""" - spec_path = self.workflow_path(process_model) + spec_path = os.path.join(FileSystemService.root_path(), process_model.id) os.makedirs(spec_path, exist_ok=True) json_path = os.path.join(spec_path, self.WF_JSON_FILE) with open(json_path, "w") as wf_json: @@ -93,7 +93,8 @@ class ProcessModelService(FileSystemService): message=f"We cannot delete the model `{process_model_id}`, there are existing instances that depend on it.", ) process_model = self.get_process_model(process_model_id) - path = self.workflow_path(process_model) + # path = self.workflow_path(process_model) + path = f"{FileSystemService.root_path()}/{process_model_id}" shutil.rmtree(path) @classmethod @@ -101,36 +102,43 @@ class ProcessModelService(FileSystemService): cls, relative_path: str ) -> ProcessModelInfo: """Get_process_model_from_relative_path.""" - process_group_identifier = os.path.dirname(relative_path) + process_group_identifier, _ = os.path.split(relative_path) process_group = cls().get_process_group(process_group_identifier) path = os.path.join(FileSystemService.root_path(), relative_path) return cls().__scan_spec(path, process_group=process_group) def get_process_model( - self, process_model_id: str, group_id: Optional[str] = None + self, process_model_id: str ) -> ProcessModelInfo: - """Get a process model from a model and group id.""" + """Get a process model from a model and group id. + process_model_id is the full path to the model--including groups""" if not os.path.exists(FileSystemService.root_path()): - raise ProcessEntityNotFoundError("process_model_not_found") + raise ProcessEntityNotFoundError("process_model_root_not_found") - if group_id is not None: - process_group = self.get_process_group(group_id) - if process_group is not None: - for process_model in process_group.process_models: - if process_model_id == process_model.id: - return process_model - with os.scandir(FileSystemService.root_path()) as process_group_dirs: - for item in process_group_dirs: - process_group_dir = item - if item.is_dir(): - with os.scandir(item.path) as spec_dirs: - for sd in spec_dirs: - if sd.name == process_model_id: - # Now we have the process_group direcotry, and spec directory - process_group = self.__scan_process_group( - process_group_dir - ) - return self.__scan_spec(sd.path, sd.name, process_group) + model_path = os.path.join(FileSystemService.root_path(), process_model_id) + if self.is_model(model_path): + process_model = self.get_process_model_from_relative_path(process_model_id) + return process_model + + # group_path, model_id = os.path.split(process_model_id) + # if group_path is not None: + # process_group = self.get_process_group(group_path) + # if process_group is not None: + # for process_model in process_group.process_models: + # if process_model_id == process_model.id: + # return process_model + # with os.scandir(FileSystemService.root_path()) as process_group_dirs: + # for item in process_group_dirs: + # process_group_dir = item + # if item.is_dir(): + # with os.scandir(item.path) as spec_dirs: + # for sd in spec_dirs: + # if sd.name == process_model_id: + # # Now we have the process_group directory, and spec directory + # process_group = self.__scan_process_group( + # process_group_dir + # ) + # return self.__scan_spec(sd.path, sd.name, process_group) raise ProcessEntityNotFoundError("process_model_not_found") def get_process_models( @@ -162,22 +170,22 @@ class ProcessModelService(FileSystemService): if os.path.exists(FileSystemService.root_path()): process_group_path = os.path.join(FileSystemService.root_path(), process_group_id) if self.is_group(process_group_path): - nested_groups = [] - process_group_dir = os.scandir(process_group_path) - for item in process_group_dir: - if self.is_group(item.path): - nested_group = self.get_process_group(os.path.join(process_group_path, item.path)) - nested_groups.append(nested_group) - elif self.is_model(item.path): - print("get_process_group: ") - return self.__scan_process_group(process_group_path) + return self.__scan_process_group(process_group_path) + # nested_groups = [] + # process_group_dir = os.scandir(process_group_path) + # for item in process_group_dir: + # if self.is_group(item.path): + # nested_group = self.get_process_group(os.path.join(process_group_path, item.path)) + # nested_groups.append(nested_group) + # elif self.is_model(item.path): + # print("get_process_group: ") + # return self.__scan_process_group(process_group_path) # with os.scandir(FileSystemService.root_path()) as directory_items: # for item in directory_items: # if item.is_dir() and item.name == process_group_id: # return self.__scan_process_group(item) - else: - raise ProcessEntityNotFoundError( + raise ProcessEntityNotFoundError( "process_group_not_found", f"Process Group Id: {process_group_id}" ) @@ -228,13 +236,13 @@ class ProcessModelService(FileSystemService): for item in directory_items: # if item.is_dir() and not item.name[0] == ".": if item.is_dir() and self.is_group(item): - scanned_process_group = self.__scan_process_group(item) + scanned_process_group = self.__scan_process_group(item.path) process_groups.append(scanned_process_group) return process_groups - def __scan_process_group(self, dir_item: os.DirEntry) -> ProcessGroup: + def __scan_process_group(self, dir_path: str) -> ProcessGroup: """Reads the process_group.json file, and any nested directories.""" - cat_path = os.path.join(dir_item.path, self.CAT_JSON_FILE) + cat_path = os.path.join(dir_path, self.CAT_JSON_FILE) if os.path.exists(cat_path): with open(cat_path) as cat_json: data = json.load(cat_json) @@ -242,18 +250,19 @@ class ProcessModelService(FileSystemService): if process_group is None: raise ApiError( error_code="process_group_could_not_be_loaded_from_disk", - message=f"We could not load the process_group from disk from: {dir_item}", + message=f"We could not load the process_group from disk from: {dir_path}", ) else: + process_group_id = dir_path.replace(FileSystemService.root_path(), '') process_group = ProcessGroup( - id=dir_item.name, - display_name=dir_item.name, + id=process_group_id, + display_name=process_group_id, display_order=10000, admin=False, ) with open(cat_path, "w") as wf_json: json.dump(self.GROUP_SCHEMA.dump(process_group), wf_json, indent=4) - with os.scandir(dir_item.path) as nested_items: + with os.scandir(dir_path) as nested_items: process_group.process_models = [] for nested_item in nested_items: if nested_item.is_dir(): @@ -282,6 +291,8 @@ class ProcessModelService(FileSystemService): if os.path.exists(spec_path): with open(spec_path) as wf_json: data = json.load(wf_json) + if "process_group_id" in data: + data.pop("process_group_id") spec = ProcessModelInfo(**data) if spec is None: raise ApiError( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py index 4e1e30e2..443f50cf 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py @@ -42,7 +42,8 @@ class SpecFileService(FileSystemService): extension_filter: str = "", ) -> List[File]: """Return all files associated with a workflow specification.""" - path = SpecFileService.workflow_path(process_model_info) + # path = SpecFileService.workflow_path(process_model_info) + path = os.path.join(FileSystemService.root_path(), process_model_info.id) files = SpecFileService._get_files(path, file_name) if extension_filter != "": files = list( @@ -64,7 +65,8 @@ class SpecFileService(FileSystemService): ) -> File: """Update_file.""" SpecFileService.assert_valid_file_name(file_name) - file_path = SpecFileService.file_path(process_model_info, file_name) + # file_path = SpecFileService.file_path(process_model_info, file_name) + file_path = os.path.join(FileSystemService.root_path(), process_model_info.id, file_name) SpecFileService.write_file_data_to_system(file_path, binary_data) file = SpecFileService.to_file_object(file_name, file_path) @@ -88,7 +90,8 @@ class SpecFileService(FileSystemService): @staticmethod def get_data(process_model_info: ProcessModelInfo, file_name: str) -> bytes: """Get_data.""" - file_path = SpecFileService.file_path(process_model_info, file_name) + # file_path = SpecFileService.file_path(process_model_info, file_name) + file_path = os.path.join(FileSystemService.root_path(), process_model_info.id, file_name) if not os.path.exists(file_path): raise ApiError( "unknown_file", @@ -123,7 +126,8 @@ class SpecFileService(FileSystemService): # for lf in lookup_files: # session.query(LookupDataModel).filter_by(lookup_file_model_id=lf.id).delete() # session.query(LookupFileModel).filter_by(id=lf.id).delete() - file_path = SpecFileService.file_path(spec, file_name) + # file_path = SpecFileService.file_path(spec, file_name) + file_path = os.path.join(FileSystemService.root_path(), spec.id, file_name) os.remove(file_path) @staticmethod @@ -327,9 +331,8 @@ class SpecFileService(FileSystemService): process_model_info: ProcessModelInfo, bpmn_file_name: str, et_root: _Element ) -> None: """Store_bpmn_process_identifiers.""" - relative_process_model_path = SpecFileService.process_model_relative_path( - process_model_info - ) + relative_process_model_path = process_model_info.id + relative_bpmn_file_path = os.path.join( relative_process_model_path, bpmn_file_name ) @@ -425,7 +428,7 @@ class SpecFileService(FileSystemService): message_triggerable_process_model = MessageTriggerableProcessModel( message_model_id=message_model.id, process_model_identifier=process_model_info.id, - process_group_identifier=process_model_info.process_group_id, + process_group_identifier="process_group_identifier", ) db.session.add(message_triggerable_process_model) db.session.commit() @@ -433,8 +436,8 @@ class SpecFileService(FileSystemService): if ( message_triggerable_process_model.process_model_identifier != process_model_info.id - or message_triggerable_process_model.process_group_identifier - != process_model_info.process_group_id + # or message_triggerable_process_model.process_group_identifier + # != process_model_info.process_group_id ): raise ValidationException( "Message model is already used to start process model" diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py index b7d2c5d7..28ec32da 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py @@ -12,6 +12,10 @@ from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db + +from spiffworkflow_backend.services.file_system_service import FileSystemService +from spiffworkflow_backend.services.process_instance_processor import ProcessInstanceProcessor +from spiffworkflow_backend.services.process_instance_service import ProcessInstanceService from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from werkzeug.test import TestResponse # type: ignore @@ -34,6 +38,43 @@ from spiffworkflow_backend.services.user_service import UserService class BaseTest: """BaseTest.""" + def basic_test_setup( + self, + client: FlaskClient, + user: UserModel, + process_group_id: Optional[str] = "test_group", + process_model_id: Optional[str] = "random_fact", + bpmn_file_name: Optional[str] = None, + bpmn_file_location: Optional[str] = None + ) -> str: + """Creates a process group + Creates a process model + Adds a bpmn file to the model""" + + process_group_display_name = process_group_id + process_group_description = process_group_id + process_model_identifier = f"{process_group_id}/{process_model_id}" + if bpmn_file_location is None: + bpmn_file_location = process_model_id + + self.create_process_group(client, user, process_group_id, process_group_display_name) + + self.create_process_model_with_api( + client, + process_model_id=process_model_identifier, + process_model_display_name=process_group_display_name, + process_model_description=process_group_description, + user=user, + ) + + load_test_spec( + process_model_id=process_model_identifier, + bpmn_file_name=bpmn_file_name, + process_model_source_directory=bpmn_file_location + ) + + return process_model_identifier + @staticmethod def find_or_create_user(username: str = "test_user_1") -> UserModel: """Find_or_create_user.""" @@ -67,17 +108,18 @@ class BaseTest: open_id_client_secret_key, ) + @staticmethod def create_process_instance( - self, client: FlaskClient, - test_process_group_id: str, test_process_model_id: str, headers: Dict[str, str], ) -> TestResponse: - """Create_process_instance.""" - load_test_spec(test_process_model_id, process_group_id=test_process_group_id) + """Create_process_instance. + There must be an existing process model to instantiate.""" + + modified_process_model_id = test_process_model_id.replace("/", ":") response = client.post( - f"/v1.0/process-models/{test_process_group_id}/{test_process_model_id}/process-instances", + f"/v1.0/process-models/{modified_process_model_id}/process-instances", headers=headers, ) assert response.status_code == 201 @@ -86,8 +128,7 @@ class BaseTest: def create_process_model_with_api( self, client: FlaskClient, - process_group_id: Optional[str] = None, - process_model_id: str = "make_cookies", + process_model_id: Optional[str] = None, process_model_display_name: str = "Cooooookies", process_model_description: str = "Om nom nom delicious cookies", fault_or_suspend_on_exception: str = NotificationType.suspend.value, @@ -97,65 +138,74 @@ class BaseTest: user: Optional[UserModel] = None, ) -> TestResponse: """Create_process_model.""" - process_model_service = ProcessModelService() - # make sure we have a group - if process_group_id is None: - process_group_tmp = ProcessGroup( - id="test_cat", - display_name="Test Category", - display_order=0, - admin=False, - ) - process_group = process_model_service.add_process_group(process_group_tmp) + if process_model_id is not None: + + # make sure we have a group + process_group_id, _ = os.path.split(process_model_id) + process_group_path = f"{FileSystemService.root_path()}/{process_group_id}" + if ProcessModelService().is_group(process_group_path): + + if exception_notification_addresses is None: + exception_notification_addresses = [] + + model = ProcessModelInfo( + id=process_model_id, + display_name=process_model_display_name, + description=process_model_description, + is_review=False, + primary_process_id=primary_process_id, + primary_file_name=primary_file_name, + fault_or_suspend_on_exception=fault_or_suspend_on_exception, + exception_notification_addresses=exception_notification_addresses, + ) + if user is None: + user = self.find_or_create_user() + + response = client.post( + "/v1.0/process-models", + content_type="application/json", + data=json.dumps(ProcessModelInfoSchema().dump(model)), + headers=self.logged_in_headers(user), + ) + assert response.status_code == 201 + return response + + else: + raise Exception("You must create the group first") else: - process_group = ProcessModelService().get_process_group(process_group_id) - - if exception_notification_addresses is None: - exception_notification_addresses = [] - model = ProcessModelInfo( - id=process_model_id, - display_name=process_model_display_name, - description=process_model_description, - process_group_id=process_group.id, - is_review=False, - primary_process_id=primary_process_id, - primary_file_name=primary_file_name, - fault_or_suspend_on_exception=fault_or_suspend_on_exception, - exception_notification_addresses=exception_notification_addresses, - ) - if user is None: - user = self.find_or_create_user() - - response = client.post( - "/v1.0/process-models", - content_type="application/json", - data=json.dumps(ProcessModelInfoSchema().dump(model)), - headers=self.logged_in_headers(user), - ) - assert response.status_code == 201 - return response + raise Exception("You must include the process_model_id, which must be a path to the model") def create_spec_file( self, client: FlaskClient, - process_group_id: str = "random_fact", - process_model_id: str = "random_fact", + process_model_id: str, + process_model_location: Optional[str] = None, process_model: Optional[ProcessModelInfo] = None, file_name: str = "random_fact.svg", file_data: bytes = b"abcdef", user: Optional[UserModel] = None, ) -> Any: - """Test_create_spec_file.""" + """Test_create_spec_file. + Adds a bpmn file to the model. + process_model_id is the destination path + process_model_location is the source path + + because of permissions, user might be required now..., not sure yet""" + if process_model_location is None: + process_model_location = file_name.split(".")[0] if process_model is None: process_model = load_test_spec( - process_model_id, process_group_id=process_group_id + process_model_id=process_model_id, + bpmn_file_name=file_name, + process_model_source_directory=process_model_location ) data = {"file": (io.BytesIO(file_data), file_name)} if user is None: user = self.find_or_create_user() + modified_process_model_id = process_model.id.replace("/", ":") response = client.post( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files", + f"/v1.0/process-models/{modified_process_model_id}/files", data=data, follow_redirects=True, content_type="multipart/form-data", @@ -168,7 +218,7 @@ class BaseTest: # assert "image/svg+xml" == file["content_type"] response = client.get( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/{file_name}", + f"/v1.0/process-models/{modified_process_model_id}/files/{file_name}", headers=self.logged_in_headers(user), ) assert response.status_code == 200 @@ -221,7 +271,7 @@ class BaseTest: status=status, process_initiator=user, process_model_identifier=process_model.id, - process_group_identifier=process_model.process_group_id, + process_group_identifier="", updated_at_in_seconds=round(time.time()), start_in_seconds=current_time - (3600 * 1), end_in_seconds=current_time - (3600 * 1 - 20), diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/example_data.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/example_data.py index a94be48e..fd8b3353 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/example_data.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/example_data.py @@ -13,27 +13,30 @@ from spiffworkflow_backend.services.spec_file_service import SpecFileService class ExampleDataLoader: """ExampleDataLoader.""" + @staticmethod def create_spec( - self, process_model_id: str, display_name: str = "", description: str = "", - process_group_id: str = "", display_order: int = 0, - from_tests: bool = False, + # from_tests: bool = False, bpmn_file_name: Optional[str] = None, - process_model_source_directory: Optional[str] = None, + process_model_source_directory: str = None, ) -> ProcessModelInfo: - """Assumes that a directory exists in static/bpmn with the same name as the given process_model_id. + """Assumes that process_model_source_directory exists in static/bpmn and contains bpmn_file_name. - further assumes that the [process_model_id].bpmn is the primary file for the process model. - returns an array of data models to be added to the database. + further assumes that bpmn_file_name is the primary file for the process model. + + if bpmn_file_name is None we load all files in process_model_source_directory, + otherwise, we only load bpmn_file_name """ + if process_model_source_directory is None: + raise Exception("You must include `process_model_source_directory`.") + spec = ProcessModelInfo( id=process_model_id, display_name=display_name, description=description, - process_group_id=process_group_id, display_order=display_order, is_review=False, ) @@ -55,25 +58,16 @@ class ExampleDataLoader: if bpmn_file_name: file_name_matcher = bpmn_file_name_with_extension - file_glob = "" - if from_tests: - file_glob = os.path.join( - current_app.instance_path, - "..", - "..", - "tests", - "data", - process_model_source_directory_to_use, - file_name_matcher, - ) - else: - file_glob = os.path.join( - current_app.root_path, - "static", - "bpmn", - process_model_source_directory_to_use, - file_name_matcher, - ) + # file_glob = "" + file_glob = os.path.join( + current_app.root_path, + "..", + "..", + "tests", + "data", + process_model_source_directory_to_use, + file_name_matcher, + ) files = glob.glob(file_glob) for file_path in files: diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py index fd418aa2..36b35998 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py @@ -37,40 +37,18 @@ def assure_process_group_exists(process_group_id: Optional[str] = None) -> Proce def load_test_spec( process_model_id: str, - process_group_id: Optional[str] = None, bpmn_file_name: Optional[str] = None, - process_model_source_directory: Optional[str] = None, + process_model_source_directory: str = None, ) -> ProcessModelInfo: - """Loads a process model into the bpmn dir based on a directory in tests/data.""" - process_group = None - process_model_service = ProcessModelService() - if process_group_id is None: - process_group_id = "test_process_group_id" - process_group = assure_process_group_exists(process_group_id) - process_group_id = process_group.id + """Loads a bpmn file into the process model dir based on a directory in tests/data.""" - try: - return process_model_service.get_process_model( - process_model_id, group_id=process_group_id - ) - except ProcessEntityNotFoundError: - spec = ExampleDataLoader().create_spec( - process_model_id=process_model_id, - from_tests=True, - display_name=process_model_id, - process_group_id=process_group_id, - bpmn_file_name=bpmn_file_name, - process_model_source_directory=process_model_source_directory, - ) - return spec + if process_model_source_directory is None: + raise Exception("You must inclode a `process_model_source_directory`.") - -# def user_info_to_query_string(user_info, redirect_url): -# query_string_list = [] -# items = user_info.items() -# for key, value in items: -# query_string_list.append('%s=%s' % (key, urllib.parse.quote(value))) -# -# query_string_list.append('redirect_url=%s' % redirect_url) -# -# return '?%s' % '&'.join(query_string_list) + spec = ExampleDataLoader.create_spec( + process_model_id=process_model_id, + display_name=process_model_id, + bpmn_file_name=bpmn_file_name, + process_model_source_directory=process_model_source_directory, + ) + return spec diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_logging_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_logging_service.py index a8d2720f..2635aada 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_logging_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_logging_service.py @@ -19,20 +19,43 @@ class TestLoggingService(BaseTest): """Test_process_instance_run.""" process_group_id = "test_logging_spiff_logger" process_model_id = "simple_script" + self.create_process_group(client=client, user=with_super_admin_user, process_group_id=process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + # create the model + process_model_info = self.create_process_model_with_api( + client=client, + process_model_id=process_model_identifier, + process_model_display_name="Simple Script", + process_model_description="Simple Script", + user=with_super_admin_user + ) + + bpmn_file_name = "simple_script.bpmn" + bpmn_file_data_bytes = self.get_test_data_file_contents( + bpmn_file_name, "simple_script" + ) + # add bpmn to the model + self.create_spec_file( + client=client, + process_model_id=process_model_identifier, + file_name=bpmn_file_name, + file_data=bpmn_file_data_bytes, + user=with_super_admin_user + ) headers = self.logged_in_headers(with_super_admin_user) response = self.create_process_instance( - client, process_group_id, process_model_id, headers + client, process_model_identifier, headers ) assert response.json is not None process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{process_instance_id}/run", headers=headers, ) assert response.status_code == 200 log_response = client.get( - f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/logs", + f"/v1.0/process-instances/{process_instance_id}/logs", headers=headers, ) assert log_response.status_code == 200 diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_nested_groups.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_nested_groups.py index 26bd7009..770d4f04 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_nested_groups.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_nested_groups.py @@ -17,7 +17,7 @@ class TestNestedGroups(BaseTest): with_db_and_bpmn_file_cleanup: None, ) -> None: # /process-groups/{process_group_path}/show - target_uri = "/v1.0/process-groups/group_a,group_b/show" + target_uri = "/v1.0/process-groups/group_a,group_b" user = self.find_or_create_user() self.add_permissions_to_user( user, target_uri=target_uri, permission_names=["read"] @@ -117,7 +117,6 @@ class TestNestedGroups(BaseTest): id="process_model", display_name="Process Model", description="Process Model", - process_group_id="group_a/group_b", primary_file_name="primary_file.bpmn", primary_process_id="primary_process_id", display_order=0 @@ -129,3 +128,45 @@ class TestNestedGroups(BaseTest): data=json.dumps(ProcessModelInfoSchema().dump(process_model)) ) print("test_process_model_add") + + def test_process_group_show( + self, + app: Flask, + client: FlaskClient, + with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel, + ) -> None: + + # target_uri = "/process-groups/{process_group_id}" + # user = self.find_or_create_user("testadmin1") + # self.add_permissions_to_user( + # user, target_uri="v1.0/process-groups", permission_names=["read", "create"] + # ) + # self.add_permissions_to_user( + # user, target_uri="/process-groups/{process_group_id}", permission_names=["read", "create"] + # ) + + process_group_a = ProcessGroup( + id="group_a", + display_name="Group A", + display_order=0, + admin=False, + ) + response_create_a = client.post( + "/v1.0/process-groups", + headers=self.logged_in_headers(with_super_admin_user), + content_type="application/json", + data=json.dumps(ProcessGroupSchema().dump(process_group_a)), + ) + + target_uri = "/v1.0/process-groups/group_a" + user = self.find_or_create_user() + self.add_permissions_to_user( + user, target_uri=target_uri, permission_names=["read"] + ) + response = client.get( + target_uri, + headers=self.logged_in_headers(user) + ) + + print("test_process_group_show: ") diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py index 2d79b652..b65dd5a0 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py @@ -1,6 +1,7 @@ """Test Process Api Blueprint.""" import io import json +import os import time from typing import Any @@ -110,10 +111,17 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_add_new_process_model.""" - process_model_identifier = "sample" - model_display_name = "Sample" - model_description = "The sample" + process_group_id = "test_process_group" + process_group_display_name = "Test Process Group" + # creates the group directory, and the json file + self.create_process_group(client, with_super_admin_user, process_group_id, process_group_display_name) + process_model_id = "sample" + model_display_name = "Sample" + model_description = "The Sample" + process_model_identifier = f"{process_group_id}/{process_model_id}" + + # creates the model directory, and adds the json file self.create_process_model_with_api( client, process_model_id=process_model_identifier, @@ -122,23 +130,27 @@ class TestProcessApi(BaseTest): user=with_super_admin_user, ) process_model = ProcessModelService().get_process_model( - process_model_identifier + process_model_identifier, ) assert model_display_name == process_model.display_name assert 0 == process_model.display_order assert 1 == len(ProcessModelService().get_process_groups()) + # add bpmn file to the model bpmn_file_name = "sample.bpmn" bpmn_file_data_bytes = self.get_test_data_file_contents( bpmn_file_name, "sample" ) self.create_spec_file( client, + process_model_id=process_model.id, + process_model_location="sample", + process_model=process_model, file_name=bpmn_file_name, file_data=bpmn_file_data_bytes, - process_model=process_model, user=with_super_admin_user, ) + # get the model, assert that primary is set process_model = ProcessModelService().get_process_model( process_model_identifier ) @@ -153,16 +165,24 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_primary_process_id_updates_via_xml.""" - process_model_identifier = "sample" + process_group_id = "test_group" + process_model_id = "sample" + process_model_identifier = f"{process_group_id}/{process_model_id}" initial_primary_process_id = "sample" terminal_primary_process_id = "new_process_id" + self.create_process_group(client=client, user=with_super_admin_user, process_group_id=process_group_id) - process_model = load_test_spec(process_model_id=process_model_identifier) + bpmn_file_name = f"{process_model_id}.bpmn" + bpmn_file_source_directory = process_model_id + process_model = load_test_spec( + process_model_id=process_model_identifier, + bpmn_file_name=bpmn_file_name, + process_model_source_directory=process_model_id + ) assert process_model.primary_process_id == initial_primary_process_id - bpmn_file_name = "sample.bpmn" bpmn_file_data_bytes = self.get_test_data_file_contents( - bpmn_file_name, "sample" + bpmn_file_name, bpmn_file_source_directory ) bpmn_file_data_string = bpmn_file_data_bytes.decode("utf-8") old_string = f'bpmn:process id="{initial_primary_process_id}"' @@ -173,8 +193,9 @@ class TestProcessApi(BaseTest): updated_bpmn_file_data_bytes = bytearray(updated_bpmn_file_data_string, "utf-8") data = {"file": (io.BytesIO(updated_bpmn_file_data_bytes), bpmn_file_name)} + modified_process_model_id = process_model_identifier.replace("/", ":") response = client.put( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/{bpmn_file_name}", + f"/v1.0/process-models/{modified_process_model_id}/files/{bpmn_file_name}", data=data, follow_redirects=True, content_type="multipart/form-data", @@ -195,19 +216,26 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_delete.""" + process_group_id = "test_process_group" + process_group_description = "Test Process Group" + process_model_id = "sample" + process_model_identifier = f"{process_group_id}/{process_model_id}" + self.create_process_group(client, with_super_admin_user, process_group_id, process_group_description) self.create_process_model_with_api( client, + process_model_id=process_model_identifier, user=with_super_admin_user, ) # assert we have a model - process_model = ProcessModelService().get_process_model("make_cookies") + process_model = ProcessModelService().get_process_model(process_model_identifier) assert process_model is not None - assert process_model.id == "make_cookies" + assert process_model.id == process_model_identifier # delete the model + modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.delete( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}", + f"/v1.0/process-models/{modified_process_model_identifier}", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 200 @@ -216,7 +244,7 @@ class TestProcessApi(BaseTest): # assert we no longer have a model with pytest.raises(ProcessEntityNotFoundError): - ProcessModelService().get_process_model("make_cookies") + ProcessModelService().get_process_model(process_model_identifier) def test_process_model_delete_with_instances( self, @@ -228,15 +256,31 @@ class TestProcessApi(BaseTest): """Test_process_model_delete_with_instances.""" test_process_group_id = "runs_without_input" test_process_model_id = "sample" + bpmn_file_name = "sample.bpmn" + bpmn_file_location = "sample" + process_model_identifier = f"{test_process_group_id}/{test_process_model_id}" + self.create_process_group(client, with_super_admin_user, test_process_group_id) + self.create_process_model_with_api(client, process_model_identifier, user=with_super_admin_user) + bpmn_file_data_bytes = self.get_test_data_file_contents( + bpmn_file_name, bpmn_file_location + ) + self.create_spec_file( + client=client, + process_model_id=process_model_identifier, + process_model_location=test_process_model_id, + file_name=bpmn_file_name, + file_data=bpmn_file_data_bytes, + user=with_super_admin_user + ) headers = self.logged_in_headers(with_super_admin_user) # create an instance from a model response = self.create_process_instance( - client, test_process_group_id, test_process_model_id, headers + client, process_model_identifier, headers ) data = json.loads(response.get_data(as_text=True)) # make sure the instance has the correct model - assert data["process_model_identifier"] == test_process_model_id + assert data["process_model_identifier"] == process_model_identifier # try to delete the model response = client.delete( @@ -250,7 +294,7 @@ class TestProcessApi(BaseTest): assert data["error_code"] == "existing_instances" assert ( data["message"] - == "We cannot delete the model `sample`, there are existing instances that depend on it." + == f"We cannot delete the model `{process_model_identifier}`, there are existing instances that depend on it." ) def test_process_model_update( @@ -261,12 +305,15 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_update.""" + self.create_process_group(client, with_super_admin_user, "test_process_group", "Test Process Group") + process_model_identifier = "test_process_group/make_cookies" self.create_process_model_with_api( client, + process_model_id=process_model_identifier, user=with_super_admin_user, ) - process_model = ProcessModelService().get_process_model("make_cookies") - assert process_model.id == "make_cookies" + process_model = ProcessModelService().get_process_model(process_model_identifier) + assert process_model.id == process_model_identifier assert process_model.display_name == "Cooooookies" assert process_model.is_review is False assert process_model.primary_file_name is None @@ -277,8 +324,9 @@ class TestProcessApi(BaseTest): process_model.primary_process_id = "superduper" process_model.is_review = True # not in the include list, so get ignored + modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.put( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}", + f"/v1.0/process-models/{modified_process_model_identifier}", headers=self.logged_in_headers(with_super_admin_user), content_type="application/json", data=json.dumps(ProcessModelInfoSchema().dump(process_model)), @@ -304,12 +352,11 @@ class TestProcessApi(BaseTest): # add 5 models to the group for i in range(5): - process_model_identifier = f"test_model_{i}" + process_model_identifier = f"{group_id}/test_model_{i}" model_display_name = f"Test Model {i}" model_description = f"Test Model {i} Description" self.create_process_model_with_api( client, - process_group_id=group_id, process_model_id=process_model_identifier, process_model_display_name=model_display_name, process_model_description=model_description, @@ -334,7 +381,7 @@ class TestProcessApi(BaseTest): ) assert response.json is not None assert len(response.json["results"]) == 1 - assert response.json["results"][0]["id"] == "test_model_0" + assert response.json["results"][0]["id"] == "test_group/test_model_0" assert response.json["pagination"]["count"] == 1 assert response.json["pagination"]["total"] == 5 assert response.json["pagination"]["pages"] == 5 @@ -346,7 +393,7 @@ class TestProcessApi(BaseTest): ) assert response.json is not None assert len(response.json["results"]) == 1 - assert response.json["results"][0]["id"] == "test_model_1" + assert response.json["results"][0]["id"] == "test_group/test_model_1" assert response.json["pagination"]["count"] == 1 assert response.json["pagination"]["total"] == 5 assert response.json["pagination"]["pages"] == 5 @@ -358,7 +405,7 @@ class TestProcessApi(BaseTest): ) assert response.json is not None assert len(response.json["results"]) == 3 - assert response.json["results"][0]["id"] == "test_model_0" + assert response.json["results"][0]["id"] == "test_group/test_model_0" assert response.json["pagination"]["count"] == 3 assert response.json["pagination"]["total"] == 5 assert response.json["pagination"]["pages"] == 2 @@ -371,7 +418,7 @@ class TestProcessApi(BaseTest): # there should only be 2 left assert response.json is not None assert len(response.json["results"]) == 2 - assert response.json["results"][0]["id"] == "test_model_3" + assert response.json["results"][0]["id"] == "test_group/test_model_3" assert response.json["pagination"]["count"] == 2 assert response.json["pagination"]["total"] == 5 assert response.json["pagination"]["pages"] == 2 @@ -556,12 +603,13 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - self.create_spec_file(client, user=with_super_admin_user) - process_model = load_test_spec("random_fact") + process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + modified_process_model_id = process_model_identifier.replace("/", ":") + data = {"key1": "THIS DATA"} response = client.put( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/random_fact.svg", + f"/v1.0/process-models/{modified_process_model_id}/files/random_fact.svg", data=data, follow_redirects=True, content_type="multipart/form-data", @@ -580,12 +628,12 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - self.create_spec_file(client, user=with_super_admin_user) + process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + modified_process_model_id = process_model_identifier.replace("/", ":") - process_model = load_test_spec("random_fact") data = {"file": (io.BytesIO(b""), "random_fact.svg")} response = client.put( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/random_fact.svg", + f"/v1.0/process-models/{modified_process_model_id}/files/random_fact.svg", data=data, follow_redirects=True, content_type="multipart/form-data", @@ -604,13 +652,29 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - original_file = self.create_spec_file(client, user=with_super_admin_user) + process_group_id = "test_group" + process_group_description = "Test Group" + process_model_id = "random_fact" + process_model_identifier = f"{process_group_id}/{process_model_id}" + self.create_process_group(client, with_super_admin_user, process_group_id, process_group_description) + self.create_process_model_with_api( + client, + process_model_id=process_model_identifier, + user=with_super_admin_user, + ) - process_model = load_test_spec("random_fact") + bpmn_file_name = "random_fact.bpmn" + original_file = load_test_spec( + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + process_model_source_directory="random_fact" + ) + + modified_process_model_id = process_model_identifier.replace("/", ":") new_file_contents = b"THIS_IS_NEW_DATA" data = {"file": (io.BytesIO(new_file_contents), "random_fact.svg")} response = client.put( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/random_fact.svg", + f"/v1.0/process-models/{modified_process_model_id}/files/random_fact.svg", data=data, follow_redirects=True, content_type="multipart/form-data", @@ -622,7 +686,7 @@ class TestProcessApi(BaseTest): assert response.json["ok"] response = client.get( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/random_fact.svg", + f"/v1.0/process-models/{modified_process_model_id}/files/random_fact.svg", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 200 @@ -638,11 +702,13 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - self.create_spec_file(client, user=with_super_admin_user) + process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + # self.create_spec_file(client, user=with_super_admin_user) - process_model = load_test_spec("random_fact") + # process_model = load_test_spec("random_fact") + bad_process_model_identifier = f"x{process_model_identifier}" response = client.delete( - f"/v1.0/process-models/INCORRECT-NON-EXISTENT-GROUP/{process_model.id}/files/random_fact.svg", + f"/v1.0/process-models/{bad_process_model_identifier}/files/random_fact.svg", follow_redirects=True, headers=self.logged_in_headers(with_super_admin_user), ) @@ -659,11 +725,11 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - self.create_spec_file(client, user=with_super_admin_user) + process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + modified_process_model_identifier = process_model_identifier.replace("/", ":") - process_model = load_test_spec("random_fact") response = client.delete( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/random_fact_DOES_NOT_EXIST.svg", + f"/v1.0/process-models/{modified_process_model_identifier}/files/random_fact_DOES_NOT_EXIST.svg", follow_redirects=True, headers=self.logged_in_headers(with_super_admin_user), ) @@ -680,11 +746,11 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - self.create_spec_file(client, user=with_super_admin_user) + process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + modified_process_model_identifier = process_model_identifier.replace("/", ":") - process_model = load_test_spec("random_fact") response = client.delete( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/random_fact.svg", + f"/v1.0/process-models/{modified_process_model_identifier}/files/random_fact.bpmn", follow_redirects=True, headers=self.logged_in_headers(with_super_admin_user), ) @@ -694,7 +760,7 @@ class TestProcessApi(BaseTest): assert response.json["ok"] response = client.get( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/random_fact.svg", + f"/v1.0/process-models/{modified_process_model_identifier}/files/random_fact.svg", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 404 @@ -707,18 +773,17 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_file.""" - test_process_group_id = "group_id1" - process_model_dir_name = "hello_world" - load_test_spec(process_model_dir_name, process_group_id=test_process_group_id) + process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + modified_process_model_identifier = process_model_identifier.replace("/", ":") + response = client.get( - f"/v1.0/process-models/{test_process_group_id}/{process_model_dir_name}/files/hello_world.bpmn", + f"/v1.0/process-models/{modified_process_model_identifier}/files/random_fact.bpmn", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 200 assert response.json is not None - assert response.json["name"] == "hello_world.bpmn" - assert response.json["process_group_id"] == "group_id1" - assert response.json["process_model_id"] == "hello_world" + assert response.json["name"] == "random_fact.bpmn" + assert response.json["process_model_id"] == "test_group/random_fact" def test_get_workflow_from_workflow_spec( self, @@ -728,15 +793,16 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_workflow_from_workflow_spec.""" - process_model = load_test_spec("hello_world") + process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + modified_process_model_identifier = process_model_identifier.replace("/", ":") + response = client.post( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/process-instances", + f"/v1.0/process-models/{modified_process_model_identifier}/process-instances", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 201 assert response.json is not None - assert "hello_world" == response.json["process_model_identifier"] - # assert('Task_GetName' == response.json['next_task']['name']) + assert "test_group/random_fact" == response.json["process_model_identifier"] def test_get_process_groups_when_none( self, @@ -762,7 +828,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_process_groups_when_there_are_some.""" - load_test_spec("hello_world") + self.basic_test_setup(client, with_super_admin_user) response = client.get( "/v1.0/process-groups", headers=self.logged_in_headers(with_super_admin_user), @@ -782,17 +848,18 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_process_group_when_found.""" - test_process_group_id = "group_id1" - process_model_dir_name = "hello_world" - load_test_spec(process_model_dir_name, process_group_id=test_process_group_id) + process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_group_id, process_model_id = os.path.split(process_model_identifier) + response = client.get( - f"/v1.0/process-groups/{test_process_group_id}", + f"/v1.0/process-groups/{process_group_id}", headers=self.logged_in_headers(with_super_admin_user), ) + assert response.status_code == 200 assert response.json is not None - assert response.json["id"] == test_process_group_id - assert response.json["process_models"][0]["id"] == process_model_dir_name + assert response.json["id"] == process_group_id + assert response.json["process_models"][0]["id"] == process_model_identifier def test_get_process_model_when_found( self, @@ -802,18 +869,20 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_process_model_when_found.""" - test_process_group_id = "group_id1" - process_model_dir_name = "hello_world" - load_test_spec(process_model_dir_name, process_group_id=test_process_group_id) + process_model_identifier = self.basic_test_setup( + client, with_super_admin_user, bpmn_file_name="random_fact.bpmn" + ) + modified_process_model_identifier = process_model_identifier.replace("/", ":") + response = client.get( - f"/v1.0/process-models/{test_process_group_id}/{process_model_dir_name}", + f"/v1.0/process-models/{modified_process_model_identifier}", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 200 assert response.json is not None - assert response.json["id"] == process_model_dir_name + assert response.json["id"] == process_model_identifier assert len(response.json["files"]) == 1 - assert response.json["files"][0]["name"] == "hello_world.bpmn" + assert response.json["files"][0]["name"] == "random_fact.bpmn" def test_get_process_model_when_not_found( self, @@ -841,11 +910,10 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_instance_create.""" - test_process_group_id = "runs_without_input" - test_process_model_id = "sample" + test_process_model_id = "runs_without_input/sample" headers = self.logged_in_headers(with_super_admin_user) response = self.create_process_instance( - client, test_process_group_id, test_process_model_id, headers + client, test_process_model_id, headers ) assert response.json is not None assert response.json["updated_at_in_seconds"] is not None @@ -863,16 +931,25 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_instance_run.""" - process_group_id = "runs_without_input" - process_model_id = "sample" + # process_model_id = "runs_without_input/sample" + process_model_identifier = self.basic_test_setup( + client=client, + user=with_super_admin_user, + process_group_id="runs_without_input", + process_model_id="sample", + bpmn_file_name=None, + bpmn_file_location="sample" + ) + headers = self.logged_in_headers(with_super_admin_user) response = self.create_process_instance( - client, process_group_id, process_model_id, headers + client, process_model_identifier, headers ) assert response.json is not None process_instance_id = response.json["id"] + modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.post( - f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) @@ -880,7 +957,7 @@ class TestProcessApi(BaseTest): assert type(response.json["updated_at_in_seconds"]) is int assert response.json["updated_at_in_seconds"] > 0 assert response.json["status"] == "complete" - assert response.json["process_model_identifier"] == process_model_id + assert response.json["process_model_identifier"] == process_model_identifier assert ( response.json["data"]["current_user"]["username"] == with_super_admin_user.username @@ -898,23 +975,30 @@ class TestProcessApi(BaseTest): """Test_process_instance_show.""" process_group_id = "simple_script" process_model_id = "simple_script" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id + ) + modified_process_model_identifier = process_model_identifier.replace("/", ":") headers = self.logged_in_headers(with_super_admin_user) create_response = self.create_process_instance( - client, process_group_id, process_model_id, headers + client, process_model_identifier, headers ) assert create_response.json is not None process_instance_id = create_response.json["id"] client.post( - f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) show_response = client.get( - f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}", + f"/v1.0/process-models/{modified_process_model_identifier}/process-instances/{process_instance_id}", headers=self.logged_in_headers(with_super_admin_user), ) assert show_response.json is not None file_system_root = FileSystemService.root_path() - file_path = f"{file_system_root}/{process_group_id}/{process_model_id}/{process_model_id}.bpmn" + file_path = f"{file_system_root}/{process_model_identifier}/{process_model_id}.bpmn" with open(file_path) as f_open: xml_file_contents = f_open.read() assert show_response.json["bpmn_xml_file_contents"] == xml_file_contents @@ -927,12 +1011,20 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_message_start_when_starting_process_instance.""" - # ensure process model is loaded in db - load_test_spec( - "message_receiver", - process_model_source_directory="message_send_one_conversation", - bpmn_file_name="message_receiver", + # ensure process model is loaded + process_group_id = "test_message_start" + process_model_id = "message_receiver" + bpmn_file_name = "message_receiver.bpmn" + bpmn_file_location = "message_send_one_conversation" + self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location ) + message_model_identifier = "message_send" payload = { "topica": "the_topica_string", @@ -968,11 +1060,20 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_message_start_when_providing_message_to_running_process_instance.""" - process_model = load_test_spec( - "message_sender", - process_model_source_directory="message_send_one_conversation", - bpmn_file_name="message_sender", + process_group_id = "test_message_start" + process_model_id = "message_sender" + bpmn_file_name = "message_sender.bpmn" + bpmn_file_location = "message_send_one_conversation" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location ) + modified_process_model_identifier = process_model_identifier.replace("/", ":") + message_model_identifier = "message_response" payload = { "the_payload": { @@ -983,16 +1084,14 @@ class TestProcessApi(BaseTest): } response = self.create_process_instance( client, - process_model.process_group_id, - process_model.id, + process_model_identifier, self.logged_in_headers(with_super_admin_user), ) assert response.json is not None process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-models/{process_model.process_group_id}/" - f"{process_model.id}/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) @@ -1030,31 +1129,37 @@ class TestProcessApi(BaseTest): ) -> None: """Test_message_start_when_providing_message_to_running_process_instance.""" # this task will wait on a catch event - process_model = load_test_spec( - "message_sender", - process_model_source_directory="message_send_one_conversation", - bpmn_file_name="message_sender", + process_group_id = "test_message_start" + process_model_id = "message_sender" + bpmn_file_name = "message_sender.bpmn" + bpmn_file_location = "message_send_one_conversation" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location ) + modified_process_model_identifier = process_model_identifier.replace("/", ":") + response = self.create_process_instance( client, - process_model.process_group_id, - process_model.id, + process_model_identifier, self.logged_in_headers(with_super_admin_user), ) assert response.json is not None process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-models/{process_model.process_group_id}/" - f"{process_model.id}/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 200 assert response.json is not None response = client.post( - f"/v1.0/process-models/{process_model.process_group_id}/" - f"{process_model.id}/process-instances/{process_instance_id}/terminate", + f"/v1.0/process-instances/{process_instance_id}/terminate", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 200 @@ -1076,16 +1181,27 @@ class TestProcessApi(BaseTest): """Test_process_instance_delete.""" process_group_id = "my_process_group" process_model_id = "user_task" + bpmn_file_name = "user_task.bpmn" + bpmn_file_location = "user_task" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location + ) + modified_process_model_identifier = process_model_identifier.replace("/", ":") headers = self.logged_in_headers(with_super_admin_user) response = self.create_process_instance( - client, process_group_id, process_model_id, headers + client, process_model_identifier, headers ) assert response.json is not None process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) @@ -1100,7 +1216,7 @@ class TestProcessApi(BaseTest): assert task_event.user_id == with_super_admin_user.id delete_response = client.delete( - f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}", + f"/v1.0/process-instances/{process_instance_id}", headers=self.logged_in_headers(with_super_admin_user), ) assert delete_response.status_code == 200 @@ -1115,16 +1231,27 @@ class TestProcessApi(BaseTest): """Test_process_instance_run_user_task.""" process_group_id = "my_process_group" process_model_id = "user_task" + bpmn_file_name = "user_task.bpmn" + bpmn_file_location = "user_task" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location + ) + modified_process_model_identifier = process_model_identifier.replace("/", ":") headers = self.logged_in_headers(with_super_admin_user) response = self.create_process_instance( - client, process_group_id, process_model_id, headers + client, process_model_identifier, headers ) assert response.json is not None process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) @@ -1149,16 +1276,27 @@ class TestProcessApi(BaseTest): """Test_process_instance_run_user_task.""" process_group_id = "my_process_group" process_model_id = "dynamic_enum_select_fields" + bpmn_file_name = "dynamic_enums_ask_for_color.bpmn" + bpmn_file_location = "dynamic_enum_select_fields" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + # bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location + ) + modified_process_model_identifier = process_model_identifier.replace("/", ":") headers = self.logged_in_headers(with_super_admin_user) response = self.create_process_instance( - client, process_group_id, process_model_id, headers + client, process_model_identifier, headers ) assert response.json is not None process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) @@ -1188,11 +1326,20 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_instance_list_with_default_list.""" - test_process_group_id = "runs_without_input" - process_model_dir_name = "sample" + process_group_id = "runs_without_input" + process_model_id = "sample" + bpmn_file_location = "sample" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_location=bpmn_file_location + ) + headers = self.logged_in_headers(with_super_admin_user) self.create_process_instance( - client, test_process_group_id, process_model_dir_name, headers + client, process_model_identifier, headers ) response = client.get( @@ -1209,10 +1356,7 @@ class TestProcessApi(BaseTest): process_instance_dict = response.json["results"][0] assert type(process_instance_dict["id"]) is int assert ( - process_instance_dict["process_model_identifier"] == process_model_dir_name - ) - assert ( - process_instance_dict["process_group_identifier"] == test_process_group_id + process_instance_dict["process_model_identifier"] == process_model_identifier ) assert type(process_instance_dict["start_in_seconds"]) is int assert process_instance_dict["start_in_seconds"] > 0 @@ -1227,23 +1371,33 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_instance_list_with_paginated_items.""" - test_process_group_id = "runs_without_input" - process_model_dir_name = "sample" + process_group_id = "runs_without_input" + process_model_id = "sample" + bpmn_file_name = "sample.bpmn" + bpmn_file_location = "sample" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location + ) headers = self.logged_in_headers(with_super_admin_user) self.create_process_instance( - client, test_process_group_id, process_model_dir_name, headers + client, process_model_identifier, headers ) self.create_process_instance( - client, test_process_group_id, process_model_dir_name, headers + client, process_model_identifier, headers ) self.create_process_instance( - client, test_process_group_id, process_model_dir_name, headers + client, process_model_identifier, headers ) self.create_process_instance( - client, test_process_group_id, process_model_dir_name, headers + client, process_model_identifier, headers ) self.create_process_instance( - client, test_process_group_id, process_model_dir_name, headers + client, process_model_identifier, headers ) response = client.get( @@ -1276,9 +1430,18 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_instance_list_filter.""" - test_process_group_id = "runs_without_input" - test_process_model_id = "sample" - load_test_spec(test_process_model_id, process_group_id=test_process_group_id) + process_group_id = "runs_without_input" + process_model_id = "sample" + bpmn_file_name = "sample.bpmn" + bpmn_file_location = "sample" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location + ) statuses = [status.value for status in ProcessInstanceStatus] # create 5 instances with different status, and different start_in_seconds/end_in_seconds @@ -1286,8 +1449,8 @@ class TestProcessApi(BaseTest): process_instance = ProcessInstanceModel( status=ProcessInstanceStatus[statuses[i]].value, process_initiator=with_super_admin_user, - process_model_identifier=test_process_model_id, - process_group_identifier=test_process_group_id, + process_model_identifier=process_model_identifier, + process_group_identifier="test_process_group_id", updated_at_in_seconds=round(time.time()), start_in_seconds=(1000 * i) + 1000, end_in_seconds=(1000 * i) + 2000, @@ -1298,7 +1461,7 @@ class TestProcessApi(BaseTest): # Without filtering we should get all 5 instances response = client.get( - f"/v1.0/process-instances?process_group_identifier={test_process_group_id}&process_model_identifier={test_process_model_id}", + f"/v1.0/process-instances?process_group_identifier={process_group_id}&process_model_identifier={process_model_id}", headers=self.logged_in_headers(with_super_admin_user), ) assert response.json is not None @@ -1309,7 +1472,7 @@ class TestProcessApi(BaseTest): # we should get 1 instance each time for i in range(5): response = client.get( - f"/v1.0/process-instances?process_status={ProcessInstanceStatus[statuses[i]].value}&process_group_identifier={test_process_group_id}&process_model_identifier={test_process_model_id}", + f"/v1.0/process-instances?process_status={ProcessInstanceStatus[statuses[i]].value}&process_group_identifier={process_group_id}&process_model_identifier={process_model_id}", headers=self.logged_in_headers(with_super_admin_user), ) assert response.json is not None @@ -1318,7 +1481,7 @@ class TestProcessApi(BaseTest): assert results[0]["status"] == ProcessInstanceStatus[statuses[i]].value response = client.get( - f"/v1.0/process-instances?process_status=not_started,complete&process_group_identifier={test_process_group_id}&process_model_identifier={test_process_model_id}", + f"/v1.0/process-instances?process_status=not_started,complete&process_group_identifier={process_group_id}&process_model_identifier={process_model_id}", headers=self.logged_in_headers(with_super_admin_user), ) assert response.json is not None @@ -1380,23 +1543,32 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_instance_report_list.""" - process_group_identifier = "runs_without_input" - process_model_identifier = "sample" - self.logged_in_headers(with_super_admin_user) - load_test_spec( - process_model_identifier, process_group_id=process_group_identifier + process_group_id = "runs_without_input" + process_model_id = "sample" + bpmn_file_name = "sample.bpmn" + bpmn_file_location = "sample" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location ) + modified_process_model_identifier = process_model_identifier.replace("/", ":") + self.logged_in_headers(with_super_admin_user) + report_identifier = "testreport" report_metadata = {"order_by": ["month"]} ProcessInstanceReportModel.create_with_attributes( identifier=report_identifier, - process_group_identifier=process_group_identifier, + process_group_identifier="", process_model_identifier=process_model_identifier, report_metadata=report_metadata, user=with_super_admin_user, ) response = client.get( - f"/v1.0/process-models/{process_group_identifier}/{process_model_identifier}/process-instances/reports", + f"/v1.0/process-models/{modified_process_model_identifier}/process-instances/reports", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 200 @@ -1414,8 +1586,20 @@ class TestProcessApi(BaseTest): setup_process_instances_for_reports: list[ProcessInstanceModel], ) -> None: """Test_process_instance_report_show_with_default_list.""" - test_process_group_id = "runs_without_input" - process_model_dir_name = "sample" + process_group_id = "runs_without_input" + process_model_id = "sample" + # bpmn_file_name = "sample.bpmn" + # bpmn_file_location = "sample" + # process_model_identifier = self.basic_test_setup( + # client, + # with_super_admin_user, + # process_group_id=process_group_id, + # process_model_id=process_model_id, + # bpmn_file_name=bpmn_file_name, + # bpmn_file_location=bpmn_file_location + # ) + process_model_identifier = f"{process_group_id}/{process_model_id}" + modified_process_model_identifier = process_model_identifier.replace("/", ":") report_metadata = { "columns": [ @@ -1438,14 +1622,14 @@ class TestProcessApi(BaseTest): ProcessInstanceReportModel.create_with_attributes( identifier="sure", - process_group_identifier=test_process_group_id, - process_model_identifier=process_model_dir_name, + process_group_identifier="test_process_group_id", + process_model_identifier=process_model_identifier, report_metadata=report_metadata, user=with_super_admin_user, ) response = client.get( - f"/v1.0/process-models/{test_process_group_id}/{process_model_dir_name}/process-instances/reports/sure", + f"/v1.0/process-models/{modified_process_model_identifier}/process-instances/reports/sure", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 200 @@ -1458,10 +1642,7 @@ class TestProcessApi(BaseTest): process_instance_dict = response.json["results"][0] assert type(process_instance_dict["id"]) is int assert ( - process_instance_dict["process_model_identifier"] == process_model_dir_name - ) - assert ( - process_instance_dict["process_group_identifier"] == test_process_group_id + process_instance_dict["process_model_identifier"] == process_model_identifier ) assert type(process_instance_dict["start_in_seconds"]) is int assert process_instance_dict["start_in_seconds"] > 0 @@ -1478,6 +1659,8 @@ class TestProcessApi(BaseTest): """Test_process_instance_report_show_with_default_list.""" test_process_group_id = "runs_without_input" process_model_dir_name = "sample" + process_model_identifier = f"{test_process_group_id}/{process_model_dir_name}" + modified_process_model_identifier = process_model_identifier.replace("/", ":") report_metadata = { "filter_by": [ @@ -1491,14 +1674,14 @@ class TestProcessApi(BaseTest): ProcessInstanceReportModel.create_with_attributes( identifier="sure", - process_group_identifier=test_process_group_id, - process_model_identifier=process_model_dir_name, + process_group_identifier="test_process_group_id", + process_model_identifier=process_model_identifier, report_metadata=report_metadata, user=with_super_admin_user, ) response = client.get( - f"/v1.0/process-models/{test_process_group_id}/{process_model_dir_name}/process-instances/reports/sure?grade_level=1", + f"/v1.0/process-models/{modified_process_model_identifier}/process-instances/reports/sure?grade_level=1", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 200 @@ -1528,14 +1711,13 @@ class TestProcessApi(BaseTest): def setup_testing_instance( self, client: FlaskClient, - process_group_id: str, process_model_id: str, with_super_admin_user: UserModel, ) -> Any: """Setup_testing_instance.""" headers = self.logged_in_headers(with_super_admin_user) response = self.create_process_instance( - client, process_group_id, process_model_id, headers + client, process_model_id, headers ) process_instance = response.json assert isinstance(process_instance, dict) @@ -1552,9 +1734,19 @@ class TestProcessApi(BaseTest): """Test_error_handler.""" process_group_id = "data" process_model_id = "error" + bpmn_file_name = "error.bpmn" + bpmn_file_location = "error" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location + ) process_instance_id = self.setup_testing_instance( - client, process_group_id, process_model_id, with_super_admin_user + client, process_model_identifier, with_super_admin_user ) process = ( @@ -1566,7 +1758,7 @@ class TestProcessApi(BaseTest): assert process.status == "not_started" response = client.post( - f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 400 @@ -1596,12 +1788,22 @@ class TestProcessApi(BaseTest): """Test_error_handler_suspend.""" process_group_id = "data" process_model_id = "error" + bpmn_file_name = "error.bpmn" + bpmn_file_location = "error" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location + ) process_instance_id = self.setup_testing_instance( - client, process_group_id, process_model_id, with_super_admin_user + client, process_model_identifier, with_super_admin_user ) process_model = ProcessModelService().get_process_model( - process_model_id, process_group_id + process_model_identifier ) ProcessModelService().update_spec( process_model, @@ -1617,7 +1819,7 @@ class TestProcessApi(BaseTest): assert process.status == "not_started" response = client.post( - f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 400 @@ -1640,13 +1842,23 @@ class TestProcessApi(BaseTest): """Test_error_handler.""" process_group_id = "data" process_model_id = "error" + bpmn_file_name = "error.bpmn" + bpmn_file_location = "error" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location + ) process_instance_id = self.setup_testing_instance( - client, process_group_id, process_model_id, with_super_admin_user + client, process_model_identifier, with_super_admin_user ) process_model = ProcessModelService().get_process_model( - process_model_id, process_group_id + process_model_identifier ) ProcessModelService().update_spec( process_model, @@ -1657,7 +1869,7 @@ class TestProcessApi(BaseTest): with mail.record_messages() as outbox: response = client.post( - f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 400 @@ -1689,17 +1901,26 @@ class TestProcessApi(BaseTest): process_model_id = "hello_world" file_name = "hello_world.svg" file_data = b"abc123" + bpmn_file_name = "hello_world.bpmn" + bpmn_file_location = "hello_world" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location + ) result = self.create_spec_file( client, - process_group_id=process_group_id, - process_model_id=process_model_id, + process_model_id=process_model_identifier, file_name=file_name, file_data=file_data, user=with_super_admin_user, ) - assert result["process_group_id"] == process_group_id - assert result["process_model_id"] == process_model_id + + assert result["process_model_id"] == process_model_identifier assert result["name"] == file_name assert bytes(str(result["file_contents"]), "utf-8") == file_data @@ -1711,11 +1932,23 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_can_get_message_instances_by_process_instance_id.""" - load_test_spec( - "message_receiver", - process_model_source_directory="message_send_one_conversation", - bpmn_file_name="message_receiver", + process_group_id = "test_message_start" + process_model_id = "message_receiver" + bpmn_file_name = "message_receiver.bpmn" + bpmn_file_location = "message_send_one_conversation" + self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location ) + # load_test_spec( + # "message_receiver", + # process_model_source_directory="message_send_one_conversation", + # bpmn_file_name="message_receiver", + # ) message_model_identifier = "message_send" payload = { "topica": "the_topica_string", @@ -1791,16 +2024,29 @@ class TestProcessApi(BaseTest): finance_group = GroupModel.query.filter_by(identifier="Finance Team").first() assert finance_group is not None - process_model = load_test_spec( - process_model_id="model_with_lanes", - bpmn_file_name="lanes.bpmn", - process_group_id="finance", + process_group_id = "finance" + process_model_id = "model_with_lanes" + bpmn_file_name = "lanes.bpmn" + bpmn_file_location = "model_with_lanes" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location ) + # process_model = load_test_spec( + # process_model_id="model_with_lanes", + # bpmn_file_name="lanes.bpmn", + # process_group_id="finance", + # ) + response = self.create_process_instance( client, - process_model.process_group_id, - process_model.id, + # process_model.process_group_id, + process_model_identifier, headers=self.logged_in_headers(initiator_user), ) assert response.status_code == 201 @@ -1808,7 +2054,7 @@ class TestProcessApi(BaseTest): assert response.json is not None process_instance_id = response.json["id"] response = client.post( - f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/process-instances/{process_instance_id}/run", + f"/v1.0/process-instances/{process_instance_id}/run", headers=self.logged_in_headers(initiator_user), ) assert response.status_code == 200 diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py index 3735ebc5..7e0e458f 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py @@ -42,16 +42,16 @@ class SecretServiceTestHelpers(BaseTest): self.test_process_group_id, display_name=self.test_process_group_display_name, ) + process_model_identifier = f"{self.test_process_group_id}/{self.test_process_model_id}" self.create_process_model_with_api( client, - process_group_id=self.test_process_group_id, - process_model_id=self.test_process_model_id, + process_model_id=process_model_identifier, process_model_display_name=self.test_process_model_display_name, process_model_description=self.test_process_model_description, user=user, ) process_model_info = ProcessModelService().get_process_model( - self.test_process_model_id, self.test_process_group_id + process_model_identifier ) return process_model_info diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_localtime.py b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_localtime.py index 9110f736..b7479be2 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_localtime.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_localtime.py @@ -29,8 +29,14 @@ class TestGetLocaltime(BaseTest): ) -> None: """Test_process_instance_run.""" initiator_user = self.find_or_create_user("initiator_user") + self.add_permissions_to_user( + initiator_user, target_uri="/v1.0/process-groups", permission_names=["read", "create"] + ) + self.create_process_group(client=client, user=initiator_user, process_group_id="test_group") process_model = load_test_spec( - process_model_id="get_localtime", bpmn_file_name="get_localtime.bpmn" + process_model_id="test_group/get_localtime", + bpmn_file_name="get_localtime.bpmn", + process_model_source_directory="get_localtime" ) process_instance = self.create_process_instance_from_process_model( process_model=process_model, user=initiator_user diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py index ff2ac9bc..2c8b6879 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py @@ -1,10 +1,13 @@ """Test_message_service.""" import pytest from flask import Flask +from flask.testing import FlaskClient + +from spiffworkflow_backend.services.process_model_service import ProcessModelService from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec -from spiffworkflow_backend.models.user import UserNotFoundError +from spiffworkflow_backend.models.user import UserModel, UserNotFoundError from spiffworkflow_backend.services.authorization_service import AuthorizationService from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, @@ -89,7 +92,11 @@ class TestAuthorizationService(BaseTest): ) def test_user_can_be_added_to_active_task_on_first_login( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, + app: Flask, + client: FlaskClient, + with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel ) -> None: """Test_user_can_be_added_to_active_task_on_first_login.""" initiator_user = self.find_or_create_user("initiator_user") @@ -98,8 +105,17 @@ class TestAuthorizationService(BaseTest): self.find_or_create_user("testuser1") AuthorizationService.import_permissions_from_yaml_file() - process_model = load_test_spec( - process_model_id="model_with_lanes", bpmn_file_name="lanes.bpmn" + process_model_identifier = self.basic_test_setup( + client=client, + user=with_super_admin_user, + process_group_id="test_group", + process_model_id="model_with_lanes", + bpmn_file_name="lanes.bpmn", + bpmn_file_location="model_with_lanes" + ) + + process_model = ProcessModelService().get_process_model( + process_model_id=process_model_identifier ) process_instance = self.create_process_instance_from_process_model( process_model=process_model, user=initiator_user diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_dot_notation.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_dot_notation.py index 4446d4d9..5ea6af39 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_dot_notation.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_dot_notation.py @@ -1,8 +1,12 @@ """Test_various_bpmn_constructs.""" from flask.app import Flask +from flask.testing import FlaskClient + +from spiffworkflow_backend.services.authorization_service import AuthorizationService from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec +from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) @@ -15,21 +19,30 @@ class TestDotNotation(BaseTest): """TestVariousBpmnConstructs.""" def test_dot_notation( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_form_data_conversion_to_dot_dict.""" - process_model = load_test_spec( - "test_dot_notation", - bpmn_file_name="diagram.bpmn", - process_model_source_directory="dot_notation", + process_group_id = "dot_notation_group" + process_model_id = "test_dot_notation" + bpmn_file_name = "diagram.bpmn" + bpmn_file_location = "dot_notation" + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location ) - current_user = self.find_or_create_user() - process_instance = self.create_process_instance_from_process_model( - process_model + headers = self.logged_in_headers(with_super_admin_user) + response = self.create_process_instance( + client, process_model_identifier, headers ) + process_instance_id = response.json["id"] + process_instance = ProcessInstanceService().get_process_instance(process_instance_id) + processor = ProcessInstanceProcessor(process_instance) - processor.do_engine_steps(save=True) user_task = processor.get_ready_user_tasks()[0] @@ -41,7 +54,7 @@ class TestDotNotation(BaseTest): "invoice.dueDate": "09/30/2022", } ProcessInstanceService.complete_form_task( - processor, user_task, form_data, current_user + processor, user_task, form_data, with_super_admin_user ) expected = { diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py index 842d5ff4..f340eefc 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py @@ -1,24 +1,46 @@ """Test_message_instance.""" import pytest from flask import Flask +from flask.testing import FlaskClient from flask_bpmn.models.db import db + +from spiffworkflow_backend.services.process_model_service import ProcessModelService from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from spiffworkflow_backend.models.message_instance import MessageInstanceModel from spiffworkflow_backend.models.message_model import MessageModel +from spiffworkflow_backend.models.user import UserModel class TestMessageInstance(BaseTest): """TestMessageInstance.""" + def setup_message_tests(self, client: FlaskClient, user: UserModel) -> str: + process_group_id = "test_group" + process_model_id = "hello_world" + bpmn_file_name = "hello_world.bpmn" + bpmn_file_location = "hello_world" + process_model_identifier = self.basic_test_setup( + client, + user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location + ) + return process_model_identifier + def test_can_create_message_instance( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_can_create_message_instance.""" message_model_identifier = "message_model_one" message_model = self.create_message_model(message_model_identifier) - process_model = load_test_spec("hello_world") + process_model_identifier = self.setup_message_tests(client, with_super_admin_user) + + process_model = ProcessModelService().get_process_model( + process_model_id=process_model_identifier + ) process_instance = self.create_process_instance_from_process_model( process_model, "waiting" ) @@ -40,12 +62,16 @@ class TestMessageInstance(BaseTest): assert queued_message_from_query is not None def test_cannot_set_invalid_status( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_cannot_set_invalid_status.""" message_model_identifier = "message_model_one" message_model = self.create_message_model(message_model_identifier) - process_model = load_test_spec("hello_world") + process_model_identifier = self.setup_message_tests(client, with_super_admin_user) + + process_model = ProcessModelService().get_process_model( + process_model_id=process_model_identifier + ) process_instance = self.create_process_instance_from_process_model( process_model, "waiting" ) @@ -76,12 +102,16 @@ class TestMessageInstance(BaseTest): ) def test_cannot_set_invalid_message_type( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_cannot_set_invalid_message_type.""" message_model_identifier = "message_model_one" message_model = self.create_message_model(message_model_identifier) - process_model = load_test_spec("hello_world") + process_model_identifier = self.setup_message_tests(client, with_super_admin_user) + + process_model = ProcessModelService().get_process_model( + process_model_id=process_model_identifier + ) process_instance = self.create_process_instance_from_process_model( process_model, "waiting" ) @@ -113,12 +143,16 @@ class TestMessageInstance(BaseTest): ) def test_force_failure_cause_if_status_is_failure( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_force_failure_cause_if_status_is_failure.""" message_model_identifier = "message_model_one" message_model = self.create_message_model(message_model_identifier) - process_model = load_test_spec("hello_world") + process_model_identifier = self.setup_message_tests(client, with_super_admin_user) + + process_model = ProcessModelService().get_process_model( + process_model_id=process_model_identifier + ) process_instance = self.create_process_instance_from_process_model( process_model, "waiting" ) @@ -154,7 +188,8 @@ class TestMessageInstance(BaseTest): assert queued_message.id is not None assert queued_message.failure_cause == "THIS TEST FAILURE" - def create_message_model(self, message_model_identifier: str) -> MessageModel: + @staticmethod + def create_message_model(message_model_identifier: str) -> MessageModel: """Create_message_model.""" message_model = MessageModel(identifier=message_model_identifier) db.session.add(message_model) diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_service.py index 38079c96..311a5157 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_service.py @@ -1,5 +1,6 @@ """Test_message_service.""" from flask import Flask +from flask.testing import FlaskClient from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec @@ -9,6 +10,7 @@ from spiffworkflow_backend.models.message_correlation_message_instance import ( ) from spiffworkflow_backend.models.message_instance import MessageInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel +from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.message_service import MessageService from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, @@ -22,25 +24,26 @@ class TestMessageService(BaseTest): """TestMessageService.""" def test_can_send_message_to_waiting_message( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_can_send_message_to_waiting_message.""" - process_model_sender = load_test_spec( - "message_sender", - process_model_source_directory="message_send_one_conversation", - bpmn_file_name="message_sender", - ) + process_group_id = "test_group" + self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) + load_test_spec( - "message_receiver", + "test_group/message_receiver", process_model_source_directory="message_send_one_conversation", - bpmn_file_name="message_receiver", + bpmn_file_name="message_receiver.bpmn" + ) + process_model_sender = load_test_spec( + "test_group/message_sender", + process_model_source_directory="message_send_one_conversation", + bpmn_file_name="message_sender.bpmn", ) - user = self.find_or_create_user() process_instance_sender = ProcessInstanceService.create_process_instance( process_model_sender.id, - user, - process_group_identifier=process_model_sender.process_group_id, + with_super_admin_user, ) processor_sender = ProcessInstanceProcessor(process_instance_sender) @@ -115,21 +118,25 @@ class TestMessageService(BaseTest): assert process_instance.status == "complete" def test_can_send_message_to_multiple_process_models( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_can_send_message_to_multiple_process_models.""" + + process_group_id = "test_group" + self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) + process_model_sender = load_test_spec( - "message_sender", + "test_group/message_sender", process_model_source_directory="message_send_two_conversations", bpmn_file_name="message_sender", ) load_test_spec( - "message_receiver_one", + "test_group/message_receiver_one", process_model_source_directory="message_send_two_conversations", bpmn_file_name="message_receiver_one", ) load_test_spec( - "message_receiver_two", + "test_group/message_receiver_two", process_model_source_directory="message_send_two_conversations", bpmn_file_name="message_receiver_two", ) @@ -139,7 +146,7 @@ class TestMessageService(BaseTest): process_instance_sender = ProcessInstanceService.create_process_instance( process_model_sender.id, user, - process_group_identifier=process_model_sender.process_group_id, + # process_group_identifier=process_model_sender.process_group_id, ) processor_sender = ProcessInstanceProcessor(process_instance_sender) @@ -189,24 +196,24 @@ class TestMessageService(BaseTest): assert len(process_instance_result) == 3 process_instance_receiver_one = ProcessInstanceModel.query.filter_by( - process_model_identifier="message_receiver_one" + process_model_identifier="test_group/message_receiver_one" ).first() assert process_instance_receiver_one is not None process_instance_receiver_two = ProcessInstanceModel.query.filter_by( - process_model_identifier="message_receiver_two" + process_model_identifier="test_group/message_receiver_two" ).first() assert process_instance_receiver_two is not None # just make sure it's a different process instance assert ( process_instance_receiver_one.process_model_identifier - == "message_receiver_one" + == "test_group/message_receiver_one" ) assert process_instance_receiver_one.id != process_instance_sender.id assert process_instance_receiver_one.status == "complete" assert ( process_instance_receiver_two.process_model_identifier - == "message_receiver_two" + == "test_group/message_receiver_two" ) assert process_instance_receiver_two.id != process_instance_sender.id assert process_instance_receiver_two.status == "complete" diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py index 39f857e2..eec3c47c 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py @@ -1,5 +1,6 @@ """Test Permissions.""" from flask.app import Flask +from flask.testing import FlaskClient from flask_bpmn.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec @@ -8,6 +9,7 @@ from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.principal import PrincipalModel +from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.user_service import UserService @@ -22,13 +24,15 @@ class TestPermissions(BaseTest): """TestPermissions.""" def test_user_can_be_given_permission_to_administer_process_group( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_user_can_be_given_permission_to_administer_process_group.""" process_group_id = "group-a" + self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) load_test_spec( - "timers_intermediate_catch_event", - process_group_id=process_group_id, + "group-a/timers_intermediate_catch_event", + bpmn_file_name="timers_intermediate_catch_event.bpmn", + process_model_source_directory="timers_intermediate_catch_event" ) dan = self.find_or_create_user() principal = dan.principal @@ -55,8 +59,9 @@ class TestPermissions(BaseTest): process_group_b_id = process_group_ids[1] for process_group_id in process_group_ids: load_test_spec( - "timers_intermediate_catch_event", - process_group_id=process_group_id, + f"{process_group_id}/timers_intermediate_catch_event", + bpmn_file_name="timers_intermediate_catch_event", + process_model_source_directory="timers_intermediate_catch_event" ) group_a_admin = self.find_or_create_user() @@ -86,11 +91,11 @@ class TestPermissions(BaseTest): """Test_user_can_be_granted_access_through_a_group.""" process_group_ids = ["group-a", "group-b"] process_group_a_id = process_group_ids[0] - process_group_ids[1] for process_group_id in process_group_ids: load_test_spec( - "timers_intermediate_catch_event", - process_group_id=process_group_id, + f"{process_group_id}/timers_intermediate_catch_event", + bpmn_file_name="timers_intermediate_catch_event.bpmn", + process_model_source_directory="timers_intermediate_catch_event" ) user = self.find_or_create_user() group = GroupModel(identifier="groupA") @@ -127,8 +132,9 @@ class TestPermissions(BaseTest): process_group_b_id = process_group_ids[1] for process_group_id in process_group_ids: load_test_spec( - "timers_intermediate_catch_event", - process_group_id=process_group_id, + f"{process_group_id}/timers_intermediate_catch_event", + bpmn_file_name="timers_intermediate_catch_event.bpmn", + process_model_source_directory="timers_intermediate_catch_event" ) group_a_admin = self.find_or_create_user() diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py index 543b99c0..d39f18db 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py @@ -2,11 +2,13 @@ import pytest from flask import g from flask.app import Flask +from flask.testing import FlaskClient from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus +from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.authorization_service import AuthorizationService from spiffworkflow_backend.services.authorization_service import ( UserDoesNotHaveAccessToTaskError, @@ -50,9 +52,12 @@ class TestProcessInstanceProcessor(BaseTest): def test_sets_permission_correctly_on_active_task( self, app: Flask, + client: FlaskClient, with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel ) -> None: """Test_sets_permission_correctly_on_active_task.""" + self.create_process_group(client, with_super_admin_user, "test_group", "test_group") initiator_user = self.find_or_create_user("initiator_user") finance_user = self.find_or_create_user("testuser2") assert initiator_user.principal is not None @@ -63,7 +68,9 @@ class TestProcessInstanceProcessor(BaseTest): assert finance_group is not None process_model = load_test_spec( - process_model_id="model_with_lanes", bpmn_file_name="lanes.bpmn" + process_model_id="test_group/model_with_lanes", + bpmn_file_name="lanes.bpmn", + process_model_source_directory="model_with_lanes" ) process_instance = self.create_process_instance_from_process_model( process_model=process_model, user=initiator_user @@ -123,9 +130,12 @@ class TestProcessInstanceProcessor(BaseTest): def test_sets_permission_correctly_on_active_task_when_using_dict( self, app: Flask, + client: FlaskClient, with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel ) -> None: """Test_sets_permission_correctly_on_active_task_when_using_dict.""" + self.create_process_group(client, with_super_admin_user, "test_group", "test_group") initiator_user = self.find_or_create_user("initiator_user") finance_user_three = self.find_or_create_user("testuser3") finance_user_four = self.find_or_create_user("testuser4") @@ -138,8 +148,9 @@ class TestProcessInstanceProcessor(BaseTest): assert finance_group is not None process_model = load_test_spec( - process_model_id="model_with_lanes", + process_model_id="test_group/model_with_lanes", bpmn_file_name="lanes_with_owner_dict.bpmn", + process_model_source_directory="model_with_lanes" ) process_instance = self.create_process_instance_from_process_model( process_model=process_model, user=initiator_user diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py index 479db44a..cbb13195 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py @@ -1,11 +1,13 @@ """Process Model.""" from flask.app import Flask +from flask.testing import FlaskClient from flask_bpmn.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup from spiffworkflow_backend.models.process_model import ProcessModelInfo +from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) @@ -22,11 +24,13 @@ class TestProcessModel(BaseTest): assert process_model_one.files == [] def test_can_run_process_model_with_call_activities_when_in_same_process_model_directory( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_can_run_process_model_with_call_activities.""" + self.create_process_group(client, with_super_admin_user, "test_group", "test_group") process_model = load_test_spec( - "call_activity_test", + "test_group/call_activity_test", + # bpmn_file_name="call_activity_test.bpmn", process_model_source_directory="call_activity_same_directory", ) @@ -38,11 +42,12 @@ class TestProcessModel(BaseTest): assert process_instance.status == "complete" def test_can_run_process_model_with_call_activities_when_not_in_same_directory( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_can_run_process_model_with_call_activities.""" + self.create_process_group(client, with_super_admin_user, "test_group", "test_group") process_model = load_test_spec( - "call_activity_nested", + "test_group/call_activity_nested", process_model_source_directory="call_activity_nested", bpmn_file_name="call_activity_nested", ) @@ -54,7 +59,7 @@ class TestProcessModel(BaseTest): ] for bpmn_file_name in bpmn_file_names: load_test_spec( - bpmn_file_name, + f"test_group/{bpmn_file_name}", process_model_source_directory="call_activity_nested", bpmn_file_name=bpmn_file_name, ) @@ -66,11 +71,12 @@ class TestProcessModel(BaseTest): assert process_instance.status == "complete" def test_can_run_process_model_with_call_activities_when_process_identifier_is_not_in_database( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_can_run_process_model_with_call_activities.""" + self.create_process_group(client, with_super_admin_user, "test_group", "test_group") process_model = load_test_spec( - "call_activity_nested", + "test_group/call_activity_nested", process_model_source_directory="call_activity_nested", bpmn_file_name="call_activity_nested", ) @@ -82,7 +88,7 @@ class TestProcessModel(BaseTest): ] for bpmn_file_name in bpmn_file_names: load_test_spec( - bpmn_file_name, + f"test_group/{bpmn_file_name}", process_model_source_directory="call_activity_nested", bpmn_file_name=bpmn_file_name, ) @@ -93,6 +99,7 @@ class TestProcessModel(BaseTest): # delete all of the id lookup items to force to processor to find the correct # process model when running the process db.session.query(BpmnProcessIdLookup).delete() + db.session.commit() processor = ProcessInstanceProcessor(process_instance) processor.do_engine_steps(save=True) assert process_instance.status == "complete" diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model_service.py index 535dc03d..5611f985 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model_service.py @@ -1,8 +1,10 @@ """Test_process_model_service.""" from flask import Flask +from flask.testing import FlaskClient from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec +from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_model_service import ProcessModelService @@ -10,11 +12,16 @@ class TestProcessModelService(BaseTest): """TestProcessModelService.""" def test_can_update_specified_attributes( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_can_update_specified_attributes.""" - process_model = load_test_spec("hello_world") - assert process_model.display_name == "hello_world" + self.create_process_group(client, with_super_admin_user, "test_group", "test_group") + process_model = load_test_spec( + "test_group/hello_world", + bpmn_file_name="hello_world.bpmn", + process_model_source_directory="hello_world" + ) + assert process_model.display_name == "test_group/hello_world" primary_process_id = process_model.primary_process_id assert primary_process_id == "Process_HelloWorld" diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py index 9b6f1bb3..ac8c44ec 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py @@ -1,10 +1,12 @@ """Test_various_bpmn_constructs.""" import pytest from flask.app import Flask +from flask.testing import FlaskClient from flask_bpmn.api.api_error import ApiError from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec +from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) @@ -14,11 +16,12 @@ class TestOpenFile(BaseTest): """TestVariousBpmnConstructs.""" def test_dot_notation( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_form_data_conversion_to_dot_dict.""" + self.create_process_group(client, with_super_admin_user, "test_group", "test_group") process_model = load_test_spec( - "dangerous", + "test_group/dangerous", bpmn_file_name="read_etc_passwd.bpmn", process_model_source_directory="dangerous-scripts", ) @@ -38,11 +41,12 @@ class TestImportModule(BaseTest): """TestVariousBpmnConstructs.""" def test_dot_notation( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_form_data_conversion_to_dot_dict.""" + self.create_process_group(client, with_super_admin_user, "test_group", "test_group") process_model = load_test_spec( - "dangerous", + "test_group/dangerous", bpmn_file_name="read_env.bpmn", process_model_source_directory="dangerous-scripts", ) diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py index 69c54851..53aa777c 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py @@ -1,8 +1,10 @@ """Test Permissions.""" from flask.app import Flask +from flask.testing import FlaskClient from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec +from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) @@ -16,17 +18,25 @@ class TestScriptUnitTestRunner(BaseTest): def test_takes_data_and_returns_expected_result( self, app: Flask, + client: FlaskClient, with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel ) -> None: """Test_takes_data_and_returns_expected_result.""" app.config["THREAD_LOCAL_DATA"].process_instance_id = None process_group_id = "test_logging_spiff_logger" + self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) process_model_id = "simple_script" - load_test_spec(process_model_id, process_group_id=process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + load_test_spec( + process_model_identifier, + bpmn_file_name=process_model_id, + process_model_source_directory=process_model_id + ) bpmn_process_instance = ( ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model( - process_model_id, process_group_id + process_model_identifier ) ) task = ProcessInstanceProcessor.get_task_by_bpmn_identifier( @@ -48,17 +58,26 @@ class TestScriptUnitTestRunner(BaseTest): def test_fails_when_expected_output_does_not_match_actual_output( self, app: Flask, + client: FlaskClient, with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel ) -> None: """Test_fails_when_expected_output_does_not_match_actual_output.""" app.config["THREAD_LOCAL_DATA"].process_instance_id = None process_group_id = "test_logging_spiff_logger" + self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) + process_model_id = "simple_script" - load_test_spec(process_model_id, process_group_id=process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + load_test_spec( + process_model_identifier, + bpmn_file_name=process_model_id, + process_model_source_directory=process_model_id + ) bpmn_process_instance = ( ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model( - process_model_id, process_group_id + process_model_identifier ) ) task = ProcessInstanceProcessor.get_task_by_bpmn_identifier( @@ -80,17 +99,26 @@ class TestScriptUnitTestRunner(BaseTest): def test_script_with_unit_tests_when_hey_is_passed_in( self, app: Flask, + client: FlaskClient, with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel ) -> None: """Test_script_with_unit_tests_when_hey_is_passed_in.""" app.config["THREAD_LOCAL_DATA"].process_instance_id = None process_group_id = "script_with_unit_tests" + self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) + process_model_id = "script_with_unit_tests" - load_test_spec(process_model_id, process_group_id=process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + load_test_spec( + process_model_identifier, + bpmn_file_name=process_model_id, + process_model_source_directory=process_model_id + ) bpmn_process_instance = ( ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model( - process_model_id, process_group_id + process_model_identifier ) ) task = ProcessInstanceProcessor.get_task_by_bpmn_identifier( @@ -110,17 +138,27 @@ class TestScriptUnitTestRunner(BaseTest): def test_script_with_unit_tests_when_hey_is_not_passed_in( self, app: Flask, + client: FlaskClient, with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel ) -> None: """Test_script_with_unit_tests_when_hey_is_not_passed_in.""" app.config["THREAD_LOCAL_DATA"].process_instance_id = None process_group_id = "script_with_unit_tests" + self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id) + process_model_id = "script_with_unit_tests" - load_test_spec(process_model_id, process_group_id=process_group_id) + process_model_identifier = f"{process_group_id}/{process_model_id}" + + load_test_spec( + process_model_identifier, + bpmn_file_name=process_model_id, + process_model_source_directory=process_model_id + ) bpmn_process_instance = ( ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model( - process_model_id, process_group_id + process_model_identifier ) ) task = ProcessInstanceProcessor.get_task_by_bpmn_identifier( diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py index fd882e71..44621e19 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py @@ -3,29 +3,38 @@ import os import pytest from flask import Flask +from flask.testing import FlaskClient from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup +from spiffworkflow_backend.models.user import UserModel class TestSpecFileService(BaseTest): """TestSpecFileService.""" + process_group_id = "test_process_group_id" + process_model_id = "call_activity_nested" + bpmn_file_name = "call_activity_nested.bpmn" + call_activity_nested_relative_file_path = os.path.join( - "test_process_group_id", "call_activity_nested", "call_activity_nested.bpmn" + process_group_id, process_model_id, bpmn_file_name ) def test_can_store_process_ids_for_lookup( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_can_store_process_ids_for_lookup.""" - load_test_spec( - "call_activity_nested", - process_model_source_directory="call_activity_nested", - bpmn_file_name="call_activity_nested", + self.basic_test_setup( + client=client, + user=with_super_admin_user, + process_group_id=self.process_group_id, + process_model_id=self.process_model_id, + bpmn_file_name=self.bpmn_file_name, + bpmn_file_location="call_activity_nested" ) bpmn_process_id_lookups = BpmnProcessIdLookup.query.all() assert len(bpmn_process_id_lookups) == 1 @@ -36,14 +45,17 @@ class TestSpecFileService(BaseTest): ) def test_fails_to_save_duplicate_process_id( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_fails_to_save_duplicate_process_id.""" bpmn_process_identifier = "Level1" - load_test_spec( - "call_activity_nested", - process_model_source_directory="call_activity_nested", - bpmn_file_name="call_activity_nested", + self.basic_test_setup( + client=client, + user=with_super_admin_user, + process_group_id=self.process_group_id, + process_model_id=self.process_model_id, + bpmn_file_name=self.bpmn_file_name, + bpmn_file_location=self.process_model_id ) bpmn_process_id_lookups = BpmnProcessIdLookup.query.all() assert len(bpmn_process_id_lookups) == 1 @@ -66,25 +78,26 @@ class TestSpecFileService(BaseTest): ) def test_updates_relative_file_path_when_appropriate( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel ) -> None: """Test_updates_relative_file_path_when_appropriate.""" bpmn_process_identifier = "Level1" - bpmn_file_relative_path = os.path.join( - "test_process_group_id", "call_activity_nested", "new_bpmn_file.bpmn" - ) process_id_lookup = BpmnProcessIdLookup( bpmn_process_identifier=bpmn_process_identifier, - bpmn_file_relative_path=bpmn_file_relative_path, + bpmn_file_relative_path=self.call_activity_nested_relative_file_path, ) db.session.add(process_id_lookup) db.session.commit() - load_test_spec( - "call_activity_nested", - process_model_source_directory="call_activity_nested", - bpmn_file_name="call_activity_nested", + self.basic_test_setup( + client=client, + user=with_super_admin_user, + process_group_id=self.process_group_id, + process_model_id=self.process_model_id, + bpmn_file_name=self.bpmn_file_name, + bpmn_file_location=self.process_model_id ) + bpmn_process_id_lookups = BpmnProcessIdLookup.query.all() assert len(bpmn_process_id_lookups) == 1 assert ( diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py index c97803d8..56e6439e 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py @@ -1,23 +1,32 @@ """Test_various_bpmn_constructs.""" from flask.app import Flask +from flask.testing import FlaskClient +from spiffworkflow_backend.models.user import UserModel +from spiffworkflow_backend.services.process_model_service import ProcessModelService +from spiffworkflow_backend.services.process_instance_processor import ProcessInstanceProcessor from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec - -from spiffworkflow_backend.services.process_instance_processor import ( - ProcessInstanceProcessor, -) class TestVariousBpmnConstructs(BaseTest): """TestVariousBpmnConstructs.""" def test_running_process_with_timer_intermediate_catch_event( - self, app: Flask, with_db_and_bpmn_file_cleanup: None + self, + app: Flask, + client: FlaskClient, + with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel ) -> None: """Test_running_process_with_timer_intermediate_catch_event.""" - process_model = load_test_spec( - "timers_intermediate_catch_event", - process_model_source_directory="timer_intermediate_catch_event", + process_model_identifier = self.basic_test_setup( + client, + with_super_admin_user, + "test_group", + "timer_intermediate_catch_event" + ) + + process_model = ProcessModelService().get_process_model( + process_model_id=process_model_identifier ) process_instance = self.create_process_instance_from_process_model(