diff --git a/src/framework/theme/components/sidebar/sidebar.component.ts b/src/framework/theme/components/sidebar/sidebar.component.ts index e36614744c..e438f661ec 100644 --- a/src/framework/theme/components/sidebar/sidebar.component.ts +++ b/src/framework/theme/components/sidebar/sidebar.component.ts @@ -338,15 +338,8 @@ export class NbSidebarComponent implements OnChanges, OnInit, OnDestroy { const menu = this.element.nativeElement.querySelector('nb-menu'); if (menu && menu.contains(event.target)) { - let link = event.target; - const linkChildren = ['span', 'i']; + const link = this.getMenuLink(event.target); - // if we clicked on span - get the link - if (linkChildren.includes(link.tagName.toLowerCase()) && link.parentNode) { - link = event.target.parentNode; - } - - // we only expand if an item has children if (link && link.nextElementSibling && link.nextElementSibling.classList.contains('menu-items')) { this.expand(); } @@ -430,4 +423,16 @@ export class NbSidebarComponent implements OnChanges, OnInit, OnDestroy { protected responsiveEnabled(): boolean { return this.responsiveValue; } + + protected getMenuLink(element: HTMLElement): HTMLElement | undefined { + if (!element || element.tagName.toLowerCase() === 'nb-menu') { + return; + } + + if (element.tagName.toLowerCase() === 'a') { + return element; + } + + return this.getMenuLink(element.parentElement); + } } diff --git a/src/framework/theme/components/sidebar/sidebar.spec.ts b/src/framework/theme/components/sidebar/sidebar.spec.ts new file mode 100644 index 0000000000..676691955a --- /dev/null +++ b/src/framework/theme/components/sidebar/sidebar.spec.ts @@ -0,0 +1,134 @@ +import { Component, DebugElement } 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 { + NbSidebarComponent, + NbMenuModule, + NbMenuItem, + NbSidebarModule, + NbMenuComponent, + NbThemeModule, + NbMenuItemComponent, NbIconComponent, +} from '@nebular/theme'; + +@Component({ + template: ` + + + + + `, +}) +export class SidebarExpandTestComponent { + menuItems: NbMenuItem[] = [ + { + title: 'no children', + }, + { + title: 'parent', + children: [ { title: 'child' } ], + }, + { + title: 'group', + group: true, + }, + ]; +} + +describe('NbSidebarComponent', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + RouterTestingModule.withRoutes([]), + NoopAnimationsModule, + NbThemeModule.forRoot(), + NbSidebarModule.forRoot(), + NbMenuModule.forRoot(), + ], + declarations: [ SidebarExpandTestComponent ], + }); + }); + + describe('States (expanded, collapsed, compacted)', () => { + let fixture: ComponentFixture; + let sidebarComponent: NbSidebarComponent; + + beforeEach(() => { + fixture = TestBed.createComponent(SidebarExpandTestComponent); + fixture.detectChanges(); + + sidebarComponent = fixture.debugElement.query(By.directive(NbSidebarComponent)).componentInstance; + }); + + 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); + }); + }); +});