68067: JSDocs + menu-effects tests

This commit is contained in:
Kristof De Langhe
2020-05-26 14:08:54 +02:00
parent 0b67bd54fb
commit 7b64d6bc31
3 changed files with 144 additions and 73 deletions

View File

@@ -7,71 +7,25 @@ import { MenuComponent } from './menu.component';
import { MenuServiceStub } from '../testing/menu-service.stub'; import { MenuServiceStub } from '../testing/menu-service.stub';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import { MenuSection } from './menu.reducer'; import { MenuSection } from './menu.reducer';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { MenuID, MenuItemType } from './initial-menus-state'; import { MenuID } from './initial-menus-state';
import { LinkMenuItemModel } from './menu-item/models/link.model';
describe('MenuComponent', () => { describe('MenuComponent', () => {
let comp: MenuComponent; let comp: MenuComponent;
let fixture: ComponentFixture<MenuComponent>; let fixture: ComponentFixture<MenuComponent>;
let menuService: MenuService; let menuService: MenuService;
let routeDataMenuSection: MenuSection;
let routeDataMenuChildSection: MenuSection;
let route: any;
let router: any; let router: any;
const mockMenuID = 'mock-menuID' as MenuID; const mockMenuID = 'mock-menuID' as MenuID;
beforeEach(async(() => { 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({ TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), NoopAnimationsModule, RouterTestingModule], imports: [TranslateModule.forRoot(), NoopAnimationsModule, RouterTestingModule],
declarations: [MenuComponent], declarations: [MenuComponent],
providers: [ providers: [
{ provide: Injector, useValue: {} }, { provide: Injector, useValue: {} },
{ provide: MenuService, useClass: MenuServiceStub }, { provide: MenuService, useClass: MenuServiceStub }
{ provide: ActivatedRoute, useValue: route }
], ],
schemas: [NO_ERRORS_SCHEMA] schemas: [NO_ERRORS_SCHEMA]
}).overrideComponent(MenuComponent, { }).overrideComponent(MenuComponent, {
@@ -90,30 +44,6 @@ describe('MenuComponent', () => {
fixture.detectChanges(); 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', () => { describe('toggle', () => {
beforeEach(() => { beforeEach(() => {
spyOn(menuService, 'toggleMenu'); spyOn(menuService, 'toggleMenu');

View File

@@ -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<any>;
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);
});
});
});

View File

@@ -10,6 +10,9 @@ import { Injectable } from '@angular/core';
import { map, take, tap } from 'rxjs/operators'; import { map, take, tap } from 'rxjs/operators';
import { MenuID } from './initial-menus-state'; import { MenuID } from './initial-menus-state';
/**
* Effects modifying the state of menus
*/
@Injectable() @Injectable()
export class MenuEffects { export class MenuEffects {
@@ -18,6 +21,9 @@ export class MenuEffects {
private route: ActivatedRoute) { private route: ActivatedRoute) {
} }
/**
* On route change, build menu sections for every menu type depending on the current route data
*/
@Effect({ dispatch: false }) @Effect({ dispatch: false })
public buildRouteMenuSections$: Observable<Action> = this.actions$ public buildRouteMenuSections$: Observable<Action> = this.actions$
.pipe( .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) { buildRouteMenuSections(menuID: MenuID) {
this.menuService.getNonPersistentMenuSections(menuID).pipe( this.menuService.getNonPersistentMenuSections(menuID).pipe(
map((sections) => sections.map((section) => section.id)), map((sections) => sections.map((section) => section.id)),