Add unit tests

This commit is contained in:
Giuseppe Digilio
2017-11-12 19:38:27 +01:00
parent 362525c6ea
commit a37b2da6a6
6 changed files with 328 additions and 14 deletions

View File

@@ -0,0 +1,103 @@
import { cold, getTestScheduler, hot } from 'jasmine-marbles';
import { TestScheduler } from 'rxjs/Rx';
import { GlobalConfig } from '../../../config';
import { ResponseCacheService } from '../cache/response-cache.service';
import { ConfigService } from './config.service';
import { RequestService } from '../data/request.service';
import { ConfigRequest, FindAllOptions } from '../data/request.models';
const LINK_NAME = 'test';
const BROWSE = 'search/findByCollection';
class TestService extends ConfigService {
protected linkName = LINK_NAME;
protected browseEndpoint = BROWSE;
constructor(
protected responseCache: ResponseCacheService,
protected requestService: RequestService,
protected EnvConfig: GlobalConfig
) {
super();
}
}
describe('ConfigService', () => {
let scheduler: TestScheduler;
let service: TestService;
let responseCache: ResponseCacheService;
let requestService: RequestService;
const envConfig = {} as GlobalConfig;
const findOptions: FindAllOptions = new FindAllOptions();
const scopeName = 'traditional';
const scopeID = 'd9d30c0c-69b7-4369-8397-ca67c888974d';
const configEndpoint = 'https://rest.api/config';
const serviceEndpoint = `${configEndpoint}/${LINK_NAME}`;
const scopedEndpoint = `${serviceEndpoint}/${scopeName}`;
const searchEndpoint = `${serviceEndpoint}/${BROWSE}?uuid=${scopeID}`;
function initMockRequestService(): RequestService {
return jasmine.createSpyObj('requestService', ['configure']);
}
function initMockResponseCacheService(isSuccessful: boolean): ResponseCacheService {
return jasmine.createSpyObj('responseCache', {
get: cold('c-', {
c: { response: { isSuccessful } }
})
});
}
function initTestService(): TestService {
return new TestService(
responseCache,
requestService,
envConfig
);
}
beforeEach(() => {
responseCache = initMockResponseCacheService(true);
requestService = initMockRequestService();
service = initTestService();
scheduler = getTestScheduler();
spyOn(service, 'getEndpoint').and
.returnValue(hot('--a-', { a: serviceEndpoint }));
});
describe('getConfigByHref', () => {
it('should configure a new ConfigRequest', () => {
const expected = new ConfigRequest(scopedEndpoint);
scheduler.schedule(() => service.getConfigByHref(scopedEndpoint).subscribe());
scheduler.flush();
expect(requestService.configure).toHaveBeenCalledWith(expected);
});
});
describe('getConfigByName', () => {
it('should configure a new ConfigRequest', () => {
const expected = new ConfigRequest(scopedEndpoint);
scheduler.schedule(() => service.getConfigByName(scopeName).subscribe());
scheduler.flush();
expect(requestService.configure).toHaveBeenCalledWith(expected);
});
});
describe('getConfigBySearch', () => {
it('should configure a new ConfigRequest', () => {
findOptions.scopeID = scopeID;
const expected = new ConfigRequest(searchEndpoint);
scheduler.schedule(() => service.getConfigBySearch(findOptions).subscribe());
scheduler.flush();
expect(requestService.configure).toHaveBeenCalledWith(expected);
});
});
});

View File

