[AAE-1594][AAE-1631] Fix not able to search for specific users, valid… (#5429)

* [AAE-1594][AAE-1631] Fix not able to search for specific users, validation not working for partial username

* [AAE-1594][AAE-1631] Fix unit tests

* [AAE-1594] Refactor comparing preselcted user with keycloak user, add unit tests for search

* [AAE-1594] Add missing undefined check

* [AAE-1594] Ignore blank space user/groups search
This commit is contained in:
arditdomi
2020-02-03 10:15:18 +00:00
committed by GitHub
parent 0a25254691
commit d9e0847b18
4 changed files with 113 additions and 25 deletions

View File

@@ -102,6 +102,26 @@ describe('GroupCloudComponent', () => {
}); });
}); });
it('should not be able to search for a group that its name matches one of the preselected groups name', (done) => {
component.preSelectGroups = [{ name: mockIdentityGroups[0].name }];
const changes = new SimpleChange(null, [{ name: mockIdentityGroups[0].name }], false);
component.ngOnChanges({ 'preSelectGroups': changes });
fixture.detectChanges();
const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
inputHTMLElement.focus();
inputHTMLElement.value = 'mock-group';
inputHTMLElement.dispatchEvent(new Event('keyup'));
inputHTMLElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(4);
done();
});
});
it('should hide result list if input is empty', (done) => { it('should hide result list if input is empty', (done) => {
fixture.detectChanges(); fixture.detectChanges();
const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');

View File

@@ -190,9 +190,12 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
return typeof value === 'string'; return typeof value === 'string';
}), }),
tap((value) => { tap((value) => {
if (value.trim()) {
this.searchedValue = value; this.searchedValue = value;
if (value) {
this.setTypingError(); this.setTypingError();
} else {
this.searchGroupsControl.markAsPristine();
this.searchGroupsControl.markAsUntouched();
} }
}), }),
tap(() => { tap(() => {
@@ -238,7 +241,7 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
} }
private isGroupAlreadySelected(group: IdentityGroupModel): boolean { private isGroupAlreadySelected(group: IdentityGroupModel): boolean {
if (this.selectedGroups && this.selectedGroups.length > 0 && this.isMultipleMode()) { if (this.selectedGroups && this.selectedGroups.length > 0) {
const result = this.selectedGroups.find((selectedGroup: IdentityGroupModel) => { const result = this.selectedGroups.find((selectedGroup: IdentityGroupModel) => {
return selectedGroup.name === group.name; return selectedGroup.name === group.name;
}); });
@@ -440,7 +443,7 @@ export class GroupCloudComponent implements OnInit, OnChanges, OnDestroy {
} }
private createSearchParam(value: string): IdentityGroupSearchParam { private createSearchParam(value: string): IdentityGroupSearchParam {
const queryParams: IdentityGroupSearchParam = { name: value }; const queryParams: IdentityGroupSearchParam = { name: value.trim() };
return queryParams; return queryParams;
} }

View File

@@ -116,6 +116,66 @@ describe('PeopleCloudComponent', () => {
}); });
}); });
it('should not be able to search for a user that his username matches one of the preselected users username', (done) => {
component.preSelectUsers = [{ username: mockUsers[0].username }];
const changes = new SimpleChange(null, [{ username: mockUsers[0].username }], false);
component.ngOnChanges({ 'preSelectUsers': changes });
fixture.detectChanges();
const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
inputHTMLElement.focus();
inputHTMLElement.value = 'first-name';
inputHTMLElement.dispatchEvent(new Event('keyup'));
inputHTMLElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(2);
done();
});
});
it('should not be able to search for a user that his id matches one of the preselected users id', (done) => {
component.preSelectUsers = [{ id: mockUsers[0].id }];
const changes = new SimpleChange(null, [{ id: mockUsers[0].id }], false);
component.ngOnChanges({ 'preSelectUsers': changes });
fixture.detectChanges();
const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
inputHTMLElement.focus();
inputHTMLElement.value = 'first-name';
inputHTMLElement.dispatchEvent(new Event('keyup'));
inputHTMLElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(2);
done();
});
});
it('should not be able to search for a user that his email matches one of the preselected users email', (done) => {
component.preSelectUsers = [{ email: mockUsers[0].email }];
const changes = new SimpleChange(null, [{ email: mockUsers[0].email }], false);
component.ngOnChanges({ 'preSelectUsers': changes });
fixture.detectChanges();
const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
inputHTMLElement.focus();
inputHTMLElement.value = 'first-name';
inputHTMLElement.dispatchEvent(new Event('keyup'));
inputHTMLElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toEqual(2);
done();
});
});
it('should hide result list if input is empty', (done) => { it('should hide result list if input is empty', (done) => {
fixture.detectChanges(); fixture.detectChanges();
const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
@@ -133,7 +193,6 @@ describe('PeopleCloudComponent', () => {
it('should selectedUser and changedUsers emit, update selected users when a user is selected', (done) => { it('should selectedUser and changedUsers emit, update selected users when a user is selected', (done) => {
const user = { username: 'username' }; const user = { username: 'username' };
fixture.detectChanges(); fixture.detectChanges();
spyOn(component, 'isPreselectedUserValid').and.returnValue(true);
const selectEmitSpy = spyOn(component.selectUser, 'emit'); const selectEmitSpy = spyOn(component.selectUser, 'emit');
const changedUsersSpy = spyOn(component.changedUsers, 'emit'); const changedUsersSpy = spyOn(component.changedUsers, 'emit');
component.onSelect(user); component.onSelect(user);
@@ -514,8 +573,6 @@ describe('PeopleCloudComponent', () => {
it('should check validation only for the first user and emit warning when user is invalid - single mode', (done) => { it('should check validation only for the first user and emit warning when user is invalid - single mode', (done) => {
spyOn(identityService, 'findUserById').and.returnValue(Promise.resolve([])); spyOn(identityService, 'findUserById').and.returnValue(Promise.resolve([]));
spyOn(component, 'isPreselectedUserValid').and.returnValue(false);
const expectedWarning = { const expectedWarning = {
message: 'INVALID_PRESELECTED_USERS', message: 'INVALID_PRESELECTED_USERS',
users: [{ users: [{

View File

@@ -189,16 +189,20 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
filter((value) => { filter((value) => {
return typeof value === 'string'; return typeof value === 'string';
}), }),
tap((value) => { tap((value: string) => {
if (value.trim()) {
this.searchedValue = value; this.searchedValue = value;
if (value) {
this.setTypingError(); this.setTypingError();
} else {
this.searchUserCtrl.markAsPristine();
this.searchUserCtrl.markAsUntouched();
} }
}), }),
tap(() => { tap(() => {
this.resetSearchUsers(); this.resetSearchUsers();
}), }),
switchMap((search) => this.identityUserService.findUsersByName(search)), switchMap((search) =>
this.identityUserService.findUsersByName(search.trim())),
mergeMap((users) => { mergeMap((users) => {
this.resetSearchUsers(); this.resetSearchUsers();
return users; return users;
@@ -259,10 +263,10 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
map((filteredUser: { hasRole: boolean, user: IdentityUserModel }) => filteredUser.user)); map((filteredUser: { hasRole: boolean, user: IdentityUserModel }) => filteredUser.user));
} }
private isUserAlreadySelected(user: IdentityUserModel): boolean { private isUserAlreadySelected(searchUser: IdentityUserModel): boolean {
if (this.selectedUsers && this.selectedUsers.length > 0) { if (this.selectedUsers && this.selectedUsers.length > 0) {
const result = this.selectedUsers.find((selectedUser) => { const result = this.selectedUsers.find((selectedUser) => {
return selectedUser.id === user.id || selectedUser.email === user.email || selectedUser.username === user.username; return this.compare(selectedUser, searchUser);
}); });
return !!result; return !!result;
@@ -297,17 +301,17 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
preselectedUsersToValidate = this.removeDuplicatedUsers(this.preSelectUsers); preselectedUsersToValidate = this.removeDuplicatedUsers(this.preSelectUsers);
} }
await Promise.all(preselectedUsersToValidate.map(async (user: IdentityUserModel) => { await Promise.all(preselectedUsersToValidate.map(async (preselectedUser: IdentityUserModel) => {
try { try {
const validationResult: IdentityUserModel = await this.searchUser(user); const userValidationResult: IdentityUserModel = await this.searchUser(preselectedUser);
if (this.isPreselectedUserValid(user, validationResult)) { if (this.compare(preselectedUser, userValidationResult)) {
validationResult.readonly = user.readonly; userValidationResult.readonly = preselectedUser.readonly;
validUsers.push(validationResult); validUsers.push(userValidationResult);
} else { } else {
this.invalidUsers.push(user); this.invalidUsers.push(preselectedUser);
} }
} catch (error) { } catch (error) {
this.invalidUsers.push(user); this.invalidUsers.push(preselectedUser);
this.logService.error(error); this.logService.error(error);
} }
})); }));
@@ -316,13 +320,17 @@ export class PeopleCloudComponent implements OnInit, OnChanges, OnDestroy {
this.isLoading = false; this.isLoading = false;
} }
isPreselectedUserValid(preselectedUser: IdentityUserModel, validatedUser: IdentityUserModel) { compare(preselectedUser: IdentityUserModel, identityUser: IdentityUserModel): boolean {
if (validatedUser && (validatedUser.id !== undefined || validatedUser.username !== undefined || validatedUser.email !== undefined)) { if (preselectedUser && identityUser) {
return preselectedUser.id === validatedUser.id || preselectedUser.username === validatedUser.username || preselectedUser.email === validatedUser.email; const uniquePropertyIdentifiers = ['id', 'username', 'email'];
} else { for (const property of Object.keys(preselectedUser)) {
return false; if (preselectedUser[property] !== undefined && uniquePropertyIdentifiers.includes(property)) {
return preselectedUser[property] === identityUser[property];
} }
} }
}
return false;
}
async searchUser(user: IdentityUserModel) { async searchUser(user: IdentityUserModel) {
let key: string = ''; let key: string = '';