mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[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
This commit is contained in:
@@ -219,7 +219,8 @@
|
|||||||
"NOTIFICATIONS": {
|
"NOTIFICATIONS": {
|
||||||
"TASK_ASSIGNED": "{{taskName}} task has been assigned to {{assignee}}",
|
"TASK_ASSIGNED": "{{taskName}} task has been assigned to {{assignee}}",
|
||||||
"PROCESS_STARTED": "{{processName}} process has been started",
|
"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-LOADING": {
|
||||||
"FORM_DATA": "Form Data",
|
"FORM_DATA": "Form Data",
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
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 { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
import { ChartsModule } from 'ng2-charts';
|
import { ChartsModule } from 'ng2-charts';
|
||||||
@@ -112,6 +112,8 @@ import localePl from '@angular/common/locales/pl';
|
|||||||
import localeFi from '@angular/common/locales/fi';
|
import localeFi from '@angular/common/locales/fi';
|
||||||
import localeDa from '@angular/common/locales/da';
|
import localeDa from '@angular/common/locales/da';
|
||||||
import localeSv from '@angular/common/locales/sv';
|
import localeSv from '@angular/common/locales/sv';
|
||||||
|
import { setupAppNotifications } from './services/app-notifications-factory';
|
||||||
|
import { AppNotificationsService } from './services/app-notifications.service';
|
||||||
|
|
||||||
registerLocaleData(localeFr);
|
registerLocaleData(localeFr);
|
||||||
registerLocaleData(localeDe);
|
registerLocaleData(localeDe);
|
||||||
@@ -225,6 +227,13 @@ registerLocaleData(localeSv);
|
|||||||
name: 'lazy-loading',
|
name: 'lazy-loading',
|
||||||
source: 'resources/lazy-loading'
|
source: 'resources/lazy-loading'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
AppNotificationsService,
|
||||||
|
{
|
||||||
|
provide: APP_INITIALIZER,
|
||||||
|
useFactory: setupAppNotifications,
|
||||||
|
deps: [AppNotificationsService],
|
||||||
|
multi: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
|
@@ -17,23 +17,6 @@
|
|||||||
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
import { Router, ActivatedRoute } from '@angular/router';
|
import { Router, ActivatedRoute } from '@angular/router';
|
||||||
import { CloudLayoutService } from './services/cloud-layout.service';
|
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({
|
@Component({
|
||||||
selector: 'app-cloud-layout',
|
selector: 'app-cloud-layout',
|
||||||
@@ -48,26 +31,13 @@ export class CloudLayoutComponent implements OnInit {
|
|||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private cloudLayoutService: CloudLayoutService,
|
private cloudLayoutService: CloudLayoutService
|
||||||
private notificationCloudService: NotificationCloudService,
|
|
||||||
private notificationService: NotificationService,
|
|
||||||
private translateService: TranslateService
|
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
let root: string = '';
|
let root: string = '';
|
||||||
this.route.params.subscribe((params) => {
|
this.route.params.subscribe((params) => {
|
||||||
this.appName = params.appName;
|
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) {
|
if (this.route.snapshot && this.route.snapshot.firstChild) {
|
||||||
@@ -92,37 +62,4 @@ export class CloudLayoutComponent implements OnInit {
|
|||||||
onStartProcess() {
|
onStartProcess() {
|
||||||
this.router.navigate([`/cloud/${this.appName}/start-process/`]);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
22
demo-shell/src/app/services/app-notifications-factory.ts
Normal file
22
demo-shell/src/app/services/app-notifications-factory.ts
Normal file
@@ -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;
|
||||||
|
}
|
110
demo-shell/src/app/services/app-notifications.service.ts
Normal file
110
demo-shell/src/app/services/app-notifications.service.ts
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
128
e2e/process-services-cloud/task-counters-cloud.e2e.ts
Normal file
128
e2e/process-services-cloud/task-counters-cloud.e2e.ts
Normal file
@@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -25,6 +25,11 @@ import { Apollo } from 'apollo-angular';
|
|||||||
describe('NotificationCloudService', () => {
|
describe('NotificationCloudService', () => {
|
||||||
let service: NotificationCloudService;
|
let service: NotificationCloudService;
|
||||||
let apollo: Apollo;
|
let apollo: Apollo;
|
||||||
|
let apolloCreateSpy;
|
||||||
|
let apolloSubscribeSpy;
|
||||||
|
const useMock = {
|
||||||
|
subscribe() {}
|
||||||
|
};
|
||||||
|
|
||||||
const queryMock = `
|
const queryMock = `
|
||||||
subscription {
|
subscription {
|
||||||
@@ -47,12 +52,13 @@ describe('NotificationCloudService', () => {
|
|||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
service = TestBed.inject(NotificationCloudService);
|
service = TestBed.inject(NotificationCloudService);
|
||||||
apollo = TestBed.inject(Apollo);
|
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', () => {
|
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);
|
service.makeGQLQuery('myAppName', queryMock);
|
||||||
expect(service.appsListening.length).toBe(1);
|
expect(service.appsListening.length).toBe(1);
|
||||||
expect(service.appsListening[0]).toBe('myAppName');
|
expect(service.appsListening[0]).toBe('myAppName');
|
||||||
@@ -61,12 +67,20 @@ describe('NotificationCloudService', () => {
|
|||||||
expect(service.appsListening.length).toBe(1);
|
expect(service.appsListening.length).toBe(1);
|
||||||
expect(service.appsListening[0]).toBe('myAppName');
|
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.length).toBe(2);
|
||||||
expect(service.appsListening[0]).toBe('myAppName');
|
expect(service.appsListening[1]).toBe('myOtherAppName');
|
||||||
expect(service.appsListening[1]).toBe('myAppName2');
|
|
||||||
|
|
||||||
expect(apolloCreateSpy).toHaveBeenCalledTimes(2);
|
expect(apolloCreateSpy).toHaveBeenCalledTimes(2);
|
||||||
expect(apolloSubscribeSpy).toHaveBeenCalledTimes(3);
|
expect(apolloSubscribeSpy).toHaveBeenCalledTimes(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -71,15 +71,15 @@ export class NotificationCloudService extends BaseCloudService {
|
|||||||
httpLink
|
httpLink
|
||||||
);
|
);
|
||||||
|
|
||||||
this.apollo.create(<any> {
|
this.apollo.createNamed(appName, {
|
||||||
link,
|
link,
|
||||||
cache: new InMemoryCache({})
|
cache: new InMemoryCache()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
makeGQLQuery(appName: string, gqlQuery: string) {
|
makeGQLQuery(appName: string, gqlQuery: string) {
|
||||||
this.initNotificationsForApp(appName);
|
this.initNotificationsForApp(appName);
|
||||||
return this.apollo.subscribe({ query : gql(gqlQuery) });
|
return this.apollo.use(appName).subscribe({ query: gql(gqlQuery) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -383,8 +383,8 @@ describe('TaskFiltersCloudComponent', () => {
|
|||||||
|
|
||||||
it('should update filter counter when notification received', async(() => {
|
it('should update filter counter when notification received', async(() => {
|
||||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||||
const change = new SimpleChange(undefined, 'my-app-1', true);
|
component.appName = 'my-app-1';
|
||||||
component.ngOnChanges({ 'appName': change });
|
component.ngOnInit();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
component.showIcons = true;
|
component.showIcons = true;
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
@@ -399,7 +399,8 @@ describe('TaskFiltersCloudComponent', () => {
|
|||||||
it('should reset filter counter notification when filter is selected', async(() => {
|
it('should reset filter counter notification when filter is selected', async(() => {
|
||||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||||
let change = new SimpleChange(undefined, 'my-app-1', true);
|
let change = new SimpleChange(undefined, 'my-app-1', true);
|
||||||
component.ngOnChanges({ 'appName': change });
|
component.appName = 'my-app-1';
|
||||||
|
component.ngOnInit();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
component.showIcons = true;
|
component.showIcons = true;
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
|
@@ -20,7 +20,7 @@ import { Observable } from 'rxjs';
|
|||||||
import { TaskFilterCloudService } from '../services/task-filter-cloud.service';
|
import { TaskFilterCloudService } from '../services/task-filter-cloud.service';
|
||||||
import { TaskFilterCloudModel, FilterParamsModel } from '../models/filter-cloud.model';
|
import { TaskFilterCloudModel, FilterParamsModel } from '../models/filter-cloud.model';
|
||||||
import { TranslationService } from '@alfresco/adf-core';
|
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 { BaseTaskFiltersCloudComponent } from './base-task-filters-cloud.component';
|
||||||
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
|
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
|
||||||
import { TaskCloudEngineEvent } from '../../../models/engine-event-cloud.model';
|
import { TaskCloudEngineEvent } from '../../../models/engine-event-cloud.model';
|
||||||
@@ -78,7 +78,7 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
|
|||||||
this.resetFilter();
|
this.resetFilter();
|
||||||
this.filters = Object.assign([], res);
|
this.filters = Object.assign([], res);
|
||||||
this.selectFilterAndEmit(this.filterParam);
|
this.selectFilterAndEmit(this.filterParam);
|
||||||
this.initFilterCounters();
|
this.updateFilterCounters();
|
||||||
this.success.emit(res);
|
this.success.emit(res);
|
||||||
},
|
},
|
||||||
(err: any) => {
|
(err: any) => {
|
||||||
@@ -87,7 +87,7 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
initFilterCounters() {
|
updateFilterCounters() {
|
||||||
this.filters.forEach((filter) => {
|
this.filters.forEach((filter) => {
|
||||||
if (filter.showCounter) {
|
if (filter.showCounter) {
|
||||||
this.counters$[filter.key] = this.taskFilterCloudService.getTaskFilterCounter(filter);
|
this.counters$[filter.key] = this.taskFilterCloudService.getTaskFilterCounter(filter);
|
||||||
@@ -96,27 +96,32 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
|
|||||||
}
|
}
|
||||||
|
|
||||||
initFilterCounterNotifications() {
|
initFilterCounterNotifications() {
|
||||||
this.taskFilterCloudService.getTaskNotificationSubscription(this.appName)
|
if (this.appName) {
|
||||||
.subscribe((result: TaskCloudEngineEvent[]) => {
|
this.taskFilterCloudService.getTaskNotificationSubscription(this.appName)
|
||||||
result.map((taskEvent: TaskCloudEngineEvent) => {
|
.subscribe((result: TaskCloudEngineEvent[]) => {
|
||||||
this.updateFilterCounter(taskEvent.entity);
|
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) => {
|
this.filters.map((filter) => {
|
||||||
if (this.isFilterPresent(filter, filterNotification)) {
|
if (this.isFilterPresent(filter, filterNotification)) {
|
||||||
this.counters$[filter.key] = this.counters$[filter.key].pipe(map((counter) => counter + 1));
|
|
||||||
this.addToUpdatedCounters(filter.key);
|
this.addToUpdatedCounters(filter.key);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this.updatedCounters.length) {
|
||||||
|
this.updateFilterCounters();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isFilterPresent(filter: TaskFilterCloudModel, filterNotification: TaskDetailsCloudModel): boolean {
|
isFilterPresent(filter: TaskFilterCloudModel, filterNotification: TaskDetailsCloudModel): boolean {
|
||||||
return filter.status === filterNotification.status
|
return filter.status === filterNotification.status
|
||||||
&& filter.assignee === filterNotification.assignee;
|
&& (filter.assignee === filterNotification.assignee || filterNotification.assignee === undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
public selectFilter(paramFilter: FilterParamsModel) {
|
public selectFilter(paramFilter: FilterParamsModel) {
|
||||||
|
@@ -34,8 +34,8 @@ const TASK_EVENT_SUBSCRIPTION_QUERY = `
|
|||||||
TASK_ASSIGNED
|
TASK_ASSIGNED
|
||||||
TASK_ACTIVATED
|
TASK_ACTIVATED
|
||||||
TASK_SUSPENDED
|
TASK_SUSPENDED
|
||||||
TASK_CANCELLED
|
TASK_CANCELLED,
|
||||||
TASK_UPDATED
|
TASK_CREATED
|
||||||
]) {
|
]) {
|
||||||
eventType
|
eventType
|
||||||
entity
|
entity
|
||||||
|
@@ -35,6 +35,11 @@ export class NotificationHistoryPage {
|
|||||||
await BrowserVisibility.waitUntilElementHasText(this.notificationList, text);
|
await BrowserVisibility.waitUntilElementHasText(this.notificationList, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async checkNotificationCenterHasNewNotifications(): Promise<void> {
|
||||||
|
const notificationListButton = element(by.css('#adf-notification-history-open-button [class*="mat-badge-active"]'));
|
||||||
|
await BrowserVisibility.waitUntilElementIsVisible(notificationListButton);
|
||||||
|
}
|
||||||
|
|
||||||
async checkNotificationIsNotPresent(text: string): Promise<void> {
|
async checkNotificationIsNotPresent(text: string): Promise<void> {
|
||||||
const notificationLisText = await BrowserActions.getText(this.notificationList);
|
const notificationLisText = await BrowserActions.getText(this.notificationList);
|
||||||
await expect(notificationLisText).not.toContain(text);
|
await expect(notificationLisText).not.toContain(text);
|
||||||
|
@@ -49,8 +49,22 @@ export class TaskFiltersCloudComponentPage {
|
|||||||
return BrowserActions.getText(this.activeFilter);
|
return BrowserActions.getText(this.activeFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getTaskFilterCounter(filterName: string): Promise<string> {
|
||||||
|
const filterCounter = element.all(by.css(`[data-automation-id="${filterName}_filter-counter"]`)).first();
|
||||||
|
return BrowserActions.getText(filterCounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkTaskFilterCounter(filterName: string): Promise<void> {
|
||||||
|
const filterCounter = element.all(by.css(`[data-automation-id="${filterName}_filter-counter"]`)).first();
|
||||||
|
await BrowserVisibility.waitUntilElementHasText(filterCounter, '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
async waitForNotification(filterName: string): Promise<void> {
|
||||||
|
const filterCounter = element(by.css(`[data-automation-id="${filterName}_filter-counter"][class*="adf-active"]`));
|
||||||
|
await BrowserVisibility.waitUntilElementIsVisible(filterCounter);
|
||||||
|
}
|
||||||
|
|
||||||
getTaskFilterLocatorByFilterName(filterName: string): ElementFinder {
|
getTaskFilterLocatorByFilterName(filterName: string): ElementFinder {
|
||||||
return element.all(by.css(`button[data-automation-id="${filterName}_filter"]`)).first();
|
return element.all(by.css(`button[data-automation-id="${filterName}_filter"]`)).first();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
8
package-lock.json
generated
8
package-lock.json
generated
@@ -4,6 +4,14 @@
|
|||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"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": {
|
"@alfresco/js-api": {
|
||||||
"version": "4.3.0-3244",
|
"version": "4.3.0-3244",
|
||||||
"resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-4.3.0-3244.tgz",
|
"resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-4.3.0-3244.tgz",
|
||||||
|
@@ -72,6 +72,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alfresco/js-api": "^4.3.0-3244",
|
"@alfresco/js-api": "^4.3.0-3244",
|
||||||
|
"@alfresco/adf-testing": "^4.3.0-31536",
|
||||||
"@angular/animations": "^10.0.4",
|
"@angular/animations": "^10.0.4",
|
||||||
"@angular/cdk": "10.1.3",
|
"@angular/cdk": "10.1.3",
|
||||||
"@angular/common": "^10.0.4",
|
"@angular/common": "^10.0.4",
|
||||||
|
Reference in New Issue
Block a user