[AAE-1975] Add no results template when searching in People/Group clo… (#5479)

* [AAE-1975] Add no results template when searching in People/Group cloud component

* [AAE-1975] Add timeout for check no results e2e method

* [AAE-1975] Adapt unit tests, add no results checks

* [AAE-1975] Fix styling, remove error icon and red colour

* [AAE-1975] Remove timeout
This commit is contained in:
arditdomi
2020-02-24 15:37:55 +00:00
committed by GitHub
parent 536e2587ea
commit 56474bc96e
10 changed files with 119 additions and 65 deletions

View File

@@ -2,7 +2,7 @@
<mat-form-field class="adf-cloud-group">
<mat-label *ngIf="!isReadonly()"
id="adf-group-cloud-title-id">{{ (title || 'ADF_CLOUD_GROUPS.SEARCH-GROUP') | translate }}</mat-label>
<mat-chip-list #groupChipList [disabled]="isReadonly() || isValidationLoading()" data-automation-id="adf-cloud-group-chip-list" class="apa-group-chip-list">
<mat-chip-list #groupChipList [disabled]="isReadonly() || isValidationLoading()" data-automation-id="adf-cloud-group-chip-list">
<mat-chip
*ngFor="let group of selectedGroups"
[removable]="!(group.readonly)"
@@ -34,18 +34,28 @@
(optionSelected)="onSelect($event.option.value)"
[displayWith]="getDisplayName"
data-automation-id="adf-cloud-group-autocomplete">
<ng-container *ngIf="(searchGroups$ | async)?.length else noResults">
<mat-option *ngFor="let group of searchGroups$ | async; let i = index" [value]="group"
[attr.data-automation-id]="'adf-cloud-group-chip-' + group.name">
<div class="adf-cloud-group-row" id="adf-group-{{i}}" fxLayout="row" fxLayoutAlign="start center"
data-automation-id="adf-cloud-group-row"
fxLayoutGap="20px">
<button class="adf-group-short-name" mat-fab>{{group | groupNameInitial }}</button>
<span>{{group.name}}</span>
</div>
</mat-option>
</ng-container>
<ng-template #noResults>
<mat-option *ngIf="searchGroupsControl.hasError('searchTypingError') && !searchLoading" disabled
class="adf-cloud-group-option-not-active"
data-automation-id="adf-cloud-group-no-results">
<span> {{ 'ADF_CLOUD_GROUPS.ERROR.NOT_FOUND' | translate : { groupName: searchedValue } }}</span>
</mat-option>
</ng-template>
</mat-autocomplete>
</mat-form-field>
<mat-progress-bar
*ngIf="isLoading"
*ngIf="validationLoading"
mode="indeterminate">
</mat-progress-bar>

View File

@@ -14,6 +14,10 @@
&-cloud-group {
width: 100%;
&-option-not-active {
background: inherit !important;
}
.mat-form-field {
width: 100%;
}

View File

@@ -97,7 +97,7 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(5);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-cloud-group-row"]')).length).toEqual(5);
expect(findGroupsByNameSpy).toHaveBeenCalled();
done();
});
@@ -118,7 +118,7 @@ describe('GroupCloudComponent', () => {
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(4);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-cloud-group-row"]')).length).toEqual(4);
done();
});
});
@@ -134,7 +134,7 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('mat-option')).toBeNull();
expect(element.querySelector('[data-automation-id="adf-cloud-group-row"]')).toBeNull();
done();
});
});
@@ -257,7 +257,7 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(5);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-cloud-group-row"]')).length).toEqual(5);
done();
});
});
@@ -275,7 +275,8 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelectorAll('mat-option').length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-cloud-group-row"]')).length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-cloud-group-no-results"]')).length).toEqual(1);
done();
});
});
@@ -292,7 +293,7 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(5);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-cloud-group-row"]')).length).toEqual(5);
expect(checkGroupHasAnyClientAppRoleSpy).toHaveBeenCalled();
done();
});
@@ -311,7 +312,8 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-cloud-group-row"]')).length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-cloud-group-no-results"]')).length).toEqual(1);
expect(checkGroupHasAnyClientAppRoleSpy).toHaveBeenCalled();
done();
});
@@ -433,7 +435,7 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(5);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-cloud-group-row"]')).length).toEqual(5);
expect(checkGroupHasRoleSpy).toHaveBeenCalledTimes(5);
done();
});
@@ -451,7 +453,8 @@ describe('GroupCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelectorAll('mat-option').length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-cloud-group-row"]')).length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-cloud-group-no-results"]')).length).toEqual(1);
expect(checkGroupHasRoleSpy).toHaveBeenCalled();
done();
});

