[AAE-13800] - Avoid reloading task/process list when column visibility changes (#8499)

* Fixing rebase conflicts

* AAE-13310: Fixing lint issues

* AAE-13800: Avoid reloading tasks list component when column visibility changes, improved unit tests

* AAE-13800: Avoid reloading process list when column visibility changes, improving unit tests

* AAE-13800: Removing extra code from unit tests

* AAE-13800: updated obserable and unit tests in service tasks component

* AAE-13800: Updated service tasks reload method

* AAE-13800: Improved unit test

* AAE-13800: Removed unnecessary unit test

* AAE-13800: Removed extra subscription from a unit test

* AAE-13800: Replacing component reload with ngOnChanges as suggested in PR review

* AAE-13800: Adding done to the unit tests with a subscription

* AAE-13800: Removing extra spy

* AAE-13800: using ngHooks instead of calling directly component methods

* AAE-13800: code clean-up

* AAE-13800: making onDestroy subject private to each component

* AAE-13800: Code improvements

* AAE-13800: Code refactoring

* AAE-13800: Added more unit tests

* AAE-13800: Fixing lint issues
This commit is contained in:
Ehsan Rezaei
2023-05-05 10:45:29 +02:00
committed by GitHub
parent c26915ae3f
commit 23149cae58
7 changed files with 222 additions and 212 deletions

View File

@@ -364,10 +364,8 @@ describe('ProcessListCloudComponent', () => {
it('should re-create columns when a column width gets changed', () => {
component.isResizingEnabled = true;
component.appName = 'FAKE-APP-NAME';
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
fixture.detectChanges();
component.reload();
fixture.detectChanges();
@@ -421,9 +419,6 @@ describe('ProcessListCloudComponent', () => {
});
it('should re-create columns when a column order gets changed', () => {
component.appName = 'FAKE-APP-NAME';
fixture.detectChanges();
component.reload();
fixture.detectChanges();
@@ -437,6 +432,33 @@ describe('ProcessListCloudComponent', () => {
expect(component.columns[1].title).toBe('ADF_CLOUD_PROCESS_LIST.PROPERTIES.NAME');
});
it('should create datatable schema when a column visibility gets changed', () => {
component.ngAfterContentInit();
spyOn(component, 'createDatatableSchema');
component.onColumnsVisibilityChange(component.columns);
fixture.detectChanges();
expect(component.createDatatableSchema).toHaveBeenCalled();
});
it('should call endpoint when a column visibility gets changed', () => {
spyOn(preferencesService, 'updatePreference').and.returnValue(of({}));
spyOn(processListCloudService, 'getProcessByRequest');
component.ngAfterContentInit();
spyOn(component, 'createDatatableSchema');
component.appName = 'fake-app-name';
component.reload();
fixture.detectChanges();
component.onColumnsVisibilityChange(component.columns);
fixture.detectChanges();
expect(processListCloudService.getProcessByRequest).toHaveBeenCalledTimes(1);
});
describe('component changes', () => {
beforeEach(() => {
@@ -515,12 +537,12 @@ describe('ProcessListCloudComponent', () => {
const skipCount = component.skipCount;
component.pagination.pipe(skip(3))
.subscribe((updatedPagination) => {
fixture.detectChanges();
expect(component.size).toBe(size);
expect(component.skipCount).toBe(skipCount);
expect(updatedPagination.maxItems).toEqual(size);
expect(updatedPagination.skipCount).toEqual(skipCount);
done();
fixture.detectChanges();
expect(component.size).toBe(size);
expect(component.skipCount).toBe(skipCount);
expect(updatedPagination.maxItems).toEqual(size);
expect(updatedPagination.skipCount).toEqual(skipCount);
done();
});
const pagination = {
@@ -546,12 +568,12 @@ describe('ProcessListCloudComponent', () => {
};
component.pagination.pipe(skip(1))
.subscribe((updatedPagination) => {
fixture.detectChanges();
expect(component.size).toBe(pagination.maxItems);
expect(component.skipCount).toBe(pagination.skipCount);
expect(updatedPagination.maxItems).toEqual(pagination.maxItems);
expect(updatedPagination.skipCount).toEqual(pagination.skipCount);
done();
fixture.detectChanges();
expect(component.size).toBe(pagination.maxItems);
expect(component.skipCount).toBe(pagination.skipCount);
expect(updatedPagination.maxItems).toEqual(pagination.maxItems);
expect(updatedPagination.skipCount).toEqual(pagination.skipCount);
done();
});
component.updatePagination(pagination);
@@ -634,12 +656,10 @@ describe('ProcessListCloudComponent', () => {
fixtureEmpty.destroy();
});
it('should render the custom template', async () => {
const emptyList = {list: {entries: []}};
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(emptyList));
it('should render the custom template', () => {
fixtureEmpty.componentInstance.processListCloud.isLoading = false;
fixtureEmpty.detectChanges();
await fixtureEmpty.whenStable();
expect(fixtureEmpty.debugElement.query(By.css('#custom-id'))).not.toBeNull();
expect(fixtureEmpty.debugElement.query(By.css('.adf-empty-content'))).toBeNull();

View File

@@ -21,11 +21,11 @@ import { DataTableSchema, PaginatedComponent,
UserPreferencesService, PaginationModel,
UserPreferenceValues, DataRowEvent, CustomLoadingContentTemplateDirective, DataCellEvent, DataRowActionEvent, DataTableComponent, DataColumn } from '@alfresco/adf-core';
import { ProcessListCloudService } from '../services/process-list-cloud.service';
import { BehaviorSubject, of } from 'rxjs';
import { BehaviorSubject, Subject, of } from 'rxjs';
import { processCloudPresetsDefaultModel } from '../models/process-cloud-preset.model';
import { ProcessQueryCloudRequestModel } from '../models/process-cloud-query-request.model';
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
import { map, switchMap, take, tap } from 'rxjs/operators';
import { map, switchMap, take, takeUntil, tap } from 'rxjs/operators';
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { ProcessListCloudPreferences } from '../models/process-cloud-preferences';
@@ -202,6 +202,8 @@ export class ProcessListCloudComponent extends DataTableSchema<ProcessListDataCo
@Output()
success: EventEmitter<any> = new EventEmitter<any>();
private onDestroy$ = new Subject<boolean>();
pagination: BehaviorSubject<PaginationModel>;
size: number;
skipCount: number = 0;
@@ -269,6 +271,11 @@ export class ProcessListCloudComponent extends DataTableSchema<ProcessListDataCo
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
ngOnChanges(changes: SimpleChanges) {
if (this.isPropertyChanged(changes, 'sorting')) {
this.formatSorting(changes['sorting'].currentValue);
@@ -294,10 +301,10 @@ export class ProcessListCloudComponent extends DataTableSchema<ProcessListDataCo
this.isLoading = true;
this.isColumnSchemaCreated$.pipe(
take(1),
switchMap(() => of(this.createRequestNode())),
tap((requestNode) => this.requestNode = requestNode),
switchMap((requestNode) => this.processListCloudService.getProcessByRequest(requestNode))
switchMap((requestNode) => this.processListCloudService.getProcessByRequest(requestNode)),
takeUntil(this.onDestroy$)
).subscribe((processes) => {
this.rows = this.variableMapperService.mapVariablesByColumnTitle(
processes.list.entries,
@@ -386,7 +393,7 @@ export class ProcessListCloudComponent extends DataTableSchema<ProcessListDataCo
}, {});
this.createColumns();
this.reload();
this.createDatatableSchema();
if (this.appName) {
this.cloudPreferenceService.updatePreference(

View File

@@ -303,6 +303,7 @@ export abstract class BaseTaskListCloudComponent<T = unknown> extends DataTableS
}, {});
this.createColumns();
this.createDatatableSchema();
if (this.appName) {
this.cloudPreferenceService.updatePreference(
@@ -311,8 +312,6 @@ export abstract class BaseTaskListCloudComponent<T = unknown> extends DataTableS
this.columnsVisibility
);
}
this.reload();
}
onColumnsWidthChanged(columns: DataColumn[]): void {

View File

@@ -16,7 +16,7 @@
*/
import { Component, SimpleChange, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { AppConfigService, setupTestBed, DataRowEvent, ObjectDataRow, User } from '@alfresco/adf-core';
import { ServiceTaskListCloudComponent } from './service-task-list-cloud.component';
@@ -179,9 +179,8 @@ describe('ServiceTaskListCloudComponent', () => {
expect(component.isListEmpty()).toBeTruthy();
});
it('should return the results if an application name is given', (done) => {
it('should reload tasks when reload() is called', (done) => {
spyOn(serviceTaskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(component.rows).toBeDefined();
@@ -202,22 +201,9 @@ describe('ServiceTaskListCloudComponent', () => {
expect(component.rows[0]['serviceName']).toBe('simpleapp-rb');
done();
});
component.appName = appName.currentValue;
component.ngOnChanges({ appName });
fixture.detectChanges();
});
it('should reload tasks when reload() is called', (done) => {
component.appName = 'fake';
spyOn(serviceTaskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(component.rows).toBeDefined();
expect(component.isListEmpty()).not.toBeTruthy();
done();
});
fixture.detectChanges();
component.reload();
fixture.detectChanges();
});
it('should emit row click event', (done) => {
@@ -231,6 +217,32 @@ describe('ServiceTaskListCloudComponent', () => {
component.onRowClick(rowEvent);
});
it('should create datatable schema when a column visibility gets changed', () => {
component.ngAfterContentInit();
spyOn(component, 'createDatatableSchema');
component.onColumnsVisibilityChange(component.columns);
fixture.detectChanges();
expect(component.createDatatableSchema).toHaveBeenCalled();
});
it('should call endpoint when a column visibility gets changed', () => {
spyOn(serviceTaskListCloudService, 'getServiceTaskByRequest');
component.ngAfterContentInit();
spyOn(component, 'createDatatableSchema');
component.appName = 'fake-app-name';
component.reload();
fixture.detectChanges();
component.onColumnsVisibilityChange(component.columns);
fixture.detectChanges();
expect(serviceTaskListCloudService.getServiceTaskByRequest).toHaveBeenCalledTimes(1);
});
describe('component changes', () => {
beforeEach(() => {
@@ -302,10 +314,6 @@ describe('ServiceTaskListCloudComponent', () => {
it('should reset pagination when resetPaginationValues is called', (done) => {
spyOn(serviceTaskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.ngOnChanges({ appName });
fixture.detectChanges();
const size = component.size;
const skipCount = component.skipCount;
component.pagination.pipe(skip(3))
@@ -323,17 +331,13 @@ describe('ServiceTaskListCloudComponent', () => {
skipCount: 200
};
component.updatePagination(pagination);
fixture.whenStable().then( () => {
component.resetPagination();
});
component.resetPagination();
});
it('should set pagination and reload when updatePagination is called', (done) => {
spyOn(serviceTaskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
spyOn(component, 'reload').and.stub();
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.ngOnChanges({ appName });
fixture.detectChanges();
const pagination = {
maxItems: 250,
@@ -357,7 +361,6 @@ describe('ServiceTaskListCloudComponent', () => {
let fixtureCustom: ComponentFixture<CustomTaskListComponent>;
let componentCustom: CustomTaskListComponent;
let customCopyComponent: CustomCopyContentTaskListComponent;
let element: HTMLElement;
let copyFixture: ComponentFixture<CustomCopyContentTaskListComponent>;
setupTestBed({
@@ -378,8 +381,6 @@ describe('ServiceTaskListCloudComponent', () => {
fixtureCustom.detectChanges();
componentCustom = fixtureCustom.componentInstance;
customCopyComponent = copyFixture.componentInstance;
element = copyFixture.debugElement.nativeElement;
customCopyComponent.taskList.isColumnSchemaCreated$ = of(true);
});
@@ -396,42 +397,32 @@ describe('ServiceTaskListCloudComponent', () => {
expect(componentCustom.taskList.columns.length).toEqual(2);
});
it('it should show copy tooltip when key is present in data-colunn', fakeAsync(() => {
it('it should show copy tooltip when key is present in data-column', () => {
customCopyComponent.taskList.reload();
copyFixture.detectChanges();
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
copyFixture.whenStable().then(() => {
copyFixture.detectChanges();
const spanHTMLElement = element.querySelector<HTMLInputElement>('span[title="04fdf69f-4ddd-48ab-9563-da776c9b163c"]');
spanHTMLElement.dispatchEvent(new Event('mouseenter'));
copyFixture.detectChanges();
expect(copyFixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull();
});
customCopyComponent.taskList.appName = appName.currentValue;
customCopyComponent.taskList.ngOnChanges({ appName });
copyFixture.detectChanges();
}));
it('it should not show copy tooltip when key is not present in data-column', (done) => {
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
customCopyComponent.taskList.success.subscribe(() => {
copyFixture.whenStable().then(() => {
copyFixture.detectChanges();
const spanHTMLElement = element.querySelector<HTMLInputElement>('span[title="serviceTaskName"]');
spanHTMLElement.dispatchEvent(new Event('mouseenter'));
copyFixture.detectChanges();
expect(copyFixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).toBeNull();
done();
});
});
customCopyComponent.taskList.appName = appName.currentValue;
customCopyComponent.taskList.ngOnChanges({ appName });
copyFixture.debugElement
.query(By.css('span[title="04fdf69f-4ddd-48ab-9563-da776c9b163c"]'))
.triggerEventHandler('mouseenter');
copyFixture.detectChanges();
expect(copyFixture.debugElement.query(By.css('.adf-copy-tooltip'))).not.toBeNull();
});
it('it should not show copy tooltip when key is not present in data-column', () => {
customCopyComponent.taskList.reload();
copyFixture.detectChanges();
copyFixture.debugElement
.query(By.css('span[title="serviceTaskName"]'))
.triggerEventHandler('mouseenter');
copyFixture.detectChanges();
expect(copyFixture.debugElement.query(By.css('.adf-copy-tooltip'))).toBeNull();
});
});
describe('Copy cell content directive from app.config specifications', () => {
let element: HTMLElement;
let taskSpy: jasmine.Spy;
setupTestBed({
@@ -467,7 +458,6 @@ describe('ServiceTaskListCloudComponent', () => {
});
fixture = TestBed.createComponent(ServiceTaskListCloudComponent);
component = fixture.componentInstance;
element = fixture.debugElement.nativeElement;
taskSpy = spyOn(serviceTaskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
});
@@ -475,42 +465,36 @@ describe('ServiceTaskListCloudComponent', () => {
fixture.destroy();
});
it('shoud show tooltip if config copyContent flag is true', fakeAsync(() => {
it('shoud show tooltip if config copyContent flag is true', () => {
taskSpy.and.returnValue(of(fakeServiceTask));
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.success.subscribe(() => {
fixture.whenStable().then(() => {
fixture.detectChanges();
const spanHTMLElement = element.querySelector<HTMLInputElement>('span[title="04fdf69f-4ddd-48ab-9563-da776c9b163c"]');
spanHTMLElement.dispatchEvent(new Event('mouseenter'));
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull();
});
});
component.presetColumn = 'fakeCustomSchema';
component.appName = appName.currentValue;
component.ngOnChanges({ appName });
component.ngAfterContentInit();
}));
it('shoud not show tooltip if config copyContent flag is true', fakeAsync(() => {
component.reload();
fixture.detectChanges();
const columnWithCopyContentFlagTrue = fixture.debugElement
.query(By.css('span[title="04fdf69f-4ddd-48ab-9563-da776c9b163c"]'));
columnWithCopyContentFlagTrue.triggerEventHandler('mouseenter');
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull();
});
it('shoud not show tooltip if config copyContent flag is NOT true', () => {
taskSpy.and.returnValue(of(fakeServiceTask));
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.success.subscribe(() => {
fixture.whenStable().then(() => {
fixture.detectChanges();
const spanHTMLElement = element.querySelector<HTMLInputElement>('span[title="serviceTaskName"]');
spanHTMLElement.dispatchEvent(new Event('mouseenter'));
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).toBeNull();
});
});
component.presetColumn = 'fakeCustomSchema';
component.appName = appName.currentValue;
component.ngOnChanges({ appName });
component.ngAfterContentInit();
}));
component.reload();
fixture.detectChanges();
const columnWithCopyContentFlagNotTrue = fixture.debugElement
.query(By.css('span[title="serviceTaskName"]'));
columnWithCopyContentFlagNotTrue.triggerEventHandler('mouseenter');
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).toBeNull();
});
});
});

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, ViewEncapsulation, Input, Inject } from '@angular/core';
import { Component, ViewEncapsulation, Input, Inject, OnDestroy } from '@angular/core';
import {
AppConfigService, UserPreferencesService
} from '@alfresco/adf-core';
@@ -23,9 +23,9 @@ import { ServiceTaskQueryCloudRequestModel } from '../models/service-task-cloud.
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
import { ServiceTaskListCloudService } from '../services/service-task-list-cloud.service';
import { TaskCloudService } from '../../services/task-cloud.service';
import { combineLatest } from 'rxjs';
import { Subject, combineLatest } from 'rxjs';
import { PreferenceCloudServiceInterface, TASK_LIST_PREFERENCES_SERVICE_TOKEN } from '../../../services/public-api';
import { take } from 'rxjs/operators';
import { takeUntil } from 'rxjs/operators';
const PRESET_KEY = 'adf-cloud-service-task-list.presets';
@@ -35,10 +35,12 @@ const PRESET_KEY = 'adf-cloud-service-task-list.presets';
styleUrls: ['./base-task-list-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ServiceTaskListCloudComponent extends BaseTaskListCloudComponent {
export class ServiceTaskListCloudComponent extends BaseTaskListCloudComponent implements OnDestroy {
@Input()
queryParams: { [key: string]: any } = {};
private onDestroyServiceTaskList$ = new Subject<boolean>();
constructor(private serviceTaskListCloudService: ServiceTaskListCloudService,
appConfigService: AppConfigService,
taskCloudService: TaskCloudService,
@@ -48,6 +50,11 @@ export class ServiceTaskListCloudComponent extends BaseTaskListCloudComponent {
super(appConfigService, taskCloudService, userPreferences, PRESET_KEY, cloudPreferenceService);
}
ngOnDestroy() {
this.onDestroyServiceTaskList$.next(true);
this.onDestroyServiceTaskList$.complete();
}
reload() {
this.requestNode = this.createRequestNode();
@@ -57,7 +64,7 @@ export class ServiceTaskListCloudComponent extends BaseTaskListCloudComponent {
this.serviceTaskListCloudService.getServiceTaskByRequest(this.requestNode),
this.isColumnSchemaCreated$
]).pipe(
take(1)
takeUntil(this.onDestroyServiceTaskList$)
).subscribe(
([tasks]) => {
this.rows = tasks.list.entries;

View File

@@ -16,7 +16,7 @@
*/
import { Component, SimpleChange, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { AppConfigService,
setupTestBed,
@@ -167,7 +167,6 @@ describe('TaskListCloudComponent', () => {
it('should display empty content when process list is empty', () => {
const emptyList = { list: { entries: [] } };
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(emptyList));
fixture.detectChanges();
expect(component.isLoading).toBe(false);
@@ -256,9 +255,7 @@ describe('TaskListCloudComponent', () => {
it('should return the results if an application name is given', (done) => {
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
component.ngAfterContentInit();
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(component.rows).toBeDefined();
@@ -273,22 +270,9 @@ describe('TaskListCloudComponent', () => {
expect(component.rows[0]).toEqual(expectedTask);
done();
});
component.appName = appName.currentValue;
component.ngOnChanges({ appName });
fixture.detectChanges();
});
it('should reload tasks when reload() is called', (done) => {
component.appName = 'fake';
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(component.rows).toBeDefined();
expect(component.isListEmpty()).not.toBeTruthy();
done();
});
fixture.detectChanges();
component.reload();
fixture.detectChanges();
});
it('should emit row click event', (done) => {
@@ -369,6 +353,32 @@ describe('TaskListCloudComponent', () => {
expect(component.columns[2].title).toBe('ADF_CLOUD_TASK_LIST.PROPERTIES.ASSIGNEE');
});
it('should create datatable schema when a column visibility gets changed', () => {
component.ngAfterContentInit();
spyOn(component, 'createDatatableSchema');
component.onColumnsVisibilityChange(component.columns);
fixture.detectChanges();
expect(component.createDatatableSchema).toHaveBeenCalled();
});
it('should call endpoint when a column visibility gets changed', () => {
spyOn(taskListCloudService, 'getTaskByRequest');
component.ngAfterContentInit();
spyOn(component, 'createDatatableSchema');
component.appName = 'fake-app-name';
component.reload();
fixture.detectChanges();
component.onColumnsVisibilityChange(component.columns);
fixture.detectChanges();
expect(taskListCloudService.getTaskByRequest).toHaveBeenCalledTimes(1);
});
describe('component changes', () => {
beforeEach(() => {
@@ -449,10 +459,6 @@ describe('TaskListCloudComponent', () => {
it('should reset pagination when resetPaginationValues is called', (done) => {
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.ngOnChanges({ appName });
fixture.detectChanges();
const size = component.size;
const skipCount = component.skipCount;
component.pagination.pipe(skip(3))
@@ -470,17 +476,13 @@ describe('TaskListCloudComponent', () => {
skipCount: 200
};
component.updatePagination(pagination);
fixture.whenStable().then( () => {
component.resetPagination();
});
component.resetPagination();
});
it('should set pagination and reload when updatePagination is called', (done) => {
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
spyOn(component, 'reload').and.stub();
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.ngOnChanges({ appName });
fixture.detectChanges();
const pagination = {
maxItems: 250,
@@ -504,7 +506,6 @@ describe('TaskListCloudComponent', () => {
let fixtureCustom: ComponentFixture<CustomTaskListComponent>;
let componentCustom: CustomTaskListComponent;
let customCopyComponent: CustomCopyContentTaskListComponent;
let element: HTMLElement;
let copyFixture: ComponentFixture<CustomCopyContentTaskListComponent>;
setupTestBed({
@@ -525,8 +526,6 @@ describe('TaskListCloudComponent', () => {
fixtureCustom.detectChanges();
componentCustom = fixtureCustom.componentInstance;
customCopyComponent = copyFixture.componentInstance;
element = copyFixture.debugElement.nativeElement;
customCopyComponent.taskList.isColumnSchemaCreated$ = of(true);
});
@@ -536,43 +535,35 @@ describe('TaskListCloudComponent', () => {
});
it('should fetch custom schemaColumn from html', () => {
fixture.detectChanges();
copyFixture.detectChanges();
expect(componentCustom.taskList.columnList).toBeDefined();
expect(componentCustom.taskList.columns[0]['title']).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.NAME');
expect(componentCustom.taskList.columns[1]['title']).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED');
expect(componentCustom.taskList.columns.length).toEqual(3);
});
it('it should show copy tooltip when key is present in data-colunn', fakeAsync(() => {
it('it should show copy tooltip when key is present in data-column', () => {
customCopyComponent.taskList.reload();
copyFixture.detectChanges();
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
copyFixture.whenStable().then(() => {
copyFixture.detectChanges();
const spanHTMLElement = element.querySelector<HTMLInputElement>('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]');
spanHTMLElement.dispatchEvent(new Event('mouseenter'));
copyFixture.detectChanges();
expect(copyFixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull();
});
customCopyComponent.taskList.appName = appName.currentValue;
customCopyComponent.taskList.ngOnChanges({ appName });
copyFixture.detectChanges();
}));
it('it should not show copy tooltip when key is not present in data-column', (done) => {
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
customCopyComponent.taskList.success.subscribe(() => {
copyFixture.whenStable().then(() => {
copyFixture.detectChanges();
const spanHTMLElement = element.querySelector<HTMLInputElement>('span[title="standalone-subtask"]');
spanHTMLElement.dispatchEvent(new Event('mouseenter'));
copyFixture.detectChanges();
expect(copyFixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).toBeNull();
done();
});
});
customCopyComponent.taskList.appName = appName.currentValue;
customCopyComponent.taskList.ngOnChanges({ appName });
copyFixture.debugElement
.query(By.css('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'))
.triggerEventHandler('mouseenter');
copyFixture.detectChanges();
expect(copyFixture.debugElement.query(By.css('.adf-copy-tooltip'))).not.toBeNull();
});
it('it should not show copy tooltip when key is not present in data-column', () => {
customCopyComponent.taskList.reload();
copyFixture.detectChanges();
copyFixture.debugElement
.query(By.css('span[title="standalone-subtask"]'))
.triggerEventHandler('mouseenter');
copyFixture.detectChanges();
expect(copyFixture.debugElement.query(By.css('.adf-copy-tooltip'))).toBeNull();
});
});
@@ -615,8 +606,6 @@ describe('TaskListCloudComponent', () => {
});
describe('Copy cell content directive from app.config specifications', () => {
let element: HTMLElement;
let taskSpy: jasmine.Spy;
setupTestBed({
@@ -658,9 +647,7 @@ describe('TaskListCloudComponent', () => {
});
fixture = TestBed.createComponent(TaskListCloudComponent);
component = fixture.componentInstance;
element = fixture.debugElement.nativeElement;
taskSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
component.isColumnSchemaCreated$ = of(true);
});
@@ -668,34 +655,33 @@ describe('TaskListCloudComponent', () => {
fixture.destroy();
});
it('should show tooltip if config copyContent flag is true', fakeAsync(() => {
it('should show tooltip if config copyContent flag is true', () => {
taskSpy.and.returnValue(of(fakeGlobalTasks));
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.presetColumn = 'fakeCustomSchema';
component.appName = appName.currentValue;
component.ngOnChanges({ appName });
component.ngAfterContentInit();
tick();
component.reload();
fixture.detectChanges();
const spanHTMLElement = element.querySelector<HTMLInputElement>('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]');
spanHTMLElement.dispatchEvent(new Event('mouseenter'));
const columnWithCopyContentFlagTrue = fixture.debugElement
.query(By.css('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'));
columnWithCopyContentFlagTrue.triggerEventHandler('mouseenter');
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull();
}));
});
it('should replace priority values', fakeAsync(() => {
it('should replace priority values', () => {
taskSpy.and.returnValue(of(fakeGlobalTasks));
component.presetColumn = 'fakeCustomSchema';
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.ngOnChanges({ appName });
fixture.detectChanges();
component.reload();
tick();
const cell = fixture.nativeElement.querySelector('[data-automation-id="text_ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE"]');
expect(cell.textContent).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE');
}));
fixture.detectChanges();
const cell = fixture.debugElement
.query(By.css('[data-automation-id="text_ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE"]'));
expect(cell.nativeElement.textContent).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE');
});
it('replacePriorityValues should return undefined when no rows defined', () => {
const emptyList = { list: { entries: [] } };

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, ViewEncapsulation, Input, Inject } from '@angular/core';
import { Component, ViewEncapsulation, Input, Inject, OnDestroy } from '@angular/core';
import { AppConfigService, UserPreferencesService } from '@alfresco/adf-core';
import { TaskQueryCloudRequestModel } from '../../../models/filter-cloud-model';
import { BaseTaskListCloudComponent } from './base-task-list-cloud.component';
@@ -23,8 +23,8 @@ import { TaskCloudService } from '../../services/task-cloud.service';
import { TASK_LIST_CLOUD_TOKEN, TASK_LIST_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
import { TaskListCloudServiceInterface } from '../../../services/task-list-cloud.service.interface';
import { of } from 'rxjs';
import { switchMap, take, tap } from 'rxjs/operators';
import { Subject, of } from 'rxjs';
import { switchMap, takeUntil, tap } from 'rxjs/operators';
import { VariableMapperService } from '../../../services/variable-mapper.sevice';
import { ProcessListDataColumnCustomData } from '../../../models/data-column-custom-data';
import { TaskCloudModel } from '../../../models/task-cloud.model';
@@ -40,7 +40,7 @@ const PRESET_KEY = 'adf-cloud-task-list.presets';
styleUrls: ['./base-task-list-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessListDataColumnCustomData> {
export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessListDataColumnCustomData> implements OnDestroy {
/**
* The assignee of the process. Possible values are: "assignee" (the current user is the assignee),
* "candidate" (the current user is a task candidate", "group_x" (the task is assigned to a group
@@ -145,6 +145,8 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessLi
@Input()
candidateGroupId: string = '';
private onDestroyTaskList$ = new Subject<boolean>();
rows: TaskInstanceCloudListViewModel[] = [];
dataAdapter: TasksListDatatableAdapter | undefined;
@@ -158,14 +160,19 @@ export class TaskListCloudComponent extends BaseTaskListCloudComponent<ProcessLi
super(appConfigService, taskCloudService, userPreferences, PRESET_KEY, cloudPreferenceService);
}
ngOnDestroy() {
this.onDestroyTaskList$.next(true);
this.onDestroyTaskList$.complete();
}
reload() {
this.isLoading = true;
this.isColumnSchemaCreated$.pipe(
take(1),
switchMap(() => of(this.createRequestNode())),
tap((requestNode) => this.requestNode = requestNode),
switchMap((requestNode) => this.taskListCloudService.getTaskByRequest(requestNode))
switchMap((requestNode) => this.taskListCloudService.getTaskByRequest(requestNode)),
takeUntil(this.onDestroyTaskList$)
).subscribe((tasks: { list: PaginatedEntries<TaskCloudModel> }) => {
const tasksWithVariables = tasks.list.entries.map((task) => ({
...task,