import { Component, DebugElement, Injectable } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { RouterTestingModule } from '@angular/router/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { Observable, Subject } from 'rxjs'; import { pairwise, startWith } from 'rxjs/operators'; import { NbSidebarComponent, NbMenuModule, NbMenuItem, NbSidebarModule, NbMenuComponent, NbThemeModule, NbMenuItemComponent, NbIconComponent, NbSidebarService, NbSidebarState, NbMediaBreakpoint, NbThemeService, NbMediaBreakpointsService, NbSidebarResponsiveState, } from '@nebular/theme'; @Component({ template: ` `, }) export class SidebarExpandTestComponent { menuItems: NbMenuItem[] = [ { title: 'no children', }, { title: 'parent', children: [ { title: 'child' } ], }, { title: 'group', group: true, }, ]; responsive = false; state: NbSidebarState = 'expanded'; } @Injectable() export class MockThemeService { private breakpoint$ = new Subject(); constructor(private breakpointsService: NbMediaBreakpointsService) { } setBreakpointTo(breakpointName: string): void { this.breakpoint$.next(this.breakpointsService.getByName(breakpointName)); } onMediaQueryChange(): Observable { const breakpoints = this.breakpointsService.getBreakpoints(); const largestBreakpoint = breakpoints[breakpoints.length - 1]; return this.breakpoint$ .pipe( startWith({ name: 'unknown', width: undefined }, largestBreakpoint), pairwise(), ); } } describe('NbSidebarComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ RouterTestingModule.withRoutes([]), NoopAnimationsModule, NbThemeModule.forRoot(), NbSidebarModule.forRoot(), NbMenuModule.forRoot(), ], providers: [ MockThemeService, { provide: NbThemeService, useExisting: MockThemeService }, ], declarations: [ SidebarExpandTestComponent ], }); }); describe('States (expanded, collapsed, compacted)', () => { let fixture: ComponentFixture; let sidebarComponent: NbSidebarComponent; let themeService: MockThemeService; beforeEach(() => { fixture = TestBed.createComponent(SidebarExpandTestComponent); fixture.detectChanges(); sidebarComponent = fixture.debugElement.query(By.directive(NbSidebarComponent)).componentInstance; themeService = TestBed.inject(MockThemeService); }); it(`should collapse when collapse method called`, () => { sidebarComponent.collapse(); fixture.detectChanges(); expect(sidebarComponent.expanded).toEqual(false); }); it('should become compacted when compact method called', () => { sidebarComponent.compact(); fixture.detectChanges(); expect(sidebarComponent.compacted).toEqual(true); }); it('should not expand when clicked outside menu', () => { const buttonOutsideMenu: DebugElement = fixture.debugElement.query(By.css('#button-outside-menu')); sidebarComponent.compact(); fixture.detectChanges(); buttonOutsideMenu.nativeElement.click(); fixture.detectChanges(); expect(sidebarComponent.compacted).toEqual(true); }); it('should not expand when clicked on menu item without children', () => { sidebarComponent.compact(); fixture.detectChanges(); const menuItemWithNoChildren: DebugElement = fixture.debugElement.query(By.directive(NbMenuComponent)); menuItemWithNoChildren.nativeElement.click(); fixture.detectChanges(); expect(sidebarComponent.compacted).toEqual(true); }); it('should not expand when clicked on menu group', () => { sidebarComponent.compact(); fixture.detectChanges(); const menuGroup: DebugElement = fixture.debugElement.queryAll(By.directive(NbMenuItemComponent))[3]; menuGroup.query(By.css('span')).nativeElement.click(); fixture.detectChanges(); expect(sidebarComponent.compacted).toEqual(true); }); it('should expand when icon of menu item with child items clicked', () => { sidebarComponent.compact(); fixture.detectChanges(); const menuItemWithChildren: DebugElement = fixture.debugElement.queryAll(By.directive(NbMenuItemComponent))[1]; menuItemWithChildren.query(By.directive(NbIconComponent)).nativeElement.click(); fixture.detectChanges(); expect(sidebarComponent.expanded).toEqual(true); }); it('should expand when link of menu item with child items clicked', () => { sidebarComponent.compact(); fixture.detectChanges(); const menuItemWithChildren: DebugElement = fixture.debugElement.queryAll(By.directive(NbMenuItemComponent))[1]; menuItemWithChildren.query(By.css('a')).nativeElement.click(); fixture.detectChanges(); expect(sidebarComponent.expanded).toEqual(true); }); it('should compact when sidebar service compact method called', () => { const sidebarService: NbSidebarService = TestBed.inject(NbSidebarService); expect(sidebarComponent.compacted).toEqual(false); sidebarService.compact(); fixture.detectChanges(); expect(sidebarComponent.compacted).toEqual(true); }); it('should expand when responsive is set to false', () => { sidebarComponent.responsive = true; sidebarComponent.collapse(); expect(sidebarComponent.state).toEqual('collapsed'); sidebarComponent.responsive = false; expect(sidebarComponent.state).toEqual('expanded'); }); it('should update state according to the current breakpoint when responsive turns on (update to compacted)', () => { const compactedBreakpoints = sidebarComponent.compactedBreakpoints; const largestCompactedBreakpointName = compactedBreakpoints[compactedBreakpoints.length - 1]; themeService.setBreakpointTo(largestCompactedBreakpointName); expect(sidebarComponent.state).toEqual('expanded'); sidebarComponent.responsive = true; expect(sidebarComponent.state).toEqual('compacted'); }); it('should update state according to the current breakpoint when responsive turns on (update to collapsed)', () => { themeService.setBreakpointTo(sidebarComponent.collapsedBreakpoints[0]); expect(sidebarComponent.state).toEqual('expanded'); sidebarComponent.responsive = true; expect(sidebarComponent.state).toEqual('collapsed'); }); it('should expand when responsive and initial state is in different breakpoint', () => { fixture = TestBed.createComponent(SidebarExpandTestComponent); fixture.componentInstance.responsive = true; fixture.componentInstance.state = 'compacted'; fixture.detectChanges(); sidebarComponent = fixture.debugElement.query(By.directive(NbSidebarComponent)).componentInstance; expect(sidebarComponent.state).toEqual('expanded'); }); it('Should return default sidebar state', (done: DoneFn) => { const sidebarService: NbSidebarService = TestBed.inject(NbSidebarService); fixture.detectChanges(); sidebarService.getSidebarState().subscribe((state: NbSidebarState) => { expect(state).toBe('expanded'); done(); }); }); it('Should return changed sidebar state', (done: DoneFn) => { const sidebarService: NbSidebarService = TestBed.inject(NbSidebarService); sidebarComponent.collapse(); fixture.detectChanges(); sidebarService.getSidebarState().subscribe((state: NbSidebarState) => { expect(state).toBe('collapsed'); done(); }); }); it('Should return default sidebar responsive state', (done: DoneFn) => { const sidebarService: NbSidebarService = TestBed.inject(NbSidebarService); fixture.detectChanges(); sidebarService.getSidebarResponsiveState().subscribe((state: NbSidebarResponsiveState) => { expect(state).toBe('pc'); done(); }); }); it('Should return changed sidebar responsive state', (done: DoneFn) => { const sidebarService: NbSidebarService = TestBed.inject(NbSidebarService); themeService.setBreakpointTo('md'); sidebarComponent.responsive = true; fixture.detectChanges(); sidebarService.getSidebarResponsiveState().subscribe((state: NbSidebarResponsiveState) => { expect(state).toBe('tablet'); done(); }); }); }); });