View File

@@ -129,7 +129,8 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
validateGroupsMessage: string;
searchedValue = '';
isLoading = false;
validationLoading = false;
searchLoading = false;
constructor(
private identityGroupService: IdentityGroupService,
@@ -178,6 +179,7 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
initSearch(): void {
this.searchGroupsControl.valueChanges.pipe(
filter((value) => {
this.searchLoading = true;
return typeof value === 'string';
}),
tap((value: string) => {
@@ -201,6 +203,7 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
),
mergeMap((groups) => {
this.resetSearchGroups();
this.searchLoading = false;
return groups;
}),
filter(group => !this.isGroupAlreadySelected(group)),
@@ -308,9 +311,9 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
}
this.groupChipsCtrl.setValue(this.selectedGroups[0].name);
if (this.isValidationEnabled()) {
this.isLoading = true;
this.validationLoading = true;
await this.validatePreselectGroups();
this.isLoading = false;
this.validationLoading = false;
}
}
@@ -322,6 +325,7 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
}
onSelect(group: IdentityGroupModel): void {
if (group) {
this.selectGroup.emit(group);
if (this.isMultipleMode()) {
@@ -340,6 +344,7 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
this.changedGroups.emit(this.selectedGroups);
this.resetSearchGroups();
}
}
onRemove(groupToRemove: IdentityGroupModel): void {
this.removeGroup.emit(groupToRemove);
@@ -474,7 +479,7 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
}
isValidationLoading(): boolean {
return this.isValidationEnabled() && this.isLoading;
return this.isValidationEnabled() && this.validationLoading;
}
setFocus(isFocused: boolean) {

View File

@@ -30,16 +30,26 @@
#auto="matAutocomplete"
(optionSelected)="onSelect($event.option.value)"
[displayWith]="getDisplayName">
<ng-container *ngIf="(searchUsers$ | async)?.length else noResults" >
<mat-option *ngFor="let user of searchUsers$ | async; let i = index" [value]="user">
<div class="adf-people-cloud-row" id="adf-people-cloud-user-{{i}}">
<div class="adf-people-cloud-row" id="adf-people-cloud-user-{{i}}"
data-automation-id="adf-people-cloud-row">
<div [outerHTML]="user | usernameInitials:'adf-people-widget-pic'"></div>
<span class="adf-people-label-name"> {{user | fullName}}</span>
</div>
</mat-option>
</ng-container>
<ng-template #noResults>
<mat-option *ngIf="searchUserCtrl.hasError('searchTypingError') && !searchLoading" disabled
class="adf-people-cloud-option-not-active"
data-automation-id="adf-people-cloud-no-results">
<span> {{ 'ADF_CLOUD_USERS.ERROR.NOT_FOUND' | translate : { userName: searchedValue } }}</span>
</mat-option>
</ng-template>
</mat-autocomplete>
</mat-form-field>
<mat-progress-bar
*ngIf="isLoading"
*ngIf="validationLoading"
mode="indeterminate">
</mat-progress-bar>

View File

@@ -8,6 +8,10 @@
&-people-cloud {
width: 100%;
&-option-not-active {
background: inherit !important;
}
}
&-people-cloud-list {

View File

@@ -113,7 +113,7 @@ describe('PeopleCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(3);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-people-cloud-row"]')).length).toEqual(3);
expect(findUsersByNameSpy).toHaveBeenCalled();
done();
});
@@ -134,7 +134,7 @@ describe('PeopleCloudComponent', () => {
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(2);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-people-cloud-row"]')).length).toEqual(2);
done();
});
});
@@ -190,7 +190,7 @@ describe('PeopleCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('mat-option')).toBeNull();
expect(element.querySelector('[data-automation-id="adf-people-cloud-row"]')).toBeNull();
done();
});
});
@@ -330,7 +330,8 @@ describe('PeopleCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelectorAll('mat-option').length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-people-cloud-row"]')).length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-people-cloud-no-results"]')).length).toEqual(1);
done();
});
});
@@ -347,7 +348,7 @@ describe('PeopleCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(3);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-people-cloud-row"]')).length).toEqual(3);
expect(checkUserHasAnyClientAppRoleSpy).toHaveBeenCalled();
done();
});
@@ -366,7 +367,8 @@ describe('PeopleCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-people-cloud-row"]')).length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-people-cloud-no-results"]')).length).toEqual(1);
expect(checkUserHasAnyClientAppRoleSpy).toHaveBeenCalled();
done();
});
@@ -486,7 +488,7 @@ describe('PeopleCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(3);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-people-cloud-row"]')).length).toEqual(3);
expect(checkUserHasRoleSpy).toHaveBeenCalledTimes(3);
done();
});
@@ -504,7 +506,8 @@ describe('PeopleCloudComponent', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelectorAll('mat-option').length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-people-cloud-row"]')).length).toEqual(0);
expect(fixture.debugElement.queryAll(By.css('[data-automation-id="adf-people-cloud-no-results"]')).length).toEqual(1);
expect(checkUserHasRoleSpy).toHaveBeenCalled();
done();
});

