mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ACS-6140] migrate tests to harness (#9071)
* migrate aspect list tests to harness * [ci:force] categories management * [ci:force] fix keyboard handling * [ci:force] fix memory leak * migrate document list * migrate new version uploader dialog * migrate folder dialog * bug fixes for keyboard, remove fake unit tests * [ci:force] migrate and cleanup notification tests * migrate app details cloud * migrate app list cloud * migrate group cloud component * [ci:force] cleanup code based on reviews * [ci:force] migrate people cloud * [ci:force] migrate process list cloud * [ci:force] migrate start process cloud * [ci:force] task form cloud * [ci:force] service task list cloud * [ci:force] task list cloud * [ci:force] process attachment list and apps list * [ci:force] code review changes * [ci:force] app list bug fixes and code cleanup * [ci:force] fix incorrect/missing typings, fix tests * [ci:force] code cleanup
This commit is contained in:
@@ -35,7 +35,7 @@
|
||||
|
||||
<ng-container *ngIf="isLoading(); else empty">
|
||||
<div class="adf-app-list-spinner">
|
||||
<mat-spinner></mat-spinner>
|
||||
<mat-progress-spinner mode="indeterminate"></mat-progress-spinner>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
|
@@ -20,15 +20,17 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { AppsProcessService } from './services/apps-process.service';
|
||||
import { of, throwError } from 'rxjs';
|
||||
|
||||
import { defaultApp, deployedApps, nonDeployedApps } from '../mock/apps-list.mock';
|
||||
import { AppsListComponent, APP_LIST_LAYOUT_GRID, APP_LIST_LAYOUT_LIST } from './apps-list.component';
|
||||
import { ProcessTestingModule } from '../testing/process.testing.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { AppDefinitionRepresentationModel } from '../task-list';
|
||||
import { HarnessLoader } from '@angular/cdk/testing';
|
||||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
|
||||
|
||||
describe('AppsListComponent', () => {
|
||||
|
||||
let loader: HarnessLoader;
|
||||
let component: AppsListComponent;
|
||||
let fixture: ComponentFixture<AppsListComponent>;
|
||||
let debugElement: DebugElement;
|
||||
@@ -37,22 +39,18 @@ describe('AppsListComponent', () => {
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<adf-apps>
|
||||
<adf-custom-empty-content-template>
|
||||
<p id="custom-id">No Apps</p>
|
||||
</adf-custom-empty-content-template>
|
||||
</adf-apps>
|
||||
<adf-apps>
|
||||
<adf-custom-empty-content-template>
|
||||
<p id="custom-id">No Apps</p>
|
||||
</adf-custom-empty-content-template>
|
||||
</adf-apps>
|
||||
`
|
||||
})
|
||||
class CustomEmptyAppListTemplateComponent {
|
||||
}
|
||||
class CustomEmptyAppListTemplateComponent {}
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
ProcessTestingModule
|
||||
],
|
||||
imports: [TranslateModule.forRoot(), ProcessTestingModule],
|
||||
declarations: [CustomEmptyAppListTemplateComponent]
|
||||
});
|
||||
fixture = TestBed.createComponent(AppsListComponent);
|
||||
@@ -61,6 +59,7 @@ describe('AppsListComponent', () => {
|
||||
|
||||
service = TestBed.inject(AppsProcessService);
|
||||
getAppsSpy = spyOn(service, 'getDeployedApplications').and.returnValue(of(deployedApps));
|
||||
loader = TestbedHarnessEnvironment.documentRootLoader(fixture);
|
||||
});
|
||||
|
||||
it('should define layoutType with the default value', () => {
|
||||
@@ -79,17 +78,16 @@ describe('AppsListComponent', () => {
|
||||
});
|
||||
|
||||
it('should show the loading spinner when the apps are loading', async () => {
|
||||
component.loading = true;
|
||||
spyOn(component, 'isLoading').and.returnValue(true);
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
const loadingSpinner = fixture.nativeElement.querySelector('mat-progress-spinner');
|
||||
expect(loadingSpinner).toBeDefined();
|
||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(true);
|
||||
});
|
||||
|
||||
it('should show the apps filtered by defaultAppId', () => {
|
||||
component.filtersAppId = [{defaultAppId: 'fake-app-1'}];
|
||||
component.filtersAppId = [{ defaultAppId: 'fake-app-1' }];
|
||||
fixture.detectChanges();
|
||||
expect(component.isEmpty()).toBe(false);
|
||||
expect(component.appList).toBeDefined();
|
||||
@@ -97,7 +95,7 @@ describe('AppsListComponent', () => {
|
||||
});
|
||||
|
||||
it('should show the apps filtered by deploymentId', () => {
|
||||
component.filtersAppId = [{deploymentId: '4'}];
|
||||
component.filtersAppId = [{ deploymentId: '4' }];
|
||||
fixture.detectChanges();
|
||||
expect(component.isEmpty()).toBe(false);
|
||||
expect(component.appList).toBeDefined();
|
||||
@@ -106,7 +104,7 @@ describe('AppsListComponent', () => {
|
||||
});
|
||||
|
||||
it('should show the apps filtered by name', () => {
|
||||
component.filtersAppId = [{name: 'App5'}];
|
||||
component.filtersAppId = [{ name: 'App5' }];
|
||||
fixture.detectChanges();
|
||||
expect(component.isEmpty()).toBe(false);
|
||||
expect(component.appList).toBeDefined();
|
||||
@@ -115,7 +113,7 @@ describe('AppsListComponent', () => {
|
||||
});
|
||||
|
||||
it('should show the apps filtered by id', () => {
|
||||
component.filtersAppId = [{id: 6}];
|
||||
component.filtersAppId = [{ id: 6 }];
|
||||
fixture.detectChanges();
|
||||
expect(component.isEmpty()).toBe(false);
|
||||
expect(component.appList).toBeDefined();
|
||||
@@ -124,7 +122,7 @@ describe('AppsListComponent', () => {
|
||||
});
|
||||
|
||||
it('should show the apps filtered by modelId', () => {
|
||||
component.filtersAppId = [{modelId: 66}];
|
||||
component.filtersAppId = [{ modelId: 66 }];
|
||||
fixture.detectChanges();
|
||||
expect(component.isEmpty()).toBe(false);
|
||||
expect(component.appList).toBeDefined();
|
||||
@@ -133,7 +131,7 @@ describe('AppsListComponent', () => {
|
||||
});
|
||||
|
||||
it('should show the apps filtered by tenantId', () => {
|
||||
component.filtersAppId = [{tenantId: 9}];
|
||||
component.filtersAppId = [{ tenantId: 9 }];
|
||||
fixture.detectChanges();
|
||||
expect(component.isEmpty()).toBe(false);
|
||||
expect(component.appList).toBeDefined();
|
||||
@@ -149,7 +147,6 @@ describe('AppsListComponent', () => {
|
||||
});
|
||||
|
||||
describe('internationalization', () => {
|
||||
|
||||
it('should provide a translation for the default application name, when app name is not provided', () => {
|
||||
const appDataMock = {
|
||||
defaultAppId: 'tasks',
|
||||
@@ -173,7 +170,6 @@ describe('AppsListComponent', () => {
|
||||
});
|
||||
|
||||
describe('layout', () => {
|
||||
|
||||
it('should display a grid by default', () => {
|
||||
fixture.detectChanges();
|
||||
expect(component.isGrid()).toBe(true);
|
||||
@@ -201,7 +197,6 @@ describe('AppsListComponent', () => {
|
||||
});
|
||||
|
||||
describe('display apps', () => {
|
||||
|
||||
it('should display all deployed apps', () => {
|
||||
getAppsSpy.and.returnValue(of(deployedApps));
|
||||
fixture.detectChanges();
|
||||
@@ -219,10 +214,9 @@ describe('AppsListComponent', () => {
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.queryAll(By.css('h1')).length).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('select apps', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
getAppsSpy.and.returnValue(of(deployedApps));
|
||||
fixture.detectChanges();
|
||||
@@ -252,7 +246,7 @@ describe('AppsListComponent', () => {
|
||||
const appEls = debugElement.queryAll(By.css('.adf-app-listgrid > div'));
|
||||
expect(appEls[1].query(By.css('.adf-app-listgrid-item-card-actions-icon'))).not.toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Custom CustomEmptyAppListTemplateComponent', () => {
|
||||
let customFixture: ComponentFixture<CustomEmptyAppListTemplateComponent>;
|
||||
|
@@ -22,6 +22,7 @@ import { Observable, Observer, of, Subject } from 'rxjs';
|
||||
import { AppDefinitionRepresentationModel } from '../task-list';
|
||||
import { IconModel } from './icon.model';
|
||||
import { share, takeUntil, finalize } from 'rxjs/operators';
|
||||
import { AppDefinitionRepresentation } from '@alfresco/js-api';
|
||||
|
||||
const DEFAULT_TASKS_APP: string = 'tasks';
|
||||
const DEFAULT_TASKS_APP_NAME: string = 'ADF_TASK_LIST.APPS.TASK_APP_NAME';
|
||||
@@ -39,7 +40,6 @@ export const APP_LIST_LAYOUT_GRID: string = 'GRID';
|
||||
host: { class: 'adf-apps' }
|
||||
})
|
||||
export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
|
||||
|
||||
@ContentChild(CustomEmptyContentTemplateDirective)
|
||||
emptyCustomContent: CustomEmptyContentTemplateDirective;
|
||||
|
||||
@@ -64,19 +64,16 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
|
||||
|
||||
apps$: Observable<AppDefinitionRepresentationModel>;
|
||||
currentApp: AppDefinitionRepresentationModel;
|
||||
appList: AppDefinitionRepresentationModel [] = [];
|
||||
appList: AppDefinitionRepresentationModel[] = [];
|
||||
loading: boolean = false;
|
||||
hasEmptyCustomContentTemplate: boolean = false;
|
||||
|
||||
private appsObserver: Observer<AppDefinitionRepresentationModel>;
|
||||
private appsObserver: Observer<AppDefinitionRepresentation>;
|
||||
private iconsMDL: IconModel;
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(
|
||||
private appsProcessService: AppsProcessService,
|
||||
private translationService: TranslationService) {
|
||||
this.apps$ = new Observable<AppDefinitionRepresentationModel>((observer) => this.appsObserver = observer)
|
||||
.pipe(share());
|
||||
constructor(private appsProcessService: AppsProcessService, private translationService: TranslationService) {
|
||||
this.apps$ = new Observable<AppDefinitionRepresentationModel>((observer) => (this.appsObserver = observer)).pipe(share());
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -84,9 +81,7 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
|
||||
this.setDefaultLayoutType();
|
||||
}
|
||||
|
||||
this.apps$
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((app: any) => this.appList.push(app));
|
||||
this.apps$.pipe(takeUntil(this.onDestroy$)).subscribe((app) => this.appList.push(app));
|
||||
|
||||
this.iconsMDL = new IconModel();
|
||||
this.load();
|
||||
@@ -103,14 +98,12 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
isDefaultApp(app: AppDefinitionRepresentationModel) {
|
||||
isDefaultApp(app: AppDefinitionRepresentation): boolean {
|
||||
return app.defaultAppId === DEFAULT_TASKS_APP;
|
||||
}
|
||||
|
||||
getAppName(app: AppDefinitionRepresentationModel) {
|
||||
return this.isDefaultApp(app)
|
||||
? this.translationService.get(DEFAULT_TASKS_APP_NAME)
|
||||
: of(app.name);
|
||||
getAppName(app: AppDefinitionRepresentationModel): Observable<string> {
|
||||
return this.isDefaultApp(app) ? this.translationService.get(DEFAULT_TASKS_APP_NAME) : of(app.name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,7 +123,7 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
|
||||
* @returns `true` if application is selected, otherwise `false`
|
||||
*/
|
||||
isSelected(appId: number): boolean {
|
||||
return (this.currentApp !== undefined && appId === this.currentApp.id);
|
||||
return this.currentApp !== undefined && appId === this.currentApp.id;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,9 +180,9 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
|
||||
this.loading = true;
|
||||
this.appsProcessService
|
||||
.getDeployedApplications()
|
||||
.pipe(finalize(() => this.loading = false))
|
||||
.pipe(finalize(() => (this.loading = false)))
|
||||
.subscribe(
|
||||
(res: AppDefinitionRepresentationModel[]) => {
|
||||
(res) => {
|
||||
this.filterApps(res).forEach((app) => {
|
||||
if (this.isDefaultApp(app)) {
|
||||
app.theme = DEFAULT_TASKS_APP_THEME;
|
||||
@@ -206,24 +199,28 @@ export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
|
||||
);
|
||||
}
|
||||
|
||||
private filterApps(apps: AppDefinitionRepresentationModel []): AppDefinitionRepresentationModel[] {
|
||||
const filteredApps: AppDefinitionRepresentationModel[] = [];
|
||||
private filterApps(apps: AppDefinitionRepresentation[]): AppDefinitionRepresentation[] {
|
||||
if (this.filtersAppId) {
|
||||
apps.filter((app: AppDefinitionRepresentationModel) => {
|
||||
const filteredApps: AppDefinitionRepresentation[] = [];
|
||||
|
||||
apps.forEach((app) => {
|
||||
this.filtersAppId.forEach((filter) => {
|
||||
if (app.defaultAppId === filter.defaultAppId ||
|
||||
if (
|
||||
app.defaultAppId === filter.defaultAppId ||
|
||||
app.deploymentId === filter.deploymentId ||
|
||||
app.name === filter.name ||
|
||||
app.id === filter.id ||
|
||||
app.modelId === filter.modelId ||
|
||||
app.tenantId === filter.tenantId) {
|
||||
app.tenantId === filter.tenantId
|
||||
) {
|
||||
filteredApps.push(app);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return apps;
|
||||
|
||||
return filteredApps;
|
||||
}
|
||||
return filteredApps;
|
||||
|
||||
return apps;
|
||||
}
|
||||
}
|
||||
|
@@ -22,21 +22,11 @@ import { CoreModule } from '@alfresco/adf-core';
|
||||
|
||||
import { AppsListComponent } from './apps-list.component';
|
||||
import { SelectAppsDialogComponent } from './select-apps-dialog.component';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
MaterialModule,
|
||||
CoreModule
|
||||
],
|
||||
declarations: [
|
||||
AppsListComponent,
|
||||
SelectAppsDialogComponent
|
||||
],
|
||||
exports: [
|
||||
AppsListComponent,
|
||||
SelectAppsDialogComponent
|
||||
]
|
||||
imports: [CommonModule, MaterialModule, CoreModule, MatProgressSpinnerModule],
|
||||
declarations: [AppsListComponent, SelectAppsDialogComponent],
|
||||
exports: [AppsListComponent, SelectAppsDialogComponent]
|
||||
})
|
||||
export class AppsListModule {
|
||||
}
|
||||
export class AppsListModule {}
|
||||
|
@@ -17,6 +17,7 @@
|
||||
|
||||
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
|
||||
import { ProcessContentService } from '../form/services/process-content.service';
|
||||
import { RelatedContentRepresentation } from '@alfresco/js-api';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-create-process-attachment',
|
||||
@@ -40,7 +41,7 @@ export class CreateProcessAttachmentComponent implements OnChanges {
|
||||
* from within the component.
|
||||
*/
|
||||
@Output()
|
||||
success: EventEmitter<any> = new EventEmitter<any>();
|
||||
success = new EventEmitter<RelatedContentRepresentation>();
|
||||
|
||||
constructor(private activitiContentService: ProcessContentService) {}
|
||||
|
||||
|
@@ -24,7 +24,6 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
import { ProcessContentService } from '../form/services/process-content.service';
|
||||
|
||||
describe('AttachmentComponent', () => {
|
||||
|
||||
let service: ProcessContentService;
|
||||
let component: AttachmentComponent;
|
||||
let fixture: ComponentFixture<AttachmentComponent>;
|
||||
@@ -32,30 +31,28 @@ describe('AttachmentComponent', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
ProcessTestingModule
|
||||
]
|
||||
imports: [TranslateModule.forRoot(), ProcessTestingModule]
|
||||
});
|
||||
fixture = TestBed.createComponent(AttachmentComponent);
|
||||
component = fixture.componentInstance;
|
||||
service = fixture.debugElement.injector.get(ProcessContentService);
|
||||
|
||||
createTaskRelatedContentSpy = spyOn(service, 'createTaskRelatedContent').and.returnValue(of(
|
||||
{
|
||||
createTaskRelatedContentSpy = spyOn(service, 'createTaskRelatedContent').and.returnValue(
|
||||
of({
|
||||
status: true
|
||||
}));
|
||||
} as any)
|
||||
);
|
||||
});
|
||||
|
||||
it('should not call createTaskRelatedContent service when taskId changed', () => {
|
||||
const change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({taskId: change});
|
||||
component.ngOnChanges({ taskId: change });
|
||||
expect(createTaskRelatedContentSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call createTaskRelatedContent service when there is no file uploaded', () => {
|
||||
const change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({taskId: change});
|
||||
component.ngOnChanges({ taskId: change });
|
||||
const customEvent: any = {
|
||||
detail: {
|
||||
files: []
|
||||
@@ -67,13 +64,11 @@ describe('AttachmentComponent', () => {
|
||||
|
||||
it('should call createTaskRelatedContent service when there is a file uploaded', () => {
|
||||
const change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({taskId: change});
|
||||
component.ngOnChanges({ taskId: change });
|
||||
const file = new File([new Blob()], 'Test');
|
||||
const customEvent = {
|
||||
detail: {
|
||||
files: [
|
||||
file
|
||||
]
|
||||
files: [file]
|
||||
}
|
||||
};
|
||||
component.onFileUpload(customEvent);
|
||||
|
@@ -24,9 +24,12 @@ import { ProcessTestingModule } from '../testing/process.testing.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { mockEmittedProcessAttachments, mockProcessAttachments } from '../mock/process/process-attachments.mock';
|
||||
import { ProcessContentService } from '../form/services/process-content.service';
|
||||
import { HarnessLoader } from '@angular/cdk/testing';
|
||||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||
import { MatMenuHarness } from '@angular/material/menu/testing';
|
||||
|
||||
describe('ProcessAttachmentListComponent', () => {
|
||||
|
||||
let loader: HarnessLoader;
|
||||
let service: ProcessContentService;
|
||||
let component: ProcessAttachmentListComponent;
|
||||
let fixture: ComponentFixture<ProcessAttachmentListComponent>;
|
||||
@@ -34,10 +37,7 @@ describe('ProcessAttachmentListComponent', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
ProcessTestingModule
|
||||
]
|
||||
imports: [TranslateModule.forRoot(), ProcessTestingModule]
|
||||
});
|
||||
fixture = TestBed.createComponent(ProcessAttachmentListComponent);
|
||||
component = fixture.componentInstance;
|
||||
@@ -48,6 +48,7 @@ describe('ProcessAttachmentListComponent', () => {
|
||||
|
||||
const blobObj = new Blob();
|
||||
spyOn(service, 'getFileRawContent').and.returnValue(of(blobObj));
|
||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -101,17 +102,15 @@ describe('ProcessAttachmentListComponent', () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
const actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]');
|
||||
actionButton.click();
|
||||
const menu = await loader.getHarness(MatMenuHarness);
|
||||
await menu.open();
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
const menuItems = await menu.getItems();
|
||||
expect(menuItems.length).toBe(3);
|
||||
|
||||
const actionMenu = window.document.querySelectorAll('button.mat-menu-item').length;
|
||||
expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.VIEW_CONTENT"]')).not.toBeNull();
|
||||
expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.REMOVE_CONTENT"]')).not.toBeNull();
|
||||
expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT"]')).not.toBeNull();
|
||||
expect(actionMenu).toBe(3);
|
||||
expect(await menuItems[0].getText()).toBe('ADF_PROCESS_LIST.MENU_ACTIONS.VIEW_CONTENT');
|
||||
expect(await menuItems[1].getText()).toBe('ADF_PROCESS_LIST.MENU_ACTIONS.REMOVE_CONTENT');
|
||||
expect(await menuItems[2].getText()).toBe('ADF_PROCESS_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT');
|
||||
});
|
||||
|
||||
it('should not display remove action if attachments are read only', async () => {
|
||||
@@ -122,39 +121,43 @@ describe('ProcessAttachmentListComponent', () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
const actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]');
|
||||
actionButton.click();
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
const menu = await loader.getHarness(MatMenuHarness);
|
||||
await menu.open();
|
||||
|
||||
const actionMenu = window.document.querySelectorAll('button.mat-menu-item').length;
|
||||
expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.VIEW_CONTENT"]')).not.toBeNull();
|
||||
expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT"]')).not.toBeNull();
|
||||
expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.REMOVE_CONTENT"]')).toBeNull();
|
||||
expect(actionMenu).toBe(2);
|
||||
const menuItems = await menu.getItems();
|
||||
expect(menuItems.length).toBe(2);
|
||||
|
||||
expect(await menuItems[0].getText()).toBe('ADF_PROCESS_LIST.MENU_ACTIONS.VIEW_CONTENT');
|
||||
expect(await menuItems[1].getText()).toBe('ADF_PROCESS_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT');
|
||||
});
|
||||
|
||||
it('should show the empty list component when the attachments list is empty', async () => {
|
||||
getProcessRelatedContentSpy.and.returnValue(of({
|
||||
size: 0,
|
||||
total: 0,
|
||||
start: 0,
|
||||
data: []
|
||||
}));
|
||||
getProcessRelatedContentSpy.and.returnValue(
|
||||
of({
|
||||
size: 0,
|
||||
total: 0,
|
||||
start: 0,
|
||||
data: []
|
||||
})
|
||||
);
|
||||
const change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({ processInstanceId: change });
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual('ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER');
|
||||
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual(
|
||||
'ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER'
|
||||
);
|
||||
});
|
||||
|
||||
it('should not show the empty list drag and drop component when is disabled', async () => {
|
||||
getProcessRelatedContentSpy.and.returnValue(of({
|
||||
size: 0,
|
||||
total: 0,
|
||||
start: 0,
|
||||
data: []
|
||||
}));
|
||||
getProcessRelatedContentSpy.and.returnValue(
|
||||
of({
|
||||
size: 0,
|
||||
total: 0,
|
||||
start: 0,
|
||||
data: []
|
||||
})
|
||||
);
|
||||
const change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({ processInstanceId: change });
|
||||
component.disabled = true;
|
||||
@@ -162,16 +165,20 @@ describe('ProcessAttachmentListComponent', () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
expect(fixture.nativeElement.querySelector('adf-empty-list .adf-empty-list-drag_drop')).toBeNull();
|
||||
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual('ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER');
|
||||
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual(
|
||||
'ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER'
|
||||
);
|
||||
});
|
||||
|
||||
it('should show the empty list component when the attachments list is empty for completed process', async () => {
|
||||
getProcessRelatedContentSpy.and.returnValue(of({
|
||||
size: 0,
|
||||
total: 0,
|
||||
start: 0,
|
||||
data: []
|
||||
}));
|
||||
getProcessRelatedContentSpy.and.returnValue(
|
||||
of({
|
||||
size: 0,
|
||||
total: 0,
|
||||
start: 0,
|
||||
data: []
|
||||
})
|
||||
);
|
||||
const change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({ processInstanceId: change });
|
||||
component.disabled = true;
|
||||
@@ -179,8 +186,9 @@ describe('ProcessAttachmentListComponent', () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim())
|
||||
.toEqual('ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER');
|
||||
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual(
|
||||
'ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER'
|
||||
);
|
||||
});
|
||||
|
||||
it('should not show the empty list component when the attachments list is not empty for completed process', async () => {
|
||||
@@ -204,7 +212,6 @@ describe('ProcessAttachmentListComponent', () => {
|
||||
});
|
||||
|
||||
describe('change detection', () => {
|
||||
|
||||
const change = new SimpleChange('123', '456', true);
|
||||
const nullChange = new SimpleChange('123', null, true);
|
||||
|
||||
@@ -241,18 +248,14 @@ describe('ProcessAttachmentListComponent', () => {
|
||||
</adf-process-attachment-list>
|
||||
`
|
||||
})
|
||||
class CustomEmptyTemplateComponent {
|
||||
}
|
||||
class CustomEmptyTemplateComponent {}
|
||||
|
||||
describe('Custom CustomEmptyTemplateComponent', () => {
|
||||
let fixture: ComponentFixture<CustomEmptyTemplateComponent>;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
ProcessTestingModule
|
||||
],
|
||||
imports: [TranslateModule.forRoot(), ProcessTestingModule],
|
||||
declarations: [CustomEmptyTemplateComponent],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
});
|
||||
|
@@ -205,7 +205,7 @@ export class TaskAttachmentListComponent implements OnChanges, AfterContentInit
|
||||
this.reset();
|
||||
const isRelatedContent = 'true';
|
||||
this.activitiContentService.getTaskRelatedContent(taskId, { isRelatedContent }).subscribe(
|
||||
(res: any) => {
|
||||
(res) => {
|
||||
const attachList = [];
|
||||
res.data.forEach((content) => {
|
||||
attachList.push({
|
||||
|
@@ -15,9 +15,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { AlfrescoApiService, LogService } from '@alfresco/adf-core';
|
||||
import { AlfrescoApiService } from '@alfresco/adf-core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivitiContentApi, RelatedContentRepresentation, ResultListDataRepresentationRelatedProcessTask } from '@alfresco/js-api';
|
||||
import {
|
||||
ActivitiContentApi,
|
||||
RelatedContentRepresentation,
|
||||
ResultListDataRepresentationRelatedProcessTask,
|
||||
ResultListDataRepresentationRelatedContentRepresentation
|
||||
} from '@alfresco/js-api';
|
||||
import { Observable, from, throwError } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
|
||||
@@ -25,7 +30,6 @@ import { catchError } from 'rxjs/operators';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ProcessContentService {
|
||||
|
||||
static UNKNOWN_ERROR_MESSAGE: string = 'Unknown error';
|
||||
static GENERIC_ERROR_MESSAGE: string = 'Server error';
|
||||
|
||||
@@ -35,9 +39,7 @@ export class ProcessContentService {
|
||||
return this._contentApi;
|
||||
}
|
||||
|
||||
constructor(private apiService: AlfrescoApiService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
constructor(private apiService: AlfrescoApiService) {}
|
||||
|
||||
/**
|
||||
* Create temporary related content from an uploaded file.
|
||||
@@ -46,8 +48,7 @@ export class ProcessContentService {
|
||||
* @returns The created content data
|
||||
*/
|
||||
createTemporaryRawRelatedContent(file: any): Observable<RelatedContentRepresentation> {
|
||||
return from(this.contentApi.createTemporaryRawRelatedContent(file))
|
||||
.pipe(catchError((err) => this.handleError(err)));
|
||||
return from(this.contentApi.createTemporaryRawRelatedContent(file)).pipe(catchError((err) => this.handleError(err)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,8 +58,7 @@ export class ProcessContentService {
|
||||
* @returns Metadata for the content
|
||||
*/
|
||||
getFileContent(contentId: number): Observable<RelatedContentRepresentation> {
|
||||
return from(this.contentApi.getContent(contentId))
|
||||
.pipe(catchError((err) => this.handleError(err)));
|
||||
return from(this.contentApi.getContent(contentId)).pipe(catchError((err) => this.handleError(err)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,8 +68,7 @@ export class ProcessContentService {
|
||||
* @returns Binary data of the related content
|
||||
*/
|
||||
getFileRawContent(contentId: number): Observable<Blob> {
|
||||
return from(this.contentApi.getRawContent(contentId))
|
||||
.pipe(catchError((err) => this.handleError(err)));
|
||||
return from(this.contentApi.getRawContent(contentId)).pipe(catchError((err) => this.handleError(err)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,8 +117,7 @@ export class ProcessContentService {
|
||||
* @returns Binary data of the thumbnail image
|
||||
*/
|
||||
getContentThumbnail(contentId: number): Observable<Blob> {
|
||||
return from(this.contentApi.getRawContent(contentId, 'thumbnail'))
|
||||
.pipe(catchError((err) => this.handleError(err)));
|
||||
return from(this.contentApi.getRawContent(contentId, 'thumbnail')).pipe(catchError((err) => this.handleError(err)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,9 +127,8 @@ export class ProcessContentService {
|
||||
* @param opts Options supported by JS-API
|
||||
* @returns Metadata for the content
|
||||
*/
|
||||
getTaskRelatedContent(taskId: string, opts?: any): Observable<any> {
|
||||
return from(this.contentApi.getRelatedContentForTask(taskId, opts))
|
||||
.pipe(catchError((err) => this.handleError(err)));
|
||||
getTaskRelatedContent(taskId: string, opts?: any): Observable<ResultListDataRepresentationRelatedContentRepresentation> {
|
||||
return from(this.contentApi.getRelatedContentForTask(taskId, opts)).pipe(catchError((err) => this.handleError(err)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,9 +138,8 @@ export class ProcessContentService {
|
||||
* @param opts Options supported by JS-API
|
||||
* @returns Metadata for the content
|
||||
*/
|
||||
getProcessRelatedContent(processId: string, opts?: any): Observable<any> {
|
||||
return from(this.contentApi.getRelatedContentForProcessInstance(processId, opts))
|
||||
.pipe(catchError((err) => this.handleError(err)));
|
||||
getProcessRelatedContent(processId: string, opts?: any): Observable<ResultListDataRepresentationRelatedContentRepresentation> {
|
||||
return from(this.contentApi.getRelatedContentForProcessInstance(processId, opts)).pipe(catchError((err) => this.handleError(err)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,8 +149,7 @@ export class ProcessContentService {
|
||||
* @returns Null response that notifies when the deletion is complete
|
||||
*/
|
||||
deleteRelatedContent(contentId: number): Observable<any> {
|
||||
return from(this.contentApi.deleteContent(contentId))
|
||||
.pipe(catchError((err) => this.handleError(err)));
|
||||
return from(this.contentApi.deleteContent(contentId)).pipe(catchError((err) => this.handleError(err)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,9 +160,10 @@ export class ProcessContentService {
|
||||
* @param opts Options supported by JS-API
|
||||
* @returns Details of created content
|
||||
*/
|
||||
createProcessRelatedContent(processInstanceId: string, content: any, opts?: any): Observable<any> {
|
||||
return from(this.contentApi.createRelatedContentOnProcessInstance(processInstanceId, content, opts))
|
||||
.pipe(catchError((err) => this.handleError(err)));
|
||||
createProcessRelatedContent(processInstanceId: string, content: any, opts?: any): Observable<RelatedContentRepresentation> {
|
||||
return from(this.contentApi.createRelatedContentOnProcessInstance(processInstanceId, content, opts)).pipe(
|
||||
catchError((err) => this.handleError(err))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,9 +174,8 @@ export class ProcessContentService {
|
||||
* @param opts Options supported by JS-API
|
||||
* @returns Details of created content
|
||||
*/
|
||||
createTaskRelatedContent(taskId: string, file: any, opts?: any) {
|
||||
return from(this.contentApi.createRelatedContentOnTask(taskId, file, opts))
|
||||
.pipe(catchError((err) => this.handleError(err)));
|
||||
createTaskRelatedContent(taskId: string, file: any, opts?: any): Observable<RelatedContentRepresentation> {
|
||||
return from(this.contentApi.createRelatedContentOnTask(taskId, file, opts)).pipe(catchError((err) => this.handleError(err)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,7 +187,12 @@ export class ProcessContentService {
|
||||
* @param page - page number
|
||||
* @returns Promise<ResultListDataRepresentationRelatedProcessTask>
|
||||
*/
|
||||
getProcessesAndTasksOnContent(sourceId: string, source: string, size?: number, page?: number): Observable<ResultListDataRepresentationRelatedProcessTask> {
|
||||
getProcessesAndTasksOnContent(
|
||||
sourceId: string,
|
||||
source: string,
|
||||
size?: number,
|
||||
page?: number
|
||||
): Observable<ResultListDataRepresentationRelatedProcessTask> {
|
||||
return from(this.contentApi.getProcessesAndTasksOnContent(sourceId, source, size, page)).pipe(catchError((err) => this.handleError(err)));
|
||||
}
|
||||
|
||||
@@ -231,11 +231,12 @@ export class ProcessContentService {
|
||||
handleError(error: any): Observable<any> {
|
||||
let errMsg = ProcessContentService.UNKNOWN_ERROR_MESSAGE;
|
||||
if (error) {
|
||||
errMsg = (error.message) ? error.message :
|
||||
error.status ? `${error.status} - ${error.statusText}` : ProcessContentService.GENERIC_ERROR_MESSAGE;
|
||||
errMsg = error.message
|
||||
? error.message
|
||||
: error.status
|
||||
? `${error.status} - ${error.statusText}`
|
||||
: ProcessContentService.GENERIC_ERROR_MESSAGE;
|
||||
}
|
||||
this.logService.error(errMsg);
|
||||
return throwError(errMsg);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export const mockProcessAttachments = {
|
||||
export const mockProcessAttachments: any = {
|
||||
size: 2,
|
||||
total: 2,
|
||||
start: 0,
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export const mockTaskAttachments = {
|
||||
export const mockTaskAttachments: any = {
|
||||
size: 2,
|
||||
total: 2,
|
||||
start: 0,
|
||||
|
Reference in New Issue
Block a user