@@ -33,8 +33,8 @@ export abstract class ConfigService extends HALEndpointService {
.distinctUntilChanged());
}
protected getConfigByIDHref(endpoint, resourceID): string {
return `${endpoint}/${resourceID}`;
protected getConfigByNameHref(endpoint, resourceName): string {
return `${endpoint}/${resourceName}`;
}
protected getConfigSearchHref(endpoint, options: FindAllOptions = {}): string {
@@ -90,7 +90,7 @@ export abstract class ConfigService extends HALEndpointService {
public getConfigByName(name: string): Observable<ConfigData> {
return this.getEndpoint()
.map((endpoint: string) => this.getConfigByIDHref(endpoint, name))
.map((endpoint: string) => this.getConfigByNameHref(endpoint, name))
.filter((href: string) => isNotEmpty(href))
.distinctUntilChanged()
.map((endpointURL: string) => new ConfigRequest(endpointURL))

View File

@@ -66,7 +66,7 @@ describe('ComColDataService', () => {
return jasmine.createSpyObj('requestService', ['configure']);
}
function initMockResponceCacheService(isSuccessful: boolean): ResponseCacheService {
function initMockResponseCacheService(isSuccessful: boolean): ResponseCacheService {
return jasmine.createSpyObj('responseCache', {
get: cold('c-', {
c: { response: { isSuccessful } }
@@ -107,7 +107,7 @@ describe('ComColDataService', () => {
cds = initMockCommunityDataService();
requestService = initMockRequestService();
objectCache = initMockObjectCacheService();
responseCache = initMockResponceCacheService(true);
responseCache = initMockResponseCacheService(true);
service = initTestService();
const expected = new FindByIDRequest(communityEndpoint, scopeID);
@@ -123,7 +123,7 @@ describe('ComColDataService', () => {
cds = initMockCommunityDataService();
requestService = initMockRequestService();
objectCache = initMockObjectCacheService();
responseCache = initMockResponceCacheService(true);
responseCache = initMockResponseCacheService(true);
service = initTestService();
});
@@ -146,7 +146,7 @@ describe('ComColDataService', () => {
cds = initMockCommunityDataService();
requestService = initMockRequestService();
objectCache = initMockObjectCacheService();
responseCache = initMockResponceCacheService(false);
responseCache = initMockResponseCacheService(false);
service = initTestService();
});
@@ -163,12 +163,12 @@ describe('ComColDataService', () => {
cds = initMockCommunityDataService();
requestService = initMockRequestService();
objectCache = initMockObjectCacheService();
responseCache = initMockResponceCacheService(true);
responseCache = initMockResponseCacheService(true);
service = initTestService();
});
it('should return this.getEndpoint()', () => {
spyOn(service, 'getEndpoint').and.returnValue(cold('--e-', { e: serviceEndpoint }))
spyOn(service, 'getEndpoint').and.returnValue(cold('--e-', { e: serviceEndpoint }));
const result = service.getScopedEndpoint(undefined);
const expected = cold('--f-', { f: serviceEndpoint });

View File

@@ -0,0 +1,212 @@
import { ConfigSuccessResponse, ErrorResponse } from '../cache/response-cache.models';
import { ConfigResponseParsingService } from './config-response-parsing.service';
import { ObjectCacheService } from '../cache/object-cache.service';
import { GlobalConfig } from '../../../config/global-config.interface';
import { ConfigRequest } from './request.models';
import { Store } from '@ngrx/store';
import { CoreState } from '../core.reducers';
import { SubmissionDefinitionsModel } from '../shared/config/config-submission-definitions.model';
import { SubmissionSectionModel } from '../shared/config/config-submission-section.model';
describe('ConfigResponseParsingService', () => {
let service: ConfigResponseParsingService;
const EnvConfig = {} as GlobalConfig;
const store = {} as Store<CoreState>;
const objectCacheService = new ObjectCacheService(store);
beforeEach(() => {
service = new ConfigResponseParsingService(EnvConfig, objectCacheService);
});
describe('parse', () => {
const validRequest = new ConfigRequest('https://rest.api/config/submissiondefinitions/traditional');
const validResponse = {
payload: {
id:'traditional',
name:'traditional',
type:'submissiondefinition',
isDefault:true,
_links:{
sections:{
href:'https://rest.api/config/submissiondefinitions/traditional/sections'
},self:{
href:'https://rest.api/config/submissiondefinitions/traditional'
}
},
_embedded:{
sections:{
page:{
number:0,
size:4,
totalPages:1,totalElements:4
},
_embedded:[
{
id:'traditionalpageone',header:'submit.progressbar.describe.stepone',
mandatory:true,
sectionType:'submission-form',
type:'submissionsection',
_links:{
self:{
href:'https://rest.api/config/submissionsections/traditionalpageone'
},
config:{
href:'https://rest.api/config/submissionforms/traditionalpageone'
}
}
}, {
id:'traditionalpagetwo',
header:'submit.progressbar.describe.steptwo',
mandatory:true,
sectionType:'submission-form',
type:'submissionsection',
_links:{
self:{
href:'https://rest.api/config/submissionsections/traditionalpagetwo'
},
config:{
href:'https://rest.api/config/submissionforms/traditionalpagetwo'
}
}
}, {
id:'upload',
header:'submit.progressbar.upload',
mandatory:false,
sectionType:'upload',
type:'submissionsection',
_links:{
self:{
href:'https://rest.api/config/submissionsections/upload'
},
config: {
href:'https://rest.api/config/submissionuploads/upload'
}
}
}, {
id:'license',
header:'submit.progressbar.license',
mandatory:true,
sectionType:'license',
visibility:{
main:null,
other:'READONLY'
},
type:'submissionsection',
_links:{
self:{
href:'https://rest.api/config/submissionsections/license'
}
}
}
],
_links:{
self:'https://rest.api/config/submissiondefinitions/traditional/sections'
}
}
}
},
statusCode:'200'
};
const invalidResponse1 = {
payload: {},
statusCode:'200'
};
const invalidResponse2 = {
payload: {
id:'traditional',
name:'traditional',
type:'submissiondefinition',
isDefault:true,
_links:{},
_embedded:{
sections:{
page:{
number:0,
size:4,
totalPages:1,totalElements:4
},
_embedded:[{},{}],
_links:{
self:'https://rest.api/config/submissiondefinitions/traditional/sections'
}
}
}
},
statusCode:'200'
};
const invalidResponse3 = {
payload: {
_links: { self: { href: 'https://rest.api/config/submissiondefinitions/traditional' } },
page: { size: 20, totalElements: 2, totalPages: 1, number: 0 }
}, statusCode: '500'
};
const definitions = [
Object.assign(new SubmissionDefinitionsModel(), {
isDefault: true,
name: 'traditional',
type: 'submissiondefinition',
_links: {},
sections: [
Object.assign(new SubmissionSectionModel(), {
header: 'submit.progressbar.describe.stepone',
mandatory: true,
sectionType: 'submission-form',
type: 'submissionsection',
_links: {}
}),
Object.assign(new SubmissionSectionModel(), {
header: 'submit.progressbar.describe.steptwo',
mandatory: true,
sectionType: 'submission-form',
type: 'submissionsection',
_links: {}
}),
Object.assign(new SubmissionSectionModel(), {
header: 'submit.progressbar.upload',
mandatory: false,
sectionType: 'upload',
type: 'submissionsection',
_links: {}
}),
Object.assign(new SubmissionSectionModel(), {
header: 'submit.progressbar.license',
mandatory: true,
sectionType: 'license',
type: 'submissionsection',
_links: {}
})
]
})
];
it('should return a ConfigSuccessResponse if data contains a valid config endpoint response', () => {
const response = service.parse(validRequest, validResponse);
expect(response.constructor).toBe(ConfigSuccessResponse);
});
it('should return an ErrorResponse if data contains an invalid config endpoint response', () => {
const response1 = service.parse(validRequest, invalidResponse1);
const response2 = service.parse(validRequest, invalidResponse2);
expect(response1.constructor).toBe(ErrorResponse);
expect(response2.constructor).toBe(ErrorResponse);
});
it('should return an ErrorResponse if data contains a statuscode other than 200', () => {
const response = service.parse(validRequest, invalidResponse3);
expect(response.constructor).toBe(ErrorResponse);
});
it('should return a ConfigSuccessResponse with the ConfigDefinitions in data', () => {
const response = service.parse(validRequest, validResponse);
expect((response as any).configDefinition).toEqual(definitions);
});
});
});

View File

@@ -27,7 +27,7 @@ export class ConfigResponseParsingService extends BaseResponseParsingService imp
}
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links)) {
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && data.statusCode === '200') {
const configDefinition = this.process<ConfigObject,ConfigType>(data.payload, request.href);
return new ConfigSuccessResponse(configDefinition[Object.keys(configDefinition)[0]], data.statusCode, this.processPageInfo(data.payload.page));
} else {

View File

@@ -26,7 +26,6 @@ export function requestStateSelector(): MemoizedSelector<CoreState, RequestState
});
}
@Injectable()
export class RequestService {
private requestsOnTheirWayToTheStore: string[] = [];