Merge remote-tracking branch 'origin/main' into bug/improve_reset_to_previous_task
This commit is contained in:
commit
3932435482
|
@ -1,3 +1,5 @@
|
|||
import groovy.json.JsonBuilder
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
|
@ -45,6 +47,17 @@ pipeline {
|
|||
}
|
||||
|
||||
stages {
|
||||
stage('Prep') {
|
||||
steps { script {
|
||||
def jobMetaJson = new JsonBuilder([
|
||||
git_commit: env.GIT_COMMIT.take(7),
|
||||
git_branch: env.GIT_BRANCH,
|
||||
build_id: env.BUILD_ID,
|
||||
]).toPrettyString()
|
||||
sh "echo '${jobMetaJson}' > version_info.json"
|
||||
} }
|
||||
}
|
||||
|
||||
stage('Build') {
|
||||
steps { script {
|
||||
dir("spiffworkflow-${params.COMPONENT}") {
|
||||
|
|
|
@ -7,10 +7,15 @@ function error_handler() {
|
|||
trap 'error_handler ${LINENO} $?' ERR
|
||||
set -o errtrace -o errexit -o nounset -o pipefail
|
||||
|
||||
port="${SPIFFWORKFLOW_BACKEND_PORT:-7000}"
|
||||
|
||||
arg="${1:-}"
|
||||
if [[ "$arg" == "acceptance" ]]; then
|
||||
export SPIFFWORKFLOW_BACKEND_LOAD_FIXTURE_DATA=true
|
||||
export SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME=acceptance_tests.yml
|
||||
elif [[ "$arg" == "localopenid" ]]; then
|
||||
export SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_URL="http://localhost:$port/openid"
|
||||
export SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME="example.yml"
|
||||
fi
|
||||
|
||||
if [[ -z "${SPIFFWORKFLOW_BACKEND_ENV:-}" ]]; then
|
||||
|
@ -38,5 +43,5 @@ else
|
|||
fi
|
||||
|
||||
# this line blocks
|
||||
SPIFFWORKFLOW_BACKEND_RUN_BACKGROUND_SCHEDULER="${SPIFFWORKFLOW_BACKEND_RUN_BACKGROUND_SCHEDULER}" FLASK_APP=src/spiffworkflow_backend poetry run flask run -p 7000
|
||||
SPIFFWORKFLOW_BACKEND_RUN_BACKGROUND_SCHEDULER="${SPIFFWORKFLOW_BACKEND_RUN_BACKGROUND_SCHEDULER}" FLASK_APP=src/spiffworkflow_backend poetry run flask run -p "$port" --host=0.0.0.0
|
||||
fi
|
||||
|
|
|
@ -62,13 +62,16 @@ SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_SECRET_KEY = environ.get(
|
|||
default="JXeQExm0JhQPLumgHtIIqf52bDalHz0q",
|
||||
) # noqa: S105
|
||||
|
||||
# Tenant specific fields is a comma separated list of field names that we will convert to list of strings
|
||||
# Tenant specific fields is a comma separated list of field names that we will be converted to list of strings
|
||||
# and store in the user table's tenant_specific_field_n columns. You can have up to three items in this
|
||||
# comma-separated list.
|
||||
SPIFFWORKFLOW_BACKEND_OPEN_ID_TENANT_SPECIFIC_FIELDS = environ.get(
|
||||
"SPIFFWORKFLOW_BACKEND_OPEN_ID_TENANT_SPECIFIC_FIELDS"
|
||||
)
|
||||
|
||||
# loggers to use is a comma separated list of logger prefixes that we will be converted to list of strings
|
||||
SPIFFWORKFLOW_BACKEND_LOGGERS_TO_USE = environ.get("SPIFFWORKFLOW_BACKEND_LOGGERS_TO_USE")
|
||||
|
||||
# cryptography or simple-crypt
|
||||
SPIFFWORKFLOW_BACKEND_ENCRYPTION_LIB = environ.get(
|
||||
# "SPIFFWORKFLOW_BACKEND_ENCRYPTION_LIB", default="cryptography"
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
default_group: everybody
|
||||
|
||||
groups:
|
||||
admin:
|
||||
users:
|
||||
- jason@sartography.com
|
||||
- kevin@sartography.com
|
||||
- dan@sartography.com
|
||||
- alex@sartography.com
|
||||
- jon@sartography.com
|
||||
- elizabeth@sartography.com
|
||||
- madhurya@sartography.com
|
||||
|
||||
tech_writers:
|
||||
users:
|
||||
- usama@sartography.com
|
||||
- phillana@sartography.com
|
||||
|
||||
permissions:
|
||||
admin:
|
||||
groups: [admin, tech_writers]
|
||||
users: []
|
||||
allowed_permissions: [create, read, update, delete]
|
||||
uri: /*
|
|
@ -172,7 +172,7 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel):
|
|||
|
||||
@classmethod
|
||||
def active_statuses(cls) -> list[str]:
|
||||
return ["user_input_required", "waiting"]
|
||||
return ["not_started", "user_input_required", "waiting"]
|
||||
|
||||
|
||||
class ProcessInstanceModelSchema(Schema):
|
||||
|
|
|
@ -87,11 +87,7 @@ def process_group_update(modified_process_group_id: str, body: dict) -> flask.wr
|
|||
def process_group_list(
|
||||
process_group_identifier: Optional[str] = None, page: int = 1, per_page: int = 100
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process_group_list."""
|
||||
if process_group_identifier is not None:
|
||||
process_groups = ProcessModelService.get_process_groups(process_group_identifier)
|
||||
else:
|
||||
process_groups = ProcessModelService.get_process_groups()
|
||||
process_groups = ProcessModelService.get_process_groups_for_api(process_group_identifier)
|
||||
batch = ProcessModelService().get_batch(items=process_groups, page=page, per_page=per_page)
|
||||
pages = len(process_groups) // per_page
|
||||
remainder = len(process_groups) % per_page
|
||||
|
|
|
@ -214,8 +214,7 @@ def process_model_list(
|
|||
page: int = 1,
|
||||
per_page: int = 100,
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process model list!"""
|
||||
process_models = ProcessModelService.get_process_models(
|
||||
process_models = ProcessModelService.get_process_models_for_api(
|
||||
process_group_id=process_group_identifier,
|
||||
recursive=recursive,
|
||||
filter_runnable_by_user=filter_runnable_by_user,
|
||||
|
|
|
@ -45,7 +45,8 @@ from spiffworkflow_backend.models.process_instance import (
|
|||
)
|
||||
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType
|
||||
from spiffworkflow_backend.models.process_model import ProcessModelInfo
|
||||
from spiffworkflow_backend.models.task import TaskModel # noqa: F401
|
||||
from spiffworkflow_backend.models.task import Task
|
||||
from spiffworkflow_backend.models.task import TaskModel
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.routes.process_api_blueprint import (
|
||||
_find_principal_or_raise,
|
||||
|
@ -400,6 +401,11 @@ def _interstitial_stream(process_instance: ProcessInstanceModel) -> Generator[st
|
|||
extensions = TaskService.get_extensions_from_task_model(task_model)
|
||||
return _render_instructions_for_end_user(task_model, extensions)
|
||||
|
||||
def render_data(return_type: str, entity: Union[ApiError, Task, ProcessInstanceModel]) -> str:
|
||||
return_hash: dict = {"type": return_type}
|
||||
return_hash[return_type] = entity
|
||||
return f"data: {current_app.json.dumps(return_hash)} \n\n"
|
||||
|
||||
tasks = get_reportable_tasks()
|
||||
while True:
|
||||
for spiff_task in tasks:
|
||||
|
@ -411,23 +417,27 @@ def _interstitial_stream(process_instance: ProcessInstanceModel) -> Generator[st
|
|||
message=f"Failed to complete an automated task. Error was: {str(e)}",
|
||||
status_code=400,
|
||||
)
|
||||
yield f"data: {current_app.json.dumps(api_error)} \n\n"
|
||||
yield render_data("error", api_error)
|
||||
raise e
|
||||
if instructions and spiff_task.id not in reported_ids:
|
||||
task = ProcessInstanceService.spiff_task_to_api_task(processor, spiff_task)
|
||||
task.properties = {"instructionsForEndUser": instructions}
|
||||
yield f"data: {current_app.json.dumps(task)} \n\n"
|
||||
yield render_data("task", task)
|
||||
reported_ids.append(spiff_task.id)
|
||||
if spiff_task.state == TaskState.READY:
|
||||
# do not do any processing if the instance is not currently active
|
||||
if process_instance.status not in ProcessInstanceModel.active_statuses():
|
||||
yield render_data("unrunnable_instance", process_instance)
|
||||
break
|
||||
try:
|
||||
processor.do_engine_steps(execution_strategy_name="one_at_a_time")
|
||||
processor.do_engine_steps(execution_strategy_name="run_until_user_message")
|
||||
processor.save() # Fixme - maybe find a way not to do this on every loop?
|
||||
except WorkflowTaskException as wfe:
|
||||
api_error = ApiError.from_workflow_exception(
|
||||
"engine_steps_error", "Failed complete an automated task.", exp=wfe
|
||||
"engine_steps_error", "Failed to complete an automated task.", exp=wfe
|
||||
)
|
||||
yield f"data: {current_app.json.dumps(api_error)} \n\n"
|
||||
yield render_data("error", api_error)
|
||||
return
|
||||
except Exception as e:
|
||||
api_error = ApiError(
|
||||
|
@ -435,7 +445,7 @@ def _interstitial_stream(process_instance: ProcessInstanceModel) -> Generator[st
|
|||
message=f"Failed to complete an automated task. Error was: {str(e)}",
|
||||
status_code=400,
|
||||
)
|
||||
yield f"data: {current_app.json.dumps(api_error)} \n\n"
|
||||
yield render_data("error", api_error)
|
||||
return
|
||||
processor.refresh_waiting_tasks()
|
||||
ready_engine_task_count = get_ready_engine_step_count(processor.bpmn_process_instance)
|
||||
|
@ -454,10 +464,10 @@ def _interstitial_stream(process_instance: ProcessInstanceModel) -> Generator[st
|
|||
message=f"Failed to complete an automated task. Error was: {str(e)}",
|
||||
status_code=400,
|
||||
)
|
||||
yield f"data: {current_app.json.dumps(api_error)} \n\n"
|
||||
yield render_data("error", api_error)
|
||||
raise e
|
||||
task.properties = {"instructionsForEndUser": instructions}
|
||||
yield f"data: {current_app.json.dumps(task)} \n\n"
|
||||
yield render_data("task", task)
|
||||
|
||||
|
||||
def get_ready_engine_step_count(bpmn_process_instance: BpmnWorkflow) -> int:
|
||||
|
@ -472,8 +482,9 @@ def get_ready_engine_step_count(bpmn_process_instance: BpmnWorkflow) -> int:
|
|||
)
|
||||
|
||||
|
||||
def _dequeued_interstitial_stream(process_instance_id: int) -> Generator[str, Optional[str], None]:
|
||||
def _dequeued_interstitial_stream(process_instance_id: int) -> Generator[Optional[str], Optional[str], None]:
|
||||
process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
|
||||
|
||||
with ProcessInstanceQueueService.dequeued(process_instance):
|
||||
yield from _interstitial_stream(process_instance)
|
||||
|
||||
|
|
|
@ -577,6 +577,8 @@ class AuthorizationService:
|
|||
permissions_to_assign.append(
|
||||
PermissionToAssign(permission="read", target_uri="/process-instances/report-metadata")
|
||||
)
|
||||
permissions_to_assign.append(PermissionToAssign(permission="read", target_uri="/process-groups"))
|
||||
permissions_to_assign.append(PermissionToAssign(permission="read", target_uri="/process-models"))
|
||||
permissions_to_assign.append(PermissionToAssign(permission="read", target_uri="/processes"))
|
||||
permissions_to_assign.append(PermissionToAssign(permission="read", target_uri="/processes/callers"))
|
||||
permissions_to_assign.append(PermissionToAssign(permission="read", target_uri="/service-tasks"))
|
||||
|
|
|
@ -129,8 +129,27 @@ def setup_logger(app: Flask) -> None:
|
|||
spiff_logger_filehandler.setFormatter(log_formatter)
|
||||
|
||||
# these loggers have been deemed too verbose to be useful
|
||||
garbage_loggers_to_exclude = ["connexion", "flask_cors.extension"]
|
||||
loggers_to_exclude_from_debug = ["sqlalchemy"]
|
||||
garbage_loggers_to_exclude = ["connexion", "flask_cors.extension", "flask_cors.core", "sqlalchemy"]
|
||||
|
||||
# if you actually want one of these excluded loggers, there is a config option to turn it on
|
||||
loggers_to_use = app.config.get("SPIFFWORKFLOW_BACKEND_LOGGERS_TO_USE", [])
|
||||
if loggers_to_use is None or loggers_to_use == "":
|
||||
loggers_to_use = []
|
||||
else:
|
||||
loggers_to_use = loggers_to_use.split(",")
|
||||
for logger_to_use in loggers_to_use:
|
||||
if logger_to_use in garbage_loggers_to_exclude:
|
||||
garbage_loggers_to_exclude.remove(logger_to_use)
|
||||
else:
|
||||
app.logger.warning(
|
||||
f"Logger '{logger_to_use}' not found in garbage_loggers_to_exclude. You do not need to add it to"
|
||||
" SPIFFWORKFLOW_BACKEND_LOGGERS_TO_USE."
|
||||
)
|
||||
|
||||
loggers_to_exclude_from_debug = []
|
||||
|
||||
if "sqlalchemy" not in garbage_loggers_to_exclude:
|
||||
loggers_to_exclude_from_debug.append("sqlalchemy")
|
||||
|
||||
# make all loggers act the same
|
||||
for name in logging.root.manager.loggerDict:
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import json
|
||||
import os
|
||||
import shutil
|
||||
import uuid
|
||||
from glob import glob
|
||||
from typing import Any
|
||||
from typing import List
|
||||
|
@ -187,9 +188,7 @@ class ProcessModelService(FileSystemService):
|
|||
cls,
|
||||
process_group_id: Optional[str] = None,
|
||||
recursive: Optional[bool] = False,
|
||||
filter_runnable_by_user: Optional[bool] = False,
|
||||
) -> List[ProcessModelInfo]:
|
||||
"""Get process models."""
|
||||
process_models = []
|
||||
root_path = FileSystemService.root_path()
|
||||
if process_group_id:
|
||||
|
@ -205,22 +204,45 @@ class ProcessModelService(FileSystemService):
|
|||
process_model = cls.get_process_model_from_relative_path(os.path.dirname(process_model_relative_path))
|
||||
process_models.append(process_model)
|
||||
process_models.sort()
|
||||
|
||||
if filter_runnable_by_user:
|
||||
user = UserService.current_user()
|
||||
new_process_model_list = []
|
||||
for process_model in process_models:
|
||||
modified_process_model_id = ProcessModelInfo.modify_process_identifier_for_path_param(process_model.id)
|
||||
uri = f"/v1.0/process-instances/{modified_process_model_id}"
|
||||
has_permission = AuthorizationService.user_has_permission(
|
||||
user=user, permission="create", target_uri=uri
|
||||
)
|
||||
if has_permission:
|
||||
new_process_model_list.append(process_model)
|
||||
return new_process_model_list
|
||||
|
||||
return process_models
|
||||
|
||||
@classmethod
|
||||
def get_process_models_for_api(
|
||||
cls,
|
||||
process_group_id: Optional[str] = None,
|
||||
recursive: Optional[bool] = False,
|
||||
filter_runnable_by_user: Optional[bool] = False,
|
||||
) -> List[ProcessModelInfo]:
|
||||
process_models = cls.get_process_models(process_group_id, recursive)
|
||||
|
||||
permission_to_check = "read"
|
||||
permission_base_uri = "/v1.0/process-models"
|
||||
user = UserService.current_user()
|
||||
if filter_runnable_by_user:
|
||||
permission_to_check = "create"
|
||||
permission_base_uri = "/v1.0/process-instances"
|
||||
|
||||
# if user has access to uri/* with that permission then there's no reason to check each one individually
|
||||
guid_of_non_existent_item_to_check_perms_against = str(uuid.uuid4())
|
||||
has_permission = AuthorizationService.user_has_permission(
|
||||
user=user,
|
||||
permission=permission_to_check,
|
||||
target_uri=f"{permission_base_uri}/{guid_of_non_existent_item_to_check_perms_against}",
|
||||
)
|
||||
if has_permission:
|
||||
return process_models
|
||||
|
||||
new_process_model_list = []
|
||||
for process_model in process_models:
|
||||
modified_process_model_id = ProcessModelInfo.modify_process_identifier_for_path_param(process_model.id)
|
||||
uri = f"{permission_base_uri}/{modified_process_model_id}"
|
||||
has_permission = AuthorizationService.user_has_permission(
|
||||
user=user, permission=permission_to_check, target_uri=uri
|
||||
)
|
||||
if has_permission:
|
||||
new_process_model_list.append(process_model)
|
||||
return new_process_model_list
|
||||
|
||||
@classmethod
|
||||
def get_parent_group_array_and_cache_it(
|
||||
cls, process_identifier: str, process_group_cache: dict[str, ProcessGroup]
|
||||
|
@ -256,6 +278,38 @@ class ProcessModelService(FileSystemService):
|
|||
process_groups.sort()
|
||||
return process_groups
|
||||
|
||||
@classmethod
|
||||
def get_process_groups_for_api(
|
||||
cls,
|
||||
process_group_id: Optional[str] = None,
|
||||
) -> List[ProcessGroup]:
|
||||
process_groups = cls.get_process_groups(process_group_id)
|
||||
|
||||
permission_to_check = "read"
|
||||
permission_base_uri = "/v1.0/process-groups"
|
||||
user = UserService.current_user()
|
||||
|
||||
# if user has access to uri/* with that permission then there's no reason to check each one individually
|
||||
guid_of_non_existent_item_to_check_perms_against = str(uuid.uuid4())
|
||||
has_permission = AuthorizationService.user_has_permission(
|
||||
user=user,
|
||||
permission=permission_to_check,
|
||||
target_uri=f"{permission_base_uri}/{guid_of_non_existent_item_to_check_perms_against}",
|
||||
)
|
||||
if has_permission:
|
||||
return process_groups
|
||||
|
||||
new_process_group_list = []
|
||||
for process_group in process_groups:
|
||||
modified_process_group_id = ProcessModelInfo.modify_process_identifier_for_path_param(process_group.id)
|
||||
uri = f"{permission_base_uri}/{modified_process_group_id}"
|
||||
has_permission = AuthorizationService.user_has_permission(
|
||||
user=user, permission=permission_to_check, target_uri=uri
|
||||
)
|
||||
if has_permission:
|
||||
new_process_group_list.append(process_group)
|
||||
return new_process_group_list
|
||||
|
||||
@classmethod
|
||||
def get_process_group(cls, process_group_id: str, find_direct_nested_items: bool = True) -> ProcessGroup:
|
||||
"""Look for a given process_group, and return it."""
|
||||
|
|
|
@ -702,7 +702,6 @@ class TestProcessApi(BaseTest):
|
|||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
"""Test_process_group_list."""
|
||||
# add 5 groups
|
||||
for i in range(5):
|
||||
group_id = f"test_process_group_{i}"
|
||||
|
@ -997,14 +996,13 @@ class TestProcessApi(BaseTest):
|
|||
assert response.json is not None
|
||||
assert "test_group/random_fact" == response.json["process_model_identifier"]
|
||||
|
||||
def test_get_process_groups_when_none(
|
||||
def test_process_group_list_when_none(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
"""Test_get_process_groups_when_none."""
|
||||
response = client.get(
|
||||
"/v1.0/process-groups",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
|
@ -1013,14 +1011,13 @@ class TestProcessApi(BaseTest):
|
|||
assert response.json is not None
|
||||
assert response.json["results"] == []
|
||||
|
||||
def test_get_process_groups_when_there_are_some(
|
||||
def test_process_group_list_when_there_are_some(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
"""Test_get_process_groups_when_there_are_some."""
|
||||
self.create_group_and_model_with_bpmn(client, with_super_admin_user)
|
||||
response = client.get(
|
||||
"/v1.0/process-groups",
|
||||
|
@ -1033,6 +1030,84 @@ class TestProcessApi(BaseTest):
|
|||
assert response.json["pagination"]["total"] == 1
|
||||
assert response.json["pagination"]["pages"] == 1
|
||||
|
||||
def test_process_group_list_when_user_has_resticted_access(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
self.create_group_and_model_with_bpmn(
|
||||
client, with_super_admin_user, process_group_id="admin_only", process_model_id="random_fact"
|
||||
)
|
||||
self.create_group_and_model_with_bpmn(
|
||||
client, with_super_admin_user, process_group_id="all_users", process_model_id="hello_world"
|
||||
)
|
||||
user_one = self.create_user_with_permission(username="user_one", target_uri="/v1.0/process-groups/all_users:*")
|
||||
self.add_permissions_to_user(user=user_one, target_uri="/v1.0/process-groups", permission_names=["read"])
|
||||
|
||||
response = client.get(
|
||||
"/v1.0/process-groups",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 2
|
||||
assert response.json["pagination"]["count"] == 2
|
||||
assert response.json["pagination"]["total"] == 2
|
||||
assert response.json["pagination"]["pages"] == 1
|
||||
|
||||
response = client.get(
|
||||
"/v1.0/process-groups",
|
||||
headers=self.logged_in_headers(user_one),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 1
|
||||
assert response.json["results"][0]["id"] == "all_users"
|
||||
assert response.json["pagination"]["count"] == 1
|
||||
assert response.json["pagination"]["total"] == 1
|
||||
assert response.json["pagination"]["pages"] == 1
|
||||
|
||||
def test_process_model_list_when_user_has_resticted_access(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
self.create_group_and_model_with_bpmn(
|
||||
client, with_super_admin_user, process_group_id="admin_only", process_model_id="random_fact"
|
||||
)
|
||||
self.create_group_and_model_with_bpmn(
|
||||
client, with_super_admin_user, process_group_id="all_users", process_model_id="hello_world"
|
||||
)
|
||||
user_one = self.create_user_with_permission(username="user_one", target_uri="/v1.0/process-models/all_users:*")
|
||||
self.add_permissions_to_user(user=user_one, target_uri="/v1.0/process-models", permission_names=["read"])
|
||||
|
||||
response = client.get(
|
||||
"/v1.0/process-models?recursive=true",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 2
|
||||
assert response.json["pagination"]["count"] == 2
|
||||
assert response.json["pagination"]["total"] == 2
|
||||
assert response.json["pagination"]["pages"] == 1
|
||||
|
||||
response = client.get(
|
||||
"/v1.0/process-models?recursive=true",
|
||||
headers=self.logged_in_headers(user_one),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
assert len(response.json["results"]) == 1
|
||||
assert response.json["results"][0]["id"] == "all_users/hello_world"
|
||||
assert response.json["pagination"]["count"] == 1
|
||||
assert response.json["pagination"]["total"] == 1
|
||||
assert response.json["pagination"]["pages"] == 1
|
||||
|
||||
def test_get_process_group_when_found(
|
||||
self,
|
||||
app: Flask,
|
||||
|
@ -1688,14 +1763,15 @@ class TestProcessApi(BaseTest):
|
|||
# The second script task should produce rendered jinja text
|
||||
# The Manual Task should then return a message as well.
|
||||
assert len(results) == 2
|
||||
assert json_results[0]["state"] == "READY"
|
||||
assert json_results[0]["title"] == "Script Task #2"
|
||||
assert json_results[0]["properties"]["instructionsForEndUser"] == "I am Script Task 2"
|
||||
assert json_results[1]["state"] == "READY"
|
||||
assert json_results[1]["title"] == "Manual Task"
|
||||
# import pdb; pdb.set_trace()
|
||||
assert json_results[0]["task"]["state"] == "READY"
|
||||
assert json_results[0]["task"]["title"] == "Script Task #2"
|
||||
assert json_results[0]["task"]["properties"]["instructionsForEndUser"] == "I am Script Task 2"
|
||||
assert json_results[1]["task"]["state"] == "READY"
|
||||
assert json_results[1]["task"]["title"] == "Manual Task"
|
||||
|
||||
response = client.put(
|
||||
f"/v1.0/tasks/{process_instance_id}/{json_results[1]['id']}",
|
||||
f"/v1.0/tasks/{process_instance_id}/{json_results[1]['task']['id']}",
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
|
@ -1705,14 +1781,14 @@ class TestProcessApi(BaseTest):
|
|||
results = list(_dequeued_interstitial_stream(process_instance_id))
|
||||
json_results = list(map(lambda x: json.loads(x[5:]), results)) # type: ignore
|
||||
assert len(results) == 1
|
||||
assert json_results[0]["state"] == "READY"
|
||||
assert json_results[0]["can_complete"] is False
|
||||
assert json_results[0]["title"] == "Please Approve"
|
||||
assert json_results[0]["properties"]["instructionsForEndUser"] == "I am a manual task in another lane"
|
||||
assert json_results[0]["task"]["state"] == "READY"
|
||||
assert json_results[0]["task"]["can_complete"] is False
|
||||
assert json_results[0]["task"]["title"] == "Please Approve"
|
||||
assert json_results[0]["task"]["properties"]["instructionsForEndUser"] == "I am a manual task in another lane"
|
||||
|
||||
# Complete task as the finance user.
|
||||
response = client.put(
|
||||
f"/v1.0/tasks/{process_instance_id}/{json_results[0]['id']}",
|
||||
f"/v1.0/tasks/{process_instance_id}/{json_results[0]['task']['id']}",
|
||||
headers=self.logged_in_headers(finance_user),
|
||||
)
|
||||
|
||||
|
@ -1722,8 +1798,8 @@ class TestProcessApi(BaseTest):
|
|||
results = list(_dequeued_interstitial_stream(process_instance_id))
|
||||
json_results = list(map(lambda x: json.loads(x[5:]), results)) # type: ignore
|
||||
assert len(json_results) == 1
|
||||
assert json_results[0]["state"] == "COMPLETED"
|
||||
assert json_results[0]["properties"]["instructionsForEndUser"] == "I am the end task"
|
||||
assert json_results[0]["task"]["state"] == "COMPLETED"
|
||||
assert json_results[0]["task"]["properties"]["instructionsForEndUser"] == "I am the end task"
|
||||
|
||||
def test_process_instance_list_with_default_list(
|
||||
self,
|
||||
|
|
|
@ -287,9 +287,9 @@ class TestAuthorizationService(BaseTest):
|
|||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
) -> None:
|
||||
"""Test_explode_permissions_basic."""
|
||||
expected_permissions = [
|
||||
("/active-users/*", "read"),
|
||||
("/process-groups", "read"),
|
||||
("/process-instances/find-by-id/*", "read"),
|
||||
("/process-instances/for-me", "create"),
|
||||
("/process-instances/report-metadata", "read"),
|
||||
|
@ -297,6 +297,7 @@ class TestAuthorizationService(BaseTest):
|
|||
("/process-instances/reports/*", "delete"),
|
||||
("/process-instances/reports/*", "read"),
|
||||
("/process-instances/reports/*", "update"),
|
||||
("/process-models", "read"),
|
||||
("/processes", "read"),
|
||||
("/processes/callers", "read"),
|
||||
("/service-tasks", "read"),
|
||||
|
|
|
@ -13,6 +13,7 @@ const submitWithUser = (
|
|||
cy.wait(1000);
|
||||
cy.log('=======visit find by id : ');
|
||||
cy.visit('/admin/process-instances/find-by-id');
|
||||
cy.wait(3000);
|
||||
cy.get('#process-instance-id-input').type(processInstanceId);
|
||||
|
||||
cy.get('button')
|
||||
|
@ -53,8 +54,8 @@ const submitWithUser = (
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').clear().type('Providing additional info. It\’s free and easy to post a job. Simply fill in a title, description and budget and competitive bids come within minutes. No job is too big or too small. We\'ve got people for jobs of any size.');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -85,7 +86,7 @@ const submitWithUser = (
|
|||
};
|
||||
|
||||
//Consulting Fees Path - Without Files
|
||||
describe('Consulting Fees Path - Without Files', () => {
|
||||
describe.only('Consulting Fees Path - Without Files', () => {
|
||||
Cypress._.times(1, () => {
|
||||
//Budget owner approves the request
|
||||
it('Budget owner approves', () => {
|
||||
|
@ -120,8 +121,8 @@ describe('Consulting Fees Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
||||
|
@ -182,9 +183,9 @@ describe('Consulting Fees Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('For professionals working in the professional services, \‘consultant\’ and advisor\’ are often used and fall under common terminology. Consultancy.uk zooms in on this field to get a closer look. \n https://www.consultancy.uk/career/what-is-consulting');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -249,8 +250,8 @@ describe('Consulting Fees Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
|
@ -311,9 +312,9 @@ describe('Consulting Fees Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('For professionals working in the professional services, ‘consultant’ and advisor’ are often used and fall under common terminology. Consultancy.uk zooms in on this field to get a closer look. \n https://www.consultancy.uk/career/what-is-consulting');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -378,8 +379,8 @@ describe('Consulting Fees Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
|
@ -441,9 +442,9 @@ describe('Consulting Fees Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('It\’s free and easy to post a job. Simply fill in a title, description and budget and competitive bids come within minutes. No job is too big or too small. We\'ve got freelancers for jobs of any size or budget across 1800 skills. No job is too complex.');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -532,8 +533,8 @@ describe('Consulting Fees Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
|
@ -636,9 +637,9 @@ describe('Consulting Fees Path - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -700,8 +701,8 @@ describe('Consulting Fees Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
|
@ -804,9 +805,9 @@ describe('Consulting Fees Path - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -871,8 +872,8 @@ describe('Consulting Fees Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
|
@ -974,9 +975,9 @@ describe('Consulting Fees Path - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
|
|
@ -13,6 +13,7 @@ const submitWithUser = (
|
|||
cy.wait(1000);
|
||||
cy.log('=======visit find by id : ');
|
||||
cy.visit('/admin/process-instances/find-by-id');
|
||||
cy.wait(3000);
|
||||
cy.get('#process-instance-id-input').type(processInstanceId);
|
||||
|
||||
cy.get('button')
|
||||
|
@ -57,8 +58,8 @@ const submitWithUser = (
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').clear().type('Providing additional info. Computer hardware includes the physical parts of a computer, such as the case, central processing unit (CPU), random access memory (RAM), monitor, mouse, keyboard, computer data storage, graphics card, sound card');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -88,7 +89,7 @@ const submitWithUser = (
|
|||
};
|
||||
|
||||
//Equipment Path - Without Files
|
||||
describe('Equipment Path - Without Files', () => {
|
||||
describe.only('Equipment Path - Without Files', () => {
|
||||
|
||||
Cypress._.times(1, () => {
|
||||
//Out of Policy. People Ops Partner Group and Budget owner approves the request
|
||||
|
@ -124,7 +125,7 @@ describe('Equipment Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -196,9 +197,9 @@ describe('Equipment Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('The template for all modern computers is the Von Neumann architecture, detailed in a 1945 paper by Hungarian mathematician John von Neumann. This describes a design architecture for a electronic digital computer with subdivisions of a processing unit');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -279,7 +280,7 @@ describe('Equipment Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -322,9 +323,9 @@ describe('Equipment Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('When using computer hardware, an upgrade means adding new or additional hardware to a computer that improves its performance, increases its capacity, or adds new features. For example, \nhttps://en.wikipedia.org/wiki/Computer_hardware');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -402,7 +403,7 @@ describe('Equipment Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -443,9 +444,9 @@ describe('Equipment Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('A supercomputer is superficially similar to a mainframe but is instead intended for extremely demanding computational tasks. As of November 2021, the fastest supercomputer on the TOP500 supercomputer list is Fugaku, in Japan');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -550,7 +551,7 @@ describe('Equipment Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -591,9 +592,9 @@ describe('Equipment Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('Computer hardware contain dangerous chemicals such as lead, mercury, nickel, and cadmium. According to the EPA these e-wastes have a harmful effect on the environment unless they are disposed properly. \nhttps://en.wikipedia.org/wiki/Computer_hardware');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -658,7 +659,7 @@ describe('Equipment Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -699,9 +700,9 @@ describe('Equipment Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('For professionals working in the professional services, \‘consultant\’ and advisor\’ are often used and fall under common terminology. Consultancy.uk zooms in on this field to get a closer look. \n https://www.consultancy.uk/career/what-is-consulting');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -766,7 +767,7 @@ describe('Equipment Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -807,9 +808,9 @@ describe('Equipment Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('The template for all modern computers is the Von Neumann architecture, detailed in a 1945 paper by Hungarian mathematician John von Neumann. \nhttps://en.wikipedia.org/wiki/Computer_hardware');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -892,7 +893,7 @@ describe('Equipment Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -933,9 +934,9 @@ describe('Equipment Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('The template for all modern computers is the Von Neumann architecture, detailed in a 1945 paper by Hungarian mathematician John von Neumann. \nhttps://en.wikipedia.org/wiki/Computer_hardware');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -1014,7 +1015,7 @@ describe('Equipment Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -1055,9 +1056,9 @@ describe('Equipment Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('The personal computer is one of the most common types of computer due to its versatility and relatively low price. Desktop personal computers have a monitor, a keyboard, a mouse, and a computer case.\nhttps://en.wikipedia.org/wiki/Computer_hardware');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -1135,7 +1136,7 @@ describe('Equipment Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -1176,9 +1177,9 @@ describe('Equipment Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('The personal computer is one of the most common types of computer due to its versatility and relatively low price. Desktop personal computers have a monitor, a keyboard, a mouse, and a computer case.\nhttps://en.wikipedia.org/wiki/Computer_hardware');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -1281,7 +1282,7 @@ describe('Equipment Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -1394,9 +1395,9 @@ describe('Equipment Path - With Files', () => {
|
|||
.attachFile(['sampletext.txt']);
|
||||
|
||||
cy.wait(2000);
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -1475,7 +1476,7 @@ describe('Equipment Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -1557,9 +1558,9 @@ describe('Equipment Path - With Files', () => {
|
|||
.attachFile(['sampletext.txt']);
|
||||
|
||||
cy.wait(2000);
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -1638,7 +1639,7 @@ describe('Equipment Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -1719,9 +1720,9 @@ describe('Equipment Path - With Files', () => {
|
|||
.attachFile(['sampletext.txt']);
|
||||
|
||||
cy.wait(2000);
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -1827,7 +1828,7 @@ describe('Equipment Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -1909,9 +1910,9 @@ describe('Equipment Path - With Files', () => {
|
|||
.attachFile(['sampletext.txt']);
|
||||
|
||||
cy.wait(2000);
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -1977,7 +1978,7 @@ describe('Equipment Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -2059,9 +2060,9 @@ describe('Equipment Path - With Files', () => {
|
|||
.attachFile(['sampletext.txt']);
|
||||
|
||||
cy.wait(2000);
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -2127,7 +2128,7 @@ describe('Equipment Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -2208,9 +2209,9 @@ describe('Equipment Path - With Files', () => {
|
|||
.attachFile(['sampletext.txt']);
|
||||
|
||||
cy.wait(2000);
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -2294,7 +2295,7 @@ describe('Equipment Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -2375,9 +2376,9 @@ describe('Equipment Path - With Files', () => {
|
|||
.attachFile(['sampletext.txt']);
|
||||
|
||||
cy.wait(2000);
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -2457,7 +2458,7 @@ describe('Equipment Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -2538,9 +2539,9 @@ describe('Equipment Path - With Files', () => {
|
|||
.attachFile(['sampletext.txt']);
|
||||
|
||||
cy.wait(2000);
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -2619,7 +2620,7 @@ describe('Equipment Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -2701,9 +2702,9 @@ describe('Equipment Path - With Files', () => {
|
|||
.attachFile(['png-5mb-2.png']);
|
||||
|
||||
cy.wait(2000);
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
//Software and License - Without Files
|
||||
describe('Initiate a Request - Without Files', () => {
|
||||
describe.only('Initiate a Request - Without Files', () => {
|
||||
Cypress._.times(1, () => {
|
||||
//Submit a Software and License request - Without Files
|
||||
it('Submit a Software and License request', () => {
|
||||
|
@ -87,9 +87,9 @@ describe('Initiate a Request - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('2021 Newest HP 17.3 inch FHD Laptop, AMD Ryzen 5 5500U 6core(Beat i7-1160G7, up to 4.0GHz),16GB RAM, 1TB PCIe SSD, Bluetooth 4.2, WiFi, HDMI, USB-A&C, Windows 10 S, w/Ghost Manta Accessories, Silver\nhttps://www.amazon.com/HP-i7-11G7-Bluetooth-Windows');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -179,9 +179,9 @@ describe('Initiate a Request - Without Files', () => {
|
|||
|
||||
//cy.get('.cds--text-area__wrapper').find('#root').type('For professionals working in the professional services, ‘consultant’ and advisor’ are often used and fall under common terminology. Consultancy.uk zooms in on this field to get a closer look. \n https://www.consultancy.uk/career/what-is-consulting');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -282,15 +282,15 @@ describe('Initiate a Request - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('2021 Newest HP 17.3 inch FHD Laptop, AMD Ryzen 5 5500U 6core(Beat i7-1160G7, up to 4.0GHz),16GB RAM, 1TB PCIe SSD, Bluetooth 4.2, WiFi, HDMI, USB-A&C, Windows 10 S, w/Ghost Manta Accessories, Silver\nhttps://www.amazon.com/HP-i7-11G7-Bluetooth-Windows');
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('2021 Newest HP 17.3 inch FHD Laptop, AMD Ryzen 5 5500U 6core(Beat i7-1160G7, up to 4.0GHz),16GB RAM, 1TB PCIe SSD, Bluetooth 4.2, WiFi, HDMI, USB-A&C, Windows 10 S,\nhttps://www.amazon.com/HP-i7-11G7-Bluetooth-Windows');
|
||||
|
||||
cy.contains('Edit the Request').click();
|
||||
//cy.contains('Edit the Request').click();
|
||||
|
||||
cy.get('input[value="Edit the Request"]').click();
|
||||
//cy.get('input[value="Edit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.contains(/^Edit Request$/)
|
||||
.click();
|
||||
|
||||
|
||||
|
@ -312,10 +312,10 @@ describe('Initiate a Request - Without Files', () => {
|
|||
'Task: Review the Request',
|
||||
{ timeout: 60000 });
|
||||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('EDITING INFO : 2021 Newest HP 17.3 inch FHD Laptop, AMD Ryzen 5 5500U 6core(Beat i7-1160G7, up to 4.0GHz),16GB RAM, 1TB PCIe SSD, Bluetooth 4.2, WiFi, HDMI, USB-A&C, Silver\nhttps://www.amazon.com/HP-i7-11G7-Bluetooth-Windows');
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('EDITING INFO');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
|
@ -331,8 +331,8 @@ describe('Initiate a Request - Without Files', () => {
|
|||
});
|
||||
});
|
||||
|
||||
//Save as Draft a Software and License request - Without Files
|
||||
it.only('Save as Draft a Software and License request', () => {
|
||||
//Close a Software and License request 1 - Without Files
|
||||
it('Close a Software and License request 1', () => {
|
||||
let username = Cypress.env('requestor_username');
|
||||
let password = Cypress.env('requestor_password');
|
||||
cy.log('=====username : ' + username);
|
||||
|
@ -405,13 +405,202 @@ describe('Initiate a Request - Without Files', () => {
|
|||
cy.get('#root_item_1_unit_price').type('4500');
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Save as draft$/)
|
||||
.contains(/^Close$/)
|
||||
.click();
|
||||
|
||||
//cy.get('button')
|
||||
// .contains(/^Return to Home$/)
|
||||
// .click();
|
||||
|
||||
cy.contains('Started by me', { timeout: 60000 });
|
||||
cy.logout();
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
//Close a Software and License request 2 - Without Files
|
||||
it('Close a Software and License request 2', () => {
|
||||
let username = Cypress.env('requestor_username');
|
||||
let password = Cypress.env('requestor_password');
|
||||
cy.log('=====username : ' + username);
|
||||
cy.log('=====password : ' + password);
|
||||
|
||||
cy.login(username, password);
|
||||
cy.visit('/');
|
||||
|
||||
cy.contains('Start New +').click();
|
||||
cy.contains('Request Goods or Services');
|
||||
|
||||
cy.runPrimaryBpmnFile(true);
|
||||
|
||||
/* cy.contains('Please select the type of request to start the process.');
|
||||
// wait a second to ensure we can click the radio button
|
||||
|
||||
cy.wait(2000);
|
||||
cy.get('input#root-procurement').click();
|
||||
cy.wait(2000);
|
||||
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.click();
|
||||
*/
|
||||
|
||||
cy.contains(
|
||||
'Request Goods or Services',
|
||||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
cy.log('==###############===processInstanceId : ', processInstanceId);
|
||||
let projectId = Cypress.env('project_id');
|
||||
cy.wait(2000);
|
||||
cy.get('#root_project').select(projectId);
|
||||
cy.get('#root_category').select('soft_and_lic');
|
||||
cy.get('#root_purpose').clear().type('Sware\nA software license is a document that provides legally binding guidelines for the use and distribution of software.\nSoftware licenses typically provide end users with the right to one or more copies of the software without violating copyrights');
|
||||
cy.get('#root_criticality').select('High');
|
||||
cy.get('#root_period').clear().type('25-11-2025');
|
||||
cy.get('body').click();
|
||||
cy.get('#root_vendor').clear().type('Microsoft');
|
||||
cy.get('#root_payment_method').select('Reimbursement');
|
||||
/* cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.click();
|
||||
|
||||
cy.contains('Task: Enter NDR Items', { timeout: 60000 });
|
||||
*/
|
||||
//item 0
|
||||
cy.get('#root_item_0_sub_category').select('op_src');
|
||||
cy.get('#root_item_0_item_name').clear().type('Open source software is code that is designed to be publicly accessible anyone can see, modify, END');
|
||||
cy.get('#root_item_0_qty').clear().type('2');
|
||||
cy.get('#root_item_0_currency_type').select('Crypto');
|
||||
cy.get('#root_item_0_currency').select('SNT');
|
||||
cy.get('#root_item_0_unit_price').type('1915');
|
||||
|
||||
|
||||
cy.get('#root_item > div:nth-child(3) > p > button').click();
|
||||
|
||||
//item 1
|
||||
cy.get('#root_item_1_sub_category').select('lic_and_sub');
|
||||
cy.get('#root_item_1_item_name').clear().type('A software license is a document that provides legally binding guidelines for the use and distri END');
|
||||
//cy.get('#root_item_1_qty').clear().type('1');
|
||||
//cy.get('#root_item_1_currency_type').select('Fiat');
|
||||
//cy.get('#root_item_1_currency').select('AED');
|
||||
//cy.get('#root_item_1_unit_price').type('4500');
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Return to Home$/)
|
||||
.contains(/^Close$/)
|
||||
.click();
|
||||
|
||||
//cy.get('button')
|
||||
// .contains(/^Return to Home$/)
|
||||
// .click();
|
||||
|
||||
cy.contains('Started by me', { timeout: 60000 });
|
||||
cy.logout();
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//Close a Software and License request 3 - Without Files
|
||||
it('Close a Software and License request 3', () => {
|
||||
let username = Cypress.env('requestor_username');
|
||||
let password = Cypress.env('requestor_password');
|
||||
cy.log('=====username : ' + username);
|
||||
cy.log('=====password : ' + password);
|
||||
|
||||
cy.login(username, password);
|
||||
cy.visit('/');
|
||||
|
||||
cy.contains('Start New +').click();
|
||||
cy.contains('Request Goods or Services');
|
||||
|
||||
cy.runPrimaryBpmnFile(true);
|
||||
|
||||
/* cy.contains('Please select the type of request to start the process.');
|
||||
// wait a second to ensure we can click the radio button
|
||||
|
||||
cy.wait(2000);
|
||||
cy.get('input#root-procurement').click();
|
||||
cy.wait(2000);
|
||||
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.click();
|
||||
*/
|
||||
|
||||
cy.contains(
|
||||
'Request Goods or Services',
|
||||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
cy.log('==###############===processInstanceId : ', processInstanceId);
|
||||
let projectId = Cypress.env('project_id');
|
||||
cy.wait(2000);
|
||||
cy.get('#root_project').select(projectId);
|
||||
cy.get('#root_category').select('soft_and_lic');
|
||||
cy.get('#root_purpose').clear().type('Sware\nA software license is a document that provides legally binding guidelines for the use and distribution of software.\nSoftware licenses typically provide end users with the right to one or more copies of the software without violating copyrights');
|
||||
cy.get('#root_criticality').select('High');
|
||||
cy.get('#root_period').clear().type('25-11-2025');
|
||||
cy.get('body').click();
|
||||
cy.get('#root_vendor').clear().type('Microsoft');
|
||||
cy.get('#root_payment_method').select('Reimbursement');
|
||||
/* cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.click();
|
||||
|
||||
cy.contains('Task: Enter NDR Items', { timeout: 60000 });
|
||||
*/
|
||||
//item 0
|
||||
cy.get('#root_item_0_sub_category').select('op_src');
|
||||
cy.get('#root_item_0_item_name').clear().type('Open source software is code that is designed to be publicly accessible anyone can see, modify, END');
|
||||
cy.get('#root_item_0_qty').clear().type('2');
|
||||
cy.get('#root_item_0_currency_type').select('Crypto');
|
||||
cy.get('#root_item_0_currency').select('SNT');
|
||||
cy.get('#root_item_0_unit_price').type('1915');
|
||||
|
||||
|
||||
cy.get('#root_item > div:nth-child(3) > p > button').click();
|
||||
|
||||
//item 1
|
||||
cy.get('#root_item_1_sub_category').select('lic_and_sub');
|
||||
cy.get('#root_item_1_item_name').clear().type('A software license is a document that provides legally binding guidelines for the use and distri END');
|
||||
cy.get('#root_item_1_qty').clear().type('1');
|
||||
cy.get('#root_item_1_currency_type').select('Fiat');
|
||||
cy.get('#root_item_1_currency').select('AED');
|
||||
cy.get('#root_item_1_unit_price').type('4500');
|
||||
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.click();
|
||||
|
||||
cy.contains(
|
||||
'Review and provide any supporting information or files for your request.',
|
||||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('2021 Newest HP 17.3 inch FHD Laptop, AMD Ryzen 5 5500U 6core(Beat i7-1160G7, up to 4.0GHz),16GB RAM, 1TB PCIe SSD, Bluetooth 4.2, WiFi, HDMI, USB-A&C, Windows 10 S, w/Ghost Manta Accessories, Silver\nhttps://www.amazon.com/HP-i7-11G7-Bluetooth-Windows');
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Close$/)
|
||||
.click();
|
||||
|
||||
// cy.get('button')
|
||||
// .contains(/^Return to Home$/)
|
||||
// .click();
|
||||
|
||||
cy.contains('Started by me', { timeout: 60000 });
|
||||
cy.logout();
|
||||
|
||||
|
@ -492,10 +681,10 @@ describe('Initiate a Request - Without Files', () => {
|
|||
cy.get('#root_item_1_currency').select('AED');
|
||||
cy.get('#root_item_1_unit_price').type('4500');
|
||||
|
||||
cy.get('#root-Yes').click();
|
||||
//cy.get('#root-Yes').click();
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.contains(/^Cancel Request$/)
|
||||
.click();
|
||||
|
||||
cy.get('button')
|
||||
|
@ -594,16 +783,12 @@ describe('Initiate a Request - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('2021 Newest HP 17.3 inch FHD Laptop, AMD Ryzen 5 5500U 6core(Beat i7-1160G7, up to 4.0GHz),16GB RAM, 1TB PCIe SSD, Bluetooth 4.2, WiFi, HDMI, USB-A&C, Windows 10 S, w/Ghost Manta Accessories, Silver\nhttps://www.amazon.com/HP-i7-11G7-Bluetooth-Windows');
|
||||
|
||||
cy.contains('Cancel the Request').click();
|
||||
//cy.contains('Cancel the Request').click();
|
||||
|
||||
cy.get('input[value="Cancel the Request"]').click();
|
||||
//cy.get('input[value="Cancel the Request"]').click();
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.click();
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Return to Home$/)
|
||||
.contains(/^Cancel Request$/)
|
||||
.click();
|
||||
|
||||
cy.contains('Started by me', { timeout: 60000 });
|
||||
|
@ -619,7 +804,7 @@ describe('Initiate a Request - Without Files', () => {
|
|||
describe('Initiate a Request - With Files', () => {
|
||||
Cypress._.times(1, () => {
|
||||
//Submit a Software and License request - Without Files
|
||||
it('Submit a Software and License request', () => {
|
||||
it('Submit a Software and License request - With Files', () => {
|
||||
let username = Cypress.env('requestor_username');
|
||||
let password = Cypress.env('requestor_password');
|
||||
cy.log('=====username : ' + username);
|
||||
|
@ -744,9 +929,9 @@ describe('Initiate a Request - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -903,9 +1088,9 @@ describe('Initiate a Request - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -924,7 +1109,7 @@ describe('Initiate a Request - With Files', () => {
|
|||
});
|
||||
|
||||
//Edit a Software and License request - With Files
|
||||
it('Edit a Software and License request', () => {
|
||||
it('Edit a Software and License request - With Files', () => {
|
||||
let username = Cypress.env('requestor_username');
|
||||
let password = Cypress.env('requestor_password');
|
||||
cy.log('=====username : ' + username);
|
||||
|
@ -1051,13 +1236,13 @@ describe('Initiate a Request - With Files', () => {
|
|||
cy.wait(2000);
|
||||
|
||||
|
||||
cy.contains('Edit the Request').click();
|
||||
//cy.contains('Edit the Request').click();
|
||||
|
||||
cy.get('input[value="Edit the Request"]').click();
|
||||
//cy.get('input[value="Edit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.contains(/^Edit Request$/)
|
||||
.click();
|
||||
|
||||
|
||||
|
@ -1079,8 +1264,8 @@ describe('Initiate a Request - With Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('EDITING INFO : 2021 Newest HP 17.3 inch FHD Laptop, AMD Ryzen 5 5500U 6core(Beat i7-1160G7, up to 4.0GHz),16GB RAM, 1TB PCIe SSD, Bluetooth 4.2, WiFi, HDMI, USB-A&C, Silver\nhttps://www.amazon.com/HP-i7-11G7-Bluetooth-Windows');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
|
@ -1096,8 +1281,139 @@ describe('Initiate a Request - With Files', () => {
|
|||
});
|
||||
});
|
||||
|
||||
//Close a Software and License request 1 - With Files
|
||||
it('Close a Software and License request 1 - With Files', () => {
|
||||
let username = Cypress.env('requestor_username');
|
||||
let password = Cypress.env('requestor_password');
|
||||
cy.log('=====username : ' + username);
|
||||
cy.log('=====password : ' + password);
|
||||
|
||||
cy.login(username, password);
|
||||
cy.visit('/');
|
||||
|
||||
cy.contains('Start New +').click();
|
||||
cy.contains('Request Goods or Services');
|
||||
|
||||
cy.runPrimaryBpmnFile(true);
|
||||
|
||||
/* cy.contains('Please select the type of request to start the process.');
|
||||
// wait a second to ensure we can click the radio button
|
||||
|
||||
cy.wait(2000);
|
||||
cy.get('input#root-procurement').click();
|
||||
cy.wait(2000);
|
||||
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.click();
|
||||
*/
|
||||
|
||||
cy.contains(
|
||||
'Request Goods or Services',
|
||||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
cy.log('==###############===processInstanceId : ', processInstanceId);
|
||||
let projectId = Cypress.env('project_id');
|
||||
cy.wait(2000);
|
||||
cy.get('#root_project').select(projectId);
|
||||
cy.get('#root_category').select('soft_and_lic');
|
||||
cy.get('#root_purpose').clear().type('Sware\nA software license is a document that provides legally binding guidelines for the use and distribution of software.\nSoftware licenses typically provide end users with the right to one or more copies of the software without violating copyrights');
|
||||
cy.get('#root_criticality').select('High');
|
||||
cy.get('#root_period').clear().type('25-11-2025');
|
||||
cy.get('body').click();
|
||||
cy.get('#root_vendor').clear().type('Microsoft');
|
||||
cy.get('#root_payment_method').select('Reimbursement');
|
||||
/* cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.click();
|
||||
|
||||
cy.contains('Task: Enter NDR Items', { timeout: 60000 });
|
||||
*/
|
||||
//item 0
|
||||
cy.get('#root_item_0_sub_category').select('op_src');
|
||||
cy.get('#root_item_0_item_name').clear().type('Open source software is code that is designed to be publicly accessible anyone can see, modify, END');
|
||||
cy.get('#root_item_0_qty').clear().type('2');
|
||||
cy.get('#root_item_0_currency_type').select('Crypto');
|
||||
cy.get('#root_item_0_currency').select('SNT');
|
||||
cy.get('#root_item_0_unit_price').type('1915');
|
||||
|
||||
|
||||
cy.get('#root_item > div:nth-child(3) > p > button').click();
|
||||
|
||||
//item 1
|
||||
cy.get('#root_item_1_sub_category').select('lic_and_sub');
|
||||
cy.get('#root_item_1_item_name').clear().type('A software license is a document that provides legally binding guidelines for the use and distri END');
|
||||
cy.get('#root_item_1_qty').clear().type('1');
|
||||
cy.get('#root_item_1_currency_type').select('Fiat');
|
||||
cy.get('#root_item_1_currency').select('AED');
|
||||
cy.get('#root_item_1_unit_price').type('4500');
|
||||
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.click();
|
||||
|
||||
cy.contains(
|
||||
'Review and provide any supporting information or files for your request.',
|
||||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('2021 Newest HP 17.3 inch FHD Laptop, AMD Ryzen 5 5500U 6core(Beat i7-1160G7, up to 4.0GHz),16GB RAM, 1TB PCIe SSD, Bluetooth 4.2, WiFi, HDMI, USB-A&C, Windows 10 S, w/Ghost Manta Accessories, Silver\nhttps://www.amazon.com/HP-i7-11G7-Bluetooth-Windows');
|
||||
|
||||
cy.get('#root > div:nth-child(3) > p > button').click();
|
||||
|
||||
cy.get("input[type=file]")
|
||||
.attachFile(['lorem-ipsum.pdf']);
|
||||
cy.wait(1000);
|
||||
|
||||
cy.get('#root > div:nth-child(3) > p > button').click();
|
||||
cy.wait(1000);
|
||||
|
||||
cy.get('#root > div.row.array-item-list > div:nth-child(2) > div > div.cds--sm\\:col-span-1.cds--md\\:col-span-1.cds--lg\\:col-span-1.cds--css-grid-column > div > div > button.btn.btn-default.array-item-move-up > svg').click();
|
||||
cy.wait(1000);
|
||||
cy.get("input[type=file]")
|
||||
.attachFile(['png-5mb-1.png']);
|
||||
cy.wait(1000);
|
||||
|
||||
cy.get('#root > div:nth-child(3) > p > button').click();
|
||||
cy.wait(1000);
|
||||
|
||||
cy.get('#root > div.row.array-item-list > div:nth-child(3) > div > div.cds--sm\\:col-span-1.cds--md\\:col-span-1.cds--lg\\:col-span-1.cds--css-grid-column > div > div > button.btn.btn-default.array-item-move-up > svg').click();
|
||||
cy.wait(1000);
|
||||
cy.get('#root > div.row.array-item-list > div:nth-child(2) > div > div.cds--sm\\:col-span-1.cds--md\\:col-span-1.cds--lg\\:col-span-1.cds--css-grid-column > div > div > button.btn.btn-default.array-item-move-up > svg').click();
|
||||
cy.wait(1000);
|
||||
|
||||
cy.get("input[type=file]")
|
||||
.attachFile(['Free_Test_Data_1MB_PDF.pdf']);
|
||||
|
||||
cy.wait(2000);
|
||||
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Close$/)
|
||||
.click();
|
||||
|
||||
cy.wait(3000);
|
||||
|
||||
// cy.get('button')
|
||||
// .contains(/^Return to Home$/)
|
||||
// .click();
|
||||
|
||||
cy.contains('Started by me', { timeout: 60000 });
|
||||
cy.logout();
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
//Cancel a Software and License request - With Files
|
||||
it('Cancel a Software and License request', () => {
|
||||
it('Cancel a Software and License request - With Files ', () => {
|
||||
let username = Cypress.env('requestor_username');
|
||||
let password = Cypress.env('requestor_password');
|
||||
cy.log('=====username : ' + username);
|
||||
|
@ -1224,9 +1540,9 @@ describe('Initiate a Request - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Cancel the Request').click();
|
||||
//cy.contains('Cancel the Request').click();
|
||||
|
||||
cy.get('input[value="Cancel the Request"]').click();
|
||||
//cy.get('input[value="Cancel the Request"]').click();
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
|
|
|
@ -13,6 +13,7 @@ const submitWithUser = (
|
|||
cy.wait(1000);
|
||||
cy.log('=======visit find by id : ');
|
||||
cy.visit('/admin/process-instances/find-by-id');
|
||||
cy.wait(3000);
|
||||
cy.get('#process-instance-id-input').type(processInstanceId);
|
||||
|
||||
cy.get('button')
|
||||
|
@ -53,8 +54,8 @@ const submitWithUser = (
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').clear().type('Providing additional info. Learning and development (L&D) is a function within an organization that is responsible for empowering employees\’ growth and developing their knowledge, skills, and capabilities to drive better business performance.');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -84,7 +85,7 @@ const submitWithUser = (
|
|||
};
|
||||
|
||||
//Learning and Development Path - Without Files
|
||||
describe('Learning and Development Path - Without Files', () => {
|
||||
describe.only('Learning and Development Path - Without Files', () => {
|
||||
|
||||
Cypress._.times(1, () => {
|
||||
//People Ops Partner Group approves the request
|
||||
|
@ -120,7 +121,7 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -161,9 +162,9 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('A L&D strategy should be aligned to the organization\’s business strategy and goals with the aim of developing the workforce\’s capability and driving business results.');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -228,7 +229,7 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -251,7 +252,7 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
cy.contains('Task: Enter NDR Items', { timeout: 60000 });
|
||||
*/
|
||||
cy.get('#root_item_0_sub_category').select('books');
|
||||
cy.get('#root_item_0_item_name').clear().type('The role of the L&D function has evolved to meet the demands of digital transformation and a modern workforce.');
|
||||
cy.get('#root_item_0_item_name').clear().type('The role of the L&D function has evolved to meet the demands of digital transformation and a modern.');
|
||||
cy.get('#root_item_0_qty').clear().type('5');
|
||||
cy.get('#root_item_0_currency_type').select('Fiat');
|
||||
cy.get('#root_item_0_currency').select('EUR');
|
||||
|
@ -269,9 +270,9 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('The function may be organized centrally, either independently or sitting under human resources (HR); decentralized throughout different business units; or be a hybrid (sometimes referred to as federated) structure.');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -335,7 +336,7 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -376,9 +377,9 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('Current and aspiring talent development professionals can enhance their skills with the various professional education courses offered by ATD Education \nhttps://www.aihr.com/blog/learning-and-development/');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -461,7 +462,7 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -524,9 +525,9 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('Learning and development is a systematic process to enhance an employee\’s skills, knowledge, and competency, resulting in better performance in a work setting. \nhttps://www.aihr.com/blog/learning-and-development/');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -604,7 +605,7 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -645,9 +646,9 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('A L&D strategy should be aligned to the organization\’s business strategy and goals with the aim of developing the workforce\’s capability and driving business results.');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -711,7 +712,7 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -752,9 +753,9 @@ describe('Learning and Development Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('Learning and development is a systematic process to enhance an employee\’s skills, knowledge, and competency, resulting in better performance in a work setting. \nhttps://www.aihr.com/blog/learning-and-development/');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -845,7 +846,7 @@ describe('Learning and Development Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -928,9 +929,9 @@ describe('Learning and Development Path - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -995,7 +996,7 @@ describe('Learning and Development Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -1078,9 +1079,9 @@ describe('Learning and Development Path - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -1145,7 +1146,7 @@ describe('Learning and Development Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -1227,9 +1228,9 @@ describe('Learning and Development Path - With Files', () => {
|
|||
.attachFile(['sampletext.txt']);
|
||||
|
||||
cy.wait(2000);
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -1313,7 +1314,7 @@ describe('Learning and Development Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -1418,9 +1419,9 @@ describe('Learning and Development Path - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -1498,7 +1499,7 @@ describe('Learning and Development Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -1581,9 +1582,9 @@ describe('Learning and Development Path - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -1648,7 +1649,7 @@ describe('Learning and Development Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
|
@ -1731,9 +1732,9 @@ describe('Learning and Development Path - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
|
|
@ -13,6 +13,7 @@ const submitWithUser = (
|
|||
cy.wait(1000);
|
||||
cy.log('=======visit find by id : ');
|
||||
cy.visit('/admin/process-instances/find-by-id');
|
||||
cy.wait(3000);
|
||||
cy.get('#process-instance-id-input').type(processInstanceId);
|
||||
|
||||
cy.get('button')
|
||||
|
@ -53,8 +54,8 @@ const submitWithUser = (
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').clear().type('Providing additional info. Coworking tends to fall into two sides: Those that are real-estate-centric (all about selling desks and offices first) while others are community-centric (focused on building community that happens to also have offices)');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -84,7 +85,7 @@ const submitWithUser = (
|
|||
cy.wait(2000);
|
||||
};
|
||||
|
||||
describe('Other Fees Path - Without Files', () => {
|
||||
describe.only('Other Fees Path - Without Files', () => {
|
||||
|
||||
Cypress._.times(1, () => {
|
||||
//Budget owner approves the request
|
||||
|
@ -120,8 +121,8 @@ describe('Other Fees Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
|
@ -173,9 +174,9 @@ describe('Other Fees Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('For professionals working in the professional services, ‘consultant’ and advisor’ are often used and fall under common terminology. Consultancy.uk zooms in on this field to get a closer look. \n https://www.consultancy.uk/career/what-is-consulting');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -240,8 +241,8 @@ describe('Other Fees Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
|
@ -281,9 +282,9 @@ describe('Other Fees Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('For professionals working in the professional services, ‘consultant’ and advisor’ are often used and fall under common terminology. Consultancy.uk zooms in on this field to get a closer look. \n https://www.consultancy.uk/career/what-is-consulting');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -347,8 +348,8 @@ describe('Other Fees Path - Without Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
|
@ -388,9 +389,9 @@ describe('Other Fees Path - Without Files', () => {
|
|||
|
||||
cy.get('.cds--text-area__wrapper').find('#root').type('It\’s free and easy to post a job. Simply fill in a title, description and budget and competitive bids come within minutes. No job is too big or too small. We\'ve got freelancers for jobs of any size or budget across 1800 skills. No job is too complex.');
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -478,8 +479,8 @@ describe('Other Fees Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
|
@ -571,16 +572,16 @@ describe('Other Fees Path - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
.contains(/^Submit$/)
|
||||
.click();
|
||||
|
||||
cy.wait(9000);
|
||||
cy.wait(20000);
|
||||
cy.get('button')
|
||||
.contains(/^Return to Home$/)
|
||||
.click();
|
||||
|
@ -638,8 +639,8 @@ describe('Other Fees Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
|
@ -721,9 +722,9 @@ describe('Other Fees Path - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
@ -788,8 +789,8 @@ describe('Other Fees Path - With Files', () => {
|
|||
{ timeout: 60000 }
|
||||
);
|
||||
|
||||
cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
//cy.wait(5000);
|
||||
cy.url().then((currentUrl) => {
|
||||
// if url is "/tasks/8/d37c2f0f-016a-4066-b669-e0925b759560"
|
||||
// extract the digits after /tasks
|
||||
const processInstanceId = currentUrl.match(/(?<=\/tasks\/)\d+/)[0];
|
||||
|
@ -871,9 +872,9 @@ describe('Other Fees Path - With Files', () => {
|
|||
|
||||
cy.wait(2000);
|
||||
|
||||
cy.contains('Submit the Request').click();
|
||||
//cy.contains('Submit the Request').click();
|
||||
|
||||
cy.get('input[value="Submit the Request"]').click();
|
||||
//cy.get('input[value="Submit the Request"]').click();
|
||||
|
||||
|
||||
cy.get('button')
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -59,11 +59,13 @@ Cypress.Commands.add('login', (username, password) => {
|
|||
});
|
||||
|
||||
Cypress.Commands.add('logout', (selector, ...args) => {
|
||||
cy.getBySel('logout-button').click();
|
||||
|
||||
cy.wait(2000);
|
||||
//cy.getBySel('logout-button').click();
|
||||
cy.get('#root > div > header > div.cds--header__global > span:nth-child(3) > button > svg').click();
|
||||
if (Cypress.env('SPIFFWORKFLOW_FRONTEND_AUTH_WITH_KEYCLOAK') === true) {
|
||||
// otherwise we can click logout, quickly load the next page, and the javascript
|
||||
// doesn't have time to actually sign you out
|
||||
//cy.wait(4000);
|
||||
cy.contains('Sign in to your account');
|
||||
} else {
|
||||
cy.get('#spiff-login-button').should('exist');
|
||||
|
@ -104,7 +106,10 @@ Cypress.Commands.add(
|
|||
(expectAutoRedirectToHumanTask = false, returnToProcessModelShow = true) => {
|
||||
// cy.getBySel('start-process-instance').click();
|
||||
// click on button with text Start
|
||||
cy.get('button')
|
||||
//cy.get('button')
|
||||
//cy.get('#process-model-tile-manage-procurement\\/procurement\\/requisition-order-management\\/new-demand-request-procurement > div > button')
|
||||
cy.get('#process-model-tile-manage-procurement\\/procurement\\/requisition-order-management\\/request-goods-services > div > button')
|
||||
//cy.get('#process-model-tile-manage-procurement\\/procurement\\/requisition-order-management\\/raise-new-demand-request > div > button')
|
||||
.contains(/^Start$/)
|
||||
.click();
|
||||
if (expectAutoRedirectToHumanTask) {
|
||||
|
|
|
@ -42,7 +42,7 @@ export default function ActiveUsers() {
|
|||
return (
|
||||
<div
|
||||
title={`${activeUser.username} is also viewing this page`}
|
||||
className="user-circle"
|
||||
className="user-circle user-circle-for-list"
|
||||
>
|
||||
{activeUser.username.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
import {
|
||||
Toggletip,
|
||||
ToggletipButton,
|
||||
ToggletipContent,
|
||||
Button,
|
||||
Header,
|
||||
HeaderContainer,
|
||||
HeaderMenuButton,
|
||||
|
@ -77,25 +81,46 @@ export default function NavigationBar() {
|
|||
return activeKey === menuItemPath;
|
||||
};
|
||||
|
||||
const profileToggletip = (
|
||||
<div style={{ display: 'flex' }} id="user-profile-toggletip">
|
||||
<Toggletip isTabTip align="bottom-right">
|
||||
<ToggletipButton
|
||||
aria-label="User Actions"
|
||||
className="user-profile-toggletip-button"
|
||||
type="button"
|
||||
>
|
||||
<div className="user-circle">
|
||||
{UserService.getPreferredUsername()[0].toUpperCase()}
|
||||
</div>
|
||||
</ToggletipButton>
|
||||
<ToggletipContent className="user-profile-toggletip-content">
|
||||
<p>
|
||||
<strong>{UserService.getPreferredUsername()}</strong>
|
||||
</p>
|
||||
<p>{UserService.getUserEmail()}</p>
|
||||
<hr />
|
||||
<Button className="button-link" onClick={handleLogout}>
|
||||
<Logout />
|
||||
Sign out
|
||||
</Button>
|
||||
</ToggletipContent>
|
||||
</Toggletip>
|
||||
</div>
|
||||
);
|
||||
|
||||
const loginAndLogoutAction = () => {
|
||||
if (UserService.isLoggedIn()) {
|
||||
return (
|
||||
<>
|
||||
{SPIFF_ENVIRONMENT ? (
|
||||
<HeaderGlobalAction className="spiff-environment-header-text unclickable-text">
|
||||
<HeaderGlobalAction
|
||||
title={`The current SpiffWorkflow environment is: ${SPIFF_ENVIRONMENT}`}
|
||||
className="spiff-environment-header-text unclickable-text"
|
||||
>
|
||||
{SPIFF_ENVIRONMENT}
|
||||
</HeaderGlobalAction>
|
||||
) : null}
|
||||
<HeaderGlobalAction className="username-header-text unclickable-text">
|
||||
{UserService.getPreferredUsername()}
|
||||
</HeaderGlobalAction>
|
||||
<HeaderGlobalAction
|
||||
aria-label="Logout"
|
||||
onClick={handleLogout}
|
||||
data-qa="logout-button"
|
||||
>
|
||||
<Logout />
|
||||
</HeaderGlobalAction>
|
||||
{profileToggletip}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1578,32 +1578,38 @@ export default function ProcessInstanceListTable({
|
|||
headers.push('Action');
|
||||
}
|
||||
|
||||
const rows = processInstances.map((row: ProcessInstance) => {
|
||||
const rows = processInstances.map((processInstance: ProcessInstance) => {
|
||||
const currentRow = reportColumns().map((column: ReportColumn) => {
|
||||
return formattedColumn(row, column);
|
||||
return formattedColumn(processInstance, column);
|
||||
});
|
||||
if (showActionsColumn) {
|
||||
let buttonElement = null;
|
||||
const interstitialUrl = `/process/${modifyProcessIdentifierForPathParam(
|
||||
row.process_model_identifier
|
||||
)}/${row.id}/interstitial`;
|
||||
processInstance.process_model_identifier
|
||||
)}/${processInstance.id}/interstitial`;
|
||||
const regex = new RegExp(`\\b(${preferredUsername}|${userEmail})\\b`);
|
||||
let hasAccessToCompleteTask = false;
|
||||
if (
|
||||
canCompleteAllTasks ||
|
||||
(row.potential_owner_usernames || '').match(regex)
|
||||
(processInstance.potential_owner_usernames || '').match(regex)
|
||||
) {
|
||||
hasAccessToCompleteTask = true;
|
||||
}
|
||||
|
||||
let buttonText = 'View';
|
||||
let buttonKind = 'ghost';
|
||||
if (
|
||||
processInstance.status !== 'suspended' &&
|
||||
hasAccessToCompleteTask &&
|
||||
processInstance.task_id
|
||||
) {
|
||||
buttonText = 'Go';
|
||||
buttonKind = 'secondary';
|
||||
}
|
||||
|
||||
buttonElement = (
|
||||
<Button
|
||||
kind={
|
||||
hasAccessToCompleteTask && row.task_id ? 'secondary' : 'ghost'
|
||||
}
|
||||
href={interstitialUrl}
|
||||
>
|
||||
{hasAccessToCompleteTask && row.task_id ? 'Go' : 'View'}
|
||||
<Button kind={buttonKind} href={interstitialUrl}>
|
||||
{buttonText}
|
||||
</Button>
|
||||
);
|
||||
currentRow.push(<td>{buttonElement}</td>);
|
||||
|
@ -1611,18 +1617,18 @@ export default function ProcessInstanceListTable({
|
|||
|
||||
const rowStyle = { cursor: 'pointer' };
|
||||
const modifiedModelId = modifyProcessIdentifierForPathParam(
|
||||
row.process_model_identifier
|
||||
processInstance.process_model_identifier
|
||||
);
|
||||
const navigateToProcessInstance = () => {
|
||||
navigate(
|
||||
`${processInstanceShowPathPrefix}/${modifiedModelId}/${row.id}`
|
||||
`${processInstanceShowPathPrefix}/${modifiedModelId}/${processInstance.id}`
|
||||
);
|
||||
};
|
||||
return (
|
||||
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
|
||||
<tr
|
||||
style={rowStyle}
|
||||
key={row.id}
|
||||
key={processInstance.id}
|
||||
onClick={navigateToProcessInstance}
|
||||
onKeyDown={navigateToProcessInstance}
|
||||
>
|
||||
|
|
|
@ -114,6 +114,12 @@ h2 {
|
|||
padding-left: 0;
|
||||
}
|
||||
|
||||
.cds--header__global .cds--btn--primary.button-link {
|
||||
color: #f4f4f4;
|
||||
background-color: #393939;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.cds--header__global .cds--btn--primary {
|
||||
background-color: #161616
|
||||
}
|
||||
|
@ -129,8 +135,8 @@ code {
|
|||
}
|
||||
|
||||
.app-logo {
|
||||
height: 85%;
|
||||
width: 85%;
|
||||
height: 37px;
|
||||
width: 152px;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
@ -200,6 +206,44 @@ h1.with-icons {
|
|||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.user-profile-toggletip-content {
|
||||
background-color: #393939;
|
||||
color: #f4f4f4;
|
||||
margin-right: 8px;
|
||||
margin-top: -20px;
|
||||
}
|
||||
|
||||
#user-profile-toggletip {
|
||||
margin-top: 8px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
#user-profile-toggletip .cds--popover-content::before {
|
||||
content: none;
|
||||
}
|
||||
|
||||
#user-profile-toggletip .cds--popover--bottom-right .cds--popover-content {
|
||||
bottom: 11px;
|
||||
right: -2px;
|
||||
border-radius: 5px;
|
||||
border: 3px solid black;
|
||||
}
|
||||
|
||||
#user-profile-toggletip .cds--popover-caret {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.user-profile-toggletip-button:hover {
|
||||
background-color: #161616;
|
||||
}
|
||||
|
||||
#user-profile-toggletip .cds--popover--tab-tip__button::after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
#user-profile-toggletip .cds--popover--tab-tip.cds--popover--open .cds--popover--tab-tip__button{
|
||||
background-color: #161616;
|
||||
}
|
||||
|
||||
.with-top-margin {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
@ -471,49 +515,12 @@ svg.notification-icon {
|
|||
border-radius: 50%;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.user-circle-for-list {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.user-circle.color-1 {
|
||||
background-color: #8e8e8e;
|
||||
}
|
||||
|
||||
.user-circle.color-2 {
|
||||
background-color: #a57c63;
|
||||
}
|
||||
|
||||
.user-circle.color-3 {
|
||||
background-color: #8f7c7c;
|
||||
}
|
||||
|
||||
.user-circle.color-4 {
|
||||
background-color: #9a927f;
|
||||
}
|
||||
|
||||
.user-circle.color-5 {
|
||||
background-color: #5e5d5d;
|
||||
}
|
||||
|
||||
.user-circle.color-6 {
|
||||
background-color: #676767;
|
||||
}
|
||||
|
||||
.user-circle.color-7 {
|
||||
background-color: #6d7d6d;
|
||||
}
|
||||
|
||||
.user-circle.color-8 {
|
||||
background-color: #7a7171;
|
||||
}
|
||||
|
||||
.user-circle.color-9 {
|
||||
background-color: #837d63;
|
||||
}
|
||||
|
||||
.user-circle.color-10 {
|
||||
background-color: #686a70;
|
||||
}
|
||||
|
||||
/* Randomize color assignment */
|
||||
.user-circle:nth-child(1) {
|
||||
background-color: #8e8e8e;
|
||||
|
|
|
@ -351,3 +351,15 @@ export interface ProcessModelCaller {
|
|||
}
|
||||
|
||||
export interface UserGroup {}
|
||||
|
||||
type InterstitialPageResponseType =
|
||||
| 'task_update'
|
||||
| 'error'
|
||||
| 'unrunnable_instance';
|
||||
|
||||
export interface InterstitialPageResponse {
|
||||
type: InterstitialPageResponseType;
|
||||
error?: any;
|
||||
task?: ProcessInstanceTask;
|
||||
process_instance?: ProcessInstance;
|
||||
}
|
||||
|
|
|
@ -23,10 +23,11 @@ export default function Configuration() {
|
|||
[targetUris.authenticationListPath]: ['GET'],
|
||||
[targetUris.secretListPath]: ['GET'],
|
||||
};
|
||||
const { ability } = usePermissionFetcher(permissionRequestData);
|
||||
const { ability, permissionsLoaded } = usePermissionFetcher(
|
||||
permissionRequestData
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('Configuration remove error');
|
||||
removeError();
|
||||
let newSelectedTabIndex = 0;
|
||||
if (location.pathname.match(/^\/admin\/configuration\/authentications\b/)) {
|
||||
|
@ -35,6 +36,13 @@ export default function Configuration() {
|
|||
setSelectedTabIndex(newSelectedTabIndex);
|
||||
}, [location, removeError]);
|
||||
|
||||
// wow, if you do not check to see if the permissions are loaded, then in safari,
|
||||
// you will get {null} inside the <TabList> which totally explodes carbon (in safari!).
|
||||
// we *think* that null inside a TabList works fine in all other browsers.
|
||||
if (!permissionsLoaded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tabs selectedIndex={selectedTabIndex}>
|
||||
|
|
|
@ -9,12 +9,14 @@ import { getBasicHeaders } from '../services/HttpService';
|
|||
// @ts-ignore
|
||||
import InstructionsForEndUser from '../components/InstructionsForEndUser';
|
||||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import { ProcessInstanceTask } from '../interfaces';
|
||||
import { ProcessInstance, ProcessInstanceTask } from '../interfaces';
|
||||
import useAPIError from '../hooks/UseApiError';
|
||||
|
||||
export default function ProcessInterstitial() {
|
||||
const [data, setData] = useState<any[]>([]);
|
||||
const [lastTask, setLastTask] = useState<any>(null);
|
||||
const [processInstance, setProcessInstance] =
|
||||
useState<ProcessInstance | null>(null);
|
||||
const [state, setState] = useState<string>('RUNNING');
|
||||
const params = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
@ -32,11 +34,13 @@ export default function ProcessInterstitial() {
|
|||
headers: getBasicHeaders(),
|
||||
onmessage(ev) {
|
||||
const retValue = JSON.parse(ev.data);
|
||||
if ('error_code' in retValue) {
|
||||
addError(retValue);
|
||||
} else {
|
||||
setData((prevData) => [retValue, ...prevData]);
|
||||
setLastTask(retValue);
|
||||
if (retValue.type === 'error') {
|
||||
addError(retValue.error);
|
||||
} else if (retValue.type === 'task') {
|
||||
setData((prevData) => [retValue.task, ...prevData]);
|
||||
setLastTask(retValue.task);
|
||||
} else if (retValue.type === 'unrunnable_instance') {
|
||||
setProcessInstance(retValue.unrunnable_instance);
|
||||
}
|
||||
},
|
||||
onclose() {
|
||||
|
@ -49,9 +53,14 @@ export default function ProcessInterstitial() {
|
|||
|
||||
const shouldRedirect = useCallback(
|
||||
(myTask: ProcessInstanceTask): boolean => {
|
||||
return myTask && myTask.can_complete && userTasks.includes(myTask.type);
|
||||
return (
|
||||
!processInstance &&
|
||||
myTask &&
|
||||
myTask.can_complete &&
|
||||
userTasks.includes(myTask.type)
|
||||
);
|
||||
},
|
||||
[userTasks]
|
||||
[userTasks, processInstance]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -68,6 +77,9 @@ export default function ProcessInterstitial() {
|
|||
}, [lastTask, navigate, userTasks, shouldRedirect]);
|
||||
|
||||
const getStatus = (): string => {
|
||||
if (processInstance) {
|
||||
return 'LOCKED';
|
||||
}
|
||||
if (!lastTask.can_complete && userTasks.includes(lastTask.type)) {
|
||||
return 'LOCKED';
|
||||
}
|
||||
|
@ -135,30 +147,35 @@ export default function ProcessInterstitial() {
|
|||
}
|
||||
|
||||
const userMessage = (myTask: ProcessInstanceTask) => {
|
||||
if (!myTask.can_complete && userTasks.includes(myTask.type)) {
|
||||
return (
|
||||
<>
|
||||
<h4 className="heading-compact-01">Waiting on Someone Else</h4>
|
||||
<p>
|
||||
This next task is assigned to a different person or team. There is
|
||||
no action for you to take at this time.
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
if (!processInstance || processInstance.status === 'completed') {
|
||||
if (!myTask.can_complete && userTasks.includes(myTask.type)) {
|
||||
return (
|
||||
<>
|
||||
<h4 className="heading-compact-01">Waiting on Someone Else</h4>
|
||||
<p>
|
||||
This next task is assigned to a different person or team. There is
|
||||
no action for you to take at this time.
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
if (shouldRedirect(myTask)) {
|
||||
return <div>Redirecting you to the next task now ...</div>;
|
||||
}
|
||||
if (myTask.error_message) {
|
||||
return <div>{myTask.error_message}</div>;
|
||||
}
|
||||
}
|
||||
if (shouldRedirect(myTask)) {
|
||||
return <div>Redirecting you to the next task now ...</div>;
|
||||
}
|
||||
if (myTask.error_message) {
|
||||
return <div>{myTask.error_message}</div>;
|
||||
|
||||
let message =
|
||||
'There are no additional instructions or information for this task.';
|
||||
if (processInstance && processInstance.status !== 'completed') {
|
||||
message = `The tasks cannot be completed on this instance because its status is "${processInstance.status}".`;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<InstructionsForEndUser
|
||||
task={myTask}
|
||||
defaultMessage="There are no additional instructions or information for this task."
|
||||
/>
|
||||
<InstructionsForEndUser task={myTask} defaultMessage={message} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -176,6 +176,9 @@ export default function TaskShow() {
|
|||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
if (!formObject) {
|
||||
navigate(`/tasks`);
|
||||
}
|
||||
let queryParams = '';
|
||||
if (submitType === FormSubmitType.Draft) {
|
||||
queryParams = '?save_as_draft=true';
|
||||
|
@ -347,20 +350,21 @@ export default function TaskShow() {
|
|||
|
||||
if (task.state === 'READY') {
|
||||
let submitButtonText = 'Submit';
|
||||
let saveAsDraftButton = null;
|
||||
let closeButton = null;
|
||||
if (task.typename === 'ManualTask') {
|
||||
submitButtonText = 'Continue';
|
||||
} else if (task.typename === 'UserTask') {
|
||||
saveAsDraftButton = (
|
||||
closeButton = (
|
||||
<Button
|
||||
id="save-as-draft-button"
|
||||
id="close-button"
|
||||
disabled={disabled}
|
||||
kind="secondary"
|
||||
title="Save changes without submitting."
|
||||
onClick={() =>
|
||||
handleFormSubmit(currentFormObject, null, FormSubmitType.Draft)
|
||||
}
|
||||
>
|
||||
Save as draft
|
||||
Close
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
@ -369,7 +373,7 @@ export default function TaskShow() {
|
|||
<Button type="submit" id="submit-button" disabled={disabled}>
|
||||
{submitButtonText}
|
||||
</Button>
|
||||
{saveAsDraftButton}
|
||||
{closeButton}
|
||||
<>
|
||||
{task.signal_buttons.map((signal) => (
|
||||
<Button
|
||||
|
|
|
@ -19,7 +19,8 @@ function SelectWidget({
|
|||
placeholder,
|
||||
rawErrors = [],
|
||||
}: WidgetProps) {
|
||||
const { enumOptions, enumDisabled } = options;
|
||||
const { enumOptions } = options;
|
||||
let { enumDisabled } = options;
|
||||
|
||||
const emptyValue = multiple ? [] : '';
|
||||
|
||||
|
@ -56,6 +57,36 @@ function SelectWidget({
|
|||
errorMessageForField = rawErrors[0];
|
||||
}
|
||||
|
||||
// ok. so in safari, the select widget showed the first option, whereas in chrome it forced you to select an option.
|
||||
// this change causes causes safari to act a little bit more like chrome, but it's different because we are actually adding
|
||||
// an element to the dropdown.
|
||||
//
|
||||
// https://stackoverflow.com/a/7944490/6090676 safari detection
|
||||
let isSafari = false;
|
||||
const ua = navigator.userAgent.toLowerCase();
|
||||
if (ua.indexOf('safari') != -1) {
|
||||
if (ua.indexOf('chrome') === -1) {
|
||||
isSafari = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isSafari) {
|
||||
if (enumOptions && enumOptions[0].value !== '') {
|
||||
enumOptions.unshift({
|
||||
value: '',
|
||||
label: '',
|
||||
});
|
||||
}
|
||||
// enumDisabled is a list of values for which the option should be disabled.
|
||||
// we don't really want users to select the fake empty option we are creating here.
|
||||
// they cannot select it in chrome, after all.
|
||||
// google is always right. https://news.ycombinator.com/item?id=35862041
|
||||
if (enumDisabled === undefined) {
|
||||
enumDisabled = [];
|
||||
}
|
||||
enumDisabled.push('');
|
||||
}
|
||||
|
||||
// maybe use placeholder somehow. it was previously jammed into the helperText field,
|
||||
// but allowing ui:help to grab that spot seems much more appropriate.
|
||||
|
||||
|
|
Loading…
Reference in New Issue