diff --git a/cspell.json b/cspell.json index 4b546049d8..1162ad973b 100644 --- a/cspell.json +++ b/cspell.json @@ -139,7 +139,8 @@ "processparent", "uploadfileform", "processwithstarteventform", - "processstring" + "processstring", + "typeahed" ], "dictionaries": [ "html", diff --git a/e2e/actions/users.actions.ts b/e2e/actions/users.actions.ts index a62ac00757..e391ba2450 100644 --- a/e2e/actions/users.actions.ts +++ b/e2e/actions/users.actions.ts @@ -56,9 +56,9 @@ export class UsersActions { async createApsUserWithName(alfrescoJsApi, tenantId, email, firstName, lastName) { const user = new User({ tenantId , email, firstName, lastName}); - await alfrescoJsApi.activiti.adminUsersApi.createNewUser(user); + const { id } = await alfrescoJsApi.activiti.adminUsersApi.createNewUser(user); - return user; + return { ...user, id }; } async cleanupTenant(alfrescoJsApi, tenantId) { diff --git a/e2e/pages/adf/process-services/task-details.page.ts b/e2e/pages/adf/process-services/task-details.page.ts index 623154ba95..be363835a7 100644 --- a/e2e/pages/adf/process-services/task-details.page.ts +++ b/e2e/pages/adf/process-services/task-details.page.ts @@ -65,6 +65,7 @@ export class TaskDetailsPage { editableAssignee = element(by.css('span[data-automation-id="card-textitem-value-assignee"][class*="clickable"]')); claimElement = element(by.css('[data-automation-id="header-claim-button"]')); releaseElement = element(by.css('[data-automation-id="header-unclaim-button"]')); + saveFormButton = element(by.css('button[id="adf-form-save"]')); attachFormDropdown = new DropdownPage(element(by.css('div[class="adf-attach-form-row"]'))); @@ -430,4 +431,9 @@ export class TaskDetailsPage { await BrowserActions.click(this.releaseElement); } + async saveTaskForm(): Promise { + await BrowserVisibility.waitUntilElementIsVisible(this.saveFormButton); + await BrowserActions.click(this.saveFormButton); + } + } diff --git a/e2e/process-services/dynamic-table-date-picker.e2e.ts b/e2e/process-services/dynamic-table-date-picker.e2e.ts index b789fe00e3..21d7cccc01 100644 --- a/e2e/process-services/dynamic-table-date-picker.e2e.ts +++ b/e2e/process-services/dynamic-table-date-picker.e2e.ts @@ -32,28 +32,24 @@ describe('Dynamic Table', () => { const datePicker = new DatePickerCalendarPage(); const navigationBarPage = new NavigationBarPage(); const widget = new Widget(); - let user, tenantId, appId, apps, users; + const apps = new AppsActions(); + const users = new UsersActions(); + const alfrescoJsApi = new AlfrescoApi({ + provider: 'BPM', + hostBpm: browser.params.testConfig.adf_aps.host + }); + + let user, tenantId, appId; beforeAll(async () => { - this.alfrescoJsApi = new AlfrescoApi({ - provider: 'BPM', - hostBpm: browser.params.testConfig.adf_aps.host - }); - - apps = new AppsActions(); - users = new UsersActions(); - - await this.alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); - - user = await users.createTenantAndUser(this.alfrescoJsApi); - + await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); + user = await users.createTenantAndUser(alfrescoJsApi); tenantId = user.tenantId; }); afterAll(async () => { - await this.alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); - - await this.alfrescoJsApi.activiti.adminTenantsApi.deleteTenant(tenantId); + await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); + await alfrescoJsApi.activiti.adminTenantsApi.deleteTenant(tenantId); }); describe('Date Picker', () => { @@ -71,23 +67,19 @@ describe('Dynamic Table', () => { const rowPosition = 0; beforeAll(async () => { - await this.alfrescoJsApi.login(user.email, user.password); - - const importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + await alfrescoJsApi.login(user.email, user.password); + const importedApp = await apps.importPublishDeployApp(alfrescoJsApi, app.file_location); appId = importedApp.id; - await loginPage.loginToProcessServicesUsingUserModel(user); }); afterAll(async () => { - await this.alfrescoJsApi.login(user.email, user.password); - - await this.alfrescoJsApi.activiti.modelsApi.deleteModel(appId); + await alfrescoJsApi.login(user.email, user.password); + await alfrescoJsApi.activiti.modelsApi.deleteModel(appId); }); beforeEach(async () => { await (await (await navigationBarPage.navigateToProcessServicesPage()).goToTaskApp()).clickProcessButton(); - await processServiceTabBarPage.clickProcessButton(); await processFiltersPage.clickCreateProcessButton(); @@ -95,14 +87,14 @@ describe('Dynamic Table', () => { }); it('[C286277] Should have a datepicker and a mask for DateTime field', async () => { - await widget.dynamicTable().clickAddButton(); + await widget.dynamicTable().clickAddRow(); await widget.dynamicTable().clickColumnDateTime(); await expect(await widget.dynamicTable().addRandomStringOnDateTime(randomText.wrongDateTime)).toBe(''); }); it('[C286279] Should be able to save row with Date field', async () => { - await widget.dynamicTable().clickAddButton(); + await widget.dynamicTable().clickAddRow(); await widget.dynamicTable().addRandomStringOnDate(randomText.wrongDate); await widget.dynamicTable().clickSaveButton(); await expect(await widget.dynamicTable().checkErrorMessage()).toBe(randomText.error); @@ -116,7 +108,7 @@ describe('Dynamic Table', () => { }); it('[C311456] Should be able to delete date that is not mandatory and save the Dynamic Table', async () => { - await widget.dynamicTable().clickAddButton(); + await widget.dynamicTable().clickAddRow(); await widget.dynamicTable().clickSaveButton(); await expect(await widget.dynamicTable().checkErrorMessage()).toBe(randomText.requiredError); @@ -135,35 +127,29 @@ describe('Dynamic Table', () => { const dropdown = widget.dropdown(); beforeAll(async () => { + await alfrescoJsApi.login(user.email, user.password); - await this.alfrescoJsApi.login(user.email, user.password); - - const importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + const importedApp = await apps.importPublishDeployApp(alfrescoJsApi, app.file_location); appId = importedApp.id; - await loginPage.loginToProcessServicesUsingUserModel(user); - }); afterAll(async () => { - await this.alfrescoJsApi.login(user.email, user.password); - - await this.alfrescoJsApi.activiti.modelsApi.deleteModel(appId); - + await alfrescoJsApi.login(user.email, user.password); + await alfrescoJsApi.activiti.modelsApi.deleteModel(appId); }); beforeEach(async () => { await (await (await navigationBarPage.navigateToProcessServicesPage()).goToApp(app.title)).clickProcessButton(); await processServiceTabBarPage.clickProcessButton(); - await processFiltersPage.clickCreateProcessButton(); await processFiltersPage.clickNewProcessDropdown(); }); it('[C286519] Should be able to save row with required dropdown column', async () => { const dropdownOption = 'Option 1'; - await widget.dynamicTable().clickAddButton(); + await widget.dynamicTable().clickAddRow(); await dropdown.selectOption(dropdownOption); await widget.dynamicTable().clickSaveButton(); await widget.dynamicTable().checkItemIsPresent(dropdownOption); diff --git a/e2e/process-services/stencil.e2e.ts b/e2e/process-services/stencil.e2e.ts new file mode 100644 index 0000000000..9b8df353f2 --- /dev/null +++ b/e2e/process-services/stencil.e2e.ts @@ -0,0 +1,100 @@ +/*! + * @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 { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { AppsActions } from '../actions/APS/apps.actions'; +import { UsersActions } from '../actions/users.actions'; +import { LoginPage } from '@alfresco/adf-testing'; +import { TasksPage } from '../pages/adf/process-services/tasks.page'; +import { browser } from 'protractor'; +import { User } from '../models/APS/user'; +import { NavigationBarPage } from '../pages/adf/navigation-bar.page'; +import { ProcessServiceTabBarPage } from '../pages/adf/process-services/process-service-tab-bar.page'; +import { StartProcessPage } from '../pages/adf/process-services/start-process.page'; +import { ProcessListDemoPage } from '../pages/adf/demo-shell/process-services/process-list-demo.page'; +import { ProcessFiltersPage } from '../pages/adf/process-services/process-filters.page'; +import { ProcessDetailsPage } from '../pages/adf/process-services/process-details.page'; +import { ProcessListPage } from '../pages/adf/process-services/process-list.page'; +import CONSTANTS = require('../util/constants'); + +describe('Stencil', () => { + + const loginPage = new LoginPage(); + const taskPage = new TasksPage(); + const navigationBarPage = new NavigationBarPage(); + const processServiceTabBarPage = new ProcessServiceTabBarPage(); + const startProcessPage = new StartProcessPage(); + const processListDemoPage = new ProcessListDemoPage(); + const processListPage = new ProcessListPage(); + const processDetailsPage = new ProcessDetailsPage(); + const processFiltersPage = new ProcessFiltersPage(); + const usersActions = new UsersActions(); + const alfrescoJsApi = new AlfrescoApi({ + provider: 'BPM', + hostBpm: browser.params.testConfig.adf_aps.host + }); + + const app = browser.params.resources.Files.STENCIL_PROCESS; + let user: User; + + beforeAll(async () => { + const appsActions = new AppsActions(); + await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); + user = await usersActions.createTenantAndUser(alfrescoJsApi); + + await alfrescoJsApi.login(user.email, user.password); + await appsActions.importPublishDeployApp(alfrescoJsApi, app.file_location); + await loginPage.loginToProcessServicesUsingUserModel(user); + }); + + afterAll(async () => { + await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); + await alfrescoJsApi.activiti.adminTenantsApi.deleteTenant(user.tenantId); + }); + + beforeEach(async () => { + await (await navigationBarPage.navigateToProcessServicesPage()).goToTaskApp(); + await taskPage.tasksListPage().checkTaskListIsLoaded(); + }); + + it('[C245648] Can start an app with custom stencil included', async () => { + const name = 'test stencil process'; + await processServiceTabBarPage.clickProcessButton(); + await processListPage.checkProcessListIsDisplayed(); + await processFiltersPage.clickCreateProcessButton(); + await processFiltersPage.clickNewProcessDropdown(); + + await startProcessPage.startProcess({ name, processName: app.processName }); + await processListDemoPage.checkProcessIsDisplayed(name); + await processFiltersPage.selectFromProcessList(name); + + await processDetailsPage.clickOnActiveTask(); + await taskPage.tasksListPage().checkTaskListIsLoaded(); + await taskPage.taskDetails().clickCompleteTask(); + + await processServiceTabBarPage.clickProcessButton(); + await processFiltersPage.checkNoContentMessage(); + + await processFiltersPage.clickCompletedFilterButton(); + await processListDemoPage.checkProcessIsDisplayed(name); + + await processServiceTabBarPage.clickTasksButton(); + await taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.COMPLETED_TASKS); + await taskPage.tasksListPage().checkTaskListIsLoaded(); + await taskPage.tasksListPage().checkContentIsDisplayed(app.taskName); + }); +}); diff --git a/e2e/process-services/task-details-form.e2e.ts b/e2e/process-services/task-details-form.e2e.ts index 0360ad12b0..d2de86b5ce 100644 --- a/e2e/process-services/task-details-form.e2e.ts +++ b/e2e/process-services/task-details-form.e2e.ts @@ -27,11 +27,13 @@ import { FiltersPage } from '../pages/adf/process-services/filters.page'; import { TaskDetailsPage } from '../pages/adf/process-services/task-details.page'; import { TasksListPage } from '../pages/adf/process-services/tasks-list.page'; import CONSTANTS = require('../util/constants'); +import { TasksPage } from '../pages/adf/process-services/tasks.page'; describe('Task Details - Form', () => { const loginPage = new LoginPage(); const tasksListPage = new TasksListPage(); const taskDetailsPage = new TaskDetailsPage(); + const taskPage = new TasksPage(); const filtersPage = new FiltersPage(); const widget = new Widget(); let task, otherTask, user, newForm, attachedForm, otherAttachedForm; @@ -373,5 +375,35 @@ describe('Task Details - Form', () => { await widget.tab().checkTabIsDisplayedByLabel(tab.tabWithFields); await widget.tab().checkTabIsDisplayedByLabel(tab.tabFieldValue); }); + + it('[C212922] Should a User task form be refreshed, saved or completed.', async () => { + await appActions.startProcess(this.alfrescoJsApi, app, app.processName); + + await filtersPage.goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); + await tasksListPage.checkTaskListIsLoaded(); + + await tasksListPage.selectRow(app.taskName); + await expect(await taskDetailsPage.getParentName()).toEqual(app.processName); + + await widget.textWidget().isWidgetVisible(app.form_fields.form_fieldId); + await widget.textWidget().setValue(app.form_fields.form_fieldId, 'value'); + + await taskPage.formFields().refreshForm(); + + await widget.textWidget().isWidgetVisible(app.form_fields.form_fieldId); + await expect(await widget.textWidget().getFieldValue(app.form_fields.form_fieldId)).toEqual(''); + + await widget.textWidget().setValue(app.form_fields.form_fieldId, 'value'); + await taskPage.taskDetails().saveTaskForm(); + + await filtersPage.goToFilter(CONSTANTS.TASK_FILTERS.COMPLETED_TASKS); + await tasksListPage.checkTaskListIsLoaded(); + + await filtersPage.goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); + await tasksListPage.checkTaskListIsLoaded(); + await expect(await widget.textWidget().getFieldValue(app.form_fields.form_fieldId)).toEqual('value'); + + await taskDetailsPage.clickCompleteFormTask(); + }); }); }); diff --git a/e2e/process-services/widgets/dynamic-table-widget.e2e.ts b/e2e/process-services/widgets/dynamic-table-widget.e2e.ts index 5314473532..43ce6ebd1f 100644 --- a/e2e/process-services/widgets/dynamic-table-widget.e2e.ts +++ b/e2e/process-services/widgets/dynamic-table-widget.e2e.ts @@ -22,15 +22,22 @@ import { LoginPage, BrowserActions, Widget } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasks.page'; import CONSTANTS = require('../../util/constants'); import { browser } from 'protractor'; +import { NavigationBarPage } from '../../pages/adf/navigation-bar.page'; describe('Dynamic Table widget ', () => { const loginPage = new LoginPage(); - let processUserModel; const taskPage = new TasksPage(); const widget = new Widget(); - let alfrescoJsApi; const appsActions = new AppsActions(); + const users = new UsersActions(); + const navigationBarPage = new NavigationBarPage(); + const alfrescoJsApi = new AlfrescoApi({ + provider: 'BPM', + hostBpm: browser.params.testConfig.adf_aps.host + }); + + let processUserModel; let appModel; let deployedApp, process; @@ -38,27 +45,16 @@ describe('Dynamic Table widget ', () => { const app = browser.params.resources.Files.WIDGET_CHECK_APP.DYNAMIC_TABLE; beforeAll(async () => { - const users = new UsersActions(); - - alfrescoJsApi = new AlfrescoApi({ - provider: 'BPM', - hostBpm: browser.params.testConfig.adf_aps.host - }); - await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); - processUserModel = await users.createTenantAndUser(alfrescoJsApi); await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, browser.params.resources.Files.WIDGET_CHECK_APP.file_location); const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); - deployedApp = appDefinitions.data.find((currentApp) => { - return currentApp.modelId === appModel.id; - }); + deployedApp = appDefinitions.data.find((currentApp) => currentApp.modelId === appModel.id); process = await appsActions.startProcess(alfrescoJsApi, appModel, app.processName); await loginPage.loginToProcessServicesUsingUserModel(processUserModel); - }); beforeEach(async () => { @@ -72,7 +68,7 @@ describe('Dynamic Table widget ', () => { await alfrescoJsApi.activiti.processApi.deleteProcessInstance(process.id); await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); await alfrescoJsApi.activiti.adminTenantsApi.deleteTenant(processUserModel.tenantId); - + await navigationBarPage.clickLogoutButton(); }); it('[C276729] Should be possible to set visibility properties for Dynamic Table', async () => { @@ -82,7 +78,7 @@ describe('Dynamic Table widget ', () => { }); it('[C279349] Should be able to have a Date Time widget in a Dynamic Table widget', async () => { - await widget.dynamicTable().clickAddButton(); + await widget.dynamicTable().clickAddRow(); await widget.dateTimeWidget().openDatepicker(app.FIELD.dateTime_input_id); await widget.dateTimeWidget().selectDay('10'); await widget.dateTimeWidget().selectHour('8'); @@ -95,50 +91,38 @@ describe('Dynamic Table widget ', () => { }); describe('with People Widget App', () => { - const app = browser.params.resources.Files.WIDGET_CHECK_APP.DYNAMIC_TABLE_USERS; beforeAll(async () => { - const users = new UsersActions(); - - alfrescoJsApi = new AlfrescoApi({ - provider: 'BPM', - hostBpm: browser.params.testConfig.adf_aps.host - }); - await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); - processUserModel = await users.createTenantAndUser(alfrescoJsApi); await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, browser.params.resources.Files.WIDGET_CHECK_APP.file_location); const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); - deployedApp = appDefinitions.data.find((currentApp) => { - return currentApp.modelId === appModel.id; - }); + deployedApp = appDefinitions.data.find((currentApp) => currentApp.modelId === appModel.id); process = await appsActions.startProcess(alfrescoJsApi, appModel, app.processName); await loginPage.loginToProcessServicesUsingUserModel(processUserModel); - - }); - - beforeEach(async () => { - const urlToNavigateTo = `${browser.params.testConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; - await BrowserActions.getUrl(urlToNavigateTo); - await taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); - await taskPage.formFields().checkFormIsDisplayed(); }); afterAll(async () => { await alfrescoJsApi.activiti.processApi.deleteProcessInstance(process.id); await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); await alfrescoJsApi.activiti.adminTenantsApi.deleteTenant(processUserModel.tenantId); + await navigationBarPage.clickLogoutButton(); + }); + beforeEach(async () => { + const urlToNavigateTo = `${browser.params.testConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + await BrowserActions.getUrl(urlToNavigateTo); + await taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); + await taskPage.tasksListPage().checkTaskListIsLoaded(); + await taskPage.formFields().checkFormIsDisplayed(); }); it('[C260407] Should be able to add/delete/update row in Dynamic Table widget', async () => { - - await widget.dynamicTable().clickAddRow(); + await widget.dynamicTable().clickAddRow(app.FIELD.dynamic_table_id); await widget.dynamicTable().setDatatableInput('User1'); await widget.dynamicTable().clickSaveButton(); await expect(await widget.dynamicTable().getTableRowText(0)).toEqual('User1'); @@ -154,10 +138,65 @@ describe('Dynamic Table widget ', () => { await widget.dynamicTable().clickSaveButton(); await expect(await widget.dynamicTable().getTableRowText(0)).toEqual('User2'); - await widget.dynamicTable().clickAddRow(); + await widget.dynamicTable().clickAddRow(app.FIELD.dynamic_table_id); await widget.dynamicTable().setDatatableInput('User3'); await widget.dynamicTable().clickCancelButton(); await widget.dynamicTable().checkTableRowIsNotVisible(1); }); }); + + describe('Custom validation', () => { + + const app = browser.params.resources.Files.WIDGET_CHECK_APP; + + beforeAll(async () => { + await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); + processUserModel = await users.createTenantAndUser(alfrescoJsApi); + + await alfrescoJsApi.login(processUserModel.email, processUserModel.password); + const application = await appsActions.importPublishDeployApp(alfrescoJsApi, app.file_location); + + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + deployedApp = appDefinitions.data.find((currentApp) => currentApp.modelId === application.id); + process = await appsActions.startProcess(alfrescoJsApi, application, app.CUSTOM_VALIDATOR.processName); + }); + + afterAll(async () => { + await alfrescoJsApi.activiti.processApi.deleteProcessInstance(process.id); + await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); + await alfrescoJsApi.activiti.adminTenantsApi.deleteTenant(processUserModel.tenantId); + }); + + beforeEach(async () => { + await loginPage.loginToProcessServicesUsingUserModel(processUserModel); + const urlToNavigateTo = `${browser.params.testConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks`; + await BrowserActions.getUrl(urlToNavigateTo); + await taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); + await taskPage.tasksListPage().checkTaskListIsLoaded(); + await taskPage.formFields().checkFormIsDisplayed(); + }); + + it('[C260437] Customised validator', async () => { + await widget.dynamicTable().clickAddRow(); + await widget.dynamicTable().setDatatableInput('admin', app.CUSTOM_VALIDATOR.FIELD.NAME); + await widget.dynamicTable().clickSaveButton(); + await expect(await widget.dynamicTable().checkErrorMessage()).toBe('Sorry, wrong value. You cannot use "admin".'); + + await widget.dynamicTable().setDatatableInput('name', app.CUSTOM_VALIDATOR.FIELD.NAME); + await widget.dynamicTable().clickSaveButton(); + await expect(await widget.dynamicTable().checkErrorMessage()).toBe('Field \'Id\' is required.'); + + await widget.dynamicTable().setDatatableInput('id', app.CUSTOM_VALIDATOR.FIELD.ID); + await widget.dynamicTable().clickSaveButton(); + await expect(await widget.dynamicTable().checkErrorMessage()).toBe('Field \'Number\' is required.' ); + + await widget.dynamicTable().setDatatableInput('12', app.CUSTOM_VALIDATOR.FIELD.NUM); + await widget.dynamicTable().clickSaveButton(); + await expect(await widget.dynamicTable().checkErrorMessage()).toBe('Field \'Address\' is required.'); + + await widget.dynamicTable().setDatatableInput('address', app.CUSTOM_VALIDATOR.FIELD.ADDRESS); + await widget.dynamicTable().clickSaveButton(); + await taskPage.taskDetails().clickCompleteFormTask(); + }); + }); }); diff --git a/e2e/process-services/widgets/people-group-widget.e2e.ts b/e2e/process-services/widgets/people-group-widget.e2e.ts new file mode 100644 index 0000000000..b28ab71d41 --- /dev/null +++ b/e2e/process-services/widgets/people-group-widget.e2e.ts @@ -0,0 +1,152 @@ +/*! + * @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 { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { AppsActions } from '../../actions/APS/apps.actions'; +import { UsersActions } from '../../actions/users.actions'; +import { LoginPage, StringUtil, Widget } from '@alfresco/adf-testing'; +import { TasksPage } from '../../pages/adf/process-services/tasks.page'; +import { browser } from 'protractor'; +import { User } from '../../models/APS/user'; +import { NavigationBarPage } from '../../pages/adf/navigation-bar.page'; +import CONSTANTS = require('../../util/constants'); + +describe('People and Group widget', () => { + + const loginPage = new LoginPage(); + const taskPage = new TasksPage(); + const navigationBarPage = new NavigationBarPage(); + const widget = new Widget(); + const usersActions = new UsersActions(); + const alfrescoJsApi = new AlfrescoApi({ + provider: 'BPM', + hostBpm: browser.params.testConfig.adf_aps.host + }); + + const app = browser.params.resources.Files.MORE_WIDGETS; + let user: User; + + beforeAll(async () => { + const appsActions = new AppsActions(); + await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); + user = await usersActions.createTenantAndUser(alfrescoJsApi); + await createGroupAndUsers(user.tenantId); + + await alfrescoJsApi.login(user.email, user.password); + try { + await appsActions.importPublishDeployApp(alfrescoJsApi, app.file_location, { renewIdmEntries: true }); + } catch (e) { console.error('failed to deploy the application'); } + await loginPage.loginToProcessServicesUsingUserModel(user); + }); + + afterAll(async () => { + await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); + await alfrescoJsApi.activiti.adminTenantsApi.deleteTenant(user.tenantId); + }); + + beforeEach(async () => { + await (await navigationBarPage.navigateToProcessServicesPage()).goToTaskApp(); + await taskPage.tasksListPage().checkTaskListIsLoaded(); + }); + + it('[C275715] Add group widget - Visibility and group restriction', async () => { + const name = 'group visibility task'; + const groupVisibilityForm = app.ADD_GROUP_VISIBILITY; + await taskPage.createTask({name, formName: groupVisibilityForm.formName}); + await expect(await taskPage.taskDetails().getTitle()).toEqual('Activities'); + + await taskPage.formFields().checkWidgetIsHidden(groupVisibilityForm.FIELD.widget_id); + await widget.checkboxWidget().clickCheckboxInput(groupVisibilityForm.FIELD.checkbox_id); + await taskPage.formFields().checkWidgetIsVisible(groupVisibilityForm.FIELD.widget_id); + + await widget.groupWidget().insertGroup(groupVisibilityForm.FIELD.widget_id, groupVisibilityForm.searchTerm); + await widget.groupWidget().checkDropDownListIsDisplayed(); + await expect(await widget.groupWidget().getDropDownList()).toEqual([ 'Heros', 'Users' ]); + await widget.groupWidget().selectGroupFromDropDown('Users'); + await taskPage.taskDetails().clickCompleteFormTask(); + }); + + it('[C275716] Add group widget - sub group restrictions', async () => { + const name = 'group widget - subgroup restriction'; + const subgroupFrom = app.ADD_GROUP_AND_SUBGROUP_RESTRICTION; + await taskPage.createTask({name, formName: subgroupFrom.formName}); + await expect(await taskPage.taskDetails().getTitle()).toEqual('Activities'); + + await taskPage.formFields().checkWidgetIsHidden(subgroupFrom.FIELD.widget_id); + await widget.checkboxWidget().clickCheckboxInput(subgroupFrom.FIELD.checkbox_id); + await taskPage.formFields().checkWidgetIsVisible(subgroupFrom.FIELD.widget_id); + + await widget.groupWidget().insertGroup(subgroupFrom.FIELD.widget_id, subgroupFrom.searchTerm); + await widget.groupWidget().checkDropDownListIsDisplayed(); + const suggestions = await widget.groupWidget().getDropDownList(); + await expect(suggestions.sort()).toEqual(getSubGroupsName().sort()); + await widget.groupWidget().selectGroupFromDropDown(getSubGroupsName()[0]); + await taskPage.taskDetails().clickCompleteFormTask(); + + await taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.COMPLETED_TASKS); + await taskPage.tasksListPage().checkTaskListIsLoaded(); + + await taskPage.tasksListPage().selectRow(name); + await widget.groupWidget().checkGroupFieldIsDisplayed(); + await expect(await widget.groupWidget().getFieldValue(subgroupFrom.FIELD.widget_id)).toBe('Heros'); + }); + + it('[C275714] Add people widget - group restrictions', async () => { + const name = 'people widget - group restrictions'; + const peopleWidget = app.ADD_PEOPLE_AND_GROUP_RESTRICTION; + await taskPage.createTask({name, formName: peopleWidget.formName}); + await expect(await taskPage.taskDetails().getTitle()).toEqual('Activities'); + + await taskPage.formFields().checkWidgetIsHidden(peopleWidget.FIELD.widget_id); + await widget.checkboxWidget().clickCheckboxInput(peopleWidget.FIELD.checkbox_id); + await taskPage.formFields().checkWidgetIsVisible(peopleWidget.FIELD.widget_id); + + await widget.peopleWidget().insertUser(peopleWidget.FIELD.widget_id, peopleWidget.searchTerm); + await widget.peopleWidget().checkDropDownListIsDisplayed(); + const suggestions = await widget.peopleWidget().getDropDownList(); + await expect(suggestions.sort()).toEqual(getGroupMembers().sort()); + await widget.peopleWidget().selectUserFromDropDown(getGroupMembers()[0]); + await taskPage.taskDetails().clickCompleteFormTask(); + }); + + async function createGroupAndUsers(tenantId) { + await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); + + try { + const happyUsers: any[] = await Promise.all(app.groupUser.map(happyUser => + usersActions.createApsUserWithName(alfrescoJsApi, tenantId, StringUtil.generateRandomString(), happyUser.firstName, happyUser.lastName))); + const subgroupUser = await usersActions.createApsUserWithName( + alfrescoJsApi, tenantId, StringUtil.generateRandomString(), app.subGroupUser.firstName, app.subGroupUser.lastName); + + const group = await alfrescoJsApi.activiti.adminGroupsApi.createNewGroup({ name: app.group.name, tenantId, type: 1 }); + await Promise.all(happyUsers.map(happyUser => alfrescoJsApi.activiti.adminGroupsApi.addGroupMember(group.id, happyUser.id))); + + const subgroups: any[] = await Promise.all(getSubGroupsName().map((name) => + alfrescoJsApi.activiti.adminGroupsApi.createNewGroup({ name, tenantId , type: 1, parentGroupId: group.id }))); + await Promise.all(subgroups.map((subgroup) => alfrescoJsApi.activiti.adminGroupsApi.addGroupMember(subgroup.id, subgroupUser.id))); + + } catch (e) {} + } + + function getSubGroupsName() { + return app.group.subgroup.map(subgroup => subgroup.name); + } + + function getGroupMembers() { + return app.groupUser.map(groupUser => `${groupUser.firstName} ${groupUser.lastName}`); + } +}); diff --git a/e2e/process-services/widgets/typeahead-widget.e2e.ts b/e2e/process-services/widgets/typeahead-widget.e2e.ts new file mode 100644 index 0000000000..b582b0f688 --- /dev/null +++ b/e2e/process-services/widgets/typeahead-widget.e2e.ts @@ -0,0 +1,90 @@ +/*! + * @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 { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { AppsActions } from '../../actions/APS/apps.actions'; +import { UsersActions } from '../../actions/users.actions'; +import { LoginPage, Widget } from '@alfresco/adf-testing'; +import { TasksPage } from '../../pages/adf/process-services/tasks.page'; +import { browser } from 'protractor'; +import { User } from '../../models/APS/user'; +import { NavigationBarPage } from '../../pages/adf/navigation-bar.page'; +import CONSTANTS = require('../../util/constants'); + +describe('Typeahead widget', () => { + + const loginPage = new LoginPage(); + const taskPage = new TasksPage(); + const navigationBarPage = new NavigationBarPage(); + const widget = new Widget(); + const usersActions = new UsersActions(); + const alfrescoJsApi = new AlfrescoApi({ + provider: 'BPM', + hostBpm: browser.params.testConfig.adf_aps.host + }); + + const app = browser.params.resources.Files.WIDGET_CHECK_APP; + let user: User; + + beforeAll(async () => { + const appsActions = new AppsActions(); + await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); + user = await usersActions.createTenantAndUser(alfrescoJsApi); + + await alfrescoJsApi.login(user.email, user.password); + await appsActions.importPublishDeployApp(alfrescoJsApi, app.file_location, { renewIdmEntries: true }); + await loginPage.loginToProcessServicesUsingUserModel(user); + }); + + afterAll(async () => { + await alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword); + await alfrescoJsApi.activiti.adminTenantsApi.deleteTenant(user.tenantId); + }); + + beforeEach(async () => { + await (await navigationBarPage.navigateToProcessServicesPage()).goToTaskApp(); + await taskPage.tasksListPage().checkTaskListIsLoaded(); + }); + + it('[C307988] Type ahead form control should work for URLs', async () => { + const name = 'typahead widget task'; + const typeaheadWidget = app.TYPE_AHEAD_WIDGET; + await taskPage.createTask({name, formName: typeaheadWidget.formName}); + await expect(await taskPage.taskDetails().getTitle()).toEqual('Activities'); + + await widget.typeahedWidget().checkTypeaheadFieldIsDisplayed(); + await widget.typeahedWidget().fillTypeaheadField(typeaheadWidget.case1.searchTerm); + await widget.typeahedWidget().checkDropDownListIsDisplayed(); + let suggestions = await widget.typeahedWidget().getDropDownList(); + await expect(suggestions.sort()).toEqual(typeaheadWidget.case1.result.sort()); + + await widget.typeahedWidget().fillTypeaheadField(typeaheadWidget.case2.searchTerm); + await widget.typeahedWidget().checkDropDownListIsDisplayed(); + suggestions = await widget.typeahedWidget().getDropDownList(); + await expect(suggestions.sort()).toEqual(typeaheadWidget.case2.result); + + await widget.typeahedWidget().selectOptionFromDropdown(); + await taskPage.taskDetails().clickCompleteFormTask(); + + await taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.COMPLETED_TASKS); + await taskPage.tasksListPage().checkTaskListIsLoaded(); + + await taskPage.tasksListPage().selectRow(name); + await widget.typeahedWidget().checkTypeaheadFieldIsDisplayed(); + await expect(await widget.typeahedWidget().getFieldValue('1583773306434')).toBe(typeaheadWidget.case2.result[0]); + }); +}); diff --git a/e2e/resources/apps/More Widgets.zip b/e2e/resources/apps/More Widgets.zip new file mode 100644 index 0000000000..94d7f8f4e0 Binary files /dev/null and b/e2e/resources/apps/More Widgets.zip differ diff --git a/e2e/resources/apps/Stencil_app.zip b/e2e/resources/apps/Stencil_app.zip new file mode 100644 index 0000000000..163dd489b2 Binary files /dev/null and b/e2e/resources/apps/Stencil_app.zip differ diff --git a/e2e/resources/apps/WidgetApps.zip b/e2e/resources/apps/WidgetApps.zip index a45d615010..97e19e4d7b 100644 Binary files a/e2e/resources/apps/WidgetApps.zip and b/e2e/resources/apps/WidgetApps.zip differ diff --git a/e2e/util/resources.js b/e2e/util/resources.js index 49cd740d71..ae29745c13 100644 --- a/e2e/util/resources.js +++ b/e2e/util/resources.js @@ -296,7 +296,6 @@ exports.Files = { checkbox_id: "viewtable", dateTime_input_id: "datetime", row: "label-row-0" - } }, @@ -305,6 +304,7 @@ exports.Files = { title: "ALL_WIDGETS", processName: "ALL_WIDGETS", FIELD: { + dynamic_table_id: "dynamictable", dynamic_table_age_id: "label2", dynamic_table_date_id: "label", checkbox_id: "viewtable", @@ -343,9 +343,88 @@ exports.Files = { user_id: "adf-people-search-input", checkbox_id: "check" } + }, + + CUSTOM_VALIDATOR: { + formName: "dynamic-table-custom-validation", + title: "dynamic-table-custom-validation", + processName: "dynamic-table-custom-validation", + FIELD: { + NAME: "name", + ID: "id", + NUM: "num", + ADDRESS: "address", + ROW: "label-row-0" + } + }, + + TYPE_AHEAD_WIDGET: { + formName: "Type ahead widget", + title: "type-ahead-process", + processName: "type-ahead-process", + FIELD: { + widget_id: "Label" + }, + case1: { + searchTerm: 'Customer', + result: [ + '123456789 - Customer Number One', + '987654321 - Customer Number Two', + '919191919191 - Customer Number Three', + '91919191 - Customer Number X' + ] + }, + case2: { + searchTerm: 'One', + result: [ '123456789 - Customer Number One' ] + } } }, + MORE_WIDGETS: { + file_location: "/resources/apps/More Widgets.zip", + title: "More Widgets", + group: { name: "Users", subgroup: [ { name: "Heros" }, { name: "Villains" }] }, + subGroupUser: { firstName: "Hero", lastName: "User" } , + groupUser: [ + { firstName: "Hero", lastName: "Audience" }, + { firstName: "Villain", lastName: "Audience" }, + ], + + ADD_PEOPLE_AND_GROUP_RESTRICTION: { + formName: 'People widget - group restriction', + FIELD: { + widget_id: 'Finally', + checkbox_id: 'check' + }, + searchTerm: 'Audience' + }, + + ADD_GROUP_VISIBILITY: { + formName: "Group widget - visibility", + FIELD: { + widget_id: 'Dreamteam', + checkbox_id: 'check' + }, + searchTerm: 'e' + }, + + ADD_GROUP_AND_SUBGROUP_RESTRICTION: { + formName: "Group widget - subgroup restriction", + FIELD: { + widget_id: 'Dreamteam', + checkbox_id: 'check' + }, + searchTerm: 's' + } + }, + + STENCIL_PROCESS: { + file_location: "/resources/apps/Stencil_app.zip", + processName: 'stencil_process', + taskName: 'stencil task' + }, + DYNAMIC_TABLE_APP: { file_location: "/resources/apps/Dynamic Table App.zip", title: "Dynamic Table App", diff --git a/lib/core/form/components/widgets/functional-group/functional-group.widget.html b/lib/core/form/components/widgets/functional-group/functional-group.widget.html index 4518018694..6ace4cb2aa 100644 --- a/lib/core/form/components/widgets/functional-group/functional-group.widget.html +++ b/lib/core/form/components/widgets/functional-group/functional-group.widget.html @@ -6,6 +6,7 @@ - - {{item.name}} + {{item.name}} diff --git a/lib/core/form/components/widgets/typeahead/typeahead.widget.html b/lib/core/form/components/widgets/typeahead/typeahead.widget.html index c3d3874f9b..19a3045f78 100644 --- a/lib/core/form/components/widgets/typeahead/typeahead.widget.html +++ b/lib/core/form/components/widgets/typeahead/typeahead.widget.html @@ -13,11 +13,12 @@ (ngModelChange)="validate()" (keyup)="onKeyUp($event)" [disabled]="field.readOnly" + data-automation-id="adf-typeahed-search-input" placeholder="{{field.placeholder}}" [matAutocomplete]="auto"> - - {{item.name}} + + {{item.name}} diff --git a/lib/core/form/components/widgets/typeahead/typeahead.widget.spec.ts b/lib/core/form/components/widgets/typeahead/typeahead.widget.spec.ts index 66b53b7b4e..6d4080de74 100644 --- a/lib/core/form/components/widgets/typeahead/typeahead.widget.spec.ts +++ b/lib/core/form/components/widgets/typeahead/typeahead.widget.spec.ts @@ -304,9 +304,9 @@ describe('TypeaheadWidgetComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('[id="typeahead-name_option_1"]'))).not.toBeNull(); - expect(fixture.debugElement.query(By.css('[id="typeahead-name_option_2"]'))).not.toBeNull(); - expect(fixture.debugElement.query(By.css('[id="typeahead-name_option_3"]'))).not.toBeNull(); + expect(fixture.debugElement.query(By.css('[id="adf-typeahed-widget-user-0"] span'))).not.toBeNull(); + expect(fixture.debugElement.query(By.css('[id="adf-typeahed-widget-user-1"] span'))).not.toBeNull(); + expect(fixture.debugElement.query(By.css('[id="adf-typeahed-widget-user-2"] span'))).not.toBeNull(); }); })); @@ -321,7 +321,7 @@ describe('TypeaheadWidgetComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('[id="typeahead-name_option_1"]'))).not.toBeNull(); + expect(fixture.debugElement.query(By.css('[id="adf-typeahed-widget-user-0"] span'))).not.toBeNull(); typeaheadHTMLElement.focus(); typeaheadWidgetComponent.value = ''; typeaheadHTMLElement.dispatchEvent(new Event('keyup')); @@ -329,7 +329,7 @@ describe('TypeaheadWidgetComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('[id="typeahead-name_option_1"]'))).toBeNull(); + expect(fixture.debugElement.query(By.css('[id="adf-typeahed-widget-user-0"] span'))).toBeNull(); }); }); })); @@ -377,9 +377,9 @@ describe('TypeaheadWidgetComponent', () => { typeaheadWidgetComponent.onKeyUp(keyboardEvent); fixture.detectChanges(); fixture.whenStable().then(() => { - expect(fixture.debugElement.queryAll(By.css('[id="mat-option-1"]'))).toBeDefined(); - expect(fixture.debugElement.queryAll(By.css('[id="mat-option-2"]'))).toBeDefined(); - expect(fixture.debugElement.queryAll(By.css('[id="mat-option-3"]'))).toBeDefined(); + expect(fixture.debugElement.queryAll(By.css('[id="adf-typeahed-widget-user-0"] span'))).toBeDefined(); + expect(fixture.debugElement.queryAll(By.css('[id="adf-typeahed-widget-user-1"] span'))).toBeDefined(); + expect(fixture.debugElement.queryAll(By.css('[id="adf-typeahed-widget-user-2"] span'))).toBeDefined(); }); })); }); diff --git a/lib/testing/src/lib/core/pages/form/widgets/dynamic-table-widget.page.ts b/lib/testing/src/lib/core/pages/form/widgets/dynamic-table-widget.page.ts index 6edad3bbd3..85e39aebb5 100644 --- a/lib/testing/src/lib/core/pages/form/widgets/dynamic-table-widget.page.ts +++ b/lib/testing/src/lib/core/pages/form/widgets/dynamic-table-widget.page.ts @@ -25,10 +25,8 @@ export class DynamicTableWidgetPage { labelLocator: Locator = by.css('dynamic-table-widget div div'); columnNameLocator: Locator = by.css('table[id*="dynamic-table"] th'); - addButton: ElementFinder = element(by.id('label-add-row')); cancelButton: ElementFinder = element(by.cssContainingText('button span', 'Cancel')); editButton: ElementFinder = element(by.cssContainingText('button span', 'edit')); - addRow: ElementFinder = element(by.id('dynamictable-add-row')); columnDateTime: ElementFinder = element(by.id('columnDateTime')); columnDate: ElementFinder = element(by.id('columnDate')); calendarHeader: ElementFinder = element(by.css('div[class="mat-datetimepicker-calendar-header-date-time"]')); @@ -37,7 +35,6 @@ export class DynamicTableWidgetPage { errorMessage: ElementFinder = element(by.css('div[class="adf-error-text"]')); dateWidget: ElementFinder = element.all(by.css('mat-datepicker-toggle button')).first(); tableRow: ElementArrayFinder = element.all(by.css('tbody tr')); - dataTableInput: ElementFinder = element(by.id('id')); getFieldLabel(fieldId): Promise { return this.formFields.getFieldLabel(fieldId, this.labelLocator); @@ -47,12 +44,9 @@ export class DynamicTableWidgetPage { return this.formFields.getFieldText(fieldId, this.columnNameLocator); } - async clickAddButton(): Promise { - await BrowserActions.click(this.addButton); - } - - async clickAddRow(): Promise { - await BrowserActions.click(this.addRow); + async clickAddRow(id?: string): Promise { + const rowButton = element(by.id(`${id ? id : 'label'}-add-row`)); + await BrowserActions.click(rowButton); } async clickTableRow(rowNumber): Promise { @@ -68,11 +62,11 @@ export class DynamicTableWidgetPage { await BrowserActions.click(this.cancelButton); } - async setDatatableInput(text): Promise { - await BrowserVisibility.waitUntilElementIsVisible(this.dataTableInput); - await this.dataTableInput.clear(); - await this.dataTableInput.sendKeys(text); - } + async setDatatableInput(text, id = 'id'): Promise { + const dataTableInput: ElementFinder = element(by.id(id)); + await BrowserVisibility.waitUntilElementIsVisible(dataTableInput); + await BrowserActions.clearSendKeys(dataTableInput, text); + } async getTableRowText(rowNumber): Promise { const tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); diff --git a/lib/testing/src/lib/core/pages/form/widgets/group-widget.page.ts b/lib/testing/src/lib/core/pages/form/widgets/group-widget.page.ts new file mode 100644 index 0000000000..35d1ffffc4 --- /dev/null +++ b/lib/testing/src/lib/core/pages/form/widgets/group-widget.page.ts @@ -0,0 +1,78 @@ +/*! + * @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 { FormFields } from '../form-fields'; +import { by, element, ElementFinder, Locator } from 'protractor'; +import { BrowserVisibility, BrowserActions } from '../../../utils/public-api'; + +export class GroupWidgetPage { + + groupField: ElementFinder = element(by.css('input[data-automation-id="adf-group-search-input"]')); + firstResult: ElementFinder = element(by.id('adf-group-widget-user-0')); + formFields: FormFields = new FormFields(); + groupDropDownList: Locator = by.css('.mat-autocomplete-panel'); + + getFieldLabel(fieldId): Promise { + return this.formFields.getFieldLabel(fieldId); + } + + getFieldValue(fieldId): Promise { + return this.formFields.getFieldValue(fieldId); + } + + getFieldText(fieldId): Promise { + return this.formFields.getFieldText(fieldId); + } + + insertGroup(fieldId, value): Promise { + return this.formFields.setValueInInputById(fieldId, value); + } + + async checkDropDownListIsDisplayed(): Promise { + await BrowserVisibility.waitUntilElementIsVisible(element(this.groupDropDownList)); + } + + async checkGroupIsListed(group): Promise { + const groupElement = element(by.cssContainingText('[id="adf-group-label-name"]', group)); + await BrowserVisibility.waitUntilElementIsVisible(groupElement); + } + + async getDropDownList(): Promise { + const user = by.css('[id="adf-group-label-name"]'); + await BrowserVisibility.waitUntilElementIsVisible(element(user)); + return element.all(user).map((elementFinder) => elementFinder.getText()); + } + + async selectGroupFromDropDown(groupName): Promise { + const group = element(by.cssContainingText('[id="adf-group-label-name"]', groupName)); + await BrowserActions.click(group); + } + + async checkGroupFieldIsDisplayed(): Promise { + await BrowserVisibility.waitUntilElementIsVisible(this.groupField); + } + + async fillGroupField(value): Promise { + await BrowserVisibility.waitUntilElementIsClickable(this.groupField); + await this.groupField.sendKeys(value); + } + + async selectGroupFromDropdown(): Promise { + await BrowserVisibility.waitUntilElementIsVisible(this.firstResult); + await BrowserActions.click(this.firstResult); + } +} diff --git a/lib/testing/src/lib/core/pages/form/widgets/people-widget.page.ts b/lib/testing/src/lib/core/pages/form/widgets/people-widget.page.ts index 14a63ac273..a563343948 100644 --- a/lib/testing/src/lib/core/pages/form/widgets/people-widget.page.ts +++ b/lib/testing/src/lib/core/pages/form/widgets/people-widget.page.ts @@ -58,6 +58,13 @@ export class PeopleWidgetPage { await BrowserActions.click(user); } + async getDropDownList(): Promise { + await this.checkDropDownListIsDisplayed(); + const users = by.css('.adf-people-label-name'); + await BrowserVisibility.waitUntilElementIsVisible(element(users)); + return element.all(users).map((elementFinder) => elementFinder.getText()); + } + async checkPeopleFieldIsDisplayed(): Promise { await BrowserVisibility.waitUntilElementIsVisible(this.peopleField); } diff --git a/lib/testing/src/lib/core/pages/form/widgets/typeahead-widget.page.ts b/lib/testing/src/lib/core/pages/form/widgets/typeahead-widget.page.ts new file mode 100644 index 0000000000..2432296c04 --- /dev/null +++ b/lib/testing/src/lib/core/pages/form/widgets/typeahead-widget.page.ts @@ -0,0 +1,78 @@ +/*! + * @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 { FormFields } from '../form-fields'; +import { by, element, ElementFinder, Locator } from 'protractor'; +import { BrowserVisibility, BrowserActions } from '../../../utils/public-api'; + +export class TypeaheadWidgetPage { + + field: ElementFinder = element(by.css('input[data-automation-id="adf-typeahed-search-input"]')); + firstResult: ElementFinder = element(by.id('adf-typeahed-widget-user-0')); + formFields: FormFields = new FormFields(); + groupDropDownList: Locator = by.css('.mat-autocomplete-panel'); + + getFieldLabel(fieldId): Promise { + return this.formFields.getFieldLabel(fieldId); + } + + getFieldValue(fieldId): Promise { + return this.formFields.getFieldValue(fieldId); + } + + getFieldText(fieldId): Promise { + return this.formFields.getFieldText(fieldId); + } + + insertValue(fieldId, value): Promise { + return this.formFields.setValueInInputById(fieldId, value); + } + + async checkDropDownListIsDisplayed(): Promise { + await BrowserVisibility.waitUntilElementIsVisible(element(this.groupDropDownList)); + } + + async checkOptionIsListed(option): Promise { + const optionElement = element(by.cssContainingText('[id="adf-typeahed-label-name"]', option)); + await BrowserVisibility.waitUntilElementIsVisible(optionElement); + } + + async getDropDownList(): Promise { + const option = by.css('[id="adf-typeahed-label-name"]'); + await BrowserVisibility.waitUntilElementIsVisible(element(option)); + return element.all(option).map((elementFinder) => elementFinder.getText()); + } + + async selectOptionFromDropDown(userName): Promise { + const option = element(by.cssContainingText('[id="adf-typeahed-label-name"]', userName)); + await BrowserActions.click(option); + } + + async checkTypeaheadFieldIsDisplayed(): Promise { + await BrowserVisibility.waitUntilElementIsVisible(this.field); + } + + async fillTypeaheadField(value): Promise { + await BrowserVisibility.waitUntilElementIsClickable(this.field); + await BrowserActions.clearSendKeys(this.field, value); + } + + async selectOptionFromDropdown(): Promise { + await BrowserVisibility.waitUntilElementIsVisible(this.firstResult); + await BrowserActions.click(this.firstResult); + } +} diff --git a/lib/testing/src/lib/core/pages/form/widgets/widget.ts b/lib/testing/src/lib/core/pages/form/widgets/widget.ts index e8a0b176ac..2db2d90f97 100644 --- a/lib/testing/src/lib/core/pages/form/widgets/widget.ts +++ b/lib/testing/src/lib/core/pages/form/widgets/widget.ts @@ -34,6 +34,8 @@ import { ContainerWidgetPage } from './container-widget.page'; import { PeopleWidgetPage } from './people-widget.page'; import { TabPage } from './tab.page'; import { DocumentWidgetPage } from './document-widget.page'; +import { GroupWidgetPage } from './group-widget.page'; +import { TypeaheadWidgetPage } from './typeahead-widget.page'; export class Widget { @@ -109,6 +111,14 @@ export class Widget { return new PeopleWidgetPage(); } + groupWidget(): GroupWidgetPage { + return new GroupWidgetPage(); + } + + typeahedWidget(): TypeaheadWidgetPage { + return new TypeaheadWidgetPage(); + } + tab(): TabPage { return new TabPage(); }