Denys Vuika 6f0bbe427e
[ACS-7421] process: break app list dependency on material bundle (#9640)
* chore: break apps list dependency on material module bundle
2024-05-06 10:34:31 -04:00

956 lines
43 KiB
TypeScript

/*!
* @license
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { SimpleChange } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppConfigService } from '@alfresco/adf-core';
import { AppsProcessService } from '../../app-list/services/apps-process.service';
import { of, throwError } from 'rxjs';
import { MatSelectChange } from '@angular/material/select';
import { ProcessInstanceVariable } from '../models/process-instance-variable.model';
import { ProcessService } from '../services/process.service';
import { newProcess, taskFormMock, testProcessDef, testMultipleProcessDefs, testProcessDefWithForm, testProcessDefinitions } from '../../mock';
import { StartProcessInstanceComponent } from './start-process.component';
import { ProcessTestingModule } from '../../testing/process.testing.module';
import { deployedApps } from '../../mock/apps-list.mock';
import { ActivitiContentService } from '../../form/services/activiti-alfresco.service';
import { HarnessLoader } from '@angular/cdk/testing';
import { MatFormFieldHarness } from '@angular/material/form-field/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatAutocompleteHarness } from '@angular/material/autocomplete/testing';
describe('StartProcessComponent', () => {
let appConfig: AppConfigService;
let activitiContentService: ActivitiContentService;
let component: StartProcessInstanceComponent;
let fixture: ComponentFixture<StartProcessInstanceComponent>;
let loader: HarnessLoader;
let processService: ProcessService;
let appsProcessService: AppsProcessService;
let getDefinitionsSpy: jasmine.Spy;
let getStartFormDefinitionSpy: jasmine.Spy;
let startProcessSpy: jasmine.Spy;
let applyAlfrescoNodeSpy: jasmine.Spy;
let getDeployedApplicationsSpy: jasmine.Spy;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessTestingModule]
});
});
const selectOptionByName = async (name: string) => {
const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown');
selectElement.click();
const autocompleteDropdown = await loader.getHarness(MatAutocompleteHarness);
const options = await autocompleteDropdown.getOptions({ text: name });
expect(options.length).toBe(1);
await options[0].click();
};
/**
* Change application id
*
* @param appId application id
*/
function changeAppId(appId: number) {
const change = new SimpleChange(null, appId, true);
component.appId = appId;
component.ngOnChanges({ appId: change });
}
beforeEach(() => {
appConfig = TestBed.inject(AppConfigService);
activitiContentService = TestBed.inject(ActivitiContentService);
fixture = TestBed.createComponent(StartProcessInstanceComponent);
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
processService = TestBed.inject(ProcessService);
appsProcessService = TestBed.inject(AppsProcessService);
getDefinitionsSpy = spyOn(processService, 'getProcessDefinitions').and.returnValue(of(testMultipleProcessDefs));
startProcessSpy = spyOn(processService, 'startProcess').and.returnValue(of(newProcess));
getStartFormDefinitionSpy = spyOn(processService, 'getStartFormDefinition').and.returnValue(of(taskFormMock));
applyAlfrescoNodeSpy = spyOn(activitiContentService, 'applyAlfrescoNode').and.returnValue(of({ id: 1234 }));
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of([{ id: '1', name: 'fake-repo-name' } as any]));
});
afterEach(() => {
fixture.destroy();
TestBed.resetTestingModule();
});
describe('first step', () => {
describe('without start form', () => {
beforeEach(() => {
fixture.detectChanges();
component.name = 'My new process';
changeAppId(123);
fixture.detectChanges();
});
it('should enable start button when name and process filled out', async () => {
spyOn(component, 'loadProcessDefinitions').and.callThrough();
component.processNameInput.setValue('My Process');
component.processDefinitionInput.setValue(testProcessDef.name);
fixture.detectChanges();
await fixture.whenStable();
const startBtn = fixture.nativeElement.querySelector('#button-start');
expect(startBtn.disabled).toBe(false);
});
it('should have start button disabled when name not filled out', async () => {
spyOn(component, 'loadProcessDefinitions').and.callThrough();
component.processNameInput.setValue('');
component.processDefinitionInput.setValue(testProcessDef.name);
fixture.detectChanges();
await fixture.whenStable();
const startBtn = fixture.nativeElement.querySelector('#button-start');
expect(startBtn.disabled).toBe(true);
});
it('should have start button disabled when no process is selected', async () => {
component.selectedProcessDef = null;
fixture.detectChanges();
await fixture.whenStable();
const startBtn = fixture.nativeElement.querySelector('#button-start');
expect(startBtn.disabled).toBe(true);
});
it('should have start button disabled process name has a space as the first or last character.', async () => {
component.processNameInput.setValue(' Space in the beginning');
component.processDefinitionInput.setValue(testProcessDef.name);
fixture.detectChanges();
await fixture.whenStable();
const startBtn = fixture.nativeElement.querySelector('#button-start');
expect(startBtn.disabled).toBe(true);
component.processNameInput.setValue('Space in the end ');
fixture.detectChanges();
await fixture.whenStable();
expect(startBtn.disabled).toBe(true);
});
});
describe('with start form', () => {
beforeEach(() => {
fixture.detectChanges();
getDefinitionsSpy.and.returnValue(of(testProcessDefWithForm));
changeAppId(123);
});
it('should initialize start form', async () => {
fixture.detectChanges();
await fixture.whenStable();
expect(component.startForm).toBeDefined();
expect(component.startForm).not.toBeNull();
});
it('should have labels for process name and type', async () => {
component.processDefinitionInput.setValue('My Default Name');
component.processNameInput.setValue('claim');
const inputLabels = await loader.getAllHarnesses(
MatFormFieldHarness.with({ ancestor: '.adf-start-process', selector: '.adf-process-input-container' })
);
expect(inputLabels.length).toBe(2);
});
it('should have floating labels for process name and type', async () => {
component.processDefinitionInput.setValue('My Default Name');
component.processNameInput.setValue('claim');
fixture.detectChanges();
await fixture.whenStable();
const inputLabelsNodes = document.querySelectorAll('.adf-start-process .adf-process-input-container');
inputLabelsNodes.forEach((labelNode) => {
expect(labelNode.getAttribute('ng-reflect-float-label')).toBe('always');
});
});
it('should load start form from service', async () => {
fixture.detectChanges();
await fixture.whenStable();
expect(getStartFormDefinitionSpy).toHaveBeenCalled();
});
it('should have start button disabled if the process is not selected', async () => {
component.name = 'My new process';
fixture.detectChanges();
await fixture.whenStable();
const startBtn = fixture.nativeElement.querySelector('#button-start');
expect(startBtn).toBeNull();
});
it('should emit cancel event on cancel Button', async () => {
fixture.detectChanges();
await fixture.whenStable();
const cancelButton = fixture.nativeElement.querySelector('#cancel_process');
const cancelSpy: jasmine.Spy = spyOn(component.cancel, 'emit');
cancelButton.click();
fixture.detectChanges();
await fixture.whenStable();
expect(cancelSpy).toHaveBeenCalled();
});
it('should return true if startFrom defined', async () => {
component.name = 'my:process1';
fixture.detectChanges();
await fixture.whenStable();
expect(component.hasStartForm()).toBe(true);
});
});
describe('CS content connection', () => {
it('Should get the alfrescoRepositoryName from the config json', async () => {
appConfig.config = Object.assign(appConfig.config, {
alfrescoRepositoryName: 'alfresco-123'
});
expect(component.getAlfrescoRepositoryName()).toBe('alfresco-123Alfresco');
});
it('Should take the alfrescoRepositoryName from the API when there is no alfrescoRepositoryName defined in config json', async () => {
fixture.detectChanges();
await fixture.whenStable();
expect(component.alfrescoRepositoryName).toBe('alfresco-1-fake-repo-name');
});
it('if values in input is a node should be linked in the process service', async () => {
component.values = {};
component.values['file'] = {
isFile: true,
name: 'example-file'
};
component.moveNodeFromCStoPS();
fixture.detectChanges();
await fixture.whenStable();
expect(component.movedNodeToPS.file[0].id).toBe(1234);
expect(applyAlfrescoNodeSpy).toHaveBeenCalled();
});
it('if values in input is a collection of nodes should be linked in the process service', async () => {
component.values = {};
component.values['file'] = [
{
isFile: true,
name: 'example-file-1'
},
{
isFile: true,
name: 'example-fil-2'
},
{
isFile: true,
name: 'example-file-3'
}
];
component.moveNodeFromCStoPS();
fixture.detectChanges();
await fixture.whenStable();
expect(component.movedNodeToPS.file.length).toBe(3);
expect(component.movedNodeToPS.file[0].id).toBe(1234);
expect(component.movedNodeToPS.file[1].id).toBe(1234);
expect(applyAlfrescoNodeSpy).toHaveBeenCalledTimes(3);
});
});
});
describe('process definitions list', () => {
beforeEach(() => {
fixture.detectChanges();
component.name = 'My new process';
changeAppId(123);
fixture.detectChanges();
});
it('should call service to fetch process definitions with appId', async () => {
await fixture.whenStable();
expect(getDefinitionsSpy).toHaveBeenCalledWith(123);
});
it('should display the correct number of processes in the select list', async () => {
const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown');
selectElement.click();
const options = await (await loader.getHarness(MatAutocompleteHarness)).getOptions();
expect(options.length).toBe(2);
expect(await options[0].getText()).toBe('My Process 1');
expect(await options[1].getText()).toBe('My Process 2');
});
it('should show no process available message when no process definition is loaded', async () => {
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of([]));
changeAppId(123);
fixture.detectChanges();
await fixture.whenStable();
const noProcessElement = fixture.nativeElement.querySelector('.adf-empty-content__title');
expect(noProcessElement).not.toBeNull('Expected no available process message to be present');
expect(noProcessElement.innerText.trim()).toBe('ADF_PROCESS_LIST.START_PROCESS.NO_PROCESS_DEFINITIONS');
});
it('should select processDefinition based on processDefinition input', async () => {
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
component.appId = 123;
component.processNameInput.setValue('My Process 2');
component.processDefinitionInput.setValue('My Process 2');
fixture.detectChanges();
await fixture.whenStable();
expect(component.selectedProcessDef.name).toBe(JSON.parse(JSON.stringify(testMultipleProcessDefs[1])).name);
});
it('should select automatically the processDefinition if the app contain only one', async () => {
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(testProcessDefinitions));
changeAppId(123);
fixture.detectChanges();
await fixture.whenStable();
expect(component.selectedProcessDef.name).toBe(JSON.parse(JSON.stringify(testProcessDefinitions[0])).name);
});
it('should not select automatically any processDefinition if the app contain multiple process and does not have any processDefinition as input', async () => {
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
changeAppId(123);
fixture.detectChanges();
await fixture.whenStable();
expect(component.selectedProcessDef.name).not.toBeDefined();
});
describe('dropdown', () => {
it('should hide the process dropdown button if showSelectProcessDropdown is false', async () => {
fixture.detectChanges();
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of([testProcessDef]));
component.appId = 123;
component.showSelectProcessDropdown = false;
component.ngOnChanges({});
fixture.detectChanges();
await fixture.whenStable();
const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown');
expect(selectElement).toBeNull();
});
it('should show the process dropdown button if showSelectProcessDropdown is false', async () => {
fixture.detectChanges();
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
component.appId = 123;
component.processDefinitionName = 'My Process 2';
component.showSelectProcessDropdown = true;
component.ngOnChanges({});
fixture.detectChanges();
await fixture.whenStable();
const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown');
expect(selectElement).not.toBeNull();
});
it('should show the process dropdown button by default', async () => {
fixture.detectChanges();
await fixture.whenStable();
getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
component.appId = 123;
component.processDefinitionName = 'My Process 2';
component.ngOnChanges({});
fixture.detectChanges();
await fixture.whenStable();
const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown');
expect(selectElement).not.toBeNull();
});
});
});
describe('input changes', () => {
beforeEach(async () => {
component.appId = 123;
fixture.detectChanges();
});
it('should reload processes when appId input changed', async () => {
changeAppId(456);
fixture.detectChanges();
expect(getDefinitionsSpy).toHaveBeenCalledWith(456);
});
it('should get current processDef', () => {
changeAppId(456);
fixture.detectChanges();
expect(getDefinitionsSpy).toHaveBeenCalled();
expect(component.processDefinitions).toBe(testMultipleProcessDefs);
});
});
describe('start process', () => {
beforeEach(() => {
fixture.detectChanges();
component.name = 'My new process';
changeAppId(123);
});
it('should call service to start process if required fields provided', async () => {
component.processDefinitionSelectionChanged(testProcessDef);
component.startProcess();
fixture.detectChanges();
await fixture.whenStable();
expect(startProcessSpy).toHaveBeenCalled();
});
it('should avoid calling service to start process if required fields NOT provided', async () => {
component.name = '';
component.startProcess();
fixture.detectChanges();
await fixture.whenStable();
expect(startProcessSpy).not.toHaveBeenCalled();
});
it('should call service to start process with the correct parameters', async () => {
component.processDefinitionSelectionChanged(testProcessDef);
component.startProcess();
fixture.detectChanges();
await fixture.whenStable();
expect(startProcessSpy).toHaveBeenCalledWith('my:process1', 'My new process', undefined, undefined, undefined);
});
it('should call service to start process with the variables setted', async () => {
const inputProcessVariable: ProcessInstanceVariable[] = [];
const variable: ProcessInstanceVariable = {};
variable.name = 'nodeId';
variable.value = 'id';
inputProcessVariable.push(variable);
component.variables = inputProcessVariable;
component.processDefinitionSelectionChanged(testProcessDef);
component.startProcess();
fixture.detectChanges();
await fixture.whenStable();
expect(startProcessSpy).toHaveBeenCalledWith('my:process1', 'My new process', undefined, undefined, inputProcessVariable);
});
it('should output start event when process started successfully', async () => {
const emitSpy = spyOn(component.start, 'emit');
component.processDefinitionSelectionChanged(testProcessDef);
component.startProcess();
fixture.detectChanges();
await fixture.whenStable();
expect(emitSpy).toHaveBeenCalledWith(newProcess);
});
it('should emit start event when start select a process and add a name', () => {
const startProcessEmitterSpy = spyOn(component.start, 'emit');
component.processDefinitionSelectionChanged(testProcessDef);
component.name = 'my:Process';
component.startProcess();
expect(startProcessEmitterSpy).toHaveBeenCalledWith(newProcess);
});
it('should emit processDefinitionSelection event when a process definition is selected', async () => {
const processDefinitionSelectionSpy = spyOn(component.processDefinitionSelection, 'emit');
await selectOptionByName(testProcessDef.name);
expect(processDefinitionSelectionSpy).toHaveBeenCalledWith(testProcessDef);
});
it('should not emit start event when start the process without select a process and name', () => {
component.name = null;
component.selectedProcessDef = null;
const startSpy: jasmine.Spy = spyOn(component.start, 'emit');
component.startProcess();
fixture.detectChanges();
expect(startSpy).not.toHaveBeenCalled();
});
it('should not emit start event when start the process without name', () => {
component.name = null;
const startSpy: jasmine.Spy = spyOn(component.start, 'emit');
component.startProcess();
fixture.detectChanges();
expect(startSpy).not.toHaveBeenCalled();
});
it('should not emit start event when start the process without select a process', () => {
component.selectedProcessDef = null;
const startSpy: jasmine.Spy = spyOn(component.start, 'emit');
component.startProcess();
fixture.detectChanges();
expect(startSpy).not.toHaveBeenCalled();
});
});
describe('Select applications', () => {
beforeEach(() => {
fixture.detectChanges();
component.name = 'My new process';
component.showSelectApplicationDropdown = true;
getDeployedApplicationsSpy = spyOn(appsProcessService, 'getDeployedApplications').and.returnValue(of(deployedApps));
});
it('Should be able to show application drop-down if showSelectApplicationDropdown set to true', async () => {
getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
changeAppId(3);
fixture.detectChanges();
const appsSelector = fixture.nativeElement.querySelector('[data-automation-id="adf-start-process-apps-drop-down"]');
const labelText = await (await loader.getHarness(MatFormFieldHarness.with({ selector: '.adf-start-process-app-list' }))).getLabel();
expect(appsSelector).not.toBeNull();
expect(labelText).toEqual('ADF_PROCESS_LIST.START_PROCESS.FORM.LABEL.SELECT_APPLICATION');
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(component.applications.length).toBe(6);
expect(component.selectedApplication).toEqual(deployedApps[2]);
expect(component.selectedApplication.id).toEqual(3);
expect(component.selectedApplication.name).toEqual('App3');
});
it('Should not be able to show application drop-down if showSelectApplicationDropdown set to false', () => {
component.showSelectApplicationDropdown = false;
fixture.detectChanges();
const appsSelector = fixture.nativeElement.querySelector('[data-automation-id="adf-start-process-apps-drop-down"]');
expect(appsSelector).toBeNull();
});
it('Should be able to list process-definition based on selected application', () => {
getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
changeAppId(3);
fixture.detectChanges();
expect(component.selectedApplication).toEqual(deployedApps[2]);
expect(component.selectedApplication.name).toEqual('App3');
expect(getDefinitionsSpy).toHaveBeenCalledWith(3);
expect(component.processDefinitions.length).toEqual(2);
expect(component.processDefinitions[0].name).toEqual('My Process 1');
expect(component.processDefinitions[1].name).toEqual('My Process 2');
getDefinitionsSpy.and.returnValue(of([{ id: 'my:process 3', name: 'My Process 3', hasStartForm: true }]));
fixture.detectChanges();
const newApplication = { value: deployedApps[1] } as MatSelectChange;
component.onAppSelectionChange(newApplication);
fixture.detectChanges();
expect(component.selectedApplication).toEqual(deployedApps[1]);
expect(component.selectedApplication.name).toEqual('App2');
expect(getDefinitionsSpy).toHaveBeenCalledWith(2);
expect(component.processDefinitions.length).toEqual(1);
expect(component.processDefinitions[0].name).toEqual('My Process 3');
});
it('Should be able to pre-select an application if the list has one application', () => {
getDeployedApplicationsSpy.and.returnValues(of([deployedApps[0]]));
getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
changeAppId(123);
fixture.detectChanges();
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(component.applications.length).toEqual(1);
expect(component.selectedApplication.name).toEqual('App1');
});
it('[C333511] Should be able to preselect single app deployed with single process and start event Form', async () => {
getDeployedApplicationsSpy.and.returnValues(of([deployedApps[0]]));
getDefinitionsSpy.and.returnValues(of(testProcessDefWithForm));
changeAppId(123);
fixture.detectChanges();
await fixture.whenStable();
const appsSelectElement = fixture.nativeElement.querySelector('[data-automation-id="adf-start-process-apps-drop-down"]');
const processDefinitionSelectInput = fixture.nativeElement.querySelector('#processDefinitionName');
const processNameInput = fixture.nativeElement.querySelector('#processName');
const cancelButton = fixture.nativeElement.querySelector('#cancel_process');
const startBtn = fixture.nativeElement.querySelector('[data-automation-id="adf-form-start process"]');
const adfStartForm = fixture.nativeElement.querySelector('adf-start-form');
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(getDefinitionsSpy).toHaveBeenCalled();
expect(component.applications.length).toEqual(1);
expect(component.processDefinitions.length).toEqual(1);
expect(component.selectedApplication.name).toEqual('App1');
expect(component.selectedProcessDef.name).toEqual('My Process 1');
expect(appsSelectElement).not.toBeNull();
expect(processDefinitionSelectInput).not.toBeNull();
expect(processNameInput).not.toBeNull();
expect(adfStartForm).not.toBeNull();
expect(startBtn).not.toBeNull();
expect(cancelButton).not.toBeNull();
});
it('[C333511] Should be able to preselect single app deployed with single process and no form', async () => {
getDeployedApplicationsSpy.and.returnValues(of([deployedApps[0]]));
getDefinitionsSpy.and.returnValues(of(testProcessDefinitions));
changeAppId(123);
fixture.detectChanges();
await fixture.whenStable();
const appsSelectElement = fixture.nativeElement.querySelector('[data-automation-id="adf-start-process-apps-drop-down"]');
const processDefinitionSelectInput = fixture.nativeElement.querySelector('#processDefinitionName');
const processNameInput = fixture.nativeElement.querySelector('#processName');
const cancelButton = fixture.nativeElement.querySelector('#cancel_process');
const startBtn = fixture.nativeElement.querySelector('#button-start');
const adfStartForm = fixture.nativeElement.querySelector('adf-start-form');
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(getDefinitionsSpy).toHaveBeenCalled();
expect(component.applications.length).toEqual(1);
expect(component.processDefinitions.length).toEqual(1);
expect(component.selectedApplication.name).toEqual('App1');
expect(component.selectedProcessDef.name).toEqual('My Process 1');
expect(appsSelectElement).not.toBeNull();
expect(processDefinitionSelectInput).not.toBeNull();
expect(processNameInput).not.toBeNull();
expect(adfStartForm).toBeNull();
expect(startBtn).not.toBeNull();
expect(cancelButton).not.toBeNull();
});
it('Should be able to pre-select an application from the apps based given appId', () => {
changeAppId(2);
fixture.detectChanges();
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(component.applications.length).toEqual(6);
expect(component.selectedApplication.id).toEqual(2);
expect(component.selectedApplication.id).toEqual(2);
expect(component.selectedApplication.name).toEqual('App2');
});
it('Should be able to disable process name and definitions inputs if there is no application selected by default', () => {
changeAppId(12345);
fixture.detectChanges();
const processDefinitionSelectInput = fixture.nativeElement.querySelector('#processDefinitionName');
const processNameInput = fixture.nativeElement.querySelector('#processName');
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(component.applications.length).toEqual(6);
expect(component.selectedApplication).toBeUndefined();
expect(processDefinitionSelectInput.disabled).toEqual(true);
expect(processNameInput.disabled).toEqual(true);
});
it('Should be able to enable process name and definitions inputs if the application selected by given appId', () => {
changeAppId(2);
fixture.detectChanges();
const processDefinitionSelectInput = fixture.nativeElement.querySelector('#processDefinitionName');
const processNameInput = fixture.nativeElement.querySelector('#processName');
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(component.applications.length).toEqual(6);
expect(component.selectedApplication.id).toEqual(2);
expect(processDefinitionSelectInput.disabled).toEqual(false);
expect(processNameInput.disabled).toEqual(false);
});
it('Should be able to enable process name and definitions inputs when the application selected from the apps drop-down', () => {
changeAppId(12345);
fixture.detectChanges();
const appsSelectElement = fixture.nativeElement.querySelector('[data-automation-id="adf-start-process-apps-drop-down"]');
const processDefinitionSelectInput = fixture.nativeElement.querySelector('#processDefinitionName');
const processNameInput = fixture.nativeElement.querySelector('#processName');
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(component.applications.length).toEqual(6);
expect(component.selectedApplication).toBeUndefined();
expect(processDefinitionSelectInput.disabled).toEqual(true);
expect(processNameInput.disabled).toEqual(true);
appsSelectElement.click();
fixture.detectChanges();
const sortOptions = document.querySelector('[data-automation-id="adf-start-process-apps-option-App2"]');
sortOptions.dispatchEvent(new Event('click'));
fixture.detectChanges();
expect(component.selectedApplication.id).toBe(2);
expect(component.selectedApplication.name).toBe('App2');
expect(processDefinitionSelectInput.disabled).toEqual(false);
expect(processNameInput.disabled).toEqual(false);
});
it('[C333521] Should be able to pre-select single deployed application with multiple processes', () => {
const singleDeployedApp = deployedApps[0];
getDeployedApplicationsSpy.and.returnValues(of([singleDeployedApp]));
changeAppId(1);
fixture.detectChanges();
expect(getDeployedApplicationsSpy).toHaveBeenCalled();
expect(component.applications.length).toBe(1);
expect(component.selectedApplication).toEqual(singleDeployedApp);
expect(getDefinitionsSpy).toHaveBeenCalledWith(1);
expect(component.processDefinitions.length).toEqual(2);
const processDefWithStartForm = testMultipleProcessDefs[1];
component.processDefinitionSelectionChanged(processDefWithStartForm);
fixture.detectChanges();
const processWithStartForm = fixture.nativeElement.querySelector('adf-start-form');
expect(processWithStartForm).not.toBeNull();
expect(component.selectedProcessDef.hasStartForm).toEqual(processDefWithStartForm.hasStartForm);
const processDefWithNoStartForm = testMultipleProcessDefs[0];
component.processDefinitionSelectionChanged(processDefWithNoStartForm);
fixture.detectChanges();
const processWithNoStartForm = fixture.nativeElement.querySelector('adf-start-form');
expect(processWithNoStartForm).toBeNull();
expect(component.selectedProcessDef.hasStartForm).toEqual(processDefWithNoStartForm.hasStartForm);
});
it('[C333522] Should be able to list multiple deployed apps with multiple process', async () => {
changeAppId(123);
fixture.detectChanges();
const application1 = deployedApps[0];
const application2 = deployedApps[1];
const application3 = deployedApps[2];
expect(component.applications.length).toBe(6);
const processDefWithStartForm = testProcessDefWithForm[0];
getDefinitionsSpy.and.returnValues(of([processDefWithStartForm]));
component.onAppSelectionChange({ value: application1 } as MatSelectChange);
fixture.detectChanges();
await fixture.whenStable();
const processWithStartForm = fixture.nativeElement.querySelector('adf-start-form');
expect(processWithStartForm).not.toBeNull();
expect(component.selectedApplication).toEqual(application1);
expect(getDefinitionsSpy).toHaveBeenCalledWith(application1.id);
expect(component.processDefinitions.length).toEqual(1);
expect(component.selectedProcessDef.name).toEqual(processDefWithStartForm.name);
expect(component.selectedProcessDef.hasStartForm).toEqual(processDefWithStartForm.hasStartForm);
getDefinitionsSpy.and.returnValues(of(testMultipleProcessDefs));
component.onAppSelectionChange({ value: application2 } as MatSelectChange);
fixture.detectChanges();
await fixture.whenStable();
expect(component.selectedApplication).toEqual(application2);
expect(getDefinitionsSpy).toHaveBeenCalledWith(application2.id);
expect(component.processDefinitions.length).toEqual(2);
const processDefWithNoStartForm = testMultipleProcessDefs[0];
getDefinitionsSpy.and.returnValues(of([processDefWithNoStartForm]));
component.onAppSelectionChange({ value: application3 } as MatSelectChange);
fixture.detectChanges();
await fixture.whenStable();
const processWithNoStartForm = fixture.nativeElement.querySelector('adf-start-form');
expect(processWithNoStartForm).toBeNull();
expect(component.selectedApplication).toEqual(application3);
expect(getDefinitionsSpy).toHaveBeenCalledWith(application3.id);
expect(component.processDefinitions.length).toEqual(1);
expect(component.selectedProcessDef.name).toEqual(processDefWithNoStartForm.name);
expect(component.selectedProcessDef.hasStartForm).toEqual(processDefWithNoStartForm.hasStartForm);
});
});
describe('Empty Template', () => {
it('[333510] Should be able to show empty template when no applications deployed', async () => {
getDeployedApplicationsSpy = spyOn(appsProcessService, 'getDeployedApplications').and.returnValue(of([]));
component.showSelectApplicationDropdown = true;
component.appId = 3;
component.ngOnInit();
fixture.detectChanges();
await fixture.whenStable();
const noProcessElement = fixture.nativeElement.querySelector('.adf-empty-content__title');
const appsSelectElement = fixture.nativeElement.querySelector('[data-automation-id="adf-start-process-apps-drop-down"]');
const processDefinitionSelectInput = fixture.nativeElement.querySelector('#processDefinitionName');
const processNameInput = fixture.nativeElement.querySelector('#processName');
const cancelButton = fixture.nativeElement.querySelector('#cancel_process');
const startBtn = fixture.nativeElement.querySelector('#button-start');
expect(appsSelectElement).toBeNull();
expect(processDefinitionSelectInput).toBeNull();
expect(processNameInput).toBeNull();
expect(startBtn).toBeNull();
expect(cancelButton).toBeNull();
expect(noProcessElement).not.toBeNull('Expected no available process message to be present');
expect(noProcessElement.innerText.trim()).toBe('ADF_PROCESS_LIST.START_PROCESS.NO_PROCESS_DEFINITIONS');
});
it('Should be able to show empty template if processDefinitions are empty', async () => {
getDefinitionsSpy.and.returnValue(of([]));
component.appId = 1;
component.ngOnInit();
fixture.detectChanges();
await fixture.whenStable();
const noProcessElement = fixture.nativeElement.querySelector('.adf-empty-content__title');
const processDefinitionSelectInput = fixture.nativeElement.querySelector('#processDefinitionName');
const processNameInput = fixture.nativeElement.querySelector('#processName');
const cancelButton = fixture.nativeElement.querySelector('#cancel_process');
const startBtn = fixture.nativeElement.querySelector('#button-start');
expect(processDefinitionSelectInput).toBeNull();
expect(processNameInput).toBeNull();
expect(startBtn).toBeNull();
expect(cancelButton).toBeNull();
expect(noProcessElement).not.toBeNull('Expected no available process message to be present');
expect(noProcessElement.innerText.trim()).toBe('ADF_PROCESS_LIST.START_PROCESS.NO_PROCESS_DEFINITIONS');
});
it('should show no process definition selected template if there is no process definition selected', async () => {
getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
getDeployedApplicationsSpy = spyOn(appsProcessService, 'getDeployedApplications').and.returnValue(of(deployedApps));
component.showSelectApplicationDropdown = true;
component.appId = 1234;
component.ngOnInit();
fixture.detectChanges();
await fixture.whenStable();
const noProcessElement = fixture.nativeElement.querySelector('.adf-empty-content__title');
expect(noProcessElement).not.toBeNull('Expected no available process message to be present');
expect(noProcessElement.innerText.trim()).toBe('ADF_PROCESS_LIST.START_PROCESS.NO_PROCESS_DEF_SELECTED');
});
it('should show no start form template if selected process definition does not have start form', async () => {
getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
getDeployedApplicationsSpy = spyOn(appsProcessService, 'getDeployedApplications').and.returnValue(of(deployedApps));
component.showSelectApplicationDropdown = true;
component.processDefinitionName = 'My Process 1';
component.appId = 3;
component.ngOnInit();
fixture.detectChanges();
await fixture.whenStable();
const noProcessElement = fixture.nativeElement.querySelector('.adf-empty-content__title');
expect(noProcessElement).not.toBeNull('Expected no available process message to be present');
expect(noProcessElement.innerText.trim()).toBe('ADF_PROCESS_LIST.START_PROCESS.NO_START_FORM');
});
});
describe('Error event', () => {
const processDefError = { message: 'Failed to load Process definitions' };
const applicationsError = { message: 'Failed to load applications' };
const startProcessError = { message: 'Failed to start process' };
beforeEach(() => {
fixture.detectChanges();
});
it('should emit error event in case loading process definitions failed', async () => {
const errorSpy = spyOn(component.error, 'emit');
getDefinitionsSpy.and.returnValue(throwError(processDefError));
component.appId = 3;
component.ngOnInit();
fixture.detectChanges();
await fixture.whenStable();
expect(errorSpy).toHaveBeenCalledWith(processDefError);
});
it('should emit error event in case loading applications failed', async () => {
const errorSpy = spyOn(component.error, 'emit');
getDeployedApplicationsSpy = spyOn(appsProcessService, 'getDeployedApplications').and.returnValue(throwError(applicationsError));
component.showSelectApplicationDropdown = true;
component.appId = 3;
component.ngOnInit();
fixture.detectChanges();
await fixture.whenStable();
expect(errorSpy).toHaveBeenCalledWith(applicationsError);
});
it('should emit error event in case start process failed', async () => {
const errorSpy = spyOn(component.error, 'emit');
getDefinitionsSpy.and.returnValue(of(testMultipleProcessDefs));
getDeployedApplicationsSpy = spyOn(appsProcessService, 'getDeployedApplications').and.returnValue(of(deployedApps));
startProcessSpy.and.returnValue(throwError(startProcessError));
component.showSelectApplicationDropdown = true;
component.processDefinitionName = 'My Process 1';
component.name = 'mock name';
component.appId = 3;
component.ngOnInit();
fixture.detectChanges();
await fixture.whenStable();
component.startProcess();
fixture.detectChanges();
expect(errorSpy).toHaveBeenCalledWith(startProcessError);
});
});
});