[ACS-6196] await-thenable rule for ESLint, fix issues (#9027)

* fix issues for core lib

* fix content services lib

* fix and cleanup process services

* [ci:force] process services cloud

* [ci:force] align coverage with all libs

* [ci:force] fix the insights
This commit is contained in:
Denys Vuika
2023-10-26 14:33:48 +01:00
committed by GitHub
parent 7ebdce7875
commit ba96ed14b2
45 changed files with 638 additions and 1224 deletions

View File

@@ -78,6 +78,7 @@ module.exports = {
accessibility: 'explicit'
}
],
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/prefer-optional-chain': 'warn',
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/no-require-imports': 'off',

View File

@@ -133,7 +133,7 @@ describe('Process Task - Attach content file', () => {
await taskFormCloudComponent.formFields().checkFormIsDisplayed();
await taskFormCloudComponent.formFields().checkWidgetIsVisible(uploadWidgetId);
const contentUploadFileWidget = await processCloudWidget.attachFileWidgetCloud(uploadWidgetId);
const contentUploadFileWidget = processCloudWidget.attachFileWidgetCloud(uploadWidgetId);
await contentUploadFileWidget.clickAttachContentFile(uploadWidgetId);
await contentNodeSelectorDialog.attachFileFromContentNode(folderName, pdfFileOne.name);

View File

@@ -311,7 +311,7 @@ describe('Start Task Form', () => {
await processDetailsCloudDemoPage.selectProcessTaskByName('UploadFileTask');
await taskFormCloudComponent.clickClaimButton();
const localFileWidget = await widget.attachFileWidgetCloud('Attachlocalfile');
const localFileWidget = widget.attachFileWidgetCloud('Attachlocalfile');
await localFileWidget.clickAttachContentFile('Attachlocalfile');
await contentNodeSelectorDialogPage.attachFilesFromLocal([pdfFile]);
await localFileWidget.checkFileIsAttached(pdfFile.name);
@@ -326,7 +326,7 @@ describe('Start Task Form', () => {
await processDetailsCloudDemoPage.checkTaskIsDisplayed('UploadFileTask');
await processDetailsCloudDemoPage.selectProcessTaskByName('UploadFileTask');
const contentFileWidget = await widget.attachFileWidgetCloud('Attachsinglecontentfile');
const contentFileWidget = widget.attachFileWidgetCloud('Attachsinglecontentfile');
await contentFileWidget.clickAttachContentFile('Attachsinglecontentfile');
await contentNodeSelectorDialogPage.attachFileFromContentNode(folderName, testFileModel.name);
@@ -344,7 +344,7 @@ describe('Start Task Form', () => {
await processDetailsCloudDemoPage.selectProcessTaskByName('UploadFileTask');
await taskFormCloudComponent.clickClaimButton();
const contentFileWidget = await widget.attachFileWidgetCloud('Attachsinglecontentfile');
const contentFileWidget = widget.attachFileWidgetCloud('Attachsinglecontentfile');
await contentFileWidget.clickAttachContentFile('Attachsinglecontentfile');
await contentNodeSelectorDialogPage.checkDialogIsDisplayed();
await expect(await breadCrumbDropdownPage.getTextOfCurrentFolder()).toBe(testUser.username);
@@ -369,7 +369,7 @@ describe('Start Task Form', () => {
await processDetailsCloudDemoPage.selectProcessTaskByName('UploadFileTask');
await taskFormCloudComponent.clickClaimButton();
const contentFileWidget = await widget.attachFileWidgetCloud('Attachsinglecontentfile');
const contentFileWidget = widget.attachFileWidgetCloud('Attachsinglecontentfile');
await contentFileWidget.clickAttachContentFile('Attachsinglecontentfile');
await contentNodeSelectorDialogPage.checkDialogIsDisplayed();
await contentNodeSelectorDialogPage.contentListPage().dataTablePage().waitTillContentLoaded();
@@ -391,7 +391,7 @@ describe('Start Task Form', () => {
await processDetailsCloudDemoPage.checkTaskIsDisplayed('UploadFileTask');
await processDetailsCloudDemoPage.selectProcessTaskByName('UploadFileTask');
const contentFileWidget = await widget.attachFileWidgetCloud('Attachsinglecontentfile');
const contentFileWidget = widget.attachFileWidgetCloud('Attachsinglecontentfile');
await contentFileWidget.clickAttachContentFile('Attachsinglecontentfile');
await contentNodeSelectorDialogPage.attachFileFromContentNode(folderName, testFileModel.name);
@@ -406,7 +406,7 @@ describe('Start Task Form', () => {
await processDetailsCloudDemoPage.checkTaskIsDisplayed('UploadFileTask');
await processDetailsCloudDemoPage.selectProcessTaskByName('UploadFileTask');
const contentFileWidget = await widget.attachFileWidgetCloud('Attachsinglecontentfile');
const contentFileWidget = widget.attachFileWidgetCloud('Attachsinglecontentfile');
await contentFileWidget.clickAttachContentFile('Attachsinglecontentfile');
await contentNodeSelectorDialogPage.attachFileFromContentNode(folderName, testFileModel.name);
@@ -426,7 +426,7 @@ describe('Start Task Form', () => {
await processDetailsCloudDemoPage.checkTaskIsDisplayed('UploadFileTask');
await processDetailsCloudDemoPage.selectProcessTaskByName('UploadFileTask');
const contentFileWidget = await widget.attachFileWidgetCloud('Attachsinglecontentfile');
const contentFileWidget = widget.attachFileWidgetCloud('Attachsinglecontentfile');
await contentFileWidget.clickAttachContentFile('Attachsinglecontentfile');
await contentNodeSelectorDialogPage.attachFileFromContentNode(folderName, testFileModel.name);
@@ -448,7 +448,7 @@ describe('Start Task Form', () => {
await processDetailsCloudDemoPage.selectProcessTaskByName('UploadFileTask');
await taskFormCloudComponent.clickClaimButton();
const contentFileWidget = await widget.attachFileWidgetCloud('Attachsinglecontentfile');
const contentFileWidget = widget.attachFileWidgetCloud('Attachsinglecontentfile');
await contentFileWidget.clickAttachContentFile('Attachsinglecontentfile');
await contentNodeSelectorDialogPage.attachFileFromContentNode(folderName, testFileModel.name);
@@ -478,7 +478,7 @@ describe('Start Task Form', () => {
await processDetailsCloudDemoPage.selectProcessTaskByName('UploadFileTask');
await taskFormCloudComponent.clickClaimButton();
const contentFileWidget = await widget.attachFileWidgetCloud('Attachsinglecontentfile');
const contentFileWidget = widget.attachFileWidgetCloud('Attachsinglecontentfile');
await contentFileWidget.clickAttachContentFile('Attachsinglecontentfile');
await contentNodeSelectorDialogPage.checkDialogIsDisplayed();
await contentNodeSelectorDialogPage.contentListPage().dataTablePage().doubleClickRowByContent(folderName);

View File

@@ -96,7 +96,7 @@ describe('Checklist component', () => {
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[0]);
await taskPage.tasksListPage().selectRow(tasks[0]);
await await taskPage.clickOnAddChecklistButton();
await taskPage.clickOnAddChecklistButton();
await taskPage.checkChecklistDialogIsDisplayed();
await expect(await taskPage.usingCheckListDialog().getDialogTitle()).toEqual('New Check');
await expect(await taskPage.usingCheckListDialog().getNameFieldPlaceholder()).toEqual('Name');
@@ -125,7 +125,7 @@ describe('Checklist component', () => {
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[2]);
await taskPage.tasksListPage().selectRow(tasks[2]);
await await taskPage.clickOnAddChecklistButton();
await taskPage.clickOnAddChecklistButton();
await taskPage.checkChecklistDialogIsDisplayed();
await checklistDialog.addName(removeChecklist[0]);
await checklistDialog.clickCreateChecklistButton();

View File

@@ -84,7 +84,7 @@ describe('People component', () => {
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[0]);
await taskPage.tasksListPage().selectRow(tasks[0]);
const taskDetails = await taskPage.taskDetails();
const taskDetails = taskPage.taskDetails();
await taskDetails.clickInvolvePeopleButton();
await taskDetails.typeUser(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName);
@@ -99,7 +99,7 @@ describe('People component', () => {
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[0]);
await taskPage.tasksListPage().selectRow(tasks[0]);
const taskDetails = await taskPage.taskDetails();
const taskDetails = taskPage.taskDetails();
await taskDetails.clickInvolvePeopleButton();
await expect(await taskPage.taskDetails().getInvolvePeopleHeader()).toEqual('Add people and groups');
@@ -114,7 +114,7 @@ describe('People component', () => {
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[0]);
await taskPage.tasksListPage().selectRow(tasks[0]);
const taskDetails = await taskPage.taskDetails();
const taskDetails = taskPage.taskDetails();
await taskDetails.clickInvolvePeopleButton();
await taskDetails.typeUser(processUserModel.firstName + ' ' + processUserModel.lastName);
await taskDetails.noUserIsDisplayedInSearchInvolvePeople(processUserModel.firstName + ' ' + processUserModel.lastName);
@@ -126,7 +126,7 @@ describe('People component', () => {
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[0]);
await taskPage.tasksListPage().selectRow(tasks[0]);
const taskDetails = await taskPage.taskDetails();
const taskDetails = taskPage.taskDetails();
await taskDetails.clickInvolvePeopleButton();
await taskDetails.typeUser(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName);
await taskDetails.selectUserToInvolve(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName);
@@ -144,7 +144,7 @@ describe('People component', () => {
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[1]);
await taskPage.tasksListPage().selectRow(tasks[1]);
const taskDetails = await taskPage.taskDetails();
const taskDetails = taskPage.taskDetails();
await taskDetails.clickInvolvePeopleButton();
await taskDetails.typeUser(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName);
await taskDetails.selectUserToInvolve(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName);
@@ -168,7 +168,7 @@ describe('People component', () => {
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[2]);
await taskPage.tasksListPage().selectRow(tasks[2]);
const taskDetails = await taskPage.taskDetails();
const taskDetails = taskPage.taskDetails();
await taskPage.taskDetails().clickInvolvePeopleButton();
await taskDetails.typeUser(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName);
await taskDetails.selectUserToInvolve(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName);
@@ -179,7 +179,7 @@ describe('People component', () => {
.toEqual(assigneeUserModel.email);
await expect(await taskPage.taskDetails().getInvolvedPeopleTitle()).toEqual(peopleTitle + '(1)');
const taskDetails2 = await taskPage.taskDetails();
const taskDetails2 = taskPage.taskDetails();
await taskDetails2.clickInvolvePeopleButton();
await taskDetails2.typeUser(secondAssigneeUserModel.firstName + ' ' + secondAssigneeUserModel.lastName);
await taskDetails2.selectUserToInvolve(secondAssigneeUserModel.firstName + ' ' + secondAssigneeUserModel.lastName);
@@ -196,7 +196,7 @@ describe('People component', () => {
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[3]);
await taskPage.tasksListPage().selectRow(tasks[3]);
const taskDetails = await taskPage.taskDetails();
const taskDetails = taskPage.taskDetails();
await taskDetails.clickInvolvePeopleButton();
await taskDetails.typeUser(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName);
await taskDetails.selectUserToInvolve(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName);

View File

@@ -463,7 +463,7 @@ describe('Start Process Component', () => {
await processInstanceTasksPage.clickOnStartForm();
await processInstanceTasksPage.checkStartProcessDialogIsDisplayed();
await expect(await processInstanceTasksPage.getTitle()).toBe('Start Form');
await expect(await (await widget.dateWidget()).getDateInput('testdate')).toBe('15-7-2019');
await expect(await widget.dateWidget().getDateInput('testdate')).toBe('15-7-2019');
await processInstanceTasksPage.clickCloseButton();
await processInstanceTasksPage.checkStartProcessDialogIsNotDisplayed();
});

View File

@@ -75,7 +75,7 @@ describe('Start Task - Task App', () => {
await taskPage.tasksListPage().checkContentIsDisplayed('Standalone task');
await taskPage.taskDetails().noFormIsDisplayed();
const taskDetails = await taskPage.taskDetails();
const taskDetails = taskPage.taskDetails();
await taskDetails.checkCompleteTaskButtonIsDisplayed();
await taskDetails.checkCompleteTaskButtonIsEnabled();
await taskPage.taskDetails().checkAttachFormButtonIsDisplayed();
@@ -110,7 +110,7 @@ describe('Start Task - Task App', () => {
await taskPage.formFields().noFormIsDisplayed();
await taskPage.taskDetails().clickAttachFormButton();
const formFields = await taskPage.formFields();
const formFields = taskPage.formFields();
await formFields.selectForm(app.formName);
await formFields.clickOnAttachFormButton();
@@ -122,7 +122,7 @@ describe('Start Task - Task App', () => {
it('[C268912] Should a standalone task be displayed when removing the form from APS', async () => {
const task = await taskPage.createNewTask();
const taskDetails = await taskPage.taskDetails();
const taskDetails = taskPage.taskDetails();
await task.addName('Remove form');
await task.selectForm(app.formName);
await task.clickStartButton();

View File

@@ -73,7 +73,7 @@ describe('Start Task - Custom App', () => {
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[0]);
const taskDetails = await taskPage.taskDetails();
const taskDetails = taskPage.taskDetails();
await taskDetails.clickInvolvePeopleButton();
await taskDetails.typeUser(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName);

View File

@@ -80,7 +80,7 @@ describe('Start Task - Task App', () => {
await task.selectForm(app.formName);
await task.clickStartButton();
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[0]);
const taskDetails = await taskPage.taskDetails();
const taskDetails = taskPage.taskDetails();
await taskDetails.clickInvolvePeopleButton();
await taskDetails.typeUser(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName);
@@ -126,7 +126,7 @@ describe('Start Task - Task App', () => {
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[4]);
const formFields = await taskPage.formFields();
const formFields = taskPage.formFields();
const formFieldValue = 'First value ';
await formFields.setFieldValue(formTextField, formFieldValue);

View File

@@ -72,26 +72,27 @@ describe('NodeAspectService', () => {
expect(nodeApiService.updateNode).toHaveBeenCalledWith('fake-node-id', expectedParameters);
});
it('should send and update node event once the node has been updated', async () => {
await nodeApiService.nodeUpdated.subscribe((nodeUpdated) => {
expect(nodeUpdated.id).toBe('fake-node-id');
expect(nodeUpdated.aspectNames).toEqual(['a', 'b', 'c']);
});
it('should send and update node event once the node has been updated', () => {
let lastValue: Node;
nodeApiService.nodeUpdated.subscribe((nodeUpdated) => lastValue = nodeUpdated);
const fakeNode = new Node({ id: 'fake-node-id', aspectNames: ['a', 'b', 'c'] });
spyOn(dialogAspectListService, 'openAspectListDialog').and.returnValue(of(['a', 'b', 'c']));
spyOn(nodeApiService, 'updateNode').and.returnValue(of(fakeNode));
nodeAspectService.updateNodeAspects('fake-node-id');
expect(lastValue.id).toBe('fake-node-id');
expect(lastValue.aspectNames).toEqual(['a', 'b', 'c']);
});
it('should send and update node aspect once the node has been updated', async () => {
await cardViewContentUpdateService.updatedAspect$.subscribe((nodeUpdated) => {
expect(nodeUpdated.id).toBe('fake-node-id');
expect(nodeUpdated.aspectNames).toEqual(['a', 'b', 'c']);
});
it('should send and update node aspect once the node has been updated', () => {
let lastValue: Node;
cardViewContentUpdateService.updatedAspect$.subscribe((nodeUpdated) => lastValue = nodeUpdated);
const fakeNode = new Node({ id: 'fake-node-id', aspectNames: ['a', 'b', 'c'] });
spyOn(dialogAspectListService, 'openAspectListDialog').and.returnValue(of(['a', 'b', 'c']));
spyOn(nodeApiService, 'updateNode').and.returnValue(of(fakeNode));
nodeAspectService.updateNodeAspects('fake-node-id');
expect(lastValue.id).toBe('fake-node-id');
expect(lastValue.aspectNames).toEqual(['a', 'b', 'c']);
});
it('should call emit on refresh from TagService', () => {

View File

@@ -126,7 +126,7 @@ describe('PeopleContentService', () => {
await peopleContentService.getCurrentUserInfo().toPromise();
expect(await peopleContentService.isCurrentUserAdmin()).toBe(true);
expect(peopleContentService.isCurrentUserAdmin()).toBe(true);
expect(getCurrentPersonSpy.calls.count()).toEqual(1);
});

View File

@@ -127,14 +127,14 @@ describe('ContentNodeSelectorPanelComponent', () => {
component.currentFolderId = 'fake-starting-folder';
});
it('should trigger siteChange event on init with parent site Title of start folder', async () => {
await component.siteChange.subscribe((siteTitle: string) => {
expect(siteTitle).toBe('fake-site');
});
it('should trigger siteChange event on init with parent site Title of start folder', () => {
let lastValue: string;
component.siteChange.subscribe((siteTitle: string) => lastValue = siteTitle);
component.ngOnInit();
fixture.detectChanges();
expect(component.startSiteGuid).toBe('fake-site');
expect(lastValue).toBe('fake-site');
});
it('should trigger siteChange event when a site is selected in sites-dropdown', async () => {
@@ -142,12 +142,12 @@ describe('ContentNodeSelectorPanelComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
await component.siteChange.subscribe((siteTitle: string) => {
expect(siteTitle).toBe('fake-new-site');
});
let lastValue: string;
component.siteChange.subscribe((siteTitle: string) => lastValue = siteTitle);
const sitesDropdown = fixture.debugElement.query(By.directive(DropdownSitesComponent));
sitesDropdown.componentInstance.selectedSite({ value: fakeSiteEntry });
expect(lastValue).toBe('fake-new-site');
});
});
@@ -177,14 +177,14 @@ describe('ContentNodeSelectorPanelComponent', () => {
expect(component.documentList.sortingMode).toBe('server');
});
it('should trigger the select event when selection has been made', async () => {
it('should trigger the select event when selection has been made', () => {
const expectedNode = { id: 'fakeid' } as Node;
await component.select.subscribe((nodes) => {
expect(nodes.length).toBe(1);
expect(nodes[0]).toBe(expectedNode);
});
let lastValue: Node[];
component.select.subscribe((nodes) => lastValue = nodes);
component.chosenNode = [expectedNode];
expect(lastValue.length).toBe(1);
expect(lastValue[0]).toBe(expectedNode);
});
it('should be able to filter out the exclude site content', () => {

View File

@@ -56,7 +56,7 @@ describe('FileAutoDownloadComponent', () => {
const waitButton = getButton('#cancelButton');
waitButton.dispatchEvent(new Event('click'));
await fixture.detectChanges();
fixture.detectChanges();
await fixture.whenStable();
expect(matDialogRef.close).toHaveBeenCalled();
@@ -66,7 +66,7 @@ describe('FileAutoDownloadComponent', () => {
const waitButton = getButton('#downloadButton');
waitButton.dispatchEvent(new Event('click'));
await fixture.detectChanges();
fixture.detectChanges();
await fixture.whenStable();
expect(matDialogRef.close).toHaveBeenCalled();

View File

@@ -23,6 +23,7 @@ import { of } from 'rxjs';
import { TestBed } from '@angular/core/testing';
import { ContentTestingModule } from '../../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { PermissionModel } from '../models/permissions.model';
describe('DocumentActionsService', () => {
@@ -94,17 +95,18 @@ describe('DocumentActionsService', () => {
expect(service.getHandler('delete')).toBeDefined();
});
it('should not delete the file node if there are no permissions', async () => {
it('should not delete the file node if there are no permissions', () => {
spyOn(documentListService, 'deleteNode').and.returnValue(of(true));
await service.permissionEvent.subscribe((permission) => {
expect(permission).toBeDefined();
expect(permission.type).toEqual('content');
expect(permission.action).toEqual('delete');
});
let lastValue: PermissionModel;
service.permissionEvent.subscribe((permission) => lastValue = permission);
const file = new FileNode();
service.getHandler('delete')(file);
expect(lastValue).toBeDefined();
expect(lastValue.type).toEqual('content');
expect(lastValue.action).toEqual('delete');
});
it('should call the error on the returned Observable if there are no permissions', async () => {
@@ -132,20 +134,21 @@ describe('DocumentActionsService', () => {
expect(documentListService.deleteNode).toHaveBeenCalledWith(file.entry.id);
});
it('should not delete the file node if there is no delete permission', async () => {
it('should not delete the file node if there is no delete permission', () => {
spyOn(documentListService, 'deleteNode').and.callThrough();
await service.permissionEvent.subscribe((permissionBack) => {
expect(permissionBack).toBeDefined();
expect(permissionBack.type).toEqual('content');
expect(permissionBack.action).toEqual('delete');
});
let lastValue: PermissionModel;
service.permissionEvent.subscribe((permissionBack) => lastValue = permissionBack);
const permission = 'delete';
const file = new FileNode();
const fileWithPermission: any = file;
fileWithPermission.entry.allowableOperations = ['create', 'update'];
service.getHandler('delete')(fileWithPermission, null, permission);
expect(lastValue).toBeDefined();
expect(lastValue.type).toEqual('content');
expect(lastValue.action).toEqual('delete');
});
it('should delete the file node if there is the delete and others permission ', () => {
@@ -202,10 +205,9 @@ describe('DocumentActionsService', () => {
expect(documentListService.deleteNode).not.toHaveBeenCalled();
});
it('should emit success event upon node deletion', async () => {
await service.success.subscribe((message) => {
expect(message).toEqual('CORE.DELETE_NODE.SINGULAR');
});
it('should emit success event upon node deletion', () => {
let lastValue: string;
service.success.subscribe((message) => lastValue = message);
spyOn(documentListService, 'deleteNode').and.returnValue(of(true));
const target = jasmine.createSpyObj('obj', ['reload']);
@@ -214,5 +216,6 @@ describe('DocumentActionsService', () => {
const fileWithPermission: any = file;
fileWithPermission.entry.allowableOperations = [permission];
service.getHandler('delete')(fileWithPermission, target, permission);
expect(lastValue).toEqual('CORE.DELETE_NODE.SINGULAR');
});
});

View File

@@ -31,9 +31,9 @@ import { ContentNodeDialogService } from '../../content-node-selector/content-no
})
export class DocumentActionsService {
permissionEvent: Subject<PermissionModel> = new Subject<PermissionModel>();
error: Subject<Error> = new Subject<Error>();
success: Subject<string> = new Subject<string>();
permissionEvent = new Subject<PermissionModel>();
error = new Subject<Error>();
success = new Subject<string>();
private handlers: { [id: string]: ContentActionHandler } = {};
@@ -113,7 +113,7 @@ export class DocumentActionsService {
return actionObservable;
}
private prepareHandlers(actionObservable): void {
private prepareHandlers(actionObservable: Subject<string>): void {
actionObservable.subscribe(
(fileOperationMessage) => {
this.success.next(fileOperationMessage);

View File

@@ -24,6 +24,7 @@ import { DocumentListService } from './document-list.service';
import { FolderActionsService } from './folder-actions.service';
import { ContentTestingModule } from '../../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { PermissionModel } from '../models/permissions.model';
describe('FolderActionsService', () => {
@@ -87,17 +88,17 @@ describe('FolderActionsService', () => {
expect(service.getHandler('delete')).toBeDefined();
});
it('should not delete the folder node if there are no permissions', async () => {
it('should not delete the folder node if there are no permissions', () => {
spyOn(documentListService, 'deleteNode').and.callThrough();
await service.permissionEvent.subscribe((permission) => {
expect(permission).toBeDefined();
expect(permission.type).toEqual('folder');
expect(permission.action).toEqual('delete');
});
let lastValue: PermissionModel;
service.permissionEvent.subscribe((permission) => lastValue = permission);
const folder = new FolderNode();
service.getHandler('delete')(folder);
expect(lastValue).toBeDefined();
expect(lastValue.type).toEqual('folder');
expect(lastValue.action).toEqual('delete');
});
it('should delete the folder node if there is the delete permission', () => {
@@ -116,22 +117,22 @@ describe('FolderActionsService', () => {
expect(deleteObservable.subscribe).toBeDefined();
});
it('should not delete the folder node if there is no delete permission', async () => {
it('should not delete the folder node if there is no delete permission', () => {
spyOn(documentListService, 'deleteNode').and.callFake(() => new Observable<any>((observer) => {
observer.next();
observer.complete();
}));
await service.permissionEvent.subscribe((permission) => {
expect(permission).toBeDefined();
expect(permission.type).toEqual('folder');
expect(permission.action).toEqual('delete');
});
let lastValue: PermissionModel;
service.permissionEvent.subscribe((permission) => lastValue = permission);
const folder = new FolderNode();
const folderWithPermission: any = folder;
folderWithPermission.entry.allowableOperations = ['create', 'update'];
service.getHandler('delete')(folderWithPermission);
expect(lastValue).toBeDefined();
expect(lastValue.type).toEqual('folder');
expect(lastValue.action).toEqual('delete');
});
it('should call the error on the returned Observable if there is no delete permission', async () => {
@@ -219,15 +220,14 @@ describe('FolderActionsService', () => {
expect(documentListService.deleteNode).toHaveBeenCalled();
});
it('should emit success event upon node deletion', async () => {
it('should emit success event upon node deletion', () => {
spyOn(documentListService, 'deleteNode').and.callFake(() => new Observable<any>((observer) => {
observer.next();
observer.complete();
}));
await service.success.subscribe((nodeId) => {
expect(nodeId).not.toBeNull();
});
let lastValue: string;
service.success.subscribe((nodeId) => lastValue = nodeId);
const permission = 'delete';
const target = jasmine.createSpyObj('obj', ['reload']);
@@ -236,5 +236,6 @@ describe('FolderActionsService', () => {
folderWithPermission.entry.allowableOperations = [permission];
service.getHandler('delete')(folderWithPermission, target, permission);
expect(lastValue).not.toBeNull();
});
});

View File

@@ -30,9 +30,9 @@ import { NodeActionsService } from './node-actions.service';
})
export class FolderActionsService {
permissionEvent: Subject<PermissionModel> = new Subject<PermissionModel>();
error: Subject<Error> = new Subject<Error>();
success: Subject<string> = new Subject<string>();
permissionEvent = new Subject<PermissionModel>();
error = new Subject<Error>();
success = new Subject<string>();
private handlers: { [id: string]: ContentActionHandler } = {};

View File

@@ -86,15 +86,15 @@ describe('AddPermissionComponent', () => {
fixture.componentInstance.selectedItems = fakeAuthorityResults;
spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(of(new Node({ id: 'fake-node-id'})));
await fixture.componentInstance.success.subscribe((node) => {
expect(node.id).toBe('fake-node-id');
});
let lastValue: Node;
fixture.componentInstance.success.subscribe((node) => lastValue = node);
fixture.detectChanges();
await fixture.whenStable();
const addButton = element.querySelector<HTMLButtonElement>('#adf-add-permission-action-button');
addButton.click();
expect(lastValue.id).toBe('fake-node-id');
});
it('should NOT emit a success event when the user does not have permission to update the node', () => {
@@ -111,13 +111,15 @@ describe('AddPermissionComponent', () => {
fixture.componentInstance.selectedItems = fakeAuthorityResults;
spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(throwError({ error: 'err'}));
await fixture.componentInstance.error.subscribe((error) => {
expect(error.error).toBe('err');
});
let lastValue: any;
fixture.componentInstance.error.subscribe((error) => lastValue = error);
fixture.detectChanges();
await fixture.whenStable();
const addButton = element.querySelector<HTMLButtonElement>('#adf-add-permission-action-button');
addButton.click();
expect(lastValue.error).toBe('err');
});
});

View File

@@ -39,11 +39,11 @@ export class AddPermissionComponent implements OnInit {
/** Emitted when the node is updated successfully. */
@Output()
success: EventEmitter<Node> = new EventEmitter();
success = new EventEmitter<Node>();
/** Emitted when an error occurs during the update. */
@Output()
error: EventEmitter<any> = new EventEmitter();
error = new EventEmitter<any>();
selectedItems: NodeEntry[] = [];
currentNode: Node;

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { LogService, UserPreferencesService } from '@alfresco/adf-core';
import { UserPreferencesService } from '@alfresco/adf-core';
import { TagService } from './tag.service';
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
import { ContentTestingModule } from '../../testing/content.testing.module';
@@ -25,8 +25,8 @@ import { Pagination, Tag, TagBody, TagEntry, TagPaging, TagPagingList } from '@a
describe('TagService', () => {
let service: TagService;
let logService: LogService;
let userPreferencesService: UserPreferencesService;
let tagEntry: TagEntry;
const mockTagPaging = (): TagPaging => {
const tagPaging = new TagPaging();
@@ -45,17 +45,19 @@ describe('TagService', () => {
imports: [TranslateModule.forRoot(), ContentTestingModule]
});
service = TestBed.inject(TagService);
logService = TestBed.inject(LogService);
userPreferencesService = TestBed.inject(UserPreferencesService);
tagEntry = new TagEntry({ entry: { id: '1', tag: 'test-tag' } });
spyOn(service.tagsApi, 'deleteTagFromNode').and.returnValue(Promise.resolve());
spyOn(service.tagsApi, 'createTagForNode').and.returnValue(Promise.resolve(new TagEntry({})));
spyOn(service.tagsApi, 'createTagForNode').and.returnValue(Promise.resolve(tagEntry));
spyOn(service.tagsApi, 'deleteTag').and.returnValue(Promise.resolve());
});
describe('Content tests', () => {
it('should catch errors on getTagsByNodeId call', async () => {
spyOn(service, 'getTagsByNodeId').and.returnValue(throwError({ error: 'error' }));
await service.getTagsByNodeId('fake-node-id').subscribe(
service.getTagsByNodeId('fake-node-id').subscribe(
() => {
throwError('This call should fail');
},
@@ -66,31 +68,28 @@ describe('TagService', () => {
});
it('should trigger a refresh event on removeTag() call', async () => {
await service.refresh.subscribe(() => {
expect(service.tagsApi.deleteTagFromNode).toHaveBeenCalledWith('fake-node-id', 'fake-tag');
});
service.removeTag('fake-node-id', 'fake-tag');
expect(service.tagsApi.deleteTagFromNode).toHaveBeenCalledWith('fake-node-id', 'fake-tag');
});
it('should trigger a refresh event on addTag() call', async () => {
await service.refresh.subscribe((res) => {
expect(res).toBeDefined();
});
let lastValue: any;
service.refresh.subscribe((res) => lastValue = res);
service.addTag('fake-node-id', 'fake-tag');
await service.addTag('fake-node-id', 'fake-tag').toPromise();
expect(lastValue).toBe(tagEntry);
});
it('should trigger a refresh event on deleteTag() call', async () => {
await service.refresh.subscribe((res) => {
expect(res).toBeDefined();
});
let lastValue = false;
service.refresh.subscribe(() => lastValue = true);
service.deleteTag('fake-tag-id');
await service.deleteTag('fake-tag-id').toPromise();
expect(lastValue).toBeTrue();
});
describe('createTags', () => {
it('should call createTags on tagsApi', (done) => {
it('should call createTags on tagsApi', () => {
spyOn(service.tagsApi, 'createTags').and.returnValue(Promise.resolve([]));
const tag1 = new TagBody();
tag1.tag = 'Some tag 1';
@@ -100,10 +99,9 @@ describe('TagService', () => {
service.createTags(tags);
expect(service.tagsApi.createTags).toHaveBeenCalledWith(tags);
done();
});
it('should emit refresh when tags creation is success', fakeAsync(() => {
it('should emit refresh when tags creation is success', async () => {
const tags: TagEntry[] = [
{
entry: {
@@ -114,19 +112,10 @@ describe('TagService', () => {
];
spyOn(service.refresh, 'emit');
spyOn(service.tagsApi, 'createTags').and.returnValue(Promise.resolve(tags));
service.createTags([]);
tick();
expect(service.refresh.emit).toHaveBeenCalledWith(tags);
}));
it('should call error on logService when error occurs during tags creation', fakeAsync(() => {
spyOn(logService, 'error');
const error = 'Some error';
spyOn(service.tagsApi, 'createTags').and.returnValue(Promise.reject(error));
service.createTags([]);
tick();
expect(logService.error).toHaveBeenCalledWith(error);
}));
await service.createTags([]).toPromise();
expect(service.refresh.emit).toHaveBeenCalledWith(tags);
});
});
describe('getAllTheTags', () => {
@@ -176,18 +165,6 @@ describe('TagService', () => {
});
tick();
}));
it('should call error on logService when error occurs during fetching paging object for tags', fakeAsync(() => {
spyOn(logService, 'error');
const error: string = 'Some error';
spyOn(service.tagsApi, 'listTags').and.returnValue(Promise.reject(error));
service.getAllTheTags().subscribe({
error: () => {
expect(logService.error).toHaveBeenCalledWith(error);
}
});
tick();
}));
});
describe('searchTags', () => {
@@ -247,18 +224,6 @@ describe('TagService', () => {
});
tick();
}));
it('should call error on logService when error occurs during fetching paging object for tags', fakeAsync(() => {
spyOn(logService, 'error');
const error: string = 'Some error';
spyOn(service.tagsApi, 'listTags').and.returnValue(Promise.reject(error));
service.searchTags('test').subscribe({
error: () => {
expect(logService.error).toHaveBeenCalledWith(error);
}
});
tick();
}));
});
describe('updateTag', () => {
@@ -283,22 +248,12 @@ describe('TagService', () => {
expect(service.tagsApi.updateTag).toHaveBeenCalledWith(tag.entry.id, tagBody);
});
it('should emit refresh when tag updated successfully', fakeAsync(() => {
it('should emit refresh when tag updated successfully', async () => {
spyOn(service.refresh, 'emit');
spyOn(service.tagsApi, 'updateTag').and.returnValue(Promise.resolve(updatedTag));
service.updateTag(tag.entry.id, tagBody);
tick();
await service.updateTag(tag.entry.id, tagBody).toPromise();
expect(service.refresh.emit).toHaveBeenCalledWith(updatedTag);
}));
it('should call error on logService when error occurs during tag update', fakeAsync(() => {
spyOn(logService, 'error');
const error = 'Some error';
spyOn(service.tagsApi, 'updateTag').and.returnValue(Promise.reject(error));
service.updateTag(tag.entry.id, tagBody);
tick();
expect(logService.error).toHaveBeenCalledWith(error);
}));
});
});
describe('findTagByName', () => {
@@ -334,19 +289,6 @@ describe('TagService', () => {
done();
});
});
it('should call error on logService when error occurs during fetching tag for name', fakeAsync(() => {
spyOn(logService, 'error');
const error = 'Some error';
spyOn(service.tagsApi, 'listTags').and.returnValue(Promise.reject(error));
service.findTagByName(tagName).subscribe({
error: () => {
expect(logService.error).toHaveBeenCalledWith(error);
}
});
tick();
}));
});
describe('assignTagsToNode', () => {

View File

@@ -15,17 +15,16 @@
* limitations under the License.
*/
import { AlfrescoApiService, LogService, UserPreferencesService } from '@alfresco/adf-core';
import { AlfrescoApiService, UserPreferencesService } from '@alfresco/adf-core';
import { EventEmitter, Injectable, Output } from '@angular/core';
import { from, Observable, throwError } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
import { from, Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { TagBody, TagEntry, TagPaging, TagsApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
})
export class TagService {
private _tagsApi: TagsApi;
get tagsApi(): TagsApi {
this._tagsApi = this._tagsApi ?? new TagsApi(this.apiService.getInstance());
@@ -36,10 +35,7 @@ export class TagService {
@Output()
refresh = new EventEmitter();
constructor(private apiService: AlfrescoApiService,
private logService: LogService,
private userPreferencesService: UserPreferencesService) {
}
constructor(private apiService: AlfrescoApiService, private userPreferencesService: UserPreferencesService) {}
/**
* Gets a list of tags added to a node.
@@ -48,9 +44,7 @@ export class TagService {
* @returns TagPaging object (defined in JS-API) containing the tags
*/
getTagsByNodeId(nodeId: string): Observable<TagPaging> {
return from(this.tagsApi.listTagsForNode(nodeId)).pipe(
catchError((err) => this.handleError(err))
);
return from(this.tagsApi.listTagsForNode(nodeId));
}
/**
@@ -61,10 +55,12 @@ export class TagService {
* @returns TagPaging object (defined in JS-API) containing the tags
*/
getAllTheTags(opts?: any, includedCounts?: boolean): Observable<TagPaging> {
return from(this.tagsApi.listTags({
include: includedCounts ? ['count'] : undefined,
...opts
})).pipe(catchError((err) => this.handleError(err)));
return from(
this.tagsApi.listTags({
include: includedCounts ? ['count'] : undefined,
...opts
})
);
}
/**
@@ -78,15 +74,7 @@ export class TagService {
const tagBody = new TagBody();
tagBody.tag = tagName;
const observableAdd = from(this.tagsApi.createTagForNode(nodeId, [tagBody]));
observableAdd.subscribe((tagEntry: TagEntry) => {
this.refresh.emit(tagEntry);
}, (err) => {
this.handleError(err);
});
return observableAdd;
return from(this.tagsApi.createTagForNode(nodeId, [tagBody])).pipe(tap((tagEntry) => this.refresh.emit(tagEntry)));
}
/**
@@ -97,15 +85,7 @@ export class TagService {
* @returns Null object when the operation completes
*/
removeTag(nodeId: string, tag: string): Observable<void> {
const observableRemove = from(this.tagsApi.deleteTagFromNode(nodeId, tag));
observableRemove.subscribe(() => {
this.refresh.emit();
}, (err) => {
this.handleError(err);
});
return observableRemove;
return from(this.tagsApi.deleteTagFromNode(nodeId, tag)).pipe(tap(() => this.refresh.emit()));
}
/**
@@ -115,12 +95,7 @@ export class TagService {
* @returns Created tags.
*/
createTags(tags: TagBody[]): Observable<TagEntry[]> {
const observableAdd$: Observable<TagEntry[]> = from(this.tagsApi.createTags(tags));
observableAdd$.subscribe(
(tagsEntries: TagEntry[]) => this.refresh.emit(tagsEntries),
(err) => this.handleError(err)
);
return observableAdd$;
return from(this.tagsApi.createTags(tags)).pipe(tap((tagEntries) => this.refresh.emit(tagEntries)));
}
/**
@@ -131,12 +106,7 @@ export class TagService {
* @returns Updated tag.
*/
updateTag(tagId: string, tagBody: TagBody): Observable<TagEntry> {
const observableUpdate$: Observable<TagEntry> = from(this.tagsApi.updateTag(tagId, tagBody));
observableUpdate$.subscribe(
(tagEntry: TagEntry) => this.refresh.emit(tagEntry),
(err) => this.handleError(err)
);
return observableUpdate$;
return from(this.tagsApi.updateTag(tagId, tagBody)).pipe(tap((tagEntry) => this.refresh.emit(tagEntry)));
}
/**
@@ -150,16 +120,24 @@ export class TagService {
* @param maxItems Specify max number of returned tags. Default is specified by UserPreferencesService.
* @returns Found tags which name contains searched name.
*/
searchTags(name: string, sorting = { orderBy: 'tag', direction: 'asc' },
includedCounts?: boolean, skipCount = 0, maxItems?: number): Observable<TagPaging> {
searchTags(
name: string,
sorting = { orderBy: 'tag', direction: 'asc' },
includedCounts?: boolean,
skipCount = 0,
maxItems?: number
): Observable<TagPaging> {
maxItems = maxItems || this.userPreferencesService.paginationSize;
return this.getAllTheTags({
tag: `*${name}*`,
skipCount,
maxItems,
sorting,
matching: true
}, includedCounts).pipe(catchError((err) => this.handleError(err)));
return this.getAllTheTags(
{
tag: `*${name}*`,
skipCount,
maxItems,
sorting,
matching: true
},
includedCounts
);
}
/**
@@ -169,10 +147,7 @@ export class TagService {
* @returns Found tag which name matches exactly to passed name.
*/
findTagByName(name: string): Observable<TagEntry> {
return this.getAllTheTags({ tag: name }).pipe(
map((result) => result.list.entries[0]),
catchError((error) => this.handleError(error))
);
return this.getAllTheTags({ tag: name }).pipe(map((result) => result.list.entries[0]));
}
/**
@@ -184,9 +159,7 @@ export class TagService {
* @returns Null object when the operation completes
*/
deleteTag(tagId: string): Observable<void> {
return from(this.tagsApi.deleteTag(tagId)).pipe(
tap((data) => this.refresh.emit(data))
);
return from(this.tagsApi.deleteTag(tagId)).pipe(tap(() => this.refresh.emit()));
}
/**
@@ -197,13 +170,6 @@ export class TagService {
* @returns Just linked tags to node or single tag if linked only one tag.
*/
assignTagsToNode(nodeId: string, tags: TagBody[]): Observable<TagPaging | TagEntry> {
return from(this.tagsApi.assignTagsToNode(nodeId, tags)).pipe(
tap((data) => this.refresh.emit(data))
);
}
private handleError(error: any) {
this.logService.error(error);
return throwError(error || 'Server error');
return from(this.tagsApi.assignTagsToNode(nodeId, tags)).pipe(tap((data) => this.refresh.emit(data)));
}
}

View File

@@ -146,7 +146,7 @@ describe('UploadButtonComponent', () => {
expect(uploadService.uploadFilesInTheQueue).not.toHaveBeenCalled();
});
it('should create a folder and emit an File uploaded event', async () => {
it('should create a folder and emit an File uploaded event', () => {
component.rootFolderId = '-my-';
spyOn(nodesApiService, 'getNode').and.returnValue(of(fakeFolderNodeWithPermission.entry));
@@ -154,9 +154,8 @@ describe('UploadButtonComponent', () => {
component.ngOnChanges({ rootFolderId: new SimpleChange(null, component.rootFolderId, true) });
fixture.detectChanges();
await component.success.subscribe((e) => {
expect(e.value).toEqual('File uploaded');
});
let lastValue: any;
component.success.subscribe((res) => lastValue = res);
spyOn(component, 'uploadFiles').and.callFake(() => {
component.success.emit({
@@ -164,6 +163,7 @@ describe('UploadButtonComponent', () => {
});
});
component.onDirectoryAdded(fakeEvent);
expect(lastValue.value).toEqual('File uploaded');
});
it('should by default the title of the button get from the JSON file', () => {
@@ -245,14 +245,14 @@ describe('UploadButtonComponent', () => {
expect(addToQueueSpy.calls.mostRecent()).toBeUndefined();
});
it('should output an error when you try to upload a file too big', async () => {
it('should output an error when you try to upload a file too big', () => {
component.maxFilesSize = 100;
await component.error.subscribe((res) => {
expect(res).toBeDefined();
});
let lastValue: FileUploadErrorEvent;
component.error.subscribe((res) => lastValue = res);
component.uploadFiles(files);
expect(lastValue).toBeDefined();
});
it('should not filter out files if max file size is not set', () => {
@@ -346,19 +346,19 @@ describe('UploadButtonComponent', () => {
expect(uploadService.uploadFilesInTheQueue).not.toHaveBeenCalled();
});
it('should emit an error message when getNode fails', async () => {
it('should emit an error message when getNode fails', () => {
component.rootFolderId = 'nodeId';
spyOn(nodesApiService, 'getNode').and.returnValue(throwError('error'));
await component.error.subscribe((value: FileUploadErrorEvent) => {
expect(value.error).toBe('FILE_UPLOAD.BUTTON.PERMISSION_CHECK_ERROR');
});
let lastValue: FileUploadErrorEvent;
component.error.subscribe((value) => lastValue = value);
component.ngOnChanges({ rootFolderId: new SimpleChange(null, component.rootFolderId, true) });
fixture.detectChanges();
component.onFilesAdded(fakeEvent);
expect(lastValue.error).toBe('FILE_UPLOAD.BUTTON.PERMISSION_CHECK_ERROR');
});
it('should not call uploadFiles for node with other permissions', () => {
@@ -394,13 +394,13 @@ describe('UploadButtonComponent', () => {
fixture.detectChanges();
});
it('should emit error if upload errored', async () => {
it('should emit error if upload errored', () => {
spyOn(uploadService, 'getUploadPromise').and.returnValue(mockUploadErrorPromise);
await component.error.subscribe((error) => {
expect(error).not.toBeNull();
});
let lastValue: FileUploadErrorEvent;
component.error.subscribe((error) => lastValue = error);
component.onFilesAdded(fakeEvent);
expect(lastValue).not.toBeNull();
});
});
});

View File

@@ -22,6 +22,7 @@ import { TranslateModule } from '@ngx-translate/core';
import { mockUploadSuccessPromise, mockUploadErrorPromise } from '../../mock/upload.service.mock';
import { UploadService } from '../../common/services/upload.service';
import { FileModel } from '../../common/models/file.model';
import { FileUploadErrorEvent } from '../../common/events/file.event';
const getFakeShareDataRow = (allowableOperations = ['delete', 'update', 'create']) => ({
obj: {
@@ -180,7 +181,7 @@ describe('UploadDragAreaComponent', () => {
fixture.detectChanges();
const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
const fakeCustomEvent = new CustomEvent('CustomEvent', {
detail: { data: getFakeShareDataRow([]), files: [fakeItem] }
});
component.onUploadFiles(fakeCustomEvent);
@@ -255,7 +256,7 @@ describe('UploadDragAreaComponent', () => {
expect(fileList.options.path).toBe('pippo/');
});
const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
const fakeCustomEvent = new CustomEvent('CustomEvent', {
detail: {
data: getFakeShareDataRow(),
files: [fakeItem]
@@ -294,7 +295,7 @@ describe('UploadDragAreaComponent', () => {
it('should upload a file when user has create permission on target folder', () => {
const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
const fakeCustomEvent = new CustomEvent('CustomEvent', {
detail: {
data: getFakeShareDataRow(),
files: [fakeItem]
@@ -318,7 +319,7 @@ describe('UploadDragAreaComponent', () => {
}
};
const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
const fakeCustomEvent = new CustomEvent('CustomEvent', {
detail: {
data: getFakeShareDataRow(),
files: [fakePngItem]
@@ -348,7 +349,7 @@ describe('UploadDragAreaComponent', () => {
}
};
const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
const fakeCustomEvent = new CustomEvent('CustomEvent', {
detail: {
data: getFakeShareDataRow(),
files: [fakeSuperItem]
@@ -368,7 +369,7 @@ describe('UploadDragAreaComponent', () => {
it('should trigger updating the file version when we drop a file over another file', async () => {
spyOn(component.updateFileVersion, 'emit');
const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
const fakeCustomEvent = new CustomEvent('CustomEvent', {
detail: {
data: getFakeFileShareRow(),
files: [fakeItem]
@@ -388,32 +389,33 @@ describe('UploadDragAreaComponent', () => {
it('should raise an error if upload a file goes wrong', async () => {
spyOn(uploadService, 'getUploadPromise').and.callThrough();
const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
const fakeCustomEvent = new CustomEvent('CustomEvent', {
detail: {
data: getFakeShareDataRow(),
files: [fakeItem]
}
});
component.error.subscribe((error) => {
expect(error).not.toBeNull();
});
let lastValue: FileUploadErrorEvent;
component.error.subscribe((error) => lastValue = error);
component.onUploadFiles(fakeCustomEvent);
fixture.detectChanges();
await fixture.whenStable();
expect(lastValue).not.toBeNull();
});
it('should emit success if successful of upload a file', async () => {
it('should emit success if successful of upload a file', () => {
spyOn(uploadService, 'getUploadPromise').and.returnValue(mockUploadSuccessPromise);
fixture.detectChanges();
await component.success.subscribe((success) => {
expect(success).not.toBeNull();
});
let lastValue: any;
component.success.subscribe((success) => lastValue = success);
const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
const fakeCustomEvent = new CustomEvent('CustomEvent', {
detail: {
data: getFakeShareDataRow(),
files: [fakeItem]
@@ -421,18 +423,18 @@ describe('UploadDragAreaComponent', () => {
});
component.onUploadFiles(fakeCustomEvent);
expect(lastValue).not.toBeNull();
});
it('should emit error if upload errored', async () => {
it('should emit error if upload errored', () => {
spyOn(uploadService, 'getUploadPromise').and.returnValue(mockUploadErrorPromise);
fixture.detectChanges();
await component.error.subscribe((error) => {
expect(error).not.toBeNull();
});
let lastValue: FileUploadErrorEvent;
component.error.subscribe((error) => lastValue = error);
const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
const fakeCustomEvent = new CustomEvent('CustomEvent', {
detail: {
data: getFakeShareDataRow(),
files: [fakeItem]
@@ -440,6 +442,7 @@ describe('UploadDragAreaComponent', () => {
});
component.onUploadFiles(fakeCustomEvent);
expect(lastValue).not.toBeNull();
});
});
});

View File

@@ -48,7 +48,7 @@ describe('VersionManagerComponent', () => {
component.node = node;
nodesApiService = TestBed.inject(NodesApiService);
spyOnListVersionHistory = spyOn(component.versionListComponent['versionsApi'], 'listVersionHistory').and.callFake(() =>
spyOnListVersionHistory = spyOn(component.versionListComponent.versionsApi, 'listVersionHistory').and.callFake(() =>
Promise.resolve(new VersionPaging({ list: { entries: [versionEntry] } }))
);
});
@@ -81,24 +81,25 @@ describe('VersionManagerComponent', () => {
expect(versionCommentEl).toBeNull();
});
it('should emit success event upon successful upload of a new version', async () => {
it('should emit success event upon successful upload of a new version', () => {
fixture.detectChanges();
const emittedData = { value: { entry: node } };
await component.uploadSuccess.subscribe((event) => {
expect(event).toBe(node);
});
let lastValue: Node;
component.uploadSuccess.subscribe((event) => lastValue = event);
component.onUploadSuccess(emittedData);
expect(lastValue).toBe(node);
});
it('should emit nodeUpdated event upon successful upload of a new version', () => {
fixture.detectChanges();
nodesApiService.nodeUpdated.subscribe((res) => {
expect(res).toEqual(node);
});
let lastValue: Node;
nodesApiService.nodeUpdated.subscribe((res) => lastValue = res);
const emittedData = { value: { entry: node } };
component.onUploadSuccess(emittedData);
expect(lastValue).toEqual(node);
});
describe('Animation', () => {

View File

@@ -61,7 +61,7 @@ describe('Auth Guard SSO role service', () => {
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
router.data = { roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'] };
expect(await authGuard.canActivate(router)).toBeTruthy();
expect(authGuard.canActivate(router)).toBeTruthy();
});
it('Should canActivate be true if case of empty roles to check', async () => {
@@ -69,7 +69,7 @@ describe('Auth Guard SSO role service', () => {
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
router.data = { roles: [] };
expect(await authGuard.canActivate(router)).toBeTruthy();
expect(authGuard.canActivate(router)).toBeTruthy();
});
it('Should canActivate be false if the Role is not present int the JWT token', async () => {
@@ -77,7 +77,7 @@ describe('Auth Guard SSO role service', () => {
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
router.data = { roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'] };
expect(await authGuard.canActivate(router)).toBeFalsy();
expect(authGuard.canActivate(router)).toBeFalsy();
});
it('Should not redirect if canActivate is', async () => {
@@ -87,7 +87,7 @@ describe('Auth Guard SSO role service', () => {
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
router.data = { roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'] };
expect(await authGuard.canActivate(router)).toBeTruthy();
expect(authGuard.canActivate(router)).toBeTruthy();
expect(routerService.navigate).not.toHaveBeenCalled();
});
@@ -95,7 +95,7 @@ describe('Auth Guard SSO role service', () => {
spyUserAccess(['MOCK_USER_ROLE', 'MOCK_ROOT_USER_ROLE'], {});
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
expect(await authGuard.canActivate(router)).toBeFalsy();
expect(authGuard.canActivate(router)).toBeFalsy();
});
it('Should redirect to the redirectURL if canActivate is false and redirectUrl is in data', async () => {
@@ -105,7 +105,7 @@ describe('Auth Guard SSO role service', () => {
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
router.data = { roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'], redirectUrl: 'no-role-url' };
expect(await authGuard.canActivate(router)).toBeFalsy();
expect(authGuard.canActivate(router)).toBeFalsy();
expect(routerService.navigate).toHaveBeenCalledWith(['/no-role-url']);
});
@@ -116,7 +116,7 @@ describe('Auth Guard SSO role service', () => {
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
router.data = { roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'] };
expect(await authGuard.canActivate(router)).toBeFalsy();
expect(authGuard.canActivate(router)).toBeFalsy();
expect(routerService.navigate).not.toHaveBeenCalled();
});
@@ -127,7 +127,7 @@ describe('Auth Guard SSO role service', () => {
route.params = { appName: 'mockApp' };
route.data = { clientRoles: ['appName'], roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'] };
expect(await authGuard.canActivate(route)).toBeFalsy();
expect(authGuard.canActivate(route)).toBeFalsy();
});
it('Should canActivate be false if hasRealm is false and hasClientRole is true', async () => {
@@ -137,7 +137,7 @@ describe('Auth Guard SSO role service', () => {
route.params = { appName: 'mockApp' };
route.data = { clientRoles: ['mockApp'], roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'] };
expect(await authGuard.canActivate(route)).toBeFalsy();
expect(authGuard.canActivate(route)).toBeFalsy();
});
it('Should canActivate be true if both Real Role and Client Role are present int the JWT token', async () => {
@@ -147,7 +147,7 @@ describe('Auth Guard SSO role service', () => {
route.params = { appName: 'mockApp' };
route.data = { clientRoles: ['appName'], roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'] };
expect(await authGuard.canActivate(route)).toBeTruthy();
expect(authGuard.canActivate(route)).toBeTruthy();
});
it('Should canActivate be false if the Client Role is not present int the JWT token with the correct role', async () => {
@@ -157,7 +157,7 @@ describe('Auth Guard SSO role service', () => {
route.params = { appName: 'mockApp' };
route.data = { clientRoles: ['appName'], roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'] };
expect(await authGuard.canActivate(route)).toBeFalsy();
expect(authGuard.canActivate(route)).toBeFalsy();
});
it('Should canActivate be false hasRealm is true and hasClientRole is false', async () => {
@@ -171,7 +171,7 @@ describe('Auth Guard SSO role service', () => {
route.params = { appName: 'mockApp' };
route.data = { clientRoles: ['appName'], roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'] };
expect(await authGuard.canActivate(route)).toBeFalsy();
expect(authGuard.canActivate(route)).toBeFalsy();
expect(materialDialog.closeAll).toHaveBeenCalled();
});
@@ -182,7 +182,7 @@ describe('Auth Guard SSO role service', () => {
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
router.data = { roles: ['MOCK_ANOTHER_ROLE'], excludedRoles: ['MOCK_USER_ROLE'] };
expect(await authGuard.canActivate(router)).toBe(false);
expect(authGuard.canActivate(router)).toBe(false);
});
it('Should canActivate be true when the user has none of the excluded roles', async () => {
@@ -190,8 +190,7 @@ describe('Auth Guard SSO role service', () => {
const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot();
router.data = { roles: ['MOCK_USER_ROLE', 'MOCK_ADMIN_ROLE'], excludedRoles: ['MOCK_ROOT_USER_ROLE'] };
const result = await authGuard.canActivate(router);
expect(result).toBeTruthy();
expect(authGuard.canActivate(router)).toBeTruthy();
});
});

View File

@@ -22,6 +22,7 @@ import { WidgetComponent } from './widget.component';
import { CoreTestingModule } from '../../../testing';
import { TranslateModule } from '@ngx-translate/core';
import { filter } from 'rxjs/operators';
import { FormRulesEvent } from '../../events/form-rules.event';
describe('WidgetComponent', () => {
@@ -69,40 +70,43 @@ describe('WidgetComponent', () => {
expect(widget.hasField()).toBeTruthy();
});
it('should send an event after view init', async () => {
it('should send an event after view init', () => {
const fakeForm = new FormModel();
const fakeField = new FormFieldModel(fakeForm, { id: 'fakeField', value: 'fakeValue' });
widget.field = fakeField;
await widget.fieldChanged.subscribe((field) => {
expect(field).not.toBe(null);
expect(field.id).toBe('fakeField');
expect(field.value).toBe('fakeValue');
});
let lastValue: FormFieldModel;
widget.fieldChanged.subscribe((field) => lastValue = field);
widget.ngAfterViewInit();
expect(lastValue).not.toBe(null);
expect(lastValue.id).toBe('fakeField');
expect(lastValue.value).toBe('fakeValue');
});
it('should send an event when a field is changed', async () => {
it('should send an event when a field is changed', () => {
const fakeForm = new FormModel();
const fakeField = new FormFieldModel(fakeForm, { id: 'fakeField', value: 'fakeValue' });
await widget.fieldChanged.subscribe((field) => {
expect(field).not.toBe(null);
expect(field.id).toBe('fakeField');
expect(field.value).toBe('fakeValue');
});
let lastValue: FormFieldModel;
widget.fieldChanged.subscribe((field) => lastValue = field);
widget.onFieldChanged(fakeField);
expect(lastValue).not.toBe(null);
expect(lastValue.id).toBe('fakeField');
expect(lastValue.value).toBe('fakeValue');
});
it('should send a rule event when a field is changed', async () => {
it('should send a rule event when a field is changed', () => {
const fakeForm = new FormModel();
const fakeField = new FormFieldModel(fakeForm, { id: 'fakeField', value: 'fakeValue' });
await widget.formService.formRulesEvent.subscribe((event) => {
expect(event.type).toEqual('fieldValueChanged');
});
let lastValue: FormRulesEvent;
widget.formService.formRulesEvent.subscribe((event) => lastValue = event);
widget.onFieldChanged(fakeField);
expect(lastValue.type).toEqual('fieldValueChanged');
});
it('should eval isRequired state of the field', () => {

View File

@@ -53,7 +53,7 @@ describe('DownloadPromptDialogComponent', () => {
const waitButton = getButton('#waitButton');
waitButton.dispatchEvent(new Event('click'));
await fixture.detectChanges();
fixture.detectChanges();
await fixture.whenStable();
expect(matDialogRef.close).toHaveBeenCalledWith(DownloadPromptActions.WAIT);
@@ -63,7 +63,7 @@ describe('DownloadPromptDialogComponent', () => {
const waitButton = getButton('#downloadButton');
waitButton.dispatchEvent(new Event('click'));
await fixture.detectChanges();
fixture.detectChanges();
await fixture.whenStable();
expect(matDialogRef.close).toHaveBeenCalledWith(DownloadPromptActions.DOWNLOAD);

View File

@@ -92,7 +92,7 @@ describe('ViewerComponent', () => {
it('should not reload the content of all the viewer after type change', async () => {
const fixtureDouble = TestBed.createComponent(DoubleViewerComponent);
await fixtureDouble.detectChanges();
fixtureDouble.detectChanges();
await fixtureDouble.whenStable();
fixtureDouble.componentInstance.urlFileViewer1 = 'fake-test-file.pdf';
@@ -101,7 +101,7 @@ describe('ViewerComponent', () => {
fixtureDouble.componentInstance.viewer1.ngOnChanges();
fixtureDouble.componentInstance.viewer2.ngOnChanges();
await fixtureDouble.detectChanges();
fixtureDouble.detectChanges();
await fixtureDouble.whenStable();
expect(fixtureDouble.componentInstance.viewer1.viewerType).toBe('pdf');
@@ -110,7 +110,7 @@ describe('ViewerComponent', () => {
fixtureDouble.componentInstance.urlFileViewer1 = 'fake-test-file.pdf';
fixtureDouble.componentInstance.urlFileViewer2 = 'fake-test-file-two.png';
await fixtureDouble.detectChanges();
fixtureDouble.detectChanges();
await fixtureDouble.whenStable();
fixtureDouble.componentInstance.viewer1.ngOnChanges();

View File

@@ -71,7 +71,7 @@ describe('AnalyticsReportListComponent', () => {
expect(component.isReportsEmpty()).toBeTruthy();
});
it('should return the default reports when the report list is empty', async () => {
it('should return the default reports when the report list is empty', (done) => {
jasmine.Ajax.stubRequest('http://localhost:9876/bpm/activiti-app/app/rest/reporting/reports').andReturn({
status: 200,
contentType: 'json',
@@ -92,7 +92,7 @@ describe('AnalyticsReportListComponent', () => {
responseText: reportList
});
await component.success.subscribe(() => {
component.success.subscribe(() => {
fixture.detectChanges();
expect(element.querySelector('#report-list-0 .adf-activiti-filters__entry-icon').innerHTML).toBe('assignment');
expect(element.querySelector('#report-list-0 > span').innerHTML).toBe('Fake Test Process definition heat map');
@@ -101,13 +101,14 @@ describe('AnalyticsReportListComponent', () => {
expect(element.querySelector('#report-list-3 > span').innerHTML).toBe('Fake Test Task overview');
expect(element.querySelector('#report-list-4 > span').innerHTML).toBe('Fake Test Task service level agreement');
expect(component.isReportsEmpty()).toBeFalsy();
done();
});
});
it('Report render the report list relative to a single app', async () => {
it('Report render the report list relative to a single app', (done) => {
fixture.detectChanges();
await component.success.subscribe(() => {
component.success.subscribe(() => {
fixture.detectChanges();
expect(element.querySelector('#report-list-0 .adf-activiti-filters__entry-icon').innerHTML).toBe('assignment');
expect(element.querySelector('#report-list-0 > span').innerHTML).toBe('Fake Test Process definition heat map');
@@ -116,6 +117,7 @@ describe('AnalyticsReportListComponent', () => {
expect(element.querySelector('#report-list-3 > span').innerHTML).toBe('Fake Test Task overview');
expect(element.querySelector('#report-list-4 > span').innerHTML).toBe('Fake Test Task service level agreement');
expect(component.isReportsEmpty()).toBeFalsy();
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
@@ -125,11 +127,12 @@ describe('AnalyticsReportListComponent', () => {
});
});
it('Report emit an error with a empty response', async () => {
it('Report emit an error with a empty response', (done) => {
fixture.detectChanges();
await component.error.subscribe((err) => {
component.error.subscribe((err) => {
expect(err).toBeDefined();
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
@@ -158,15 +161,16 @@ describe('AnalyticsReportListComponent', () => {
expect(component.isSelected(anotherReport)).toBe(false);
});
it('Should reload the report list', async () => {
it('Should reload the report list', (done) => {
component.initObserver();
const report = new ReportParametersModel({ id: 2002, name: 'Fake Test Process definition heat map' });
component.reports = [report];
expect(component.reports.length).toEqual(1);
component.reload();
await component.success.subscribe(() => {
component.success.subscribe(() => {
expect(component.reports.length).toEqual(5);
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
@@ -176,17 +180,18 @@ describe('AnalyticsReportListComponent', () => {
});
});
it('Should reload the report list and select the report with the given id', async () => {
it('Should reload the report list and select the report with the given id', (done) => {
component.initObserver();
expect(component.reports.length).toEqual(0);
component.reload(2002);
await component.success.subscribe(() => {
component.success.subscribe(() => {
expect(component.reports.length).toEqual(5);
expect(component.currentReport).toBeDefined();
expect(component.currentReport).not.toBeNull();
expect(component.currentReport.id).toEqual(2002);
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({

View File

@@ -15,9 +15,9 @@
* limitations under the License.
*/
import { AlfrescoApiService, LogService } from '@alfresco/adf-core';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { Injectable } from '@angular/core';
import { Observable, from, throwError, of } from 'rxjs';
import { Observable, from, of } from 'rxjs';
import { ParameterValueModel } from '../../diagram/models/report/parameter-value.model';
import { ReportParametersModel } from '../../diagram/models/report/report-parameters.model';
import { BarChart } from '../../diagram/models/chart/bar-chart.model';
@@ -27,12 +27,11 @@ import { HeatMapChart } from '../../diagram/models/chart/heat-map-chart.model';
import { MultiBarChart } from '../../diagram/models/chart/multi-bar-chart.model';
import { PieChart } from '../../diagram/models/chart/pie-chart.model';
import { TableChart } from '../../diagram/models/chart/table-chart.model';
import { map, catchError } from 'rxjs/operators';
import { map } from 'rxjs/operators';
import { ProcessDefinitionsApi, ReportApi } from '@alfresco/js-api';
@Injectable({ providedIn: 'root' })
export class AnalyticsService {
private _reportApi: ReportApi;
get reportApi(): ReportApi {
this._reportApi = this._reportApi ?? new ReportApi(this.apiService.getInstance());
@@ -45,9 +44,7 @@ export class AnalyticsService {
return this._processDefinitionsApi;
}
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
}
constructor(private apiService: AlfrescoApiService) {}
/**
* Retrieve all the Deployed app
@@ -56,20 +53,18 @@ export class AnalyticsService {
* @returns list or report parameter models
*/
getReportList(appId: number): Observable<ReportParametersModel[]> {
return from(this.reportApi.getReportList())
.pipe(
map((res: any) => {
const reports: ReportParametersModel[] = [];
res.forEach((report: ReportParametersModel) => {
const reportModel = new ReportParametersModel(report);
if (this.isReportValid(appId, report)) {
reports.push(reportModel);
}
});
return reports;
}),
catchError((err) => this.handleError(err))
);
return from(this.reportApi.getReportList()).pipe(
map((res) => {
const reports: ReportParametersModel[] = [];
res.forEach((report: ReportParametersModel) => {
const reportModel = new ReportParametersModel(report);
if (this.isReportValid(appId, report)) {
reports.push(reportModel);
}
});
return reports;
})
);
}
/**
@@ -79,19 +74,11 @@ export class AnalyticsService {
* @returns report model
*/
getReportByName(reportName: string): Observable<any> {
return from(this.reportApi.getReportList())
.pipe(
map((response: any) => response.find((report) => report.name === reportName)),
catchError((err) => this.handleError(err))
);
return from(this.reportApi.getReportList()).pipe(map((response) => response.find((report) => report.name === reportName)));
}
getReportParams(reportId: string): Observable<ReportParametersModel> {
return from(this.reportApi.getReportParams(reportId))
.pipe(
map((res: any) => new ReportParametersModel(res)),
catchError((err) => this.handleError(err))
);
return from(this.reportApi.getReportParams(reportId)).pipe(map((res) => new ReportParametersModel(res)));
}
getParamValuesByType(type: string, appId: number, reportId?: string, processDefinitionId?: string): Observable<ParameterValueModel[]> {
@@ -145,125 +132,85 @@ export class AnalyticsService {
}
getProcessDefinitionsValuesNoApp(): Observable<ParameterValueModel[]> {
return from(this.reportApi.getProcessDefinitions())
.pipe(
map((res: any) => {
const paramOptions: ParameterValueModel[] = [];
res.forEach((opt) => {
paramOptions.push(new ParameterValueModel(opt));
});
return paramOptions;
}),
catchError((err) => this.handleError(err))
);
return from(this.reportApi.getProcessDefinitions()).pipe(
map((res) => {
const paramOptions: ParameterValueModel[] = [];
res.forEach((opt) => {
paramOptions.push(new ParameterValueModel(opt));
});
return paramOptions;
})
);
}
getProcessDefinitionsValues(appId: number): Observable<ParameterValueModel[]> {
const options = { appDefinitionId: appId };
return from(this.processDefinitionsApi.getProcessDefinitions(options))
.pipe(
map((res: any) => {
const paramOptions: ParameterValueModel[] = [];
res.data.forEach((opt) => {
paramOptions.push(new ParameterValueModel(opt));
});
return paramOptions;
}),
catchError((err) => this.handleError(err))
);
return from(this.processDefinitionsApi.getProcessDefinitions(options)).pipe(
map((res) => {
const paramOptions: ParameterValueModel[] = [];
res.data.forEach((opt) => {
paramOptions.push(new ParameterValueModel(opt));
});
return paramOptions;
})
);
}
getTasksByProcessDefinitionId(reportId: string, processDefinitionId: string): Observable<ParameterValueModel[]> {
return from(this.reportApi.getTasksByProcessDefinitionId(reportId, processDefinitionId))
.pipe(
map((res: any) => {
const paramOptions: ParameterValueModel[] = [];
res.forEach((opt) => {
paramOptions.push(new ParameterValueModel({ id: opt, name: opt }));
});
return paramOptions;
}),
catchError((err) => this.handleError(err))
);
return from(this.reportApi.getTasksByProcessDefinitionId(reportId, processDefinitionId)).pipe(
map((res) => {
const paramOptions: ParameterValueModel[] = [];
res.forEach((opt) => {
paramOptions.push(new ParameterValueModel({ id: opt, name: opt }));
});
return paramOptions;
})
);
}
getReportsByParams(reportId: string, paramsQuery: any): Observable<Chart[]> {
return from(this.reportApi.getReportsByParams(reportId, paramsQuery))
.pipe(
map((res: any) => {
const elements: Chart[] = [];
res.elements.forEach((chartData) => {
if (chartData.type === 'pieChart') {
elements.push(new PieChart(chartData));
} else if (chartData.type === 'table') {
elements.push(new TableChart(chartData));
} else if (chartData.type === 'processDefinitionHeatMap') {
elements.push(new HeatMapChart(chartData));
} else if (chartData.type === 'masterDetailTable') {
elements.push(new DetailsTableChart(chartData));
} else if (chartData.type === 'barChart') {
elements.push(new BarChart(chartData));
} else if (chartData.type === 'multiBarChart') {
elements.push(new MultiBarChart(chartData));
}
});
return from(this.reportApi.getReportsByParams(reportId, paramsQuery)).pipe(
map((res: any) => {
const elements: Chart[] = [];
res.elements.forEach((chartData) => {
if (chartData.type === 'pieChart') {
elements.push(new PieChart(chartData));
} else if (chartData.type === 'table') {
elements.push(new TableChart(chartData));
} else if (chartData.type === 'processDefinitionHeatMap') {
elements.push(new HeatMapChart(chartData));
} else if (chartData.type === 'masterDetailTable') {
elements.push(new DetailsTableChart(chartData));
} else if (chartData.type === 'barChart') {
elements.push(new BarChart(chartData));
} else if (chartData.type === 'multiBarChart') {
elements.push(new MultiBarChart(chartData));
}
});
return elements;
}),
catchError((err) => this.handleError(err))
);
return elements;
})
);
}
createDefaultReports(): Observable<any> {
return from(this.reportApi.createDefaultReports())
.pipe(
map(res => res || {}),
catchError((err) => this.handleError(err))
);
return from(this.reportApi.createDefaultReports()).pipe(map((res) => res || {}));
}
updateReport(reportId: string, name: string): Observable<any> {
return from(this.reportApi.updateReport(reportId, name))
.pipe(
map(() => this.logService.info('upload')),
catchError((err) => this.handleError(err))
);
return from(this.reportApi.updateReport(reportId, name));
}
exportReportToCsv(reportId: string, paramsQuery: any): Observable<any> {
return from(this.reportApi.exportToCsv(reportId, paramsQuery))
.pipe(
map((res: any) => {
this.logService.info('export');
return res;
}),
catchError((err) => this.handleError(err))
);
return from(this.reportApi.exportToCsv(reportId, paramsQuery));
}
saveReport(reportId: string, paramsQuery: any): Observable<any> {
return from(this.reportApi.saveReport(reportId, paramsQuery))
.pipe(
map(() => {
this.logService.info('save');
}),
catchError((err) => this.handleError(err))
);
return from(this.reportApi.saveReport(reportId, paramsQuery));
}
deleteReport(reportId: string): Observable<any> {
return from(this.reportApi.deleteReport(reportId))
.pipe(
map(() => {
this.logService.info('delete');
}),
catchError((err) => this.handleError(err))
);
}
private handleError(error: any) {
this.logService.error(error);
return throwError(error || 'Server error');
return from(this.reportApi.deleteReport(reportId));
}
private isReportValid(appId: number, report: ReportParametersModel) {

View File

@@ -29,7 +29,8 @@ import {
AppConfigService,
UploadWidgetContentLinkModel,
LocalizedDatePipe,
NotificationService
NotificationService,
ContentLinkModel
} from '@alfresco/adf-core';
import {
allSourceParams,
@@ -578,11 +579,10 @@ describe('AttachFileCloudWidgetComponent', () => {
});
});
it('should preview file when show is clicked', async () => {
it('should preview file when show is clicked', () => {
spyOn(processCloudContentService, 'getRawContentNode').and.returnValue(of(new Blob()));
await formService.formContentClicked.subscribe((fileClicked: any) => {
expect(fileClicked.nodeId).toBe('fake-properties');
});
let lastValue: ContentLinkModel;
formService.formContentClicked.subscribe((fileClicked) => lastValue = fileClicked);
fixture.detectChanges();
const menuButton = fixture.debugElement.query(By.css('#file-fake-properties-option-menu')).nativeElement as HTMLButtonElement;
@@ -590,6 +590,8 @@ describe('AttachFileCloudWidgetComponent', () => {
fixture.detectChanges();
const showOption = fixture.debugElement.query(By.css('#file-fake-properties-show-file')).nativeElement as HTMLButtonElement;
showOption.click();
expect(lastValue.nodeId).toBe('fake-properties');
});
it('should request form to be updated with metadata when retrieve is clicked', async () => {

View File

@@ -148,7 +148,7 @@ describe('ContentCloudNodeSelectorService', () => {
expect(service.sourceNodeNotFound).toBe(true);
}
await service.openUploadFileDialog('nodeId', 'single', true, true);
service.openUploadFileDialog('nodeId', 'single', true, true);
expect(openDialogSpy).toHaveBeenCalled();
expect(showWarningSpy).toHaveBeenCalledWith('ADF_CLOUD_TASK_FORM.ERROR.DESTINATION_FOLDER_PATH_ERROR');
@@ -167,7 +167,7 @@ describe('ContentCloudNodeSelectorService', () => {
expect(service.sourceNodeNotFound).toBe(true);
}
await service.openUploadFileDialog('nodeId', 'single', true, true);
service.openUploadFileDialog('nodeId', 'single', true, true);
expect(openDialogSpy).toHaveBeenCalled();
expect(showWarningSpy).toHaveBeenCalledWith('ADF_CLOUD_TASK_FORM.ERROR.DESTINATION_FOLDER_PATH_ERROR');

View File

@@ -108,21 +108,18 @@ describe('ProcessFiltersCloudComponent', () => {
expect(filters[2].nativeElement.innerText).toContain('FakeCompletedProcesses');
});
it('should emit an error with a bad response', async () => {
const mockErrorFilterList = {
error: 'wrong request'
};
getProcessFiltersSpy.and.returnValue(throwError(mockErrorFilterList));
it('should emit an error with a bad response', () => {
getProcessFiltersSpy.and.returnValue(throwError('wrong request'));
const appName = 'my-app-1';
const change = new SimpleChange(null, appName, true);
await component.error.subscribe((err) => {
expect(err).toBeDefined();
});
let lastValue: any;
component.error.subscribe((err) => lastValue = err);
component.ngOnChanges({appName: change});
fixture.detectChanges();
expect(lastValue).toBeDefined();
});
it('should emit success with the filters when filters are loaded', async () => {

View File

@@ -63,16 +63,17 @@ describe('ProcessFilterCloudService', () => {
getCurrentUserInfoSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue(identityUserMock);
});
it('should create processfilter key by using appName and the username', async () => {
await service.getProcessFilters('mock-appName').subscribe((res: any) => {
it('should create processfilter key by using appName and the username', (done) => {
service.getProcessFilters('mock-appName').subscribe((res: any) => {
expect(res).toBeDefined();
expect(getCurrentUserInfoSpy).toHaveBeenCalled();
done();
});
});
it('should create default process filters', async () => {
it('should create default process filters', (done) => {
getPreferencesSpy.and.returnValue(of(fakeEmptyProcessCloudFilterEntries));
await service.getProcessFilters('mock-appName').subscribe((res: any) => {
service.getProcessFilters('mock-appName').subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(3);
@@ -91,12 +92,14 @@ describe('ProcessFilterCloudService', () => {
expect(res[2].id).toBe('3');
expect(res[2].name).toBe('MOCK_PROCESS_NAME_3');
expect(res[2].status).toBe('MOCK-COMPLETED');
expect(createPreferenceSpy).toHaveBeenCalled();
done();
});
expect(createPreferenceSpy).toHaveBeenCalled();
});
it('should fetch the process filters if filters are available', async () => {
await service.getProcessFilters('mock-appName').subscribe((res: any) => {
it('should fetch the process filters if filters are available', (done) => {
service.getProcessFilters('mock-appName').subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(3);
@@ -115,13 +118,16 @@ describe('ProcessFilterCloudService', () => {
expect(res[2].id).toBe('3');
expect(res[2].name).toBe('MOCK_PROCESS_NAME_3');
expect(res[2].status).toBe('MOCK-COMPLETED');
expect(getPreferencesSpy).toHaveBeenCalled();
done();
});
expect(getPreferencesSpy).toHaveBeenCalled();
});
it('should create the process filters in case the filters are not exist in the user preferences', async () => {
it('should create the process filters in case the filters are not exist in the user preferences', (done) => {
getPreferencesSpy.and.returnValue(of(fakeProcessCloudFilterWithDifferentEntries));
await service.getProcessFilters('mock-appName').subscribe((res: any) => {
service.getProcessFilters('mock-appName').subscribe((res: any) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(3);
@@ -140,64 +146,77 @@ describe('ProcessFilterCloudService', () => {
expect(res[2].id).toBe('3');
expect(res[2].name).toBe('MOCK_PROCESS_NAME_3');
expect(res[2].status).toBe('MOCK-COMPLETED');
expect(getPreferencesSpy).toHaveBeenCalled();
expect(createPreferenceSpy).toHaveBeenCalled();
done();
});
expect(getPreferencesSpy).toHaveBeenCalled();
expect(createPreferenceSpy).toHaveBeenCalled();
});
it('should return filter by process filter id', async () => {
await service.getFilterById('mock-appName', '2').subscribe((res: any) => {
it('should return filter by process filter id', (done) => {
service.getFilterById('mock-appName', '2').subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.appName).toBe('mock-appName');
expect(res.id).toBe('2');
expect(res.name).toBe('MOCK_PROCESS_NAME_2');
expect(res.status).toBe('MOCK-RUNNING');
expect(getPreferenceByKeySpy).toHaveBeenCalled();
done();
});
expect(getPreferenceByKeySpy).toHaveBeenCalled();
});
it('should add process filter if filter is not exist in the filters', async () => {
it('should add process filter if filter is not exist in the filters', (done) => {
getPreferenceByKeySpy.and.returnValue(of([]));
await service.getFilterById('mock-appName', '2').subscribe((res: any) => {
service.getFilterById('mock-appName', '2').subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.appName).toBe('mock-appName');
expect(res.id).toBe('2');
expect(res.name).toBe('MOCK_PROCESS_NAME_2');
expect(res.status).toBe('MOCK-RUNNING');
done();
});
});
it('should update filter', async () => {
await service.updateFilter(fakeProcessFilter).subscribe((res: any) => {
it('should update filter', (done) => {
service.updateFilter(fakeProcessFilter).subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(3);
expect(res[0].appName).toBe('mock-appName');
expect(res[1].appName).toBe('mock-appName');
expect(res[2].appName).toBe('mock-appName');
done();
});
});
it('should create process filter when trying to update in case filter is not exist in the filters', async () => {
it('should create process filter when trying to update in case filter is not exist in the filters', (done) => {
getPreferenceByKeySpy.and.returnValue(of([]));
await service.updateFilter(fakeProcessFilter).subscribe((res: any) => {
service.updateFilter(fakeProcessFilter).subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(3);
expect(res[0].appName).toBe('mock-appName');
expect(res[1].appName).toBe('mock-appName');
expect(res[2].appName).toBe('mock-appName');
expect(createPreferenceSpy).toHaveBeenCalled();
done();
});
expect(createPreferenceSpy).toHaveBeenCalled();
});
it('should delete filter', async () => {
await service.deleteFilter(fakeProcessFilter).subscribe((res: any) => {
it('should delete filter', (done) => {
service.deleteFilter(fakeProcessFilter).subscribe((res) => {
expect(res).toBeDefined();
expect(updatePreferenceSpy).toHaveBeenCalled();
done();
});
expect(updatePreferenceSpy).toHaveBeenCalled();
});
it('should check if given filter is a default filter', () => {

View File

@@ -16,9 +16,9 @@
*/
import { Injectable, Inject } from '@angular/core';
import { Observable, of, BehaviorSubject, throwError } from 'rxjs';
import { Observable, of, BehaviorSubject } from 'rxjs';
import { ProcessFilterCloudModel } from '../models/process-filter-cloud.model';
import { switchMap, map, catchError } from 'rxjs/operators';
import { switchMap, map } from 'rxjs/operators';
import { PROCESS_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
import { IdentityUserService } from '../../../people/services/identity-user.service';
@@ -100,7 +100,7 @@ export class ProcessFilterCloudService {
this.preferenceService
.getPreferences(appName, key)
.pipe(
switchMap((response: any) => {
switchMap((response) => {
const preferences = response?.list?.entries ? response.list.entries : [];
if (!this.hasPreferences(preferences)) {
return this.createProcessFilters(appName, key, this.defaultProcessFilters(appName));
@@ -109,8 +109,7 @@ export class ProcessFilterCloudService {
} else {
return of(this.findFiltersByKeyInPreferences(preferences, key));
}
}),
catchError((err) => this.handleProcessError(err))
})
)
.subscribe((filters) => {
this.addFiltersToStream(filters);
@@ -138,15 +137,14 @@ export class ProcessFilterCloudService {
getFilterById(appName: string, id: string): Observable<ProcessFilterCloudModel> {
const key: string = this.prepareKey(appName);
return this.getProcessFiltersByKey(appName, key).pipe(
switchMap((filters: ProcessFilterCloudModel[]) => {
switchMap((filters) => {
if (filters?.length === 0) {
return this.createProcessFilters(appName, key, this.defaultProcessFilters(appName));
} else {
return of(filters);
}
}),
map((filters) => filters.filter((filter) => filter.id === id)[0]),
catchError((err) => this.handleProcessError(err))
map((filters) => filters.filter((filter) => filter.id === id)[0])
);
}
@@ -158,7 +156,7 @@ export class ProcessFilterCloudService {
*/
addFilter(newFilter: ProcessFilterCloudModel): Observable<ProcessFilterCloudModel[]> {
const { appName, name } = newFilter;
const key: string = this.prepareKey(appName);
const key = this.prepareKey(appName);
return this.getProcessFiltersByKey(appName, key).pipe(
switchMap((filters) => {
@@ -174,11 +172,10 @@ export class ProcessFilterCloudService {
return this.preferenceService.updatePreference(appName, key, filters);
}
}),
map((filters: ProcessFilterCloudModel[]) => {
map((filters) => {
this.addFiltersToStream(filters);
return filters;
}),
catchError((err) => this.handleProcessError(err))
})
);
}
@@ -189,7 +186,7 @@ export class ProcessFilterCloudService {
* @returns Observable of process instance filters with updated filter
*/
updateFilter(updatedFilter: ProcessFilterCloudModel): Observable<ProcessFilterCloudModel[]> {
const key: string = this.prepareKey(updatedFilter.appName);
const key = this.prepareKey(updatedFilter.appName);
return this.getProcessFiltersByKey(updatedFilter.appName, key).pipe(
switchMap((filters) => {
if (filters?.length === 0) {
@@ -203,8 +200,7 @@ export class ProcessFilterCloudService {
map((updatedFilters) => {
this.addFiltersToStream(updatedFilters);
return updatedFilters;
}),
catchError((err) => this.handleProcessError(err))
})
);
}
@@ -226,11 +222,10 @@ export class ProcessFilterCloudService {
return of([]);
}
}),
map((filters: ProcessFilterCloudModel[]) => {
map((filters) => {
this.addFiltersToStream(filters);
return filters;
}),
catchError((err) => this.handleProcessError(err))
})
);
}
@@ -345,10 +340,6 @@ export class ProcessFilterCloudService {
this.filtersSubject.next(filters);
}
private handleProcessError(error: any) {
return throwError(error || 'Server error');
}
/**
* Creates and returns the default filters for a process app.
*

View File

@@ -112,21 +112,18 @@ describe('ServiceTaskFiltersCloudComponent', () => {
expect(filters[2].nativeElement.innerText).toContain('FakeMyServiceTasks2');
});
it('should emit an error with a bad response', async () => {
const mockErrorFilterList = {
error: 'wrong request'
};
getTaskListFiltersSpy.and.returnValue(throwError(mockErrorFilterList));
it('should emit an error with a bad response', () => {
getTaskListFiltersSpy.and.returnValue(throwError('wrong request'));
const appName = 'my-app-1';
const change = new SimpleChange(null, appName, true);
await component.error.subscribe((err) => {
expect(err).toBeDefined();
});
let lastValue: any;
component.error.subscribe((err) => lastValue = err);
component.ngOnChanges({ appName: change });
fixture.detectChanges();
expect(lastValue).toBeDefined();
});
it('should not select any filter as default', async () => {

View File

@@ -31,9 +31,7 @@ import {
import { UserPreferenceCloudService } from '../../../services/user-preference-cloud.service';
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TaskFilterCloudModel } from '../models/filter-cloud.model';
import { NotificationCloudService } from '../../../services/notification-cloud.service';
import { TaskCloudEngineEvent } from './../../../models/engine-event-cloud.model';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { IdentityUserService } from '../../../people/services/identity-user.service';
import { ApolloModule } from 'apollo-angular';
@@ -72,16 +70,18 @@ describe('TaskFilterCloudService', () => {
getCurrentUserInfoSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue(identityUserMock);
});
it('should create task filter key by using appName and the username', async () => {
await service.getTaskListFilters('fakeAppName').subscribe((res: any) => {
it('should create task filter key by using appName and the username', (done) => {
service.getTaskListFilters('fakeAppName').subscribe((res) => {
expect(res).toBeDefined();
expect(getCurrentUserInfoSpy).toHaveBeenCalled();
done();
});
});
it('should create default task filters if there are no task filter preferences', async () => {
it('should create default task filters if there are no task filter preferences', (done) => {
getPreferencesSpy.and.returnValue(of(fakeEmptyTaskCloudPreferenceList));
await service.getTaskListFilters('fakeAppName').subscribe((res: any) => {
service.getTaskListFilters('fakeAppName').subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(3);
@@ -100,12 +100,14 @@ describe('TaskFilterCloudService', () => {
expect(res[2].id).toBe('3');
expect(res[2].name).toBe('FAKE_TASK_3');
expect(res[2].status).toBe('COMPLETED');
expect(createPreferenceSpy).toHaveBeenCalled();
done();
});
expect(createPreferenceSpy).toHaveBeenCalled();
});
it('should return the task filters if filters available', async () => {
await service.getTaskListFilters('fakeAppName').subscribe((res: any) => {
it('should return the task filters if filters available', (done) => {
service.getTaskListFilters('fakeAppName').subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(3);
@@ -124,14 +126,16 @@ describe('TaskFilterCloudService', () => {
expect(res[2].id).toBe('3');
expect(res[2].name).toBe('FAKE_TASK_3');
expect(res[2].status).toBe('COMPLETED');
expect(getPreferencesSpy).toHaveBeenCalled();
done();
});
expect(getPreferencesSpy).toHaveBeenCalled();
});
it('should create the task filters if the user preference does not have task filters', async () => {
it('should create the task filters if the user preference does not have task filters', (done) => {
getPreferencesSpy.and.returnValue(of(fakePreferenceWithNoTaskFilterPreference));
await service.getTaskListFilters('fakeAppName').subscribe((res) => {
service.getTaskListFilters('fakeAppName').subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(3);
@@ -150,57 +154,67 @@ describe('TaskFilterCloudService', () => {
expect(res[2].id).toBe('3');
expect(res[2].name).toBe('FAKE_TASK_3');
expect(res[2].status).toBe('COMPLETED');
});
done();
});
});
it('should return filter by task filter id', async () => {
await service.getTaskFilterById('fakeAppName', '2').subscribe((res: any) => {
it('should return filter by task filter id', (done) => {
service.getTaskFilterById('fakeAppName', '2').subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.appName).toBe('fakeAppName');
expect(res.id).toBe('2');
expect(res.name).toBe('FAKE_TASK_2');
expect(res.status).toBe('RUNNING');
expect(getPreferenceByKeySpy).toHaveBeenCalled();
done();
});
expect(getPreferenceByKeySpy).toHaveBeenCalled();
});
it('should add task filter if filter is not exist in the filters', async () => {
it('should add task filter if filter is not exist in the filters', (done) => {
getPreferenceByKeySpy.and.returnValue(of([]));
await service.getTaskFilterById('fakeAppName', '2').subscribe((res: any) => {
service.getTaskFilterById('fakeAppName', '2').subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.appName).toBe('fakeAppName');
expect(res.id).toBe('2');
expect(res.name).toBe('FAKE_TASK_2');
expect(res.status).toBe('RUNNING');
done();
});
});
it('should update filter', async () => {
it('should update filter', (done) => {
createPreferenceSpy.and.returnValue(of(fakeTaskCloudFilters));
await service.updateFilter(fakeTaskFilter).subscribe((res: any) => {
service.updateFilter(fakeTaskFilter).subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(3);
expect(res[0].appName).toBe('fakeAppName');
expect(res[1].appName).toBe('fakeAppName');
expect(res[2].appName).toBe('fakeAppName');
done();
});
});
it('should create task filter when trying to update in case filter is not exist in the filters', async () => {
it('should create task filter when trying to update in case filter is not exist in the filters', (done) => {
getPreferenceByKeySpy.and.returnValue(of([]));
await service.updateFilter(fakeTaskFilter).subscribe((res: any) => {
service.updateFilter(fakeTaskFilter).subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(3);
expect(res[0].appName).toBe('fakeAppName');
expect(res[1].appName).toBe('fakeAppName');
expect(res[2].appName).toBe('fakeAppName');
expect(createPreferenceSpy).toHaveBeenCalled();
done();
});
expect(createPreferenceSpy).toHaveBeenCalled();
});
it('should check if given filter is a default filter', () => {
@@ -211,13 +225,14 @@ describe('TaskFilterCloudService', () => {
expect(service.isDefaultFilter(fakeFilterName)).toBe(false);
});
it('should return engine event task subscription', async () => {
it('should return engine event task subscription', (done) => {
spyOn(notificationCloudService, 'makeGQLQuery').and.returnValue(of(taskCloudEngineEventsMock));
await service.getTaskNotificationSubscription('myAppName').subscribe((res: TaskCloudEngineEvent[]) => {
service.getTaskNotificationSubscription('myAppName').subscribe((res) => {
expect(res.length).toBe(1);
expect(res[0].eventType).toBe('TASK_ASSIGNED');
expect(res[0].entity.name).toBe('This is a new task');
done();
});
});
});
@@ -244,9 +259,10 @@ describe('Inject [LocalPreferenceCloudService] into the TaskFilterCloudService',
spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue(identityUserMock);
});
it('should create default task filters if there are no task filter preferences', async () => {
it('should create default task filters if there are no task filter preferences', (done) => {
const appName = 'fakeAppName';
await service.getTaskListFilters(appName).subscribe((res: TaskFilterCloudModel[]) => {
service.getTaskListFilters(appName).subscribe((res) => {
expect(res.length).toEqual(3);
expect(res[0].name).toEqual('ADF_CLOUD_TASK_FILTERS.MY_TASKS');
@@ -267,29 +283,31 @@ describe('Inject [LocalPreferenceCloudService] into the TaskFilterCloudService',
expect(res[2].appName).toEqual(appName);
expect(res[2].icon).toEqual('done');
expect(res[2].status).toEqual('COMPLETED');
expect(getPreferencesSpy).toHaveBeenCalled();
const localData = JSON.parse(localStorage.getItem(`task-filters-${appName}-${identityUserMock.username}`));
expect(localData.length).toEqual(3);
expect(localData[0].name).toEqual('ADF_CLOUD_TASK_FILTERS.MY_TASKS');
expect(localData[0].key).toEqual('my-tasks');
expect(localData[0].appName).toEqual(appName);
expect(localData[0].icon).toEqual('inbox');
expect(localData[0].status).toEqual('ASSIGNED');
expect(localData[0].assignee).toEqual(identityUserMock.username);
expect(localData[1].name).toEqual('ADF_CLOUD_TASK_FILTERS.QUEUED_TASKS');
expect(localData[1].key).toEqual('queued-tasks');
expect(localData[1].appName).toEqual(appName);
expect(localData[1].icon).toEqual('queue');
expect(localData[1].status).toEqual('CREATED');
expect(localData[2].name).toEqual('ADF_CLOUD_TASK_FILTERS.COMPLETED_TASKS');
expect(localData[2].key).toEqual('completed-tasks');
expect(localData[2].appName).toEqual(appName);
expect(localData[2].icon).toEqual('done');
expect(localData[2].status).toEqual('COMPLETED');
done();
});
expect(getPreferencesSpy).toHaveBeenCalled();
const localData = JSON.parse(localStorage.getItem(`task-filters-${appName}-${identityUserMock.username}`));
expect(localData.length).toEqual(3);
expect(localData[0].name).toEqual('ADF_CLOUD_TASK_FILTERS.MY_TASKS');
expect(localData[0].key).toEqual('my-tasks');
expect(localData[0].appName).toEqual(appName);
expect(localData[0].icon).toEqual('inbox');
expect(localData[0].status).toEqual('ASSIGNED');
expect(localData[0].assignee).toEqual(identityUserMock.username);
expect(localData[1].name).toEqual('ADF_CLOUD_TASK_FILTERS.QUEUED_TASKS');
expect(localData[1].key).toEqual('queued-tasks');
expect(localData[1].appName).toEqual(appName);
expect(localData[1].icon).toEqual('queue');
expect(localData[1].status).toEqual('CREATED');
expect(localData[2].name).toEqual('ADF_CLOUD_TASK_FILTERS.COMPLETED_TASKS');
expect(localData[2].key).toEqual('completed-tasks');
expect(localData[2].appName).toEqual(appName);
expect(localData[2].icon).toEqual('done');
expect(localData[2].status).toEqual('COMPLETED');
});
});

View File

@@ -56,7 +56,7 @@ module.exports = function (config) {
reporters: [{ type: 'html' }, { type: 'text-summary' }],
check: {
global: {
statements: 80,
statements: 75,
branches: 67,
functions: 70,
lines: 75

View File

@@ -16,22 +16,17 @@
*/
import { Injectable } from '@angular/core';
import { Observable, from, throwError, of } from 'rxjs';
import { AlfrescoApiService, LogService, GroupModel } from '@alfresco/adf-core';
import { Observable, from, of } from 'rxjs';
import { AlfrescoApiService, GroupModel } from '@alfresco/adf-core';
import { BpmUserModel } from '../models/bpm-user.model';
import { UserProcessModel } from '../models/user-process.model';
import { catchError, combineAll, defaultIfEmpty, map, switchMap } from 'rxjs/operators';
import {
TaskActionsApi,
UsersApi,
ResultListDataRepresentationLightUserRepresentation, ActivitiGroupsApi, UserProfileApi
} from '@alfresco/js-api';
import { combineAll, defaultIfEmpty, map, switchMap } from 'rxjs/operators';
import { TaskActionsApi, UsersApi, ResultListDataRepresentationLightUserRepresentation, ActivitiGroupsApi, UserProfileApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
})
export class PeopleProcessService {
private _taskActionsApi: TaskActionsApi;
get taskActionsApi(): TaskActionsApi {
this._taskActionsApi = this._taskActionsApi ?? new TaskActionsApi(this.apiService.getInstance());
@@ -56,9 +51,7 @@ export class PeopleProcessService {
return this._profileApi;
}
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
}
constructor(private apiService: AlfrescoApiService) {}
/**
* Gets information about the current user.
@@ -66,11 +59,7 @@ export class PeopleProcessService {
* @returns User information object
*/
getCurrentUserInfo(): Observable<BpmUserModel> {
return from(this.profileApi.getProfile())
.pipe(
map((userRepresentation) => new BpmUserModel(userRepresentation)),
catchError((err) => this.handleError(err))
);
return from(this.profileApi.getProfile()).pipe(map((userRepresentation) => new BpmUserModel(userRepresentation)));
}
/**
@@ -94,11 +83,7 @@ export class PeopleProcessService {
if (groupId) {
option.groupId = groupId;
}
return from(this.groupsApi.getGroups(option))
.pipe(
map((response: any) => response.data || []),
catchError((err) => this.handleError(err))
);
return from(this.groupsApi.getGroups(option)).pipe(map((response: any) => response.data || []));
}
/**
@@ -112,17 +97,15 @@ export class PeopleProcessService {
getWorkflowUsers(taskId?: string, searchWord?: string, groupId?: string): Observable<UserProcessModel[]> {
const option = { excludeTaskId: taskId, filter: searchWord, groupId };
return from(this.getWorkflowUserApi(option))
.pipe(
switchMap(response => response.data as UserProcessModel[] || []),
map((user) => {
user.userImage = this.getUserProfileImageApi(user.id.toString());
return of(user);
}),
combineAll(),
defaultIfEmpty([]),
catchError((err) => this.handleError(err))
);
return from(this.getWorkflowUserApi(option)).pipe(
switchMap((response) => (response.data as UserProcessModel[]) || []),
map((user) => {
user.userImage = this.getUserProfileImageApi(user.id.toString());
return of(user);
}),
combineAll(),
defaultIfEmpty([])
);
}
/**
* Gets the profile picture URL for the specified user.
@@ -142,11 +125,7 @@ export class PeopleProcessService {
* @returns Empty response when the update completes
*/
involveUserWithTask(taskId: string, idToInvolve: string): Observable<UserProcessModel[]> {
const node = { userId: idToInvolve };
return from(this.involveUserToTaskApi(taskId, node))
.pipe(
catchError((err) => this.handleError(err))
);
return from(this.involveUserToTaskApi(taskId, { userId: idToInvolve }));
}
/**
@@ -157,11 +136,7 @@ export class PeopleProcessService {
* @returns Empty response when the update completes
*/
removeInvolvedUser(taskId: string, idToRemove: string): Observable<UserProcessModel[]> {
const node = { userId: idToRemove };
return from(this.removeInvolvedUserFromTaskApi(taskId, node))
.pipe(
catchError((err) => this.handleError(err))
);
return from(this.removeInvolvedUserFromTaskApi(taskId, { userId: idToRemove }));
}
private getWorkflowUserApi(options: any): Promise<ResultListDataRepresentationLightUserRepresentation> {
@@ -179,9 +154,4 @@ export class PeopleProcessService {
private getUserProfileImageApi(userId: string): string {
return this.userApi.getUserProfilePictureUrl(userId);
}
private handleError(error: any) {
this.logService.error(error);
return throwError(error || 'Server error');
}
}

View File

@@ -16,7 +16,7 @@
*/
import { CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core';
import { from, of } from 'rxjs';
import { from, of, throwError } from 'rxjs';
import { FilterProcessRepresentationModel } from '../models/filter-process.model';
import { AppsProcessService } from '../../app-list/services/apps-process.service';
import { ProcessFilterService } from '../services/process-filter.service';
@@ -28,6 +28,7 @@ import { ProcessTestingModule } from '../../testing/process.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { NavigationStart, Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { ProcessInstanceFilterRepresentation, UserProcessInstanceFilterRepresentation } from '@alfresco/js-api';
describe('ProcessFiltersComponent', () => {
@@ -62,14 +63,8 @@ describe('ProcessFiltersComponent', () => {
const appId = '1';
const change = new SimpleChange(null, appId, true);
await filterList.success.subscribe((res) => {
expect(res).toBeDefined();
expect(filterList.filters).toBeDefined();
expect(filterList.filters.length).toEqual(3);
expect(filterList.filters[0].name).toEqual('FakeCompleted');
expect(filterList.filters[1].name).toEqual('FakeAll');
expect(filterList.filters[2].name).toEqual('Running');
});
let lastValue: ProcessInstanceFilterRepresentation[];
filterList.success.subscribe((res) => lastValue = res);
spyOn(filterList, 'getFiltersByAppId').and.callThrough();
@@ -79,6 +74,14 @@ describe('ProcessFiltersComponent', () => {
await fixture.whenStable();
expect(filterList.getFiltersByAppId).toHaveBeenCalled();
expect(lastValue).toBeDefined();
expect(lastValue).toEqual(filterList.filters);
expect(filterList.filters).toBeDefined();
expect(filterList.filters.length).toEqual(3);
expect(filterList.filters[0].name).toEqual('FakeCompleted');
expect(filterList.filters[1].name).toEqual('FakeAll');
expect(filterList.filters[2].name).toEqual('Running');
});
it('should select the Running process filter', async () => {
@@ -87,15 +90,13 @@ describe('ProcessFiltersComponent', () => {
const appId = '1';
const change = new SimpleChange(null, appId, true);
await filterList.success.subscribe(() => {
filterList.selectRunningFilter();
expect(filterList.currentFilter.name).toEqual('Running');
});
filterList.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
filterList.selectRunningFilter();
expect(filterList.currentFilter.name).toEqual('Running');
});
it('should emit the selected filter based on the filterParam input', async () => {
@@ -104,13 +105,14 @@ describe('ProcessFiltersComponent', () => {
const appId = '1';
const change = new SimpleChange(null, appId, true);
await filterList.filterSelected.subscribe((filter) => {
expect(filter.name).toEqual('FakeCompleted');
});
let lastValue: UserProcessInstanceFilterRepresentation;
filterList.filterSelected.subscribe((filter) => lastValue = filter);
filterList.ngOnChanges({ appId: change });
fixture.detectChanges();
await fixture.whenStable();
expect(lastValue.name).toEqual('FakeCompleted');
});
it('should filterClicked emit when a filter is clicked from the UI', async () => {
@@ -143,50 +145,44 @@ describe('ProcessFiltersComponent', () => {
expect(filterList.currentFilter).toBe(undefined);
});
it('should return the filter task list, filtered By Name', async () => {
spyOn(appsProcessService, 'getDeployedApplicationsByName').and.returnValue(from(Promise.resolve({ id: 1 })));
it('should return the filter task list, filtered By Name', () => {
const deployApp = spyOn(appsProcessService, 'getDeployedApplicationsByName').and.returnValue(from(Promise.resolve({ id: 1 })));
spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters));
const change = new SimpleChange(null, 'test', true);
filterList.ngOnChanges({ appName: change });
await filterList.success.subscribe((res) => {
const deployApp: any = appsProcessService.getDeployedApplicationsByName;
expect(deployApp.calls.count()).toEqual(1);
expect(res).toBeDefined();
});
fixture.detectChanges();
expect(deployApp.calls.count()).toEqual(1);
});
it('should emit an error with a bad response of getProcessFilters', async () => {
const mockErrorFilterPromise = Promise.reject(new Error('wrong request'));
spyOn(processFilterService, 'getProcessFilters').and.returnValue(from(mockErrorFilterPromise));
it('should emit an error with a bad response of getProcessFilters', () => {
spyOn(processFilterService, 'getProcessFilters').and.returnValue(throwError('error'));
const appId = '1';
const change = new SimpleChange(null, appId, true);
let lastValue: any;
filterList.error.subscribe((err) => lastValue = err);
filterList.ngOnChanges({ appId: change });
await filterList.error.subscribe((err) => {
expect(err).toBeDefined();
});
fixture.detectChanges();
expect(lastValue).toBeDefined();
});
it('should emit an error with a bad response of getDeployedApplicationsByName', async () => {
const mockErrorFilterPromise = Promise.reject(new Error('wrong request'));
spyOn(appsProcessService, 'getDeployedApplicationsByName').and.returnValue(from(mockErrorFilterPromise));
it('should emit an error with a bad response of getDeployedApplicationsByName', () => {
spyOn(appsProcessService, 'getDeployedApplicationsByName').and.returnValue(throwError('wrong request'));
const appId = 'fake-app';
const change = new SimpleChange(null, appId, true);
let lastValue: any;
filterList.error.subscribe((err) => lastValue = err);
filterList.ngOnChanges({ appName: change });
await filterList.error.subscribe((err) => {
expect(err).toBeDefined();
});
fixture.detectChanges();
expect(lastValue).toBeDefined();
});
it('should emit an event when a filter is selected', async () => {
@@ -196,13 +192,13 @@ describe('ProcessFiltersComponent', () => {
filter: { state: 'open', assignment: 'fake-involved' }
});
await filterList.filterClicked.subscribe((filter) => {
expect(filter).toBeDefined();
expect(filter).toEqual(currentFilter);
expect(filterList.currentFilter).toEqual(currentFilter);
});
let lastValue: UserProcessInstanceFilterRepresentation;
filterList.filterClicked.subscribe((filter) => lastValue = filter);
filterList.selectFilter(currentFilter);
expect(lastValue).toBeDefined();
expect(lastValue).toEqual(currentFilter);
expect(filterList.currentFilter).toEqual(currentFilter);
});
it('should reload filters by appId on binding changes', () => {

View File

@@ -127,16 +127,16 @@ export class ProcessFiltersComponent implements OnInit, OnChanges, OnDestroy {
*/
getFiltersByAppId(appId?: number) {
this.processFilterService.getProcessFilters(appId).subscribe(
(res: ProcessInstanceFilterRepresentation[]) => {
(res) => {
if (res.length === 0 && this.isFilterListEmpty()) {
this.processFilterService.createDefaultFilters(appId).subscribe(
(resDefault: ProcessInstanceFilterRepresentation[]) => {
(resDefault) => {
this.resetFilter();
this.filters = resDefault;
this.selectProcessFilter(this.filterParam);
this.success.emit(resDefault);
},
(errDefault: any) => {
(errDefault) => {
this.error.emit(errDefault);
}
);
@@ -147,7 +147,7 @@ export class ProcessFiltersComponent implements OnInit, OnChanges, OnDestroy {
this.success.emit(res);
}
},
(err: any) => {
(err) => {
this.error.emit(err);
}
);

View File

@@ -19,14 +19,7 @@ import { NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { of, throwError } from 'rxjs';
import {
FormModel,
FormOutcomeEvent,
FormOutcomeModel,
LogService,
CommentModel,
User
} from '@alfresco/adf-core';
import { FormModel, FormOutcomeEvent, FormOutcomeModel, CommentModel, User } from '@alfresco/adf-core';
import { TaskDetailsModel } from '../models/task-details.model';
import {
noDataMock,
@@ -60,7 +53,6 @@ const fakeTaskAssignResponse = new TaskDetailsModel({
});
describe('TaskDetailsComponent', () => {
let taskListService: TaskListService;
let taskService: TaskService;
let taskFormService: TaskFormService;
@@ -70,7 +62,6 @@ describe('TaskDetailsComponent', () => {
let getCommentsSpy: jasmine.Spy;
let getTasksSpy: jasmine.Spy;
let assignTaskSpy: jasmine.Spy;
let logService: LogService;
let taskCommentsService: TaskCommentsService;
let peopleProcessService: PeopleProcessService;
@@ -82,7 +73,6 @@ describe('TaskDetailsComponent', () => {
],
schemas: [NO_ERRORS_SCHEMA]
});
logService = TestBed.inject(LogService);
peopleProcessService = TestBed.inject(PeopleProcessService);
spyOn(peopleProcessService, 'getCurrentUserInfo').and.returnValue(of({ email: 'fake-email' } as any));
@@ -130,14 +120,14 @@ describe('TaskDetailsComponent', () => {
expect(getTaskDetailsSpy).not.toHaveBeenCalled();
});
it('should send a claim task event when a task is claimed', async () => {
await component.claimedTask.subscribe((taskId) => {
expect(taskId).toBe('FAKE-TASK-CLAIM');
});
it('should send a claim task event when a task is claimed', () => {
let lastValue: string;
component.claimedTask.subscribe((taskId) => lastValue = taskId);
component.onClaimAction('FAKE-TASK-CLAIM');
expect(lastValue).toBe('FAKE-TASK-CLAIM');
});
it('should send a unclaim task event when a task is unclaimed', async () => {
it('should send a unclaim task event when a task is unclaimed', () => {
const taskUnclaimedSpy = spyOn(component.unClaimedTask, 'emit');
component.onUnclaimAction('FAKE-TASK-UNCLAIM');
@@ -397,7 +387,7 @@ describe('TaskDetailsComponent', () => {
fixture.detectChanges();
});
it('should return an observable with user search results', async () => {
it('should return an observable with user search results', () => {
spyOn(peopleProcessService, 'getWorkflowUsers').and.returnValue(of([{
id: 1,
firstName: 'fake-test-1',
@@ -410,32 +400,25 @@ describe('TaskDetailsComponent', () => {
email: 'fake-test-2@test.com'
}]));
await component.peopleSearch.subscribe((users) => {
expect(users.length).toBe(2);
expect(users[0].firstName).toBe('fake-test-1');
expect(users[0].lastName).toBe('fake-last-1');
expect(users[0].email).toBe('fake-test-1@test.com');
expect(users[0].id).toBe(1);
});
let lastValue: UserProcessModel[];
component.peopleSearch.subscribe((users) => lastValue = users);
component.searchUser('fake-search-word');
expect(lastValue.length).toBe(2);
expect(lastValue[0].firstName).toBe('fake-test-1');
expect(lastValue[0].lastName).toBe('fake-last-1');
expect(lastValue[0].email).toBe('fake-test-1@test.com');
expect(lastValue[0].id).toBe(1);
});
it('should return an empty list for not valid search', async () => {
it('should return an empty list for not valid search', () => {
spyOn(peopleProcessService, 'getWorkflowUsers').and.returnValue(of([]));
await component.peopleSearch.subscribe((users) => {
expect(users.length).toBe(0);
});
let lastValue: UserProcessModel[];
component.peopleSearch.subscribe((users) => lastValue = users);
component.searchUser('fake-search-word');
});
it('should log error message when search fails', async () => {
const logServiceErrorSpy = spyOn(logService, 'error');
spyOn(peopleProcessService, 'getWorkflowUsers').and.returnValue(throwError('fake-error'));
component.searchUser('fake-search');
expect(logServiceErrorSpy).toHaveBeenCalledWith('Could not load users');
expect(lastValue.length).toBe(0);
});
it('should assign task to user', () => {

View File

@@ -19,7 +19,7 @@ import { SimpleChange } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppsProcessService } from '../../app-list/services/apps-process.service';
import { AppConfigService } from '@alfresco/adf-core';
import { from, of } from 'rxjs';
import { of, throwError } from 'rxjs';
import { FilterParamsModel, FilterRepresentationModel } from '../models/filter.model';
import { TaskListService } from '../services/tasklist.service';
import { TaskFilterService } from '../services/task-filter.service';
@@ -60,37 +60,35 @@ describe('TaskFiltersComponent', () => {
router = TestBed.inject(Router);
});
it('should emit an error with a bad response', async () => {
const mockErrorFilterList = {
error: 'wrong request'
};
const mockErrorFilterPromise = Promise.reject(mockErrorFilterList);
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(mockErrorFilterPromise));
it('should emit an error with a bad response', () => {
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(throwError('wrong request'));
const appId = '1';
const change = new SimpleChange(null, appId, true);
component.ngOnChanges({ appId: change });
await component.error.subscribe((err) => {
expect(err).toBeDefined();
});
let lastError: any;
component.error.subscribe((err) => lastError = err);
component.ngOnChanges({ appId: change });
expect(lastError).toBeDefined();
});
it('should return the filter task list', async () => {
it('should return the filter task list', () => {
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(of(fakeTaskFilters));
const appId = '1';
const change = new SimpleChange(null, appId, true);
await component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(component.filters).toBeDefined();
expect(component.filters.length).toEqual(3);
expect(component.filters[0].name).toEqual('FakeInvolvedTasks');
expect(component.filters[1].name).toEqual('FakeMyTasks1');
expect(component.filters[2].name).toEqual('FakeMyTasks2');
});
let lastValue: any;
component.success.subscribe((res) => lastValue = res);
component.ngOnChanges({ appId: change });
expect(lastValue).toBeDefined();
expect(component.filters).toBeDefined();
expect(component.filters.length).toEqual(3);
expect(component.filters[0].name).toEqual('FakeInvolvedTasks');
expect(component.filters[1].name).toEqual('FakeMyTasks1');
expect(component.filters[2].name).toEqual('FakeMyTasks2');
});
it('Should call the API to create the default task filters when no task filters exist', async () => {
@@ -105,52 +103,54 @@ describe('TaskFiltersComponent', () => {
expect(createDefaultFiltersSpy).toHaveBeenCalledWith(appId);
});
it('should return the filter task list, filtered By Name', async () => {
spyOn(appsProcessService, 'getDeployedApplicationsByName').and.returnValue(of({} as any));
it('should return the filter task list, filtered By Name', () => {
const deployApp = spyOn(appsProcessService, 'getDeployedApplicationsByName').and.returnValue(of({} as any));
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(of(fakeTaskFilters));
const change = new SimpleChange(null, 'test', true);
await component.success.subscribe((res) => {
const deployApp: any = appsProcessService.getDeployedApplicationsByName;
expect(deployApp.calls.count()).toEqual(1);
expect(res).toBeDefined();
});
let lastValue: any;
component.success.subscribe((res) => lastValue = res);
component.ngOnChanges({ appName: change });
expect(deployApp.calls.count()).toEqual(1);
expect(lastValue).toBeDefined();
});
it('should select the task filter based on the input by name param', async () => {
it('should select the task filter based on the input by name param', () => {
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(of(fakeTaskFilters));
component.filterParam = new FilterParamsModel({ name: 'FakeMyTasks1' });
await component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(component.currentFilter).toBeDefined();
expect(component.currentFilter.name).toEqual('FakeMyTasks1');
});
let lastValue: any;
component.success.subscribe((res) => lastValue = res);
const appId = '1';
const change = new SimpleChange(null, appId, true);
component.ngOnChanges({ appId: change });
expect(lastValue).toBeDefined();
expect(component.currentFilter).toBeDefined();
expect(component.currentFilter.name).toEqual('FakeMyTasks1');
});
it('should select the task filter based on the input by index param', async () => {
it('should select the task filter based on the input by index param', () => {
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(of(fakeTaskFilters));
component.filterParam = new FilterParamsModel({ index: 2 });
await component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(component.currentFilter).toBeDefined();
expect(component.currentFilter.name).toEqual('FakeMyTasks2');
});
let lastValue: any;
component.success.subscribe((res) => lastValue = res);
const appId = '1';
const change = new SimpleChange(null, appId, true);
component.ngOnChanges({ appId: change });
expect(lastValue).toBeDefined();
expect(component.currentFilter).toBeDefined();
expect(component.currentFilter.name).toEqual('FakeMyTasks2');
});
it('should select the task filter based on the input by id param', async () => {
it('should select the task filter based on the input by id param', () => {
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(of(fakeTaskFilters));
component.filterParam = new FilterParamsModel({ id: 10 });
@@ -158,13 +158,14 @@ describe('TaskFiltersComponent', () => {
const appId = '1';
const change = new SimpleChange(null, appId, true);
await component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(component.currentFilter).toBeDefined();
expect(component.currentFilter.name).toEqual('FakeInvolvedTasks');
});
let lastValue: any;
component.success.subscribe((res) => lastValue = res);
component.ngOnChanges({ appId: change });
expect(lastValue).toBeDefined();
expect(component.currentFilter).toBeDefined();
expect(component.currentFilter.name).toEqual('FakeInvolvedTasks');
});
it('should emit the selected filter based on the filterParam input', () => {

View File

@@ -18,74 +18,27 @@
import { TestBed } from '@angular/core/testing';
import { CoreModule } from '@alfresco/adf-core';
import { of } from 'rxjs';
import {
fakeCompletedTaskList,
fakeFormList,
fakeOpenTaskList,
fakeTaskDetails,
fakeTaskList,
fakeTasksChecklist,
fakeUser1,
fakeUser2,
secondFakeTaskList
} from '../../mock';
import { fakeFilter, fakeRepresentationFilter1, fakeRepresentationFilter2 } from '../../mock/task/task-filters.mock';
import { FilterRepresentationModel } from '../models/filter.model';
import { TaskDetailsModel } from '../models/task-details.model';
import { fakeCompletedTaskList, fakeOpenTaskList, fakeTaskList } from '../../mock';
import { fakeFilter } from '../../mock/task/task-filters.mock';
import { TaskListService } from './tasklist.service';
import { TaskRepresentation, TaskUpdateRepresentation } from '@alfresco/js-api';
import { ProcessTestingModule } from '../../testing/process.testing.module';
import { UserProcessModel } from '../../common/models/user-process.model';
declare let jasmine: any;
describe('Activiti TaskList Service', () => {
let service: TaskListService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
CoreModule.forRoot(),
ProcessTestingModule
]
imports: [CoreModule.forRoot(), ProcessTestingModule]
});
service = TestBed.inject(TaskListService);
jasmine.Ajax.install();
});
afterEach(() => {
jasmine.Ajax.uninstall();
});
describe('Content tests', () => {
it('should return the task list filtered', (done) => {
service.getTasks(fakeFilter).subscribe((res) => {
expect(res).toBeDefined();
expect(res.size).toEqual(1);
expect(res.start).toEqual(0);
expect(res.data).toBeDefined();
expect(res.data.length).toEqual(1);
expect(res.data[0].name).toEqual('FakeNameTask');
expect(res.data[0].assignee.email).toEqual('fake-email@dom.com');
expect(res.data[0].assignee.firstName).toEqual('firstName');
expect(res.data[0].assignee.lastName).toEqual('lastName');
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskList)
});
});
it('should return the task list with all tasks filtered by state', (done) => {
spyOn(service, 'getTasks').and.returnValue(of(fakeTaskList));
spyOn(service, 'getTotalTasks').and.returnValue(of(fakeTaskList));
service.findAllTaskByState(fakeFilter, 'open').subscribe((res) => {
expect(res).toBeDefined();
expect(res.size).toEqual(1);
expect(res.start).toEqual(0);
@@ -117,27 +70,6 @@ describe('Activiti TaskList Service', () => {
});
});
it('should return the task list filtered by state', (done) => {
service.findTasksByState(fakeFilter, 'open').subscribe((res) => {
expect(res).toBeDefined();
expect(res.size).toEqual(1);
expect(res.start).toEqual(0);
expect(res.data).toBeDefined();
expect(res.data.length).toEqual(1);
expect(res.data[0].name).toEqual('FakeNameTask');
expect(res.data[0].assignee.email).toEqual('fake-email@dom.com');
expect(res.data[0].assignee.firstName).toEqual('firstName');
expect(res.data[0].assignee.lastName).toEqual('lastName');
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskList)
});
});
it('should return the task list with all tasks filtered without state', (done) => {
spyOn(service, 'getTasks').and.returnValue(of(fakeTaskList));
spyOn(service, 'getTotalTasks').and.returnValue(of(fakeTaskList));
@@ -190,325 +122,5 @@ describe('Activiti TaskList Service', () => {
done();
});
});
it('should return the task details ', (done) => {
service.getTaskDetails('999').subscribe((res: TaskDetailsModel) => {
expect(res).toBeDefined();
expect(res.id).toEqual('999');
expect(res.name).toEqual('fake-task-name');
expect(res.formKey).toEqual('99');
expect(res.assignee).toBeDefined();
expect(res.assignee.email).toEqual('fake-email@dom.com');
expect(res.assignee.firstName).toEqual('firstName');
expect(res.assignee.lastName).toEqual('lastName');
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskDetails)
});
});
it('should return the tasks checklists ', (done) => {
service.getTaskChecklist('999').subscribe((res: TaskDetailsModel[]) => {
expect(res).toBeDefined();
expect(res.length).toEqual(2);
expect(res[0].name).toEqual('FakeCheckTask1');
expect(res[0].assignee.email).toEqual('fake-email@dom.com');
expect(res[0].assignee.firstName).toEqual('firstName');
expect(res[0].assignee.lastName).toEqual('lastName');
expect(res[1].name).toEqual('FakeCheckTask2');
expect(res[1].assignee.email).toEqual('fake-email@dom.com');
expect(res[1].assignee.firstName).toEqual('firstName');
expect(res[0].assignee.lastName).toEqual('lastName');
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTasksChecklist)
});
});
it('should add a task ', (done) => {
const taskFake = new TaskDetailsModel({
id: 123,
parentTaskId: 456,
name: 'FakeNameTask',
description: null,
category: null,
assignee: fakeUser1,
created: ''
});
service.addTask(taskFake).subscribe((res: TaskDetailsModel) => {
expect(res).toBeDefined();
expect(res.id).not.toEqual('');
expect(res.name).toEqual('FakeNameTask');
expect(res.created).not.toEqual(null);
done();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
id: '777', name: 'FakeNameTask', description: null, category: null,
assignee: fakeUser1,
created: '2016-07-15T11:19:17.440+0000'
})
});
});
it('should remove a checklist task ', async () => {
await service.deleteTask('999').subscribe((res) => {
expect(res).toEqual({});
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({})
});
});
it('should complete the task', async () => {
await service.completeTask('999').subscribe((res: any) => {
expect(res).toBeDefined();
expect(res).toEqual({});
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({})
});
});
it('should return the total number of tasks', async () => {
await service.getTotalTasks(fakeFilter).subscribe((res: any) => {
expect(res).toBeDefined();
expect(res.size).toEqual(1);
expect(res.total).toEqual(1);
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskList)
});
});
it('should create a new standalone task ', async () => {
const taskFake = new TaskDetailsModel({
name: 'FakeNameTask',
description: 'FakeDescription',
category: '3'
});
await service.createNewTask(taskFake).subscribe((res: TaskDetailsModel) => {
expect(res).toBeDefined();
expect(res.id).not.toEqual('');
expect(res.name).toEqual('FakeNameTask');
expect(res.description).toEqual('FakeDescription');
expect(res.category).toEqual('3');
expect(res.created).not.toEqual(null);
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
id: '777',
name: 'FakeNameTask',
description: 'FakeDescription',
category: '3',
assignee: fakeUser1,
created: '2016-07-15T11:19:17.440+0000'
})
});
});
it('should assign task to a user', async () => {
const testTaskId = '8888';
await service.assignTask(testTaskId, fakeUser2).subscribe((res: TaskDetailsModel) => {
expect(res).toBeDefined();
expect(res.id).toEqual(testTaskId);
expect(res.name).toEqual('FakeNameTask');
expect(res.description).toEqual('FakeDescription');
expect(res.category).toEqual('3');
expect(res.created).not.toEqual(null);
expect(res.adhocTaskCanBeReassigned).toBe(true);
expect(res.assignee).toEqual(new UserProcessModel(fakeUser2));
expect(res.involvedPeople[0].email).toEqual(fakeUser1.email);
expect(res.involvedPeople[0].firstName).toEqual(fakeUser1.firstName);
expect(res.involvedPeople[0].lastName).toEqual(fakeUser1.lastName);
expect(res.involvedPeople[0].id).toEqual(fakeUser1.id);
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
id: testTaskId,
name: 'FakeNameTask',
description: 'FakeDescription',
adhocTaskCanBeReassigned: true,
category: '3',
assignee: fakeUser2,
involvedPeople: [fakeUser1],
created: '2016-07-15T11:19:17.440+0000'
})
});
});
it('should assign task to a userId', async () => {
const testTaskId = '8888';
await service.assignTaskByUserId(testTaskId, fakeUser2.id.toString()).subscribe((res: TaskDetailsModel) => {
expect(res).toBeDefined();
expect(res.id).toEqual(testTaskId);
expect(res.name).toEqual('FakeNameTask');
expect(res.description).toEqual('FakeDescription');
expect(res.category).toEqual('3');
expect(res.created).not.toEqual(null);
expect(res.adhocTaskCanBeReassigned).toBe(true);
expect(res.assignee).toEqual(new UserProcessModel(fakeUser2));
expect(res.involvedPeople[0].email).toEqual(fakeUser1.email);
expect(res.involvedPeople[0].firstName).toEqual(fakeUser1.firstName);
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({
id: testTaskId,
name: 'FakeNameTask',
description: 'FakeDescription',
adhocTaskCanBeReassigned: true,
category: '3',
assignee: fakeUser2,
involvedPeople: [fakeUser1],
created: '2016-07-15T11:19:17.440+0000'
})
});
});
it('should claim a task', async () => {
const taskId = '111';
await service.claimTask(taskId).subscribe((res) => {
expect(res).toEqual({});
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({})
});
});
it('should unclaim a task', async () => {
const taskId = '111';
await service.unclaimTask(taskId).subscribe((res) => {
expect(res).toEqual({});
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({})
});
});
it('should update a task', async () => {
const taskId = '111';
const updated: TaskUpdateRepresentation = {
name: 'someName'
};
await service.updateTask(taskId, updated).subscribe((res) => {
expect(res).toEqual(new TaskRepresentation({}));
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify({})
});
});
it('should return the filter if it contains task id', async () => {
const taskId = '1';
const filterFake = new FilterRepresentationModel({
name: 'FakeNameFilter',
assignment: 'fake-assignment',
filter: {
processDefinitionKey: '1',
assignment: 'fake',
state: 'none',
sort: 'asc'
}
});
await service.isTaskRelatedToFilter(taskId, filterFake).subscribe((res: any) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskList)
});
});
it('should return the filters if it contains task id', async () => {
const taskId = '1';
const fakeFilterList: FilterRepresentationModel[] = [];
fakeFilterList.push(fakeRepresentationFilter1, fakeRepresentationFilter2);
let resultFilter: FilterRepresentationModel = null;
await service.getFilterForTaskById(taskId, fakeFilterList).subscribe((res: FilterRepresentationModel) => {
resultFilter = res;
}, () => {
}, () => {
expect(resultFilter).toBeDefined();
expect(resultFilter).not.toBeNull();
expect(resultFilter.name).toBe('CONTAIN FILTER');
});
jasmine.Ajax.requests.at(0).respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeTaskList)
});
jasmine.Ajax.requests.at(1).respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(secondFakeTaskList)
});
});
it('should get possible form list', async () => {
await service.getFormList().subscribe((res: any) => {
expect(res).toBeDefined();
expect(res.length).toBe(2);
expect(res[0].id).toBe(1);
expect(res[0].name).toBe('form with all widgets');
expect(res[1].id).toBe(2);
expect(res[1].name).toBe('uppy');
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeFormList)
});
});
});
});

View File

@@ -15,9 +15,9 @@
* limitations under the License.
*/
import { AlfrescoApiService, LogService } from '@alfresco/adf-core';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { Injectable } from '@angular/core';
import { Observable, from, forkJoin, throwError, of } from 'rxjs';
import { Observable, from, forkJoin, of } from 'rxjs';
import { map, catchError, switchMap, flatMap, filter } from 'rxjs/operators';
import { FilterRepresentationModel, TaskQueryRequestRepresentationModel } from '../models/filter.model';
import { Form } from '../models/form.model';
@@ -57,8 +57,7 @@ export class TaskListService {
return this._checklistsApi;
}
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
constructor(private apiService: AlfrescoApiService) {
}
/**
@@ -87,8 +86,7 @@ export class TaskListService {
const requestNodeForFilter = this.generateTaskRequestNodeFromFilter(filterModel);
return from(this.callApiTasksFiltered(requestNodeForFilter))
.pipe(
map(res => res.data.find((element) => element.id === taskId) ? filterModel : null),
catchError((err) => this.handleError(err))
map(res => res.data.find((element) => element.id === taskId) ? filterModel : null)
);
}
@@ -99,10 +97,7 @@ export class TaskListService {
* @returns List of tasks
*/
getTasks(requestNode: TaskQueryRequestRepresentationModel): Observable<TaskListModel> {
return from(this.callApiTasksFiltered(requestNode))
.pipe(
catchError((err) => this.handleError(err))
);
return from(this.callApiTasksFiltered(requestNode));
}
/**
@@ -168,8 +163,7 @@ export class TaskListService {
getTaskDetails(taskId: string): Observable<TaskDetailsModel> {
return from(this.callApiTaskDetails(taskId))
.pipe(
map(details => new TaskDetailsModel(details)),
catchError((err) => this.handleError(err))
map(details => new TaskDetailsModel(details))
);
}
@@ -188,8 +182,7 @@ export class TaskListService {
checklists.push(new TaskDetailsModel(checklist));
});
return checklists;
}),
catchError((err) => this.handleError(err))
})
);
}
@@ -213,8 +206,7 @@ export class TaskListService {
forms.push(new Form(form.id, form.name));
});
return forms;
}),
catchError((err) => this.handleError(err))
})
);
}
@@ -226,10 +218,7 @@ export class TaskListService {
* @returns Null response notifying when the operation is complete
*/
attachFormToATask(taskId: string, formId: number): Observable<any> {
return from(this.taskActionsApi.attachForm(taskId, { formId }))
.pipe(
catchError((err) => this.handleError(err))
);
return from(this.taskActionsApi.attachForm(taskId, { formId }));
}
/**
@@ -241,8 +230,7 @@ export class TaskListService {
addTask(task: TaskDetailsModel): Observable<TaskDetailsModel> {
return from(this.callApiAddTask(task))
.pipe(
map((response) => new TaskDetailsModel(response)),
catchError((err) => this.handleError(err))
map((response) => new TaskDetailsModel(response))
);
}
@@ -253,10 +241,7 @@ export class TaskListService {
* @returns Null response notifying when the operation is complete
*/
deleteTask(taskId: string): Observable<TaskDetailsModel> {
return from(this.callApiDeleteTask(taskId))
.pipe(
catchError((err) => this.handleError(err))
);
return from(this.callApiDeleteTask(taskId));
}
/**
@@ -266,10 +251,7 @@ export class TaskListService {
* @returns Null response notifying when the operation is complete
*/
deleteForm(taskId: string): Observable<TaskDetailsModel> {
return from(this.callApiDeleteForm(taskId))
.pipe(
catchError((err) => this.handleError(err))
);
return from(this.callApiDeleteForm(taskId));
}
/**
@@ -279,10 +261,7 @@ export class TaskListService {
* @returns Null response notifying when the operation is complete
*/
completeTask(taskId: string) {
return from(this.taskActionsApi.completeTask(taskId))
.pipe(
catchError((err) => this.handleError(err))
);
return from(this.taskActionsApi.completeTask(taskId));
}
/**
@@ -291,12 +270,9 @@ export class TaskListService {
* @param requestNode Query to search for tasks
* @returns Number of tasks
*/
public getTotalTasks(requestNode: TaskQueryRequestRepresentationModel): Observable<any> {
public getTotalTasks(requestNode: TaskQueryRequestRepresentationModel): Observable<TaskListModel> {
requestNode.size = 0;
return from(this.callApiTasksFiltered(requestNode))
.pipe(
catchError((err) => this.handleError(err))
);
return from(this.callApiTasksFiltered(requestNode));
}
/**
@@ -308,8 +284,7 @@ export class TaskListService {
createNewTask(task: TaskDetailsModel): Observable<TaskDetailsModel> {
return from(this.callApiCreateTask(task))
.pipe(
map((response) => new TaskDetailsModel(response)),
catchError((err) => this.handleError(err))
map((response) => new TaskDetailsModel(response))
);
}
@@ -324,8 +299,7 @@ export class TaskListService {
const assignee = { assignee: requestNode.id };
return from(this.callApiAssignTask(taskId, assignee))
.pipe(
map((response) => new TaskDetailsModel(response)),
catchError((err) => this.handleError(err))
map((response) => new TaskDetailsModel(response))
);
}
@@ -341,8 +315,7 @@ export class TaskListService {
return from(this.callApiAssignTask(taskId, assignee))
.pipe(
map((response) => new TaskDetailsModel(response)),
catchError((err) => this.handleError(err))
map((response) => new TaskDetailsModel(response))
);
}
@@ -353,10 +326,7 @@ export class TaskListService {
* @returns Details of the claimed task
*/
claimTask(taskId: string): Observable<TaskDetailsModel> {
return from(this.taskActionsApi.claimTask(taskId))
.pipe(
catchError((err) => this.handleError(err))
);
return from(this.taskActionsApi.claimTask(taskId));
}
/**
@@ -366,10 +336,7 @@ export class TaskListService {
* @returns Null response notifying when the operation is complete
*/
unclaimTask(taskId: string): Observable<TaskDetailsModel> {
return from(this.taskActionsApi.unclaimTask(taskId))
.pipe(
catchError((err) => this.handleError(err))
);
return from(this.taskActionsApi.unclaimTask(taskId));
}
/**
@@ -382,8 +349,7 @@ export class TaskListService {
updateTask(taskId: string, updated: TaskUpdateRepresentation): Observable<TaskDetailsModel> {
return from(this.tasksApi.updateTask(taskId, updated))
.pipe(
map((result) => result as TaskDetailsModel),
catchError((err) => this.handleError(err))
map((result) => result as TaskDetailsModel)
);
}
@@ -394,11 +360,7 @@ export class TaskListService {
* @returns Binary PDF data
*/
fetchTaskAuditPdfById(taskId: string): Observable<Blob> {
return from(this.tasksApi.getTaskAuditPdf(taskId))
.pipe(
map((data) => data as Blob),
catchError((err) => this.handleError(err))
);
return from(this.tasksApi.getTaskAuditPdf(taskId));
}
/**
@@ -408,10 +370,7 @@ export class TaskListService {
* @returns JSON data
*/
fetchTaskAuditJsonById(taskId: string): Observable<any> {
return from(this.tasksApi.getTaskAuditLog(taskId))
.pipe(
catchError((err) => this.handleError(err))
);
return from(this.tasksApi.getTaskAuditLog(taskId));
}
/**
@@ -461,10 +420,4 @@ export class TaskListService {
private callApiAssignTask(taskId: string, requestNode: AssigneeIdentifierRepresentation): Promise<TaskDetailsModel> {
return this.taskActionsApi.assignTask(taskId, requestNode);
}
private handleError(error: any) {
this.logService.error(error);
return throwError(error || 'Server error');
}
}