Skip to content
Snippets Groups Projects
Commit 950d92cd authored by OZGCloud's avatar OZGCloud
Browse files

OZG-2844 OZG-2903 impl message for no first- and lastName exists

parent 118b87f9
Branches
Tags
No related merge requests found
Showing
with 220 additions and 43 deletions
import { faker } from '@faker-js/faker'; import { faker } from '@faker-js/faker';
import { convertForDataTest, EMPTY_STRING, getFirstLetter, hasMinLength, isNotEmpty, isNotNil, isNotNull, replaceAllWhitespaces, replacePlaceholder, replacePlaceholders } from './tech.util'; import { convertForDataTest, EMPTY_STRING, getFirstLetter, getStringValue, hasMinLength, isNotEmpty, isNotNil, isNotNull, replaceAllWhitespaces, replacePlaceholder, replacePlaceholders } from './tech.util';
describe('TechUtil', () => { describe('TechUtil', () => {
...@@ -208,5 +208,30 @@ describe('TechUtil', () => { ...@@ -208,5 +208,30 @@ describe('TechUtil', () => {
}) })
}) })
describe('get string value', () => {
it('should return empty string on null', () => {
const value: string = null;
const result: string = getStringValue(value);
expect(result).toBe(EMPTY_STRING);
})
it('should return empty string on undefined', () => {
const value: string = undefined;
const result: string = getStringValue(value);
expect(result).toBe(EMPTY_STRING);
})
it('should return given value', () => {
const value: string = 'value of this...';
const result: string = getStringValue(value);
expect(result).toBe(value);
})
})
}) })
\ No newline at end of file
...@@ -65,3 +65,10 @@ export function hasMinLength(value: any, length: number): boolean { ...@@ -65,3 +65,10 @@ export function hasMinLength(value: any, length: number): boolean {
export function convertForDataTest(value: string): string { export function convertForDataTest(value: string): string {
return replaceAllWhitespaces(value, '_'); return replaceAllWhitespaces(value, '_');
} }
export function getStringValue(value: null | undefined | string): string {
if (isNull(value) || isUndefined(value)) {
return EMPTY_STRING;
}
return value;
}
\ No newline at end of file
export * from './lib/user-profile-shared.module'; export * from './lib/user-profile-shared.module';
export * from './lib/user-profile.linkrel'; export * from './lib/user-profile.linkrel';
export * from './lib/user-profile.message';
export * from './lib/user-profile.model'; export * from './lib/user-profile.model';
export * from './lib/user-profile.service'; export * from './lib/user-profile.service';
export * from './lib/user-profile.message'; export * from './lib/user-profile.util';
...@@ -4,5 +4,5 @@ export const userProfileMessage = { ...@@ -4,5 +4,5 @@ export const userProfileMessage = {
[MessageCode.SERVICE_UNAVAILABLE]: 'Die Benutzerdaten konnten nicht geladen werden', [MessageCode.SERVICE_UNAVAILABLE]: 'Die Benutzerdaten konnten nicht geladen werden',
[MessageCode.RESOURCE_NOT_FOUND]: 'Der zugewiesene Bearbeiter konnte nicht gefunden werden', [MessageCode.RESOURCE_NOT_FOUND]: 'Der zugewiesene Bearbeiter konnte nicht gefunden werden',
UNASSIGNED: 'Kein Bearbeiter zugewiesen', UNASSIGNED: 'Kein Bearbeiter zugewiesen',
UNKNOW_ERROR: 'Ein unbekannter Fehler ist aufgetreten', UNKNOW_ERROR: 'Ein unbekannter Fehler ist aufgetreten'
} }
import { EMPTY_STRING } from '@goofy-client/tech-shared';
import { createUserProfileResource } from '../../../user-profile-shared/test/user-profile';
import { UserProfileResource } from './user-profile.model';
import { existsName, getUserName, getUserNameInitials } from './user-profile.util';
describe('UserProfileUtil', () => {
describe('existsName', () => {
it('should return true if only firstName exists', () => {
const exists: boolean = existsName({ ...createUserProfileResource(), lastName: EMPTY_STRING });
expect(exists).toBeTruthy();
})
it('should return true if only lastName exists', () => {
const exists: boolean = existsName({ ...createUserProfileResource(), firstName: EMPTY_STRING });
expect(exists).toBeTruthy();
})
it('should return false if either firstName nor lastName exists', () => {
const exists: boolean = existsName({ ...createUserProfileResource(), firstName: EMPTY_STRING, lastName: EMPTY_STRING });
expect(exists).toBeFalsy();
})
})
describe('get user name', () => {
it('should return full name', () => {
const userProfile: UserProfileResource = createUserProfileResource();
const userName: string = getUserName(userProfile);
expect(userName).toBe(`${userProfile.firstName} ${userProfile.lastName}`);
})
it('should return if only firstName exists', () => {
const userProfile: UserProfileResource = { ...createUserProfileResource(), lastName: EMPTY_STRING };
const userName: string = getUserName(userProfile);
expect(userName).toBe(userProfile.firstName);
})
it('should return only lastName exists', () => {
const userProfile: UserProfileResource = { ...createUserProfileResource(), firstName: EMPTY_STRING };
const userName: string = getUserName(userProfile);
expect(userName).toBe(userProfile.lastName);
})
it('should return empty string if either firstName nor lastName exists', () => {
const userProfile: UserProfileResource = { ...createUserProfileResource(), firstName: EMPTY_STRING, lastName: EMPTY_STRING };
const userName: string = getUserName(userProfile);
expect(userName).toBe(EMPTY_STRING);
})
})
describe('get user name initials', () => {
it('should return for full name', () => {
const userProfile: UserProfileResource = createUserProfileResource();
const userName: string = getUserNameInitials(userProfile);
expect(userName).toBe(`${userProfile.firstName.substring(0, 1).toLocaleUpperCase()}${userProfile.lastName.substring(0, 1).toLocaleUpperCase()}`);
})
it('should return if only firstName exists', () => {
const userProfile: UserProfileResource = { ...createUserProfileResource(), lastName: EMPTY_STRING };
const userName: string = getUserNameInitials(userProfile);
expect(userName).toBe(`${userProfile.firstName.substring(0, 1).toLocaleUpperCase()}`);
})
it('should return only lastName exists', () => {
const userProfile: UserProfileResource = { ...createUserProfileResource(), firstName: EMPTY_STRING };
const userName: string = getUserNameInitials(userProfile);
expect(userName).toBe(`${userProfile.lastName.substring(0, 1).toLocaleUpperCase()}`);
})
it('should return empty string if either firstName nor lastName exists', () => {
const userProfile: UserProfileResource = { ...createUserProfileResource(), firstName: EMPTY_STRING, lastName: EMPTY_STRING };
const userName: string = getUserNameInitials(userProfile);
expect(userName).toBe(EMPTY_STRING);
})
})
})
\ No newline at end of file
import { EMPTY_STRING, getFirstLetter, getStringValue, isNotEmpty } from '@goofy-client/tech-shared';
import { isNull } from 'lodash-es';
import { UserProfileResource } from './user-profile.model';
export function existsName(userProfile: UserProfileResource): boolean {
return isNotEmpty(userProfile.firstName) || isNotEmpty(userProfile.lastName);
}
export function getUserName(userProfile: UserProfileResource): string {
return `${getStringValue(userProfile.firstName)} ${getStringValue(userProfile.lastName)}`;
}
export function getUserNameInitials(userProfile: UserProfileResource): string {
return `${getFirstLetterUpperCase(userProfile.firstName)}${getFirstLetterUpperCase(userProfile.lastName)}`;
}
function getFirstLetterUpperCase(value: string) {
const firstLetter: string = getFirstLetter(value);
return isNull(firstLetter) ? EMPTY_STRING : firstLetter.toUpperCase();
}
...@@ -2,10 +2,11 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; ...@@ -2,10 +2,11 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatIcon } from '@angular/material/icon'; import { MatIcon } from '@angular/material/icon';
import { MatTooltipModule } from '@angular/material/tooltip'; import { MatTooltipModule } from '@angular/material/tooltip';
import { faker } from '@faker-js/faker'; import { faker } from '@faker-js/faker';
import { ApiError, createEmptyStateResource, createErrorStateResource, createStateResource, MessageCode } from '@goofy-client/tech-shared'; import { ApiError, createEmptyStateResource, createErrorStateResource, createStateResource, EMPTY_STRING, MessageCode } from '@goofy-client/tech-shared';
import { getElementFromFixture } from '@goofy-client/test-utils'; import { getElementFromFixture } from '@goofy-client/test-utils';
import { SpinnerComponent } from '@goofy-client/ui'; import { SpinnerComponent } from '@goofy-client/ui';
import { userProfileMessage, UserProfileResource } from '@goofy-client/user-profile-shared'; import { userProfileMessage, UserProfileResource } from '@goofy-client/user-profile-shared';
import { getDataTestClassOf } from 'libs/tech-shared/test/data-test';
import { createUserProfileResource } from 'libs/user-profile-shared/test/user-profile'; import { createUserProfileResource } from 'libs/user-profile-shared/test/user-profile';
import { MockComponent } from 'ng-mocks'; import { MockComponent } from 'ng-mocks';
import { createApiError, createIssue } from '../../../../tech-shared/test/error'; import { createApiError, createIssue } from '../../../../tech-shared/test/error';
...@@ -15,10 +16,10 @@ describe('UserIconComponent', () => { ...@@ -15,10 +16,10 @@ describe('UserIconComponent', () => {
let component: UserIconComponent; let component: UserIconComponent;
let fixture: ComponentFixture<UserIconComponent>; let fixture: ComponentFixture<UserIconComponent>;
const profileAssignedIcon: string = '[data-test-class="user-profile-assigned"]'; const profileAssignedIcon: string = getDataTestClassOf('user-profile-assigned');
const profileUnassigned: string = '[data-test-class="user-profile-unassigned"]'; const profileUnassigned: string = getDataTestClassOf('user-profile-unassigned');
const profileUserNotFound: string = '[data-test-class="user-profile-user-not-found"]'; const profileUserNotFound: string = getDataTestClassOf('user-profile-user-not-found');
const profileServiceUnavailable: string = '[data-test-class="user-profile-service-unavailable"]'; const profileServiceUnavailable: string = getDataTestClassOf('user-profile-service-unavailable');
const userProfile: UserProfileResource = createUserProfileResource(); const userProfile: UserProfileResource = createUserProfileResource();
...@@ -64,17 +65,6 @@ describe('UserIconComponent', () => { ...@@ -64,17 +65,6 @@ describe('UserIconComponent', () => {
expect(element).toBeInstanceOf(HTMLElement); expect(element).toBeInstanceOf(HTMLElement);
}) })
it('should show empty icon if user has no name', () => {
component.userProfileStateResource = createStateResource(userProfile);
component.userProfileStateResource.resource.lastName = '';
component.userProfileStateResource.resource.firstName = '';
fixture.detectChanges();
const element = getElementFromFixture(fixture, profileAssignedIcon);
expect(element).toBeEmptyDOMElement();
})
it('should show user not found icon', () => { it('should show user not found icon', () => {
component.userProfileStateResource = createErrorStateResource(createApiErrorWithMessageCode(MessageCode.RESOURCE_NOT_FOUND)); component.userProfileStateResource = createErrorStateResource(createApiErrorWithMessageCode(MessageCode.RESOURCE_NOT_FOUND));
...@@ -95,6 +85,7 @@ describe('UserIconComponent', () => { ...@@ -95,6 +85,7 @@ describe('UserIconComponent', () => {
}) })
describe('tooltip', () => { describe('tooltip', () => {
it('should return user name', () => { it('should return user name', () => {
component.userProfileStateResource = createStateResource(userProfile); component.userProfileStateResource = createStateResource(userProfile);
...@@ -119,9 +110,18 @@ describe('UserIconComponent', () => { ...@@ -119,9 +110,18 @@ describe('UserIconComponent', () => {
expect(component.getErrorTooltip).toHaveBeenCalled(); expect(component.getErrorTooltip).toHaveBeenCalled();
}) })
it('should return empty string on missing name', () => {
component.userProfileStateResource = createStateResource({ ...userProfile, firstName: EMPTY_STRING, lastName: EMPTY_STRING });
const tooltip = component.getTooltip();
expect(tooltip).toEqual(EMPTY_STRING);
})
}); });
describe('error tooltip', () => { describe('error tooltip', () => {
it('should return user not found', () => { it('should return user not found', () => {
component.userProfileStateResource = createErrorStateResource(createApiErrorWithMessageCode(MessageCode.RESOURCE_NOT_FOUND)); component.userProfileStateResource = createErrorStateResource(createApiErrorWithMessageCode(MessageCode.RESOURCE_NOT_FOUND));
......
import { Component, Input, SimpleChanges } from '@angular/core'; import { Component, Input, SimpleChanges } from '@angular/core';
import { createEmptyStateResource, getFirstLetter, hasError, MessageCode, StateResource } from '@goofy-client/tech-shared'; import { createEmptyStateResource, hasError, MessageCode, StateResource } from '@goofy-client/tech-shared';
import { userProfileMessage, UserProfileResource } from '@goofy-client/user-profile-shared'; import { getUserName, getUserNameInitials, userProfileMessage, UserProfileResource } from '@goofy-client/user-profile-shared';
import { isNull, isUndefined } from 'lodash'; import { isUndefined } from 'lodash';
@Component({ @Component({
selector: 'goofy-client-user-icon', selector: 'goofy-client-user-icon',
...@@ -34,7 +34,7 @@ export class UserIconComponent { ...@@ -34,7 +34,7 @@ export class UserIconComponent {
} }
getUserTooltip(): string { getUserTooltip(): string {
return `${this.userProfileStateResource.resource.firstName} ${this.userProfileStateResource.resource.lastName}`; return getUserName(this.userProfileStateResource.resource);
} }
getErrorTooltip(): string { getErrorTooltip(): string {
...@@ -47,16 +47,6 @@ export class UserIconComponent { ...@@ -47,16 +47,6 @@ export class UserIconComponent {
} }
get initials(): string { get initials(): string {
if (this.userProfileStateResource.resource.firstName.length === 0 return getUserNameInitials(this.userProfileStateResource.resource);
&& this.userProfileStateResource.resource.lastName) {
return '';
}
return this.getFirstLetterUpperCase(this.userProfileStateResource.resource.firstName) + this.getFirstLetterUpperCase(this.userProfileStateResource.resource.lastName);
}
private getFirstLetterUpperCase(value: string) {
const firstLetter: string = getFirstLetter(value);
return isNull(firstLetter) ? null : firstLetter.toUpperCase();
} }
} }
<div *ngIf="userProfileStateResource.resource; else unknownUser"> <div *ngIf="userProfileStateResource.resource; else unknownUser">
<span data-test-class="user-profile-name">{{userProfileStateResource.resource.firstName}} {{userProfileStateResource.resource.lastName}}</span> <span data-test-class="user-profile-name">{{userName}}</span>
</div> </div>
<ng-template #unknownUser> <ng-template #unknownUser>
<span data-test-class="user-profile-name-unknown">Unbekannter Benutzer</span> <span data-test-class="user-profile-name-unknown">Unbekannter Benutzer</span>
......
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { createEmptyStateResource, createErrorStateResource, createStateResource } from '@goofy-client/tech-shared'; import { createEmptyStateResource, createErrorStateResource, createStateResource, EMPTY_STRING } from '@goofy-client/tech-shared';
import { UserProfileResource } from '@goofy-client/user-profile-shared'; import { UserProfileResource } from '@goofy-client/user-profile-shared';
import { getDataTestClassOf } from 'libs/tech-shared/test/data-test'; import { getDataTestClassOf } from 'libs/tech-shared/test/data-test';
import { createApiError } from 'libs/tech-shared/test/error'; import { createApiError } from 'libs/tech-shared/test/error';
...@@ -13,6 +13,8 @@ describe('UserProfileNameComponent', () => { ...@@ -13,6 +13,8 @@ describe('UserProfileNameComponent', () => {
const userProfileName: string = getDataTestClassOf('user-profile-name'); const userProfileName: string = getDataTestClassOf('user-profile-name');
const userProfileNameUnknown: string = getDataTestClassOf('user-profile-name-unknown'); const userProfileNameUnknown: string = getDataTestClassOf('user-profile-name-unknown');
const userProfile: UserProfileResource = createUserProfileResource();
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [UserProfileNameComponent], declarations: [UserProfileNameComponent],
...@@ -32,8 +34,6 @@ describe('UserProfileNameComponent', () => { ...@@ -32,8 +34,6 @@ describe('UserProfileNameComponent', () => {
describe('if user-profile exists', () => { describe('if user-profile exists', () => {
const userProfile: UserProfileResource = createUserProfileResource();
beforeEach(() => { beforeEach(() => {
component.userProfileStateResource = createStateResource(userProfile); component.userProfileStateResource = createStateResource(userProfile);
fixture.detectChanges(); fixture.detectChanges();
...@@ -43,7 +43,6 @@ describe('UserProfileNameComponent', () => { ...@@ -43,7 +43,6 @@ describe('UserProfileNameComponent', () => {
const element = fixture.nativeElement.querySelector(userProfileName); const element = fixture.nativeElement.querySelector(userProfileName);
expect(element).toBeInstanceOf(HTMLElement); expect(element).toBeInstanceOf(HTMLElement);
expect((<HTMLElement>element).innerHTML).toContain(userProfile.firstName + ' ' + userProfile.lastName);
}) })
}) })
...@@ -61,4 +60,23 @@ describe('UserProfileNameComponent', () => { ...@@ -61,4 +60,23 @@ describe('UserProfileNameComponent', () => {
expect((<HTMLElement>element).innerHTML).toContain('Unbekannter Benutzer'); expect((<HTMLElement>element).innerHTML).toContain('Unbekannter Benutzer');
}) })
}) })
describe('get user name', () => {
it('should return name if first- or lastName is filled', () => {
component.userProfileStateResource = createStateResource(userProfile);
const userName: string = component.getUserName();
expect(userName).toBe(`${userProfile.firstName} ${userProfile.lastName}`);
})
it('should return "no name message" on empty first- and lastName', () => {
component.userProfileStateResource = createStateResource({ ...userProfile, firstName: EMPTY_STRING, lastName: EMPTY_STRING });
const userName: string = component.getUserName();
expect(userName).toBe(UserProfileNameComponent.NO_NAME_MESSAGE);
})
})
}); });
import { Component, Input } from '@angular/core'; import { Component, Input, OnInit } from '@angular/core';
import { StateResource } from '@goofy-client/tech-shared'; import { isNotNull, StateResource } from '@goofy-client/tech-shared';
import { UserProfileResource } from '@goofy-client/user-profile-shared'; import { existsName, getUserName, UserProfileResource } from '@goofy-client/user-profile-shared';
@Component({ @Component({
selector: 'goofy-client-user-profile-name', selector: 'goofy-client-user-profile-name',
templateUrl: './user-profile-name.component.html', templateUrl: './user-profile-name.component.html',
styleUrls: ['./user-profile-name.component.scss'], styleUrls: ['./user-profile-name.component.scss'],
}) })
export class UserProfileNameComponent { export class UserProfileNameComponent implements OnInit {
@Input() userProfileStateResource: StateResource<UserProfileResource>; @Input() userProfileStateResource: StateResource<UserProfileResource>;
static readonly NO_NAME_MESSAGE: string = 'Benutzer ohne hinterlegtem Namen';
userName: string;
ngOnInit(): void {
if (isNotNull(this.userProfileStateResource.resource)) {
this.userName = this.getUserName();
}
}
getUserName(): string {
if (existsName(this.userProfileStateResource.resource)) {
return getUserName(this.userProfileStateResource.resource);
} else {
return UserProfileNameComponent.NO_NAME_MESSAGE;
}
}
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment