Skip to content

Commit

Permalink
fix(dropdown): fix duplicated events, add spec
Browse files Browse the repository at this point in the history
  • Loading branch information
IlyaSurmay authored and valorkin committed Jun 1, 2017
1 parent 7ef989a commit da92081
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 106 deletions.
7 changes: 3 additions & 4 deletions src/dropdown/bs-dropdown.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,10 @@ export class BsDropdownDirective implements OnInit, OnDestroy {

if (this._showInline) {
this._isInlineOpen = true;
this._state.isOpenChange.emit(true);
this.onShown.emit(true);
this._state.isOpenChange.emit(true);
return;
}

this._state.dropdownMenu
.then((dropdownMenu) => {
// check direction in which dropdown should be opened
Expand All @@ -206,8 +205,8 @@ export class BsDropdownDirective implements OnInit, OnDestroy {
});

this._state.isOpenChange.emit(true);
this.onShown.emit(true);
});

}

/**
Expand All @@ -221,12 +220,12 @@ export class BsDropdownDirective implements OnInit, OnDestroy {

if (this._showInline) {
this._isInlineOpen = false;
this.onHidden.emit(true);
} else {
this._dropdown.hide();
}

this._state.isOpenChange.emit(false);
this.onHidden.emit(true);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Component } from '@angular/core';
import { fakeAsync, TestBed, tick } from '@angular/core/testing';

import { BsDropdownConfig, BsDropdownModule } from './';
import { BsDropdownConfig, BsDropdownModule } from '../dropdown/index';

const defaultHtml = `
<div dropdown>
Expand All @@ -14,6 +14,16 @@ const defaultHtml = `
</div>
`;

const htmlWithBinding = `
<div dropdown [(isOpen)]="isOpen">
<button dropdownToggle>Dropdown</button>
<ul *dropdownMenu>
<li><a href="#">One</a></li>
<li><a href="#">Two</a></li>
</ul>
</div>
`;

describe('Directive: Dropdown', () => {

it('should be closed by default', () => {
Expand All @@ -25,37 +35,28 @@ describe('Directive: Dropdown', () => {
let fixture = TestBed.createComponent(TestDropdownComponent);
fixture.detectChanges();
const element = fixture.nativeElement;
expect(element.querySelector('.dropdown').classList).not.toContain('open');
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
});

it('should be opened if isOpen === true and toggle on isOpen changes', () => {
const html = `
<div dropdown [(isOpen)]="isOpen">
<button dropdownToggle>Dropdown</button>
<ul *dropdownMenu>
<li><a href="#">One</a></li>
<li><a href="#">Two</a></li>
</ul>
</div>
`;
TestBed.configureTestingModule({
declarations: [TestDropdownComponent],
imports: [BsDropdownModule.forRoot()]
});
TestBed.overrideComponent(TestDropdownComponent, {set: {template: html}});
TestBed.overrideComponent(TestDropdownComponent, {set: {template: htmlWithBinding}});
let fixture = TestBed.createComponent(TestDropdownComponent);
fixture.detectChanges();
const element = fixture.nativeElement;
const context = fixture.componentInstance;
context.isOpen = true;
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
expect(element.querySelector('[dropdown]').classList).toContain('open');
context.isOpen = false;
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).not.toContain('open');
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
context.isOpen = true;
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
expect(element.querySelector('[dropdown]').classList).toContain('open');
});

it('should toggle by click', () => {
Expand All @@ -67,15 +68,56 @@ describe('Directive: Dropdown', () => {
let fixture = TestBed.createComponent(TestDropdownComponent);
fixture.detectChanges();
const element = fixture.nativeElement;
expect(element.querySelector('.dropdown').classList).not.toContain('open');
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
expect(element.querySelector('[dropdown]').classList).toContain('open');
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).not.toContain('open');
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
});

it('should be closed if was opened by click and then isOpen === false was set', () => {
TestBed.configureTestingModule({
declarations: [TestDropdownComponent],
imports: [BsDropdownModule.forRoot()]
});
TestBed.overrideComponent(TestDropdownComponent, {set: {template: htmlWithBinding}});
let fixture = TestBed.createComponent(TestDropdownComponent);
fixture.detectChanges();
const element = fixture.nativeElement;
const context = fixture.componentInstance;
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]').classList).toContain('open');
context.isOpen = false;
fixture.detectChanges();
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
});

it('should change and update isOpen when it is opened or closed', fakeAsync(() => {
TestBed.configureTestingModule({
declarations: [TestDropdownComponent],
imports: [BsDropdownModule.forRoot()]
});
TestBed.overrideComponent(TestDropdownComponent, {set: {template: htmlWithBinding}});
let fixture = TestBed.createComponent(TestDropdownComponent);
fixture.detectChanges();
tick();
const element = fixture.nativeElement;
const context = fixture.componentInstance;
fixture.detectChanges();
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]').classList).toContain('open');
expect(context.isOpen).toBe(true);
element.querySelector('li').click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
expect(context.isOpen).toBe(false);
}));

it('should close by click on nonInput menu item', fakeAsync(() => {
const html = `
<div dropdown>
Expand All @@ -93,18 +135,18 @@ describe('Directive: Dropdown', () => {
TestBed.overrideComponent(TestDropdownComponent, {set: {template: html}});
let fixture = TestBed.createComponent(TestDropdownComponent);
fixture.detectChanges();
tick();
const element = fixture.nativeElement;
fixture.detectChanges();
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
expect(element.querySelector('[dropdown]').classList).toContain('open');
element.querySelector('li').click();
tick();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).not.toContain('open');
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
}));

it('should not close by click on input or textarea menu item', () => {
xit('should not close by click on input or textarea menu item', fakeAsync(() => {
const html = `
<div dropdown>
<button dropdownToggle>Dropdown</button>
Expand All @@ -122,20 +164,21 @@ describe('Directive: Dropdown', () => {
TestBed.overrideComponent(TestDropdownComponent, {set: {template: html}});
let fixture = TestBed.createComponent(TestDropdownComponent);
fixture.detectChanges();
tick();
const element = fixture.nativeElement;
fixture.detectChanges();
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
expect(element.querySelector('[dropdown]').classList).toContain('open');
element.querySelector('input').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
expect(element.querySelector('[dropdown]').classList).toContain('open');
element.querySelector('textarea').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
});
expect(element.querySelector('[dropdown]').classList).toContain('open');
}));

it('should not close by click on menu item if autoClose === disabled', () => {
it('should not close by click on menu item if autoClose === false', fakeAsync(() => {
const html = `
<div dropdown [autoClose]="autoClose">
<button dropdownToggle>Dropdown</button>
Expand All @@ -154,15 +197,16 @@ describe('Directive: Dropdown', () => {
fixture.detectChanges();
const element = fixture.nativeElement;
const context = fixture.componentInstance;
context.autoClose = 'disabled';
context.autoClose = false;
tick();
fixture.detectChanges();
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
expect(element.querySelector('[dropdown]').classList).toContain('open');
element.querySelector('li').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
});
expect(element.querySelector('[dropdown]').classList).toContain('open');
}));

xit('should close by click on input in menu if autoClose === always', () => {
const html = `
Expand All @@ -183,14 +227,14 @@ describe('Directive: Dropdown', () => {
fixture.detectChanges();
const element = fixture.nativeElement;
const context = fixture.componentInstance;
context.autoClose = 'always';
context.autoClose = true;
fixture.detectChanges();
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
expect(element.querySelector('[dropdown]').classList).toContain('open');
element.querySelector('input').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).not.toContain('open');
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
});

xit('should close by click on any element outside the dropdown', () => {
Expand All @@ -213,17 +257,17 @@ describe('Directive: Dropdown', () => {
fixture.detectChanges();
const element = fixture.nativeElement;
const context = fixture.componentInstance;
context.autoClose = 'outsideClick';
context.autoClose = true;
fixture.detectChanges();
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
expect(element.querySelector('[dropdown]').classList).toContain('open');
element.querySelector('li').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
expect(element.querySelector('[dropdown]').classList).toContain('open');
element.querySelector('span').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).not.toContain('open');
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
});

xit('should enable navigation of dropdown list elements with the arrow keys if keyboardNav is true', () => {
Expand All @@ -249,15 +293,15 @@ describe('Directive: Dropdown', () => {
fixture.detectChanges();
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
expect(element.querySelector('[dropdown]').classList).toContain('open');
// todo: emulate keypress, check if item has hover
});

describe('Directive: dropdownToggle', () => {
});
describe('Directive: dropdownToggle', () => {
it('should not open if toggle isDisabled', () => {
const html = `
<div dropdown>
<button dropdownToggle [isDisabled]="isDisabled">Dropdown</button>
<div dropdown [isDisabled]="isDisabled">
<button dropdownToggle>Dropdown</button>
<ul *dropdownMenu>
<li><a href="#">One</a></li>
<li><a href="#">Two</a></li>
Expand All @@ -275,74 +319,31 @@ describe('Directive: Dropdown', () => {
const context = fixture.componentInstance;
context.isDisabled = true;
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).not.toContain('open');
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).not.toContain('open');
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
context.isDisabled = false;
fixture.detectChanges();
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('.dropdown').classList).toContain('open');
});

it('should have dropdown-toggle class by default', () => {
const html = `
<div dropdown>
<button dropdownToggle>Dropdown</button>
<ul *dropdownMenu>
<li><a href="#">One</a></li>
<li><a href="#">Two</a></li>
</ul>
</div>
`;
TestBed.configureTestingModule({
declarations: [TestDropdownComponent],
imports: [BsDropdownModule.forRoot()]
});
TestBed.overrideComponent(TestDropdownComponent, {set: {template: html}});
let fixture = TestBed.createComponent(TestDropdownComponent);
fixture.detectChanges();
const element = fixture.nativeElement;
expect(element.querySelector('button').classList).toContain('dropdown-toggle');
});

it('should not add dropdown-toggle class if addToggleClass is false', () => {
const html = `
<div dropdown>
<button dropdownToggle [addToggleClass]="addToggleClass">Dropdown</button>
<ul *dropdownMenu>
<li><a href="#">One</a></li>
<li><a href="#">Two</a></li>
</ul>
</div>
`;
TestBed.configureTestingModule({
declarations: [TestDropdownComponent],
imports: [BsDropdownModule.forRoot()]
});
TestBed.overrideComponent(TestDropdownComponent, {set: {template: html}});
let fixture = TestBed.createComponent(TestDropdownComponent);
fixture.detectChanges();
const element = fixture.nativeElement;
expect(element.querySelector('button').classList).not.toContain('dropdown-toggle');
expect(element.querySelector('[dropdown]').classList).toContain('open');
});
});
});

@Component({
selector: 'dropdown-test',
template: ''
})
@Component({
selector: 'dropdown-test',
template: ''
})

class TestDropdownComponent {
public isOpen: Boolean = false;
public isDisabled: Boolean = false;
public addToggleClass: Boolean = false;
public autoClose: string = 'nonInput';
public keyboardNav: Boolean = false;
class TestDropdownComponent {
public isOpen: Boolean = false;
public isDisabled: Boolean = false;
public addToggleClass: Boolean = false;
public autoClose: boolean = false;
public keyboardNav: Boolean = false;

public constructor(config: BsDropdownConfig) {
Object.assign(this, config);
public constructor(config: BsDropdownConfig) {
Object.assign(this, config);
}
}
}

0 comments on commit da92081

Please sign in to comment.