[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:
Denys Vuika
2023-11-09 09:24:56 +00:00
committed by GitHub
parent 479cc8b545
commit f0a11fdab0
35 changed files with 941 additions and 1231 deletions

View File

@@ -24,33 +24,32 @@ import { DEFAULT_APP_INSTANCE_THEME } from '../models/application-instance.model
import { TranslateModule } from '@ngx-translate/core';
describe('AppDetailsCloudComponent', () => {
let component: AppDetailsCloudComponent;
let fixture: ComponentFixture<AppDetailsCloudComponent>;
let host: HTMLElement;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule,
AppListCloudModule
]
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule, AppListCloudModule]
});
fixture = TestBed.createComponent(AppDetailsCloudComponent);
component = fixture.componentInstance;
host = fixture.nativeElement as HTMLElement;
component.applicationInstance = fakeApplicationInstance[0];
});
const getAppCard = () => host.querySelector<HTMLElement>('.adf-app-listgrid-item-card');
it('should display application name', () => {
fixture.detectChanges();
const appName = fixture.nativeElement.querySelector('.adf-app-listgrid-item-card-title');
const appName = host.querySelector<HTMLDivElement>('.adf-app-listgrid-item-card-title');
expect(appName.innerText.trim()).toEqual(fakeApplicationInstance[0].name);
});
it('should emit a click event when app selected', () => {
spyOn(component.selectedApp, 'emit');
fixture.detectChanges();
const app = fixture.nativeElement.querySelector('.mat-card');
const app = getAppCard();
app.click();
expect(component.selectedApp.emit).toHaveBeenCalledWith(fakeApplicationInstance[0]);
});
@@ -59,17 +58,17 @@ describe('AppDetailsCloudComponent', () => {
component.applicationInstance = fakeApplicationInstance[2];
fixture.detectChanges();
const theme = fixture.nativeElement.querySelector('.adf-app-listgrid-item-card').getAttribute('ng-reflect-ng-class');
const icon = fixture.nativeElement.querySelector('.adf-app-listgrid-item-card-logo-icon');
const card = getAppCard();
expect(card.classList.contains(DEFAULT_APP_INSTANCE_THEME));
expect(theme).toEqual(DEFAULT_APP_INSTANCE_THEME);
const icon = host.querySelector('.adf-app-listgrid-item-card-logo-icon');
expect(icon).toBeTruthy();
});
it('should render card with a non ApplicationInstanceModel input object', () => {
component.applicationInstance = { name: 'application-new-3', createdAt: '2018-09-21T12:31:39.000Z', status: 'Pending' };
component.applicationInstance = { name: 'application-new-3', createdAt: '2018-09-21T12:31:39.000Z', status: 'Pending' };
fixture.detectChanges();
const app = fixture.nativeElement.querySelector('.mat-card');
const app = getAppCard();
expect(app).toBeTruthy();
});
});
});

View File

@@ -15,7 +15,7 @@
<mat-list-item class="adf-app-list-item" (click)="onSelectApp(app)" (keyup.enter)="onSelectApp(app)"
*ngFor="let app of appsList" tabindex="0" role="button" title="{{app.name}}">
<mat-icon matListIcon>touch_app</mat-icon>
<span matLine>{{app.name}}</span>
<span class="adf-app-list-item-text" matLine>{{app.name}}</span>
</mat-list-item>
</mat-list>
</ng-template>

View File

