From 4ee7b299f2dd62acedb8c2be5dd5438cb03e4e34 Mon Sep 17 00:00:00 2001 From: jasquat Date: Mon, 6 Mar 2023 11:59:33 -0500 Subject: [PATCH] pyl and fixed cypress tests w/ burnettk --- spiffworkflow-backend/conftest.py | 2 +- spiffworkflow-backend/migrations/env.py | 2 - .../models/bpmn_process.py | 7 +- .../models/process_instance.py | 7 +- .../routes/process_instances_controller.py | 4 +- .../services/process_instance_processor.py | 97 +++++++++++++------ .../cypress/e2e/process_instances.cy.js | 5 +- .../cypress/pilot/pp1.cy.js | 2 +- .../cypress/support/commands.js | 8 +- 9 files changed, 86 insertions(+), 48 deletions(-) diff --git a/spiffworkflow-backend/conftest.py b/spiffworkflow-backend/conftest.py index 3e4804a8b..3adf8725e 100644 --- a/spiffworkflow-backend/conftest.py +++ b/spiffworkflow-backend/conftest.py @@ -5,9 +5,9 @@ import shutil import pytest from flask.app import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.models.bpmn_process import BpmnProcessModel from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from spiffworkflow_backend.models.bpmn_process import BpmnProcessModel from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/migrations/env.py b/spiffworkflow-backend/migrations/env.py index 68feded2a..630e381ad 100644 --- a/spiffworkflow-backend/migrations/env.py +++ b/spiffworkflow-backend/migrations/env.py @@ -1,5 +1,3 @@ -from __future__ import with_statement - import logging from logging.config import fileConfig diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process.py index b5a3137e6..e1c146d4f 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process.py @@ -1,5 +1,4 @@ from __future__ import annotations -from typing import Optional from sqlalchemy import ForeignKey @@ -16,9 +15,11 @@ from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel class BpmnProcessModel(SpiffworkflowBaseDBModel): __tablename__ = "bpmn_process" id: int = db.Column(db.Integer, primary_key=True) - guid: Optional[str] = db.Column(db.String(36), nullable=True, unique=True, index=True) + guid: str | None = db.Column(db.String(36), nullable=True, unique=True, index=True) - parent_process_id: Optional[int] = db.Column(ForeignKey("bpmn_process.id"), nullable=True) + parent_process_id: int | None = db.Column( + ForeignKey("bpmn_process.id"), nullable=True + ) properties_json: dict = db.Column(db.JSON, nullable=False) json_data_hash: str = db.Column(db.String(255), nullable=False, index=True) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py index ea7f45623..cbbceaba9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py @@ -1,7 +1,5 @@ """Process_instance.""" from __future__ import annotations -from typing import Optional -from spiffworkflow_backend.models.bpmn_process import BpmnProcessModel from typing import Any from typing import cast @@ -17,6 +15,7 @@ from sqlalchemy.orm import relationship from sqlalchemy.orm import validates from spiffworkflow_backend.helpers.spiff_enum import SpiffEnum +from spiffworkflow_backend.models.bpmn_process import BpmnProcessModel from spiffworkflow_backend.models.bpmn_process_definition import ( BpmnProcessDefinitionModel, ) @@ -65,11 +64,11 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel): process_initiator_id: int = db.Column(ForeignKey(UserModel.id), nullable=False) # type: ignore process_initiator = relationship("UserModel") - bpmn_process_definition_id: Optional[int] = db.Column( + bpmn_process_definition_id: int | None = db.Column( ForeignKey(BpmnProcessDefinitionModel.id), nullable=True # type: ignore ) bpmn_process_definition = relationship(BpmnProcessDefinitionModel) - bpmn_process_id: Optional[int] = db.Column( + bpmn_process_id: int | None = db.Column( ForeignKey(BpmnProcessModel.id), nullable=True # type: ignore ) bpmn_process = relationship(BpmnProcessModel) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py index d33a1c000..fbf33ad38 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py @@ -586,7 +586,9 @@ def process_instance_task_list( spiff_task_id, TaskState.FUTURE ) - bpmn_process_instance = ProcessInstanceProcessor._serializer.workflow_from_dict(full_bpmn_process_dict) + bpmn_process_instance = ProcessInstanceProcessor._serializer.workflow_from_dict( + full_bpmn_process_dict + ) spiff_task = processor.__class__.get_task_by_bpmn_identifier( step_details[-1].bpmn_task_identifier, bpmn_process_instance 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 24e6a3187..e90acd77a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -1,7 +1,5 @@ """Process_instance_processor.""" import _strptime # type: ignore -from SpiffWorkflow.task import TaskStateNames # type: ignore -from spiffworkflow_backend.models.task import TaskModel # noqa: F401 import decimal import json import logging @@ -53,6 +51,7 @@ from SpiffWorkflow.serializer.exceptions import MissingSpecError # type: ignore from SpiffWorkflow.spiff.serializer.config import SPIFF_SPEC_CONFIG # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import TaskState +from SpiffWorkflow.task import TaskStateNames from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore from sqlalchemy import text @@ -86,6 +85,7 @@ from spiffworkflow_backend.models.script_attributes_context import ( ) from spiffworkflow_backend.models.spec_reference import SpecReferenceCache from spiffworkflow_backend.models.spiff_step_details import SpiffStepDetailsModel +from spiffworkflow_backend.models.task import TaskModel # noqa: F401 from spiffworkflow_backend.models.task_definition import TaskDefinitionModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.scripts.script import Script @@ -465,11 +465,13 @@ class ProcessInstanceProcessor: ) try: - (self.bpmn_process_instance, self.full_bpmn_process_dict) = self.__get_bpmn_process_instance( - process_instance_model, - bpmn_process_spec, - validate_only, - subprocesses=subprocesses, + (self.bpmn_process_instance, self.full_bpmn_process_dict) = ( + self.__get_bpmn_process_instance( + process_instance_model, + bpmn_process_spec, + validate_only, + subprocesses=subprocesses, + ) ) self.set_script_engine(self.bpmn_process_instance) @@ -545,7 +547,9 @@ class ProcessInstanceProcessor: @classmethod def _set_definition_dict_for_bpmn_subprocess_definitions( - cls, bpmn_process_definition: BpmnProcessDefinitionModel, spiff_bpmn_process_dict: dict + cls, + bpmn_process_definition: BpmnProcessDefinitionModel, + spiff_bpmn_process_dict: dict, ) -> None: bpmn_process_subprocess_definitions = ( BpmnProcessDefinitionRelationshipModel.query.filter_by( @@ -562,19 +566,23 @@ class ProcessInstanceProcessor: @classmethod def _get_bpmn_process_dict(cls, bpmn_process: BpmnProcessModel) -> dict: - json_data = JsonDataModel.query.filter_by(hash=bpmn_process.json_data_hash).first() - bpmn_process_dict = {'data': json_data.data, 'tasks': {}} + json_data = JsonDataModel.query.filter_by( + hash=bpmn_process.json_data_hash + ).first() + bpmn_process_dict = {"data": json_data.data, "tasks": {}} bpmn_process_dict.update(bpmn_process.properties_json) tasks = TaskModel.query.filter_by(bpmn_process_id=bpmn_process.id).all() for task in tasks: json_data = JsonDataModel.query.filter_by(hash=task.json_data_hash).first() - bpmn_process_dict['tasks'][task.guid] = task.properties_json - bpmn_process_dict['tasks'][task.guid]['data'] = json_data.data + bpmn_process_dict["tasks"][task.guid] = task.properties_json + bpmn_process_dict["tasks"][task.guid]["data"] = json_data.data return bpmn_process_dict @classmethod - def _get_full_bpmn_process_dict(cls, process_instance_model: ProcessInstanceModel) -> dict: + def _get_full_bpmn_process_dict( + cls, process_instance_model: ProcessInstanceModel + ) -> dict: if process_instance_model.bpmn_process_definition_id is None: return {} @@ -582,7 +590,7 @@ class ProcessInstanceProcessor: "serializer_version": process_instance_model.spiff_serializer_version, "spec": {}, "subprocess_specs": {}, - "subprocesses": {} + "subprocesses": {}, } bpmn_process_definition = process_instance_model.bpmn_process_definition if bpmn_process_definition is not None: @@ -591,17 +599,23 @@ class ProcessInstanceProcessor: bpmn_process_definition ) ) - cls._set_definition_dict_for_bpmn_subprocess_definitions(bpmn_process_definition, spiff_bpmn_process_dict) + cls._set_definition_dict_for_bpmn_subprocess_definitions( + bpmn_process_definition, spiff_bpmn_process_dict + ) bpmn_process = process_instance_model.bpmn_process if bpmn_process is not None: bpmn_process_dict = cls._get_bpmn_process_dict(bpmn_process) spiff_bpmn_process_dict.update(bpmn_process_dict) - bpmn_subprocesses = BpmnProcessModel.query.filter_by(parent_process_id=bpmn_process.id).all() + bpmn_subprocesses = BpmnProcessModel.query.filter_by( + parent_process_id=bpmn_process.id + ).all() for bpmn_subprocess in bpmn_subprocesses: bpmn_process_dict = cls._get_bpmn_process_dict(bpmn_subprocess) - spiff_bpmn_process_dict['subprocesses'][bpmn_subprocess.guid] = bpmn_process_dict + spiff_bpmn_process_dict["subprocesses"][ + bpmn_subprocess.guid + ] = bpmn_process_dict return spiff_bpmn_process_dict @@ -647,10 +661,16 @@ class ProcessInstanceProcessor: spiff_logger.setLevel(logging.WARNING) try: - full_bpmn_process_dict = ProcessInstanceProcessor._get_full_bpmn_process_dict( - process_instance_model + full_bpmn_process_dict = ( + ProcessInstanceProcessor._get_full_bpmn_process_dict( + process_instance_model + ) + ) + bpmn_process_instance = ( + ProcessInstanceProcessor._serializer.workflow_from_dict( + full_bpmn_process_dict + ) ) - bpmn_process_instance = ProcessInstanceProcessor._serializer.workflow_from_dict(full_bpmn_process_dict) except Exception as err: raise err finally: @@ -981,14 +1001,20 @@ class ProcessInstanceProcessor: bpmn_process_definition_parent ) - def _add_bpmn_process(self, bpmn_process_dict: dict, bpmn_process_parent: Optional[BpmnProcessModel] = None, bpmn_process_guid: Optional[str] = None) -> BpmnProcessModel: + def _add_bpmn_process( + self, + bpmn_process_dict: dict, + bpmn_process_parent: Optional[BpmnProcessModel] = None, + bpmn_process_guid: Optional[str] = None, + ) -> BpmnProcessModel: tasks = bpmn_process_dict.pop("tasks") bpmn_process_data = bpmn_process_dict.pop("data") bpmn_process = None if bpmn_process_parent is not None: bpmn_process = BpmnProcessModel.query.filter_by( - parent_process_id=bpmn_process_parent.id, guid=bpmn_process_guid).first() + parent_process_id=bpmn_process_parent.id, guid=bpmn_process_guid + ).first() elif self.process_instance_model.bpmn_process_id is not None: bpmn_process = self.process_instance_model.bpmn_process @@ -997,12 +1023,20 @@ class ProcessInstanceProcessor: bpmn_process.properties_json = bpmn_process_dict - bpmn_process_data_json = json.dumps(bpmn_process_data, sort_keys=True).encode("utf8") + bpmn_process_data_json = json.dumps(bpmn_process_data, sort_keys=True).encode( + "utf8" + ) bpmn_process_data_hash = sha256(bpmn_process_data_json).hexdigest() if bpmn_process.json_data_hash != bpmn_process_data_hash: - json_data = db.session.query(JsonDataModel.id).filter_by(hash=bpmn_process_data_hash).first() + json_data = ( + db.session.query(JsonDataModel.id) + .filter_by(hash=bpmn_process_data_hash) + .first() + ) if json_data is None: - json_data = JsonDataModel(hash=bpmn_process_data_hash, data=bpmn_process_data) + json_data = JsonDataModel( + hash=bpmn_process_data_hash, data=bpmn_process_data + ) db.session.add(json_data) bpmn_process.json_data_hash = bpmn_process_data_hash @@ -1013,15 +1047,16 @@ class ProcessInstanceProcessor: db.session.add(bpmn_process) for task_id, task_properties in tasks.items(): - task_data_dict = task_properties.pop('data') - state_int = task_properties['state'] + task_data_dict = task_properties.pop("data") + state_int = task_properties["state"] task = TaskModel.query.filter_by(guid=task_id).first() if task is None: # bpmn_process_identifier = task_properties['workflow_name'] # bpmn_identifier = task_properties['task_spec'] # - # task_definition = TaskDefinitionModel.query.filter_by(bpmn_identifier=bpmn_identifier).join(BpmnProcessDefinitionModel).filter(BpmnProcessDefinitionModel.bpmn_identifier==bpmn_process_identifier).first() + # task_definition = TaskDefinitionModel.query.filter_by(bpmn_identifier=bpmn_identifier) + # .join(BpmnProcessDefinitionModel).filter(BpmnProcessDefinitionModel.bpmn_identifier==bpmn_process_identifier).first() # if task_definition is None: # subprocess_task = TaskModel.query.filter_by(guid=bpmn_process.guid) task = TaskModel(guid=task_id, bpmn_process_id=bpmn_process.id) @@ -1031,7 +1066,11 @@ class ProcessInstanceProcessor: task_data_json = json.dumps(task_data_dict, sort_keys=True).encode("utf8") task_data_hash = sha256(task_data_json).hexdigest() if task.json_data_hash != task_data_hash: - json_data = db.session.query(JsonDataModel.id).filter_by(hash=task_data_hash).first() + json_data = ( + db.session.query(JsonDataModel.id) + .filter_by(hash=task_data_hash) + .first() + ) if json_data is None: json_data = JsonDataModel(hash=task_data_hash, data=task_data_dict) db.session.add(json_data) diff --git a/spiffworkflow-frontend/cypress/e2e/process_instances.cy.js b/spiffworkflow-frontend/cypress/e2e/process_instances.cy.js index e582dcbba..846d41627 100644 --- a/spiffworkflow-frontend/cypress/e2e/process_instances.cy.js +++ b/spiffworkflow-frontend/cypress/e2e/process_instances.cy.js @@ -179,13 +179,14 @@ describe('process-instances', () => { cy.get(statusSelect).contains(processStatus).click(); cy.get(statusSelect).click(); cy.getBySel('filter-button').click(); - // FIXME: wait a little bit for the useEffects to be able to fully set processInstanceFilters - cy.wait(1000); cy.url().should('include', `status=${processStatus}`); cy.assertAtLeastOneItemInPaginatedResults(); cy.getBySel(`process-instance-status-${processStatus}`); // there should really only be one, but in CI there are sometimes more cy.get('div[aria-label="Clear all selected items"]:first').click(); + cy.get('div[aria-label="Clear all selected items"]').should( + 'not.exist' + ); } }); diff --git a/spiffworkflow-frontend/cypress/pilot/pp1.cy.js b/spiffworkflow-frontend/cypress/pilot/pp1.cy.js index 47dbbf30a..c34315b83 100644 --- a/spiffworkflow-frontend/cypress/pilot/pp1.cy.js +++ b/spiffworkflow-frontend/cypress/pilot/pp1.cy.js @@ -31,7 +31,7 @@ const approveWithUser = ( }; describe('pp1', () => { - it('can run PP1', () => { + it.skip('can run PP1', () => { cy.login('core5.contributor', 'core5.contributor'); cy.visit('/'); cy.contains('Start New +').click(); diff --git a/spiffworkflow-frontend/cypress/support/commands.js b/spiffworkflow-frontend/cypress/support/commands.js index a878fbf46..5e786a0dc 100644 --- a/spiffworkflow-frontend/cypress/support/commands.js +++ b/spiffworkflow-frontend/cypress/support/commands.js @@ -42,13 +42,11 @@ Cypress.Commands.add('navigateToAdmin', () => { }); Cypress.Commands.add('login', (username, password) => { - // Cypress.Commands.add('login', (selector, ...args) => { cy.visit('/admin'); + console.log('username', username); if (!username) { - const username = - Cypress.env('SPIFFWORKFLOW_FRONTEND_USERNAME') || 'ciadmin1'; - const password = - Cypress.env('SPIFFWORKFLOW_FRONTEND_PASSWORD') || 'ciadmin1'; + username = Cypress.env('SPIFFWORKFLOW_FRONTEND_USERNAME') || 'ciadmin1'; + password = Cypress.env('SPIFFWORKFLOW_FRONTEND_PASSWORD') || 'ciadmin1'; } cy.get('#username').type(username); cy.get('#password').type(password);