import { CUSTOM_ELEMENTS_SCHEMA, DebugElement, } from '@angular/core'; import { ComponentFixture, inject, TestBed, waitForAsync, } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { ActivatedRoute } from '@angular/router'; import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; import { Store, StoreModule, } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; import { of } from 'rxjs'; import { APP_DATA_SERVICES_MAP } from '../../../config/app-config.interface'; import { AppState } from '../../app.reducer'; import { authReducer, AuthState, } from '../../core/auth/auth.reducer'; import { AuthService } from '../../core/auth/auth.service'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; import { XSRFService } from '../../core/xsrf/xsrf.service'; import { HostWindowService } from '../host-window.service'; import { ActivatedRouteStub } from '../testing/active-router.stub'; import { BrowserOnlyMockPipe } from '../testing/browser-only-mock.pipe'; import { EPersonMock } from '../testing/eperson.mock'; import { HostWindowServiceStub } from '../testing/host-window-service.stub'; import { AuthNavMenuComponent } from './auth-nav-menu.component'; describe('AuthNavMenuComponent', () => { let component: AuthNavMenuComponent; let deNavMenu: DebugElement; let deNavMenuItem: DebugElement; let fixture: ComponentFixture<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, loaded: false, blocking: false, loading: false, idle: false, }; authState = { authenticated: true, loaded: true, blocking: false, loading: false, authToken: new AuthTokenInfo('test_token'), userId: EPersonMock.id, idle: false, }; } describe('when is a not mobile view', () => { beforeEach(waitForAsync(() => { const window = new HostWindowServiceStub(800); serviceInit(); // refine the test module by declaring the test component TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, StoreModule.forRoot(authReducer, { runtimeChecks: { strictStateImmutability: false, strictActionImmutability: false, }, }), TranslateModule.forRoot(), AuthNavMenuComponent, NgbDropdownModule, BrowserOnlyMockPipe, ], providers: [ { provide: APP_DATA_SERVICES_MAP, useValue: {} }, { provide: HostWindowService, useValue: window }, { provide: AuthService, useValue: authService }, { provide: ActivatedRoute, useValue: new ActivatedRouteStub() }, { provide: XSRFService, useValue: {} }, ], schemas: [ CUSTOM_ELEMENTS_SCHEMA, ], }) .compileComponents(); })); beforeEach(() => { init(); }); describe('when route is /login and user is not authenticated', () => { beforeEach(inject([Store], (store: Store<AppState>) => { routerState = { url: '/login', }; store .subscribe((state) => { (state as any).router = Object.create({}); (state as any).router.state = routerState; (state as any).core = Object.create({}); (state as any).core.auth = notAuthState; }); // create component and test fixture fixture = TestBed.createComponent(AuthNavMenuComponent); // get test component from the fixture component = fixture.componentInstance; fixture.detectChanges(); const navMenuSelector = '[data-test="auth-nav"]'; deNavMenu = fixture.debugElement.query(By.css(navMenuSelector)); const navMenuItemSelector = '.nav-item'; deNavMenuItem = deNavMenu.query(By.css(navMenuItemSelector)); })); afterEach(() => { fixture.destroy(); }); it('should not render', () => { expect(component).toBeTruthy(); expect(deNavMenu.nativeElement).toBeDefined(); expect(deNavMenuItem).toBeNull(); }); }); describe('when route is /logout and user is authenticated', () => { beforeEach(inject([Store], (store: Store<AppState>) => { routerState = { url: '/logout', }; store .subscribe((state) => { (state as any).router = Object.create({}); (state as any).router.state = routerState; (state as any).core = Object.create({}); (state as any).core.auth = authState; }); // create component and test fixture fixture = TestBed.createComponent(AuthNavMenuComponent); // get test component from the fixture component = fixture.componentInstance; fixture.detectChanges(); const navMenuSelector = '[data-test="auth-nav"]'; deNavMenu = fixture.debugElement.query(By.css(navMenuSelector)); const navMenuItemSelector = '.nav-item'; deNavMenuItem = deNavMenu.query(By.css(navMenuItemSelector)); })); afterEach(() => { fixture.destroy(); }); it('should not render', () => { expect(component).toBeTruthy(); expect(deNavMenu.nativeElement).toBeDefined(); expect(deNavMenuItem).toBeNull(); }); }); describe('when route is not /login neither /logout', () => { describe('when user is not authenticated', () => { beforeEach(inject([Store], (store: Store<AppState>) => { routerState = { url: '/home', }; store .subscribe((state) => { (state as any).router = Object.create({}); (state as any).router.state = routerState; (state as any).core = Object.create({}); (state as any).core.auth = notAuthState; }); // create component and test fixture fixture = TestBed.createComponent(AuthNavMenuComponent); // get test component from the fixture component = fixture.componentInstance; fixture.detectChanges(); const navMenuSelector = '[data-test="auth-nav"]'; deNavMenu = fixture.debugElement.query(By.css(navMenuSelector)); const navMenuItemSelector = '.nav-item'; deNavMenuItem = deNavMenu.query(By.css(navMenuItemSelector)); })); afterEach(() => { fixture.destroy(); component = null; }); it('should render login dropdown menu', () => { const loginDropdownMenu = deNavMenuItem.query(By.css('div#loginDropdownMenu')); expect(loginDropdownMenu.nativeElement).toBeDefined(); }); }); describe('when user is authenticated', () => { beforeEach(inject([Store], (store: Store<AppState>) => { routerState = { url: '/home', }; store .subscribe((state) => { (state as any).router = Object.create({}); (state as any).router.state = routerState; (state as any).core = Object.create({}); (state as any).core.auth = authState; }); // create component and test fixture fixture = TestBed.createComponent(AuthNavMenuComponent); // get test component from the fixture component = fixture.componentInstance; fixture.detectChanges(); const navMenuSelector = '[data-test="auth-nav"]'; deNavMenu = fixture.debugElement.query(By.css(navMenuSelector)); const navMenuItemSelector = '.nav-item'; deNavMenuItem = deNavMenu.query(By.css(navMenuItemSelector)); })); afterEach(() => { fixture.destroy(); component = null; }); it('should render UserMenuComponent component', () => { const logoutDropdownMenu = deNavMenuItem.query(By.css('ds-user-menu')); expect(logoutDropdownMenu.nativeElement).toBeDefined(); }); }); }); }); describe('when is a mobile view', () => { beforeEach(waitForAsync(() => { const window = new HostWindowServiceStub(300); serviceInit(); // refine the test module by declaring the test component TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, StoreModule.forRoot(authReducer, { runtimeChecks: { strictStateImmutability: false, strictActionImmutability: false, }, }), TranslateModule.forRoot(), AuthNavMenuComponent, ], providers: [ { provide: HostWindowService, useValue: window }, { provide: AuthService, useValue: authService }, { provide: ActivatedRoute, useValue: new ActivatedRouteStub() }, ], schemas: [ CUSTOM_ELEMENTS_SCHEMA, ], }) .compileComponents(); })); beforeEach(() => { init(); }); describe('when user is not authenticated', () => { beforeEach(inject([Store], (store: Store<AppState>) => { store .subscribe((state) => { (state as any).router = Object.create({}); (state as any).router.state = routerState; (state as any).core = Object.create({}); (state as any).core.auth = notAuthState; }); // create component and test fixture fixture = TestBed.createComponent(AuthNavMenuComponent); // get test component from the fixture component = fixture.componentInstance; fixture.detectChanges(); const navMenuSelector = '[data-test="auth-nav"]'; deNavMenu = fixture.debugElement.query(By.css(navMenuSelector)); })); afterEach(() => { fixture.destroy(); component = null; }); it('should render login link', () => { const loginDropdownMenu = deNavMenu.query(By.css('.loginLink')); expect(loginDropdownMenu.nativeElement).toBeDefined(); }); }); describe('when user is authenticated', () => { beforeEach(inject([Store], (store: Store<AppState>) => { store .subscribe((state) => { (state as any).router = Object.create({}); (state as any).router.state = routerState; (state as any).core = Object.create({}); (state as any).core.auth = authState; }); // create component and test fixture fixture = TestBed.createComponent(AuthNavMenuComponent); // get test component from the fixture component = fixture.componentInstance; fixture.detectChanges(); const navMenuSelector = '[data-test="auth-nav"]'; deNavMenu = fixture.debugElement.query(By.css(navMenuSelector)); })); afterEach(() => { fixture.destroy(); component = null; }); it('should render logout link', inject([Store], (store: Store<AppState>) => { const logoutDropdownMenu = deNavMenu.query(By.css('a.logoutLink')); expect(logoutDropdownMenu.nativeElement).toBeDefined(); })); }); }); });