Skip to content
Snippets Groups Projects
Commit f34490db authored by Giuseppe Digilio's avatar Giuseppe Digilio
Browse files

Added tests

parent e0ac7ea0
Branches
Tags
No related merge requests found
import { cold, hot } from 'jasmine-marbles';
import { Observable } from 'rxjs/Observable';
import { TestBed } from '@angular/core/testing';
import { provideMockActions } from '@ngrx/effects/testing';
import { AuthEffects } from './auth.effects';
import {
AuthActionTypes,
AuthenticatedAction,
AuthenticatedErrorAction,
AuthenticatedSuccessAction,
AuthenticationErrorAction,
AuthenticationSuccessAction,
CheckAuthenticationTokenErrorAction,
LogOutErrorAction,
LogOutSuccessAction,
RefreshTokenErrorAction,
RefreshTokenSuccessAction
} from './auth.actions';
import { AuthTokenInfo } from './models/auth-token-info.model';
import { AuthServiceStub } from '../../shared/testing/auth-service-stub';
import { AuthService } from './auth.service';
import { TruncatablesState } from '../../shared/truncatable/truncatable.reducer';
import { Store } from '@ngrx/store';
import { EpersonMock } from '../../shared/testing/eperson-mock';
describe('AuthEffects', () => {
let authEffects: AuthEffects;
let actions: Observable<any>;
const store: Store<TruncatablesState> = jasmine.createSpyObj('store', {
/* tslint:disable:no-empty */
dispatch: {},
/* tslint:enable:no-empty */
select: Observable.of(true)
});
const token = new AuthTokenInfo('token_test');
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
AuthEffects,
{provide: AuthService, useClass: AuthServiceStub},
{provide: Store, useValue: store},
provideMockActions(() => actions),
// other providers
],
});
authEffects = TestBed.get(AuthEffects);
});
describe('authenticate$', () => {
describe('when credentials are correct', () => {
it('should return a AUTHENTICATE_SUCCESS action in response to a AUTHENTICATE action', () => {
actions = hot('--a-', {
a: {
type: AuthActionTypes.AUTHENTICATE,
payload: {email: 'user', password: 'password'}
}
});
const expected = cold('--b-', {b: new AuthenticationSuccessAction(new AuthTokenInfo('token_test'))});
expect(authEffects.authenticate$).toBeObservable(expected);
});
});
describe('when credentials are wrong', () => {
it('should return a AUTHENTICATE_ERROR action in response to a AUTHENTICATE action', () => {
spyOn((authEffects as any).authService, 'authenticate').and.returnValue(Observable.throw(new Error('Message Error test')));
actions = hot('--a-', {
a: {
type: AuthActionTypes.AUTHENTICATE,
payload: {email: 'user', password: 'wrongpassword'}
}
});
const expected = cold('--b-', {b: new AuthenticationErrorAction(new Error('Message Error test'))});
expect(authEffects.authenticate$).toBeObservable(expected);
});
});
});
describe('authenticateSuccess$', () => {
it('should return a AUTHENTICATED action in response to a AUTHENTICATE_SUCCESS action', () => {
actions = hot('--a-', {a: {type: AuthActionTypes.AUTHENTICATE_SUCCESS, payload: token}});
const expected = cold('--b-', {b: new AuthenticatedAction(new AuthTokenInfo('token_test'))});
expect(authEffects.authenticateSuccess$).toBeObservable(expected);
});
});
describe('authenticated$', () => {
describe('when token is valid', () => {
it('should return a AUTHENTICATED_SUCCESS action in response to a AUTHENTICATED action', () => {
actions = hot('--a-', {a: {type: AuthActionTypes.AUTHENTICATED, payload: token}});
const expected = cold('--b-', {b: new AuthenticatedSuccessAction(true, token, EpersonMock)});
expect(authEffects.authenticated$).toBeObservable(expected);
});
});
describe('when token is not valid', () => {
it('should return a AUTHENTICATED_ERROR action in response to a AUTHENTICATED action', () => {
spyOn((authEffects as any).authService, 'authenticatedUser').and.returnValue(Observable.throw(new Error('Message Error test')));
actions = hot('--a-', {a: {type: AuthActionTypes.AUTHENTICATED, payload: token}});
const expected = cold('--b-', {b: new AuthenticatedErrorAction(new Error('Message Error test'))});
expect(authEffects.authenticated$).toBeObservable(expected);
});
});
});
describe('checkToken$', () => {
describe('when check token succeeded', () => {
it('should return a AUTHENTICATED action in response to a CHECK_AUTHENTICATION_TOKEN action', () => {
actions = hot('--a-', {a: {type: AuthActionTypes.CHECK_AUTHENTICATION_TOKEN}});
const expected = cold('--b-', {b: new AuthenticatedAction(new AuthTokenInfo('token_test'))});
expect(authEffects.checkToken$).toBeObservable(expected);
});
});
describe('when check token failed', () => {
it('should return a CHECK_AUTHENTICATION_TOKEN_ERROR action in response to a CHECK_AUTHENTICATION_TOKEN action', () => {
spyOn((authEffects as any).authService, 'hasValidAuthenticationToken').and.returnValue(Observable.throw(''));
actions = hot('--a-', {a: {type: AuthActionTypes.CHECK_AUTHENTICATION_TOKEN, payload: token}});
const expected = cold('--b-', {b: new CheckAuthenticationTokenErrorAction()});
expect(authEffects.checkToken$).toBeObservable(expected);
});
})
});
describe('refreshToken$', () => {
describe('when refresh token succeeded', () => {
it('should return a REFRESH_TOKEN_SUCCESS action in response to a REFRESH_TOKEN action', () => {
actions = hot('--a-', {a: {type: AuthActionTypes.REFRESH_TOKEN}});
const expected = cold('--b-', {b: new RefreshTokenSuccessAction(new AuthTokenInfo('token_test'))});
expect(authEffects.refreshToken$).toBeObservable(expected);
});
});
describe('when refresh token failed', () => {
it('should return a REFRESH_TOKEN_ERROR action in response to a REFRESH_TOKEN action', () => {
spyOn((authEffects as any).authService, 'refreshAuthenticationToken').and.returnValue(Observable.throw(''));
actions = hot('--a-', {a: {type: AuthActionTypes.REFRESH_TOKEN, payload: token}});
const expected = cold('--b-', {b: new RefreshTokenErrorAction()});
expect(authEffects.refreshToken$).toBeObservable(expected);
});
})
});
describe('logOut$', () => {
describe('when refresh token succeeded', () => {
it('should return a LOG_OUT_SUCCESS action in response to a LOG_OUT action', () => {
actions = hot('--a-', {a: {type: AuthActionTypes.LOG_OUT}});
const expected = cold('--b-', {b: new LogOutSuccessAction()});
expect(authEffects.logOut$).toBeObservable(expected);
});
});
describe('when refresh token failed', () => {
it('should return a REFRESH_TOKEN_ERROR action in response to a LOG_OUT action', () => {
spyOn((authEffects as any).authService, 'logout').and.returnValue(Observable.throw(new Error('Message Error test')));
actions = hot('--a-', {a: {type: AuthActionTypes.LOG_OUT, payload: token}});
const expected = cold('--b-', {b: new LogOutErrorAction(new Error('Message Error test'))});
expect(authEffects.logOut$).toBeObservable(expected);
});
})
});
});
import { Injectable } from '@angular/core';
// import @ngrx
import { Effect, Actions } from '@ngrx/effects';
import { Actions, Effect } from '@ngrx/effects';
import { Action, Store } from '@ngrx/store';
// import rxjs
......@@ -9,16 +9,22 @@ import { Observable } from 'rxjs/Observable';
// import services
import { AuthService } from './auth.service';
// import actions
import {
AuthActionTypes, AuthenticateAction, AuthenticatedAction,
AuthActionTypes,
AuthenticateAction,
AuthenticatedAction,
AuthenticatedErrorAction,
AuthenticatedSuccessAction,
AuthenticationErrorAction,
AuthenticationSuccessAction, CheckAuthenticationTokenErrorAction,
AuthenticationSuccessAction,
CheckAuthenticationTokenErrorAction,
LogOutErrorAction,
LogOutSuccessAction, RefreshTokenAction, RefreshTokenErrorAction, RefreshTokenSuccessAction, RegistrationAction,
LogOutSuccessAction,
RefreshTokenAction,
RefreshTokenErrorAction,
RefreshTokenSuccessAction,
RegistrationAction,
RegistrationErrorAction,
RegistrationSuccessAction
} from './auth.actions';
......@@ -37,7 +43,7 @@ export class AuthEffects {
* @method authenticate
*/
@Effect()
public authenticate: Observable<Action> = this.actions$
public authenticate$: Observable<Action> = this.actions$
.ofType(AuthActionTypes.AUTHENTICATE)
.switchMap((action: AuthenticateAction) => {
return this.authService.authenticate(action.payload.email, action.payload.password)
......@@ -47,13 +53,13 @@ export class AuthEffects {
});
@Effect()
public authenticateSuccess: Observable<Action> = this.actions$
public authenticateSuccess$: Observable<Action> = this.actions$
.ofType(AuthActionTypes.AUTHENTICATE_SUCCESS)
.do((action: AuthenticationSuccessAction) => this.authService.storeToken(action.payload))
.map((action: AuthenticationSuccessAction) => new AuthenticatedAction(action.payload));
@Effect()
public authenticated: Observable<Action> = this.actions$
public authenticated$: Observable<Action> = this.actions$
.ofType(AuthActionTypes.AUTHENTICATED)
.switchMap((action: AuthenticatedAction) => {
return this.authService.authenticatedUser(action.payload)
......@@ -63,12 +69,12 @@ export class AuthEffects {
// It means "reacts to this action but don't send another"
@Effect({dispatch: false})
public authenticatedError: Observable<Action> = this.actions$
public authenticatedError$: Observable<Action> = this.actions$
.ofType(AuthActionTypes.AUTHENTICATED_ERROR)
.do((action: LogOutSuccessAction) => this.authService.removeToken());
@Effect()
public checkToken: Observable<Action> = this.actions$
public checkToken$: Observable<Action> = this.actions$
.ofType(AuthActionTypes.CHECK_AUTHENTICATION_TOKEN)
.switchMap(() => {
return this.authService.hasValidAuthenticationToken()
......@@ -77,7 +83,7 @@ export class AuthEffects {
});
@Effect()
public createUser: Observable<Action> = this.actions$
public createUser$: Observable<Action> = this.actions$
.ofType(AuthActionTypes.REGISTRATION)
.debounceTime(500) // to remove when functionality is implemented
.switchMap((action: RegistrationAction) => {
......@@ -87,7 +93,7 @@ export class AuthEffects {
});
@Effect()
public refreshToken: Observable<Action> = this.actions$
public refreshToken$: Observable<Action> = this.actions$
.ofType(AuthActionTypes.REFRESH_TOKEN)
.switchMap((action: RefreshTokenAction) => {
return this.authService.refreshAuthenticationToken(action.payload)
......@@ -97,7 +103,7 @@ export class AuthEffects {
// It means "reacts to this action but don't send another"
@Effect({dispatch: false})
public refreshTokenSuccess: Observable<Action> = this.actions$
public refreshTokenSuccess$: Observable<Action> = this.actions$
.ofType(AuthActionTypes.REFRESH_TOKEN_SUCCESS)
.do((action: RefreshTokenSuccessAction) => this.authService.replaceToken(action.payload));
......@@ -106,7 +112,7 @@ export class AuthEffects {
* clear a possible invalid token or authentication errors
*/
@Effect({dispatch: false})
public clearInvalidTokenOnRehydrate = this.actions$
public clearInvalidTokenOnRehydrate$: Observable<any> = this.actions$
.ofType(StoreActionTypes.REHYDRATE)
.switchMap(() => {
return this.store.select(isAuthenticated)
......@@ -117,7 +123,7 @@ export class AuthEffects {
});
@Effect()
public logOut: Observable<Action> = this.actions$
public logOut$: Observable<Action> = this.actions$
.ofType(AuthActionTypes.LOG_OUT)
.switchMap(() => {
return this.authService.logout()
......@@ -126,19 +132,19 @@ export class AuthEffects {
});
@Effect({dispatch: false})
public logOutSuccess: Observable<Action> = this.actions$
public logOutSuccess$: Observable<Action> = this.actions$
.ofType(AuthActionTypes.LOG_OUT_SUCCESS)
.do(() => this.authService.removeToken())
.do(() => this.authService.refreshAfterLogout());
@Effect({dispatch: false})
public redirectToLogin: Observable<Action> = this.actions$
public redirectToLogin$: Observable<Action> = this.actions$
.ofType(AuthActionTypes.REDIRECT_AUTHENTICATION_REQUIRED)
.do(() => this.authService.removeToken())
.do(() => this.authService.redirectToLogin());
@Effect({dispatch: false})
public redirectToLoginTokenExpired: Observable<Action> = this.actions$
public redirectToLoginTokenExpired$: Observable<Action> = this.actions$
.ofType(AuthActionTypes.REDIRECT_TOKEN_EXPIRED)
.do(() => this.authService.removeToken())
.do(() => this.authService.redirectToLoginWhenTokenExpired());
......
import { AuthStatus } from '../../core/auth/models/auth-status.model';
import { Observable } from 'rxjs/Observable';
import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model';
import { EpersonMock } from './eperson-mock';
import { Eperson } from '../../core/eperson/models/eperson.model';
export class AuthServiceStub {
public authenticate(user: string, password: string): Observable<AuthStatus> {
if (user === 'user' && password === 'password') {
const authStatus = new AuthStatus();
authStatus.okay = true;
authStatus.authenticated = true;
authStatus.token = new AuthTokenInfo('token_test');
authStatus.eperson = [EpersonMock];
return Observable.of(authStatus);
} else {
console.log('error');
throw(new Error('Message Error test'));
}
}
public authenticatedUser(token: AuthTokenInfo): Observable<Eperson> {
if (token.accessToken === 'token_test') {
return Observable.of(EpersonMock);
} else {
throw(new Error('Message Error test'));
}
}
public hasValidAuthenticationToken(): Observable<AuthTokenInfo> {
return Observable.of(new AuthTokenInfo('token_test'));
}
public logout(): Observable<boolean> {
return Observable.of(true);
}
public refreshAuthenticationToken(token: AuthTokenInfo): Observable<AuthTokenInfo> {
return Observable.of(new AuthTokenInfo('token_test'));
}
public redirectToPreviousUrl() {
return;
}
public removeToken() {
return;
}
public storeToken(token: AuthTokenInfo) {
return;
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment