diff --git a/src/app/core/auth/auth.effects.ts b/src/app/core/auth/auth.effects.ts index d876add98e..22d1bf35e7 100644 --- a/src/app/core/auth/auth.effects.ts +++ b/src/app/core/auth/auth.effects.ts @@ -67,7 +67,6 @@ export class AuthEffects { * Authenticate user. * @method authenticate */ - public authenticate$: Observable = createEffect(() => this.actions$.pipe( ofType(AuthActionTypes.AUTHENTICATE), switchMap((action: AuthenticateAction) => { @@ -79,13 +78,11 @@ export class AuthEffects { }) )); - public authenticateSuccess$: Observable = createEffect(() => this.actions$.pipe( ofType(AuthActionTypes.AUTHENTICATE_SUCCESS), map((action: AuthenticationSuccessAction) => new AuthenticatedAction(action.payload)) )); - public authenticated$: Observable = createEffect(() => this.actions$.pipe( ofType(AuthActionTypes.AUTHENTICATED), switchMap((action: AuthenticatedAction) => { @@ -95,7 +92,6 @@ export class AuthEffects { }) )); - public authenticatedSuccess$: Observable = createEffect(() => this.actions$.pipe( ofType(AuthActionTypes.AUTHENTICATED_SUCCESS), tap((action: AuthenticatedSuccessAction) => this.authService.storeToken(action.payload.authToken)), @@ -112,7 +108,6 @@ export class AuthEffects { }) )); - public redirectAfterLoginSuccess$: Observable = createEffect(() => this.actions$.pipe( ofType(AuthActionTypes.REDIRECT_AFTER_LOGIN_SUCCESS), tap((action: RedirectAfterLoginSuccessAction) => { @@ -122,13 +117,11 @@ export class AuthEffects { ), { dispatch: false }); // It means "reacts to this action but don't send another" - public authenticatedError$: Observable = createEffect(() => this.actions$.pipe( ofType(AuthActionTypes.AUTHENTICATED_ERROR), tap((action: LogOutSuccessAction) => this.authService.removeToken()) ), { dispatch: false }); - public retrieveAuthenticatedEperson$: Observable = createEffect(() => this.actions$.pipe( ofType(AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON), switchMap((action: RetrieveAuthenticatedEpersonAction) => { @@ -145,7 +138,6 @@ export class AuthEffects { }) )); - public checkToken$: Observable = createEffect(() => this.actions$.pipe(ofType(AuthActionTypes.CHECK_AUTHENTICATION_TOKEN), switchMap(() => { return this.authService.hasValidAuthenticationToken().pipe( @@ -155,7 +147,6 @@ export class AuthEffects { }) )); - public checkTokenCookie$: Observable = createEffect(() => this.actions$.pipe( ofType(AuthActionTypes.CHECK_AUTHENTICATION_TOKEN_COOKIE), switchMap(() => { @@ -173,7 +164,6 @@ export class AuthEffects { }) )); - public retrieveToken$: Observable = createEffect(() => this.actions$.pipe( ofType(AuthActionTypes.RETRIEVE_TOKEN), switchMap((action: AuthenticateAction) => { @@ -185,7 +175,6 @@ export class AuthEffects { }) )); - public refreshToken$: Observable = createEffect(() => this.actions$.pipe(ofType(AuthActionTypes.REFRESH_TOKEN), switchMap((action: RefreshTokenAction) => { return this.authService.refreshAuthenticationToken(action.payload).pipe( @@ -196,7 +185,6 @@ export class AuthEffects { )); // It means "reacts to this action but don't send another" - public refreshTokenSuccess$: Observable = createEffect(() => this.actions$.pipe( ofType(AuthActionTypes.REFRESH_TOKEN_SUCCESS), tap((action: RefreshTokenSuccessAction) => this.authService.replaceToken(action.payload)) @@ -206,13 +194,12 @@ export class AuthEffects { * When the store is rehydrated in the browser, * clear a possible invalid token or authentication errors */ - public clearInvalidTokenOnRehydrate$: Observable = createEffect(() => this.actions$.pipe( ofType(StoreActionTypes.REHYDRATE), switchMap(() => { const isLoaded$ = this.store.pipe(select(isAuthenticatedLoaded)); const authenticated$ = this.store.pipe(select(isAuthenticated)); - return observableCombineLatest(isLoaded$, authenticated$).pipe( + return observableCombineLatest([isLoaded$, authenticated$]).pipe( take(1), filter(([loaded, authenticated]) => loaded && !authenticated), tap(() => this.authService.removeToken()), @@ -230,7 +217,6 @@ export class AuthEffects { tap(() => this.authorizationsService.invalidateAuthorizationsRequestCache()) ), { dispatch: false }); - public logOut$: Observable = createEffect(() => this.actions$ .pipe( ofType(AuthActionTypes.LOG_OUT), @@ -243,7 +229,6 @@ export class AuthEffects { }) )); - public logOutSuccess$: Observable = createEffect(() => this.actions$ .pipe(ofType(AuthActionTypes.LOG_OUT_SUCCESS), tap(() => this.authService.removeToken()), @@ -251,7 +236,6 @@ export class AuthEffects { tap(() => this.authService.refreshAfterLogout()) ), { dispatch: false }); - public redirectToLoginTokenExpired$: Observable = createEffect(() => this.actions$ .pipe( ofType(AuthActionTypes.REDIRECT_TOKEN_EXPIRED), @@ -259,7 +243,6 @@ export class AuthEffects { tap(() => this.authService.redirectToLoginWhenTokenExpired()) ), { dispatch: false }); - public retrieveMethods$: Observable = createEffect(() => this.actions$ .pipe( ofType(AuthActionTypes.RETRIEVE_AUTH_METHODS), @@ -278,7 +261,6 @@ export class AuthEffects { * => Return the action to set the user as idle ({@link SetUserAsIdleAction}) * @method trackIdleness */ - public trackIdleness$: Observable = createEffect(() => this.actions$.pipe( filter((action: Action) => !IDLE_TIMER_IGNORE_TYPES.includes(action.type)), // Using switchMap the effect will stop subscribing to the previous timer if a new action comes diff --git a/src/app/core/auth/selectors.ts b/src/app/core/auth/selectors.ts index 9ee9f7eb2e..4ce7e65c13 100644 --- a/src/app/core/auth/selectors.ts +++ b/src/app/core/auth/selectors.ts @@ -1,4 +1,4 @@ -import { createSelector } from '@ngrx/store'; +import { createFeatureSelector, createSelector } from '@ngrx/store'; /** * Every reducer module's default export is the reducer function itself. In @@ -8,6 +8,8 @@ import { createSelector } from '@ngrx/store'; */ import { AuthState } from './auth.reducer'; import { AppState } from '../../app.reducer'; +import { CoreState } from '../core.reducers'; +import { coreSelector } from '../core.selectors'; /** * Returns the user state. @@ -15,7 +17,7 @@ import { AppState } from '../../app.reducer'; * @param {AppState} state Top level state. * @return {AuthState} */ -export const getAuthState = (state: any) => state.core.auth; +export const getAuthState = createSelector(coreSelector, (state: CoreState) => state.auth); /** * Returns true if the user is authenticated. diff --git a/src/app/submission/selectors.ts b/src/app/submission/selectors.ts index 09f1bae3fe..fbb538a07e 100644 --- a/src/app/submission/selectors.ts +++ b/src/app/submission/selectors.ts @@ -8,7 +8,7 @@ import { SubmissionObjectEntry, SubmissionSectionObject } from './objects/submis * Export a function to return a subset of the state by key */ export function keySelector(parentSelector: Selector, subState: string, key: string): MemoizedSelector { - return createSelector(parentSelector, (state: T) => { + return createSelector(parentSelector, (state: T) => { if (hasValue(state) && hasValue(state[subState])) { return state[subState][key]; } else { @@ -21,7 +21,7 @@ export function keySelector(parentSelector: Selector, subState: * Export a function to return a subset of the state */ export function subStateSelector(parentSelector: Selector, subState: string): MemoizedSelector { - return createSelector(parentSelector, (state: T) => { + return createSelector(parentSelector, (state: T) => { if (hasValue(state) && hasValue(state[subState])) { return state[subState]; } else { diff --git a/src/test.ts b/src/test.ts index 6b03dbe8b6..dfafd98807 100644 --- a/src/test.ts +++ b/src/test.ts @@ -2,6 +2,7 @@ import 'zone.js/testing'; import { getTestBed } from '@angular/core/testing'; +import { MockStore } from '@ngrx/store/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting @@ -12,10 +13,15 @@ declare const require: any; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), { - teardown: { destroyAfterEach: false } -} + platformBrowserDynamicTesting(), + { teardown: { destroyAfterEach: false } } ); + +// If store is mocked, reset state after each test (see https://ngrx.io/guide/migration/v13) +jasmine.getEnv().afterEach(() => { + getTestBed().inject(MockStore, null)?.resetSelectors(); +}); + // Then we find all the tests. const context = require.context('./', true, /\.spec\.ts$/); // And load the modules.