mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
327 lines
12 KiB
TypeScript
327 lines
12 KiB
TypeScript
import { cold, getTestScheduler, hot } from 'jasmine-marbles';
|
|
import { TestScheduler } from 'rxjs/testing';
|
|
import { getMockRequestService } from '../../shared/mocks/request.service.mock';
|
|
import { GetRequest } from '../data/request.models';
|
|
import { RequestEntry } from '../data/request.reducer';
|
|
import { RequestService } from '../data/request.service';
|
|
import {
|
|
sendRequest,
|
|
getAllSucceededRemoteData,
|
|
getFirstSucceededRemoteData,
|
|
getRemoteDataPayload,
|
|
getRequestFromRequestHref,
|
|
getRequestFromRequestUUID,
|
|
getResponseFromEntry,
|
|
redirectOn4xx
|
|
} from './operators';
|
|
import { of as observableOf } from 'rxjs';
|
|
import {
|
|
createFailedRemoteDataObject,
|
|
createSuccessfulRemoteDataObject
|
|
} from '../../shared/remote-data.utils';
|
|
|
|
// tslint:disable:no-shadowed-variable
|
|
|
|
describe('Core Module - RxJS Operators', () => {
|
|
let scheduler: TestScheduler;
|
|
let requestService: RequestService;
|
|
const testRequestHref = 'https://rest.api/';
|
|
const testRequestUUID = 'https://rest.api/';
|
|
|
|
const testRCEs = {
|
|
a: { response: { isSuccessful: true, resourceSelfLinks: ['a', 'b', 'c', 'd'] } },
|
|
b: { response: { isSuccessful: false, resourceSelfLinks: ['e', 'f'] } },
|
|
c: { response: { isSuccessful: undefined, resourceSelfLinks: ['g', 'h', 'i'] } },
|
|
d: { response: { isSuccessful: true, resourceSelfLinks: ['j', 'k', 'l', 'm', 'n'] } },
|
|
e: { response: { isSuccessful: 1, resourceSelfLinks: [] } },
|
|
f: { response: undefined },
|
|
g: undefined
|
|
};
|
|
|
|
const testResponses = {
|
|
a: testRCEs.a.response,
|
|
b: testRCEs.b.response,
|
|
c: testRCEs.c.response,
|
|
d: testRCEs.d.response,
|
|
e: testRCEs.e.response
|
|
};
|
|
|
|
beforeEach(() => {
|
|
scheduler = getTestScheduler();
|
|
});
|
|
|
|
describe('getRequestFromRequestHref', () => {
|
|
|
|
it('should return the RequestEntry corresponding to the self link in the source', () => {
|
|
requestService = getMockRequestService();
|
|
|
|
const source = hot('a', { a: testRequestHref });
|
|
const result = source.pipe(getRequestFromRequestHref(requestService));
|
|
const expected = cold('a', { a: new RequestEntry() });
|
|
|
|
expect(result).toBeObservable(expected);
|
|
});
|
|
|
|
it('should use the requestService to fetch the request by its self link', () => {
|
|
requestService = getMockRequestService();
|
|
|
|
const source = hot('a', { a: testRequestHref });
|
|
scheduler.schedule(() => source.pipe(getRequestFromRequestHref(requestService)).subscribe());
|
|
scheduler.flush();
|
|
|
|
expect(requestService.getByHref).toHaveBeenCalledWith(testRequestHref);
|
|
});
|
|
|
|
it('shouldn\'t return anything if there is no request matching the self link', () => {
|
|
requestService = getMockRequestService(cold('a', { a: undefined }));
|
|
|
|
const source = hot('a', { a: testRequestUUID });
|
|
const result = source.pipe(getRequestFromRequestHref(requestService));
|
|
const expected = cold('-');
|
|
|
|
expect(result).toBeObservable(expected);
|
|
});
|
|
});
|
|
|
|
describe('getRequestFromRequestUUID', () => {
|
|
|
|
it('should return the RequestEntry corresponding to the request uuid in the source', () => {
|
|
requestService = getMockRequestService();
|
|
|
|
const source = hot('a', { a: testRequestUUID });
|
|
const result = source.pipe(getRequestFromRequestUUID(requestService));
|
|
const expected = cold('a', { a: new RequestEntry() });
|
|
|
|
expect(result).toBeObservable(expected);
|
|
});
|
|
|
|
it('should use the requestService to fetch the request by its request uuid', () => {
|
|
requestService = getMockRequestService();
|
|
|
|
const source = hot('a', { a: testRequestUUID });
|
|
scheduler.schedule(() => source.pipe(getRequestFromRequestUUID(requestService)).subscribe());
|
|
scheduler.flush();
|
|
|
|
expect(requestService.getByUUID).toHaveBeenCalledWith(testRequestUUID);
|
|
});
|
|
|
|
it('shouldn\'t return anything if there is no request matching the request uuid', () => {
|
|
requestService = getMockRequestService(cold('a', { a: undefined }));
|
|
|
|
const source = hot('a', { a: testRequestUUID });
|
|
const result = source.pipe(getRequestFromRequestUUID(requestService));
|
|
const expected = cold('-');
|
|
|
|
expect(result).toBeObservable(expected);
|
|
});
|
|
});
|
|
|
|
describe('sendRequest', () => {
|
|
it('should call requestService.send with the source request', () => {
|
|
requestService = getMockRequestService();
|
|
const testRequest = new GetRequest('6b789e31-f026-4ff8-8993-4eb3b730c841', testRequestHref);
|
|
const source = hot('a', { a: testRequest });
|
|
scheduler.schedule(() => source.pipe(sendRequest(requestService)).subscribe());
|
|
scheduler.flush();
|
|
|
|
expect(requestService.send).toHaveBeenCalledWith(testRequest);
|
|
});
|
|
});
|
|
|
|
describe('getRemoteDataPayload', () => {
|
|
it('should return the payload of the source RemoteData', () => {
|
|
const testRD = { a: { payload: 'a' } };
|
|
const source = hot('a', testRD);
|
|
const result = source.pipe(getRemoteDataPayload());
|
|
const expected = cold('a', {
|
|
a: testRD.a.payload,
|
|
});
|
|
|
|
expect(result).toBeObservable(expected);
|
|
});
|
|
});
|
|
|
|
describe('getResponseFromEntry', () => {
|
|
it('should return the response for all not empty request entries, when they have a value', () => {
|
|
const source = hot('abcdefg', testRCEs);
|
|
const result = source.pipe(getResponseFromEntry());
|
|
const expected = cold('abcde--', {
|
|
a: testRCEs.a.response,
|
|
b: testRCEs.b.response,
|
|
c: testRCEs.c.response,
|
|
d: testRCEs.d.response,
|
|
e: testRCEs.e.response
|
|
});
|
|
|
|
expect(result).toBeObservable(expected);
|
|
});
|
|
});
|
|
|
|
describe('getFirstSucceededRemoteData', () => {
|
|
it('should return the first() hasSucceeded RemoteData Observable', () => {
|
|
const testRD = {
|
|
a: createFailedRemoteDataObject(),
|
|
b: createFailedRemoteDataObject(),
|
|
c: createSuccessfulRemoteDataObject('c'),
|
|
d: createSuccessfulRemoteDataObject('d'),
|
|
};
|
|
const source = hot('abcd', testRD);
|
|
const result = source.pipe(getFirstSucceededRemoteData());
|
|
const expected = cold('--(c|)', testRD);
|
|
|
|
expect(result).toBeObservable(expected);
|
|
|
|
});
|
|
});
|
|
|
|
describe('redirectOn4xx', () => {
|
|
let router;
|
|
let authService;
|
|
let testScheduler;
|
|
|
|
beforeEach(() => {
|
|
testScheduler = new TestScheduler((actual, expected) => {
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
router = jasmine.createSpyObj('router', ['navigateByUrl']);
|
|
authService = jasmine.createSpyObj('authService', {
|
|
isAuthenticated: observableOf(true),
|
|
setRedirectUrl: {}
|
|
});
|
|
});
|
|
|
|
it('should call navigateByUrl to a 404 page, when the remote data contains a 404 error, and not emit anything', () => {
|
|
testScheduler.run(({ cold, expectObservable, flush }) => {
|
|
const testRD = createFailedRemoteDataObject('Object was not found', 404);
|
|
const source = cold('a', { a: testRD });
|
|
const expected = '-';
|
|
const values = {};
|
|
|
|
expectObservable(source.pipe(redirectOn4xx(router, authService))).toBe(expected, values);
|
|
flush();
|
|
expect(router.navigateByUrl).toHaveBeenCalledWith('/404', { skipLocationChange: true });
|
|
});
|
|
});
|
|
|
|
it('should call navigateByUrl to a 404 page, when the remote data contains a 422 error, and not emit anything', () => {
|
|
testScheduler.run(({ cold, expectObservable, flush }) => {
|
|
const testRD = createFailedRemoteDataObject('Unprocessable Entity', 422);
|
|
const source = cold('a', { a: testRD });
|
|
const expected = '-';
|
|
const values = {};
|
|
|
|
expectObservable(source.pipe(redirectOn4xx(router, authService))).toBe(expected, values);
|
|
flush();
|
|
expect(router.navigateByUrl).toHaveBeenCalledWith('/404', { skipLocationChange: true });
|
|
});
|
|
});
|
|
|
|
it('should call navigateByUrl to a 401 page, when the remote data contains a 403 error, and not emit anything', () => {
|
|
testScheduler.run(({ cold, expectObservable, flush }) => {
|
|
const testRD = createFailedRemoteDataObject('Forbidden', 403);
|
|
const source = cold('a', { a: testRD });
|
|
const expected = '-';
|
|
const values = {};
|
|
|
|
expectObservable(source.pipe(redirectOn4xx(router, authService))).toBe(expected, values);
|
|
flush();
|
|
expect(router.navigateByUrl).toHaveBeenCalledWith('/403', { skipLocationChange: true });
|
|
});
|
|
});
|
|
|
|
it('should not call navigateByUrl to a 404, 403 or 401 page, when the remote data contains another error than a 404, 422, 403 or 401, and emit the source rd', () => {
|
|
testScheduler.run(({ cold, expectObservable, flush }) => {
|
|
const testRD = createFailedRemoteDataObject('Something went wrong', 500);
|
|
const source = cold('a', { a: testRD });
|
|
const expected = 'a';
|
|
const values = { a: testRD };
|
|
|
|
expectObservable(source.pipe(redirectOn4xx(router, authService))).toBe(expected, values);
|
|
flush();
|
|
expect(router.navigateByUrl).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
it('should not call navigateByUrl to a 404, 403 or 401 page, when the remote data contains no error, and emit the source rd', () => {
|
|
testScheduler.run(({ cold, expectObservable, flush }) => {
|
|
const testRD = createSuccessfulRemoteDataObject(undefined);
|
|
const source = cold('a', { a: testRD });
|
|
const expected = 'a';
|
|
const values = { a: testRD };
|
|
|
|
expectObservable(source.pipe(redirectOn4xx(router, authService))).toBe(expected, values);
|
|
flush();
|
|
expect(router.navigateByUrl).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('when the user is not authenticated', () => {
|
|
beforeEach(() => {
|
|
(authService.isAuthenticated as jasmine.Spy).and.returnValue(observableOf(false));
|
|
});
|
|
|
|
it('should set the redirect url and navigate to login when the remote data contains a 401 error, and not emit anything', () => {
|
|
testScheduler.run(({ cold, expectObservable, flush }) => {
|
|
const testRD = createFailedRemoteDataObject('The current user is unauthorized', 401);
|
|
const source = cold('a', { a: testRD });
|
|
const expected = '-';
|
|
const values = {};
|
|
|
|
expectObservable(source.pipe(redirectOn4xx(router, authService))).toBe(expected, values);
|
|
flush();
|
|
expect(authService.setRedirectUrl).toHaveBeenCalled();
|
|
expect(router.navigateByUrl).toHaveBeenCalledWith('login');
|
|
});
|
|
});
|
|
|
|
it('should set the redirect url and navigate to login when the remote data contains a 403 error, and not emit anything', () => {
|
|
testScheduler.run(({ cold, expectObservable, flush }) => {
|
|
const testRD = createFailedRemoteDataObject('Forbidden', 403);
|
|
const source = cold('a', { a: testRD });
|
|
const expected = '-';
|
|
const values = {};
|
|
|
|
expectObservable(source.pipe(redirectOn4xx(router, authService))).toBe(expected, values);
|
|
flush();
|
|
expect(authService.setRedirectUrl).toHaveBeenCalled();
|
|
expect(router.navigateByUrl).toHaveBeenCalledWith('login');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('getResponseFromEntry', () => {
|
|
it('should return the response for all not empty request entries, when they have a value', () => {
|
|
const source = hot('abcdefg', testRCEs);
|
|
const result = source.pipe(getResponseFromEntry());
|
|
const expected = cold('abcde--', {
|
|
a: testRCEs.a.response,
|
|
b: testRCEs.b.response,
|
|
c: testRCEs.c.response,
|
|
d: testRCEs.d.response,
|
|
e: testRCEs.e.response
|
|
});
|
|
|
|
expect(result).toBeObservable(expected);
|
|
});
|
|
});
|
|
|
|
describe('getAllSucceededRemoteData', () => {
|
|
it('should return all hasSucceeded RemoteData Observables', () => {
|
|
const testRD = {
|
|
a: createFailedRemoteDataObject(),
|
|
b: createFailedRemoteDataObject(),
|
|
c: createSuccessfulRemoteDataObject('c'),
|
|
d: createSuccessfulRemoteDataObject('d'),
|
|
};
|
|
const source = hot('abcd', testRD);
|
|
const result = source.pipe(getAllSucceededRemoteData());
|
|
const expected = cold('--cd', testRD);
|
|
|
|
expect(result).toBeObservable(expected);
|
|
|
|
});
|
|
|
|
});
|
|
});
|