-
Notifications
You must be signed in to change notification settings - Fork 90
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* #14 - Add source priority list in AvatarConfig. Read config file in avatar service constructor, check for a source priority list reorder sources constant based on order of config priority list. * Reimplement custom avatar source order in refactored avatar.service. * new comparison, ng guidelines, comment * doc comments * add tests scenarios * Implement source priority order in refactored avatar service. * unit tests for custom source priority order * Remove debugger statement. * refactor source priority * refactor avatar source configuration * delete covergae folder
- Loading branch information
1 parent
44791e7
commit 118a7e6
Showing
9 changed files
with
11,739 additions
and
110 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { AvatarConfigService } from './avatar-config.service'; | ||
import { AvatarSource } from './sources/avatar-source.enum'; | ||
import { AvatarConfig } from './avatar-config'; | ||
import { defaultSources, defaultColors } from './avatar.service'; | ||
|
||
describe('AvatarConfigService', () => { | ||
describe('AvatarSources', () => { | ||
it('should return the list of sources with the default order when the user provides an empty list of sources', () => { | ||
const userConfig: AvatarConfig = { sourcePriorityOrder: [] }; | ||
const avatarConfigService = new AvatarConfigService(userConfig); | ||
|
||
expect(avatarConfigService.getAvatarSources(defaultSources)).toEqual( | ||
defaultSources | ||
); | ||
}); | ||
|
||
it('should return the list of sources with the default order when the user provides an unknown list of sources', () => { | ||
const userConfig: AvatarConfig = { | ||
sourcePriorityOrder: <any>['UNKOWN_SOURCE'] | ||
}; | ||
const avatarConfigService = new AvatarConfigService(userConfig); | ||
|
||
expect(avatarConfigService.getAvatarSources(defaultSources)).toEqual( | ||
defaultSources | ||
); | ||
}); | ||
|
||
it('should override the source priority order when the user provides a valid list of sources', () => { | ||
const userConfig: AvatarConfig = { | ||
sourcePriorityOrder: [AvatarSource.INITIALS, AvatarSource.TWITTER] | ||
}; | ||
const avatarConfigService = new AvatarConfigService(userConfig); | ||
|
||
const expectedSourcesOrder = [ | ||
AvatarSource.INITIALS, | ||
AvatarSource.TWITTER, | ||
AvatarSource.FACEBOOK, | ||
AvatarSource.GOOGLE, | ||
AvatarSource.VKONTAKTE, | ||
AvatarSource.SKYPE, | ||
AvatarSource.GRAVATAR, | ||
AvatarSource.GITHUB, | ||
AvatarSource.CUSTOM, | ||
AvatarSource.VALUE | ||
]; | ||
expect(avatarConfigService.getAvatarSources(defaultSources)).toEqual( | ||
expectedSourcesOrder | ||
); | ||
}); | ||
|
||
it('should ignore redundant sources', () => { | ||
const userConfig: AvatarConfig = { | ||
sourcePriorityOrder: [AvatarSource.INITIALS, AvatarSource.INITIALS] | ||
}; | ||
const avatarConfigService = new AvatarConfigService(userConfig); | ||
|
||
const expectedSourcesOrder = [ | ||
AvatarSource.INITIALS, | ||
AvatarSource.FACEBOOK, | ||
AvatarSource.GOOGLE, | ||
AvatarSource.TWITTER, | ||
AvatarSource.VKONTAKTE, | ||
AvatarSource.SKYPE, | ||
AvatarSource.GRAVATAR, | ||
AvatarSource.GITHUB, | ||
AvatarSource.CUSTOM, | ||
AvatarSource.VALUE | ||
]; | ||
expect(avatarConfigService.getAvatarSources(defaultSources)).toEqual( | ||
expectedSourcesOrder | ||
); | ||
}); | ||
}); | ||
|
||
describe('AvatarColors', () => { | ||
it("should return the user's list of colors when provided in the avatar configuration", () => { | ||
const userColors = ['#ccc', '#fff']; | ||
const userConfig: AvatarConfig = { | ||
colors: userColors | ||
}; | ||
|
||
const avatarConfigService = new AvatarConfigService(userConfig); | ||
|
||
expect(avatarConfigService.getAvatarColors(defaultColors)).toBe( | ||
userColors | ||
); | ||
}); | ||
|
||
it('should return the default colors when no colors are provided in the avatar configuration', () => { | ||
const avatarConfigService = new AvatarConfigService({}); | ||
|
||
expect(avatarConfigService.getAvatarColors(defaultColors)).toBe( | ||
defaultColors | ||
); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { Injectable, Inject, Optional } from '@angular/core'; | ||
|
||
import { AvatarSource } from './sources/avatar-source.enum'; | ||
import { AVATAR_CONFIG } from './avatar-config.token'; | ||
import { AvatarConfig } from './avatar-config'; | ||
|
||
@Injectable() | ||
export class AvatarConfigService { | ||
constructor( | ||
@Optional() | ||
@Inject(AVATAR_CONFIG) | ||
public userConfig: AvatarConfig | ||
) {} | ||
|
||
public getAvatarSources(defaultSources: AvatarSource[]): AvatarSource[] { | ||
if ( | ||
this.userConfig.sourcePriorityOrder && | ||
this.userConfig.sourcePriorityOrder.length | ||
) { | ||
const uniqueSources = [...new Set(this.userConfig.sourcePriorityOrder)]; | ||
const validSources = uniqueSources.filter(source => | ||
defaultSources.includes(source) | ||
); | ||
return [ | ||
...validSources, | ||
...defaultSources.filter(source => !validSources.includes(source)) | ||
]; | ||
} | ||
return defaultSources; | ||
} | ||
|
||
public getAvatarColors(defaultColors: string[]): string[] { | ||
return ( | ||
(this.userConfig && | ||
this.userConfig.colors && | ||
this.userConfig.colors.length && | ||
this.userConfig.colors) || | ||
defaultColors | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,17 @@ | ||
import { AvatarSource } from "./sources/avatar-source.enum"; | ||
|
||
/** | ||
* Represents avatar configuration object | ||
* Represents avatar configuration object. | ||
*/ | ||
export interface AvatarConfig { | ||
|
||
/** | ||
* The avatars colors. | ||
*/ | ||
colors?: string[]; | ||
|
||
/** | ||
* The order in which the avatar sources will be used. | ||
*/ | ||
sourcePriorityOrder?: AvatarSource[]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,109 +1,134 @@ | ||
import { TestBed } from "@angular/core/testing"; | ||
import { TestBed } from '@angular/core/testing'; | ||
import { | ||
HttpClientTestingModule, | ||
HttpTestingController | ||
} from "@angular/common/http/testing"; | ||
|
||
import { AvatarService } from "./avatar.service"; | ||
import { AVATAR_CONFIG } from "./avatar-config.token"; | ||
import { AvatarSource } from "./sources/avatar-source.enum"; | ||
|
||
describe("AvatarService", () => { | ||
} from '@angular/common/http/testing'; | ||
|
||
import { AvatarService, defaultSources, defaultColors } from './avatar.service'; | ||
import { AvatarSource } from './sources/avatar-source.enum'; | ||
import { AvatarConfigService } from './avatar-config.service'; | ||
|
||
const avatarServiceCongigSpy = { | ||
getAvatarSources: jasmine | ||
.createSpy('avatarConfigService.getAvatarSources') | ||
.and.returnValue(defaultSources), | ||
getAvatarColors: jasmine | ||
.createSpy('avatarConfigService.getAvatarColors') | ||
.and.returnValue(defaultColors) | ||
}; | ||
|
||
describe('AvatarService', () => { | ||
let avatarService: AvatarService; | ||
let httpMock: HttpTestingController; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [HttpClientTestingModule], | ||
providers: [AvatarService, { provide: AVATAR_CONFIG, useValue: {} }] | ||
}); | ||
describe('Avatar service with default configuration', () => { | ||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [HttpClientTestingModule], | ||
providers: [ | ||
AvatarService, | ||
{ provide: AvatarConfigService, useValue: avatarServiceCongigSpy } | ||
] | ||
}); | ||
|
||
avatarService = TestBed.get(AvatarService); | ||
httpMock = TestBed.get(HttpTestingController); | ||
}); | ||
avatarService = TestBed.get(AvatarService); | ||
httpMock = TestBed.get(HttpTestingController); | ||
}); | ||
|
||
afterEach(() => { | ||
httpMock.verify(); | ||
}); | ||
afterEach(() => { | ||
httpMock.verify(); | ||
}); | ||
|
||
it("should be created", () => { | ||
expect(avatarService).toBeTruthy(); | ||
}); | ||
it('should be created', () => { | ||
expect(avatarService).toBeTruthy(); | ||
}); | ||
|
||
describe("fetchAvatar", () => { | ||
it("should send get request and fetch avatar data from the given url", () => { | ||
const avatarUrl = "dummy-avatar-url"; | ||
const expectedAvatarData = { | ||
img: "url-for-avatar-img" | ||
}; | ||
avatarService.fetchAvatar(avatarUrl).subscribe(avatarData => { | ||
expect(avatarData).toEqual(expectedAvatarData); | ||
describe('fetchAvatar', () => { | ||
it('should send get request and fetch avatar data from the given url', () => { | ||
const avatarUrl = 'dummy-avatar-url'; | ||
const expectedAvatarData = { | ||
img: 'url-for-avatar-img' | ||
}; | ||
avatarService.fetchAvatar(avatarUrl).subscribe(avatarData => { | ||
expect(avatarData).toEqual(expectedAvatarData); | ||
}); | ||
|
||
const req = httpMock.expectOne( | ||
request => request.method === 'GET' && request.url === avatarUrl | ||
); | ||
req.flush(expectedAvatarData); | ||
}); | ||
|
||
const req = httpMock.expectOne( | ||
request => request.method === "GET" && request.url === avatarUrl | ||
); | ||
req.flush(expectedAvatarData); | ||
}); | ||
}); | ||
|
||
describe("isSource", () => { | ||
it("should return true when the given value is a valid avatar source", () => { | ||
const isValidAvatar = avatarService.isSource(AvatarSource.GITHUB); | ||
describe('isSource', () => { | ||
it('should return true when the given value is a valid avatar source', () => { | ||
const isValidAvatar = avatarService.isSource(AvatarSource.GITHUB); | ||
|
||
expect(isValidAvatar).toBeTruthy(); | ||
}); | ||
|
||
it("should return false when the given value is not a valid avatar source", () => { | ||
const isValidAvatar = avatarService.isSource("unknown-source"); | ||
expect(isValidAvatar).toBeTruthy(); | ||
}); | ||
|
||
expect(isValidAvatar).toBeFalsy(); | ||
}); | ||
}); | ||
it('should return false when the given value is not a valid avatar source', () => { | ||
const isValidAvatar = avatarService.isSource('unknown-source'); | ||
|
||
describe("isTextAvatar", () => { | ||
it("should return true when the given value is a text avatar", () => { | ||
expect(avatarService.isTextAvatar(AvatarSource.INITIALS)).toBeTruthy(); | ||
expect(isValidAvatar).toBeFalsy(); | ||
}); | ||
}); | ||
|
||
it("should return false when the given value is not a text avatar", () => { | ||
expect(avatarService.isTextAvatar(AvatarSource.GITHUB)).toBeFalsy(); | ||
describe('isTextAvatar', () => { | ||
it('should return true when the given value is a text avatar', () => { | ||
expect(avatarService.isTextAvatar(AvatarSource.INITIALS)).toBeTruthy(); | ||
}); | ||
|
||
it('should return false when the given value is not a text avatar', () => { | ||
expect(avatarService.isTextAvatar(AvatarSource.GITHUB)).toBeFalsy(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("getRandomColor", () => { | ||
it("should return transparent when the given value is undefined", () => { | ||
const color = avatarService.getRandomColor(undefined); | ||
describe('getRandomColor', () => { | ||
it('should return transparent when the given value is undefined', () => { | ||
const color = avatarService.getRandomColor(undefined); | ||
|
||
expect(color).toBe("transparent"); | ||
}); | ||
expect(color).toBe('transparent'); | ||
}); | ||
|
||
it("should return a random color based on the ascii code of the given value is", () => { | ||
const color = avatarService.getRandomColor("random name"); | ||
const cssColorRegex = /#([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?\b/; | ||
expect(color).toMatch(cssColorRegex); | ||
}); | ||
it('should return a random color based on the ascii code of the given value is', () => { | ||
const color = avatarService.getRandomColor('random name'); | ||
const cssColorRegex = /#([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?\b/; | ||
expect(color).toMatch(cssColorRegex); | ||
}); | ||
|
||
it("should not return the same color for two different values", () => { | ||
const color1 = avatarService.getRandomColor("name1"); | ||
const color2 = avatarService.getRandomColor("name2"); | ||
it('should not return the same color for two different values', () => { | ||
const color1 = avatarService.getRandomColor('name1'); | ||
const color2 = avatarService.getRandomColor('name2'); | ||
|
||
expect(color1).not.toBe(color2); | ||
expect(color1).not.toBe(color2); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("compareSources", () => { | ||
it("should return a negative value when the first avatar type comes after the second one", () => { | ||
expect(avatarService.copmareSources(AvatarSource.FACEBOOK, AvatarSource.GOOGLE)).toBeLessThan(0); | ||
}); | ||
describe('compareSources', () => { | ||
it('should return a negative value when the first avatar type comes after the second one', () => { | ||
expect( | ||
avatarService.copmareSources( | ||
AvatarSource.FACEBOOK, | ||
AvatarSource.GOOGLE | ||
) | ||
).toBeLessThan(0); | ||
}); | ||
|
||
it("should return a positive value when the first avatar type comes before the second one", () => { | ||
expect(avatarService.copmareSources(AvatarSource.INITIALS, AvatarSource.FACEBOOK)).toBeGreaterThan(0); | ||
}); | ||
it('should return a positive value when the first avatar type comes before the second one', () => { | ||
expect( | ||
avatarService.copmareSources( | ||
AvatarSource.INITIALS, | ||
AvatarSource.FACEBOOK | ||
) | ||
).toBeGreaterThan(0); | ||
}); | ||
|
||
it("should return a zero value when the two give values are equales", () => { | ||
expect(avatarService.copmareSources(AvatarSource.GITHUB, AvatarSource.GITHUB)).toBe(0); | ||
it('should return a zero value when the two give values are equales', () => { | ||
expect( | ||
avatarService.copmareSources(AvatarSource.GITHUB, AvatarSource.GITHUB) | ||
).toBe(0); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.