View File

@@ -138,7 +138,8 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
validateUsersMessage: string;
searchedValue = '';
isLoading = false;
validationLoading = false;
searchLoading = false;
constructor(
private identityUserService: IdentityUserService,
@@ -183,6 +184,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
private initSearch(): void {
this.searchUserCtrl.valueChanges.pipe(
filter((value) => {
this.searchLoading = true;
return typeof value === 'string';
}),
tap((value: string) => {
@@ -207,6 +209,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
this.identityUserService.findUsersByName(search.trim())),
mergeMap((users) => {
this.resetSearchUsers();
this.searchLoading = false;
return users;
}),
filter(user => !this.isUserAlreadySelected(user)),
@@ -283,9 +286,9 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
}
this.userChipsCtrl.setValue(this.selectedUsers[0].username);
if (this.isValidationEnabled()) {
this.isLoading = true;
this.validationLoading = true;
await this.validatePreselectUsers();
this.isLoading = false;
this.validationLoading = false;
}
}
@@ -381,6 +384,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
}
onSelect(user: IdentityUserModel): void {
if (user) {
this.selectUser.emit(user);
if (this.isMultipleMode()) {
@@ -399,6 +403,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
this.changedUsers.emit(this.selectedUsers);
this.resetSearchUsers();
}
}
onRemove(userToRemove: IdentityUserModel): void {
this.removeUser.emit(userToRemove);
@@ -522,7 +527,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
}
isValidationLoading(): boolean {
return this.isValidationEnabled() && this.isLoading;
return this.isValidationEnabled() && this.validationLoading;
}
setFocus(isFocused: boolean) {

View File

@@ -97,4 +97,9 @@ export class GroupCloudComponentPage {
}
}
async checkNoResultsFoundError(): Promise<void> {
const errorLocator = element(by.css('[data-automation-id="adf-cloud-group-no-results"]'));
await BrowserVisibility.waitUntilElementIsVisible(errorLocator);
}
}

View File

@@ -133,4 +133,9 @@ export class PeopleCloudComponentPage {
}
}
async checkNoResultsFoundError(): Promise<void> {
const errorLocator = element(by.css('[data-automation-id="adf-people-cloud-no-results"]'));
await BrowserVisibility.waitUntilElementIsVisible(errorLocator);
}
}