import { Component, ElementRef, Input, NgModule, Type, ViewChild } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { RouterTestingModule } from '@angular/router/testing';
import { NbThemeModule } from '../../theme.module';
import { NbLayoutModule } from '../layout/layout.module';
import { NbAdjustment, NbPosition } from '../cdk/overlay/overlay-position';
import { NbDynamicOverlayHandler } from '../cdk/overlay/dynamic/dynamic-overlay-handler';
import { NbOverlayContent } from '../cdk/overlay/overlay-service';
import { NbRenderableContainer } from '../cdk/overlay/overlay-container';
import { NbTrigger } from '../cdk/overlay/overlay-trigger';
import { NbMenuModule } from '../menu/menu.module';
import { NbContextMenuDirective } from './context-menu.directive';
import { NbContextMenuComponent } from './context-menu.component';
import { NbContextMenuModule } from './context-menu.module';
import { NbOverlayConfig } from '../cdk/overlay/mapping';
@Component({
selector: 'nb-context-menu-default-test',
template: `
`,
})
export class NbContextMenuDefaultTestComponent {
@ViewChild('button') button: ElementRef;
@ViewChild(NbContextMenuDirective) contextMenu: NbContextMenuDirective;
items = [{ title: 'User' }, { title: 'Log Out' }];
contextMenuClass = '';
}
@Component({
selector: 'nb-context-menu-bindings-test',
template: `
`,
})
export class NbContextMenuBindingsTestComponent {
@ViewChild(NbContextMenuDirective) contextMenu: NbContextMenuDirective;
@ViewChild('button') button: ElementRef;
@Input() trigger = NbTrigger.CLICK;
@Input() position = NbPosition.TOP;
@Input() adjustment = NbAdjustment.CLOCKWISE;
@Input() tag = '';
@Input() items = [{ title: 'User' }, { title: 'Log Out' }];
}
@Component({
selector: 'nb-context-menu-instance-test',
template: `
Some Template
`,
})
export class NbContextMenuInstanceTestComponent {
@ViewChild(NbContextMenuDirective) contextMenu: NbContextMenuDirective;
@ViewChild('button') button: ElementRef;
items = [{ title: 'User' }, { title: 'Log Out' }];
}
const dynamicOverlay = {
show() {},
hide() {},
toggle() {},
destroy() {},
};
export class NbDynamicOverlayHandlerMock {
_componentType: Type;
_host: ElementRef;
_context: Object = {};
_content: NbOverlayContent;
_trigger: NbTrigger = NbTrigger.NOOP;
_position: NbPosition = NbPosition.TOP;
_adjustment: NbAdjustment = NbAdjustment.NOOP;
_offset: number;
_overlayConfig: NbOverlayConfig = {};
constructor() {
}
host(host: ElementRef) {
this._host = host;
return this;
}
trigger(trigger: NbTrigger) {
this._trigger = trigger;
return this;
}
position(position: NbPosition) {
this._position = position;
return this;
}
adjustment(adjustment: NbAdjustment) {
this._adjustment = adjustment;
return this;
}
componentType(componentType: Type) {
this._componentType = componentType;
return this;
}
content(content: NbOverlayContent) {
this._content = content;
return this;
}
context(context: {}) {
this._context = context;
return this;
}
offset(offset: number) {
this._offset = offset;
return this;
}
overlayConfig(overlayConfig: NbOverlayConfig) {
this._overlayConfig = overlayConfig;
return this;
}
build() {
return dynamicOverlay;
}
rebuild() {
return dynamicOverlay;
}
connect() {
}
disconnect() {
}
destroy() {
}
}
const TEST_COMPONENTS = [
NbContextMenuDefaultTestComponent,
NbContextMenuBindingsTestComponent,
NbContextMenuInstanceTestComponent,
];
@NgModule({
imports: [NbLayoutModule, NbContextMenuModule],
exports: [...TEST_COMPONENTS],
declarations: [...TEST_COMPONENTS],
})
class ContextMenuTestModule { }
describe('Directive: NbContextMenuDirective', () => {
const overlayHandler = new NbDynamicOverlayHandlerMock();
beforeEach(waitForAsync(() => {
TestBed.resetTestingModule();
TestBed.configureTestingModule({
imports: [
NoopAnimationsModule,
RouterTestingModule.withRoutes([]),
NbThemeModule.forRoot(),
NbMenuModule.forRoot(),
ContextMenuTestModule,
],
});
}));
describe('smoke ', () => {
let fixture: ComponentFixture;
afterEach(() => {
fixture.destroy();
});
it('should render string', () => {
fixture = TestBed.createComponent(NbContextMenuDefaultTestComponent);
fixture.detectChanges();
fixture.componentInstance.contextMenu.show();
fixture.detectChanges();
const textContainer = fixture.nativeElement.querySelector('nb-menu');
expect(textContainer.textContent).toContain('Log Out');
});
it('should hide', () => fakeAsync(() => {
fixture = TestBed.createComponent(NbContextMenuDefaultTestComponent);
fixture.detectChanges();
fixture.componentInstance.contextMenu.show();
fixture.detectChanges();
const textContainer = fixture.nativeElement.querySelector('nb-menu');
expect(textContainer.textContent).toContain('Logout');
fixture.componentInstance.contextMenu.hide();
fixture.detectChanges();
tick(); // we need this tick for animations
const contextMenu = fixture.nativeElement.querySelector('nb-menu');
expect(contextMenu).toBeNull();
}));
it('should render different items', () => {
fixture = TestBed.createComponent(NbContextMenuDefaultTestComponent);
fixture.detectChanges();
fixture.componentInstance.contextMenu.show();
fixture.detectChanges();
fixture.componentInstance.items = [ { title: 'Hello' } ];
fixture.detectChanges();
const textContainer = fixture.nativeElement.querySelector('nb-menu');
expect(textContainer.textContent).toContain('Hello');
});
});
describe('mocked services', () => {
beforeEach(waitForAsync(() => {
TestBed.resetTestingModule();
TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes([]),
NbThemeModule.forRoot(),
NbMenuModule.forRoot(),
ContextMenuTestModule,
],
})
.overrideDirective(NbContextMenuDirective, {
set: {
providers: [
{ provide: NbDynamicOverlayHandler, useValue: overlayHandler },
],
},
});
}));
describe('default context-menu', () => {
let fixture: ComponentFixture;
afterEach(() => {
fixture.destroy();
});
it('should build', () => {
const componentSpy = spyOn(overlayHandler, 'componentType').and.callThrough();
const hostSpy = spyOn(overlayHandler, 'host').and.callThrough();
const positionSpy = spyOn(overlayHandler, 'position').and.callThrough();
const triggerSpy = spyOn(overlayHandler, 'trigger').and.callThrough();
const adjustmentSpy = spyOn(overlayHandler, 'adjustment').and.callThrough();
const contentSpy = spyOn(overlayHandler, 'content').and.callThrough();
const contextSpy = spyOn(overlayHandler, 'context').and.callThrough();
const offsetSpy = spyOn(overlayHandler, 'offset').and.callThrough();
const buildSpy = spyOn(overlayHandler, 'build').and.callThrough();
const rebuildSpy = spyOn(overlayHandler, 'rebuild').and.callThrough();
fixture = TestBed.createComponent(NbContextMenuDefaultTestComponent);
fixture.detectChanges();
expect(componentSpy).toHaveBeenCalledTimes(1);
expect(componentSpy).toHaveBeenCalledWith(NbContextMenuComponent);
expect(hostSpy).toHaveBeenCalledWith(fixture.componentInstance.button);
expect(hostSpy).toHaveBeenCalledTimes(1);
expect(offsetSpy).toHaveBeenCalledTimes(0);
expect(positionSpy).toHaveBeenCalledTimes(2);
expect(positionSpy).toHaveBeenCalledWith(NbPosition.BOTTOM);
expect(triggerSpy).toHaveBeenCalledTimes(2);
expect(triggerSpy).toHaveBeenCalledWith(NbTrigger.CLICK);
expect(adjustmentSpy).toHaveBeenCalledTimes(2);
expect(adjustmentSpy).toHaveBeenCalledWith(NbAdjustment.CLOCKWISE);
expect(contentSpy).toHaveBeenCalledTimes(0);
expect(contextSpy).toHaveBeenCalledTimes(2);
expect(contextSpy).toHaveBeenCalledWith({
position: NbPosition.BOTTOM,
items: [{ title: 'User' }, { title: 'Log Out' }],
tag: undefined,
});
expect(buildSpy).toHaveBeenCalledTimes(1);
expect(rebuildSpy).toHaveBeenCalledTimes(1);
});
it('should show/hide/toggle', () => {
fixture = TestBed.createComponent(NbContextMenuDefaultTestComponent);
fixture.detectChanges();
const showSpy = spyOn(dynamicOverlay, 'show').and.callThrough();
const hideSpy = spyOn(dynamicOverlay, 'hide').and.callThrough();
const toggleSpy = spyOn(dynamicOverlay, 'toggle').and.callThrough();
fixture.componentInstance.contextMenu.show();
fixture.detectChanges();
expect(showSpy).toHaveBeenCalledTimes(1);
expect(hideSpy).toHaveBeenCalledTimes(0);
expect(toggleSpy).toHaveBeenCalledTimes(0);
fixture.componentInstance.contextMenu.hide();
fixture.detectChanges();
expect(showSpy).toHaveBeenCalledTimes(1);
expect(hideSpy).toHaveBeenCalledTimes(1);
expect(toggleSpy).toHaveBeenCalledTimes(0);
fixture.componentInstance.contextMenu.toggle();
fixture.detectChanges();
expect(showSpy).toHaveBeenCalledTimes(1);
expect(hideSpy).toHaveBeenCalledTimes(1);
expect(toggleSpy).toHaveBeenCalledTimes(1);
});
it('should set overlay config', () => {
const contextMenuClass = 'custom-context-menu-class';
const overlayConfigSpy = spyOn(overlayHandler, 'overlayConfig').and.callThrough();
fixture = TestBed.createComponent(NbContextMenuDefaultTestComponent);
fixture.componentInstance.contextMenuClass = contextMenuClass;
fixture.detectChanges();
expect(overlayConfigSpy).toHaveBeenCalledWith(jasmine.objectContaining({panelClass: contextMenuClass}));
});
});
describe('binding contextMenu', () => {
let fixture: ComponentFixture;
afterEach(() => {
fixture.destroy();
});
it('should rebuild', () => {
const componentSpy = spyOn(overlayHandler, 'componentType').and.callThrough();
const hostSpy = spyOn(overlayHandler, 'host').and.callThrough();
const positionSpy = spyOn(overlayHandler, 'position').and.callThrough();
const triggerSpy = spyOn(overlayHandler, 'trigger').and.callThrough();
const adjustmentSpy = spyOn(overlayHandler, 'adjustment').and.callThrough();
const contentSpy = spyOn(overlayHandler, 'content').and.callThrough();
const contextSpy = spyOn(overlayHandler, 'context').and.callThrough();
const offsetSpy = spyOn(overlayHandler, 'offset').and.callThrough();
const buildSpy = spyOn(overlayHandler, 'build').and.callThrough();
const rebuildSpy = spyOn(overlayHandler, 'rebuild').and.callThrough();
fixture = TestBed.createComponent(NbContextMenuBindingsTestComponent);
fixture.detectChanges();
fixture.componentInstance.adjustment = NbAdjustment.HORIZONTAL;
fixture.componentInstance.trigger = NbTrigger.HOVER;
fixture.componentInstance.items = [{ title: 'New' }];
fixture.componentInstance.tag = 'new';
fixture.componentInstance.position = NbPosition.LEFT;
fixture.detectChanges();
expect(componentSpy).toHaveBeenCalledTimes(1);
expect(componentSpy).toHaveBeenCalledWith(NbContextMenuComponent);
expect(hostSpy).toHaveBeenCalledWith(fixture.componentInstance.button);
expect(hostSpy).toHaveBeenCalledTimes(1);
expect(offsetSpy).toHaveBeenCalledTimes(0);
expect(positionSpy).toHaveBeenCalledTimes(3);
expect(positionSpy).toHaveBeenCalledWith(NbPosition.LEFT);
expect(triggerSpy).toHaveBeenCalledTimes(3);
expect(triggerSpy).toHaveBeenCalledWith(NbTrigger.HOVER);
expect(adjustmentSpy).toHaveBeenCalledTimes(3);
expect(adjustmentSpy).toHaveBeenCalledWith(NbAdjustment.HORIZONTAL);
expect(contentSpy).toHaveBeenCalledTimes(0);
expect(contextSpy).toHaveBeenCalledTimes(3);
expect(contextSpy).toHaveBeenCalledWith({
position: NbPosition.LEFT,
items: [{ title: 'New' }],
tag: 'new',
});
expect(buildSpy).toHaveBeenCalledTimes(1);
expect(rebuildSpy).toHaveBeenCalledTimes(2);
});
});
describe('instance context-menu', () => {
let fixture: ComponentFixture;
afterEach(() => {
fixture.destroy();
});
it('should rebuild', () => {
const componentSpy = spyOn(overlayHandler, 'componentType').and.callThrough();
const hostSpy = spyOn(overlayHandler, 'host').and.callThrough();
const positionSpy = spyOn(overlayHandler, 'position').and.callThrough();
const triggerSpy = spyOn(overlayHandler, 'trigger').and.callThrough();
const adjustmentSpy = spyOn(overlayHandler, 'adjustment').and.callThrough();
const contentSpy = spyOn(overlayHandler, 'content').and.callThrough();
const contextSpy = spyOn(overlayHandler, 'context').and.callThrough();
const offsetSpy = spyOn(overlayHandler, 'offset').and.callThrough();
const buildSpy = spyOn(overlayHandler, 'build').and.callThrough();
const rebuildSpy = spyOn(overlayHandler, 'rebuild').and.callThrough();
fixture = TestBed.createComponent(NbContextMenuInstanceTestComponent);
fixture.detectChanges();
fixture.componentInstance.contextMenu.adjustment = NbAdjustment.HORIZONTAL;
fixture.componentInstance.contextMenu.trigger = NbTrigger.HOVER;
fixture.componentInstance.contextMenu.items = [{ title: 'New' }];
fixture.componentInstance.contextMenu.tag = 'new';
fixture.componentInstance.contextMenu.position = NbPosition.LEFT;
fixture.componentInstance.contextMenu.rebuild();
expect(componentSpy).toHaveBeenCalledTimes(1);
expect(componentSpy).toHaveBeenCalledWith(NbContextMenuComponent);
expect(hostSpy).toHaveBeenCalledWith(fixture.componentInstance.button);
expect(hostSpy).toHaveBeenCalledTimes(1);
expect(positionSpy).toHaveBeenCalledTimes(3);
expect(positionSpy).toHaveBeenCalledWith(NbPosition.LEFT);
expect(triggerSpy).toHaveBeenCalledTimes(3);
expect(triggerSpy).toHaveBeenCalledWith(NbTrigger.HOVER);
expect(offsetSpy).toHaveBeenCalledTimes(0);
expect(adjustmentSpy).toHaveBeenCalledTimes(3);
expect(adjustmentSpy).toHaveBeenCalledWith(NbAdjustment.HORIZONTAL);
expect(contentSpy).toHaveBeenCalledTimes(0);
expect(contextSpy).toHaveBeenCalledTimes(3);
expect(contextSpy).toHaveBeenCalledWith({
position: NbPosition.LEFT,
items: [{ title: 'New' }],
tag: 'new',
});
expect(buildSpy).toHaveBeenCalledTimes(1);
expect(rebuildSpy).toHaveBeenCalledTimes(2);
});
});
});
});