From e96491fe256c713c4e02236867f66b47b8cf6020 Mon Sep 17 00:00:00 2001 From: davidcanonieto Date: Fri, 26 Feb 2021 08:57:27 +0100 Subject: [PATCH] [ACA-4299] Add e2e tests for task counters and notifications (#6726) * [ACA-4299] Add ete tests for task counters and notifications * Fix unit test * Fix update for indirect counter changes --- demo-shell/resources/i18n/en.json | 3 +- demo-shell/src/app/app.module.ts | 11 +- .../cloud/cloud-layout.component.ts | 65 +-------- .../app/services/app-notifications-factory.ts | 22 +++ .../app/services/app-notifications.service.ts | 110 +++++++++++++++ .../task-counters-cloud.e2e.ts | 128 ++++++++++++++++++ .../notification-cloud.service.spec.ts | 28 +++- .../services/notification-cloud.service.ts | 6 +- .../task-filters-cloud.component.spec.ts | 7 +- .../task-filters-cloud.component.ts | 29 ++-- .../services/task-filter-cloud.service.ts | 4 +- .../core/pages/notification-history.page.ts | 5 + .../task-filters-cloud-component.page.ts | 16 ++- package-lock.json | 8 ++ package.json | 1 + 15 files changed, 349 insertions(+), 94 deletions(-) create mode 100644 demo-shell/src/app/services/app-notifications-factory.ts create mode 100644 demo-shell/src/app/services/app-notifications.service.ts create mode 100644 e2e/process-services-cloud/task-counters-cloud.e2e.ts diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json index 37a95b6ae3..ffa0dc8927 100644 --- a/demo-shell/resources/i18n/en.json +++ b/demo-shell/resources/i18n/en.json @@ -219,7 +219,8 @@ "NOTIFICATIONS": { "TASK_ASSIGNED": "{{taskName}} task has been assigned to {{assignee}}", "PROCESS_STARTED": "{{processName}} process has been started", - "TASK_UPDATED": "{{taskName}} task details has been updated" + "TASK_UPDATED": "{{taskName}} task details have been updated", + "TASK_CREATED": "{{taskName}} task was created" }, "FORM-LOADING": { "FORM_DATA": "Form Data", diff --git a/demo-shell/src/app/app.module.ts b/demo-shell/src/app/app.module.ts index e5124a69bf..feb9cfe531 100644 --- a/demo-shell/src/app/app.module.ts +++ b/demo-shell/src/app/app.module.ts @@ -16,7 +16,7 @@ */ import { BrowserModule } from '@angular/platform-browser'; -import { NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FlexLayoutModule } from '@angular/flex-layout'; import { ChartsModule } from 'ng2-charts'; @@ -112,6 +112,8 @@ import localePl from '@angular/common/locales/pl'; import localeFi from '@angular/common/locales/fi'; import localeDa from '@angular/common/locales/da'; import localeSv from '@angular/common/locales/sv'; +import { setupAppNotifications } from './services/app-notifications-factory'; +import { AppNotificationsService } from './services/app-notifications.service'; registerLocaleData(localeFr); registerLocaleData(localeDe); @@ -225,6 +227,13 @@ registerLocaleData(localeSv); name: 'lazy-loading', source: 'resources/lazy-loading' } + }, + AppNotificationsService, + { + provide: APP_INITIALIZER, + useFactory: setupAppNotifications, + deps: [AppNotificationsService], + multi: true } ], bootstrap: [AppComponent] diff --git a/demo-shell/src/app/components/cloud/cloud-layout.component.ts b/demo-shell/src/app/components/cloud/cloud-layout.component.ts index d854a7787d..f3513c1629 100644 --- a/demo-shell/src/app/components/cloud/cloud-layout.component.ts +++ b/demo-shell/src/app/components/cloud/cloud-layout.component.ts @@ -17,23 +17,6 @@ import { Component, OnInit, ViewEncapsulation } from '@angular/core'; import { Router, ActivatedRoute } from '@angular/router'; import { CloudLayoutService } from './services/cloud-layout.service'; -import { NotificationModel, NotificationService } from '@alfresco/adf-core'; -import { map } from 'rxjs/operators'; -import { NotificationCloudService } from '@alfresco/adf-process-services-cloud'; -import { TranslateService } from '@ngx-translate/core'; - -const SUBSCRIPTION_QUERY = ` - subscription { - engineEvents(eventType: [ - PROCESS_STARTED - TASK_ASSIGNED - TASK_UPDATED - ]) { - eventType - entity - } - } -`; @Component({ selector: 'app-cloud-layout', @@ -48,26 +31,13 @@ export class CloudLayoutComponent implements OnInit { constructor( private router: Router, private route: ActivatedRoute, - private cloudLayoutService: CloudLayoutService, - private notificationCloudService: NotificationCloudService, - private notificationService: NotificationService, - private translateService: TranslateService + private cloudLayoutService: CloudLayoutService ) { } ngOnInit() { let root: string = ''; this.route.params.subscribe((params) => { this.appName = params.appName; - this.notificationCloudService.makeGQLQuery( - this.appName, SUBSCRIPTION_QUERY - ) - .pipe(map((events: any) => events.data.engineEvents)) - .subscribe((result) => { - result.map((engineEvent) => { - this.notifyEvent(engineEvent); - - }); - }); }); if (this.route.snapshot && this.route.snapshot.firstChild) { @@ -92,37 +62,4 @@ export class CloudLayoutComponent implements OnInit { onStartProcess() { this.router.navigate([`/cloud/${this.appName}/start-process/`]); } - - notifyEvent(engineEvent) { - let message; - switch (engineEvent.eventType) { - case 'TASK_ASSIGNED': - message = this.translateService.instant('NOTIFICATIONS.TASK_ASSIGNED', - { taskName: engineEvent.entity.name || '', assignee: engineEvent.entity.assignee }); - this.pushNotification(engineEvent, message); - break; - case 'PROCESS_STARTED': - message = this.translateService.instant('NOTIFICATIONS.PROCESS_STARTED', - { processName: engineEvent.entity.name }); - this.pushNotification(engineEvent, message); - break; - case 'TASK_UPDATED': - message = this.translateService.instant('NOTIFICATIONS.TASK_UPDATED', - { taskName: engineEvent.entity.name || '' }); - this.pushNotification(engineEvent, message); - break; - default: - } - } - - pushNotification(engineEvent: any, message: string) { - const notification = { - messages: [message], - icon: 'info', - datetime: new Date(), - initiator: { displayName: engineEvent.entity.initiator || 'System' } - } as NotificationModel; - - this.notificationService.pushToNotificationHistory(notification); - } } diff --git a/demo-shell/src/app/services/app-notifications-factory.ts b/demo-shell/src/app/services/app-notifications-factory.ts new file mode 100644 index 0000000000..71ff181e6a --- /dev/null +++ b/demo-shell/src/app/services/app-notifications-factory.ts @@ -0,0 +1,22 @@ +/*! + * @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 { AppNotificationsService } from './app-notifications.service'; + +export function setupAppNotifications(appNotificationsService: AppNotificationsService) { + return () => appNotificationsService; +} diff --git a/demo-shell/src/app/services/app-notifications.service.ts b/demo-shell/src/app/services/app-notifications.service.ts new file mode 100644 index 0000000000..0574626df2 --- /dev/null +++ b/demo-shell/src/app/services/app-notifications.service.ts @@ -0,0 +1,110 @@ +/*! + * @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 { AppConfigService, NotificationService, NotificationModel, AlfrescoApiService, IdentityUserService } from '@alfresco/adf-core'; +import { NotificationCloudService } from '@alfresco/adf-process-services-cloud'; +import { Injectable } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { map } from 'rxjs/operators'; + +const SUBSCRIPTION_QUERY = ` + subscription { + engineEvents(eventType: [ + PROCESS_STARTED + TASK_ASSIGNED + TASK_UPDATED, + TASK_CREATED + ]) { + eventType + entity + } + } +`; + +@Injectable() +export class AppNotificationsService { + + constructor( + private appConfigService: AppConfigService, + private notificationCloudService: NotificationCloudService, + private notificationService: NotificationService, + private translateService: TranslateService, + private identityUserService: IdentityUserService, + private alfrescoApiService: AlfrescoApiService + ) { + this.alfrescoApiService.alfrescoApiInitialized.subscribe(() => { + const deployedApps = this.appConfigService.get('alfresco-deployed-apps', []); + if (deployedApps?.length) { + deployedApps.forEach((app) => { + this.notificationCloudService + .makeGQLQuery(app.name, SUBSCRIPTION_QUERY) + .pipe(map((events: any) => events.data.engineEvents)) + .subscribe((result) => { + result.map((engineEvent) => this.notifyEvent(engineEvent)); + }); + }); + } + }); + } + + notifyEvent(engineEvent) { + let message; + switch (engineEvent.eventType) { + case 'TASK_ASSIGNED': + message = this.translateService.instant('NOTIFICATIONS.TASK_ASSIGNED', { taskName: engineEvent.entity.name || '', assignee: engineEvent.entity.assignee }); + this.pushNotification(engineEvent, message); + break; + case 'TASK_UPDATED': + message = this.translateService.instant('NOTIFICATIONS.TASK_UPDATED', { taskName: engineEvent.entity.name || '' }); + this.pushNotification(engineEvent, message); + break; + case 'TASK_COMPLETED': + message = this.translateService.instant('NOTIFICATIONS.TASK_COMPLETED', { taskName: engineEvent.entity.name || '' }); + this.pushNotification(engineEvent, message); + break; + case 'TASK_ACTIVATED': + message = this.translateService.instant('NOTIFICATIONS.TASK_ACTIVATED', { taskName: engineEvent.entity.name || '' }); + this.pushNotification(engineEvent, message); + break; + case 'TASK_CANCELLED': + message = this.translateService.instant('NOTIFICATIONS.TASK_CANCELLED', { taskName: engineEvent.entity.name || '' }); + this.pushNotification(engineEvent, message); + break; + case 'TASK_SUSPENDED': + message = this.translateService.instant('NOTIFICATIONS.TASK_SUSPENDED', { taskName: engineEvent.entity.name || '' }); + this.pushNotification(engineEvent, message); + break; + case 'TASK_CREATED': + message = this.translateService.instant('NOTIFICATIONS.TASK_CREATED', { taskName: engineEvent.entity.name || '' }); + this.pushNotification(engineEvent, message); + break; + default: + } + } + + pushNotification(engineEvent: any, message: string) { + if (engineEvent.entity.assignee === this.identityUserService.getCurrentUserInfo().username) { + const notification = { + messages: [message], + icon: 'info', + datetime: new Date(), + initiator: { displayName: engineEvent.entity.initiator || 'System' } + } as NotificationModel; + + this.notificationService.pushToNotificationHistory(notification); + } + } +} diff --git a/e2e/process-services-cloud/task-counters-cloud.e2e.ts b/e2e/process-services-cloud/task-counters-cloud.e2e.ts new file mode 100644 index 0000000000..3ce5e7d864 --- /dev/null +++ b/e2e/process-services-cloud/task-counters-cloud.e2e.ts @@ -0,0 +1,128 @@ +/*! + * @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 { + LoginPage, + TasksService, + ApiService, + AppListCloudPage, + StringUtil, + IdentityService, + GroupIdentityService, + NotificationHistoryPage, + ProcessInstancesService, + ProcessDefinitionsService, + QueryService +} from '@alfresco/adf-testing'; +import { NavigationBarPage } from '../core/pages/navigation-bar.page'; +import { TasksCloudDemoPage } from './pages/tasks-cloud-demo.page'; + +describe('Task counters cloud', () => { + + describe('Task Counters', () => { + + const simpleApp = browser.params.resources.ACTIVITI_CLOUD_APPS.SIMPLE_APP.name; + + const loginSSOPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const appListCloudComponent = new AppListCloudPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); + const notificationHistoryPage = new NotificationHistoryPage(); + const taskFilter = tasksCloudDemoPage.taskFilterCloudComponent; + + const apiService = new ApiService(); + const identityService = new IdentityService(apiService); + const groupIdentityService = new GroupIdentityService(apiService); + const tasksService = new TasksService(apiService); + const processDefinitionService = new ProcessDefinitionsService(apiService); + const processInstancesService = new ProcessInstancesService(apiService); + const queryService = new QueryService(apiService); + + let testUser, groupInfo; + + const createdTaskName = StringUtil.generateRandomString(); + + beforeAll(async () => { + await apiService.loginWithProfile('identityAdmin'); + + testUser = await identityService.createIdentityUserWithRole([identityService.ROLES.ACTIVITI_USER]); + groupInfo = await groupIdentityService.getGroupInfoByGroupName('hr'); + await identityService.addUserToGroup(testUser.idIdentityService, groupInfo.id); + + await apiService.login(testUser.username, testUser.password); + await loginSSOPage.login(testUser.username, testUser.password); + }); + + afterAll(async () => { + await apiService.loginWithProfile('identityAdmin'); + await identityService.deleteIdentityUser(testUser.idIdentityService); + }); + + beforeEach(async () => { + await navigationBarPage.navigateToProcessServicesCloudPage(); + await appListCloudComponent.checkApsContainer(); + await appListCloudComponent.goToApp(simpleApp); + }); + + it('[C593065] Should display notification in counter when process started', async () => { + await taskFilter.checkTaskFilterCounter('my-tasks'); + await expect(await taskFilter.getTaskFilterCounter('my-tasks')).toBe('0'); + + const processDefinition = await processDefinitionService.getProcessDefinitionByName(browser.params.resources.ACTIVITI_CLOUD_APPS.SIMPLE_APP.processes.uploadSingleMultipleFiles, simpleApp); + const processInstance = await processInstancesService.createProcessInstance(processDefinition.entry.key, simpleApp, { 'name': StringUtil.generateRandomString() }); + const task = await queryService.getProcessInstanceTasks(processInstance.entry.id, simpleApp); + await tasksService.claimTask(task.list.entries[0].entry.id, simpleApp); + + await notificationHistoryPage.checkNotificationCenterHasNewNotifications(); + await notificationHistoryPage.clickNotificationButton(); + await notificationHistoryPage.checkNotificationIsPresent(`task has been assigned`); + + await notificationHistoryPage.clickMarkAsRead(); + await processInstancesService.deleteProcessInstance(processInstance.entry.id, simpleApp); + }); + + it('[C593066] Should display notification in counter when task assigned', async () => { + await taskFilter.checkTaskFilterCounter('my-tasks'); + await expect(await taskFilter.getTaskFilterCounter('my-tasks')).toBe('0'); + + const taskCounter = await taskFilter.getTaskFilterCounter('my-tasks'); + const assigneeTask = await tasksService.createStandaloneTask(createdTaskName, simpleApp); + await tasksService.claimTask(assigneeTask.entry.id, simpleApp); + + await taskFilter.waitForNotification('my-tasks'); + await expect(await taskFilter.getTaskFilterCounter('my-tasks')).toBe((parseInt(taskCounter, 10) + 1).toString()); + + await notificationHistoryPage.clickNotificationButton(); + await notificationHistoryPage.clickMarkAsRead(); + await tasksService.deleteTask(assigneeTask.entry.id, simpleApp); + }); + + it('[C290009] Should display notification in task center', async () => { + await taskFilter.checkTaskFilterCounter('my-tasks'); + const assigneeTask = await tasksService.createStandaloneTask(createdTaskName, simpleApp); + await tasksService.claimTask(assigneeTask.entry.id, simpleApp); + + await notificationHistoryPage.checkNotificationCenterHasNewNotifications(); + await notificationHistoryPage.clickNotificationButton(); + await notificationHistoryPage.checkNotificationIsPresent(`${assigneeTask.entry.name} task has been assigned`); + + await notificationHistoryPage.clickMarkAsRead(); + await tasksService.deleteTask(assigneeTask.entry.id, simpleApp); + }); + }); +}); diff --git a/lib/process-services-cloud/src/lib/services/notification-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/services/notification-cloud.service.spec.ts index 20747cdc31..b94be98d9b 100644 --- a/lib/process-services-cloud/src/lib/services/notification-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/services/notification-cloud.service.spec.ts @@ -25,6 +25,11 @@ import { Apollo } from 'apollo-angular'; describe('NotificationCloudService', () => { let service: NotificationCloudService; let apollo: Apollo; + let apolloCreateSpy; + let apolloSubscribeSpy; + const useMock = { + subscribe() {} + }; const queryMock = ` subscription { @@ -47,12 +52,13 @@ describe('NotificationCloudService', () => { beforeEach(async(() => { service = TestBed.inject(NotificationCloudService); apollo = TestBed.inject(Apollo); + + service.appsListening = []; + apolloCreateSpy = spyOn(apollo, 'createNamed'); + apolloSubscribeSpy = spyOn(apollo, 'use').and.returnValue(useMock); })); it('should not create more than one websocket per app if it was already created', () => { - const apolloCreateSpy = spyOn(apollo, 'create'); - const apolloSubscribeSpy = spyOn(apollo, 'subscribe'); - service.makeGQLQuery('myAppName', queryMock); expect(service.appsListening.length).toBe(1); expect(service.appsListening[0]).toBe('myAppName'); @@ -61,12 +67,20 @@ describe('NotificationCloudService', () => { expect(service.appsListening.length).toBe(1); expect(service.appsListening[0]).toBe('myAppName'); - service.makeGQLQuery('myAppName2', queryMock); + expect(apolloCreateSpy).toHaveBeenCalledTimes(1); + expect(apolloSubscribeSpy).toHaveBeenCalledTimes(2); + }); + + it('should create new websocket if it is subscribing to new app', () => { + service.makeGQLQuery('myAppName', queryMock); + expect(service.appsListening.length).toBe(1); + expect(service.appsListening[0]).toBe('myAppName'); + + service.makeGQLQuery('myOtherAppName', queryMock); expect(service.appsListening.length).toBe(2); - expect(service.appsListening[0]).toBe('myAppName'); - expect(service.appsListening[1]).toBe('myAppName2'); + expect(service.appsListening[1]).toBe('myOtherAppName'); expect(apolloCreateSpy).toHaveBeenCalledTimes(2); - expect(apolloSubscribeSpy).toHaveBeenCalledTimes(3); + expect(apolloSubscribeSpy).toHaveBeenCalledTimes(2); }); }); diff --git a/lib/process-services-cloud/src/lib/services/notification-cloud.service.ts b/lib/process-services-cloud/src/lib/services/notification-cloud.service.ts index 5db39faf2f..c31f4fa0fa 100644 --- a/lib/process-services-cloud/src/lib/services/notification-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/services/notification-cloud.service.ts @@ -71,15 +71,15 @@ export class NotificationCloudService extends BaseCloudService { httpLink ); - this.apollo.create( { + this.apollo.createNamed(appName, { link, - cache: new InMemoryCache({}) + cache: new InMemoryCache() }); } } makeGQLQuery(appName: string, gqlQuery: string) { this.initNotificationsForApp(appName); - return this.apollo.subscribe({ query : gql(gqlQuery) }); + return this.apollo.use(appName).subscribe({ query: gql(gqlQuery) }); } } diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.spec.ts index 1df66e2401..f0d559dbe6 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.spec.ts @@ -383,8 +383,8 @@ describe('TaskFiltersCloudComponent', () => { it('should update filter counter when notification received', async(() => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable); - const change = new SimpleChange(undefined, 'my-app-1', true); - component.ngOnChanges({ 'appName': change }); + component.appName = 'my-app-1'; + component.ngOnInit(); fixture.detectChanges(); component.showIcons = true; fixture.whenStable().then(() => { @@ -399,7 +399,8 @@ describe('TaskFiltersCloudComponent', () => { it('should reset filter counter notification when filter is selected', async(() => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable); let change = new SimpleChange(undefined, 'my-app-1', true); - component.ngOnChanges({ 'appName': change }); + component.appName = 'my-app-1'; + component.ngOnInit(); fixture.detectChanges(); component.showIcons = true; fixture.whenStable().then(() => { diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.ts index 4d6fb46aaa..002d6688c0 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.ts @@ -20,7 +20,7 @@ import { Observable } from 'rxjs'; import { TaskFilterCloudService } from '../services/task-filter-cloud.service'; import { TaskFilterCloudModel, FilterParamsModel } from '../models/filter-cloud.model'; import { TranslationService } from '@alfresco/adf-core'; -import { map, takeUntil } from 'rxjs/operators'; +import { takeUntil } from 'rxjs/operators'; import { BaseTaskFiltersCloudComponent } from './base-task-filters-cloud.component'; import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; import { TaskCloudEngineEvent } from '../../../models/engine-event-cloud.model'; @@ -78,7 +78,7 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp this.resetFilter(); this.filters = Object.assign([], res); this.selectFilterAndEmit(this.filterParam); - this.initFilterCounters(); + this.updateFilterCounters(); this.success.emit(res); }, (err: any) => { @@ -87,7 +87,7 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp ); } - initFilterCounters() { + updateFilterCounters() { this.filters.forEach((filter) => { if (filter.showCounter) { this.counters$[filter.key] = this.taskFilterCloudService.getTaskFilterCounter(filter); @@ -96,27 +96,32 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp } initFilterCounterNotifications() { - this.taskFilterCloudService.getTaskNotificationSubscription(this.appName) - .subscribe((result: TaskCloudEngineEvent[]) => { - result.map((taskEvent: TaskCloudEngineEvent) => { - this.updateFilterCounter(taskEvent.entity); + if (this.appName) { + this.taskFilterCloudService.getTaskNotificationSubscription(this.appName) + .subscribe((result: TaskCloudEngineEvent[]) => { + result.map((taskEvent: TaskCloudEngineEvent) => { + this.checkFilterCounter(taskEvent.entity); + }); + this.filterCounterUpdated.emit(result); }); - this.filterCounterUpdated.emit(result); - }); + } } - updateFilterCounter(filterNotification: TaskDetailsCloudModel) { + checkFilterCounter(filterNotification: TaskDetailsCloudModel) { this.filters.map((filter) => { if (this.isFilterPresent(filter, filterNotification)) { - this.counters$[filter.key] = this.counters$[filter.key].pipe(map((counter) => counter + 1)); this.addToUpdatedCounters(filter.key); } }); + + if (this.updatedCounters.length) { + this.updateFilterCounters(); + } } isFilterPresent(filter: TaskFilterCloudModel, filterNotification: TaskDetailsCloudModel): boolean { return filter.status === filterNotification.status - && filter.assignee === filterNotification.assignee; + && (filter.assignee === filterNotification.assignee || filterNotification.assignee === undefined); } public selectFilter(paramFilter: FilterParamsModel) { diff --git a/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts b/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts index 2d981f5185..87e78514d6 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts @@ -34,8 +34,8 @@ const TASK_EVENT_SUBSCRIPTION_QUERY = ` TASK_ASSIGNED TASK_ACTIVATED TASK_SUSPENDED - TASK_CANCELLED - TASK_UPDATED + TASK_CANCELLED, + TASK_CREATED ]) { eventType entity diff --git a/lib/testing/src/lib/core/pages/notification-history.page.ts b/lib/testing/src/lib/core/pages/notification-history.page.ts index 1293169d48..9d23000f6d 100644 --- a/lib/testing/src/lib/core/pages/notification-history.page.ts +++ b/lib/testing/src/lib/core/pages/notification-history.page.ts @@ -35,6 +35,11 @@ export class NotificationHistoryPage { await BrowserVisibility.waitUntilElementHasText(this.notificationList, text); } + async checkNotificationCenterHasNewNotifications(): Promise { + const notificationListButton = element(by.css('#adf-notification-history-open-button [class*="mat-badge-active"]')); + await BrowserVisibility.waitUntilElementIsVisible(notificationListButton); + } + async checkNotificationIsNotPresent(text: string): Promise { const notificationLisText = await BrowserActions.getText(this.notificationList); await expect(notificationLisText).not.toContain(text); diff --git a/lib/testing/src/lib/process-services-cloud/pages/task-filters-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/task-filters-cloud-component.page.ts index b47baee85a..9eaeb1b540 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/task-filters-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/task-filters-cloud-component.page.ts @@ -49,8 +49,22 @@ export class TaskFiltersCloudComponentPage { return BrowserActions.getText(this.activeFilter); } + async getTaskFilterCounter(filterName: string): Promise { + const filterCounter = element.all(by.css(`[data-automation-id="${filterName}_filter-counter"]`)).first(); + return BrowserActions.getText(filterCounter); + } + + async checkTaskFilterCounter(filterName: string): Promise { + const filterCounter = element.all(by.css(`[data-automation-id="${filterName}_filter-counter"]`)).first(); + await BrowserVisibility.waitUntilElementHasText(filterCounter, '0'); + } + + async waitForNotification(filterName: string): Promise { + const filterCounter = element(by.css(`[data-automation-id="${filterName}_filter-counter"][class*="adf-active"]`)); + await BrowserVisibility.waitUntilElementIsVisible(filterCounter); + } + getTaskFilterLocatorByFilterName(filterName: string): ElementFinder { return element.all(by.css(`button[data-automation-id="${filterName}_filter"]`)).first(); } - } diff --git a/package-lock.json b/package-lock.json index 2d2765b2fe..94d21e49c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,14 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@alfresco/adf-testing": { + "version": "4.3.0-31536", + "resolved": "https://registry.npmjs.org/@alfresco/adf-testing/-/adf-testing-4.3.0-31536.tgz", + "integrity": "sha512-V4hXMtQqFlV6h6rBN91H+6DNWRwa5MNXgd/iFPxvRUUolJZi1N1Ehk+XBLFjfzECZlgAhRcr0sjJP62JIQC4fg==", + "requires": { + "tslib": "^2.0.0" + } + }, "@alfresco/js-api": { "version": "4.3.0-3244", "resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-4.3.0-3244.tgz", diff --git a/package.json b/package.json index 7d31324829..0f6a71f8c8 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ ], "dependencies": { "@alfresco/js-api": "^4.3.0-3244", + "@alfresco/adf-testing": "^4.3.0-31536", "@angular/animations": "^10.0.4", "@angular/cdk": "10.1.3", "@angular/common": "^10.0.4",