@@ -27,7 +27,6 @@ import { ProcessServiceCloudTestingModule } from '../../testing/process-service-
import { TranslateModule } from '@ngx-translate/core';
describe('AppListCloudComponent', () => {
let component: AppListCloudComponent;
let fixture: ComponentFixture<AppListCloudComponent>;
let appsProcessCloudService: AppsProcessCloudService;
@@ -35,32 +34,28 @@ describe('AppListCloudComponent', () => {
let alfrescoApiService: AlfrescoApiService;
const mock: any = {
oauth2Auth: {
callCustomApi: () => Promise.resolve(fakeApplicationInstance)
},
isEcmLoggedIn: () => false,
reply: jasmine.createSpy('reply')
oauth2Auth: {
callCustomApi: () => Promise.resolve(fakeApplicationInstance)
},
isEcmLoggedIn: () => false,
reply: jasmine.createSpy('reply')
};
@Component({
template: `
<adf-cloud-app-list>
<adf-custom-empty-content-template>
<mat-icon>apps</mat-icon>
<p id="custom-id">No Apps Found</p>
</adf-custom-empty-content-template>
</adf-cloud-app-list>
`
<adf-cloud-app-list>
<adf-custom-empty-content-template>
<mat-icon>apps</mat-icon>
<p id="custom-id">No Apps Found</p>
</adf-custom-empty-content-template>
</adf-cloud-app-list>
`
})
class CustomEmptyAppListCloudTemplateComponent {
}
class CustomEmptyAppListCloudTemplateComponent {}
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
declarations: [CustomEmptyAppListCloudTemplateComponent]
});
fixture = TestBed.createComponent(AppListCloudComponent);
@@ -127,10 +122,9 @@ describe('AppListCloudComponent', () => {
expect(getAppsSpy).toHaveBeenCalled();
done();
});
});
});
describe('Grid Layout ', () => {
it('should display a grid by default', () => {
fixture.detectChanges();
expect(component.isGrid()).toBe(true);
@@ -165,7 +159,6 @@ describe('AppListCloudComponent', () => {
});
describe('List Layout ', () => {
beforeEach(() => {
component.layoutType = LAYOUT_LIST;
});
@@ -176,11 +169,11 @@ describe('AppListCloudComponent', () => {
expect(component.isList()).toBe(true);
});
it('should defined mat-list when layout type is LIST', () => {
it('should display list when layout type is LIST', () => {
fixture.detectChanges();
const appListElement = fixture.nativeElement.querySelectorAll('mat-list');
const appListItemElement = fixture.nativeElement.querySelectorAll('mat-list-item');
const appName = fixture.nativeElement.querySelector('.mat-list-text');
const appListElement = fixture.nativeElement.querySelectorAll('.adf-app-list');
const appListItemElement = fixture.nativeElement.querySelectorAll('.adf-app-list-item');
const appName = fixture.nativeElement.querySelector('.adf-app-list-item-text');
expect(appListElement).toBeDefined();
expect(appListElement).not.toBeNull();
@@ -200,7 +193,7 @@ describe('AppListCloudComponent', () => {
it('should emit a click event when app selected', () => {
spyOn(component.appClick, 'emit');
fixture.detectChanges();
const onAppClick = fixture.nativeElement.querySelector('.mat-card');
const onAppClick = fixture.nativeElement.querySelector('.adf-app-listgrid-item-card');
onAppClick.click();
expect(component.appClick.emit).toHaveBeenCalledWith(fakeApplicationInstance[0]);
});
@@ -221,7 +214,7 @@ describe('AppListCloudComponent', () => {
customFixture.detectChanges();
await customFixture.whenStable();
const title: any = customFixture.nativeElement.querySelector('#custom-id');
const title: any = customFixture.nativeElement.querySelector('#custom-id');
expect(title.innerText).toBe('No Apps Found');
});
});

View File

@@ -26,39 +26,29 @@ 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';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatChipHarness, MatChipListHarness } from '@angular/material/chips/testing';
import { MatIconHarness } from '@angular/material/icon/testing';
import { MatInputHarness } from '@angular/material/input/testing';
describe('GroupCloudComponent', () => {
let loader: HarnessLoader;
let component: GroupCloudComponent;
let fixture: ComponentFixture<GroupCloudComponent>;
let element: HTMLElement;
let identityGroupService: IdentityGroupService;
let findGroupsByNameSpy: jasmine.Spy;
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
/**
* get the native element for the selector
*
* @param selector selector
* @returns native element
*/
function getElement<T = HTMLElement>(selector: string): T {
return fixture.nativeElement.querySelector(selector);
}
/**
* search group by value
*
* @param value element input value
*/
async function searchGroup(value: string) {
const input = getElement<HTMLInputElement>('input');
input.focus();
input.value = value;
input.dispatchEvent(new Event('keyup'));
input.dispatchEvent(new Event('input'));
await fixture.whenStable();
fixture.detectChanges();
const input = await loader.getHarness(MatInputHarness);
await input.focus();
await input.setValue(value);
}
/**
@@ -67,17 +57,10 @@ describe('GroupCloudComponent', () => {
* @param value value
*/
async function searchGroupsAndBlur(value: string) {
const input = getElement<HTMLInputElement>('input');
input.focus();
input.value = value;
input.dispatchEvent(new Event('keyup'));
input.dispatchEvent(new Event('input'));
await fixture.whenStable();
fixture.detectChanges();
input.blur();
fixture.detectChanges();
const input = await loader.getHarness(MatInputHarness);
await input.focus();
await input.setValue(value);
await input.blur();
}
/**
@@ -91,18 +74,14 @@ describe('GroupCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
CoreTestingModule,
ProcessServiceCloudTestingModule,
GroupCloudModule
]
imports: [TranslateModule.forRoot(), CoreTestingModule, ProcessServiceCloudTestingModule, GroupCloudModule]
});
fixture = TestBed.createComponent(GroupCloudComponent);
component = fixture.componentInstance;
element = fixture.nativeElement;
identityGroupService = TestBed.inject(IdentityGroupService);
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should populate placeholder when title is present', () => {
@@ -115,7 +94,6 @@ describe('GroupCloudComponent', () => {
});
describe('Search group', () => {
beforeEach(() => {
fixture.detectChanges();
findGroupsByNameSpy = spyOn(identityGroupService, 'search').and.returnValue(of(mockFoodGroups));
@@ -208,19 +186,19 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
});
it('should not pre-select any group when preSelectGroups is empty - single mode', () => {
it('should not pre-select any group when preSelectGroups is empty - single mode', async () => {
component.mode = 'single';
fixture.detectChanges();
const chips = fixture.debugElement.queryAll(By.css('mat-chip'));
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toEqual(0);
});
it('should not pre-select any group when preSelectGroups is empty - multiple mode', () => {
it('should not pre-select any group when preSelectGroups is empty - multiple mode', async () => {
component.mode = 'multiple';
fixture.detectChanges();
const chips = fixture.debugElement.queryAll(By.css('mat-chip'));
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toEqual(0);
});
});
@@ -235,10 +213,11 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
});
it('should show only one mat chip with the first preSelectedGroup', () => {
const chips = fixture.debugElement.queryAll(By.css('mat-chip'));
it('should show only one mat chip with the first preSelectedGroup', async () => {
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toEqual(1);
expect(chips[0].attributes['data-automation-id']).toEqual(`adf-cloud-group-chip-${mockVegetableAubergine.name}`);
const testId = await (await chips[0].host()).getAttribute('data-automation-id');
expect(testId).toEqual(`adf-cloud-group-chip-${mockVegetableAubergine.name}`);
});
});
@@ -252,12 +231,13 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
});
it('should render all preselected groups', () => {
it('should render all preselected groups', async () => {
component.mode = 'multiple';
fixture.detectChanges();
component.ngOnChanges({ preSelectGroups: change });
fixture.detectChanges();
const chips = fixture.debugElement.queryAll(By.css('mat-chip'));
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(2);
});
@@ -266,42 +246,40 @@ describe('GroupCloudComponent', () => {
const changedGroupsEmitterSpy = spyOn(component.changedGroups, 'emit');
component.mode = 'multiple';
const removeIcon = fixture.debugElement.query(By.css('mat-chip mat-icon'));
removeIcon.nativeElement.click();
fixture.detectChanges();
const chip = await loader.getHarness(MatChipHarness);
const icon = await chip.getHarness(MatIconHarness);
await (await icon.host()).click();
await fixture.whenStable();
expect(removeGroupEmitterSpy).toHaveBeenCalledWith(mockVegetableAubergine);
expect(changedGroupsEmitterSpy).toHaveBeenCalledWith([mockMeatChicken]);
expect(component.selectedGroups.indexOf({
id: mockMeatChicken.id,
name: mockMeatChicken.name
})).toEqual(-1);
expect(
component.selectedGroups.indexOf({
id: mockMeatChicken.id,
name: mockMeatChicken.name
})
).toEqual(-1);
});
});
describe('Multiple Mode with read-only', () => {
it('Should not show remove icon for pre-selected groups if readonly property set to true', async () => {
component.mode = 'multiple';
component.preSelectGroups = [
{ id: mockVegetableAubergine.id, name: mockVegetableAubergine.name, readonly: true },
mockMeatChicken
];
component.preSelectGroups = [{ id: mockVegetableAubergine.id, name: mockVegetableAubergine.name, readonly: true }, mockMeatChicken];
const changes = new SimpleChange(null, [{ name: mockVegetableAubergine.name }], false);
component.ngOnChanges({ preSelectGroups: changes });
fixture.detectChanges();
await fixture.whenStable();
const chipList = fixture.nativeElement.querySelectorAll('mat-chip-list mat-chip');
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(2);
expect(chipList.length).toBe(2);
const removeIconAubergine = getElement(`[data-automation-id="adf-cloud-group-chip-remove-icon-${mockVegetableAubergine.name}"]`);
const removeIconAubergine = element.querySelector(
`[data-automation-id="adf-cloud-group-chip-remove-icon-${mockVegetableAubergine.name}"]`
);
expect(removeIconAubergine).toBeNull();
const removeIconPepper = getElement(`[data-automation-id="adf-cloud-group-chip-remove-icon-${mockMeatChicken.name}"]`);
const removeIconPepper = element.querySelector(`[data-automation-id="adf-cloud-group-chip-remove-icon-${mockMeatChicken.name}"]`);
expect(removeIconPepper).not.toBeNull();
});
it('Should be able to remove preselected groups if readonly property set to false', async () => {
@@ -314,28 +292,26 @@ describe('GroupCloudComponent', () => {
const removeGroupSpy = spyOn(component.removeGroup, 'emit');
fixture.detectChanges();
fixture.whenStable();
fixture.detectChanges();
let chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(2);
const chipList = fixture.nativeElement.querySelectorAll('mat-chip-list mat-chip');
expect(chipList.length).toBe(2);
const removeIcon = getElement(`[data-automation-id="adf-cloud-group-chip-remove-icon-${mockMeatChicken.name}"]`);
const removeIcon = element.querySelector<HTMLElement>(`[data-automation-id="adf-cloud-group-chip-remove-icon-${mockMeatChicken.name}"]`);
removeIcon.click();
fixture.detectChanges();
expect(removeGroupSpy).toHaveBeenCalled();
expect(fixture.nativeElement.querySelectorAll('mat-chip-list mat-chip').length).toBe(1);
chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(1);
});
it('should removeDuplicatedGroups return only unique groups', () => {
const duplicatedGroups = [ mockMeatChicken, mockMeatChicken];
const duplicatedGroups = [mockMeatChicken, mockMeatChicken];
expect(component.removeDuplicatedGroups(duplicatedGroups)).toEqual([mockMeatChicken]);
});
});
describe('Preselected groups and validation enabled', () => {
beforeEach(() => {
spyOn(identityGroupService, 'search').and.throwError('Invalid group');
component.validate = true;
@@ -364,7 +340,7 @@ describe('GroupCloudComponent', () => {
describe('Component readonly mode', () => {
const change = new SimpleChange(null, mockFoodGroups, false);
it('should chip list be disabled and show one single chip - single mode', () => {
it('should chip list be disabled and show one single chip - single mode', async () => {
component.mode = 'single';
component.readOnly = true;
component.preSelectGroups = mockFoodGroups;
@@ -372,16 +348,14 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
const chips = fixture.debugElement.queryAll(By.css('mat-chip'));
const chipList = getElement('mat-chip-list');
expect(chips).toBeDefined();
expect(chipList).toBeDefined();
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(1);
expect(chipList.attributes['ng-reflect-disabled']?.value).toEqual('true');
const chipList = await loader.getHarness(MatChipListHarness);
expect(await chipList.isDisabled()).toBe(true);
});
it('should chip list be disabled and show all the chips - multiple mode', () => {
it('should chip list be disabled and show all the chips - multiple mode', async () => {
component.mode = 'multiple';
component.readOnly = true;
component.preSelectGroups = mockFoodGroups;
@@ -389,14 +363,11 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
const chips = fixture.debugElement.queryAll(By.css('mat-chip'));
const chipList = getElement('mat-chip-list');
expect(chips).toBeDefined();
expect(chipList).toBeDefined();
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(2);
expect(chipList.attributes['ng-reflect-disabled']?.value).toEqual('true');
const chipList = await loader.getHarness(MatChipListHarness);
expect(await chipList.isDisabled()).toBe(true);
});
});
});

View File

@@ -26,46 +26,29 @@ 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';
import {
mockFoodUsers,
mockKielbasaSausage,
mockShepherdsPie,
mockYorkshirePudding,
mockPreselectedFoodUsers
} from '../mock/people-cloud.mock';
import { mockFoodUsers, mockKielbasaSausage, mockShepherdsPie, mockYorkshirePudding, mockPreselectedFoodUsers } from '../mock/people-cloud.mock';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatChipHarness, MatChipListHarness } from '@angular/material/chips/testing';
import { MatInputHarness } from '@angular/material/input/testing';
describe('PeopleCloudComponent', () => {
let loader: HarnessLoader;
let component: PeopleCloudComponent;
let fixture: ComponentFixture<PeopleCloudComponent>;
let element: HTMLElement;
let identityUserService: IdentityUserServiceInterface;
let searchSpy: jasmine.Spy;
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
/**
* get the native element by selector
*
* @param selector selector
* @returns native element
*/
function getElement<T = HTMLElement>(selector: string): T {
return fixture.nativeElement.querySelector(selector);
}
/**
* Search users by value
*
* @param value value
*/
async function searchUsers(value: string) {
const input = getElement<HTMLInputElement>('input');
input.focus();
input.value = value;
input.dispatchEvent(new Event('keyup'));
input.dispatchEvent(new Event('input'));
await fixture.whenStable();
fixture.detectChanges();
const input = await loader.getHarness(MatInputHarness);
await input.focus();
await input.setValue(value);
}
/**
@@ -74,17 +57,10 @@ describe('PeopleCloudComponent', () => {
* @param value value
*/
async function searchUsersAndBlur(value: string) {
const input = getElement<HTMLInputElement>('input');
input.focus();
input.value = value;
input.dispatchEvent(new Event('keyup'));
input.dispatchEvent(new Event('input'));
await fixture.whenStable();
fixture.detectChanges();
input.blur();
fixture.detectChanges();
const input = await loader.getHarness(MatInputHarness);
await input.focus();
await input.setValue(value);
await input.blur();
}
/**
@@ -96,15 +72,6 @@ describe('PeopleCloudComponent', () => {
return fixture.debugElement.queryAll(By.css('[data-automation-id="adf-people-cloud-row"]'));
}
/**
* Get users chip list UI
*
* @returns list of debug elements
*/
function getUsersChipsUI(): DebugElement[] {
return fixture.debugElement.queryAll(By.css('mat-chip'));
}
/**
* Get the first user from the list
*
@@ -116,32 +83,29 @@ describe('PeopleCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
CoreTestingModule,
ProcessServiceCloudTestingModule,
PeopleCloudModule
]
imports: [TranslateModule.forRoot(), CoreTestingModule, ProcessServiceCloudTestingModule, PeopleCloudModule]
});
fixture = TestBed.createComponent(PeopleCloudComponent);
component = fixture.componentInstance;
element = fixture.nativeElement;
identityUserService = TestBed.inject(IDENTITY_USER_SERVICE_TOKEN);
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should populate placeholder when title is present', () => {
component.title = 'TITLE_KEY';
fixture.detectChanges();
const matLabel = getElement<HTMLInputElement>('#adf-people-cloud-title-id');
const matLabel = element.querySelector<HTMLInputElement>('#adf-people-cloud-title-id');
expect(matLabel.textContent).toEqual('TITLE_KEY');
});
it('should not populate placeholder when title is not present', () => {
it('should not populate placeholder when title is not present', () => {
fixture.detectChanges();
const matLabel = getElement<HTMLInputElement>('#adf-people-cloud-title-id');
const matLabel = element.querySelector<HTMLInputElement>('#adf-people-cloud-title-id');
expect(matLabel.textContent).toEqual('');
});
@@ -196,7 +160,9 @@ describe('PeopleCloudComponent', () => {
});
it('should not be able to search for a user that his email matches one of the excluded users email', async () => {
component.excludedUsers = [{ email: mockKielbasaSausage.email, username: 'new-username', firstName: 'new-first-name', lastName: 'new-last-name' }];
component.excludedUsers = [
{ email: mockKielbasaSausage.email, username: 'new-username', firstName: 'new-first-name', lastName: 'new-last-name' }
];
fixture.detectChanges();
await searchUsers('first-name');
@@ -205,7 +171,15 @@ describe('PeopleCloudComponent', () => {
});
it('should not be able to search for a user that his id matches one of the excluded users id', async () => {
component.excludedUsers = [{ id: mockKielbasaSausage.id, username: 'new-username', firstName: 'new-first-name', lastName: 'new-last-name', email: 'new-email@food.com' }];
component.excludedUsers = [
{
id: mockKielbasaSausage.id,
username: 'new-username',
firstName: 'new-first-name',
lastName: 'new-last-name',
email: 'new-email@food.com'
}
];
fixture.detectChanges();
await searchUsers('first-name');
@@ -214,7 +188,9 @@ describe('PeopleCloudComponent', () => {
});
it('should not be able to search for a user that his username matches one of the excluded users username', async () => {
component.excludedUsers = [{ username: mockKielbasaSausage.username, firstName: 'new-first-name', lastName: 'new-last-name', email: 'new-email@food.com' }];
component.excludedUsers = [
{ username: mockKielbasaSausage.username, firstName: 'new-first-name', lastName: 'new-last-name', email: 'new-email@food.com' }
];
fixture.detectChanges();
await searchUsers('first-name');
@@ -301,17 +277,20 @@ describe('PeopleCloudComponent', () => {
});
describe('No preselected users', () => {
it('should not pre-select any user when preSelectUsers is empty - single mode', () => {
it('should not pre-select any user when preSelectUsers is empty - single mode', async () => {
component.mode = 'single';
fixture.detectChanges();
expect(getUsersChipsUI().length).toEqual(0);
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(0);
});
it('should not pre-select any users when preSelectUsers is empty - multiple mode', () => {
it('should not pre-select any users when preSelectUsers is empty - multiple mode', async () => {
component.mode = 'multiple';
fixture.detectChanges();
expect(getUsersChipsUI().length).toEqual(0);
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toEqual(0);
});
});
@@ -327,14 +306,16 @@ describe('PeopleCloudComponent', () => {
element = fixture.nativeElement;
});
it('should show only one mat chip with the first preSelectedUser', () => {
expect(getUsersChipsUI().length).toEqual(1);
expect(getUsersChipsUI()[0].attributes['data-automation-id']).toEqual(`adf-people-cloud-chip-${mockPreselectedFoodUsers[0].username}`);
it('should show only one mat chip with the first preSelectedUser', async () => {
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toEqual(1);
const testId = await (await chips[0].host()).getAttribute('data-automation-id');
expect(testId).toEqual(`adf-people-cloud-chip-${mockPreselectedFoodUsers[0].username}`);
});
});
describe('Multiple Mode with Pre-selected Users', () => {
beforeEach(() => {
component.mode = 'multiple';
});
@@ -347,9 +328,15 @@ describe('PeopleCloudComponent', () => {
await fixture.whenStable();
fixture.detectChanges();
expect(getUsersChipsUI().length).toEqual(2);
expect(getUsersChipsUI()[0].attributes['data-automation-id']).toEqual(`adf-people-cloud-chip-${mockPreselectedFoodUsers[0].username}`);
expect(getUsersChipsUI()[1].attributes['data-automation-id']).toEqual(`adf-people-cloud-chip-${mockPreselectedFoodUsers[1].username}`);
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toEqual(2);
const testId1 = await (await chips[0].host()).getAttribute('data-automation-id');
const testId2 = await (await chips[1].host()).getAttribute('data-automation-id');
expect(testId1).toEqual(`adf-people-cloud-chip-${mockPreselectedFoodUsers[0].username}`);
expect(testId2).toEqual(`adf-people-cloud-chip-${mockPreselectedFoodUsers[1].username}`);
});
it('Should not show remove icon for pre-selected users if readonly property set to true', async () => {
@@ -361,12 +348,16 @@ describe('PeopleCloudComponent', () => {
const change = new SimpleChange(null, component.preSelectUsers, false);
component.ngOnChanges({ preSelectUsers: change });
await fixture.whenStable();
fixture.detectChanges();
await fixture.whenStable();
const removeIcon = getElement(`[data-automation-id="adf-people-cloud-chip-remove-icon-${mockPreselectedFoodUsers[0].username}"]`);
const removeIcon = element.querySelector(
`[data-automation-id="adf-people-cloud-chip-remove-icon-${mockPreselectedFoodUsers[0].username}"]`
);
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(2);
expect(getUsersChipsUI().length).toBe(2);
expect(component.preSelectUsers[0].readonly).toBeTruthy();
expect(component.preSelectUsers[1].readonly).toBeTruthy();
expect(removeIcon).toBeNull();
@@ -380,27 +371,32 @@ describe('PeopleCloudComponent', () => {
const removeUserSpy = spyOn(component.removeUser, 'emit');
await fixture.whenStable();
fixture.detectChanges();
await fixture.whenStable();
const removeIcon = getElement(`[data-automation-id="adf-people-cloud-chip-remove-icon-${mockPreselectedFoodUsers[0].username}"]`);
const removeIcon = element.querySelector<HTMLElement>(
`[data-automation-id="adf-people-cloud-chip-remove-icon-${mockPreselectedFoodUsers[0].username}"]`
);
expect(getUsersChipsUI().length).toBe(2);
expect(component.preSelectUsers[0].readonly).toBe(false, 'Removable');
expect(component.preSelectUsers[1].readonly).toBe(false, 'Removable');
let chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(2);
expect(component.preSelectUsers[0].readonly).toBe(false);
expect(component.preSelectUsers[1].readonly).toBe(false);
removeIcon.click();
fixture.detectChanges();
expect(removeUserSpy).toHaveBeenCalled();
expect(getUsersChipsUI().length).toBe(1);
chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(1);
});
describe('Component readonly mode', () => {
const change = new SimpleChange(null, mockPreselectedFoodUsers, false);
it('should chip list be disabled and show one single chip - single mode', () => {
it('should chip list be disabled and show one single chip - single mode', async () => {
component.mode = 'single';
component.readOnly = true;
component.preSelectUsers = mockPreselectedFoodUsers;
@@ -408,15 +404,14 @@ describe('PeopleCloudComponent', () => {
fixture.detectChanges();
const chipList = getElement('mat-chip-list');
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(1);
expect(getUsersChipsUI()).toBeDefined();
expect(chipList).toBeDefined();
expect(getUsersChipsUI().length).toBe(1);
expect(chipList.attributes['ng-reflect-disabled'].value).toEqual('true');
const chipList = await loader.getHarness(MatChipListHarness);
expect(await chipList.isDisabled()).toBe(true);
});
it('should chip list be disabled and show mat chips for all the preselected users - multiple mode', () => {
it('should chip list be disabled and show mat chips for all the preselected users - multiple mode', async () => {
component.mode = 'multiple';
component.readOnly = true;
component.preSelectUsers = mockPreselectedFoodUsers;
@@ -424,18 +419,16 @@ describe('PeopleCloudComponent', () => {
fixture.detectChanges();
const chipList = getElement('mat-chip-list');
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(2);
expect(getUsersChipsUI()).toBeDefined();
expect(chipList).toBeDefined();
expect(getUsersChipsUI().length).toBe(2);
expect(chipList.attributes['ng-reflect-disabled'].value).toEqual('true');
const chipList = await loader.getHarness(MatChipListHarness);
expect(await chipList.isDisabled()).toBe(true);
});
});
});
describe('Preselected users and validation enabled', () => {
beforeEach(() => {
spyOn(identityUserService, 'search').and.throwError('Invalid user');
component.validate = true;

View File

@@ -44,6 +44,9 @@ 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';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
@Component({
template: ` <adf-cloud-process-list #processListCloud>
@@ -68,6 +71,7 @@ class CustomTaskListComponent {
}
describe('ProcessListCloudComponent', () => {
let loader: HarnessLoader;
let component: ProcessListCloudComponent;
let fixture: ComponentFixture<ProcessListCloudComponent>;
let appConfig: AppConfigService;
@@ -118,6 +122,7 @@ describe('ProcessListCloudComponent', () => {
});
component.isColumnSchemaCreated$ = of(true).pipe(shareReplay(1));
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => {
@@ -132,41 +137,39 @@ describe('ProcessListCloudComponent', () => {
expect(component.columns.length).toEqual(10);
});
it('should display empty content when process list is empty', () => {
it('should display empty content when process list is empty', async () => {
const emptyList = { list: { entries: [] } };
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(emptyList));
fixture.detectChanges();
expect(component.isLoading).toBe(true);
let loadingContent = fixture.debugElement.query(By.css('mat-progress-spinner'));
expect(loadingContent.nativeElement).toBeDefined();
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(true);
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
component.ngOnChanges({ appName });
fixture.detectChanges();
loadingContent = fixture.debugElement.query(By.css('mat-progress-spinner'));
expect(loadingContent).toBeFalsy();
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
expect(emptyContent.nativeElement).toBeDefined();
});
it('should load spinner and show the content', () => {
it('should load spinner and show the content', async () => {
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
fixture.detectChanges();
expect(component.isLoading).toBe(true);
let loadingContent = fixture.debugElement.query(By.css('mat-progress-spinner'));
expect(loadingContent.nativeElement).toBeDefined();
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(true);
component.ngOnChanges({ appName });
fixture.detectChanges();
expect(component.isLoading).toBe(false);
loadingContent = fixture.debugElement.query(By.css('mat-progress-spinner'));
expect(loadingContent).toBeFalsy();
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
expect(emptyContent).toBeFalsy();

View File

@@ -21,7 +21,6 @@
data-automation-id="adf-select-cloud-process-dropdown">
<mat-label>{{ 'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.LABEL.TYPE' | translate }}</mat-label>
<input
#inputAutocomplete
matInput
formControlName="processDefinition"
[matAutocomplete]="auto"

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { SimpleChange, DebugElement } from '@angular/core';
import { SimpleChange } from '@angular/core';
import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { FormModel } from '@alfresco/adf-core';
import { of, throwError } from 'rxjs';
@@ -30,7 +30,6 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import {
fakeProcessDefinitions,
fakeStartForm,
@@ -50,8 +49,13 @@ import { ProcessInstanceCloud } from '../models/process-instance-cloud.model';
import { ESCAPE } from '@angular/cdk/keycodes';
import { ProcessDefinitionCloud, TaskVariableCloud } from '@alfresco/adf-process-services-cloud';
import { first } from 'rxjs/operators';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatAutocompleteHarness } from '@angular/material/autocomplete/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
describe('StartProcessCloudComponent', () => {
let loader: HarnessLoader;
let component: StartProcessCloudComponent;
let fixture: ComponentFixture<StartProcessCloudComponent>;
let processService: StartProcessCloudService;
@@ -64,18 +68,11 @@ describe('StartProcessCloudComponent', () => {
const firstChange = new SimpleChange(undefined, 'myApp', true);
const selectOptionByName = async (name: string) => {
const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown');
selectElement.click();
fixture.detectChanges();
await fixture.whenStable();
const options: any = fixture.debugElement.queryAll(By.css('.mat-autocomplete-panel .mat-option'));
const currentOption: DebugElement = options.find(
(option: DebugElement) => option.nativeElement.querySelector('.mat-option-text').innerHTML.trim() === name
);
const arrowButton = await loader.getHarness(MatButtonHarness.with({ selector: '#adf-select-process-dropdown' }));
await arrowButton.click();
if (currentOption) {
currentOption.nativeElement.click();
}
const panel = await loader.getHarness(MatAutocompleteHarness);
await panel.selectOption({ text: name });
};
const typeValueInto = (selector: any, value: string) => {
@@ -112,6 +109,7 @@ describe('StartProcessCloudComponent', () => {
spyOn(processService, 'updateProcess').and.returnValue(of());
startProcessSpy = spyOn(processService, 'startProcess').and.returnValue(of(fakeProcessInstance));
getStartEventFormStaticValuesMappingSpy = spyOn(processService, 'getStartEventFormStaticValuesMapping').and.returnValue(of([]));
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => {
@@ -372,27 +370,12 @@ describe('StartProcessCloudComponent', () => {
});
it('should display the correct number of processes in the select list', async () => {
await fixture.whenStable();
const arrowButton = await loader.getHarness(MatButtonHarness.with({ selector: '#adf-select-process-dropdown' }));
await arrowButton.click();
const arrowButton = fixture.nativeElement.querySelector('button#adf-select-process-dropdown');
arrowButton.click();
fixture.detectChanges();
const processLists = fixture.debugElement.query(By.css('.mat-autocomplete-panel'));
expect(processLists.children.length).toBe(4);
});
it('should display the option def details', async () => {
fixture.detectChanges();
await fixture.whenStable();
const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown');
selectElement.click();
fixture.detectChanges();
const optionElement = fixture.debugElement.queryAll(By.css('.mat-autocomplete-panel .mat-option'));
expect(selectElement).not.toBeNull();
expect(selectElement).toBeDefined();
expect(optionElement).not.toBeNull();
expect(optionElement).toBeDefined();
const panel = await loader.getHarness(MatAutocompleteHarness);
const options = await panel.getOptions();
expect(options.length).toBe(4);
});
it('should display the key when the processDefinition name is empty or null', async () => {
@@ -400,14 +383,12 @@ describe('StartProcessCloudComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown');
selectElement.click();
fixture.detectChanges();
const optionElement = fixture.debugElement.queryAll(By.css('.mat-autocomplete-panel .mat-option'));
expect(selectElement).not.toBeNull();
expect(selectElement).toBeDefined();
expect(optionElement).not.toBeNull();
expect(optionElement[0].nativeElement.textContent.trim()).toBe('NewProcess 1');
const arrowButton = await loader.getHarness(MatButtonHarness.with({ selector: '#adf-select-process-dropdown' }));
await arrowButton.click();
const panel = await loader.getHarness(MatAutocompleteHarness);
const options = await panel.getOptions();
expect(await options[0].getText()).toBe('NewProcess 1');
});
it('should indicate an error to the user if process defs cannot be loaded', async () => {
@@ -486,7 +467,7 @@ describe('StartProcessCloudComponent', () => {
component.processDefinitionName = 'process';
component.appName = 'myApp';
component.ngOnChanges({});
selectOptionByName('process');
await selectOptionByName('process');
fixture.detectChanges();
await fixture.whenStable();
@@ -550,20 +531,6 @@ describe('StartProcessCloudComponent', () => {
fixture.detectChanges();
});
it('should have floating labels for process name and type', async () => {
getDefinitionsSpy.and.returnValue(of(fakeProcessDefinitions));
component.ngOnChanges({ appName: change });
fixture.detectChanges();
await fixture.whenStable();
component.processForm.controls.processInstanceName.setValue('My sharona');
component.processForm.controls.processDefinition.setValue('process');
fixture.detectChanges();
const inputLabelsNodes = document.querySelectorAll('.mat-form-field-label');
expect(inputLabelsNodes.length).toBe(2);
});
it('should reload processes when appName input changed', async () => {
getDefinitionsSpy.and.returnValue(of(fakeProcessDefinitions));
component.ngOnChanges({ appName: firstChange });
@@ -837,7 +804,7 @@ describe('StartProcessCloudComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
component.processDefinitionName = 'processwithoutform1';
selectOptionByName(fakeProcessDefinitions[0].name);
await selectOptionByName(fakeProcessDefinitions[0].name);
fixture.detectChanges();
await fixture.whenStable();
expect(emitSpy).toHaveBeenCalledOnceWith(fakeProcessDefinitions[0]);

View File

@@ -33,6 +33,9 @@ import {
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';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
const taskDetails: TaskDetailsCloudModel = {
appName: 'simple-app',
@@ -50,7 +53,7 @@ const taskDetails: TaskDetailsCloudModel = {
};
describe('TaskFormCloudComponent', () => {
let loader: HarnessLoader;
let taskCloudService: TaskCloudService;
let identityUserService: IdentityUserService;
@@ -63,10 +66,7 @@ describe('TaskFormCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule]
});
taskDetails.status = TASK_ASSIGNED_STATE;
taskDetails.permissions = [TASK_VIEW_PERMISSION];
@@ -82,6 +82,7 @@ describe('TaskFormCloudComponent', () => {
fixture = TestBed.createComponent(TaskFormCloudComponent);
debugElement = fixture.debugElement;
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => {
@@ -89,7 +90,6 @@ describe('TaskFormCloudComponent', () => {
});
describe('Complete button', () => {
beforeEach(() => {
component.taskId = 'task1';
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
@@ -120,7 +120,6 @@ describe('TaskFormCloudComponent', () => {
});
describe('Claim/Unclaim buttons', () => {
beforeEach(() => {
spyOn(component, 'hasCandidateUsers').and.returnValue(true);
getTaskSpy.and.returnValue(of(taskDetails));
@@ -213,7 +212,6 @@ describe('TaskFormCloudComponent', () => {
});
describe('Cancel button', () => {
it('should show cancel button by default', () => {
component.appName = 'app1';
component.taskId = 'task1';
@@ -238,7 +236,6 @@ describe('TaskFormCloudComponent', () => {
});
describe('Inputs', () => {
it('should not show complete/claim/unclaim buttons when readOnly=true', () => {
component.appName = 'app1';
component.taskId = 'task1';
@@ -284,7 +281,6 @@ describe('TaskFormCloudComponent', () => {
});
describe('Events', () => {
beforeEach(() => {
component.appName = 'app1';
component.taskId = 'task1';
@@ -292,7 +288,7 @@ describe('TaskFormCloudComponent', () => {
});
it('should emit cancelClick when cancel button is clicked', async () => {
spyOn(component.cancelClick,'emit').and.stub();
spyOn(component.cancelClick, 'emit').and.stub();
fixture.detectChanges();
@@ -395,22 +391,18 @@ describe('TaskFormCloudComponent', () => {
expect(reloadSpy).toHaveBeenCalled();
});
it('should show loading template while task data is being loaded', () => {
it('should show loading template while task data is being loaded', async () => {
component.loading = true;
fixture.detectChanges();
const loadingTemplate = debugElement.query(By.css('mat-progress-spinner'));
expect(loadingTemplate).toBeDefined();
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(true);
});
it('should not show loading template while task data is not being loaded', () => {
it('should not show loading template while task data is not being loaded', async () => {
component.loading = false;
fixture.detectChanges();
const loadingTemplate = debugElement.query(By.css('mat-progress-spinner'));
expect(loadingTemplate).toBeNull();
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
});
it('should emit an executeOutcome event when form outcome executed', () => {

View File

@@ -27,12 +27,19 @@ 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';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
@Component({
template: `
<adf-cloud-service-task-list #taskListCloud>
template: ` <adf-cloud-service-task-list #taskListCloud>
<data-columns>
<data-column key="activityName" title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME" class="adf-full-width adf-name-column" [order]="2"></data-column>
<data-column
key="activityName"
title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME"
class="adf-full-width adf-name-column"
[order]="2"
></data-column>
<data-column key="startedDate" title="ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED" class="adf-hidden"></data-column>
</data-columns>
</adf-cloud-service-task-list>`
@@ -43,18 +50,16 @@ class CustomTaskListComponent {
}
@Component({
template: `
<adf-cloud-service-task-list>
<adf-custom-empty-content-template>
<p id="custom-id"></p>
</adf-custom-empty-content-template>
</adf-cloud-service-task-list>
`
<adf-cloud-service-task-list>
<adf-custom-empty-content-template>
<p id="custom-id"></p>
</adf-custom-empty-content-template>
</adf-cloud-service-task-list>
`
})
class EmptyTemplateComponent {
}
class EmptyTemplateComponent {}
@Component({
template: `
<adf-cloud-service-task-list>
template: ` <adf-cloud-service-task-list>
<data-columns>
<data-column [copyContent]="true" key="id" title="ADF_CLOUD_TASK_LIST.PROPERTIES.ID"></data-column>
<data-column key="activityName" title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME"></data-column>
@@ -67,6 +72,7 @@ class CustomCopyContentTaskListComponent {
}
describe('ServiceTaskListCloudComponent', () => {
let loader: HarnessLoader;
let component: ServiceTaskListCloudComponent;
let fixture: ComponentFixture<ServiceTaskListCloudComponent>;
let appConfig: AppConfigService;
@@ -74,13 +80,8 @@ describe('ServiceTaskListCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
declarations: [
EmptyTemplateComponent
]
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
declarations: [EmptyTemplateComponent]
});
appConfig = TestBed.inject(AppConfigService);
serviceTaskListCloudService = TestBed.inject(ServiceTaskListCloudService);
@@ -108,6 +109,7 @@ describe('ServiceTaskListCloudComponent', () => {
});
component.isColumnSchemaCreated$ = of(true).pipe(shareReplay(1));
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => {
@@ -120,19 +122,18 @@ describe('ServiceTaskListCloudComponent', () => {
expect(component.columns.length).toEqual(3);
});
it('should display empty content when process list is empty', () => {
it('should display empty content when process list is empty', async () => {
const emptyList = { list: { entries: [] } };
spyOn(serviceTaskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(emptyList));
fixture.detectChanges();
const loadingContent = fixture.debugElement.query(By.css('mat-progress-spinner'));
expect(loadingContent).toBeFalsy();
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
expect(emptyContent.nativeElement).toBeDefined();
});
it('should load spinner and show the content', () => {
it('should load spinner and show the content', async () => {
spyOn(serviceTaskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
@@ -140,8 +141,7 @@ describe('ServiceTaskListCloudComponent', () => {
component.ngOnChanges({ appName });
fixture.detectChanges();
const loadingContent = fixture.debugElement.query(By.css('mat-progress-spinner'));
expect(loadingContent).toBeFalsy();
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
expect(emptyContent).toBeFalsy();
@@ -235,7 +235,6 @@ describe('ServiceTaskListCloudComponent', () => {
});
describe('component changes', () => {
beforeEach(() => {
component.rows = fakeServiceTask.list.entries;
fixture.detectChanges();
@@ -283,13 +282,15 @@ describe('ServiceTaskListCloudComponent', () => {
it('should reload task list when sorting on a column changes', () => {
const getServiceTaskByRequestSpy = spyOn(serviceTaskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
component.onSortingChanged(new CustomEvent('sorting-changed', {
detail: {
key: 'fakeName',
direction: 'asc'
},
bubbles: true
}));
component.onSortingChanged(
new CustomEvent('sorting-changed', {
detail: {
key: 'fakeName',
direction: 'asc'
},
bubbles: true
})
);
fixture.detectChanges();
expect(component.sorting).toEqual([
new TaskListCloudSortingModel({
@@ -307,15 +308,14 @@ describe('ServiceTaskListCloudComponent', () => {
const size = component.size;
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();
});
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();
});
const pagination = {
maxItems: 250,
@@ -334,15 +334,14 @@ describe('ServiceTaskListCloudComponent', () => {
maxItems: 250,
skipCount: 200
};
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();
});
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();
});
component.updatePagination(pagination);
});
@@ -358,14 +357,8 @@ describe('ServiceTaskListCloudComponent: Injecting custom columns for task list
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
declarations: [
CustomTaskListComponent,
CustomCopyContentTaskListComponent
]
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
declarations: [CustomTaskListComponent, CustomCopyContentTaskListComponent]
});
serviceTaskListCloudService = TestBed.inject(ServiceTaskListCloudService);
@@ -396,9 +389,7 @@ describe('ServiceTaskListCloudComponent: Injecting custom columns for task list
customCopyComponent.taskList.reload();
copyFixture.detectChanges();
copyFixture.debugElement
.query(By.css('span[title="04fdf69f-4ddd-48ab-9563-da776c9b163c"]'))
.triggerEventHandler('mouseenter');
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();
@@ -408,9 +399,7 @@ describe('ServiceTaskListCloudComponent: Injecting custom columns for task list
customCopyComponent.taskList.reload();
copyFixture.detectChanges();
copyFixture.debugElement
.query(By.css('span[title="serviceTaskName"]'))
.triggerEventHandler('mouseenter');
copyFixture.debugElement.query(By.css('span[title="serviceTaskName"]')).triggerEventHandler('mouseenter');
copyFixture.detectChanges();
expect(copyFixture.debugElement.query(By.css('.adf-copy-tooltip'))).toBeNull();
@@ -426,10 +415,7 @@ describe('ServiceTaskListCloudComponent: Copy cell content directive from app.co
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule]
});
appConfig = TestBed.inject(AppConfigService);
serviceTaskListCloudService = TestBed.inject(ServiceTaskListCloudService);
@@ -457,7 +443,6 @@ describe('ServiceTaskListCloudComponent: Copy cell content directive from app.co
fixture = TestBed.createComponent(ServiceTaskListCloudComponent);
component = fixture.componentInstance;
taskSpy = spyOn(serviceTaskListCloudService, 'getServiceTaskByRequest').and.returnValue(of(fakeServiceTask));
});
afterEach(() => {
fixture.destroy();
@@ -470,8 +455,7 @@ describe('ServiceTaskListCloudComponent: Copy cell content directive from app.co
component.reload();
fixture.detectChanges();
const columnWithCopyContentFlagTrue = fixture.debugElement
.query(By.css('span[title="04fdf69f-4ddd-48ab-9563-da776c9b163c"]'));
const columnWithCopyContentFlagTrue = fixture.debugElement.query(By.css('span[title="04fdf69f-4ddd-48ab-9563-da776c9b163c"]'));
columnWithCopyContentFlagTrue.triggerEventHandler('mouseenter');
@@ -486,8 +470,7 @@ describe('ServiceTaskListCloudComponent: Copy cell content directive from app.co
component.reload();
fixture.detectChanges();
const columnWithCopyContentFlagNotTrue = fixture.debugElement
.query(By.css('span[title="serviceTaskName"]'));
const columnWithCopyContentFlagNotTrue = fixture.debugElement.query(By.css('span[title="serviceTaskName"]'));
columnWithCopyContentFlagNotTrue.triggerEventHandler('mouseenter');

View File

@@ -18,17 +18,19 @@
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,
AlfrescoApiService,
AlfrescoApiServiceMock,
AppConfigServiceMock,
TranslationService,
TranslationMock
} 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';
@@ -43,16 +45,29 @@ 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';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
@Component({
template: `
<adf-cloud-task-list #taskListCloud>
template: ` <adf-cloud-task-list #taskListCloud>
<data-columns>
<data-column id="name" key="name" title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME" class="adf-full-width adf-name-column" [order]="3"></data-column>
<data-column
id="name"
key="name"
title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME"
class="adf-full-width adf-name-column"
[order]="3"
></data-column>
<data-column id="created" key="created" title="ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED" class="adf-hidden"></data-column>
<data-column id="startedBy" key="startedBy" title="ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED" class="adf-desktop-only dw-dt-col-3 adf-ellipsis-cell">
<data-column
id="startedBy"
key="startedBy"
title="ADF_CLOUD_TASK_LIST.PROPERTIES.CREATED"
class="adf-desktop-only dw-dt-col-3 adf-ellipsis-cell"
>
<ng-template let-entry="$implicit">
<div>{{getFullName(entry.row?.obj?.startedBy)}}</div>
<div>{{ getFullName(entry.row?.obj?.startedBy) }}</div>
</ng-template>
</data-column>
</data-columns>
@@ -68,18 +83,16 @@ class CustomTaskListComponent {
}
@Component({
template: `
<adf-cloud-task-list>
<adf-custom-empty-content-template>
<p id="custom-id"></p>
</adf-custom-empty-content-template>
</adf-cloud-task-list>
`
<adf-cloud-task-list>
<adf-custom-empty-content-template>
<p id="custom-id"></p>
</adf-custom-empty-content-template>
</adf-cloud-task-list>
`
})
class EmptyTemplateComponent {
}
class EmptyTemplateComponent {}
@Component({
template: `
<adf-cloud-task-list>
template: ` <adf-cloud-task-list>
<data-columns>
<data-column [copyContent]="true" key="id" title="ADF_CLOUD_TASK_LIST.PROPERTIES.ID"></data-column>
<data-column key="name" title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME"></data-column>
@@ -92,6 +105,7 @@ class CustomCopyContentTaskListComponent {
}
describe('TaskListCloudComponent', () => {
let loader: HarnessLoader;
let component: TaskListCloudComponent;
let fixture: ComponentFixture<TaskListCloudComponent>;
let appConfig: AppConfigService;
@@ -103,10 +117,7 @@ describe('TaskListCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
providers: [
{
provide: TASK_LIST_CLOUD_TOKEN,
@@ -144,6 +155,7 @@ describe('TaskListCloudComponent', () => {
});
component.isColumnSchemaCreated$ = of(true).pipe(shareReplay(1));
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => {
@@ -162,7 +174,7 @@ describe('TaskListCloudComponent', () => {
expect(component.columns.length).toEqual(3);
});
it('should display empty content when process list is empty', () => {
it('should display empty content when process list is empty', async () => {
const emptyList = { list: { entries: [] } };
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(emptyList));
fixture.detectChanges();
@@ -171,14 +183,13 @@ describe('TaskListCloudComponent', () => {
component.ngOnChanges({ appName });
fixture.detectChanges();
const loadingContent = fixture.debugElement.query(By.css('mat-progress-spinner'));
expect(loadingContent).toBeFalsy();
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
expect(emptyContent.nativeElement).toBeDefined();
});
it('should load spinner and show the content', () => {
it('should load spinner and show the content', async () => {
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
@@ -186,8 +197,7 @@ describe('TaskListCloudComponent', () => {
component.ngOnChanges({ appName });
fixture.detectChanges();
const loadingContent = fixture.debugElement.query(By.css('mat-progress-spinner'));
expect(loadingContent).toBeFalsy();
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
expect(emptyContent).toBeFalsy();
@@ -374,7 +384,6 @@ describe('TaskListCloudComponent', () => {
});
describe('component changes', () => {
beforeEach(() => {
component.rows = fakeGlobalTasks.list.entries;
fixture.detectChanges();
@@ -431,13 +440,15 @@ describe('TaskListCloudComponent', () => {
it('should reload task list when sorting on a column changes', () => {
const getTaskByRequestSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
component.onSortingChanged(new CustomEvent('sorting-changed', {
detail: {
key: 'fakeName',
direction: 'asc'
},
bubbles: true
}));
component.onSortingChanged(
new CustomEvent('sorting-changed', {
detail: {
key: 'fakeName',
direction: 'asc'
},
bubbles: true
})
);
fixture.detectChanges();
expect(component.sorting).toEqual([
new TaskListCloudSortingModel({
@@ -455,15 +466,14 @@ describe('TaskListCloudComponent', () => {
const size = component.size;
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();
});
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();
});
const pagination = {
maxItems: 250,
@@ -482,15 +492,14 @@ describe('TaskListCloudComponent', () => {
maxItems: 250,
skipCount: 200
};
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();
});
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();
});
component.updatePagination(pagination);
});
@@ -506,14 +515,8 @@ describe('TaskListCloudComponent: Injecting custom colums for tasklist - CustomT
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
],
declarations: [
CustomTaskListComponent,
CustomCopyContentTaskListComponent
]
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule],
declarations: [CustomTaskListComponent, CustomCopyContentTaskListComponent]
});
taskListCloudService = TestBed.inject(TASK_LIST_CLOUD_TOKEN);
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTasks));
@@ -543,9 +546,7 @@ describe('TaskListCloudComponent: Injecting custom colums for tasklist - CustomT
customCopyComponent.taskList.reload();
copyFixture.detectChanges();
copyFixture.debugElement
.query(By.css('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'))
.triggerEventHandler('mouseenter');
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();
@@ -555,9 +556,7 @@ describe('TaskListCloudComponent: Injecting custom colums for tasklist - CustomT
customCopyComponent.taskList.reload();
copyFixture.detectChanges();
copyFixture.debugElement
.query(By.css('span[title="standalone-subtask"]'))
.triggerEventHandler('mouseenter');
copyFixture.debugElement.query(By.css('span[title="standalone-subtask"]')).triggerEventHandler('mouseenter');
copyFixture.detectChanges();
expect(copyFixture.debugElement.query(By.css('.adf-copy-tooltip'))).toBeNull();
@@ -570,12 +569,7 @@ describe('TaskListCloudComponent: Creating an empty custom template - EmptyTempl
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientModule,
NoopAnimationsModule,
TranslateModule.forRoot(),
TaskListCloudModule
],
imports: [HttpClientModule, NoopAnimationsModule, TranslateModule.forRoot(), TaskListCloudModule],
providers: [
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
{ provide: AppConfigService, useClass: AppConfigServiceMock },
@@ -612,10 +606,7 @@ describe('TaskListCloudComponent: Copy cell content directive from app.config sp
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule]
});
appConfig = TestBed.inject(AppConfigService);
taskListCloudService = TestBed.inject(TASK_LIST_CLOUD_TOKEN);
@@ -663,8 +654,7 @@ describe('TaskListCloudComponent: Copy cell content directive from app.config sp
component.reload();
fixture.detectChanges();
const columnWithCopyContentFlagTrue = fixture.debugElement
.query(By.css('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'));
const columnWithCopyContentFlagTrue = fixture.debugElement.query(By.css('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'));
columnWithCopyContentFlagTrue.triggerEventHandler('mouseenter');
@@ -679,8 +669,7 @@ describe('TaskListCloudComponent: Copy cell content directive from app.config sp
component.reload();
fixture.detectChanges();
const cell = fixture.debugElement
.query(By.css('[data-automation-id="text_ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NONE"]'));
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');
});
@@ -695,15 +684,20 @@ describe('TaskListCloudComponent: Copy cell content directive from app.config sp
const emptyContent = fixture.debugElement.query(By.css('.adf-empty-content'));
expect(emptyContent.nativeElement).toBeDefined();
expect(component.replacePriorityValues({
obj: {},
isSelected: false,
hasValue: () => false,
getValue: () => undefined
}, {
type: 'text',
key: 'priority'
})).toEqual(undefined);
expect(
component.replacePriorityValues(
{
obj: {},
isSelected: false,
hasValue: () => false,
getValue: () => undefined
},
{
type: 'text',
key: 'priority'
}
)
).toEqual(undefined);
});
it('replacePriorityValues should return replaced value when rows are defined', () => {
@@ -714,17 +708,21 @@ describe('TaskListCloudComponent: Copy cell content directive from app.config sp
component.ngOnChanges({ appName });
fixture.detectChanges();
expect(component.replacePriorityValues({
obj: {
priority: 1
},
isSelected: false,
hasValue: () => false,
getValue: () => undefined
}, {
type: 'text',
key: 'priority'
})).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.LOW');
expect(
component.replacePriorityValues(
{
obj: {
priority: 1
},
isSelected: false,
hasValue: () => false,
getValue: () => undefined
},
{
type: 'text',
key: 'priority'
}
)
).toEqual('ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.LOW');
});
});