[ACS-7688] Reduce the usage of LogService and TranslateModule (tests) (#9567)

This commit is contained in:
Denys Vuika
2024-04-19 12:14:33 -04:00
committed by GitHub
parent caa2166151
commit 54c3e12ad8
275 changed files with 4089 additions and 5550 deletions
@@ -21,7 +21,6 @@ import { AppDetailsCloudComponent } from './app-details-cloud.component';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { AppListCloudModule } from '../app-list-cloud.module';
import { DEFAULT_APP_INSTANCE_THEME } from '../models/application-instance.model';
import { TranslateModule } from '@ngx-translate/core';
describe('AppDetailsCloudComponent', () => {
let component: AppDetailsCloudComponent;
@@ -30,7 +29,7 @@ describe('AppDetailsCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule, AppListCloudModule]
imports: [ProcessServiceCloudTestingModule, AppListCloudModule]
});
fixture = TestBed.createComponent(AppDetailsCloudComponent);
component = fixture.componentInstance;
@@ -19,12 +19,10 @@ import { Component } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { of, throwError } from 'rxjs';
import { fakeApplicationInstance } from '../mock/app-model.mock';
import { AppListCloudComponent, LAYOUT_GRID, LAYOUT_LIST } from './app-list-cloud.component';
import { AppsProcessCloudService } from '../services/apps-process-cloud.service';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
describe('AppListCloudComponent', () => {
let component: AppListCloudComponent;
@@ -55,7 +53,7 @@ describe('AppListCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
imports: [ProcessServiceCloudTestingModule],
declarations: [CustomEmptyAppListCloudTemplateComponent]
});
fixture = TestBed.createComponent(AppListCloudComponent);
@@ -22,29 +22,22 @@ import { HttpErrorResponse } from '@angular/common/http';
import { AppsProcessCloudService } from './apps-process-cloud.service';
import { fakeApplicationInstance, fakeApplicationInstanceWithEnvironment } from '../mock/app-model.mock';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { fakeEnvironmentList } from '../../common/mock/environment.mock';
import { AdfHttpClient } from '@alfresco/adf-core/api';
describe('AppsProcessCloudService', () => {
let service: AppsProcessCloudService;
let appConfigService: AppConfigService;
let adfHttpClient: AdfHttpClient;
const apiMockResponse: any = Promise.resolve({list : { entries: [ {entry: fakeApplicationInstance[0]}, {entry: fakeApplicationInstance[1]}] }});
const apiMockResponse: any = Promise.resolve({
list: { entries: [{ entry: fakeApplicationInstance[0] }, { entry: fakeApplicationInstance[1] }] }
});
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
CoreTestingModule,
ProcessServiceCloudTestingModule
],
providers: [
AlfrescoApiService,
AppConfigService
]
imports: [CoreTestingModule, ProcessServiceCloudTestingModule],
providers: [AlfrescoApiService, AppConfigService]
});
adfHttpClient = TestBed.inject(AdfHttpClient);
spyOn(adfHttpClient, 'request').and.returnValue(apiMockResponse);
@@ -56,50 +49,45 @@ describe('AppsProcessCloudService', () => {
it('should get the deployed applications no apps are specified in app.config', (done) => {
spyOn(appConfigService, 'get').and.returnValue([]);
service.loadApps();
service.getDeployedApplicationsByStatus('fake').subscribe(
(res) => {
expect(res).toBeDefined();
expect(res.length).toEqual(2);
expect(res[0].name).toEqual('application-new-1');
expect(res[1].name).toEqual('application-new-2');
done();
}
);
service.getDeployedApplicationsByStatus('fake').subscribe((res) => {
expect(res).toBeDefined();
expect(res.length).toEqual(2);
expect(res[0].name).toEqual('application-new-1');
expect(res[1].name).toEqual('application-new-2');
done();
});
});
it('should get apps from app.config when apps are specified in app.config', (done) => {
spyOn(appConfigService, 'get').and.returnValue([fakeApplicationInstance[0]]);
service.loadApps();
service.getDeployedApplicationsByStatus('fake').subscribe(
(res) => {
expect(res).toBeDefined();
expect(res.length).toEqual(1);
expect(res[0]).toEqual(fakeApplicationInstance[0]);
expect(res[0].name).toEqual('application-new-1');
done();
}
);
service.getDeployedApplicationsByStatus('fake').subscribe((res) => {
expect(res).toBeDefined();
expect(res.length).toEqual(1);
expect(res[0]).toEqual(fakeApplicationInstance[0]);
expect(res[0].name).toEqual('application-new-1');
done();
});
});
it('Should not fetch deployed applications if error occurred', () => {
const errorResponse = new HttpErrorResponse({
error: 'Mock Error',
status: 404, statusText: 'Not Found'
status: 404,
statusText: 'Not Found'
});
spyOn(service, 'getDeployedApplicationsByStatus').and.returnValue(throwError(errorResponse));
service.getDeployedApplicationsByStatus('fake')
.subscribe(
() => fail('expected an error, not applications'),
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
}
);
service.getDeployedApplicationsByStatus('fake').subscribe(
() => fail('expected an error, not applications'),
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
}
);
});
it('should return label with application name', () => {
const applicationLabel = service.getApplicationLabel(fakeApplicationInstance[0]);
expect(applicationLabel).toBe('application-new-1');
@@ -17,7 +17,6 @@
import { DateRangeFilterComponent } from './date-range-filter.component';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { MatSelectChange } from '@angular/material/select';
import { DateCloudFilterType } from '../../models/date-cloud-filter.model';
@@ -38,10 +37,7 @@ describe('DateRangeFilterComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [ProcessServiceCloudTestingModule]
});
fixture = TestBed.createComponent(DateRangeFilterComponent);
component = fixture.componentInstance;
@@ -66,9 +62,11 @@ describe('DateRangeFilterComponent', () => {
spyOn(service, 'getDateRange');
spyOn(component.dateTypeChange, 'emit');
const stateElement = await loader.getHarness(MatSelectHarness.with({ selector: '[data-automation-id="adf-cloud-edit-process-property-createdDate"]' }));
const stateElement = await loader.getHarness(
MatSelectHarness.with({ selector: '[data-automation-id="adf-cloud-edit-process-property-createdDate"]' })
);
await stateElement.clickOptions({ selector: '[data-automation-id="adf-cloud-edit-process-property-options-WEEK"]'});
await stateElement.clickOptions({ selector: '[data-automation-id="adf-cloud-edit-process-property-options-WEEK"]' });
expect(service.getDateRange).not.toHaveBeenCalled();
expect(component.dateTypeChange.emit).toHaveBeenCalled();
@@ -76,9 +74,11 @@ describe('DateRangeFilterComponent', () => {
it('should not emit event on `RANGE` option change', async () => {
spyOn(component.dateTypeChange, 'emit');
const stateElement = await loader.getHarness(MatSelectHarness.with({ selector: '[data-automation-id="adf-cloud-edit-process-property-createdDate"]' }));
const stateElement = await loader.getHarness(
MatSelectHarness.with({ selector: '[data-automation-id="adf-cloud-edit-process-property-createdDate"]' })
);
await stateElement.clickOptions({ selector: '[data-automation-id="adf-cloud-edit-process-property-options-RANGE"]'});
await stateElement.clickOptions({ selector: '[data-automation-id="adf-cloud-edit-process-property-options-RANGE"]' });
expect(component.dateTypeChange.emit).not.toHaveBeenCalled();
});
@@ -133,7 +133,9 @@ describe('DateRangeFilterComponent', () => {
});
it('should have floating labels when values are present', async () => {
const stateElement = await loader.getHarness(MatSelectHarness.with({ selector: '[data-automation-id="adf-cloud-edit-process-property-createdDate"]' }));
const stateElement = await loader.getHarness(
MatSelectHarness.with({ selector: '[data-automation-id="adf-cloud-edit-process-property-createdDate"]' })
);
await stateElement.open();
const selectField = await loader.getHarness(MatFormFieldHarness.with({ selector: '[data-automation-id="createdDate"]' }));
@@ -19,60 +19,43 @@ import { FormModel } from '@alfresco/adf-core';
import { Component, DebugElement, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { FormCloudComponent } from './form-cloud.component';
@Component({
selector: 'adf-cloud-form-with-custom-outcomes',
template: `
<adf-cloud-form #adfCloudForm>
<adf-cloud-form-custom-outcomes>
<button mat-button id="adf-custom-outcome-1" (click)="onCustomButtonOneClick()">
CUSTOM-BUTTON-1
</button>
<button mat-button id="adf-custom-outcome-2" (click)="onCustomButtonTwoClick()">
CUSTOM-BUTTON-2
</button>
</adf-cloud-form-custom-outcomes>
</adf-cloud-form>`
template: ` <adf-cloud-form #adfCloudForm>
<adf-cloud-form-custom-outcomes>
<button mat-button id="adf-custom-outcome-1" (click)="onCustomButtonOneClick()">CUSTOM-BUTTON-1</button>
<button mat-button id="adf-custom-outcome-2" (click)="onCustomButtonTwoClick()">CUSTOM-BUTTON-2</button>
</adf-cloud-form-custom-outcomes>
</adf-cloud-form>`
})
class FormCloudWithCustomOutComesComponent {
@ViewChild('adfCloudForm', { static: true })
adfCloudForm: FormCloudComponent;
onCustomButtonOneClick() {
}
onCustomButtonOneClick() {}
onCustomButtonTwoClick() {
}
onCustomButtonTwoClick() {}
}
describe('FormCloudWithCustomOutComesComponent', () => {
let fixture: ComponentFixture<FormCloudWithCustomOutComesComponent>;
let customComponent: FormCloudWithCustomOutComesComponent;
let debugElement: DebugElement;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
imports: [ProcessServiceCloudTestingModule],
declarations: [FormCloudWithCustomOutComesComponent]
});
fixture = TestBed.createComponent(FormCloudWithCustomOutComesComponent);
customComponent = fixture.componentInstance;
debugElement = fixture.debugElement;
const formRepresentation = {
fields: [
{ id: 'container1' }
],
outcomes: [
{ id: 'outcome-1', name: 'outcome 1' }
]
fields: [{ id: 'container1' }],
outcomes: [{ id: 'outcome-1', name: 'outcome 1' }]
};
const form = new FormModel(formRepresentation);
@@ -21,13 +21,11 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FormDefinitionSelectorCloudComponent } from './form-definition-selector-cloud.component';
import { of } from 'rxjs';
import { FormDefinitionSelectorCloudService } from '../services/form-definition-selector-cloud.service';
import { TranslateModule } from '@ngx-translate/core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing';
describe('FormDefinitionCloudComponent', () => {
let fixture: ComponentFixture<FormDefinitionSelectorCloudComponent>;
let service: FormDefinitionSelectorCloudService;
let getFormsSpy: jasmine.Spy;
@@ -35,10 +33,7 @@ describe('FormDefinitionCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
imports: [ProcessServiceCloudTestingModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
fixture = TestBed.createComponent(FormDefinitionSelectorCloudComponent);
@@ -65,7 +60,7 @@ describe('FormDefinitionCloudComponent', () => {
const options = await selectElement.getOptions();
expect((options).length).toBe(1);
expect(options.length).toBe(1);
});
it('should not preselect any form by default', async () => {
@@ -71,7 +71,6 @@ import {
import { By } from '@angular/platform-browser';
import { of, throwError } from 'rxjs';
import { FormCloudModule } from '../../../form-cloud.module';
import { TranslateModule } from '@ngx-translate/core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
@@ -155,7 +154,7 @@ describe('AttachFileCloudWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule, FormCloudModule, ContentModule.forRoot()],
imports: [ProcessServiceCloudTestingModule, FormCloudModule, ContentModule.forRoot()],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
notificationService = TestBed.inject(NotificationService);
@@ -599,7 +598,7 @@ describe('AttachFileCloudWidgetComponent', () => {
it('should preview file when show is clicked', () => {
spyOn(processCloudContentService, 'getRawContentNode').and.returnValue(of(new Blob()));
let lastValue: ContentLinkModel;
formService.formContentClicked.subscribe((fileClicked) => lastValue = fileClicked);
formService.formContentClicked.subscribe((fileClicked) => (lastValue = fileClicked));
fixture.detectChanges();
const menuButton = fixture.debugElement.query(By.css('#file-fake-properties-option-menu')).nativeElement as HTMLButtonElement;
@@ -17,10 +17,9 @@
/* eslint-disable @angular-eslint/component-selector */
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core';
import {
FormService,
LogService,
ThumbnailService,
NotificationService,
FormValues,
@@ -35,13 +34,19 @@ import { ContentCloudNodeSelectorService } from '../../../services/content-cloud
import { ProcessCloudContentService } from '../../../services/process-cloud-content.service';
import { UploadCloudWidgetComponent } from './upload-cloud.widget';
import { DestinationFolderPathModel, DestinationFolderPathType } from '../../../models/form-cloud-representation.model';
import { ContentNodeSelectorPanelService, NewVersionUploaderDataAction, NewVersionUploaderDialogData, NewVersionUploaderService, VersionManagerUploadData } from '@alfresco/adf-content-services';
import {
ContentNodeSelectorPanelService,
NewVersionUploaderDataAction,
NewVersionUploaderDialogData,
NewVersionUploaderService,
VersionManagerUploadData
} from '@alfresco/adf-content-services';
export const RETRIEVE_METADATA_OPTION = 'retrieveMetadata';
export const ALIAS_ROOT_FOLDER = '-root-';
export const ALIAS_USER_FOLDER = '-my-';
export const APP_NAME = '-appname-';
export const VALID_ALIAS = [ ALIAS_ROOT_FOLDER, ALIAS_USER_FOLDER, '-shared-' ];
export const VALID_ALIAS = [ALIAS_ROOT_FOLDER, ALIAS_USER_FOLDER, '-shared-'];
@Component({
selector: 'adf-cloud-attach-file-cloud-widget',
@@ -65,6 +70,9 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
rootNodeId = ALIAS_USER_FOLDER;
selectedNode: Node;
@Output()
error = new EventEmitter<any>();
private previewState = false;
private _nodesApi: NodesApi;
get nodesApi(): NodesApi {
@@ -75,7 +83,6 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
constructor(
formService: FormService,
logger: LogService,
thumbnails: ThumbnailService,
processCloudContentService: ProcessCloudContentService,
notificationService: NotificationService,
@@ -85,7 +92,7 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
private contentNodeSelectorPanelService: ContentNodeSelectorPanelService,
private newVersionUploaderService: NewVersionUploaderService
) {
super(formService, thumbnails, processCloudContentService, notificationService, logger);
super(formService, thumbnails, processCloudContentService, notificationService);
}
ngOnInit() {
@@ -95,7 +102,7 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
this.contentModelFormFileHandler(files[0]);
}
this.field.params.displayableCMProperties = this.field.params.displayableCMProperties ?? [];
this.displayedColumns.splice(2, 0, ...(this.field.params.displayableCMProperties?.map(property => property?.name) || []));
this.displayedColumns.splice(2, 0, ...(this.field.params.displayableCMProperties?.map((property) => property?.name) || []));
this.setPreviewState();
}
@@ -139,7 +146,7 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
this.contentNodeSelectorService
.openUploadFileDialog(this.rootNodeId, selectedMode, this.isAlfrescoAndLocal(), true)
.subscribe((selections: Node[]) => {
selections.forEach(node => (node['isExternal'] = true));
selections.forEach((node) => (node['isExternal'] = true));
const selectionWithoutDuplication = this.removeExistingSelection(selections);
const hadFilesAttached = this.field.value?.length > 0;
this.fixIncompatibilityFromPreviousAndNewForm(selectionWithoutDuplication);
@@ -171,14 +178,14 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
return rootNodeId;
}
async getNodeIdFromPath(destinationFolderPath: DestinationFolderPath): Promise<string> {
async getNodeIdFromPath(destinationFolderPath: DestinationFolderPath): Promise<string> {
let nodeId: string;
const destinationPath = this.getAliasAndRelativePathFromDestinationFolderPath(destinationFolderPath.value);
const destinationPath = this.getAliasAndRelativePathFromDestinationFolderPath(destinationFolderPath.value);
destinationPath.path = this.replaceAppNameAliasWithValue(destinationPath.path);
try {
nodeId = await this.contentNodeSelectorService.getNodeIdFromPath(destinationPath);
} catch (error) {
this.logService.error(error);
this.error.emit(error);
}
return nodeId;
@@ -189,14 +196,15 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
try {
nodeId = await this.contentNodeSelectorService.getNodeIdFromFolderVariableValue(destinationFolderPath.value, ALIAS_USER_FOLDER);
} catch (error) {
this.logService.error(error);
this.error.emit(error);
}
return nodeId;
}
getAliasAndRelativePathFromDestinationFolderPath(destinationFolderPath: string): DestinationFolderPathModel {
let alias: string; let path: string;
let alias: string;
let path: string;
if (destinationFolderPath) {
const startOfRelativePathIndex = destinationFolderPath.indexOf('/');
if (startOfRelativePathIndex >= 0) {
@@ -211,8 +219,8 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
}
removeExistingSelection(selections: Node[]) {
const existingNode: Node[] = [...this.field.value || []];
return selections.filter(opt => !existingNode.some((node) => node.id === opt.id));
const existingNode: Node[] = [...(this.field.value || [])];
return selections.filter((opt) => !existingNode.some((node) => node.id === opt.id));
}
downloadContent(file: Node): void {
@@ -220,12 +228,13 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
}
onUploadNewFileVersion(node: NewVersionUploaderDialogData): void {
this.newVersionUploaderService.openUploadNewVersionDialog(node).subscribe((newVersionUploaderData) => {
if (newVersionUploaderData.action === NewVersionUploaderDataAction.upload) {
this.replaceOldFileVersionWithNew(newVersionUploaderData as VersionManagerUploadData);
}
},
error => this.notificationService.showError(error.value)
this.newVersionUploaderService.openUploadNewVersionDialog(node).subscribe(
(newVersionUploaderData) => {
if (newVersionUploaderData.action === NewVersionUploaderDataAction.upload) {
this.replaceOldFileVersionWithNew(newVersionUploaderData as VersionManagerUploadData);
}
},
(error) => this.notificationService.showError(error.value)
);
}
@@ -250,11 +259,11 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
contentModelFormFileHandler(file?: any) {
if (file?.id && this.isRetrieveMetadataOptionEnabled()) {
const values: FormValues = {};
this.nodesApi.getNode(file.id).then(acsNode => {
this.nodesApi.getNode(file.id).then((acsNode) => {
const metadata = acsNode?.entry?.properties;
if (metadata) {
const keys = Object.keys(metadata);
keys.forEach(key => {
keys.forEach((key) => {
const sanitizedKey = key.replace(':', '_');
values[sanitizedKey] = metadata[key];
});
@@ -18,7 +18,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { FilePropertiesTableCloudComponent } from './file-properties-table-cloud.component';
import { By } from '@angular/platform-browser';
import { MatTableModule } from '@angular/material/table';
@@ -30,12 +29,7 @@ describe('FilePropertiesTableCloudComponent', () => {
beforeEach(async () => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule,
MatTableModule,
MatIconModule
],
imports: [ProcessServiceCloudTestingModule, MatTableModule, MatIconModule],
declarations: [FilePropertiesTableCloudComponent]
}).compileComponents();
});
@@ -44,34 +38,34 @@ describe('FilePropertiesTableCloudComponent', () => {
fixture = TestBed.createComponent(FilePropertiesTableCloudComponent);
widget = fixture.componentInstance;
widget.uploadedFiles = [{
id: 'id',
name: 'download.png',
mimeType: 'image/png',
isExternal: true,
isFile: true,
isFolder: false,
content: {
mimeType: 'image/png'
widget.uploadedFiles = [
{
id: 'id',
name: 'download.png',
mimeType: 'image/png',
isExternal: true,
isFile: true,
isFolder: false,
content: {
mimeType: 'image/png'
}
},
{
id: 'id2',
name: 'download2.png',
mimeType: 'image/png',
isExternal: true,
isFile: true,
isFolder: false,
content: {
mimeType: 'image/png'
}
}
}, {
id: 'id2',
name: 'download2.png',
mimeType: 'image/png',
isExternal: true,
isFile: true,
isFolder: false,
content: {
mimeType: 'image/png'
}
}];
];
widget.hasFile = true;
widget.displayedColumns = [
'icon',
'fileName'
];
widget.displayedColumns = ['icon', 'fileName'];
fixture.detectChanges();
});
@@ -17,11 +17,11 @@
/* eslint-disable @angular-eslint/component-selector */
import { Component, ElementRef, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { Node } from '@alfresco/js-api';
import { Observable, from } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
import { WidgetComponent, LogService, FormService, ThumbnailService, NotificationService } from '@alfresco/adf-core';
import { WidgetComponent, FormService, ThumbnailService, NotificationService } from '@alfresco/adf-core';
import { ProcessCloudContentService } from '../../../services/process-cloud-content.service';
import { FileSourceTypes, DestinationFolderPathType } from '../../../models/form-cloud-representation.model';
import { VersionManagerUploadData } from '@alfresco/adf-content-services';
@@ -49,6 +49,9 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni
multipleOption: string = '';
mimeTypeIcon: string;
@Output()
error = new EventEmitter<any>();
@ViewChild('uploadFiles')
fileInput: ElementRef;
@@ -56,8 +59,7 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni
formService: FormService,
private thumbnailService: ThumbnailService,
protected processCloudContentService: ProcessCloudContentService,
protected notificationService: NotificationService,
protected logService: LogService
protected notificationService: NotificationService
) {
super(formService);
}
@@ -103,7 +105,7 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni
(res) => {
filesSaved.push(res);
},
(error) => this.logService.error(`Error uploading file. See console output for more details. ${error}`),
(error) => this.widgetError.emit(`Error uploading file. See console output for more details. ${error}`),
() => {
this.fixIncompatibilityFromPreviousAndNewForm(filesSaved);
this.hasFile = true;
@@ -16,7 +16,7 @@
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DataColumn, FormFieldModel, FormFieldTypes, FormModel, LogService, VariableConfig } from '@alfresco/adf-core';
import { DataColumn, FormFieldModel, FormFieldTypes, FormModel, VariableConfig } from '@alfresco/adf-core';
import { By } from '@angular/platform-browser';
import { DataTableWidgetComponent } from './data-table.widget';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
@@ -41,8 +41,6 @@ describe('DataTableWidgetComponent', () => {
let widget: DataTableWidgetComponent;
let fixture: ComponentFixture<DataTableWidgetComponent>;
let formCloudService: FormCloudService;
let logService: LogService;
let logServiceSpy: jasmine.Spy;
const errorIcon: string = 'error_outline';
@@ -86,14 +84,11 @@ describe('DataTableWidgetComponent', () => {
widget = fixture.componentInstance;
formCloudService = TestBed.inject(FormCloudService);
logService = TestBed.inject(LogService);
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
type: FormFieldTypes.DATA_TABLE,
name: 'Data Table'
});
logServiceSpy = spyOn(logService, 'error');
});
it('should display label', () => {
@@ -219,34 +214,31 @@ describe('DataTableWidgetComponent', () => {
expect(dataTable).toBeNull();
});
it('should display and log error if data source is not linked to every column', () => {
it('should display error if data source is not linked to every column', () => {
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
fixture.detectChanges();
checkDataTableErrorMessage();
expect(logServiceSpy).toHaveBeenCalledWith('Data source has corrupted model or structure');
expect(widget.dataSource.getRows()).toEqual([]);
});
it('should display and log error if data source has invalid column structure', () => {
it('should display error if data source has invalid column structure', () => {
widget.field = getDataVariable(mockVariableConfig, mockInvalidSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
fixture.detectChanges();
checkDataTableErrorMessage();
expect(logServiceSpy).toHaveBeenCalledWith('Data source has corrupted model or structure');
expect(widget.dataSource.getRows()).toEqual([]);
});
it('should display and log error if data source is not found', () => {
it('should display error if data source is not found', () => {
widget.field = getDataVariable({ variableName: 'not-found-data-source' }, mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
fixture.detectChanges();
checkDataTableErrorMessage();
expect(logServiceSpy).toHaveBeenCalledWith('Data source not found or it is not an array');
expect(widget.dataSource).toBeUndefined();
});
it('should display and log error if path is incorrect', () => {
it('should display error if path is incorrect', () => {
widget.field = getDataVariable(
{ ...mockVariableConfig, optionsPath: 'wrong.path' },
mockSchemaDefinition,
@@ -256,11 +248,10 @@ describe('DataTableWidgetComponent', () => {
fixture.detectChanges();
checkDataTableErrorMessage();
expect(logServiceSpy).toHaveBeenCalledWith('Data source not found or it is not an array');
expect(widget.dataSource).toBeUndefined();
});
it('should display and log error if provided data by path is not an array', () => {
it('should display error if provided data by path is not an array', () => {
widget.field = getDataVariable(
{ ...mockVariableConfig, optionsPath: 'response.no-array' },
mockSchemaDefinition,
@@ -270,7 +261,6 @@ describe('DataTableWidgetComponent', () => {
fixture.detectChanges();
checkDataTableErrorMessage();
expect(logServiceSpy).toHaveBeenCalledWith('Data source not found or it is not an array');
expect(widget.dataSource).toBeUndefined();
});
});
@@ -18,7 +18,7 @@
/* eslint-disable @angular-eslint/component-selector */
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { WidgetComponent, FormService, DataTableModule, LogService, FormBaseModule, DataRow, DataColumn } from '@alfresco/adf-core';
import { WidgetComponent, FormService, DataTableModule, FormBaseModule, DataRow, DataColumn } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { FormCloudService } from '../../../services/form-cloud.service';
@@ -46,6 +46,7 @@ import { DataTablePathParserHelper } from './helpers/data-table-path-parser.help
encapsulation: ViewEncapsulation.None
})
export class DataTableWidgetComponent extends WidgetComponent implements OnInit {
dataSource: WidgetDataTableAdapter;
dataTableLoadFailed = false;
previewState = false;
@@ -56,7 +57,7 @@ export class DataTableWidgetComponent extends WidgetComponent implements OnInit
private defaultResponseProperty = 'data';
private pathParserHelper = new DataTablePathParserHelper();
constructor(public formService: FormService, private formCloudService: FormCloudService, private logService: LogService) {
constructor(public formService: FormService, private formCloudService: FormCloudService) {
super(formService);
}
@@ -120,7 +121,7 @@ export class DataTableWidgetComponent extends WidgetComponent implements OnInit
private handleError(error: any) {
if (!this.previewState) {
this.dataTableLoadFailed = true;
this.logService.error(error);
this.widgetError.emit(error);
}
}
}
@@ -19,7 +19,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DateCloudWidgetComponent } from './date-cloud.widget';
import { FormFieldModel, FormModel, FormFieldTypes, DateFieldValidator, MinDateFieldValidator, MaxDateFieldValidator } from '@alfresco/adf-core';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { DateAdapter } from '@angular/material/core';
import { isEqual, subDays, addDays } from 'date-fns';
import { HarnessLoader } from '@angular/cdk/testing';
@@ -37,7 +36,7 @@ describe('DateWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule]
imports: [ProcessServiceCloudTestingModule]
});
form = new FormModel();
@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { FormService, FormFieldModel, FormModel, FormFieldTypes, LogService } from '@alfresco/adf-core';
import { FormService, FormFieldModel, FormModel, FormFieldTypes } from '@alfresco/adf-core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
@@ -23,27 +23,19 @@ import { ReactiveFormsModule } from '@angular/forms';
import { MatInputHarness } from '@angular/material/input/testing';
import { DisplayExternalPropertyWidgetComponent } from './display-external-property.widget';
import { FormCloudService } from '../../../services/form-cloud.service';
import { TranslateModule } from '@ngx-translate/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { By } from '@angular/platform-browser';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
describe('DisplayExternalPropertyWidgetComponent', () => {
let loader: HarnessLoader;
let widget: DisplayExternalPropertyWidgetComponent;
let fixture: ComponentFixture<DisplayExternalPropertyWidgetComponent>;
let element: HTMLElement;
let logService: LogService;
let logServiceSpy: jasmine.Spy;
let formCloudService: FormCloudService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
NoopAnimationsModule,
ReactiveFormsModule,
DisplayExternalPropertyWidgetComponent
],
imports: [ProcessServiceCloudTestingModule, ReactiveFormsModule, DisplayExternalPropertyWidgetComponent],
providers: [FormService]
}).compileComponents();
@@ -51,10 +43,7 @@ describe('DisplayExternalPropertyWidgetComponent', () => {
widget = fixture.componentInstance;
element = fixture.nativeElement;
loader = TestbedHarnessEnvironment.loader(fixture);
logService = TestBed.inject(LogService);
formCloudService = TestBed.inject(FormCloudService);
logServiceSpy = spyOn(logService, 'error');
});
it('should display initial value', async () => {
@@ -101,10 +90,6 @@ describe('DisplayExternalPropertyWidgetComponent', () => {
const errorElement = element.querySelector('error-widget');
expect(errorElement.textContent.trim()).toContain('FORM.FIELD.EXTERNAL_PROPERTY_LOAD_FAILED');
});
it('should log the error', () => {
expect(logServiceSpy).toHaveBeenCalledWith('External property not found');
});
});
describe('when property is in preview state', () => {
@@ -124,10 +109,6 @@ describe('DisplayExternalPropertyWidgetComponent', () => {
expect(errorElement).toBeFalsy();
});
it('should NOT log the error', () => {
expect(logServiceSpy).not.toHaveBeenCalled();
});
it('should display external property name', () => {
const externalPropertyPreview = fixture.debugElement.query(By.css('[data-automation-id="adf-display-external-property-widget-preview"]'));
expect(externalPropertyPreview.nativeElement.textContent.trim()).toBe('fruitName');
@@ -16,12 +16,7 @@
*/
import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';
import {
WidgetComponent,
FormService,
LogService,
FormBaseModule
} from '@alfresco/adf-core';
import { WidgetComponent, FormService, FormBaseModule } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { FormCloudService } from '../../../services/form-cloud.service';
@@ -31,14 +26,7 @@ import { MatInputModule } from '@angular/material/input';
@Component({
standalone: true,
imports: [
CommonModule,
TranslateModule,
ReactiveFormsModule,
MatFormFieldModule,
MatInputModule,
FormBaseModule
],
imports: [CommonModule, TranslateModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, FormBaseModule],
selector: 'adf-cloud-display-external-property',
templateUrl: './display-external-property.widget.html',
styleUrls: ['./display-external-property.widget.scss'],
@@ -57,16 +45,11 @@ import { MatInputModule } from '@angular/material/input';
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DisplayExternalPropertyWidgetComponent extends WidgetComponent implements OnInit {
propertyLoadFailed = false;
previewState = false;
propertyControl: FormControl;
constructor(
public readonly formService: FormService,
private readonly formCloudService: FormCloudService,
private readonly logService: LogService
) {
constructor(public readonly formService: FormService, private readonly formCloudService: FormCloudService) {
super(formService);
}
@@ -103,7 +86,7 @@ export class DisplayExternalPropertyWidgetComponent extends WidgetComponent impl
private handleError(error: any): void {
if (!this.previewState) {
this.propertyLoadFailed = true;
this.logService.error(error);
this.widgetError.emit(error);
}
}
}
@@ -19,23 +19,14 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { of, throwError } from 'rxjs';
import { DropdownCloudWidgetComponent } from './dropdown-cloud.widget';
import {
FormFieldModel,
FormModel,
FormService,
FormFieldEvent,
FormFieldTypes,
LogService
} from '@alfresco/adf-core';
import { FormFieldModel, FormModel, FormService, FormFieldEvent, FormFieldTypes } from '@alfresco/adf-core';
import { FormCloudService } from '../../../services/form-cloud.service';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import {
fakeOptionList,
filterOptionList,
mockConditionalEntries,
mockFormVariableWithJson,
mockPlayersResponse,
mockRestDropdownOptions,
mockSecondRestDropdownOptions,
mockVariablesWithDefaultJson,
@@ -49,21 +40,16 @@ import { MatFormFieldHarness } from '@angular/material/form-field/testing';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
describe('DropdownCloudWidgetComponent', () => {
let formService: FormService;
let widget: DropdownCloudWidgetComponent;
let formCloudService: FormCloudService;
let logService: LogService;
let fixture: ComponentFixture<DropdownCloudWidgetComponent>;
let element: HTMLElement;
let loader: HarnessLoader;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [ProcessServiceCloudTestingModule]
});
fixture = TestBed.createComponent(DropdownCloudWidgetComponent);
widget = fixture.componentInstance;
@@ -71,14 +57,12 @@ describe('DropdownCloudWidgetComponent', () => {
formService = TestBed.inject(FormService);
formCloudService = TestBed.inject(FormCloudService);
logService = TestBed.inject(LogService);
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => fixture.destroy());
describe('Simple Dropdown', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
id: 'dropdown-id',
@@ -163,23 +147,25 @@ describe('DropdownCloudWidgetComponent', () => {
name: 'default1_value'
};
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of([
{
id: 'opt1',
name: 'default1_value'
},
{
id: 2,
name: 'default2_value'
}
] as any));
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(
of([
{
id: 'opt1',
name: 'default1_value'
},
{
id: 2,
name: 'default2_value'
}
] as any)
);
widget.ngOnInit();
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
await dropdown.open();
expect((await (await dropdown.getOptions())[0].getText())).toEqual('default1_value');
expect(await (await dropdown.getOptions())[0].getText()).toEqual('default1_value');
});
it('should preselect dropdown widget value when String (defined value) passed ', async () => {
@@ -187,30 +173,29 @@ describe('DropdownCloudWidgetComponent', () => {
widget.field.optionType = 'rest';
widget.field.value = 'opt1';
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of([
{
id: 'opt1',
name: 'default1_value'
},
{
id: 2,
name: 'default2_value'
}
] as any));
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(
of([
{
id: 'opt1',
name: 'default1_value'
},
{
id: 2,
name: 'default2_value'
}
] as any)
);
widget.ngOnInit();
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
await dropdown.open();
expect((await (await dropdown.getOptions())[0].getText())).toEqual('default1_value');
expect(await (await dropdown.getOptions())[0].getText()).toEqual('default1_value');
expect(widget.field.form.values['dropdown-id']).toEqual({ id: 'opt1', name: 'default1_value' });
});
it('should not display required error for a non required dropdown when selecting the none option', async () => {
widget.field.options = [
{ id: 'empty', name: 'Choose empty' },
...fakeOptionList
];
widget.field.options = [{ id: 'empty', name: 'Choose empty' }, ...fakeOptionList];
widget.ngOnInit();
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
@@ -226,10 +211,7 @@ describe('DropdownCloudWidgetComponent', () => {
it('should not display required error when selecting a valid option for a required dropdown', async () => {
widget.field.required = true;
widget.field.options = [
{ id: 'empty', name: 'Choose empty' },
...fakeOptionList
];
widget.field.options = [{ id: 'empty', name: 'Choose empty' }, ...fakeOptionList];
widget.ngOnInit();
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
@@ -243,10 +225,7 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should not have a value when switching from an available option to the None option', async () => {
widget.field.options = [
{ id: 'empty', name: 'This is a mock none option' },
...fakeOptionList
];
widget.field.options = [{ id: 'empty', name: 'This is a mock none option' }, ...fakeOptionList];
widget.ngOnInit();
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
@@ -270,7 +249,6 @@ describe('DropdownCloudWidgetComponent', () => {
});
describe('when tooltip is set', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.DROPDOWN,
@@ -288,7 +266,7 @@ describe('DropdownCloudWidgetComponent', () => {
expect(tooltipElement).toBeTruthy();
expect(await tooltipElement.getTooltipText()).toBe('my custom tooltip');
expect(await tooltipElement.isOpen()).toBeTruthy();
});
});
it('should hide tooltip', async () => {
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
@@ -303,9 +281,8 @@ describe('DropdownCloudWidgetComponent', () => {
});
describe('when is required', () => {
beforeEach(() => {
widget.field = new FormFieldModel( new FormModel({ taskId: '<id>' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.DROPDOWN,
required: true
});
@@ -341,7 +318,6 @@ describe('DropdownCloudWidgetComponent', () => {
});
describe('filter', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
id: 'dropdown-id',
@@ -393,7 +369,6 @@ describe('DropdownCloudWidgetComponent', () => {
});
describe('multiple selection', () => {
it('should show preselected option', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
id: 'dropdown-id',
@@ -439,31 +414,33 @@ describe('DropdownCloudWidgetComponent', () => {
type: 'dropdown',
readOnly: 'false',
restUrl: 'https://fake-rest-url',
optionType : 'rest',
optionType: 'rest',
selectionType: 'multiple',
value: [
{ id: 'opt_3', name: 'option_3' },
{ id: 'opt_4', name: 'option_4' }
]
});
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of([
{
id: 'opt_1',
name: 'option_1'
},
{
id: 'opt_2',
name: 'option_2'
},
{
id: 'opt_3',
name: 'option_3'
},
{
id: 'opt_4',
name: 'option_4'
}
] as any));
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(
of([
{
id: 'opt_1',
name: 'option_1'
},
{
id: 'opt_2',
name: 'option_2'
},
{
id: 'opt_3',
name: 'option_3'
},
{
id: 'opt_4',
name: 'option_4'
}
] as any)
);
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
@@ -477,28 +454,30 @@ describe('DropdownCloudWidgetComponent', () => {
type: 'dropdown',
readOnly: 'false',
restUrl: 'https://fake-rest-url',
optionType : 'rest',
optionType: 'rest',
selectionType: 'multiple'
});
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of([
{
id: 'opt_1',
name: 'option_1'
},
{
id: 'opt_2',
name: 'option_2'
},
{
id: 'opt_3',
name: 'option_3'
},
{
id: 'opt_4',
name: 'option_4'
}
] as any));
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(
of([
{
id: 'opt_1',
name: 'option_1'
},
{
id: 'opt_2',
name: 'option_2'
},
{
id: 'opt_3',
name: 'option_3'
},
{
id: 'opt_4',
name: 'option_4'
}
] as any)
);
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
await dropdown.clickOptions({ selector: '[id="opt_2"]' });
@@ -512,9 +491,7 @@ describe('DropdownCloudWidgetComponent', () => {
});
describe('Linked Dropdown', () => {
describe('Rest URL options', () => {
const parentDropdown = new FormFieldModel(new FormModel(), {
id: 'parentDropdown',
type: 'dropdown',
@@ -716,7 +693,6 @@ describe('DropdownCloudWidgetComponent', () => {
});
describe('Load selection for linked dropdown (i.e. saved, completed forms)', () => {
it('should load the selection of a manual type linked dropdown', () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
id: 'child-dropdown-id',
@@ -737,7 +713,7 @@ describe('DropdownCloudWidgetComponent', () => {
expect(updateFormSpy).toHaveBeenCalled();
expect(widget.field.options).toEqual(mockConditionalEntries[1].options);
expect(widget.field.form.values).toEqual({ 'child-dropdown-id': { id: 'MI', name: 'MILAN' }});
expect(widget.field.form.values).toEqual({ 'child-dropdown-id': { id: 'MI', name: 'MILAN' } });
});
it('should load the selection of a rest type linked dropdown', () => {
@@ -767,7 +743,6 @@ describe('DropdownCloudWidgetComponent', () => {
});
describe('when form model has left labels', () => {
it('should have left labels classes on leftLabels true', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', leftLabels: true }), {
id: 'dropdown-id',
@@ -828,18 +803,17 @@ describe('DropdownCloudWidgetComponent', () => {
});
describe('variable options', () => {
let logServiceSpy: jasmine.Spy;
const errorIcon: string = 'error_outline';
const getVariableDropdownWidget = (
variableName: string,
optionsPath: string,
optionsId: string,
optionsLabel: string,
processVariables?: TaskVariableCloud[],
variables?: TaskVariableCloud[]
) => new FormFieldModel(
new FormModel({ taskId: 'fake-task-id', processVariables, variables }), {
variableName: string,
optionsPath: string,
optionsId: string,
optionsLabel: string,
processVariables?: TaskVariableCloud[],
variables?: TaskVariableCloud[]
) =>
new FormFieldModel(new FormModel({ taskId: 'fake-task-id', processVariables, variables }), {
id: 'variable-dropdown-id',
name: 'variable-options-dropdown',
type: 'dropdown',
@@ -860,12 +834,14 @@ describe('DropdownCloudWidgetComponent', () => {
expect(widget.field.options.length).toEqual(0);
};
beforeEach(() => {
logServiceSpy = spyOn(logService, 'error');
});
it('should display options persisted from process variable', async () => {
widget.field = getVariableDropdownWidget('variables.json-variable', 'response.people.players', 'playerId', 'playerFullName', mockProcessVariablesWithJson);
widget.field = getVariableDropdownWidget(
'variables.json-variable',
'response.people.players',
'playerId',
'playerFullName',
mockProcessVariablesWithJson
);
fixture.detectChanges();
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
await dropdown.open();
@@ -913,35 +889,55 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should return empty array and display error when path is incorrect', () => {
widget.field = getVariableDropdownWidget('variables.json-variable', 'response.wrongPath.players', 'playerId', 'playerFullName', mockProcessVariablesWithJson);
widget.field = getVariableDropdownWidget(
'variables.json-variable',
'response.wrongPath.players',
'playerId',
'playerFullName',
mockProcessVariablesWithJson
);
fixture.detectChanges();
checkDropdownVariableOptionsFailed();
expect(logServiceSpy).toHaveBeenCalledWith(`wrongPath not found in ${JSON.stringify(mockPlayersResponse.response)}`);
});
it('should return empty array and display error when id is incorrect', () => {
widget.field = getVariableDropdownWidget('variables.json-variable', 'response.people.players', 'wrongId', 'playerFullName', mockProcessVariablesWithJson);
widget.field = getVariableDropdownWidget(
'variables.json-variable',
'response.people.players',
'wrongId',
'playerFullName',
mockProcessVariablesWithJson
);
fixture.detectChanges();
checkDropdownVariableOptionsFailed();
expect(logServiceSpy).toHaveBeenCalledWith(`'id' or 'label' is not properly defined`);
});
it('should return empty array and display error when label is incorrect', () => {
widget.field = getVariableDropdownWidget('variables.json-variable', 'response.people.players', 'playerId', 'wrongFullName', mockProcessVariablesWithJson);
widget.field = getVariableDropdownWidget(
'variables.json-variable',
'response.people.players',
'playerId',
'wrongFullName',
mockProcessVariablesWithJson
);
fixture.detectChanges();
checkDropdownVariableOptionsFailed();
expect(logServiceSpy).toHaveBeenCalledWith(`'id' or 'label' is not properly defined`);
});
it('should return empty array and display error when variable is NOT found', () => {
widget.field = getVariableDropdownWidget('variables.wrong-variable-id', 'response.people.players', 'playerId', 'playerFullName', mockProcessVariablesWithJson);
widget.field = getVariableDropdownWidget(
'variables.wrong-variable-id',
'response.people.players',
'playerId',
'playerFullName',
mockProcessVariablesWithJson
);
fixture.detectChanges();
checkDropdownVariableOptionsFailed();
expect(logServiceSpy).toHaveBeenCalledWith(`variables.wrong-variable-id not found`);
});
it('should return empty array and display error if there are NO process and form variables', () => {
@@ -949,11 +945,16 @@ describe('DropdownCloudWidgetComponent', () => {
fixture.detectChanges();
checkDropdownVariableOptionsFailed();
expect(logServiceSpy).toHaveBeenCalledWith('variables.json-variable not found');
});
it('should NOT display errors if form is in the preview state', () => {
widget.field = getVariableDropdownWidget('variables.json-variable', 'response.wrongPath.players', 'playerId', 'playerFullName', mockProcessVariablesWithJson);
widget.field = getVariableDropdownWidget(
'variables.json-variable',
'response.wrongPath.players',
'playerId',
'playerFullName',
mockProcessVariablesWithJson
);
spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
fixture.detectChanges();
@@ -23,7 +23,6 @@ import {
FormFieldOption,
FormFieldTypes,
FormService,
LogService,
RuleEntry,
WidgetComponent
} from '@alfresco/adf-core';
@@ -73,10 +72,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
protected onDestroy$ = new Subject<boolean>();
constructor(public formService: FormService,
private formCloudService: FormCloudService,
private logService: LogService,
private appConfig: AppConfigService) {
constructor(public formService: FormService, private formCloudService: FormCloudService, private appConfig: AppConfigService) {
super(formService);
}
@@ -148,8 +144,8 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
private getOptionsFromArray(nestedData: any[], id: string, label: string): FormFieldOption[] {
const options = nestedData.map(item => this.createOption(item, id, label));
const hasInvalidOption = options.some(option => !option);
const options = nestedData.map((item) => this.createOption(item, id, label));
const hasInvalidOption = options.some((option) => !option);
if (hasInvalidOption) {
this.variableOptionsFailed = true;
@@ -174,7 +170,11 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
return option;
}
private getOptionsFromVariable(processVariables: TaskVariableCloud[], formVariables: TaskVariableCloud[], variableName: string): TaskVariableCloud {
private getOptionsFromVariable(
processVariables: TaskVariableCloud[],
formVariables: TaskVariableCloud[],
variableName: string
): TaskVariableCloud {
const processVariableDropdownOptions: TaskVariableCloud = this.getVariableValueByName(processVariables, variableName);
const formVariableDropdownOptions: TaskVariableCloud = this.getVariableValueByName(formVariables, variableName);
@@ -182,7 +182,8 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
private getVariableValueByName(variables: TaskVariableCloud[], variableName: string): any {
return variables?.find((variable: TaskVariableCloud) => variable?.name === `variables.${variableName}` || variable?.name === variableName)?.value;
return variables?.find((variable: TaskVariableCloud) => variable?.name === `variables.${variableName}` || variable?.name === variableName)
?.value;
}
private isVariableOptionType(): boolean {
@@ -193,18 +194,22 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
if (this.isValidRestType()) {
this.resetRestApiErrorMessage();
const bodyParam = this.buildBodyParam();
this.formCloudService.getRestWidgetData(this.field.form.id, this.field.id, bodyParam)
this.formCloudService
.getRestWidgetData(this.field.form.id, this.field.id, bodyParam)
.pipe(takeUntil(this.onDestroy$))
.subscribe((result: FormFieldOption[]) => {
this.resetRestApiErrorMessage();
this.field.options = result;
this.updateOptions();
this.field.updateForm();
this.resetInvalidValue();
}, (err) => {
this.resetRestApiOptions();
this.handleError(err);
});
.subscribe(
(result: FormFieldOption[]) => {
this.resetRestApiErrorMessage();
this.field.options = result;
this.updateOptions();
this.field.updateForm();
this.resetInvalidValue();
},
(err) => {
this.resetRestApiOptions();
this.handleError(err);
}
);
}
}
@@ -225,7 +230,8 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
this.formService.formFieldValueChanged
.pipe(
filter((event: FormFieldEvent) => this.isFormFieldEventOfTypeDropdown(event) && this.isParentFormFieldEvent(event)),
takeUntil(this.onDestroy$))
takeUntil(this.onDestroy$)
)
.subscribe((event: FormFieldEvent) => {
const valueOfParentWidget = event.field.value;
this.parentValueChanged(valueOfParentWidget);
@@ -291,11 +297,11 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
private isSelectedValueInOptions(): boolean {
if (Array.isArray(this.fieldValue)) {
const optionIdList = [...this.field.options].map(option => option.id);
const fieldValueIds = this.fieldValue.map(valueOption => valueOption.id);
return fieldValueIds.every(valueOptionId => optionIdList.includes(valueOptionId));
const optionIdList = [...this.field.options].map((option) => option.id);
const fieldValueIds = this.fieldValue.map((valueOption) => valueOption.id);
return fieldValueIds.every((valueOptionId) => optionIdList.includes(valueOptionId));
} else {
return [...this.field.options].map(option => option.id).includes(this.fieldValue);
return [...this.field.options].map((option) => option.id).includes(this.fieldValue);
}
}
@@ -380,7 +386,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
private handleError(error: any) {
if (!this.previewState) {
this.logService.error(error);
this.widgetError.emit(error);
}
}
@@ -395,16 +401,15 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
updateOptions(): void {
this.showInputFilter = this.field.options.length > this.appConfig.get<number>('form.dropDownFilterLimit', HIDE_FILTER_LIMIT);
this.list$ = combineLatest([of(this.field.options), this.filter$])
.pipe(
map(([items, search]) => {
if (!search) {
return items;
}
return items.filter(({ name }) => name.toLowerCase().includes(search.toLowerCase()));
}),
takeUntil(this.onDestroy$)
);
this.list$ = combineLatest([of(this.field.options), this.filter$]).pipe(
map(([items, search]) => {
if (!search) {
return items;
}
return items.filter(({ name }) => name.toLowerCase().includes(search.toLowerCase()));
}),
takeUntil(this.onDestroy$)
);
}
resetRestApiErrorMessage() {
@@ -428,10 +433,12 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
showRequiredMessage(): boolean {
return (this.isInvalidFieldRequired() || (this.isNoneValueSelected(this.field.value) && this.isRequired())) &&
return (
(this.isInvalidFieldRequired() || (this.isNoneValueSelected(this.field.value) && this.isRequired())) &&
this.isTouched() &&
!this.isRestApiFailed &&
!this.variableOptionsFailed;
!this.variableOptionsFailed
);
}
getDefaultOption(options: FormFieldOption[]): FormFieldOption {
@@ -19,7 +19,6 @@ import { FormFieldModel, FormFieldTypes, FormModel, IdentityGroupModel } from '@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { GroupCloudWidgetComponent } from './group-cloud.widget';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
@@ -35,16 +34,9 @@ describe('GroupCloudWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
declarations: [
GroupCloudWidgetComponent
],
schemas: [
CUSTOM_ELEMENTS_SCHEMA
]
imports: [ProcessServiceCloudTestingModule],
declarations: [GroupCloudWidgetComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
fixture = TestBed.createComponent(GroupCloudWidgetComponent);
widget = fixture.componentInstance;
@@ -58,7 +50,7 @@ describe('GroupCloudWidgetComponent', () => {
it('should have enabled validation if field is NOT readOnly', () => {
const readOnly = false;
widget.field = new FormFieldModel( new FormModel({ taskId: '<id>' }, null, readOnly), {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }, null, readOnly), {
type: FormFieldTypes.GROUP,
value: []
});
@@ -68,7 +60,6 @@ describe('GroupCloudWidgetComponent', () => {
});
describe('when tooltip is set', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.GROUP,
@@ -86,7 +77,7 @@ describe('GroupCloudWidgetComponent', () => {
const tooltipElement = await loader.getHarness(MatTooltipHarness);
expect(await tooltipElement.isOpen()).toBeTruthy();
expect(await tooltipElement.getTooltipText()).toEqual('my custom tooltip');
});
});
it('should hide tooltip', async () => {
const cloudGroupInput = element.querySelector('[data-automation-id="adf-cloud-group-search-input"]');
@@ -104,9 +95,8 @@ describe('GroupCloudWidgetComponent', () => {
});
describe('when is required', () => {
beforeEach(() => {
widget.field = new FormFieldModel( new FormModel({ taskId: '<id>' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.GROUP,
required: true
});
@@ -138,7 +128,7 @@ describe('GroupCloudWidgetComponent', () => {
});
it('should be invalid after deselecting all groups', async () => {
widget.onChangedGroup([{id: 'test-id', name: 'test-name'}]);
widget.onChangedGroup([{ id: 'test-id', name: 'test-name' }]);
fixture.detectChanges();
await fixture.whenStable();
@@ -156,16 +146,17 @@ describe('GroupCloudWidgetComponent', () => {
});
describe('when is readOnly', () => {
const readOnly = true;
it('should single chip be disabled', async () => {
const mockSpaghetti: IdentityGroupModel[] = [{
id: 'bolognese',
name: 'Bolognese'
}];
const mockSpaghetti: IdentityGroupModel[] = [
{
id: 'bolognese',
name: 'Bolognese'
}
];
widget.field = new FormFieldModel( new FormModel({ taskId: '<id>'}, null, readOnly), {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }, null, readOnly), {
type: FormFieldTypes.GROUP,
value: mockSpaghetti
});
@@ -186,7 +177,7 @@ describe('GroupCloudWidgetComponent', () => {
{ id: 'carbonara', name: 'Carbonara' }
];
widget.field = new FormFieldModel( new FormModel({ taskId: '<id>'}, null, readOnly), {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }, null, readOnly), {
type: FormFieldTypes.GROUP,
value: mockSpaghetti
});
@@ -203,7 +194,7 @@ describe('GroupCloudWidgetComponent', () => {
});
it('should have disabled validation', () => {
widget.field = new FormFieldModel( new FormModel({ taskId: '<id>'}, null, readOnly), {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }, null, readOnly), {
type: FormFieldTypes.GROUP,
value: []
});
@@ -214,7 +205,6 @@ describe('GroupCloudWidgetComponent', () => {
});
describe('when form model has left labels', () => {
it('should have left labels classes on leftLabels true', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', leftLabels: true }), {
id: 'group-id',
@@ -16,7 +16,6 @@
*/
import { FormFieldModel, FormFieldTypes, FormModel, IdentityUserModel } from '@alfresco/adf-core';
import { TranslateModule } from '@ngx-translate/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PeopleCloudWidgetComponent } from './people-cloud.widget';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@@ -38,16 +37,9 @@ describe('PeopleCloudWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
declarations: [
PeopleCloudWidgetComponent
],
schemas: [
CUSTOM_ELEMENTS_SCHEMA
]
imports: [ProcessServiceCloudTestingModule],
declarations: [PeopleCloudWidgetComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
identityUserService = TestBed.inject(IdentityUserService);
fixture = TestBed.createComponent(PeopleCloudWidgetComponent);
@@ -85,7 +77,7 @@ describe('PeopleCloudWidgetComponent', () => {
it('should have enabled validation if field is NOT readOnly', () => {
const readOnly = false;
widget.field = new FormFieldModel( new FormModel({ taskId: '<id>'}, null, readOnly), {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }, null, readOnly), {
type: FormFieldTypes.PEOPLE,
value: []
});
@@ -95,7 +87,6 @@ describe('PeopleCloudWidgetComponent', () => {
});
describe('when tooltip is set', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.PEOPLE,
@@ -114,7 +105,7 @@ describe('PeopleCloudWidgetComponent', () => {
const tooltipElement = await loader.getHarness(MatTooltipHarness);
expect(await tooltipElement.isOpen()).toBeTruthy();
expect(await tooltipElement.getTooltipText()).toEqual('my custom tooltip');
});
});
it('should hide tooltip', async () => {
const cloudPeopleInput = element.querySelector('adf-cloud-people');
@@ -132,9 +123,8 @@ describe('PeopleCloudWidgetComponent', () => {
});
describe('when is required', () => {
beforeEach(() => {
widget.field = new FormFieldModel( new FormModel({ taskId: '<id>' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.PEOPLE,
required: true
});
@@ -166,7 +156,7 @@ describe('PeopleCloudWidgetComponent', () => {
});
it('should be invalid after deselecting all people', async () => {
widget.onChangedUser([{id: 'test-id', username: 'test-name'}]);
widget.onChangedUser([{ id: 'test-id', username: 'test-name' }]);
fixture.detectChanges();
await fixture.whenStable();
@@ -184,17 +174,18 @@ describe('PeopleCloudWidgetComponent', () => {
});
describe('when is readOnly', () => {
const readOnly = true;
it('should single chip be disabled', async () => {
const mockSpaghetti: IdentityUserModel[] = [{
id: 'bolognese',
username: 'Bolognese',
email: 'bolognese@example.com'
}];
const mockSpaghetti: IdentityUserModel[] = [
{
id: 'bolognese',
username: 'Bolognese',
email: 'bolognese@example.com'
}
];
widget.field = new FormFieldModel( new FormModel({ taskId: '<id>'}, null, readOnly), {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }, null, readOnly), {
type: FormFieldTypes.PEOPLE,
value: mockSpaghetti
});
@@ -214,7 +205,7 @@ describe('PeopleCloudWidgetComponent', () => {
{ id: 'carbonara', username: 'Carbonara', email: 'carbonara@example.com' }
];
widget.field = new FormFieldModel( new FormModel({ taskId: '<id>'}, null, readOnly), {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }, null, readOnly), {
type: FormFieldTypes.PEOPLE,
value: mockSpaghetti
});
@@ -229,7 +220,7 @@ describe('PeopleCloudWidgetComponent', () => {
});
it('should have disabled validation', () => {
widget.field = new FormFieldModel( new FormModel({ taskId: '<id>'}, null, readOnly), {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }, null, readOnly), {
type: FormFieldTypes.PEOPLE,
value: []
});
@@ -240,7 +231,6 @@ describe('PeopleCloudWidgetComponent', () => {
});
describe('when form model has left labels', () => {
it('should have left labels classes on leftLabels true', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', leftLabels: true }), {
id: 'people-id',
@@ -16,7 +16,6 @@
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { PropertiesViewerWrapperComponent } from './properties-viewer-wrapper.component';
import { ProcessServiceCloudTestingModule } from '../../../../../testing/process-service-cloud.testing.module';
import { of } from 'rxjs';
@@ -30,14 +29,8 @@ describe('PropertiesViewerWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
providers: [
NodesApiService,
{ provide: BasicPropertiesService, useValue: { getProperties: () => [] } }
]
imports: [ProcessServiceCloudTestingModule],
providers: [NodesApiService, { provide: BasicPropertiesService, useValue: { getProperties: () => [] } }]
});
fixture = TestBed.createComponent(PropertiesViewerWrapperComponent);
component = fixture.componentInstance;
@@ -17,7 +17,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormFieldModel, FormModel } from '@alfresco/adf-core';
import { TranslateModule } from '@ngx-translate/core';
import { PropertiesViewerWidgetComponent } from './properties-viewer.widget';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { fakeNodeWithProperties } from '../../../mocks/attach-file-cloud-widget.mock';
@@ -48,15 +47,9 @@ describe('PropertiesViewerWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
imports: [ProcessServiceCloudTestingModule],
declarations: [PropertiesViewerWrapperComponent],
providers: [
NodesApiService,
{ provide: BasicPropertiesService, useValue: { getProperties: () => [] } }
]
providers: [NodesApiService, { provide: BasicPropertiesService, useValue: { getProperties: () => [] } }]
});
fixture = TestBed.createComponent(PropertiesViewerWidgetComponent);
nodesApiService = TestBed.inject(NodesApiService);
@@ -16,7 +16,6 @@
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { FormFieldModel, FormFieldOption, FormFieldTypes, FormModel } from '@alfresco/adf-core';
import { FormCloudService } from '../../../services/form-cloud.service';
import { RadioButtonsCloudWidgetComponent } from './radio-buttons-cloud.widget';
@@ -46,10 +45,7 @@ describe('RadioButtonsCloudWidgetComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [ProcessServiceCloudTestingModule]
});
formCloudService = TestBed.inject(FormCloudService);
fixture = TestBed.createComponent(RadioButtonsCloudWidgetComponent);
@@ -132,7 +128,7 @@ describe('RadioButtonsCloudWidgetComponent', () => {
const option = await loader.getHarness(MatRadioButtonHarness.with({ label: 'opt-name-1' }));
await option.check();
await loader.getHarness(MatRadioButtonHarness.with({ checked: true, label: 'opt-name-1'}));
await loader.getHarness(MatRadioButtonHarness.with({ checked: true, label: 'opt-name-1' }));
expect(widget.field.isValid).toBe(true);
});
@@ -210,7 +206,6 @@ describe('RadioButtonsCloudWidgetComponent', () => {
});
describe('when tooltip is set', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.RADIO_BUTTONS,
@@ -226,7 +221,7 @@ describe('RadioButtonsCloudWidgetComponent', () => {
await (await radioButton.host()).hover();
const tooltip = await loader.getHarness(MatTooltipHarness);
expect(await tooltip.getTooltipText()).toBe('my custom tooltip');
});
});
it('should hide tooltip', async () => {
const radioButton = await loader.getHarness(MatRadioButtonHarness);
@@ -18,7 +18,7 @@
/* eslint-disable @angular-eslint/component-selector */
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { WidgetComponent, FormService, LogService, FormFieldOption, ErrorMessageModel } from '@alfresco/adf-core';
import { WidgetComponent, FormService, FormFieldOption, ErrorMessageModel } from '@alfresco/adf-core';
import { FormCloudService } from '../../../services/form-cloud.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@@ -47,12 +47,7 @@ export class RadioButtonsCloudWidgetComponent extends WidgetComponent implements
protected onDestroy$ = new Subject<boolean>();
constructor(
public formService: FormService,
private formCloudService: FormCloudService,
private logService: LogService,
private translateService: TranslateService
) {
constructor(public formService: FormService, private formCloudService: FormCloudService, private translateService: TranslateService) {
super(formService);
}
@@ -87,7 +82,7 @@ export class RadioButtonsCloudWidgetComponent extends WidgetComponent implements
this.restApiError = new ErrorMessageModel({
message: this.translateService.instant('FORM.FIELD.REST_API_FAILED', { hostname: this.getRestUrlHostName() })
});
this.logService.error(error);
this.widgetError.emit(error);
}
isChecked(option: FormFieldOption): boolean {
@@ -18,7 +18,6 @@
import { TestBed } from '@angular/core/testing';
import { AlfrescoApiService, AlfrescoApiServiceMock, NotificationService } from '@alfresco/adf-core';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { of, Subject } from 'rxjs';
import { ContentCloudNodeSelectorService } from './content-cloud-node-selector.service';
@@ -51,7 +50,7 @@ describe('ContentCloudNodeSelectorService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule, MatDialogModule],
imports: [ProcessServiceCloudTestingModule, MatDialogModule],
providers: [{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }]
});
service = TestBed.inject(ContentCloudNodeSelectorService);
@@ -16,13 +16,9 @@
*/
import { Injectable } from '@angular/core';
import { AlfrescoApiService, LogService, NotificationService } from '@alfresco/adf-core';
import { AlfrescoApiService, NotificationService } from '@alfresco/adf-core';
import { MatDialog } from '@angular/material/dialog';
import {
ContentNodeSelectorComponent,
ContentNodeSelectorComponentData,
NodeAction
} from '@alfresco/adf-content-services';
import { ContentNodeSelectorComponent, ContentNodeSelectorComponentData, NodeAction } from '@alfresco/adf-content-services';
import { Node, NodeEntry, NodesApi } from '@alfresco/js-api';
import { from, Observable, Subject, throwError } from 'rxjs';
import { catchError, map, mapTo } from 'rxjs/operators';
@@ -32,7 +28,6 @@ import { DestinationFolderPathModel } from '../models/form-cloud-representation.
providedIn: 'root'
})
export class ContentCloudNodeSelectorService {
private _nodesApi: NodesApi;
get nodesApi(): NodesApi {
this._nodesApi = this._nodesApi ?? new NodesApi(this.apiService.getInstance());
@@ -41,14 +36,14 @@ export class ContentCloudNodeSelectorService {
sourceNodeNotFound = false;
constructor(
private apiService: AlfrescoApiService,
private notificationService: NotificationService,
private logService: LogService,
private dialog: MatDialog) {
}
constructor(private apiService: AlfrescoApiService, private notificationService: NotificationService, private dialog: MatDialog) {}
openUploadFileDialog(currentFolderId?: string, selectionMode?: string, isAllFileSources?: boolean, restrictRootToCurrentFolderId?: boolean): Observable<Node[]> {
openUploadFileDialog(
currentFolderId?: string,
selectionMode?: string,
isAllFileSources?: boolean,
restrictRootToCurrentFolderId?: boolean
): Observable<Node[]> {
const select = new Subject<Node[]>();
select.subscribe({ complete: this.close.bind(this) });
const data = {
@@ -71,9 +66,7 @@ export class ContentCloudNodeSelectorService {
if (destinationFolderPath.alias && destinationFolderPath.path) {
try {
return await this.getNodeId(destinationFolderPath.alias, destinationFolderPath.path).toPromise();
} catch (error) {
this.logService.error(error);
}
} catch {}
}
return this.getNodeId(destinationFolderPath.alias).toPromise();
@@ -89,9 +82,7 @@ export class ContentCloudNodeSelectorService {
if (nodeId) {
try {
isExistingNode = await this.getNodeId(nodeId).pipe(mapTo(true)).toPromise();
} catch (error) {
this.logService.error(error);
}
} catch {}
}
return isExistingNode;
}
@@ -19,18 +19,15 @@ import { TestBed } from '@angular/core/testing';
import { FormCloudService } from './form-cloud.service';
import { of } from 'rxjs';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { AdfHttpClient } from '@alfresco/adf-core/api';
const mockTaskResponseBody = {
entry:
{ id: 'id', name: 'name', formKey: 'form-key' }
entry: { id: 'id', name: 'name', formKey: 'form-key' }
};
const mockFormResponseBody = { formRepresentation: { id: 'form-id', name: 'task-form', taskId: 'task-id' } };
describe('Form Cloud service', () => {
let service: FormCloudService;
let adfHttpClient: AdfHttpClient;
let requestSpy: jasmine.Spy;
@@ -40,10 +37,7 @@ describe('Form Cloud service', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [ProcessServiceCloudTestingModule]
});
service = TestBed.inject(FormCloudService);
adfHttpClient = TestBed.inject(AdfHttpClient);
@@ -88,44 +82,45 @@ describe('Form Cloud service', () => {
expect(requestSpy.calls.mostRecent().args[1].httpMethod).toBe('GET');
done();
});
});
it('should fetch task variables', (done) => {
requestSpy.and.returnValue(Promise.resolve({
list: {
entries: [
{
entry: {
serviceName: 'fake-rb',
serviceFullName: 'fake-rb',
serviceVersion: '',
appName: 'fake',
appVersion: '',
serviceType: null,
id: 25,
type: 'string',
name: 'fakeProperty',
createTime: 1556112661342,
lastUpdatedTime: 1556112661342,
executionId: null,
value: 'fakeValue',
markedAsDeleted: false,
processInstanceId: '18e16bc7-6694-11e9-9c1b-0a586460028a',
taskId: '18e192da-6694-11e9-9c1b-0a586460028a',
taskVariable: true
requestSpy.and.returnValue(
Promise.resolve({
list: {
entries: [
{
entry: {
serviceName: 'fake-rb',
serviceFullName: 'fake-rb',
serviceVersion: '',
appName: 'fake',
appVersion: '',
serviceType: null,
id: 25,
type: 'string',
name: 'fakeProperty',
createTime: 1556112661342,
lastUpdatedTime: 1556112661342,
executionId: null,
value: 'fakeValue',
markedAsDeleted: false,
processInstanceId: '18e16bc7-6694-11e9-9c1b-0a586460028a',
taskId: '18e192da-6694-11e9-9c1b-0a586460028a',
taskVariable: true
}
}
],
pagination: {
skipCount: 0,
maxItems: 100,
count: 1,
hasMoreItems: false,
totalItems: 1
}
],
pagination: {
skipCount: 0,
maxItems: 100,
count: 1,
hasMoreItems: false,
totalItems: 1
}
}
}));
})
);
service.getTaskVariables(appName, taskId).subscribe((result) => {
expect(result).toBeDefined();
@@ -139,40 +134,42 @@ describe('Form Cloud service', () => {
});
it('should fetch result if the variable value is 0', (done) => {
requestSpy.and.returnValue(Promise.resolve({
list: {
entries: [
{
entry: {
serviceName: 'fake-rb',
serviceFullName: 'fake-rb',
serviceVersion: '',
appName: 'fake',
appVersion: '',
serviceType: null,
id: 25,
type: 'string',
name: 'fakeProperty',
createTime: 1556112661342,
lastUpdatedTime: 1556112661342,
executionId: null,
value: 0,
markedAsDeleted: false,
processInstanceId: '18e16bc7-6694-11e9-9c1b-0a586460028a',
taskId: '18e192da-6694-11e9-9c1b-0a586460028a',
taskVariable: true
requestSpy.and.returnValue(
Promise.resolve({
list: {
entries: [
{
entry: {
serviceName: 'fake-rb',
serviceFullName: 'fake-rb',
serviceVersion: '',
appName: 'fake',
appVersion: '',
serviceType: null,
id: 25,
type: 'string',
name: 'fakeProperty',
createTime: 1556112661342,
lastUpdatedTime: 1556112661342,
executionId: null,
value: 0,
markedAsDeleted: false,
processInstanceId: '18e16bc7-6694-11e9-9c1b-0a586460028a',
taskId: '18e192da-6694-11e9-9c1b-0a586460028a',
taskVariable: true
}
}
],
pagination: {
skipCount: 0,
maxItems: 100,
count: 1,
hasMoreItems: false,
totalItems: 1
}
],
pagination: {
skipCount: 0,
maxItems: 100,
count: 1,
hasMoreItems: false,
totalItems: 1
}
}
}));
})
);
service.getTaskVariables(appName, taskId).subscribe((result) => {
expect(result).toBeDefined();
@@ -185,12 +182,14 @@ describe('Form Cloud service', () => {
it('should fetch task form flattened', (done) => {
spyOn(service, 'getTask').and.returnValue(of(mockTaskResponseBody.entry));
spyOn(service, 'getForm').and.returnValue(of({
formRepresentation: {
name: 'task-form',
formDefinition: {}
}
} as any));
spyOn(service, 'getForm').and.returnValue(
of({
formRepresentation: {
name: 'task-form',
formDefinition: {}
}
} as any)
);
service.getTaskForm(appName, taskId).subscribe((result) => {
expect(result).toBeDefined();
@@ -199,7 +198,6 @@ describe('Form Cloud service', () => {
expect(result.taskName).toBe('name');
done();
});
});
it('should save task form', (done) => {
@@ -214,7 +212,6 @@ describe('Form Cloud service', () => {
expect(requestSpy.calls.mostRecent().args[1].httpMethod).toBe('POST');
done();
});
});
it('should complete task form', (done) => {
@@ -18,22 +18,17 @@
import { TestBed } from '@angular/core/testing';
import { FormDefinitionSelectorCloudService } from './form-definition-selector-cloud.service';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { mockFormRepresentations } from '../mocks/form-representation.mock';
import { AdfHttpClient } from '@alfresco/adf-core/api';
describe('Form Definition Selector Cloud Service', () => {
let service: FormDefinitionSelectorCloudService;
let adfHttpClient: AdfHttpClient;
const appName = 'app-name';
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [ProcessServiceCloudTestingModule]
});
service = TestBed.inject(FormDefinitionSelectorCloudService);
adfHttpClient = TestBed.inject(AdfHttpClient);
@@ -23,7 +23,6 @@ import { GroupCloudModule } from '../group-cloud.module';
import { GroupCloudComponent } from './group-cloud.component';
import { CoreTestingModule } from '@alfresco/adf-core';
import { DebugElement, SimpleChange } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { IdentityGroupService } from '../services/identity-group.service';
import { mockFoodGroups, mockMeatChicken, mockVegetableAubergine } from '../mock/group-cloud.mock';
import { HarnessLoader } from '@angular/cdk/testing';
@@ -74,7 +73,7 @@ describe('GroupCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), CoreTestingModule, ProcessServiceCloudTestingModule, GroupCloudModule]
imports: [CoreTestingModule, ProcessServiceCloudTestingModule, GroupCloudModule]
});
fixture = TestBed.createComponent(GroupCloudComponent);
component = fixture.componentInstance;
@@ -33,7 +33,6 @@ import { UntypedFormControl } from '@angular/forms';
import { trigger, state, style, transition, animate } from '@angular/animations';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { distinctUntilChanged, switchMap, mergeMap, filter, tap, takeUntil, debounceTime } from 'rxjs/operators';
import { LogService } from '@alfresco/adf-core';
import { ComponentSelectionMode } from '../../types';
import { IdentityGroupModel } from '../models/identity-group.model';
import { IdentityGroupServiceInterface } from '../services/identity-group.service.interface';
@@ -140,8 +139,7 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
constructor(
@Inject(IDENTITY_GROUP_SERVICE_TOKEN)
private identityGroupService: IdentityGroupServiceInterface,
private logService: LogService
private identityGroupService: IdentityGroupServiceInterface
) {}
ngOnInit(): void {
@@ -247,7 +245,6 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
}
} catch (error) {
this.invalidGroups.push(group);
this.logService.error(error);
}
}
@@ -16,7 +16,6 @@
*/
import { TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { IdentityGroupService } from './identity-group.service';
import {
@@ -29,17 +28,13 @@ import { mockFoodGroups } from '../mock/group-cloud.mock';
import { AdfHttpClient } from '@alfresco/adf-core/api';
describe('IdentityGroupService', () => {
let service: IdentityGroupService;
let adfHttpClient: AdfHttpClient;
let requestSpy: jasmine.Spy;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [ProcessServiceCloudTestingModule]
});
service = TestBed.inject(IdentityGroupService);
adfHttpClient = TestBed.inject(AdfHttpClient);
@@ -47,21 +42,18 @@ describe('IdentityGroupService', () => {
});
describe('Search', () => {
it('should fetch groups', (done) => {
requestSpy.and.returnValue(Promise.resolve(mockFoodGroups));
const searchSpy = spyOn(service, 'search').and.callThrough();
service.search('fake').subscribe(
res => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake'
});
done();
}
);
service.search('fake').subscribe((res) => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake'
});
done();
});
});
it('should not fetch groups if error occurred', (done) => {
@@ -69,113 +61,104 @@ describe('IdentityGroupService', () => {
const searchSpy = spyOn(service, 'search').and.callThrough();
service.search('fake')
.subscribe(
() => {
fail('expected an error, not groups');
},
(error) => {
expect(searchSpy).toHaveBeenCalled();
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
service.search('fake').subscribe(
() => {
fail('expected an error, not groups');
},
(error) => {
expect(searchSpy).toHaveBeenCalled();
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should fetch groups by roles', (done) => {
requestSpy.and.returnValue(Promise.resolve(mockFoodGroups));
const searchSpy = spyOn(service, 'search').and.callThrough();
service.search('fake', mockSearchGroupByRoles).subscribe(
res => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
role: 'fake-role-1,fake-role-2'
});
done();
}
);
service.search('fake', mockSearchGroupByRoles).subscribe((res) => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
role: 'fake-role-1,fake-role-2'
});
done();
});
});
it('should not fetch groups by roles if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(mockHttpErrorResponse));
const searchSpy = spyOn(service, 'search').and.callThrough();
service.search('fake', mockSearchGroupByRoles)
.subscribe(
() => {
fail('expected an error, not groups');
},
(error) => {
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
role: 'fake-role-1,fake-role-2'
});
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
service.search('fake', mockSearchGroupByRoles).subscribe(
() => {
fail('expected an error, not groups');
},
(error) => {
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
role: 'fake-role-1,fake-role-2'
});
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should fetch groups within app', (done) => {
requestSpy.and.returnValue(Promise.resolve(mockFoodGroups));
service.search('fake', mockSearchGroupByApp).subscribe(
res => {
expect(res).toBeDefined();
expect(service.queryParams).toEqual({
search: 'fake',
application: 'fake-app-name'
});
done();
}
);
service.search('fake', mockSearchGroupByApp).subscribe((res) => {
expect(res).toBeDefined();
expect(service.queryParams).toEqual({
search: 'fake',
application: 'fake-app-name'
});
done();
});
});
it('should fetch groups within app with roles', (done) => {
requestSpy.and.returnValue(Promise.resolve(mockFoodGroups));
service.search('fake', mockSearchGroupByRolesAndApp).subscribe(
res => {
expect(res).toBeDefined();
expect(service.queryParams).toEqual({
search: 'fake',
application: 'fake-app-name',
role: 'fake-role-1,fake-role-2'
});
done();
}
);
service.search('fake', mockSearchGroupByRolesAndApp).subscribe((res) => {
expect(res).toBeDefined();
expect(service.queryParams).toEqual({
search: 'fake',
application: 'fake-app-name',
role: 'fake-role-1,fake-role-2'
});
done();
});
});
it('should not fetch groups within app if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(mockHttpErrorResponse));
const searchSpy = spyOn(service, 'search').and.callThrough();
service.search('fake', mockSearchGroupByApp)
.subscribe(
() => {
fail('expected an error, not groups');
},
(error) => {
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
application: 'fake-app-name'
});
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
service.search('fake', mockSearchGroupByApp).subscribe(
() => {
fail('expected an error, not groups');
},
(error) => {
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
application: 'fake-app-name'
});
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
});
});
@@ -22,7 +22,6 @@ import { ProcessServiceCloudTestingModule } from '../../testing/process-service-
import { PeopleCloudModule } from '../people-cloud.module';
import { DebugElement, SimpleChange } from '@angular/core';
import { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core';
import { of } from 'rxjs';
import { IdentityUserServiceInterface } from '../services/identity-user.service.interface';
import { IDENTITY_USER_SERVICE_TOKEN } from '../services/identity-user-service.token';
@@ -83,7 +82,7 @@ describe('PeopleCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), CoreTestingModule, ProcessServiceCloudTestingModule, PeopleCloudModule]
imports: [CoreTestingModule, ProcessServiceCloudTestingModule, PeopleCloudModule]
});
fixture = TestBed.createComponent(PeopleCloudComponent);
component = fixture.componentInstance;
@@ -32,7 +32,7 @@ import {
} from '@angular/core';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { switchMap, debounceTime, distinctUntilChanged, mergeMap, tap, filter, takeUntil } from 'rxjs/operators';
import { FullNamePipe, LogService } from '@alfresco/adf-core';
import { FullNamePipe } from '@alfresco/adf-core';
import { trigger, state, style, transition, animate } from '@angular/animations';
import { ComponentSelectionMode } from '../../types';
import { IdentityUserModel } from '../models/identity-user.model';
@@ -162,8 +162,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
constructor(
@Inject(IDENTITY_USER_SERVICE_TOKEN)
private identityUserService: IdentityUserServiceInterface,
private logService: LogService
private identityUserService: IdentityUserServiceInterface
) {}
ngOnInit(): void {
@@ -300,7 +299,6 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
}
} catch (error) {
this.invalidUsers.push(user);
this.logService.error(error);
}
}
@@ -16,7 +16,6 @@
*/
import { TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { IdentityUserService } from './identity-user.service';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import {
@@ -33,17 +32,13 @@ import { AdfHttpClient } from '@alfresco/adf-core/api';
import { mockHttpErrorResponse } from '../../group/mock/identity-group.service.mock';
describe('IdentityUserService', () => {
let service: IdentityUserService;
let adfHttpClient: AdfHttpClient;
let requestSpy: jasmine.Spy;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [ProcessServiceCloudTestingModule]
});
service = TestBed.inject(IdentityUserService);
adfHttpClient = TestBed.inject(AdfHttpClient);
@@ -51,21 +46,18 @@ describe('IdentityUserService', () => {
});
describe('Search', () => {
it('should fetch users', (done) => {
requestSpy.and.returnValue(Promise.resolve(mockFoodUsers));
const searchSpy = spyOn(service, 'search').and.callThrough();
service.search('fake').subscribe(
res => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake'
});
done();
}
);
service.search('fake').subscribe((res) => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake'
});
done();
});
});
it('should not fetch users if error occurred', (done) => {
@@ -73,190 +65,172 @@ describe('IdentityUserService', () => {
const searchSpy = spyOn(service, 'search').and.callThrough();
service.search('fake')
.subscribe(
() => {
fail('expected an error, not users');
},
(error) => {
expect(searchSpy).toHaveBeenCalled();
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
service.search('fake').subscribe(
() => {
fail('expected an error, not users');
},
(error) => {
expect(searchSpy).toHaveBeenCalled();
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should fetch users by roles', (done) => {
requestSpy.and.returnValue(Promise.resolve(mockFoodUsers));
const searchSpy = spyOn(service, 'search').and.callThrough();
service.search('fake', mockSearchUserByRoles).subscribe(
res => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
role: 'fake-role-1,fake-role-2'
});
done();
}
);
service.search('fake', mockSearchUserByRoles).subscribe((res) => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
role: 'fake-role-1,fake-role-2'
});
done();
});
});
it('should not fetch users by roles if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(mockHttpErrorResponse));
service.search('fake', mockSearchUserByRoles)
.subscribe(
() => {
fail('expected an error, not users');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
service.search('fake', mockSearchUserByRoles).subscribe(
() => {
fail('expected an error, not users');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should fetch users by groups', (done) => {
requestSpy.and.returnValue(Promise.resolve(mockFoodUsers));
const searchSpy = spyOn(service, 'search').and.callThrough();
service.search('fake', mockSearchUserByGroups).subscribe(
res => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
group: 'fake-group-1,fake-group-2'
});
done();
}
);
service.search('fake', mockSearchUserByGroups).subscribe((res) => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
group: 'fake-group-1,fake-group-2'
});
done();
});
});
it('should fetch users by roles with groups', (done) => {
requestSpy.and.returnValue(Promise.resolve(mockFoodUsers));
const searchSpy = spyOn(service, 'search').and.callThrough();
service.search('fake', mockSearchUserByGroupsAndRoles).subscribe(
res => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
role: 'fake-role-1,fake-role-2',
group: 'fake-group-1,fake-group-2'
});
done();
}
);
service.search('fake', mockSearchUserByGroupsAndRoles).subscribe((res) => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
role: 'fake-role-1,fake-role-2',
group: 'fake-group-1,fake-group-2'
});
done();
});
});
it('should fetch users by roles with groups and appName', (done) => {
requestSpy.and.returnValue(Promise.resolve(mockFoodUsers));
const searchSpy = spyOn(service, 'search').and.callThrough();
service.search('fake', mockSearchUserByGroupsAndRolesAndApp).subscribe(
res => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
role: 'fake-role-1,fake-role-2',
application: 'fake-app-name',
group: 'fake-group-1,fake-group-2'
});
done();
}
);
service.search('fake', mockSearchUserByGroupsAndRolesAndApp).subscribe((res) => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
role: 'fake-role-1,fake-role-2',
application: 'fake-app-name',
group: 'fake-group-1,fake-group-2'
});
done();
});
});
it('should not fetch users by groups if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(mockHttpErrorResponse));
service.search('fake', mockSearchUserByGroups)
.subscribe(
() => {
fail('expected an error, not users');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
service.search('fake', mockSearchUserByGroups).subscribe(
() => {
fail('expected an error, not users');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should fetch users within app', (done) => {
requestSpy.and.returnValue(Promise.resolve(mockFoodUsers));
service.search('fake', mockSearchUserByApp).subscribe(
res => {
expect(res).toBeDefined();
expect(service.queryParams).toEqual({
search: 'fake',
application: 'fake-app-name'
});
done();
}
);
service.search('fake', mockSearchUserByApp).subscribe((res) => {
expect(res).toBeDefined();
expect(service.queryParams).toEqual({
search: 'fake',
application: 'fake-app-name'
});
done();
});
});
it('should fetch users within app with roles', (done) => {
requestSpy.and.returnValue(Promise.resolve(mockFoodUsers));
service.search('fake', mockSearchUserByRolesAndApp).subscribe(
res => {
expect(res).toBeDefined();
expect(service.queryParams).toEqual({
search: 'fake',
application: 'fake-app-name',
role: 'fake-role-1,fake-role-2'
});
done();
}
);
service.search('fake', mockSearchUserByRolesAndApp).subscribe((res) => {
expect(res).toBeDefined();
expect(service.queryParams).toEqual({
search: 'fake',
application: 'fake-app-name',
role: 'fake-role-1,fake-role-2'
});
done();
});
});
it('should fetch users within app with groups', (done) => {
requestSpy.and.returnValue(Promise.resolve(mockFoodUsers));
const searchSpy = spyOn(service, 'search').and.callThrough();
service.search('fake', mockSearchUserByAppAndGroups).subscribe(
res => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
application: 'fake-app-name',
group: 'fake-group-1,fake-group-2'
});
done();
}
);
service.search('fake', mockSearchUserByAppAndGroups).subscribe((res) => {
expect(res).toBeDefined();
expect(searchSpy).toHaveBeenCalled();
expect(service.queryParams).toEqual({
search: 'fake',
application: 'fake-app-name',
group: 'fake-group-1,fake-group-2'
});
done();
});
});
it('should not fetch users within app if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(mockHttpErrorResponse));
service.search('fake', mockSearchUserByApp)
.subscribe(
() => {
fail('expected an error, not users');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
service.search('fake', mockSearchUserByApp).subscribe(
() => {
fail('expected an error, not users');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
});
});
@@ -16,13 +16,11 @@
*/
import { TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { ProcessNameCloudPipe } from './process-name-cloud.pipe';
import { LocalizedDatePipe, CoreTestingModule } from '@alfresco/adf-core';
import { ProcessInstanceCloud } from '../process/start-process/models/process-instance-cloud.model';
describe('ProcessNameCloudPipe', () => {
let processNamePipe: ProcessNameCloudPipe;
const defaultName = 'default-name';
const datetimeIdentifier = '%{datetime}';
@@ -36,10 +34,7 @@ describe('ProcessNameCloudPipe', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
CoreTestingModule
]
imports: [CoreTestingModule]
});
const localizedDatePipe = TestBed.inject(LocalizedDatePipe);
processNamePipe = new ProcessNameCloudPipe(localizedDatePipe);
@@ -71,5 +66,4 @@ describe('ProcessNameCloudPipe', () => {
const transformResult = processNamePipe.transform(nameWithProcessDefinitionIdentifier);
expect(transformResult).toEqual(`${defaultName} - `);
});
});
@@ -19,7 +19,6 @@ import { Component, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CancelProcessDirective } from './cancel-process.directive';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { ProcessInstanceCloud } from '../start-process/models/process-instance-cloud.model';
import { IdentityUserService } from '../../people/services/identity-user.service';
@@ -27,13 +26,11 @@ const processDetailsMockRunning: ProcessInstanceCloud = { initiator: 'usermock',
const processDetailsMockCompleted: ProcessInstanceCloud = { initiator: 'usermock', status: 'COMPLETED' };
describe('CancelProcessDirective', () => {
@Component({
selector: 'adf-cloud-cancel-process-test-component',
template: '<button adf-cloud-cancel-process></button>'
})
class TestComponent {
@ViewChild(CancelProcessDirective)
cancelProcessDirective: CancelProcessDirective;
}
@@ -44,18 +41,13 @@ describe('CancelProcessDirective', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
declarations: [
TestComponent
]
imports: [ProcessServiceCloudTestingModule],
declarations: [TestComponent]
});
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
identityUserService = TestBed.inject(IdentityUserService);
spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({username: 'usermock'});
spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({ username: 'usermock' });
fixture.detectChanges();
});
@@ -15,7 +15,6 @@
* limitations under the License.
*/
import { LogService } from '@alfresco/adf-core';
import { Injectable } from '@angular/core';
import { Observable, of, Subject, throwError } from 'rxjs';
import { ProcessInstanceCloud } from '../start-process/models/process-instance-cloud.model';
@@ -30,11 +29,8 @@ import { ProcessCloudInterface } from '../services/process-cloud.interface';
providedIn: 'root'
})
export class ProcessCloudServiceMock implements ProcessCloudInterface {
dataChangesDetected = new Subject<ProcessInstanceCloud>();
constructor(private logService: LogService) { }
getProcessInstanceById(appName: string, processInstanceId: string): Observable<ProcessInstanceCloud> {
if (appName === 'app-placeholders' && processInstanceId) {
return of(processInstancePlaceholdersCloudMock);
@@ -42,9 +38,7 @@ export class ProcessCloudServiceMock implements ProcessCloudInterface {
if (appName && processInstanceId) {
return of(processInstanceDetailsCloudMock);
} else {
this.logService.error('AppName and ProcessInstanceId are mandatory for querying a process');
return throwError('AppName/ProcessInstanceId not configured');
}
}
@@ -52,9 +46,7 @@ export class ProcessCloudServiceMock implements ProcessCloudInterface {
getProcessDefinitions(appName: string): Observable<ProcessDefinitionCloud[]> {
if (appName || appName === '') {
return of(fakeProcessDefinitions);
} else {
this.logService.error('AppName is mandatory for querying task');
return throwError('AppName not configured');
}
}
@@ -63,7 +55,6 @@ export class ProcessCloudServiceMock implements ProcessCloudInterface {
if (appName) {
return of(mockAppVersions);
} else {
this.logService.error('AppName is mandatory for querying the versions of an application');
return throwError('AppName not configured');
}
}
@@ -72,7 +63,6 @@ export class ProcessCloudServiceMock implements ProcessCloudInterface {
if (appName && processInstanceId) {
return of();
} else {
this.logService.error('App name and Process id are mandatory for deleting a process');
return throwError('App name and process id not configured');
}
}
@@ -34,7 +34,6 @@ import { AppsProcessCloudService } from '../../../app/services/apps-process-clou
import { fakeApplicationInstance, fakeApplicationInstanceWithEnvironment } from './../../../app/mock/app-model.mock';
import { PROCESS_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { LocalPreferenceCloudService } from '../../../services/local-preference-cloud.service';
import { TranslateModule } from '@ngx-translate/core';
import { ProcessCloudService } from '../../services/process-cloud.service';
import { DateCloudFilterType } from '../../../models/date-cloud-filter.model';
import { MatIconTestingModule } from '@angular/material/icon/testing';
@@ -84,7 +83,7 @@ describe('EditProcessFilterCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessFiltersCloudModule, ProcessServiceCloudTestingModule, MatIconTestingModule],
imports: [ProcessFiltersCloudModule, ProcessServiceCloudTestingModule, MatIconTestingModule],
providers: [MatDialog, { provide: PROCESS_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }]
});
fixture = TestBed.createComponent(EditProcessFilterCloudComponent);
@@ -20,7 +20,6 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { ProcessFilterDialogCloudComponent } from './process-filter-dialog-cloud.component';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { ProcessFiltersCloudModule } from '../process-filters-cloud.module';
import { TranslateModule } from '@ngx-translate/core';
describe('ProcessFilterDialogCloudComponent', () => {
let component: ProcessFilterDialogCloudComponent;
@@ -32,16 +31,12 @@ describe('ProcessFilterDialogCloudComponent', () => {
};
const mockDialogData = {
data: {name: 'Mock-Title'}
data: { name: 'Mock-Title' }
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule,
ProcessFiltersCloudModule
],
imports: [ProcessServiceCloudTestingModule, ProcessFiltersCloudModule],
providers: [
{ provide: MatDialogRef, useValue: mockDialogRef },
{ provide: MAT_DIALOG_DATA, useValue: mockDialogData }
@@ -62,20 +57,14 @@ describe('ProcessFilterDialogCloudComponent', () => {
it('should display title', () => {
fixture.detectChanges();
const titleElement = fixture.debugElement.nativeElement.querySelector(
'#adf-process-filter-dialog-title'
);
const titleElement = fixture.debugElement.nativeElement.querySelector('#adf-process-filter-dialog-title');
expect(titleElement.textContent).toEqual(' ADF_CLOUD_EDIT_PROCESS_FILTER.DIALOG.TITLE ');
});
it('should enable save button if form is valid', async () => {
fixture.detectChanges();
const saveButton = fixture.debugElement.nativeElement.querySelector(
'#adf-save-button-id'
);
const inputElement = fixture.debugElement.nativeElement.querySelector(
'#adf-filter-name-id'
);
const saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-button-id');
const inputElement = fixture.debugElement.nativeElement.querySelector('#adf-filter-name-id');
inputElement.value = 'My custom Name';
inputElement.dispatchEvent(new Event('input'));
@@ -88,36 +77,28 @@ describe('ProcessFilterDialogCloudComponent', () => {
it('should disable save button if form is not valid', async () => {
fixture.detectChanges();
const inputElement = fixture.debugElement.nativeElement.querySelector(
'#adf-filter-name-id'
);
const inputElement = fixture.debugElement.nativeElement.querySelector('#adf-filter-name-id');
inputElement.value = '';
inputElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
await fixture.whenStable();
const saveButton = fixture.debugElement.nativeElement.querySelector(
'#adf-save-button-id'
);
const saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-button-id');
expect(saveButton).toBeDefined();
expect(saveButton.disabled).toBe(true);
});
it('should able to close dialog on click of save button if form is valid', async () => {
fixture.detectChanges();
const inputElement = fixture.debugElement.nativeElement.querySelector(
'#adf-filter-name-id'
);
const inputElement = fixture.debugElement.nativeElement.querySelector('#adf-filter-name-id');
inputElement.value = 'My custom Name';
inputElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
await fixture.whenStable();
const saveButton = fixture.debugElement.nativeElement.querySelector(
'#adf-save-button-id'
);
const saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-button-id');
expect(saveButton).toBeDefined();
expect(saveButton.disabled).toBeFalsy();
@@ -127,9 +108,7 @@ describe('ProcessFilterDialogCloudComponent', () => {
it('should able close dialog on click of cancel button', () => {
component.data = { data: { name: '' } };
const cancelButton = fixture.debugElement.nativeElement.querySelector(
'#adf-cancel-button-id'
);
const cancelButton = fixture.debugElement.nativeElement.querySelector('#adf-cancel-button-id');
fixture.detectChanges();
cancelButton.click();
expect(cancelButton).toBeDefined();
@@ -25,7 +25,6 @@ import { ProcessServiceCloudTestingModule } from '../../../testing/process-servi
import { ProcessFiltersCloudModule } from '../process-filters-cloud.module';
import { PROCESS_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { LocalPreferenceCloudService } from '../../../services/local-preference-cloud.service';
import { TranslateModule } from '@ngx-translate/core';
import { mockProcessFilters } from '../mock/process-filters-cloud.mock';
describe('ProcessFiltersCloudComponent', () => {
@@ -36,14 +35,8 @@ describe('ProcessFiltersCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule,
ProcessFiltersCloudModule
],
providers: [
{ provide: PROCESS_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }
]
imports: [ProcessServiceCloudTestingModule, ProcessFiltersCloudModule],
providers: [{ provide: PROCESS_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }]
});
fixture = TestBed.createComponent(ProcessFiltersCloudComponent);
component = fixture.componentInstance;
@@ -58,7 +51,7 @@ describe('ProcessFiltersCloudComponent', () => {
it('should attach specific icon for each filter if hasIcon is true', async () => {
const change = new SimpleChange(undefined, 'my-app-1', true);
component.ngOnChanges({appName: change});
component.ngOnChanges({ appName: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -90,7 +83,7 @@ describe('ProcessFiltersCloudComponent', () => {
it('should display the filters', async () => {
const change = new SimpleChange(undefined, 'my-app-1', true);
component.ngOnChanges({appName: change});
component.ngOnChanges({ appName: change });
fixture.detectChanges();
await fixture.whenStable();
@@ -115,9 +108,9 @@ describe('ProcessFiltersCloudComponent', () => {
const change = new SimpleChange(null, appName, true);
let lastValue: any;
component.error.subscribe((err) => lastValue = err);
component.error.subscribe((err) => (lastValue = err));
component.ngOnChanges({appName: change});
component.ngOnChanges({ appName: change });
fixture.detectChanges();
expect(lastValue).toBeDefined();
});
@@ -168,7 +161,7 @@ describe('ProcessFiltersCloudComponent', () => {
expect(component.currentFilter).toEqual(mockProcessFilters[1]);
expect(filterSelectedSpy).toHaveBeenCalledWith(mockProcessFilters[1]);
});
});
it('should select the filter based on the input by key param', async () => {
const filterSelectedSpy = spyOn(component.filterSelected, 'emit');
@@ -180,7 +173,7 @@ describe('ProcessFiltersCloudComponent', () => {
expect(component.currentFilter).toEqual(mockProcessFilters[2]);
expect(filterSelectedSpy).toHaveBeenCalledWith(mockProcessFilters[2]);
});
});
it('should select the filter based on the input by index param', async () => {
const filterSelectedSpy = spyOn(component.filterSelected, 'emit');
@@ -192,7 +185,7 @@ describe('ProcessFiltersCloudComponent', () => {
expect(component.currentFilter).toEqual(mockProcessFilters[2]);
expect(filterSelectedSpy).toHaveBeenCalledWith(mockProcessFilters[2]);
});
});
it('should select the filter based on the input by id param', async () => {
const filterSelectedSpy = spyOn(component.filterSelected, 'emit');
@@ -285,7 +278,6 @@ describe('ProcessFiltersCloudComponent', () => {
});
describe('Highlight Selected Filter', () => {
const allProcessesFilterKey = mockProcessFilters[0].key;
const runningProcessesFilterKey = mockProcessFilters[1].key;
const completedProcessesFilterKey = mockProcessFilters[2].key;
@@ -21,8 +21,13 @@ import { ProcessFilterCloudService } from './process-filter-cloud.service';
import { PROCESS_FILTERS_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { LocalPreferenceCloudService } from '../../../services/local-preference-cloud.service';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { fakeEmptyProcessCloudFilterEntries, fakeProcessCloudFilterEntries, fakeProcessCloudFilters, fakeProcessCloudFilterWithDifferentEntries, fakeProcessFilter } from '../mock/process-filters-cloud.mock';
import {
fakeEmptyProcessCloudFilterEntries,
fakeProcessCloudFilterEntries,
fakeProcessCloudFilters,
fakeProcessCloudFilterWithDifferentEntries,
fakeProcessFilter
} from '../mock/process-filters-cloud.mock';
import { ProcessFilterCloudModel } from '../models/process-filter-cloud.model';
import { IdentityUserService } from '../../../people/services/identity-user.service';
@@ -43,13 +48,8 @@ describe('ProcessFilterCloudService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
providers: [
{ provide: PROCESS_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }
]
imports: [ProcessServiceCloudTestingModule],
providers: [{ provide: PROCESS_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }]
});
service = TestBed.inject(ProcessFilterCloudService);
@@ -23,7 +23,6 @@ import { ProcessServiceCloudTestingModule } from '../../../testing/process-servi
import { ProcessHeaderCloudComponent } from './process-header-cloud.component';
import { ProcessHeaderCloudModule } from '../process-header-cloud.module';
import { ProcessCloudService } from '../../services/process-cloud.service';
import { TranslateModule } from '@ngx-translate/core';
import { processInstanceDetailsCloudMock } from '../../mock/process-instance-details-cloud.mock';
describe('ProcessHeaderCloudComponent', () => {
@@ -34,11 +33,7 @@ describe('ProcessHeaderCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule,
ProcessHeaderCloudModule
]
imports: [ProcessServiceCloudTestingModule, ProcessHeaderCloudModule]
});
fixture = TestBed.createComponent(ProcessHeaderCloudComponent);
component = fixture.componentInstance;
@@ -174,7 +169,6 @@ describe('ProcessHeaderCloudComponent', () => {
});
describe('Config Filtering', () => {
it('should show only the properties from the configuration file', async () => {
spyOn(appConfigService, 'get').and.returnValue(['name', 'status']);
component.ngOnChanges();
@@ -207,7 +201,6 @@ describe('ProcessHeaderCloudComponent', () => {
});
describe('Date values format', () => {
beforeEach(() => {
appConfigService.config = {
'adf-cloud-process-header': {
@@ -35,13 +35,10 @@ import { fakeCustomSchema, fakeProcessCloudList, processListSchemaMock } from '.
import { of } from 'rxjs';
import { shareReplay, skip } from 'rxjs/operators';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { ProcessListCloudPreferences } from '../models/process-cloud-preferences';
import { PROCESS_LIST_CUSTOM_VARIABLE_COLUMN } from '../../../models/data-column-custom-data';
import { HttpClientModule } from '@angular/common/http';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { PreferenceCloudServiceInterface } from '@alfresco/adf-process-services-cloud';
import { HarnessLoader } from '@angular/cdk/testing';
@@ -82,7 +79,7 @@ describe('ProcessListCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule]
imports: [ProcessServiceCloudTestingModule]
});
appConfig = TestBed.inject(AppConfigService);
processListCloudService = TestBed.inject(ProcessListCloudService);
@@ -594,7 +591,7 @@ describe('ProcessListCloudComponent: Injecting custom columns for task list - Cu
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
imports: [ProcessServiceCloudTestingModule],
declarations: [CustomTaskListComponent]
});
fixtureCustom = TestBed.createComponent(CustomTaskListComponent);
@@ -639,7 +636,7 @@ describe('ProcessListCloudComponent: Creating an empty custom template - EmptyTe
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), HttpClientModule, NoopAnimationsModule, DataTableModule, MatProgressSpinnerModule],
imports: [ProcessServiceCloudTestingModule, DataTableModule, MatProgressSpinnerModule],
providers: [{ provide: PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN, useValue: preferencesService }],
declarations: [EmptyTemplateComponent, ProcessListCloudComponent, CustomEmptyContentTemplateDirective]
});
@@ -49,7 +49,6 @@ export class ProcessListCloudService extends BaseCloudService {
})
);
} else {
this.logService.error('Appname is mandatory for querying task');
return throwError('Appname not configured');
}
}
@@ -107,7 +106,11 @@ export class ProcessListCloudService extends BaseCloudService {
const queryParam = {};
for (const property in requestNode) {
if (Object.prototype.hasOwnProperty.call(requestNode, property) && !this.isExcludedField(property) && this.isPropertyValueValid(requestNode, property)) {
if (
Object.prototype.hasOwnProperty.call(requestNode, property) &&
!this.isExcludedField(property) &&
this.isPropertyValueValid(requestNode, property)
) {
queryParam[property] = this.getQueryParamValueFromRequestNode(requestNode, property as keyof ProcessQueryCloudRequestModel);
}
}
@@ -52,7 +52,6 @@ export class ProcessTaskListCloudService extends BaseCloudService implements Tas
})
);
} else {
this.logService.error('Appname is mandatory for querying task');
return throwError('Appname not configured');
}
}
@@ -60,7 +59,11 @@ export class ProcessTaskListCloudService extends BaseCloudService implements Tas
protected buildQueryParams(requestNode: TaskQueryCloudRequestModel): any {
const queryParam: any = {};
for (const property in requestNode) {
if (Object.prototype.hasOwnProperty.call(requestNode, property) && !this.isExcludedField(property) && this.isPropertyValueValid(requestNode, property)) {
if (
Object.prototype.hasOwnProperty.call(requestNode, property) &&
!this.isExcludedField(property) &&
this.isPropertyValueValid(requestNode, property)
) {
queryParam[property] = requestNode[property];
}
}
@@ -17,7 +17,7 @@
import { Injectable } from '@angular/core';
import { Observable, Subject, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { map } from 'rxjs/operators';
import { ProcessInstanceCloud } from '../start-process/models/process-instance-cloud.model';
import { BaseCloudService } from '../../services/base-cloud.service';
import { ProcessDefinitionCloud } from '../../models/process-definition-cloud.model';
@@ -48,7 +48,6 @@ export class ProcessCloudService extends BaseCloudService implements ProcessClou
})
);
} else {
this.logService.error('AppName and ProcessInstanceId are mandatory for querying a process');
return throwError('AppName/ProcessInstanceId not configured');
}
}
@@ -63,11 +62,8 @@ export class ProcessCloudService extends BaseCloudService implements ProcessClou
if (appName || appName === '') {
const url = `${this.getBasePath(appName)}/rb/v1/process-definitions`;
return this.get(url).pipe(
map((res: any) => res.list.entries.map((processDefs) => new ProcessDefinitionCloud(processDefs.entry)))
);
return this.get(url).pipe(map((res: any) => res.list.entries.map((processDefs) => new ProcessDefinitionCloud(processDefs.entry))));
} else {
this.logService.error('AppName is mandatory for querying task');
return throwError('AppName not configured');
}
}
@@ -82,12 +78,8 @@ export class ProcessCloudService extends BaseCloudService implements ProcessClou
if (appName) {
const url = `${this.getBasePath(appName)}/query/v1/applications`;
return this.get<any>(url).pipe(
map((appEntities: ApplicationVersionResponseModel) => appEntities.list.entries),
catchError((err) => this.handleError(err))
);
return this.get(url).pipe(map((appEntities: ApplicationVersionResponseModel) => appEntities.list.entries));
} else {
this.logService.error('AppName is mandatory for querying the versions of an application');
return throwError('AppName not configured');
}
}
@@ -104,18 +96,12 @@ export class ProcessCloudService extends BaseCloudService implements ProcessClou
const queryUrl = `${this.getBasePath(appName)}/rb/v1/process-instances/${processInstanceId}`;
return this.delete(queryUrl).pipe(
map((res: any) => {
this.dataChangesDetected.next(res.entry);
return res.entry;
this.dataChangesDetected.next(res.entry);
return res.entry;
})
);
} else {
this.logService.error('App name and Process id are mandatory for deleting a process');
return throwError('App name and process id not configured');
}
}
private handleError(error?: any) {
this.logService.error(error);
return throwError(error || 'Server error');
}
}
@@ -43,7 +43,6 @@ import {
import { By } from '@angular/platform-browser';
import { ProcessPayloadCloud } from '../models/process-payload-cloud.model';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { ProcessNameCloudPipe } from '../../../pipes/process-name-cloud.pipe';
import { ProcessInstanceCloud } from '../models/process-instance-cloud.model';
import { ESCAPE } from '@angular/cdk/keycodes';
@@ -84,7 +83,6 @@ describe('StartProcessCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule,
FormsModule,
MatCommonModule,
@@ -47,7 +47,6 @@ export class StartProcessCloudService extends BaseCloudService {
map((res: any) => res.list.entries.map((processDefs) => new ProcessDefinitionCloud(processDefs.entry)))
);
} else {
this.logService.error('AppName is mandatory for querying task');
return throwError('AppName not configured');
}
}
@@ -63,9 +62,7 @@ export class StartProcessCloudService extends BaseCloudService {
const url = `${this.getBasePath(appName)}/rb/v1/process-instances`;
payload.payloadType = 'StartProcessPayload';
return this.post(url, payload).pipe(
map((result: any) => result.entry)
);
return this.post(url, payload).pipe(map((result: any) => result.entry));
}
/**
@@ -80,9 +77,7 @@ export class StartProcessCloudService extends BaseCloudService {
const url = `${this.getBasePath(appName)}/rb/v1/process-instances/${processInstanceId}`;
payload.payloadType = 'UpdateProcessPayload';
return this.put(url, payload).pipe(
map((processInstance: any) => processInstance.entry)
);
return this.put(url, payload).pipe(map((processInstance: any) => processInstance.entry));
}
/**
@@ -111,7 +106,7 @@ export class StartProcessCloudService extends BaseCloudService {
map((res: { [key: string]: any }) => {
const result = [];
if (res) {
Object.keys(res).forEach(mapping => result.push(new TaskVariableCloud({ name: mapping, value: res[mapping] })));
Object.keys(res).forEach((mapping) => result.push(new TaskVariableCloud({ name: mapping, value: res[mapping] })));
}
return result;
})
@@ -15,19 +15,16 @@
* limitations under the License.
*/
import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core';
import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core';
import { Injectable, inject } from '@angular/core';
import { from, Observable } from 'rxjs';
import { AdfHttpClient } from '@alfresco/adf-core/api';
import { RequestOptions } from '@alfresco/js-api';
@Injectable()
export class BaseCloudService {
protected apiService = inject(AlfrescoApiService);
protected appConfigService = inject(AppConfigService);
protected logService = inject(LogService);
protected defaultParams: RequestOptions = {
path: '',
@@ -36,76 +33,58 @@ export class BaseCloudService {
accepts: ['application/json']
};
constructor(
protected adfHttpClient: AdfHttpClient) {}
constructor(protected adfHttpClient: AdfHttpClient) {}
getBasePath(appName: string): string {
return appName
? `${this.contextRoot}/${appName}`
: this.contextRoot;
return appName ? `${this.contextRoot}/${appName}` : this.contextRoot;
}
protected post<T, R>(url: string, data?: T, queryParams?: any): Observable<R> {
return from(
this.callApi<R>(
url,
{
...this.defaultParams,
path: url,
httpMethod: 'POST',
bodyParam: data,
queryParams
}
)
this.callApi<R>(url, {
...this.defaultParams,
path: url,
httpMethod: 'POST',
bodyParam: data,
queryParams
})
);
}
protected put<T, R>(url: string, data?: T): Observable<R> {
return from(
this.callApi<R>(
url,
{
...this.defaultParams,
path: url,
httpMethod: 'PUT',
bodyParam: data
}
)
this.callApi<R>(url, {
...this.defaultParams,
path: url,
httpMethod: 'PUT',
bodyParam: data
})
);
}
protected delete(url: string): Observable<void> {
return from(
this.callApi<void>(
url,
{
...this.defaultParams,
path: url,
httpMethod: 'DELETE'
}
)
this.callApi<void>(url, {
...this.defaultParams,
path: url,
httpMethod: 'DELETE'
})
);
}
protected get<T>(url: string, queryParams?: any): Observable<T> {
return from(
this.callApi<T>(
url,
{
...this.defaultParams,
path: url,
httpMethod: 'GET',
queryParams
}
)
this.callApi<T>(url, {
...this.defaultParams,
path: url,
httpMethod: 'GET',
queryParams
})
);
}
protected callApi<T>(url: string, params: RequestOptions): Promise<T> {
return this.adfHttpClient.request(
url,
params
);
return this.adfHttpClient.request(url, params);
}
protected get contextRoot() {
@@ -17,7 +17,6 @@
import { TestBed } from '@angular/core/testing';
import { ProcessServiceCloudTestingModule } from '../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { NotificationCloudService } from './notification-cloud.service';
import { Apollo } from 'apollo-angular';
@@ -44,10 +43,7 @@ describe('NotificationCloudService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [ProcessServiceCloudTestingModule]
});
service = TestBed.inject(NotificationCloudService);
apollo = TestBed.inject(Apollo);
@@ -19,164 +19,156 @@ import { TestBed } from '@angular/core/testing';
import { UserPreferenceCloudService } from './user-preference-cloud.service';
import { mockPreferences, getMockPreference, createMockPreference, updateMockPreference } from '../mock/user-preference.mock';
import { ProcessServiceCloudTestingModule } from '../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { AdfHttpClient } from '@alfresco/adf-core/api';
describe('PreferenceService', () => {
let service: UserPreferenceCloudService;
let adfHttpClient: AdfHttpClient;
let requestSpy: jasmine.Spy;
let service: UserPreferenceCloudService;
let adfHttpClient: AdfHttpClient;
let requestSpy: jasmine.Spy;
const errorResponse = {
error: 'Mock Error',
state: 404, stateText: 'Not Found'
};
const errorResponse = {
error: 'Mock Error',
state: 404,
stateText: 'Not Found'
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
});
service = TestBed.inject(UserPreferenceCloudService);
adfHttpClient = TestBed.inject(AdfHttpClient);
requestSpy = spyOn(adfHttpClient, 'request').and.returnValue(Promise.resolve(mockPreferences));
});
it('should return the preferences', (done) => {
service.getPreferences('mock-app-name').subscribe((res: any) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.list.entries.length).toBe(3);
expect(res.list.entries[0].entry.key).toBe('mock-preference-key-1');
expect(res.list.entries[0].entry.value.length).toBe(2);
expect(res.list.entries[0].entry.value[0].username).toBe('mock-username-1');
expect(res.list.entries[0].entry.value[0].firstName).toBe('mock-firstname-1');
expect(res.list.entries[1].entry.key).toBe('mock-preference-key-2');
expect(res.list.entries[1].entry.value).toBe('my mock preference value');
expect(res.list.entries[2].entry.key).toBe('mock-preference-key-3');
expect(res.list.entries[2].entry.value.appName).toBe('mock-appName');
expect(res.list.entries[2].entry.value.state).toBe('MOCK-COMPLETED');
done();
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule]
});
service = TestBed.inject(UserPreferenceCloudService);
adfHttpClient = TestBed.inject(AdfHttpClient);
requestSpy = spyOn(adfHttpClient, 'request').and.returnValue(Promise.resolve(mockPreferences));
});
});
it('Should not fetch preferences if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(errorResponse));
service.getPreferences('mock-app-name')
.subscribe(
() => fail('expected an error, not preferences'),
(error) => {
expect(error.state).toEqual(404);
expect(error.stateText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should return the preferences', (done) => {
service.getPreferences('mock-app-name').subscribe((res: any) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.list.entries.length).toBe(3);
expect(res.list.entries[0].entry.key).toBe('mock-preference-key-1');
expect(res.list.entries[0].entry.value.length).toBe(2);
expect(res.list.entries[0].entry.value[0].username).toBe('mock-username-1');
expect(res.list.entries[0].entry.value[0].firstName).toBe('mock-firstname-1');
it('should return the preference by key', (done) => {
requestSpy.and.returnValue(Promise.resolve(getMockPreference));
service.getPreferenceByKey('mock-app-name', 'mock-preference-key').subscribe((res: any) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(2);
expect(res[0].appName).toBe('mock-appName');
expect(res[0].firstName).toBe('mock-firstname-1');
expect(res[1].appName).toBe('mock-appName');
expect(res[1].username).toBe('mock-username-2');
done();
expect(res.list.entries[1].entry.key).toBe('mock-preference-key-2');
expect(res.list.entries[1].entry.value).toBe('my mock preference value');
expect(res.list.entries[2].entry.key).toBe('mock-preference-key-3');
expect(res.list.entries[2].entry.value.appName).toBe('mock-appName');
expect(res.list.entries[2].entry.value.state).toBe('MOCK-COMPLETED');
done();
});
});
});
it('Should not fetch preference by key if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(errorResponse));
service.getPreferenceByKey('mock-app-name', 'mock-preference-key')
.subscribe(
() => fail('expected an error, not preference'),
(error) => {
expect(error.state).toEqual(404);
expect(error.stateText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should create preference', (done) => {
requestSpy.and.returnValue(Promise.resolve(createMockPreference));
service.createPreference('mock-app-name', 'mock-preference-key', createMockPreference).subscribe((res: any) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res).toBe(createMockPreference);
expect(res.appName).toBe('mock-appName');
expect(res.name).toBe('create-preference');
done();
it('Should not fetch preferences if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(errorResponse));
service.getPreferences('mock-app-name').subscribe(
() => fail('expected an error, not preferences'),
(error) => {
expect(error.state).toEqual(404);
expect(error.stateText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
});
it('Should not create preference if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(errorResponse));
service.createPreference('mock-app-name', 'mock-preference-key', createMockPreference)
.subscribe(
() => fail('expected an error, not to create preference'),
(error) => {
expect(error.state).toEqual(404);
expect(error.stateText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should update preference', (done) => {
requestSpy.and.returnValue(Promise.resolve(updateMockPreference));
service.updatePreference('mock-app-name', 'mock-preference-key', updateMockPreference).subscribe((res: any) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res).toBe(updateMockPreference);
expect(res.appName).toBe('mock-appName');
expect(res.name).toBe('update-preference');
done();
it('should return the preference by key', (done) => {
requestSpy.and.returnValue(Promise.resolve(getMockPreference));
service.getPreferenceByKey('mock-app-name', 'mock-preference-key').subscribe((res: any) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.length).toBe(2);
expect(res[0].appName).toBe('mock-appName');
expect(res[0].firstName).toBe('mock-firstname-1');
expect(res[1].appName).toBe('mock-appName');
expect(res[1].username).toBe('mock-username-2');
done();
});
});
});
it('Should not update preference if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(errorResponse));
service.createPreference('mock-app-name', 'mock-preference-key', updateMockPreference)
.subscribe(
() => fail('expected an error, not to update preference'),
(error) => {
expect(error.state).toEqual(404);
expect(error.stateText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should delete preference', (done) => {
requestSpy.and.returnValue(Promise.resolve(''));
service.deletePreference('mock-app-name', 'mock-preference-key').subscribe((res: any) => {
expect(res).toBeDefined();
done();
it('Should not fetch preference by key if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(errorResponse));
service.getPreferenceByKey('mock-app-name', 'mock-preference-key').subscribe(
() => fail('expected an error, not preference'),
(error) => {
expect(error.state).toEqual(404);
expect(error.stateText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
});
it('Should not delete preference if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(errorResponse));
service.deletePreference('mock-app-name', 'mock-preference-key')
.subscribe(
() => fail('expected an error, not to delete preference'),
(error) => {
expect(error.state).toEqual(404);
expect(error.stateText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should create preference', (done) => {
requestSpy.and.returnValue(Promise.resolve(createMockPreference));
service.createPreference('mock-app-name', 'mock-preference-key', createMockPreference).subscribe((res: any) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res).toBe(createMockPreference);
expect(res.appName).toBe('mock-appName');
expect(res.name).toBe('create-preference');
done();
});
});
it('Should not create preference if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(errorResponse));
service.createPreference('mock-app-name', 'mock-preference-key', createMockPreference).subscribe(
() => fail('expected an error, not to create preference'),
(error) => {
expect(error.state).toEqual(404);
expect(error.stateText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should update preference', (done) => {
requestSpy.and.returnValue(Promise.resolve(updateMockPreference));
service.updatePreference('mock-app-name', 'mock-preference-key', updateMockPreference).subscribe((res: any) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res).toBe(updateMockPreference);
expect(res.appName).toBe('mock-appName');
expect(res.name).toBe('update-preference');
done();
});
});
it('Should not update preference if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(errorResponse));
service.createPreference('mock-app-name', 'mock-preference-key', updateMockPreference).subscribe(
() => fail('expected an error, not to update preference'),
(error) => {
expect(error.state).toEqual(404);
expect(error.stateText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
it('should delete preference', (done) => {
requestSpy.and.returnValue(Promise.resolve(''));
service.deletePreference('mock-app-name', 'mock-preference-key').subscribe((res: any) => {
expect(res).toBeDefined();
done();
});
});
it('Should not delete preference if error occurred', (done) => {
requestSpy.and.returnValue(Promise.reject(errorResponse));
service.deletePreference('mock-app-name', 'mock-preference-key').subscribe(
() => fail('expected an error, not to delete preference'),
(error) => {
expect(error.state).toEqual(404);
expect(error.stateText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
done();
}
);
});
});
@@ -22,85 +22,81 @@ import { BaseCloudService } from './base-cloud.service';
@Injectable({ providedIn: 'root' })
export class UserPreferenceCloudService extends BaseCloudService implements PreferenceCloudServiceInterface {
/**
* Gets user preferences
*
* @param appName Name of the target app
* @returns List of user preferences
*/
getPreferences(appName: string): Observable<any> {
if (appName) {
const url = `${this.getBasePath(appName)}/preference/v1/preferences`;
return this.get(url);
} else {
this.logService.error('Appname is mandatory for querying preferences');
return throwError('Appname not configured');
/**
* Gets user preferences
*
* @param appName Name of the target app
* @returns List of user preferences
*/
getPreferences(appName: string): Observable<any> {
if (appName) {
const url = `${this.getBasePath(appName)}/preference/v1/preferences`;
return this.get(url);
} else {
return throwError('Appname not configured');
}
}
}
/**
* Gets user preference.
*
* @param appName Name of the target app
* @param key Key of the target preference
* @returns Observable of user preference
*/
getPreferenceByKey(appName: string, key: string): Observable<any> {
if (appName) {
const url = `${this.getBasePath(appName)}/preference/v1/preferences/${key}`;
return this.get(url);
} else {
this.logService.error('Appname and key are mandatory for querying preference');
return throwError('Appname not configured');
/**
* Gets user preference.
*
* @param appName Name of the target app
* @param key Key of the target preference
* @returns Observable of user preference
*/
getPreferenceByKey(appName: string, key: string): Observable<any> {
if (appName) {
const url = `${this.getBasePath(appName)}/preference/v1/preferences/${key}`;
return this.get(url);
} else {
return throwError('Appname not configured');
}
}
}
/**
* Creates user preference.
*
* @param appName Name of the target app
* @param key Key of the target preference
* @param newPreference Details of new user preference
* @returns Observable of created user preferences
*/
createPreference(appName: string, key: string, newPreference: any): Observable<any> {
if (appName) {
const url = `${this.getBasePath(appName)}/preference/v1/preferences/${key}`;
const payload = JSON.stringify(newPreference);
/**
* Creates user preference.
*
* @param appName Name of the target app
* @param key Key of the target preference
* @param newPreference Details of new user preference
* @returns Observable of created user preferences
*/
createPreference(appName: string, key: string, newPreference: any): Observable<any> {
if (appName) {
const url = `${this.getBasePath(appName)}/preference/v1/preferences/${key}`;
const payload = JSON.stringify(newPreference);
return this.put(url, payload);
} else {
this.logService.error('Appname and key are mandatory for creating preference');
return throwError('Appname not configured');
return this.put(url, payload);
} else {
return throwError('Appname not configured');
}
}
}
/**
* Updates user preference.
*
* @param appName Name of the target app
* @param key Key of the target preference
* @param updatedPreference Details of updated preference
* @returns Observable of updated user preferences
*/
updatePreference(appName: string, key: string, updatedPreference: any): Observable<any> {
return this.createPreference(appName, key, updatedPreference);
}
/**
* Updates user preference.
*
* @param appName Name of the target app
* @param key Key of the target preference
* @param updatedPreference Details of updated preference
* @returns Observable of updated user preferences
*/
updatePreference(appName: string, key: string, updatedPreference: any): Observable<any> {
return this.createPreference(appName, key, updatedPreference);
}
/**
* Deletes user preference by given preference key.
*
* @param appName Name of the target app
* @param key Key of the target preference
* @returns Observable of delete operation status
*/
deletePreference(appName: string, key: string): Observable<any> {
if (appName) {
const url = `${this.getBasePath(appName)}/preference/v1/preferences/${key}`;
return this.delete(url);
} else {
this.logService.error('Appname and key are mandatory to delete preference');
return throwError('Appname not configured');
/**
* Deletes user preference by given preference key.
*
* @param appName Name of the target app
* @param key Key of the target preference
* @returns Observable of delete operation status
*/
deletePreference(appName: string, key: string): Observable<any> {
if (appName) {
const url = `${this.getBasePath(appName)}/preference/v1/preferences/${key}`;
return this.delete(url);
} else {
return throwError('Appname not configured');
}
}
}
}
@@ -22,17 +22,14 @@ import { of, throwError } from 'rxjs';
import { ClaimTaskCloudDirective } from './claim-task-cloud.directive';
import { taskClaimCloudMock } from '../task-header/mocks/fake-claim-task.mock';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { By } from '@angular/platform-browser';
describe('ClaimTaskCloudDirective', () => {
@Component({
selector: 'adf-cloud-claim-test-component',
selector: 'adf-cloud-claim-test-component',
template: '<button adf-cloud-claim-task [taskId]="taskMock" [appName]="appNameMock" (error)="onError($event)"></button>'
})
class TestComponent {
taskMock = 'test1234';
appNameMock = 'simple-app';
@@ -49,13 +46,8 @@ describe('ClaimTaskCloudDirective', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
declarations: [
TestComponent
]
imports: [ProcessServiceCloudTestingModule],
declarations: [TestComponent]
});
taskCloudService = TestBed.inject(TaskCloudService);
fixture = TestBed.createComponent(TestComponent);
@@ -101,13 +93,11 @@ describe('ClaimTaskCloudDirective', () => {
});
describe('Claim Task Directive validation errors', () => {
@Component({
selector: 'adf-cloud-claim-no-fields-validation-component',
selector: 'adf-cloud-claim-no-fields-validation-component',
template: '<button adf-cloud-claim-task></button>'
})
class ClaimTestMissingInputDirectiveComponent {
appName = 'simple-app';
appNameUndefined = undefined;
appNameNull = null;
@@ -117,11 +107,10 @@ describe('Claim Task Directive validation errors', () => {
}
@Component({
selector: 'adf-cloud-claim-no-taskid-validation-component',
selector: 'adf-cloud-claim-no-taskid-validation-component',
template: '<button adf-cloud-claim-task [appName]="appName"></button>'
})
class ClaimTestMissingTaskIdDirectiveComponent {
appName = 'simple-app';
@ContentChildren(ClaimTaskCloudDirective)
@@ -129,11 +118,10 @@ describe('Claim Task Directive validation errors', () => {
}
@Component({
selector: 'adf-cloud-claim-undefined-appname-component',
selector: 'adf-cloud-claim-undefined-appname-component',
template: '<button adf-cloud-claim-task [taskId]="taskMock" [appName]="appNameUndefined"></button>'
})
class ClaimTestInvalidAppNameUndefinedDirectiveComponent {
appNameUndefined = undefined;
taskMock = 'test1234';
@@ -142,11 +130,10 @@ describe('Claim Task Directive validation errors', () => {
}
@Component({
selector: 'adf-cloud-claim-null-appname-component',
selector: 'adf-cloud-claim-null-appname-component',
template: '<button adf-cloud-claim-task [taskId]="taskMock" [appName]="appNameNull"></button>'
})
class ClaimTestInvalidAppNameNullDirectiveComponent {
appNameNull = null;
taskMock = 'test1234';
@@ -158,10 +145,7 @@ describe('Claim Task Directive validation errors', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
imports: [ProcessServiceCloudTestingModule],
declarations: [
ClaimTestMissingTaskIdDirectiveComponent,
ClaimTestInvalidAppNameUndefinedDirectiveComponent,
@@ -179,16 +163,16 @@ describe('Claim Task Directive validation errors', () => {
it('should throw error when taskId is not set', () => {
fixture = TestBed.createComponent(ClaimTestMissingTaskIdDirectiveComponent);
expect( () => fixture.detectChanges()).toThrowError('Attribute taskId is required');
expect(() => fixture.detectChanges()).toThrowError('Attribute taskId is required');
});
it('should throw error when appName is undefined', () => {
fixture = TestBed.createComponent(ClaimTestInvalidAppNameUndefinedDirectiveComponent);
expect( () => fixture.detectChanges()).toThrowError('Attribute appName is required');
expect(() => fixture.detectChanges()).toThrowError('Attribute appName is required');
});
it('should throw error when appName is null', () => {
fixture = TestBed.createComponent(ClaimTestInvalidAppNameUndefinedDirectiveComponent);
expect( () => fixture.detectChanges()).toThrowError('Attribute appName is required');
expect(() => fixture.detectChanges()).toThrowError('Attribute appName is required');
});
});
@@ -22,17 +22,20 @@ import { of, throwError } from 'rxjs';
import { taskCompleteCloudMock } from '../task-header/mocks/fake-complete-task.mock';
import { TaskCloudService } from '../services/task-cloud.service';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { By } from '@angular/platform-browser';
describe('CompleteTaskDirective', () => {
@Component({
selector: 'adf-cloud-test-component',
template: `<button adf-cloud-complete-task [taskId]='taskMock' [appName]='appNameMock' (success)="onCompleteTask($event)" (error)="onError($event)"></button>`
selector: 'adf-cloud-test-component',
template: `<button
adf-cloud-complete-task
[taskId]="taskMock"
[appName]="appNameMock"
(success)="onCompleteTask($event)"
(error)="onError($event)"
></button>`
})
class TestComponent {
taskMock = 'test1234';
appNameMock = 'simple-app';
@@ -53,13 +56,8 @@ describe('CompleteTaskDirective', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
declarations: [
TestComponent
]
imports: [ProcessServiceCloudTestingModule],
declarations: [TestComponent]
});
taskCloudService = TestBed.inject(TaskCloudService);
fixture = TestBed.createComponent(TestComponent);
@@ -73,7 +71,7 @@ describe('CompleteTaskDirective', () => {
expect(taskCloudService.completeTask).toHaveBeenCalled();
});
it('should emit error on api fail', async () => {
it('should emit error on api fail', async () => {
const error = { message: 'process key not found' };
spyOn(taskCloudService, 'completeTask').and.returnValue(throwError(error));
spyOn(fixture.componentInstance, 'onError').and.callThrough();
@@ -105,13 +103,11 @@ describe('CompleteTaskDirective', () => {
});
describe('Complete Task Directive validation errors', () => {
@Component({
selector: 'adf-cloud-no-fields-validation-component',
selector: 'adf-cloud-no-fields-validation-component',
template: '<button adf-cloud-complete-task (success)="onCompleteTask($event)"></button>'
})
class TestMissingInputDirectiveComponent {
appName = 'simple-app';
appNameUndefined = undefined;
appNameNull = null;
@@ -125,11 +121,10 @@ describe('Complete Task Directive validation errors', () => {
}
@Component({
selector: 'adf-cloud-no-taskid-validation-component',
selector: 'adf-cloud-no-taskid-validation-component',
template: '<button adf-cloud-complete-task [appName]="appName" (success)="onCompleteTask($event)"></button>'
})
class TestMissingTaskIdDirectiveComponent {
appName = 'simple-app';
@ContentChildren(CompleteTaskDirective)
@@ -141,11 +136,10 @@ describe('Complete Task Directive validation errors', () => {
}
@Component({
selector: 'adf-cloud-undefined-appname-component',
selector: 'adf-cloud-undefined-appname-component',
template: '<button adf-cloud-complete-task [taskId]="taskMock" [appName]="appNameUndefined" (success)="onCompleteTask($event)"></button>'
})
class TestInvalidAppNameUndefinedDirectiveComponent {
appName = 'simple-app';
taskMock = 'test1234';
@@ -158,11 +152,10 @@ describe('Complete Task Directive validation errors', () => {
}
@Component({
selector: 'adf-cloud-null-appname-component',
selector: 'adf-cloud-null-appname-component',
template: '<button adf-cloud-complete-task [taskId]="taskMock" [appName]="appNameNull" (success)="onCompleteTask($event)"></button>'
})
class TestInvalidAppNameNullDirectiveComponent {
appName = 'simple-app';
taskMock = 'test1234';
@@ -178,10 +171,7 @@ describe('Complete Task Directive validation errors', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
imports: [ProcessServiceCloudTestingModule],
declarations: [
TestMissingTaskIdDirectiveComponent,
TestInvalidAppNameUndefinedDirectiveComponent,
@@ -198,16 +188,16 @@ describe('Complete Task Directive validation errors', () => {
it('should throw error when taskId is not set', () => {
fixture = TestBed.createComponent(TestMissingTaskIdDirectiveComponent);
expect( () => fixture.detectChanges()).toThrowError('Attribute taskId is required');
expect(() => fixture.detectChanges()).toThrowError('Attribute taskId is required');
});
it('should throw error when appName is undefined', () => {
fixture = TestBed.createComponent(TestInvalidAppNameUndefinedDirectiveComponent);
expect( () => fixture.detectChanges()).toThrowError('Attribute appName is required');
expect(() => fixture.detectChanges()).toThrowError('Attribute appName is required');
});
it('should throw error when appName is null', () => {
fixture = TestBed.createComponent(TestInvalidAppNameUndefinedDirectiveComponent);
expect( () => fixture.detectChanges()).toThrowError('Attribute appName is required');
expect(() => fixture.detectChanges()).toThrowError('Attribute appName is required');
});
});
@@ -22,17 +22,14 @@ import { of, throwError } from 'rxjs';
import { UnClaimTaskCloudDirective } from './unclaim-task-cloud.directive';
import { taskClaimCloudMock } from '../task-header/mocks/fake-claim-task.mock';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { By } from '@angular/platform-browser';
describe('UnClaimTaskCloudDirective', () => {
@Component({
selector: 'adf-cloud-test-component',
selector: 'adf-cloud-test-component',
template: '<button adf-cloud-unclaim-task [taskId]="taskIdMock" [appName]="appName" (error)="onError($event)"></button>'
})
class TestComponent {
appName = 'simple-app';
taskIdMock = '1234';
@@ -49,13 +46,8 @@ describe('UnClaimTaskCloudDirective', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
declarations: [
TestComponent
]
imports: [ProcessServiceCloudTestingModule],
declarations: [TestComponent]
});
taskCloudService = TestBed.inject(TaskCloudService);
fixture = TestBed.createComponent(TestComponent);
@@ -101,13 +93,11 @@ describe('UnClaimTaskCloudDirective', () => {
});
describe('UnClaim Task Directive validation errors', () => {
@Component({
selector: 'adf-cloud-claim-no-fields-validation-component',
selector: 'adf-cloud-claim-no-fields-validation-component',
template: '<button adf-cloud-unclaim-task></button>'
})
class ClaimTestMissingInputDirectiveComponent {
appName = 'simple-app';
appNameUndefined = undefined;
appNameNull = null;
@@ -117,11 +107,10 @@ describe('UnClaim Task Directive validation errors', () => {
}
@Component({
selector: 'adf-cloud-claim-no-taskid-validation-component',
selector: 'adf-cloud-claim-no-taskid-validation-component',
template: '<button adf-cloud-unclaim-task [appName]="appName"></button>'
})
class ClaimTestMissingTaskIdDirectiveComponent {
appName = 'simple-app';
@ContentChildren(UnClaimTaskCloudDirective)
@@ -129,11 +118,10 @@ describe('UnClaim Task Directive validation errors', () => {
}
@Component({
selector: 'adf-cloud-claim-undefined-appname-component',
selector: 'adf-cloud-claim-undefined-appname-component',
template: '<button adf-cloud-unclaim-task [taskId]="taskMock" [appName]="appNameUndefined"></button>'
})
class ClaimTestInvalidAppNameUndefinedDirectiveComponent {
appNameUndefined = undefined;
taskMock = 'test1234';
@@ -142,11 +130,10 @@ describe('UnClaim Task Directive validation errors', () => {
}
@Component({
selector: 'adf-cloud-claim-null-appname-component',
selector: 'adf-cloud-claim-null-appname-component',
template: '<button adf-cloud-unclaim-task [taskId]="taskMock" [appName]="appNameNull"></button>'
})
class ClaimTestInvalidAppNameNullDirectiveComponent {
appNameNull = null;
taskMock = 'test1234';
@@ -158,10 +145,7 @@ describe('UnClaim Task Directive validation errors', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
imports: [ProcessServiceCloudTestingModule],
declarations: [
ClaimTestMissingTaskIdDirectiveComponent,
ClaimTestInvalidAppNameUndefinedDirectiveComponent,
@@ -179,16 +163,16 @@ describe('UnClaim Task Directive validation errors', () => {
it('should throw error when taskId is not set', () => {
fixture = TestBed.createComponent(ClaimTestMissingTaskIdDirectiveComponent);
expect( () => fixture.detectChanges()).toThrowError('Attribute taskId is required');
expect(() => fixture.detectChanges()).toThrowError('Attribute taskId is required');
});
it('should throw error when appName is undefined', () => {
fixture = TestBed.createComponent(ClaimTestInvalidAppNameUndefinedDirectiveComponent);
expect( () => fixture.detectChanges()).toThrowError('Attribute appName is required');
expect(() => fixture.detectChanges()).toThrowError('Attribute appName is required');
});
it('should throw error when appName is null', () => {
fixture = TestBed.createComponent(ClaimTestInvalidAppNameUndefinedDirectiveComponent);
expect( () => fixture.detectChanges()).toThrowError('Attribute appName is required');
expect(() => fixture.detectChanges()).toThrowError('Attribute appName is required');
});
});
@@ -16,7 +16,7 @@
*/
import { Injectable } from '@angular/core';
import { AppConfigService, CardViewArrayItem, LogService } from '@alfresco/adf-core';
import { AppConfigService, CardViewArrayItem } from '@alfresco/adf-core';
import { from, Observable, of, Subject, throwError } from 'rxjs';
import { DEFAULT_TASK_PRIORITIES, TaskPriorityOption } from '../models/task.model';
import { TaskDetailsCloudModel, TASK_ASSIGNED_STATE, TASK_CREATED_STATE } from '../start-task/models/task-details-cloud.model';
@@ -29,11 +29,10 @@ import { TaskCloudServiceInterface } from '../services/task-cloud.service.interf
providedIn: 'root'
})
export class TaskCloudServiceMock implements TaskCloudServiceInterface {
currentUserMock = 'AssignedTaskUser';
dataChangesDetected$ = new Subject();
constructor(private appConfigService: AppConfigService, private logService: LogService) { }
constructor(private appConfigService: AppConfigService) {}
getTaskById(_appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
return of(taskDetailsContainer[taskId]);
@@ -68,7 +67,11 @@ export class TaskCloudServiceMock implements TaskCloudServiceInterface {
return taskDetails.status === TASK_ASSIGNED_STATE && this.isAssignedToMe(taskDetails.assignee);
}
isAssigneePropertyClickable(taskDetails: TaskDetailsCloudModel, candidateUsers: CardViewArrayItem[], candidateGroups: CardViewArrayItem[]): boolean {
isAssigneePropertyClickable(
taskDetails: TaskDetailsCloudModel,
candidateUsers: CardViewArrayItem[],
candidateGroups: CardViewArrayItem[]
): boolean {
let isClickable = false;
const states = [TASK_ASSIGNED_STATE];
if (candidateUsers?.length || candidateGroups?.length) {
@@ -103,7 +106,6 @@ export class TaskCloudServiceMock implements TaskCloudServiceInterface {
return from([]);
} else {
this.logService.error('AppName and TaskId are mandatory for complete a task');
return throwError('AppName/TaskId not configured');
}
}
@@ -119,7 +121,6 @@ export class TaskCloudServiceMock implements TaskCloudServiceInterface {
return from([]);
} else {
this.logService.error('AppName and TaskId are mandatory for querying a task');
return throwError('AppName/TaskId not configured');
}
}
@@ -130,7 +131,6 @@ export class TaskCloudServiceMock implements TaskCloudServiceInterface {
return from([]);
} else {
this.logService.error('AppName and TaskId are mandatory for querying a task');
return throwError('AppName/TaskId not configured');
}
}
@@ -147,7 +147,6 @@ export class TaskCloudServiceMock implements TaskCloudServiceInterface {
return from([]);
} else {
this.logService.error('AppName is mandatory for querying task');
return throwError('AppName not configured');
}
}
@@ -158,7 +157,6 @@ export class TaskCloudServiceMock implements TaskCloudServiceInterface {
return from([]);
} else {
this.logService.error('AppName and TaskId are mandatory to change/update the task assignee');
return throwError('AppName/TaskId not configured');
}
}
@@ -19,16 +19,18 @@ import { TestBed } from '@angular/core/testing';
import { TranslationService } from '@alfresco/adf-core';
import { TaskCloudService } from './task-cloud.service';
import { taskCompleteCloudMock } from '../task-header/mocks/fake-complete-task.mock';
import { assignedTaskDetailsCloudMock, createdTaskDetailsCloudMock, emptyOwnerTaskDetailsCloudMock } from '../task-header/mocks/task-details-cloud.mock';
import {
assignedTaskDetailsCloudMock,
createdTaskDetailsCloudMock,
emptyOwnerTaskDetailsCloudMock
} from '../task-header/mocks/task-details-cloud.mock';
import { fakeTaskDetailsCloud } from '../task-header/mocks/fake-task-details-response.mock';
import { cloudMockUser } from '../start-task/mock/user-cloud.mock';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { IdentityUserService } from '../../people/services/identity-user.service';
import { AdfHttpClient } from '@alfresco/adf-core/api';
describe('Task Cloud Service', () => {
let service: TaskCloudService;
let adfHttpClient: AdfHttpClient;
let identityUserService: IdentityUserService;
@@ -47,16 +49,13 @@ describe('Task Cloud Service', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [ProcessServiceCloudTestingModule]
});
adfHttpClient = TestBed.inject(AdfHttpClient);
identityUserService = TestBed.inject(IdentityUserService);
translateService = TestBed.inject(TranslationService);
service = TestBed.inject(TaskCloudService);
spyOn(translateService, 'instant').and.callFake((key) => key ? `${key}_translated` : null);
spyOn(translateService, 'instant').and.callFake((key) => (key ? `${key}_translated` : null));
spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue(cloudMockUser);
requestSpy = spyOn(adfHttpClient, 'request');
});
@@ -104,7 +103,11 @@ describe('Task Cloud Service', () => {
});
it('should verify if the task assignee property is clickable', () => {
const isAssigneePropertyClickable = service.isAssigneePropertyClickable(assignedTaskDetailsCloudMock, [ { icon: '', value: 'user' } ], [ { icon: '', value: 'group' } ]);
const isAssigneePropertyClickable = service.isAssigneePropertyClickable(
assignedTaskDetailsCloudMock,
[{ icon: '', value: 'user' }],
[{ icon: '', value: 'group' }]
);
expect(isAssigneePropertyClickable).toEqual(true);
});
@@ -144,11 +147,12 @@ describe('Task Cloud Service', () => {
const assignee = 'user12';
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.claimTask(appName, taskId, assignee).subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('AppName/TaskId not configured');
done();
});
}
);
});
it('should throw error if taskId is not defined when claiming a task', (done) => {
@@ -157,11 +161,12 @@ describe('Task Cloud Service', () => {
const assignee = 'user12';
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.claimTask(appName, taskId, assignee).subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('AppName/TaskId not configured');
done();
});
}
);
});
it('should return the task details when unclaiming a task', (done) => {
@@ -182,11 +187,12 @@ describe('Task Cloud Service', () => {
const taskId = '68d54a8f';
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.unclaimTask(appName, taskId).subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('AppName/TaskId not configured');
done();
});
}
);
});
it('should throw error if taskId is not defined when unclaiming a task', (done) => {
@@ -194,11 +200,12 @@ describe('Task Cloud Service', () => {
const taskId = null;
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.unclaimTask(appName, taskId).subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('AppName/TaskId not configured');
done();
});
}
);
});
it('should return the task details when querying by id', (done) => {
@@ -219,11 +226,12 @@ describe('Task Cloud Service', () => {
const taskId = '68d54a8f';
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.getTaskById(appName, taskId).subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('AppName/TaskId not configured');
done();
});
}
);
});
it('should throw error if taskId is not defined when querying by id', (done) => {
@@ -231,11 +239,12 @@ describe('Task Cloud Service', () => {
const taskId = null;
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.getTaskById(appName, taskId).subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('AppName/TaskId not configured');
done();
});
}
);
});
it('should throw error if appName is not defined when updating a task', (done) => {
@@ -244,11 +253,12 @@ describe('Task Cloud Service', () => {
const updatePayload = { description: 'New description' };
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.updateTask(appName, taskId, updatePayload).subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('AppName/TaskId not configured');
done();
});
}
);
});
it('should throw error if taskId is not defined when updating a task', (done) => {
@@ -257,11 +267,12 @@ describe('Task Cloud Service', () => {
const updatePayload = { description: 'New description' };
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.updateTask(appName, taskId, updatePayload).subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('AppName/TaskId not configured');
done();
});
}
);
});
it('should return the task details when updating a task', (done) => {
@@ -284,11 +295,12 @@ describe('Task Cloud Service', () => {
const updatePayload = { description: 'New description' };
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.updateTask(appName, taskId, updatePayload).subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('AppName/TaskId not configured');
done();
});
}
);
});
it('should throw error if taskId is not defined updating a task', (done) => {
@@ -297,11 +309,12 @@ describe('Task Cloud Service', () => {
const updatePayload = { description: 'New description' };
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.updateTask(appName, taskId, updatePayload).subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('AppName/TaskId not configured');
done();
});
}
);
});
it('should return the candidate users by appName and taskId', (done) => {
@@ -322,22 +335,20 @@ describe('Task Cloud Service', () => {
const appName = null;
const taskId = '68d54a8f';
requestSpy.and.callFake(returnFakeCandidateUsersResults);
service.getCandidateUsers(appName, taskId).subscribe(
(res: any[]) => {
expect(res.length).toBe(0);
done();
});
service.getCandidateUsers(appName, taskId).subscribe((res: any[]) => {
expect(res.length).toBe(0);
done();
});
});
it('should log message and return empty array if taskId is not defined when fetching candidate users', (done) => {
const appName = 'task-app';
const taskId = null;
requestSpy.and.callFake(returnFakeCandidateUsersResults);
service.getCandidateUsers(appName, taskId).subscribe(
(res: any[]) => {
expect(res.length).toBe(0);
done();
});
service.getCandidateUsers(appName, taskId).subscribe((res: any[]) => {
expect(res.length).toBe(0);
done();
});
});
it('should return the candidate groups by appName and taskId', (done) => {
@@ -358,33 +369,30 @@ describe('Task Cloud Service', () => {
const appName = null;
const taskId = '68d54a8f';
requestSpy.and.callFake(returnFakeCandidateGroupResults);
service.getCandidateGroups(appName, taskId).subscribe(
(res: any[]) => {
expect(res.length).toBe(0);
done();
});
service.getCandidateGroups(appName, taskId).subscribe((res: any[]) => {
expect(res.length).toBe(0);
done();
});
});
it('should log message and return empty array if taskId is not defined when fetching candidate groups', (done) => {
const appName = 'task-app';
const taskId = null;
requestSpy.and.callFake(returnFakeCandidateGroupResults);
service.getCandidateGroups(appName, taskId).subscribe(
(res: any[]) => {
expect(res.length).toBe(0);
done();
});
service.getCandidateGroups(appName, taskId).subscribe((res: any[]) => {
expect(res.length).toBe(0);
done();
});
});
it('should call assign api and return updated task details', (done) => {
const appName = 'task-app';
const taskId = '68d54a8f';
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.assign(appName, taskId, 'Phil Woods').subscribe(
(res) => {
expect(res.assignee).toBe('Phil Woods');
done();
});
service.assign(appName, taskId, 'Phil Woods').subscribe((res) => {
expect(res.assignee).toBe('Phil Woods');
done();
});
});
it('should throw error if appName is not defined when changing task assignee', (done) => {
@@ -392,11 +400,12 @@ describe('Task Cloud Service', () => {
const taskId = '68d54a8f';
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.assign(appName, taskId, 'mock-assignee').subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('AppName/TaskId not configured');
done();
});
}
);
});
it('should throw error if taskId is not defined when changing task assignee', (done) => {
@@ -404,11 +413,11 @@ describe('Task Cloud Service', () => {
const taskId = '';
requestSpy.and.callFake(returnFakeTaskDetailsResults);
service.assign(appName, taskId, 'mock-assignee').subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('AppName/TaskId not configured');
done();
});
}
);
});
});
@@ -18,7 +18,7 @@
import { Injectable } from '@angular/core';
import { CardViewArrayItem, TranslationService } from '@alfresco/adf-core';
import { throwError, Observable, of, Subject } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { map } from 'rxjs/operators';
import {
TaskDetailsCloudModel,
StartTaskCloudResponseModel,
@@ -39,14 +39,9 @@ import { AdfHttpClient } from '@alfresco/adf-core/api';
providedIn: 'root'
})
export class TaskCloudService extends BaseCloudService implements TaskCloudServiceInterface {
dataChangesDetected$ = new Subject();
constructor(
private translateService: TranslationService,
private identityUserService: IdentityUserService,
adfHttpClient: AdfHttpClient
) {
constructor(private translateService: TranslationService, private identityUserService: IdentityUserService, adfHttpClient: AdfHttpClient) {
super(adfHttpClient);
}
@@ -64,7 +59,6 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
return this.post<any, TaskDetailsCloudModel>(url, payload);
} else {
this.logService.error('AppName and TaskId are mandatory for complete a task');
return throwError('AppName/TaskId not configured');
}
}
@@ -89,7 +83,11 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
return taskDetails && taskDetails.status === TASK_ASSIGNED_STATE && this.isAssignedToMe(taskDetails.assignee);
}
isAssigneePropertyClickable(taskDetails: TaskDetailsCloudModel, candidateUsers: CardViewArrayItem[], candidateGroups: CardViewArrayItem[]): boolean {
isAssigneePropertyClickable(
taskDetails: TaskDetailsCloudModel,
candidateUsers: CardViewArrayItem[],
candidateGroups: CardViewArrayItem[]
): boolean {
let isClickable = false;
const states = [TASK_ASSIGNED_STATE];
if (candidateUsers?.length || candidateGroups?.length) {
@@ -105,9 +103,7 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
* @returns Boolean value if the task can be completed
*/
canClaimTask(taskDetails: TaskDetailsCloudModel): boolean {
return taskDetails?.status === TASK_CREATED_STATE &&
taskDetails?.permissions.includes(TASK_CLAIM_PERMISSION) &&
!taskDetails?.standalone;
return taskDetails?.status === TASK_CREATED_STATE && taskDetails?.permissions.includes(TASK_CLAIM_PERMISSION) && !taskDetails?.standalone;
}
/**
@@ -118,10 +114,12 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
*/
canUnclaimTask(taskDetails: TaskDetailsCloudModel): boolean {
const currentUser = this.identityUserService.getCurrentUserInfo().username;
return taskDetails?.status === TASK_ASSIGNED_STATE &&
taskDetails?.assignee === currentUser &&
taskDetails?.permissions.includes(TASK_RELEASE_PERMISSION) &&
!taskDetails?.standalone;
return (
taskDetails?.status === TASK_ASSIGNED_STATE &&
taskDetails?.assignee === currentUser &&
taskDetails?.permissions.includes(TASK_RELEASE_PERMISSION) &&
!taskDetails?.standalone
);
}
/**
@@ -143,7 +141,6 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
})
);
} else {
this.logService.error('AppName and TaskId are mandatory for querying a task');
return throwError('AppName/TaskId not configured');
}
}
@@ -166,7 +163,6 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
})
);
} else {
this.logService.error('AppName and TaskId are mandatory for querying a task');
return throwError('AppName/TaskId not configured');
}
}
@@ -182,30 +178,24 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
if ((appName || appName === '') && taskId) {
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`;
return this.get(queryUrl).pipe(
map((res: any) => res.entry)
);
return this.get(queryUrl).pipe(map((res: any) => res.entry));
} else {
this.logService.error('AppName and TaskId are mandatory for querying a task');
return throwError('AppName/TaskId not configured');
}
}
/**
* Creates a new standalone task.
*
* @param startTaskRequest request model
* @param appName application name
* @returns Details of the newly created task
*/
/**
* Creates a new standalone task.
*
* @param startTaskRequest request model
* @param appName application name
* @returns Details of the newly created task
*/
createNewTask(startTaskRequest: StartTaskCloudRequestModel, appName: string): Observable<TaskDetailsCloudModel> {
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks`;
const payload = JSON.stringify(new StartTaskCloudRequestModel(startTaskRequest));
return this.post<any, StartTaskCloudResponseModel>(queryUrl, payload)
.pipe(
map(response => response.entry)
);
return this.post<any, StartTaskCloudResponseModel>(queryUrl, payload).pipe(map((response) => response.entry));
}
/**
@@ -221,11 +211,8 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
payload.payloadType = 'UpdateTaskPayload';
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}`;
return this.put(queryUrl, payload).pipe(
map((res: any) => res.entry)
);
return this.put(queryUrl, payload).pipe(map((res: any) => res.entry));
} else {
this.logService.error('AppName and TaskId are mandatory for querying a task');
return throwError('AppName/TaskId not configured');
}
}
@@ -240,11 +227,8 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
getCandidateUsers(appName: string, taskId: string): Observable<string[]> {
if ((appName || appName === '') && taskId) {
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/candidate-users`;
return this.get<string[]>(queryUrl).pipe(
catchError((err) => this.handleError(err))
);
return this.get<string[]>(queryUrl);
} else {
this.logService.error('AppName and TaskId are mandatory to get candidate user');
return of([]);
}
}
@@ -261,7 +245,6 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/candidate-groups`;
return this.get<string[]>(queryUrl);
} else {
this.logService.error('AppName and TaskId are mandatory to get candidate groups');
return of([]);
}
}
@@ -276,11 +259,8 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
if (appName || appName === '') {
const url = `${this.getBasePath(appName)}/rb/v1/process-definitions`;
return this.get(url).pipe(
map((res: any) => res.list.entries.map((processDefs) => new ProcessDefinitionCloud(processDefs.entry)))
);
return this.get(url).pipe(map((res: any) => res.list.entries.map((processDefs) => new ProcessDefinitionCloud(processDefs.entry))));
} else {
this.logService.error('AppName is mandatory for querying task');
return throwError('AppName not configured');
}
}
@@ -298,17 +278,14 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
const payLoad = { assignee, taskId, payloadType: 'AssignTaskPayload' };
const url = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/assign`;
return this.post(url, payLoad).pipe(
map((res: any) => res.entry)
);
return this.post(url, payLoad).pipe(map((res: any) => res.entry));
} else {
this.logService.error('AppName and TaskId are mandatory to change/update the task assignee');
return throwError('AppName/TaskId not configured');
}
}
}
getPriorityLabel(priority: number): string {
const priorityItem = this.priorities.find(item => item.value === priority.toString()) || this.priorities[0];
const priorityItem = this.priorities.find((item) => item.value === priority.toString()) || this.priorities[0];
return this.translateService.instant(priorityItem.label);
}
@@ -320,9 +297,4 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
const currentUser = this.identityUserService.getCurrentUserInfo().username;
return assignee === currentUser;
}
private handleError(error?: any) {
this.logService.error(error);
return throwError(error || 'Server error');
}
}
@@ -25,12 +25,10 @@ import { ProcessServiceCloudTestingModule } from './../../../testing/process-ser
import { FormDefinitionSelectorCloudService } from '../../../form/services/form-definition-selector-cloud.service';
import { TaskCloudService } from '../../services/task-cloud.service';
import { StartTaskCloudRequestModel } from '../models/start-task-cloud-request.model';
import { TranslateModule } from '@ngx-translate/core';
import { IdentityUserService } from '../../../people/services/identity-user.service';
import { IdentityUserModel } from '../../../people/models/identity-user.model';
describe('StartTaskCloudComponent', () => {
let component: StartTaskCloudComponent;
let fixture: ComponentFixture<StartTaskCloudComponent>;
let service: TaskCloudService;
@@ -48,15 +46,12 @@ describe('StartTaskCloudComponent', () => {
reply: jasmine.createSpy('reply')
};
const mockUser: IdentityUserModel = {username: 'currentUser', firstName: 'Test', lastName: 'User', email: 'currentUser@test.com'};
const mockUser: IdentityUserModel = { username: 'currentUser', firstName: 'Test', lastName: 'User', email: 'currentUser@test.com' };
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
imports: [ProcessServiceCloudTestingModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
fixture = TestBed.createComponent(StartTaskCloudComponent);
component = fixture.componentInstance;
@@ -74,7 +69,6 @@ describe('StartTaskCloudComponent', () => {
});
describe('create task', () => {
it('should create new task when start button is clicked', async () => {
const successSpy = spyOn(component.success, 'emit');
component.taskForm.controls['name'].setValue('fakeName');
@@ -143,7 +137,7 @@ describe('StartTaskCloudComponent', () => {
createTaskButton.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
const taskRequest = new StartTaskCloudRequestModel({ name: 'fakeName', assignee: 'currentUser', candidateGroups: []});
const taskRequest = new StartTaskCloudRequestModel({ name: 'fakeName', assignee: 'currentUser', candidateGroups: [] });
expect(createNewTaskSpy).toHaveBeenCalledWith(taskRequest, 'fakeAppName');
done();
});
@@ -157,7 +151,7 @@ describe('StartTaskCloudComponent', () => {
createTaskButton.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
const taskRequest = new StartTaskCloudRequestModel({ name: 'fakeName', assignee: 'currentUser', candidateGroups: []});
const taskRequest = new StartTaskCloudRequestModel({ name: 'fakeName', assignee: 'currentUser', candidateGroups: [] });
expect(createNewTaskSpy).toHaveBeenCalledWith(taskRequest, 'fakeAppName');
done();
});
@@ -19,12 +19,7 @@ import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation, OnDe
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import { Observable, Subject } from 'rxjs';
import { UntypedFormBuilder, Validators, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
import {
DateFnsUtils,
LogService,
UserPreferencesService,
UserPreferenceValues
} from '@alfresco/adf-core';
import { DateFnsUtils, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
import { PeopleCloudComponent } from '../../../people/components/people-cloud.component';
import { GroupCloudComponent } from '../../../group/components/group-cloud.component';
import { TaskCloudService } from '../../services/task-cloud.service';
@@ -45,7 +40,8 @@ const DATE_FORMAT: string = 'dd/MM/yyyy';
styleUrls: ['./start-task-cloud.component.scss'],
providers: [
{ provide: DateAdapter, useClass: DateFnsAdapter },
{ provide: MAT_DATE_FORMATS, useValue: MAT_DATE_FNS_FORMATS }],
{ provide: MAT_DATE_FORMATS, useValue: MAT_DATE_FNS_FORMATS }
],
encapsulation: ViewEncapsulation.None
})
export class StartTaskCloudComponent implements OnInit, OnDestroy {
@@ -105,19 +101,19 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy {
private groupForm = new UntypedFormControl('');
private onDestroy$ = new Subject<boolean>();
constructor(private taskService: TaskCloudService,
private dateAdapter: DateAdapter<DateFnsAdapter>,
private userPreferencesService: UserPreferencesService,
private formBuilder: UntypedFormBuilder,
private identityUserService: IdentityUserService,
private logService: LogService) {
}
constructor(
private taskService: TaskCloudService,
private dateAdapter: DateAdapter<DateFnsAdapter>,
private userPreferencesService: UserPreferencesService,
private formBuilder: UntypedFormBuilder,
private identityUserService: IdentityUserService
) {}
ngOnInit() {
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.dateAdapter.setLocale(DateFnsUtils.getLocaleFromString(locale)));
.subscribe((locale) => this.dateAdapter.setLocale(DateFnsUtils.getLocaleFromString(locale)));
this.loadCurrentUser();
this.buildForm();
this.loadDefaultPriorities();
@@ -162,17 +158,16 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy {
}
private createNewTask(newTask: StartTaskCloudRequestModel) {
this.taskService.createNewTask(newTask, this.appName)
.subscribe(
(res: any) => {
this.submitted = false;
this.success.emit(res);
},
(err) => {
this.submitted = false;
this.error.emit(err);
this.logService.error('An error occurred while creating new task');
});
this.taskService.createNewTask(newTask, this.appName).subscribe(
(res: any) => {
this.submitted = false;
this.success.emit(res);
},
(err) => {
this.submitted = false;
this.error.emit(err);
}
);
}
public onCancel() {
@@ -212,11 +207,7 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy {
}
canStartTask(): boolean {
return !(this.dateError ||
!this.taskForm.valid ||
this.submitted ||
this.assignee.hasError() ||
this.candidateGroups.hasError());
return !(this.dateError || !this.taskForm.valid || this.submitted || this.assignee.hasError() || this.candidateGroups.hasError());
}
public whitespaceValidator(control: UntypedFormControl) {
@@ -21,53 +21,46 @@ import { taskDetailsMock } from '../mock/task-details.mock';
import { TaskDetailsCloudModel } from '../models/task-details-cloud.model';
import { HttpErrorResponse } from '@angular/common/http';
import { TaskCloudService } from '../../services/task-cloud.service';
import { TranslateModule } from '@ngx-translate/core';
import { ProcessServiceCloudTestingModule } from './../../../testing/process-service-cloud.testing.module';
describe('StartTaskCloudService', () => {
let service: TaskCloudService;
const fakeAppName: string = 'fake-app';
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [ProcessServiceCloudTestingModule]
});
service = TestBed.inject(TaskCloudService);
});
it('should able to create a new task ', (done) => {
spyOn(service, 'createNewTask').and.returnValue(of({id: 'fake-id', name: 'fake-name'}));
service.createNewTask(taskDetailsMock, fakeAppName).subscribe(
(res: TaskDetailsCloudModel) => {
expect(res).toBeDefined();
expect(res.id).toEqual('fake-id');
expect(res.name).toEqual('fake-name');
done();
}
);
spyOn(service, 'createNewTask').and.returnValue(of({ id: 'fake-id', name: 'fake-name' }));
service.createNewTask(taskDetailsMock, fakeAppName).subscribe((res: TaskDetailsCloudModel) => {
expect(res).toBeDefined();
expect(res.id).toEqual('fake-id');
expect(res.name).toEqual('fake-name');
done();
});
});
it('Should not able to create a task if error occurred', () => {
const errorResponse = new HttpErrorResponse({
error: 'Mock Error',
status: 404, statusText: 'Not Found'
status: 404,
statusText: 'Not Found'
});
spyOn(service, 'createNewTask').and.returnValue(throwError(errorResponse));
service.createNewTask(taskDetailsMock, fakeAppName)
.subscribe(
() => {
fail('expected an error, not applications');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
}
);
service.createNewTask(taskDetailsMock, fakeAppName).subscribe(
() => {
fail('expected an error, not applications');
},
(error) => {
expect(error.status).toEqual(404);
expect(error.statusText).toEqual('Not Found');
expect(error.error).toEqual('Mock Error');
}
);
});
});
@@ -28,7 +28,6 @@ import { TaskFiltersCloudModule } from '../../task-filters-cloud.module';
import { ServiceTaskFilterCloudService } from '../../services/service-task-filter-cloud.service';
import { TaskCloudService } from '../../../services/task-cloud.service';
import { fakeServiceFilter } from '../../mock/task-filters-cloud.mock';
import { TranslateModule } from '@ngx-translate/core';
import { EditServiceTaskFilterCloudComponent } from './edit-service-task-filter-cloud.component';
import { MatIconTestingModule } from '@angular/material/icon/testing';
import { ProcessDefinitionCloud } from '../../../../models/process-definition-cloud.model';
@@ -55,7 +54,7 @@ describe('EditServiceTaskFilterCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule, TaskFiltersCloudModule, MatIconTestingModule],
imports: [ProcessServiceCloudTestingModule, TaskFiltersCloudModule, MatIconTestingModule],
providers: [MatDialog, { provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }]
});
fixture = TestBed.createComponent(EditServiceTaskFilterCloudComponent);
@@ -30,7 +30,6 @@ import { EditTaskFilterCloudComponent } from './edit-task-filter-cloud.component
import { TaskFilterCloudService } from '../../services/task-filter-cloud.service';
import { TaskCloudService } from '../../../services/task-cloud.service';
import { fakeFilter } from '../../mock/task-filters-cloud.mock';
import { TranslateModule } from '@ngx-translate/core';
import { DateCloudFilterType } from '../../../../models/date-cloud-filter.model';
import { AssignmentType, TaskFilterCloudModel, TaskStatusFilter } from '../../models/filter-cloud.model';
import { PeopleCloudModule } from '../../../../people/people-cloud.module';
@@ -75,7 +74,7 @@ describe('EditTaskFilterCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule, TaskFiltersCloudModule, PeopleCloudModule, MatIconTestingModule],
imports: [ProcessServiceCloudTestingModule, TaskFiltersCloudModule, PeopleCloudModule, MatIconTestingModule],
providers: [MatDialog, { provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }]
});
fixture = TestBed.createComponent(EditTaskFilterCloudComponent);
@@ -24,7 +24,6 @@ import { By } from '@angular/platform-browser';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TaskFiltersCloudModule } from '../task-filters-cloud.module';
import { fakeGlobalServiceFilters } from '../mock/task-filters-cloud.mock';
import { TranslateModule } from '@ngx-translate/core';
import { ServiceTaskFilterCloudService } from '../services/service-task-filter-cloud.service';
import { ServiceTaskFiltersCloudComponent } from './service-task-filters-cloud.component';
@@ -37,14 +36,8 @@ describe('ServiceTaskFiltersCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule,
TaskFiltersCloudModule
],
providers: [
{ provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }
]
imports: [ProcessServiceCloudTestingModule, TaskFiltersCloudModule],
providers: [{ provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }]
});
fixture = TestBed.createComponent(ServiceTaskFiltersCloudComponent);
component = fixture.componentInstance;
@@ -119,7 +112,7 @@ describe('ServiceTaskFiltersCloudComponent', () => {
const change = new SimpleChange(null, appName, true);
let lastValue: any;
component.error.subscribe((err) => lastValue = err);
component.error.subscribe((err) => (lastValue = err));
component.ngOnChanges({ appName: change });
fixture.detectChanges();
@@ -16,13 +16,10 @@
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslationService, TranslationMock } from '@alfresco/adf-core';
import { TranslateModule } from '@ngx-translate/core';
import { TaskAssignmentFilterCloudComponent } from './task-assignment-filter.component';
import { GroupCloudModule } from '../../../../group/group-cloud.module';
import { TaskFiltersCloudModule } from '../../task-filters-cloud.module';
import { AssignmentType, TaskStatusFilter } from '../../models/filter-cloud.model';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { IdentityUserService } from '../../../../people/services/identity-user.service';
import { By } from '@angular/platform-browser';
import { DebugElement, SimpleChange } from '@angular/core';
@@ -32,6 +29,7 @@ import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing';
import { MatFormFieldHarness } from '@angular/material/form-field/testing';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
describe('TaskAssignmentFilterComponent', () => {
let component: TaskAssignmentFilterCloudComponent;
@@ -60,15 +58,7 @@ describe('TaskAssignmentFilterComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
GroupCloudModule,
TaskFiltersCloudModule,
NoopAnimationsModule
],
providers: [
{ provide: TranslationService, useClass: TranslationMock }
]
imports: [ProcessServiceCloudTestingModule, GroupCloudModule, TaskFiltersCloudModule]
});
});
@@ -132,7 +122,7 @@ describe('TaskAssignmentFilterComponent', () => {
it('should have floating labels when values are present', async () => {
const inputLabelsNodes = await loader.getAllHarnesses(MatFormFieldHarness);
inputLabelsNodes.forEach(async labelNode => {
inputLabelsNodes.forEach(async (labelNode) => {
expect(await labelNode.isLabelFloating()).toBeTruthy();
});
});
@@ -148,21 +138,21 @@ describe('TaskAssignmentFilterComponent', () => {
it('should CREATED status set assignment type to UNASSIGNED', () => {
const createdStatusChange = new SimpleChange(null, TaskStatusFilter.CREATED, true);
component.ngOnChanges({status: createdStatusChange});
component.ngOnChanges({ status: createdStatusChange });
expect(component.assignmentType).toEqual(AssignmentType.UNASSIGNED);
});
it('should ASSIGNED status set assignment type to ASSIGNED_TO', () => {
const createdStatusChange = new SimpleChange(null, TaskStatusFilter.ASSIGNED, true);
component.ngOnChanges({status: createdStatusChange});
component.ngOnChanges({ status: createdStatusChange });
expect(component.assignmentType).toEqual(AssignmentType.ASSIGNED_TO);
});
it('should ALL status set assignment type to NONE', () => {
const createdStatusChange = new SimpleChange(null, TaskStatusFilter.ALL, true);
component.ngOnChanges({status: createdStatusChange});
component.ngOnChanges({ status: createdStatusChange });
expect(component.assignmentType).toEqual(AssignmentType.NONE);
});
@@ -182,7 +172,7 @@ describe('TaskAssignmentFilterComponent', () => {
label: 'mock-filter',
value: { assignedUsers: mockFoodUsers },
type: 'assignment',
attributes: { assignedUsers: 'assignedUsers', candidateGroups: 'candidateGroups'}
attributes: { assignedUsers: 'assignedUsers', candidateGroups: 'candidateGroups' }
};
fixture.detectChanges();
@@ -195,7 +185,7 @@ describe('TaskAssignmentFilterComponent', () => {
label: 'mock-filter',
value: { candidateGroups: mockFoodGroups },
type: 'assignment',
attributes: { assignedUsers: 'assignedUsers', candidateGroups: 'candidateGroups'}
attributes: { assignedUsers: 'assignedUsers', candidateGroups: 'candidateGroups' }
};
fixture.detectChanges();
@@ -208,7 +198,7 @@ describe('TaskAssignmentFilterComponent', () => {
label: 'mock-filter',
value: {},
type: 'assignment',
attributes: { assignedUsers: 'assignedUsers', candidateGroups: 'candidateGroups'}
attributes: { assignedUsers: 'assignedUsers', candidateGroups: 'candidateGroups' }
};
fixture.detectChanges();
@@ -20,7 +20,6 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { TaskFilterDialogCloudComponent } from './task-filter-dialog-cloud.component';
import { TaskFiltersCloudModule } from '../../task-filters-cloud.module';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
describe('TaskFilterDialogCloudComponent', () => {
let component: TaskFilterDialogCloudComponent;
@@ -32,16 +31,12 @@ describe('TaskFilterDialogCloudComponent', () => {
};
const mockDialogData = {
data: {name: 'Mock-Title'}
data: { name: 'Mock-Title' }
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule,
TaskFiltersCloudModule
],
imports: [ProcessServiceCloudTestingModule, TaskFiltersCloudModule],
providers: [
{ provide: MatDialogRef, useValue: mockDialogRef },
{ provide: MAT_DIALOG_DATA, useValue: mockDialogData }
@@ -31,7 +31,6 @@ import {
TASK_VIEW_PERMISSION
} from '../../start-task/models/task-details-cloud.model';
import { TaskCloudService } from '../../services/task-cloud.service';
import { TranslateModule } from '@ngx-translate/core';
import { IdentityUserService } from '../../../people/services/identity-user.service';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
@@ -68,7 +67,7 @@ describe('TaskFormCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
imports: [ProcessServiceCloudTestingModule],
declarations: [FormCloudComponent]
});
taskDetails.status = TASK_ASSIGNED_STATE;
@@ -31,7 +31,6 @@ import {
taskDetailsWithParentTaskIdMock,
createdTaskDetailsCloudMock
} from '../mocks/task-details-cloud.mock';
import { TranslateModule } from '@ngx-translate/core';
import { MatSelectModule } from '@angular/material/select';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
@@ -62,12 +61,7 @@ describe('TaskHeaderCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule,
TaskHeaderCloudModule,
MatSelectModule
]
imports: [ProcessServiceCloudTestingModule, TaskHeaderCloudModule, MatSelectModule]
});
appConfigService = TestBed.inject(AppConfigService);
appConfigService.config = {
@@ -94,7 +88,6 @@ describe('TaskHeaderCloudComponent', () => {
});
describe('Task Details', () => {
beforeEach(() => {
component.ngOnChanges();
});
@@ -225,7 +218,6 @@ describe('TaskHeaderCloudComponent', () => {
});
describe('Task with parentTaskId', () => {
beforeEach(() => {
getTaskByIdSpy.and.returnValue(of(taskDetailsWithParentTaskIdMock));
component.ngOnChanges();
@@ -253,7 +245,6 @@ describe('TaskHeaderCloudComponent', () => {
});
describe('Assigned Task', () => {
beforeEach(() => {
getTaskByIdSpy.and.returnValue(of(assignedTaskDetailsCloudMock));
component.ngOnChanges();
@@ -277,7 +268,9 @@ describe('TaskHeaderCloudComponent', () => {
it('should render defined edit icon for assignee property if the task in assigned state and shared among candidate users', async () => {
fixture.detectChanges();
await fixture.whenStable();
const value = fixture.debugElement.query(By.css(`[data-automation-id="header-assignee"] [data-automation-id="card-textitem-clickable-icon-assignee"]`));
const value = fixture.debugElement.query(
By.css(`[data-automation-id="header-assignee"] [data-automation-id="card-textitem-clickable-icon-assignee"]`)
);
expect(value).not.toBeNull();
expect(value.nativeElement.innerText).toBe('create');
});
@@ -289,29 +282,41 @@ describe('TaskHeaderCloudComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const editIcon = fixture.debugElement.query(By.css(`[data-automation-id="header-assignee"] [data-automation-id="card-textitem-clickable-icon-assignee"]`));
const editIcon = fixture.debugElement.query(
By.css(`[data-automation-id="header-assignee"] [data-automation-id="card-textitem-clickable-icon-assignee"]`)
);
expect(editIcon).toBeNull();
});
it('should not render defined edit icon for assignee property if the task in assigned state and shared among candidate groups', async () => {
component.candidateGroups = [{ value: 'mock-group-1', icon: 'edit' }, { value: 'mock-group-2', icon: 'edit' }];
component.candidateGroups = [
{ value: 'mock-group-1', icon: 'edit' },
{ value: 'mock-group-2', icon: 'edit' }
];
component.candidateUsers = [];
fixture.detectChanges();
await fixture.whenStable();
const value = fixture.debugElement.query(By.css(`[data-automation-id="header-assignee"] [data-automation-id="card-textitem-clickable-icon-assignee"]`));
const value = fixture.debugElement.query(
By.css(`[data-automation-id="header-assignee"] [data-automation-id="card-textitem-clickable-icon-assignee"]`)
);
expect(value).not.toBeNull();
expect(value.nativeElement.innerText).toBe('create');
});
it('should not render defined edit icon for assignee property if the task in created state and shared among condidate groups', async () => {
getTaskByIdSpy.and.returnValue(of(createdTaskDetailsCloudMock));
component.candidateGroups = [{ value: 'mock-group-1', icon: 'edit' }, { value: 'mock-group-2', icon: 'edit' }];
component.candidateGroups = [
{ value: 'mock-group-1', icon: 'edit' },
{ value: 'mock-group-2', icon: 'edit' }
];
component.candidateUsers = [];
component.ngOnChanges();
fixture.detectChanges();
await fixture.whenStable();
const editIcon = fixture.debugElement.query(By.css(`[data-automation-id="header-assignee"] [data-automation-id="card-textitem-clickable-icon-assignee"]`));
const editIcon = fixture.debugElement.query(
By.css(`[data-automation-id="header-assignee"] [data-automation-id="card-textitem-clickable-icon-assignee"]`)
);
expect(editIcon).toBeNull();
});
@@ -331,7 +336,6 @@ describe('TaskHeaderCloudComponent', () => {
});
describe('Created Task', () => {
beforeEach(() => {
getTaskByIdSpy.and.returnValue(of(createdStateTaskDetailsCloudMock));
isTaskEditableSpy.and.returnValue(false);
@@ -362,7 +366,6 @@ describe('TaskHeaderCloudComponent', () => {
});
describe('Completed Task', () => {
beforeEach(() => {
getTaskByIdSpy.and.returnValue(of(completedTaskDetailsCloudMock));
isTaskEditableSpy.and.returnValue(false);
@@ -384,7 +387,6 @@ describe('TaskHeaderCloudComponent', () => {
});
describe('Suspended Task', () => {
beforeEach(() => {
getTaskByIdSpy.and.returnValue(of(suspendedTaskDetailsCloudMock));
isTaskEditableSpy.and.returnValue(false);
@@ -406,7 +408,6 @@ describe('TaskHeaderCloudComponent', () => {
});
describe('Task with candidates', () => {
it('should display candidate groups', async () => {
component.ngOnChanges();
fixture.detectChanges();
@@ -459,7 +460,6 @@ describe('TaskHeaderCloudComponent', () => {
});
describe('Config properties', () => {
it('should show only the properties from the configuration file', async () => {
appConfigService.config = {
'adf-cloud-task-header': {
@@ -508,7 +508,6 @@ describe('TaskHeaderCloudComponent', () => {
});
describe('Task errors', () => {
it('should emit an error when task can not be found', (done) => {
getTaskByIdSpy.and.returnValue(throwError('Task not found'));
@@ -523,7 +522,7 @@ describe('TaskHeaderCloudComponent', () => {
});
it('should emit an error when app name and/or task id are not provided', (done) => {
component.error.subscribe( (err) => {
component.error.subscribe((err) => {
expect(err).toEqual('App Name and Task Id are mandatory');
done();
});
@@ -23,7 +23,6 @@ import { ServiceTaskListCloudComponent } from './service-task-list-cloud.compone
import { fakeServiceTask, fakeCustomSchema } from '../mock/fake-task-response.mock';
import { of } from 'rxjs';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
import { shareReplay, skip } from 'rxjs/operators';
import { ServiceTaskListCloudService } from '../services/service-task-list-cloud.service';
@@ -80,7 +79,7 @@ describe('ServiceTaskListCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
imports: [ProcessServiceCloudTestingModule],
declarations: [EmptyTemplateComponent]
});
appConfig = TestBed.inject(AppConfigService);
@@ -357,7 +356,7 @@ describe('ServiceTaskListCloudComponent: Injecting custom columns for task list
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
imports: [ProcessServiceCloudTestingModule],
declarations: [CustomTaskListComponent, CustomCopyContentTaskListComponent]
});
@@ -415,7 +414,7 @@ describe('ServiceTaskListCloudComponent: Copy cell content directive from app.co
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule]
imports: [ProcessServiceCloudTestingModule]
});
appConfig = TestBed.inject(AppConfigService);
serviceTaskListCloudService = TestBed.inject(ServiceTaskListCloudService);
@@ -18,32 +18,17 @@
import { Component, SimpleChange, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import {
AppConfigService,
DataRowEvent,
ObjectDataRow,
User,
DataColumn,
ColumnsSelectorComponent,
AlfrescoApiService,
AlfrescoApiServiceMock,
AppConfigServiceMock,
TranslationService,
TranslationMock
} from '@alfresco/adf-core';
import { AppConfigService, DataRowEvent, ObjectDataRow, User, DataColumn, ColumnsSelectorComponent } from '@alfresco/adf-core';
import { TaskListCloudService } from '../services/task-list-cloud.service';
import { TaskListCloudComponent } from './task-list-cloud.component';
import { fakeGlobalTasks, fakeCustomSchema, fakeGlobalTask } from '../mock/fake-task-response.mock';
import { of } from 'rxjs';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { TaskListCloudSortingModel } from '../../../models/task-list-sorting.model';
import { shareReplay, skip } from 'rxjs/operators';
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
import { TASK_LIST_CLOUD_TOKEN, TASK_LIST_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { TaskListCloudModule } from '../task-list-cloud.module';
import { HttpClientModule } from '@angular/common/http';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
@@ -117,7 +102,7 @@ describe('TaskListCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
imports: [ProcessServiceCloudTestingModule],
providers: [
{
provide: TASK_LIST_CLOUD_TOKEN,
@@ -515,7 +500,7 @@ describe('TaskListCloudComponent: Injecting custom colums for tasklist - CustomT
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
imports: [ProcessServiceCloudTestingModule],
declarations: [CustomTaskListComponent, CustomCopyContentTaskListComponent]
});
taskListCloudService = TestBed.inject(TASK_LIST_CLOUD_TOKEN);
@@ -569,12 +554,7 @@ describe('TaskListCloudComponent: Creating an empty custom template - EmptyTempl
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientModule, NoopAnimationsModule, TranslateModule.forRoot(), TaskListCloudModule],
providers: [
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
{ provide: AppConfigService, useClass: AppConfigServiceMock },
{ provide: TranslationService, useClass: TranslationMock }
]
imports: [ProcessServiceCloudTestingModule, TaskListCloudModule]
});
taskListCloudService = TestBed.inject(TASK_LIST_CLOUD_TOKEN);
const emptyList = { list: { entries: [] } };
@@ -606,7 +586,7 @@ describe('TaskListCloudComponent: Copy cell content directive from app.config sp
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule]
imports: [ProcessServiceCloudTestingModule]
});
appConfig = TestBed.inject(AppConfigService);
taskListCloudService = TestBed.inject(TASK_LIST_CLOUD_TOKEN);
@@ -16,7 +16,6 @@
*/
import { TestBed } from '@angular/core/testing';
import { LogService } from '@alfresco/adf-core';
import { ServiceTaskListCloudService } from './service-task-list-cloud.service';
import { ServiceTaskQueryCloudRequestModel } from '../models/service-task-cloud.model';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
@@ -24,10 +23,8 @@ import { of } from 'rxjs';
import { AdfHttpClient } from '@alfresco/adf-core/api';
describe('Activiti ServiceTaskList Cloud Service', () => {
let service: ServiceTaskListCloudService;
let adfHttpClient: AdfHttpClient;
let logService: LogService;
let requestSpy: jasmine.Spy;
const returnCallQueryParameters = (_queryUrl, options) => Promise.resolve(options.queryParams);
@@ -36,13 +33,10 @@ describe('Activiti ServiceTaskList Cloud Service', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
ProcessServiceCloudTestingModule
]
imports: [ProcessServiceCloudTestingModule]
});
adfHttpClient = TestBed.inject(AdfHttpClient);
service = TestBed.inject(ServiceTaskListCloudService);
logService = TestBed.inject(LogService);
requestSpy = spyOn(adfHttpClient, 'request');
});
@@ -72,8 +66,14 @@ describe('Activiti ServiceTaskList Cloud Service', () => {
it('should concat the sorting to append as parameters', (done) => {
const taskRequest = {
appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service',
sorting: [{ orderBy: 'NAME', direction: 'DESC' }, { orderBy: 'TITLE', direction: 'ASC' }]
appName: 'fakeName',
skipCount: 0,
maxItems: 20,
service: 'fake-service',
sorting: [
{ orderBy: 'NAME', direction: 'DESC' },
{ orderBy: 'TITLE', direction: 'ASC' }
]
} as ServiceTaskQueryCloudRequestModel;
requestSpy.and.callFake(returnCallQueryParameters);
service.getServiceTaskByRequest(taskRequest).subscribe((res) => {
@@ -88,7 +88,7 @@ describe('Activiti ServiceTaskList Cloud Service', () => {
const taskRequest = { appName: null } as ServiceTaskQueryCloudRequestModel;
requestSpy.and.callFake(returnCallUrl);
service.getServiceTaskByRequest(taskRequest).subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('Appname not configured');
done();
@@ -97,16 +97,11 @@ describe('Activiti ServiceTaskList Cloud Service', () => {
});
describe('run replayServiceTaskRequest method', () => {
let logServiceErrorSpy: jasmine.Spy;
beforeEach(() => {
spyOn(service, 'getBasePath').and.returnValue('http://localhost/fakeName');
requestSpy.and.callFake(returnCallUrl);
logServiceErrorSpy = spyOn(logService, 'error');
});
it('should execute post method if all parameters are provided', async () => {
const expected = {
expectedQueryUrl: 'http://localhost/fakeName/rb/admin/v1/executions/executionId_1/replay/service-task',
@@ -119,49 +114,54 @@ describe('Activiti ServiceTaskList Cloud Service', () => {
const params = ['fakeName', 'executionId_1', 'flowNodeId_1'] as const;
await service.replayServiceTaskRequest(...params).toPromise();
expect(spyOnPost).toHaveBeenCalledWith(expected.expectedQueryUrl, expected.expectedPayload);
expect(logServiceErrorSpy).not.toHaveBeenCalled();
});
it('should throw an exeption and execute logService error if appName is null', (done) => {
const expectedErrorMessage = 'Appname/executionId/flowNodeId not configured';
const params = [null, 'executionId_1', 'flowNodeId_1'] as const;
service.replayServiceTaskRequest(...params).toPromise().catch((error) => {
expect(error).toEqual(expectedErrorMessage);
expect(logServiceErrorSpy).toHaveBeenCalled();
done();
});
service
.replayServiceTaskRequest(...params)
.toPromise()
.catch((error) => {
expect(error).toEqual(expectedErrorMessage);
done();
});
});
it('should throw an exeption and execute logService error if executionId is null', (done) => {
const expectedErrorMessage = 'Appname/executionId/flowNodeId not configured';
const params = ['fakeName', null, 'flowNodeId_1'] as const;
service.replayServiceTaskRequest(...params).toPromise().catch((error) => {
expect(error).toEqual(expectedErrorMessage);
expect(logServiceErrorSpy).toHaveBeenCalled();
done();
});
service
.replayServiceTaskRequest(...params)
.toPromise()
.catch((error) => {
expect(error).toEqual(expectedErrorMessage);
done();
});
});
it('should throw an exeption and execute logService error if flowNodeId is null', (done) => {
const expectedErrorMessage = 'Appname/executionId/flowNodeId not configured';
const params = ['fakeName', 'executionId_1', null] as const;
service.replayServiceTaskRequest(...params).toPromise().catch((error) => {
expect(error).toEqual(expectedErrorMessage);
expect(logServiceErrorSpy).toHaveBeenCalled();
done();
});
service
.replayServiceTaskRequest(...params)
.toPromise()
.catch((error) => {
expect(error).toEqual(expectedErrorMessage);
done();
});
});
it('should throw an exeption and execute logService error if appName, executionId and flowNodeId are null', (done) => {
const expectedErrorMessage = 'Appname/executionId/flowNodeId not configured';
const params = [null, null, null] as const;
service.replayServiceTaskRequest(...params).toPromise().catch((error) => {
expect(error).toEqual(expectedErrorMessage);
expect(logServiceErrorSpy).toHaveBeenCalled();
done();
});
service
.replayServiceTaskRequest(...params)
.toPromise()
.catch((error) => {
expect(error).toEqual(expectedErrorMessage);
done();
});
});
});
});
@@ -40,7 +40,6 @@ export class ServiceTaskListCloudService extends BaseCloudService {
}
return this.get(queryUrl, queryParams);
} else {
this.logService.error('Appname is mandatory for querying task');
return throwError('Appname not configured');
}
}
@@ -55,11 +54,8 @@ export class ServiceTaskListCloudService extends BaseCloudService {
getServiceTaskStatus(appName: string, serviceTaskId: string): Observable<ServiceTaskIntegrationContextCloudModel> {
if (appName) {
const queryUrl = `${this.getBasePath(appName)}/query/admin/v1/service-tasks/${serviceTaskId}/integration-context`;
return this.get(queryUrl).pipe(
map((response: any) => response.entry)
);
return this.get(queryUrl).pipe(map((response: any) => response.entry));
} else {
this.logService.error('Appname is mandatory for querying task');
return throwError('Appname not configured');
}
}
@@ -78,7 +74,6 @@ export class ServiceTaskListCloudService extends BaseCloudService {
const queryUrl = `${this.getBasePath(appName)}/rb/admin/v1/executions/${executionId}/replay/service-task`;
return this.post(queryUrl, payload);
} else {
this.logService.error('Appname, executionId and flowNodeId are mandatory to replaying a service task');
return throwError('Appname/executionId/flowNodeId not configured');
}
}
@@ -86,9 +81,11 @@ export class ServiceTaskListCloudService extends BaseCloudService {
protected buildQueryParams(requestNode: ServiceTaskQueryCloudRequestModel): any {
const queryParam: any = {};
for (const property in requestNode) {
if (Object.prototype.hasOwnProperty.call(requestNode, property) &&
if (
Object.prototype.hasOwnProperty.call(requestNode, property) &&
!this.isExcludedField(property) &&
this.isPropertyValueValid(requestNode, property)) {
this.isPropertyValueValid(requestNode, property)
) {
queryParam[property] = requestNode[property];
}
}
@@ -19,11 +19,9 @@ import { TestBed } from '@angular/core/testing';
import { TaskListCloudService } from './task-list-cloud.service';
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { AdfHttpClient } from '@alfresco/adf-core/api';
describe('TaskListCloudService', () => {
let service: TaskListCloudService;
let adfHttpClient: AdfHttpClient;
let requestSpy: jasmine.Spy;
@@ -34,10 +32,7 @@ describe('TaskListCloudService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [ProcessServiceCloudTestingModule]
});
adfHttpClient = TestBed.inject(AdfHttpClient);
service = TestBed.inject(TaskListCloudService);
@@ -69,8 +64,16 @@ describe('TaskListCloudService', () => {
});
it('should concat the sorting to append as parameters', (done) => {
const taskRequest = { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service',
sorting: [{ orderBy: 'NAME', direction: 'DESC'}, { orderBy: 'TITLE', direction: 'ASC'}] } as TaskQueryCloudRequestModel;
const taskRequest = {
appName: 'fakeName',
skipCount: 0,
maxItems: 20,
service: 'fake-service',
sorting: [
{ orderBy: 'NAME', direction: 'DESC' },
{ orderBy: 'TITLE', direction: 'ASC' }
]
} as TaskQueryCloudRequestModel;
requestSpy.and.callFake(returnCallQueryParameters);
service.getTaskByRequest(taskRequest).subscribe((res) => {
expect(res).toBeDefined();
@@ -84,7 +87,7 @@ describe('TaskListCloudService', () => {
const taskRequest = { appName: null } as TaskQueryCloudRequestModel;
requestSpy.and.callFake(returnCallUrl);
service.getTaskByRequest(taskRequest).subscribe(
() => { },
() => {},
(error) => {
expect(error).toBe('Appname not configured');
done();
@@ -52,7 +52,6 @@ export class TaskListCloudService extends BaseCloudService implements TaskListCl
})
);
} else {
this.logService.error('Appname is mandatory for querying task');
return throwError('Appname not configured');
}
}