From 7b64d6bc3101dcd086ac096b1ea111c87a2cef17 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 26 May 2020 14:08:54 +0200 Subject: [PATCH] 68067: JSDocs + menu-effects tests --- src/app/shared/menu/menu.component.spec.ts | 76 +----------- src/app/shared/menu/menu.effects.spec.ts | 129 +++++++++++++++++++++ src/app/shared/menu/menu.effects.ts | 12 ++ 3 files changed, 144 insertions(+), 73 deletions(-) create mode 100644 src/app/shared/menu/menu.effects.spec.ts diff --git a/src/app/shared/menu/menu.component.spec.ts b/src/app/shared/menu/menu.component.spec.ts index 901f072dd7..2b83ec4414 100644 --- a/src/app/shared/menu/menu.component.spec.ts +++ b/src/app/shared/menu/menu.component.spec.ts @@ -7,71 +7,25 @@ import { MenuComponent } from './menu.component'; import { MenuServiceStub } from '../testing/menu-service.stub'; import { of as observableOf } from 'rxjs'; import { MenuSection } from './menu.reducer'; -import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; +import { Router } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; -import { MenuID, MenuItemType } from './initial-menus-state'; -import { LinkMenuItemModel } from './menu-item/models/link.model'; +import { MenuID } from './initial-menus-state'; describe('MenuComponent', () => { let comp: MenuComponent; let fixture: ComponentFixture; let menuService: MenuService; - let routeDataMenuSection: MenuSection; - let routeDataMenuChildSection: MenuSection; - let route: any; let router: any; const mockMenuID = 'mock-menuID' as MenuID; beforeEach(async(() => { - routeDataMenuSection = { - id: 'mockSection', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.mockSection', - link: '' - } as LinkMenuItemModel - }; - routeDataMenuChildSection = { - id: 'mockChildSection', - parentID: 'mockSection', - active: false, - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.mockChildSection', - link: '' - } as LinkMenuItemModel - }; - route = { - root: { - snapshot: { - data: { - menu: { - [mockMenuID]: routeDataMenuSection - } - } - }, - firstChild: { - snapshot: { - data: { - menu: { - [mockMenuID]: routeDataMenuChildSection - } - } - } - } - } - }; TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), NoopAnimationsModule, RouterTestingModule], declarations: [MenuComponent], providers: [ { provide: Injector, useValue: {} }, - { provide: MenuService, useClass: MenuServiceStub }, - { provide: ActivatedRoute, useValue: route } + { provide: MenuService, useClass: MenuServiceStub } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(MenuComponent, { @@ -90,30 +44,6 @@ describe('MenuComponent', () => { fixture.detectChanges(); }); - describe('ngOnInit', () => { - beforeEach(() => { - spyOn(comp, 'resolveMenuSections').and.returnValue([]); - }); - - it('should call resolveMenuSections on init', () => { - router.events = observableOf(new NavigationEnd(0, '', '')); - comp.ngOnInit(); - expect(comp.resolveMenuSections).toHaveBeenCalledWith(route.root); - }) - }); - - describe('resolveMenuSections', () => { - let result: MenuSection[]; - - beforeEach(() => { - result = comp.resolveMenuSections(route.root); - }); - - it('should return the current route\'s menu sections', () => { - expect(result).toEqual([routeDataMenuSection, routeDataMenuChildSection]) - }); - }); - describe('toggle', () => { beforeEach(() => { spyOn(menuService, 'toggleMenu'); diff --git a/src/app/shared/menu/menu.effects.spec.ts b/src/app/shared/menu/menu.effects.spec.ts new file mode 100644 index 0000000000..11b468eded --- /dev/null +++ b/src/app/shared/menu/menu.effects.spec.ts @@ -0,0 +1,129 @@ +import { MenuID, MenuItemType } from './initial-menus-state'; +import { MenuSection } from './menu.reducer'; +import { LinkMenuItemModel } from './menu-item/models/link.model'; +import { TestBed } from '@angular/core/testing'; +import { MenuService } from './menu.service'; +import { ActivatedRoute } from '@angular/router'; +import { Observable } from 'rxjs/internal/Observable'; +import { provideMockActions } from '@ngrx/effects/testing'; +import { of as observableOf } from 'rxjs'; +import { cold, hot } from 'jasmine-marbles'; +import { ROUTER_NAVIGATED } from '@ngrx/router-store'; +import { MenuEffects } from './menu.effects'; + +describe('MenuEffects', () => { + let menuEffects: MenuEffects; + let routeDataMenuSection: MenuSection; + let routeDataMenuChildSection: MenuSection; + let toBeRemovedMenuSection: MenuSection; + let alreadyPresentMenuSection: MenuSection; + let route; + let menuService; + let actions: Observable; + + function init() { + routeDataMenuSection = { + id: 'mockSection', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.mockSection', + link: '' + } as LinkMenuItemModel + }; + routeDataMenuChildSection = { + id: 'mockChildSection', + parentID: 'mockSection', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.mockChildSection', + link: '' + } as LinkMenuItemModel + }; + toBeRemovedMenuSection = { + id: 'toBeRemovedSection', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.toBeRemovedSection', + link: '' + } as LinkMenuItemModel + }; + alreadyPresentMenuSection = { + id: 'alreadyPresentSection', + active: false, + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.alreadyPresentSection', + link: '' + } as LinkMenuItemModel + }; + route = { + root: { + snapshot: { + data: { + menu: { + [MenuID.PUBLIC]: [routeDataMenuSection, alreadyPresentMenuSection] + } + } + }, + firstChild: { + snapshot: { + data: { + menu: { + [MenuID.PUBLIC]: routeDataMenuChildSection + } + } + } + } + } + }; + + menuService = jasmine.createSpyObj('menuService', { + getNonPersistentMenuSections: observableOf([toBeRemovedMenuSection, alreadyPresentMenuSection]), + addSection: {}, + removeSection: {} + }); + } + + beforeEach(() => { + init(); + TestBed.configureTestingModule({ + providers: [ + MenuEffects, + { provide: MenuService, useValue: menuService }, + { provide: ActivatedRoute, useValue: route }, + provideMockActions(() => actions) + ] + }); + + menuEffects = TestBed.get(MenuEffects); + }); + + describe('buildRouteMenuSections$', () => { + it('should add and remove menu sections depending on the current route', () => { + actions = hot('--a-', { + a: { + type: ROUTER_NAVIGATED + } + }); + + const expected = cold('--b-', { + b: { + type: ROUTER_NAVIGATED + } + }); + + expect(menuEffects.buildRouteMenuSections$).toBeObservable(expected); + expect(menuService.addSection).toHaveBeenCalledWith(MenuID.PUBLIC, routeDataMenuSection); + expect(menuService.addSection).toHaveBeenCalledWith(MenuID.PUBLIC, routeDataMenuChildSection); + expect(menuService.addSection).not.toHaveBeenCalledWith(MenuID.PUBLIC, alreadyPresentMenuSection); + expect(menuService.removeSection).toHaveBeenCalledWith(MenuID.PUBLIC, toBeRemovedMenuSection.id); + }); + }); +}); diff --git a/src/app/shared/menu/menu.effects.ts b/src/app/shared/menu/menu.effects.ts index f0a6c3f958..92df41caff 100644 --- a/src/app/shared/menu/menu.effects.ts +++ b/src/app/shared/menu/menu.effects.ts @@ -10,6 +10,9 @@ import { Injectable } from '@angular/core'; import { map, take, tap } from 'rxjs/operators'; import { MenuID } from './initial-menus-state'; +/** + * Effects modifying the state of menus + */ @Injectable() export class MenuEffects { @@ -18,6 +21,9 @@ export class MenuEffects { private route: ActivatedRoute) { } + /** + * On route change, build menu sections for every menu type depending on the current route data + */ @Effect({ dispatch: false }) public buildRouteMenuSections$: Observable = this.actions$ .pipe( @@ -29,6 +35,12 @@ export class MenuEffects { }) ); + /** + * Build menu sections depending on the current route + * - Adds sections found in the current route data that aren't active yet + * - Removes sections that are active, but not present in the current route data + * @param menuID The menu to add/remove sections to/from + */ buildRouteMenuSections(menuID: MenuID) { this.menuService.getNonPersistentMenuSections(menuID).pipe( map((sections) => sections.map((section) => section.id)),