ng2-tree-hackaday
Version:
angular2 component for visualizing data that can be naturally represented as a tree
183 lines (133 loc) • 6.49 kB
text/typescript
import { TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { EventEmitter } from '@angular/core';
import { NodeMenuComponent } from '../../src/menu/node-menu.component';
import { NodeMenuService } from '../../src/menu/node-menu.service';
import { NodeMenuItemAction, NodeMenuAction, NodeMenuEvent } from '../../src/menu/menu.events';
import { MouseButtons, Keys } from '../../src/utils/event.utils';
let fixture;
let nodeMenuService;
let componentInstance;
describe('NodeMenuComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [NodeMenuComponent],
providers: [NodeMenuService]
});
fixture = TestBed.createComponent(NodeMenuComponent);
componentInstance = fixture.debugElement.componentInstance;
nodeMenuService = TestBed.get(NodeMenuService);
});
it('should be created by angular', () => {
expect(fixture).not.toBeNull();
expect(nodeMenuService).not.toBeNull();
});
it('should have event emitter properly created', () => {
expect(fixture.componentInstance.menuItemSelected instanceof EventEmitter).toBe(true);
});
it('should have basic menu items', () => {
expect(fixture.componentInstance.availableMenuItems.length).toEqual(4);
expect(fixture.componentInstance.availableMenuItems[0]).toEqual({
name: "New tag",
action: NodeMenuItemAction.NewTag,
cssClass: 'new-tag'
});
expect(fixture.componentInstance.availableMenuItems[1]).toEqual({
name: 'New folder',
action: NodeMenuItemAction.NewFolder,
cssClass: 'new-folder'
});
expect(fixture.componentInstance.availableMenuItems[2]).toEqual({
name: 'Rename',
action: NodeMenuItemAction.Rename,
cssClass: 'rename'
});
expect(fixture.componentInstance.availableMenuItems[3]).toEqual({
name: 'Remove',
action: NodeMenuItemAction.Remove,
cssClass: 'remove'
});
});
it('should render basic menu items', () => {
fixture.detectChanges();
const menuItems = fixture.debugElement.queryAll(By.css('.node-menu-item'));
expect(menuItems).not.toBeNull();
expect(menuItems.length).toEqual(4);
expect(menuItems[0].query(By.css('.node-menu-item-icon')).nativeElement.classList).toContain('new-tag');
expect(menuItems[0].query(By.css('.node-menu-item-value')).nativeElement.innerText).toEqual('New tag');
expect(menuItems[1].query(By.css('.node-menu-item-icon')).nativeElement.classList).toContain('new-folder');
expect(menuItems[1].query(By.css('.node-menu-item-value')).nativeElement.innerText).toEqual('New folder');
expect(menuItems[2].query(By.css('.node-menu-item-icon')).nativeElement.classList).toContain('rename');
expect(menuItems[2].query(By.css('.node-menu-item-value')).nativeElement.innerText).toEqual('Rename');
expect(menuItems[3].query(By.css('.node-menu-item-icon')).nativeElement.classList).toContain('remove');
expect(menuItems[3].query(By.css('.node-menu-item-value')).nativeElement.innerText).toEqual('Remove');
});
it('should not emit an action on right mouse button click', () => {
fixture.detectChanges();
const event = {
button: MouseButtons.Right
};
const menuItem = fixture.debugElement.query(By.css('.node-menu-item'));
spyOn(componentInstance.menuItemSelected, 'emit');
menuItem.triggerEventHandler('click', event);
expect(componentInstance.menuItemSelected.emit).not.toHaveBeenCalled();
});
it('should emit an action on left mouse button click', () => {
fixture.detectChanges();
const event = {
button: MouseButtons.Left
};
const menuItem = fixture.debugElement.query(By.css('.node-menu-item'));
spyOn(componentInstance.menuItemSelected, 'emit');
menuItem.triggerEventHandler('click', event);
expect(componentInstance.menuItemSelected.emit).toHaveBeenCalledWith({nodeMenuItemAction: NodeMenuItemAction.NewTag});
});
it('should close menu on any click outside of it', () => {
fixture.detectChanges();
spyOn(nodeMenuService.nodeMenuEvents$, 'next');
const event = document.createEvent("MouseEvents");
event.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
document.dispatchEvent(event);
const expectedNodeMenuEvent: NodeMenuEvent = {
sender: (event.target as HTMLElement),
action: NodeMenuAction.Close
};
expect(nodeMenuService.nodeMenuEvents$.next).toHaveBeenCalledWith(expectedNodeMenuEvent);
expect(nodeMenuService.nodeMenuEvents$.next).toHaveBeenCalledTimes(1);
});
it('should close menu on any keyup outside of it', () => {
fixture.detectChanges();
spyOn(nodeMenuService.nodeMenuEvents$, 'next');
const event: any = document.createEvent('Events');
event.keyCode = Keys.Escape;
event.initEvent('keyup', true, true);
document.dispatchEvent(event);
const expectedNodeMenuEvent: NodeMenuEvent = {
sender: (event.target as HTMLElement),
action: NodeMenuAction.Close
};
expect(nodeMenuService.nodeMenuEvents$.next).toHaveBeenCalledWith(expectedNodeMenuEvent);
expect(nodeMenuService.nodeMenuEvents$.next).toHaveBeenCalledTimes(1);
});
it('should not close menu on event not considered to do so', () => {
fixture.detectChanges();
spyOn(nodeMenuService.nodeMenuEvents$, 'next');
const event: any = document.createEvent('Events');
event.initEvent('keyup', true, true);
document.dispatchEvent(event);
expect(nodeMenuService.nodeMenuEvents$.next).not.toHaveBeenCalled();
});
it('should destroy globally registered event listeners', () => {
fixture.detectChanges();
spyOn(nodeMenuService.nodeMenuEvents$, 'next');
componentInstance.ngOnDestroy();
const mouseEvent = document.createEvent("MouseEvents");
mouseEvent.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
const keyboardEvent: any = document.createEvent('Events');
keyboardEvent.keyCode = Keys.Escape;
keyboardEvent.initEvent('keyup', true, true);
document.dispatchEvent(keyboardEvent);
document.dispatchEvent(mouseEvent);
expect(nodeMenuService.nodeMenuEvents$.next).not.toHaveBeenCalled();
});
});