diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts index 4319c77e8b..7a301aa7e9 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts @@ -31,6 +31,8 @@ import { NotificationsServiceStub } from '../../../../shared/testing/notificatio import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; import { EPeopleRegistryComponent } from '../epeople-registry.component'; import { EPersonFormComponent } from './eperson-form.component'; +import { AuthService } from '../../../../core/auth/auth.service'; +import { AuthServiceStub } from '../../../../shared/testing/auth-service-stub'; describe('EPersonFormComponent', () => { let component: EPersonFormComponent; @@ -125,6 +127,7 @@ describe('EPersonFormComponent', () => { { provide: Store, useValue: {} }, { provide: RemoteDataBuildService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, + { provide: AuthService, useValue: new AuthServiceStub() }, EPeopleRegistryComponent ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts index f221042418..9e3bcc88c0 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -161,7 +161,9 @@ export class EPersonFormComponent implements OnInit, OnDestroy { private authService: AuthService) { this.subs.push(this.epersonService.getActiveEPerson().subscribe((eperson: EPerson) => { this.epersonInitial = eperson; - this.isImpersonated = this.authService.isImpersonatingUser(eperson.id); + if (hasValue(eperson)) { + this.isImpersonated = this.authService.isImpersonatingUser(eperson.id); + } })); } diff --git a/src/app/core/auth/auth.effects.spec.ts b/src/app/core/auth/auth.effects.spec.ts index 1f6fa51afd..872c71022f 100644 --- a/src/app/core/auth/auth.effects.spec.ts +++ b/src/app/core/auth/auth.effects.spec.ts @@ -234,7 +234,7 @@ describe('AuthEffects', () => { } }); - const expected = cold('--b-', { b: new RetrieveAuthenticatedEpersonSuccessAction(EPersonMock) }); + const expected = cold('--b-', { b: new RetrieveAuthenticatedEpersonSuccessAction(EPersonMock.id) }); expect(authEffects.retrieveAuthenticatedEperson$).toBeObservable(expected); }); diff --git a/src/app/core/auth/auth.reducer.spec.ts b/src/app/core/auth/auth.reducer.spec.ts index 7a39ef3da4..a50c469836 100644 --- a/src/app/core/auth/auth.reducer.spec.ts +++ b/src/app/core/auth/auth.reducer.spec.ts @@ -189,7 +189,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EPersonMock + userId: EPersonMock.id }; const action = new LogOutAction(); @@ -206,7 +206,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EPersonMock + userId: EPersonMock.id }; const action = new LogOutSuccessAction(); @@ -219,7 +219,7 @@ describe('authReducer', () => { loading: false, info: undefined, refreshing: false, - user: undefined + userId: undefined }; expect(newState).toEqual(state); }); @@ -232,7 +232,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EPersonMock + userId: EPersonMock.id }; const action = new LogOutErrorAction(mockError); @@ -244,7 +244,7 @@ describe('authReducer', () => { error: 'Test error message', loading: false, info: undefined, - user: EPersonMock + userId: EPersonMock.id }; expect(newState).toEqual(state); }); @@ -258,7 +258,7 @@ describe('authReducer', () => { loading: true, info: undefined }; - const action = new RetrieveAuthenticatedEpersonSuccessAction(EPersonMock); + const action = new RetrieveAuthenticatedEpersonSuccessAction(EPersonMock.id); const newState = authReducer(initialState, action); state = { authenticated: true, @@ -267,7 +267,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EPersonMock + userId: EPersonMock.id }; expect(newState).toEqual(state); }); @@ -301,7 +301,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EPersonMock + userId: EPersonMock.id }; const newTokenInfo = new AuthTokenInfo('Refreshed token'); const action = new RefreshTokenAction(newTokenInfo); @@ -313,7 +313,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EPersonMock, + userId: EPersonMock.id, refreshing: true }; expect(newState).toEqual(state); @@ -327,7 +327,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EPersonMock, + userId: EPersonMock.id, refreshing: true }; const newTokenInfo = new AuthTokenInfo('Refreshed token'); @@ -340,7 +340,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EPersonMock, + userId: EPersonMock.id, refreshing: false }; expect(newState).toEqual(state); @@ -354,7 +354,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EPersonMock, + userId: EPersonMock.id, refreshing: true }; const action = new RefreshTokenErrorAction(); @@ -367,7 +367,7 @@ describe('authReducer', () => { loading: false, info: undefined, refreshing: false, - user: undefined + userId: undefined }; expect(newState).toEqual(state); }); @@ -380,7 +380,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EPersonMock + userId: EPersonMock.id }; state = { @@ -390,7 +390,7 @@ describe('authReducer', () => { loading: false, error: undefined, info: 'Message', - user: undefined + userId: undefined }; }); diff --git a/src/app/profile-page/profile-page.component.spec.ts b/src/app/profile-page/profile-page.component.spec.ts index 5992012be9..3b9c8e7d6d 100644 --- a/src/app/profile-page/profile-page.component.spec.ts +++ b/src/app/profile-page/profile-page.component.spec.ts @@ -12,12 +12,15 @@ import { AuthTokenInfo } from '../core/auth/models/auth-token-info.model'; import { EPersonDataService } from '../core/eperson/eperson-data.service'; import { NotificationsService } from '../shared/notifications/notifications.service'; import { authReducer } from '../core/auth/auth.reducer'; +import { of } from 'rxjs/internal/observable/of'; +import { AuthService } from '../core/auth/auth.service'; describe('ProfilePageComponent', () => { let component: ProfilePageComponent; let fixture: ComponentFixture; const user = Object.assign(new EPerson(), { + id: 'userId', groups: createSuccessfulRemoteDataObject$(createPaginatedList([])) }); const authState = { @@ -25,9 +28,12 @@ describe('ProfilePageComponent', () => { loaded: true, loading: false, authToken: new AuthTokenInfo('test_token'), - user: user + userId: user.id }; + const authService = jasmine.createSpyObj('authService', { + getAuthenticatedUserFromStore: of(user) + }); const epersonService = jasmine.createSpyObj('epersonService', { findById: createSuccessfulRemoteDataObject$(user) }); @@ -43,7 +49,8 @@ describe('ProfilePageComponent', () => { imports: [StoreModule.forRoot(authReducer), TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], providers: [ { provide: EPersonDataService, useValue: epersonService }, - { provide: NotificationsService, useValue: notificationsService } + { provide: NotificationsService, useValue: notificationsService }, + { provide: AuthService, useValue: authService } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts index 5e01494674..9c20f2be4d 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts @@ -14,6 +14,7 @@ import { HostWindowService } from '../host-window.service'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; import { AuthService } from '../../core/auth/auth.service'; +import { of } from 'rxjs/internal/observable/of'; describe('AuthNavMenuComponent', () => { @@ -25,9 +26,19 @@ describe('AuthNavMenuComponent', () => { let notAuthState: AuthState; let authState: AuthState; + let authService: AuthService; + let routerState = { url: '/home' }; + + function serviceInit() { + authService = jasmine.createSpyObj('authService', { + getAuthenticatedUserFromStore: of(EPersonMock), + setRedirectUrl: {} + }); + } + function init() { notAuthState = { authenticated: false, @@ -39,13 +50,14 @@ describe('AuthNavMenuComponent', () => { loaded: true, loading: false, authToken: new AuthTokenInfo('test_token'), - user: EPersonMock + userId: EPersonMock.id }; } describe('when is a not mobile view', () => { beforeEach(async(() => { const window = new HostWindowServiceStub(800); + serviceInit(); // refine the test module by declaring the test component TestBed.configureTestingModule({ @@ -59,12 +71,7 @@ describe('AuthNavMenuComponent', () => { ], providers: [ { provide: HostWindowService, useValue: window }, - { - provide: AuthService, useValue: { - setRedirectUrl: () => { /*empty*/ - } - } - } + { provide: AuthService, useValue: authService } ], schemas: [ CUSTOM_ELEMENTS_SCHEMA @@ -239,6 +246,7 @@ describe('AuthNavMenuComponent', () => { describe('when is a mobile view', () => { beforeEach(async(() => { const window = new HostWindowServiceStub(300); + serviceInit(); // refine the test module by declaring the test component TestBed.configureTestingModule({ @@ -252,12 +260,7 @@ describe('AuthNavMenuComponent', () => { ], providers: [ { provide: HostWindowService, useValue: window }, - { - provide: AuthService, useValue: { - setRedirectUrl: () => { /*empty*/ - } - } - } + { provide: AuthService, useValue: authService } ], schemas: [ CUSTOM_ELEMENTS_SCHEMA diff --git a/src/app/shared/auth-nav-menu/user-menu/user-menu.component.spec.ts b/src/app/shared/auth-nav-menu/user-menu/user-menu.component.spec.ts index 512d9e0917..80d03dfc47 100644 --- a/src/app/shared/auth-nav-menu/user-menu/user-menu.component.spec.ts +++ b/src/app/shared/auth-nav-menu/user-menu/user-menu.component.spec.ts @@ -12,6 +12,8 @@ import { AppState } from '../../../app.reducer'; import { MockTranslateLoader } from '../../mocks/mock-translate-loader'; import { cold } from 'jasmine-marbles'; import { By } from '@angular/platform-browser'; +import { AuthService } from '../../../core/auth/auth.service'; +import { of } from 'rxjs'; describe('UserMenuComponent', () => { @@ -20,6 +22,13 @@ describe('UserMenuComponent', () => { let deUserMenu: DebugElement; let authState: AuthState; let authStateLoading: AuthState; + let authService: AuthService; + + function serviceInit() { + authService = jasmine.createSpyObj('authService', { + getAuthenticatedUserFromStore: of(EPersonMock) + }); + } function init() { authState = { @@ -27,18 +36,19 @@ describe('UserMenuComponent', () => { loaded: true, loading: false, authToken: new AuthTokenInfo('test_token'), - user: EPersonMock + userId: EPersonMock.id }; authStateLoading = { authenticated: true, loaded: true, loading: true, authToken: null, - user: EPersonMock + userId: EPersonMock.id }; } beforeEach(async(() => { + serviceInit(); TestBed.configureTestingModule({ imports: [ StoreModule.forRoot(authReducer), @@ -49,6 +59,9 @@ describe('UserMenuComponent', () => { } }) ], + providers: [ + { provide: AuthService, useValue: authService } + ], declarations: [ UserMenuComponent ], @@ -93,7 +106,7 @@ describe('UserMenuComponent', () => { b: true })); - expect(component.user$).toBeObservable(cold('c', { + expect(component.user$).toBeObservable(cold('(c|)', { c: EPersonMock })); @@ -132,7 +145,7 @@ describe('UserMenuComponent', () => { b: false })); - expect(component.user$).toBeObservable(cold('c', { + expect(component.user$).toBeObservable(cold('(c|)', { c: EPersonMock })); diff --git a/src/app/shared/testing/auth-service-stub.ts b/src/app/shared/testing/auth-service-stub.ts index 26ce79cb5f..2fd401aa49 100644 --- a/src/app/shared/testing/auth-service-stub.ts +++ b/src/app/shared/testing/auth-service-stub.ts @@ -5,6 +5,7 @@ import { EPersonMock } from './eperson-mock'; import { EPerson } from '../../core/eperson/models/eperson.model'; import { createSuccessfulRemoteDataObject$ } from './utils'; import { AuthMethod } from '../../core/auth/models/auth.method'; +import { hasValue } from '../empty.util'; export const authMethodsMock = [ new AuthMethod('password'), @@ -14,6 +15,7 @@ export const authMethodsMock = [ export class AuthServiceStub { token: AuthTokenInfo = new AuthTokenInfo('token_test'); + impersonating: string; private _tokenExpired = false; private redirectUrl; @@ -47,6 +49,10 @@ export class AuthServiceStub { return observableOf(EPersonMock); } + public retrieveAuthenticatedUserById(id: string): Observable { + return observableOf(EPersonMock); + } + public buildAuthHeader(token?: AuthTokenInfo): string { return `Bearer ${token.accessToken}`; } @@ -120,4 +126,28 @@ export class AuthServiceStub { retrieveAuthMethodsFromAuthStatus(status: AuthStatus) { return observableOf(authMethodsMock); } + + impersonate(id: string) { + this.impersonating = id; + } + + isImpersonating() { + return hasValue(this.impersonating); + } + + isImpersonatingUser(id: string) { + return this.impersonating === id; + } + + stopImpersonating() { + this.impersonating = undefined; + } + + stopImpersonatingAndRefresh() { + this.stopImpersonating(); + } + + getImpersonateID() { + return this.impersonating; + } }