refactored AvatarService
This commit is contained in:
parent
7b35c0c0d5
commit
ff6673fb07
8 changed files with 177 additions and 55 deletions
|
@ -27,7 +27,7 @@ module.exports = function(config) {
|
||||||
// static/lib resources
|
// static/lib resources
|
||||||
'static/lib/**/*.js',
|
'static/lib/**/*.js',
|
||||||
|
|
||||||
// Application resources
|
// Tests
|
||||||
'static/js/**/*.spec.ts*',
|
'static/js/**/*.spec.ts*',
|
||||||
|
|
||||||
// Tests utils
|
// Tests utils
|
||||||
|
@ -37,13 +37,13 @@ module.exports = function(config) {
|
||||||
preprocessors: {
|
preprocessors: {
|
||||||
'static/lib/ngReact/react.ngReact.min.js': ['webpack'],
|
'static/lib/ngReact/react.ngReact.min.js': ['webpack'],
|
||||||
'static/lib/angular-moment.min.js': ['webpack'],
|
'static/lib/angular-moment.min.js': ['webpack'],
|
||||||
'static/js/**/*.ts*': ['webpack'],
|
'static/js/**/*.spec.ts*': ['webpack'],
|
||||||
},
|
},
|
||||||
webpack: webpackConfig,
|
webpack: webpackConfig,
|
||||||
webpackMiddleware: {
|
webpackMiddleware: {
|
||||||
stats: 'errors-only'
|
stats: 'errors-only'
|
||||||
},
|
},
|
||||||
reporters: ['dots', 'coverage', 'karma-typescript'],
|
reporters: ['dots', 'coverage'],
|
||||||
coverageReporter: {
|
coverageReporter: {
|
||||||
dir: 'coverage',
|
dir: 'coverage',
|
||||||
type: 'html'
|
type: 'html'
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
"@types/angular": "1.5.16",
|
"@types/angular": "1.5.16",
|
||||||
"@types/angular-mocks": "^1.5.8",
|
"@types/angular-mocks": "^1.5.8",
|
||||||
"@types/angular-route": "^1.3.3",
|
"@types/angular-route": "^1.3.3",
|
||||||
|
"@types/angular-sanitize": "^1.3.4",
|
||||||
"@types/es6-shim": "^0.31.32",
|
"@types/es6-shim": "^0.31.32",
|
||||||
"@types/jasmine": "^2.5.41",
|
"@types/jasmine": "^2.5.41",
|
||||||
"@types/react": "0.14.39",
|
"@types/react": "0.14.39",
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { LinearWorkflowSectionComponent } from './directives/ui/linear-workflow/
|
||||||
import { QuayConfig } from './quay-config.module';
|
import { QuayConfig } from './quay-config.module';
|
||||||
import { QuayRun } from './quay-run.module';
|
import { QuayRun } from './quay-run.module';
|
||||||
import { BuildServiceImpl } from './services/build/build.service.impl';
|
import { BuildServiceImpl } from './services/build/build.service.impl';
|
||||||
|
import { AvatarServiceImpl } from './services/avatar/avatar.service.impl';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,6 +36,7 @@ import { BuildServiceImpl } from './services/build/build.service.impl';
|
||||||
providers: [
|
providers: [
|
||||||
ViewArrayImpl,
|
ViewArrayImpl,
|
||||||
BuildServiceImpl,
|
BuildServiceImpl,
|
||||||
|
AvatarServiceImpl,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class quay {
|
export class quay {
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
/**
|
|
||||||
* Service which provides helper methods for retrieving the avatars displayed in the app.
|
|
||||||
*/
|
|
||||||
angular.module('quay').factory('AvatarService', ['Config', '$sanitize', 'md5',
|
|
||||||
function(Config, $sanitize, md5) {
|
|
||||||
var avatarService = {};
|
|
||||||
var cache = {};
|
|
||||||
|
|
||||||
avatarService.getAvatar = function(hash, opt_size, opt_notfound) {
|
|
||||||
var size = opt_size || 16;
|
|
||||||
switch (Config['AVATAR_KIND']) {
|
|
||||||
case 'local':
|
|
||||||
return '/avatar/' + hash + '?size=' + size;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'gravatar':
|
|
||||||
var notfound = opt_notfound || '404';
|
|
||||||
return '//www.gravatar.com/avatar/' + hash + '?d=' + notfound + '&size=' + size;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
avatarService.computeHash = function(opt_email, opt_name) {
|
|
||||||
var email = opt_email || '';
|
|
||||||
var name = opt_name || '';
|
|
||||||
|
|
||||||
var cacheKey = email + ':' + name;
|
|
||||||
if (!cacheKey) { return '-'; }
|
|
||||||
|
|
||||||
if (cache[cacheKey]) {
|
|
||||||
return cache[cacheKey];
|
|
||||||
}
|
|
||||||
|
|
||||||
var hash = md5.createHash(email.toString().toLowerCase());
|
|
||||||
switch (Config['AVATAR_KIND']) {
|
|
||||||
case 'local':
|
|
||||||
if (name) {
|
|
||||||
hash = name[0] + hash;
|
|
||||||
} else if (email) {
|
|
||||||
hash = email[0] + hash;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cache[cacheKey] = hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
return avatarService;
|
|
||||||
}]);
|
|
97
static/js/services/avatar/avatar.service.impl.spec.ts
Normal file
97
static/js/services/avatar/avatar.service.impl.spec.ts
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import { AvatarServiceImpl } from './avatar.service.impl';
|
||||||
|
|
||||||
|
|
||||||
|
describe("AvatarServiceImpl", () => {
|
||||||
|
var avatarServiceImpl: AvatarServiceImpl;
|
||||||
|
var configMock: any;
|
||||||
|
var md5Mock: any;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
configMock = {AVATAR_KIND: 'local'};
|
||||||
|
md5Mock = jasmine.createSpyObj('md5Mock', ['createHash']);
|
||||||
|
avatarServiceImpl = new AvatarServiceImpl(configMock, md5Mock);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getAvatar", () => {
|
||||||
|
var hash: string;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
hash = "a1b2c3d4e5f6";
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns a local avatar URL if given config has avatar kind set to local", () => {
|
||||||
|
var avatarURL: string = avatarServiceImpl.getAvatar(hash);
|
||||||
|
|
||||||
|
expect(avatarURL).toEqual(`/avatar/${hash}?size=16`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns a Gravatar URL if given config has avatar kind set to Gravatar", () => {
|
||||||
|
configMock['AVATAR_KIND'] = 'gravatar';
|
||||||
|
var avatarURL: string = avatarServiceImpl.getAvatar(hash);
|
||||||
|
|
||||||
|
expect(avatarURL).toEqual(`//www.gravatar.com/avatar/${hash}?d=404&size=16`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses 16 as default size query parameter if not provided", () => {
|
||||||
|
var size: number = 16;
|
||||||
|
var avatarURL: string = avatarServiceImpl.getAvatar(hash);
|
||||||
|
|
||||||
|
expect(avatarURL).toEqual(`/avatar/${hash}?size=${size}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses 404 as default not found query parameter for Gravatar URL if not provided", () => {
|
||||||
|
configMock['AVATAR_KIND'] = 'gravatar';
|
||||||
|
var notFound: string = '404';
|
||||||
|
var avatarURL: string = avatarServiceImpl.getAvatar(hash);
|
||||||
|
|
||||||
|
expect(avatarURL).toEqual(`//www.gravatar.com/avatar/${hash}?d=${notFound}&size=16`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("computeHash", () => {
|
||||||
|
var email: string;
|
||||||
|
var name: string;
|
||||||
|
var expectedHash: string;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
email = "some_example@gmail.com";
|
||||||
|
name = "example";
|
||||||
|
expectedHash = "a1b2c3d4e5f6";
|
||||||
|
md5Mock.createHash = jasmine.createSpy('createHashSpy').and.returnValue(expectedHash);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns hash from cache if it exists", () => {
|
||||||
|
// Call once to set the cache
|
||||||
|
avatarServiceImpl.computeHash(email, name);
|
||||||
|
md5Mock.createHash.calls.reset();
|
||||||
|
avatarServiceImpl.computeHash(email, name);
|
||||||
|
|
||||||
|
expect(md5Mock.createHash).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls MD5 service to create hash using given email if cache is not set", () => {
|
||||||
|
avatarServiceImpl.computeHash(email, name);
|
||||||
|
|
||||||
|
expect(md5Mock.createHash.calls.argsFor(0)[0]).toEqual(email.toString().toLowerCase());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds first character of given name to hash if config has avatar kind set to local", () => {
|
||||||
|
var hash: string = avatarServiceImpl.computeHash(email, name);
|
||||||
|
|
||||||
|
expect(hash[0]).toEqual(name[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds first character of given email to hash if config has avatar kind set to local and not given name", () => {
|
||||||
|
var hash: string = avatarServiceImpl.computeHash(email);
|
||||||
|
|
||||||
|
expect(hash[0]).toEqual(email[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds nothing to hash if config avatar kind is not set to local", () => {
|
||||||
|
configMock['AVATAR_KIND'] = 'gravatar';
|
||||||
|
var hash: string = avatarServiceImpl.computeHash(email);
|
||||||
|
|
||||||
|
expect(hash).toEqual(expectedHash);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
49
static/js/services/avatar/avatar.service.impl.ts
Normal file
49
static/js/services/avatar/avatar.service.impl.ts
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import { AvatarService } from './avatar.service';
|
||||||
|
import { Injectable } from 'angular-ts-decorators';
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable(AvatarService.name)
|
||||||
|
export class AvatarServiceImpl implements AvatarService {
|
||||||
|
|
||||||
|
private cache: {[cacheKey: string]: string} = {};
|
||||||
|
|
||||||
|
constructor(private Config: any, private md5: any) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAvatar(hash: string, size: number = 16, notFound: string = '404'): string {
|
||||||
|
var avatarURL: string;
|
||||||
|
switch (this.Config['AVATAR_KIND']) {
|
||||||
|
case 'local':
|
||||||
|
avatarURL = `/avatar/${hash}?size=${size}`;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'gravatar':
|
||||||
|
avatarURL = `//www.gravatar.com/avatar/${hash}?d=${notFound}&size=${size}`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return avatarURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public computeHash(email: string = '', name: string = ''): string {
|
||||||
|
const cacheKey: string = email + ':' + name;
|
||||||
|
|
||||||
|
if (this.cache[cacheKey]) {
|
||||||
|
return this.cache[cacheKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
var hash: string = this.md5.createHash(email.toString().toLowerCase());
|
||||||
|
switch (this.Config['AVATAR_KIND']) {
|
||||||
|
case 'local':
|
||||||
|
if (name) {
|
||||||
|
hash = name[0] + hash;
|
||||||
|
} else if (email) {
|
||||||
|
hash = email[0] + hash;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.cache[cacheKey] = hash;
|
||||||
|
}
|
||||||
|
}
|
22
static/js/services/avatar/avatar.service.ts
Normal file
22
static/js/services/avatar/avatar.service.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/**
|
||||||
|
* Service which provides helper methods for retrieving the avatars displayed in the app.
|
||||||
|
*/
|
||||||
|
export abstract class AvatarService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve URL for avatar image with given hash.
|
||||||
|
* @param hash Avatar image hash.
|
||||||
|
* @param size Avatar image size.
|
||||||
|
* @param notFound URL parameter if avatar image is not found.
|
||||||
|
* @return avatarURL The URL for the avatar image.
|
||||||
|
*/
|
||||||
|
public abstract getAvatar(hash: string, size?: number, notFound?: string): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the avatar image hash.
|
||||||
|
* @param email Email for avatar user.
|
||||||
|
* @param name Username for avatar user.
|
||||||
|
* @return hash The hash for the avatar image.
|
||||||
|
*/
|
||||||
|
public abstract computeHash(email?: string, name?: string): string;
|
||||||
|
}
|
|
@ -9,14 +9,14 @@ describe("Service: PageServiceImpl", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("create", () => {
|
describe("create", () => {
|
||||||
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("get", () => {
|
describe("get", () => {
|
||||||
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("$get", () => {
|
describe("$get", () => {
|
||||||
|
// TODO
|
||||||
});
|
});
|
||||||
});
|
});
|
Reference in a new issue