diff --git a/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts index a259496c83..ee905ada6e 100644 --- a/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts @@ -93,4 +93,11 @@ export class ProcessCloudDemoPage { async clickOnCreateButton(): Promise { await BrowserActions.click(this.createButton); } + + async checkActionExecuted(processInstanceId: string, action: string): Promise { + await BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText(`span`, 'Action Menu:'))); + await BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText(`span`, 'Context Menu:'))); + await BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText(`span`, 'ProcessInstanceId: ' + processInstanceId))); + await BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText(`span`, 'Action Type: ' + action))); + } } diff --git a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts index 7210085316..9b01db694d 100644 --- a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts @@ -41,10 +41,17 @@ export class TasksCloudDemoPage { modeSelector: ElementFinder = element(by.css("div[class*='mat-select-panel']")); displayTaskDetailsToggle: ElementFinder = element(by.css('mat-slide-toggle[data-automation-id="taskDetailsRedirection"]')); displayProcessDetailsToggle: ElementFinder = element(by.css('mat-slide-toggle[data-automation-id="processDetailsRedirection"]')); + actionMenuToggle: ElementFinder = element(by.css('mat-slide-toggle[data-automation-id="actionmenu"]')); + contextMenuToggle: ElementFinder = element(by.css('mat-slide-toggle[data-automation-id="contextmenu"]')); multiSelectionToggle: ElementFinder = element(by.css('mat-slide-toggle[data-automation-id="multiSelection"]')); testingModeToggle: ElementFinder = element(by.css('mat-slide-toggle[data-automation-id="testingMode"]')); selectedRows: ElementFinder = element(by.xpath("//div[text()=' Selected rows: ']")); noOfSelectedRows: ElementArrayFinder = element.all(by.xpath("//div[text()=' Selected rows: ']//li")); + addActionTitle: ElementFinder = element(by.cssContainingText('.mat-card-title', 'Add Action')); + keyInputField: ElementFinder = element(by.css('input[placeholder="Key"]')); + titleInputField: ElementFinder = element(by.css('input[placeholder="Title"]')); + iconInputField: ElementFinder = element(by.css('input[placeholder="Icon"]')); + addActionButton: ElementFinder = element(by.cssContainingText('button span', 'Add')); formControllersPage: FormControllersPage = new FormControllersPage(); @@ -62,6 +69,14 @@ export class TasksCloudDemoPage { await this.formControllersPage.enableToggle(this.multiSelectionToggle); } + async enableActionMenu(): Promise { + await this.formControllersPage.enableToggle(this.actionMenuToggle); + } + + async enableContextMenu(): Promise { + await this.formControllersPage.enableToggle(this.contextMenuToggle); + } + async enableTestingMode(): Promise { await this.formControllersPage.enableToggle(this.testingModeToggle); } @@ -137,4 +152,20 @@ export class TasksCloudDemoPage { const row: ElementFinder = element(by.xpath(`//div[text()=' Selected rows: ']//li[${rowNo}]`)); return await BrowserActions.getText(row); } + + async addActionIsDisplayed(): Promise { + await BrowserVisibility.waitUntilElementIsVisible(this.addActionTitle); + } + + async addAction(text: string): Promise { + await BrowserActions.clearSendKeys(this.keyInputField, text); + await BrowserActions.clearSendKeys(this.titleInputField, text); + await BrowserActions.clearSendKeys(this.iconInputField, text); + await BrowserActions.click(this.addActionButton); + } + + async actionAdded(action: string): Promise { + await BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText(`mat-chip`, action))); + } + } diff --git a/e2e/process-services-cloud/process-list-cloud-action-menu.e2e.ts b/e2e/process-services-cloud/process-list-cloud-action-menu.e2e.ts new file mode 100644 index 0000000000..25d679b811 --- /dev/null +++ b/e2e/process-services-cloud/process-list-cloud-action-menu.e2e.ts @@ -0,0 +1,111 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * 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 { browser } from 'protractor'; +import { GroupIdentityService, IdentityService, LoginSSOPage, SettingsPage } from '@alfresco/adf-testing'; +import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; +import { AppListCloudPage } from '@alfresco/adf-testing'; +import { NavigationBarPage } from '../pages/adf/navigationBarPage'; +import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; + +import { ProcessDefinitionsService, ApiService } from '@alfresco/adf-testing'; +import { ProcessInstancesService } from '@alfresco/adf-testing'; +import resources = require('../util/resources'); + +describe('Process list cloud', () => { + + describe('Process List - Custom Action Menu', () => { + const loginSSOPage = new LoginSSOPage(); + const navigationBarPage = new NavigationBarPage(); + const appListCloudComponent = new AppListCloudPage(); + const processCloudDemoPage = new ProcessCloudDemoPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); + const settingsPage = new SettingsPage(); + + let processDefinitionService: ProcessDefinitionsService; + let processInstancesService: ProcessInstancesService; + let identityService: IdentityService; + let groupIdentityService: GroupIdentityService; + let testUser, groupInfo, editProcess, deleteProcess; + + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; + const apiService = new ApiService(browser.params.config.oauth2.clientId, browser.params.config.bpmHost, browser.params.config.oauth2.host, 'BPM'); + + beforeAll(async () => { + + await apiService.login(browser.params.identityAdmin.email, browser.params.identityAdmin.password); + identityService = new IdentityService(apiService); + groupIdentityService = new GroupIdentityService(apiService); + testUser = await identityService.createIdentityUserWithRole(apiService, [identityService.ROLES.APS_USER]); + groupInfo = await groupIdentityService.getGroupInfoByGroupName('hr'); + await identityService.addUserToGroup(testUser.idIdentityService, groupInfo.id); + + await apiService.login(testUser.email, testUser.password); + processDefinitionService = new ProcessDefinitionsService(apiService); + const processDefinition = await processDefinitionService + .getProcessDefinitionByName(resources.ACTIVITI7_APPS.SIMPLE_APP.processes.simpleProcess, simpleApp); + + processInstancesService = new ProcessInstancesService(apiService); + editProcess = await processInstancesService.createProcessInstance(processDefinition.entry.key, simpleApp); + deleteProcess = await processInstancesService.createProcessInstance(processDefinition.entry.key, simpleApp); + + await settingsPage.setProviderBpmSso( + browser.params.config.bpmHost, + browser.params.config.oauth2.host, + browser.params.config.identityHost); + await loginSSOPage.loginSSOIdentityService(testUser.email, testUser.password); + + }); + + afterAll(async() => { + await apiService.login(browser.params.identityAdmin.email, browser.params.identityAdmin.password); + await identityService.deleteIdentityUser(testUser.idIdentityService); + + }); + + beforeAll(async () => { + await navigationBarPage.navigateToProcessServicesCloudPage(); + await appListCloudComponent.checkApsContainer(); + await appListCloudComponent.goToApp(simpleApp); + await tasksCloudDemoPage.clickSettingsButton(); + await tasksCloudDemoPage.enableTestingMode(); + await tasksCloudDemoPage.enableActionMenu(); + await tasksCloudDemoPage.enableContextMenu(); + await tasksCloudDemoPage.addActionIsDisplayed(); + await tasksCloudDemoPage.addAction('edit'); + await tasksCloudDemoPage.actionAdded('edit'); + await tasksCloudDemoPage.addAction('delete'); + await tasksCloudDemoPage.actionAdded('delete'); + await tasksCloudDemoPage.clickAppButton(); + await processCloudDemoPage.clickOnProcessFilters(); + await processCloudDemoPage.runningProcessesFilter().clickProcessFilter(); + }); + + it('[C315236] Should be able to see and execute custom action menu', async () => { + await expect(await processCloudDemoPage.getActiveFilterName()).toBe('Running Processes'); + await processCloudDemoPage.processListCloudComponent().checkProcessListIsLoaded(); + await processCloudDemoPage.processListCloudComponent().checkContentIsDisplayedById(editProcess.entry.id); + await processCloudDemoPage.processListCloudComponent().clickOnCustomActionMenu(editProcess.entry.id, 'edit'); + await processCloudDemoPage.checkActionExecuted(editProcess.entry.id, 'edit'); + await processCloudDemoPage.processListCloudComponent().rightClickOnRow(deleteProcess.entry.id); + await processCloudDemoPage.processListCloudComponent().clickContextMenuActionNamed('delete'); + await processCloudDemoPage.checkActionExecuted(deleteProcess.entry.id, 'delete'); + }); + + }); + +}); diff --git a/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts index a24da2a85e..68f4c0ea31 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts @@ -17,7 +17,7 @@ import { BrowserVisibility } from '../../core/utils/browser-visibility'; import { DataTableComponentPage } from '../../core/pages/data-table-component.page'; -import { element, by, ElementFinder } from 'protractor'; +import { element, by, ElementFinder, Locator } from 'protractor'; import { BrowserActions } from '../../core/utils/browser-actions'; export class ProcessListCloudComponentPage { @@ -29,6 +29,8 @@ export class ProcessListCloudComponentPage { processList: ElementFinder = element(by.css('adf-cloud-process-list')); noProcessFound: ElementFinder = element.all(by.css("div[class='adf-empty-content__title']")).first(); + actionMenu: ElementFinder = element(by.css('div[role="menu"]')); + optionButton: Locator = by.css('button[data-automation-id*="action_menu_"]'); dataTable: DataTableComponentPage = new DataTableComponentPage(this.processList); @@ -100,4 +102,21 @@ export class ProcessListCloudComponentPage { return this.dataTable.getAllRowsColumnValues(column); } + async clickOnCustomActionMenu(content: string, action: string): Promise { + await BrowserActions.closeMenuAndDialogs(); + const row: ElementFinder = this.dataTable.getRow('Id', content); + await BrowserActions.click(row.element(this.optionButton)); + await BrowserVisibility.waitUntilElementIsVisible(this.actionMenu); + const actionButton = element(by.css(`button[data-automation-id*="${action}"]`)); + await BrowserActions.click(actionButton); + } + + async rightClickOnRow(processInstance: string): Promise { + await this.dataTable.rightClickOnRow('Id', processInstance); + } + + async clickContextMenuActionNamed(actionName): Promise { + await BrowserActions.clickExecuteScript(`button[data-automation-id="context-${actionName}"]`); + } + }