diff --git a/demo/src/app/components/+dropdown/demos/index.ts b/demo/src/app/components/+dropdown/demos/index.ts
index 9112424d97..be71ab2e25 100644
--- a/demo/src/app/components/+dropdown/demos/index.ts
+++ b/demo/src/app/components/+dropdown/demos/index.ts
@@ -17,6 +17,7 @@ import { DemoDropdownAutoCloseComponent } from './autoclose/autoclose';
import { DemoDropdownCustomHtmlComponent } from './custom-html/custom-html';
import { DemoAccessibilityComponent } from './accessibility/accessibility';
import { DemoDropdownByIsOpenPropComponent } from './trigger-by-isopen-property/trigger-by-isopen-property';
+import { DemoDropdownInsideClickComponent } from './inside-click/inside-click';
export const DEMO_COMPONENTS = [
DemoDropdownBasicComponent,
@@ -37,5 +38,6 @@ export const DEMO_COMPONENTS = [
DemoDropdownStateChangeEventComponent,
DemoDropdownAutoCloseComponent,
DemoDropdownCustomHtmlComponent,
- DemoAccessibilityComponent
+ DemoAccessibilityComponent,
+ DemoDropdownInsideClickComponent
];
diff --git a/demo/src/app/components/+dropdown/demos/inside-click/inside-click.html b/demo/src/app/components/+dropdown/demos/inside-click/inside-click.html
new file mode 100644
index 0000000000..f61699c3ce
--- /dev/null
+++ b/demo/src/app/components/+dropdown/demos/inside-click/inside-click.html
@@ -0,0 +1,13 @@
+
+
+ Button dropdown
+
+
+
diff --git a/demo/src/app/components/+dropdown/demos/inside-click/inside-click.ts b/demo/src/app/components/+dropdown/demos/inside-click/inside-click.ts
new file mode 100644
index 0000000000..e32e360fb6
--- /dev/null
+++ b/demo/src/app/components/+dropdown/demos/inside-click/inside-click.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'demo-dropdown-inside-click',
+ templateUrl: './inside-click.html'
+})
+export class DemoDropdownInsideClickComponent {}
diff --git a/demo/src/app/components/+dropdown/dropdown-section.list.ts b/demo/src/app/components/+dropdown/dropdown-section.list.ts
index 6768a42692..1f63222461 100644
--- a/demo/src/app/components/+dropdown/dropdown-section.list.ts
+++ b/demo/src/app/components/+dropdown/dropdown-section.list.ts
@@ -17,6 +17,7 @@ import { DemoDropdownStateChangeEventComponent } from './demos/state-change-even
import { DemoDropdownAutoCloseComponent } from './demos/autoclose/autoclose';
import { DemoDropdownCustomHtmlComponent } from './demos/custom-html/custom-html';
import { DemoAccessibilityComponent } from './demos/accessibility/accessibility';
+import { DemoDropdownInsideClickComponent } from './demos/inside-click/inside-click';
import { ContentSection } from '../../docs/models/content-section.model';
import { DemoTopSectionComponent } from '../../docs/demo-section-components/demo-top-section/index';
@@ -120,6 +121,15 @@ export const demoComponentContent: ContentSection[] = [
to right align the dropdown menu.`,
outlet: DemoDropdownAlignmentComponent
},
+ {
+ title: 'Inside click',
+ anchor: 'inside-click',
+ component: require('!!raw-loader?lang=typescript!./demos/inside-click/inside-click.ts'),
+ html: require('!!raw-loader?lang=markup!./demos/inside-click/inside-click.html'),
+ description: `By default, a dropdown menu closes on document click, even if you clicked on an element inside the dropdown.
+ Use [insideClick]="true"
to allow click inside the dropdown
`,
+ outlet: DemoDropdownInsideClickComponent
+ },
{
title: 'Nested dropdowns (experimental)',
anchor: 'nested-dropdowns',
diff --git a/src/dropdown/bs-dropdown-container.component.ts b/src/dropdown/bs-dropdown-container.component.ts
index 79be5cf0c4..f927decf0d 100644
--- a/src/dropdown/bs-dropdown-container.component.ts
+++ b/src/dropdown/bs-dropdown-container.component.ts
@@ -36,11 +36,11 @@ export class BsDropdownContainerComponent implements OnDestroy {
private _state: BsDropdownState,
private cd: ChangeDetectorRef,
private _renderer: Renderer2,
- _element: ElementRef
+ private _element: ElementRef
) {
this._subscription = _state.isOpenChange.subscribe((value: boolean) => {
this.isOpen = value;
- const dropdown = _element.nativeElement.querySelector('.dropdown-menu');
+ const dropdown = this._element.nativeElement.querySelector('.dropdown-menu');
if (dropdown && !isBs3()) {
this._renderer.addClass(dropdown, 'show');
if (dropdown.classList.contains('dropdown-menu-right')) {
@@ -61,6 +61,11 @@ export class BsDropdownContainerComponent implements OnDestroy {
});
}
+ /** @internal */
+ _contains(el: Element): boolean {
+ return this._element.nativeElement.contains(el);
+ }
+
ngOnDestroy(): void {
this._subscription.unsubscribe();
}
diff --git a/src/dropdown/bs-dropdown-toggle.directive.ts b/src/dropdown/bs-dropdown-toggle.directive.ts
index 3a16dfd626..7999e375ad 100644
--- a/src/dropdown/bs-dropdown-toggle.directive.ts
+++ b/src/dropdown/bs-dropdown-toggle.directive.ts
@@ -8,6 +8,7 @@ import {
import { Subscription } from 'rxjs';
import { BsDropdownState } from './bs-dropdown.state';
+import { BsDropdownDirective } from './bs-dropdown.directive';
@Directive({
selector: '[bsDropdownToggle],[dropdownToggle]',
@@ -24,7 +25,7 @@ export class BsDropdownToggleDirective implements OnDestroy {
private _subscriptions: Subscription[] = [];
- constructor(private _state: BsDropdownState, private _element: ElementRef) {
+ constructor(private _state: BsDropdownState, private _element: ElementRef, private dropdown: BsDropdownDirective) {
// sync is open value with state
this._subscriptions.push(
this._state.isOpenChange.subscribe(
@@ -52,7 +53,8 @@ export class BsDropdownToggleDirective implements OnDestroy {
if (
this._state.autoClose &&
event.button !== 2 &&
- !this._element.nativeElement.contains(event.target)
+ !this._element.nativeElement.contains(event.target) &&
+ !(this.dropdown.insideClick && this.dropdown._contains(event))
) {
this._state.toggleClick.emit(false);
}
diff --git a/src/dropdown/bs-dropdown.directive.ts b/src/dropdown/bs-dropdown.directive.ts
index a49c5b2698..e60c9716b8 100644
--- a/src/dropdown/bs-dropdown.directive.ts
+++ b/src/dropdown/bs-dropdown.directive.ts
@@ -65,6 +65,11 @@ export class BsDropdownDirective implements OnInit, OnDestroy {
return this._state.autoClose;
}
+ /**
+ * This attribute indicates that the dropdown shouldn't close on inside click when autoClose is set to true
+ */
+ @Input() insideClick: boolean;
+
/**
* Disables dropdown toggle and hides dropdown menu if opened
*/
@@ -120,17 +125,17 @@ export class BsDropdownDirective implements OnInit, OnDestroy {
return !isBs3();
}
- // todo: move to component loader
- private _isInlineOpen = false;
+ private _dropdown: ComponentLoader;
private get _showInline(): boolean {
return !this.container;
}
- private _inlinedMenu: EmbeddedViewRef;
+ // todo: move to component loader
+ private _isInlineOpen = false;
+ private _inlinedMenu: EmbeddedViewRef;
private _isDisabled: boolean;
- private _dropdown: ComponentLoader;
private _subscriptions: Subscription[] = [];
private _isInited = false;
@@ -280,6 +285,12 @@ export class BsDropdownDirective implements OnInit, OnDestroy {
return this.show();
}
+ /** @internal */
+ _contains(event: any): boolean {
+ return this._elementRef.nativeElement.contains(event.target) ||
+ (this._dropdown.instance && this._dropdown.instance._contains(event.target));
+ }
+
ngOnDestroy(): void {
// clean up subscriptions and destroy dropdown
for (const sub of this._subscriptions) {
diff --git a/src/spec/accordion.component.spec.ts b/src/spec/accordion.component.spec.ts
index 636f3c6155..2a60f2a48b 100644
--- a/src/spec/accordion.component.spec.ts
+++ b/src/spec/accordion.component.spec.ts
@@ -126,7 +126,7 @@ describe('Component: Accordion', () => {
it('should have the appropriate heading', () => {
const titles = Array.from(
- element.querySelectorAll('.panel-heading .accordion-toggle div')
+ element.querySelectorAll('.panel-heading .accordion-toggle button')
);
titles.forEach((title: HTMLElement, idx: number) => {
const expectedTitle = `Panel ${idx + 1}`;
diff --git a/src/spec/bs-dropdown-container.component.spec.ts b/src/spec/bs-dropdown-container.component.spec.ts
new file mode 100644
index 0000000000..a9a00b2f50
--- /dev/null
+++ b/src/spec/bs-dropdown-container.component.spec.ts
@@ -0,0 +1,45 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { BsDropdownContainerComponent, BsDropdownModule, BsDropdownState } from '../dropdown';
+import { Subject } from 'rxjs';
+import { window } from '../utils';
+
+describe('BsDropdownContainerComponent tests', () => {
+ let fixture: ComponentFixture;
+ let component: BsDropdownContainerComponent;
+ /* tslint:disable-next-line:no-inferred-empty-object-type */
+ const stateSubject = new Subject();
+ let fakeService;
+
+ beforeEach(() => {
+ fakeService = {
+ isOpenChange: stateSubject.asObservable()
+ };
+ TestBed.configureTestingModule({
+ imports: [BsDropdownModule.forRoot()],
+ providers: [{ provide: BsDropdownState, useValue: fakeService }]
+ });
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(BsDropdownContainerComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should not be null', () => {
+ expect(component).not.toBeNull();
+ });
+
+ it('should be call isOpenChange method', () => {
+ const tempVal = window.__theme;
+ window.__theme = 'bs4';
+ const spy = spyOn((component as any).cd, 'detectChanges');
+
+ stateSubject.next(true);
+ fixture.detectChanges();
+
+ expect(spy).toHaveBeenCalled();
+ window.__theme = tempVal;
+ });
+});
diff --git a/src/spec/bs-dropdown.directive.spec.ts b/src/spec/bs-dropdown.directive.spec.ts
index f46e58f284..fff59f65d5 100644
--- a/src/spec/bs-dropdown.directive.spec.ts
+++ b/src/spec/bs-dropdown.directive.spec.ts
@@ -1,8 +1,10 @@
/* tslint:disable:max-file-line-count */
-import { Component } from '@angular/core';
-import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { Component, DebugElement } from '@angular/core';
+import { async, fakeAsync, TestBed, tick, ComponentFixture } from '@angular/core/testing';
-import { BsDropdownConfig, BsDropdownModule } from '../dropdown';
+import { BsDropdownConfig, BsDropdownDirective, BsDropdownModule } from '../dropdown';
+import { window } from '../utils/facade/browser';
+import { By } from '@angular/platform-browser';
@Component({
selector: 'dropdown-test',
@@ -10,10 +12,12 @@ import { BsDropdownConfig, BsDropdownModule } from '../dropdown';
})
class TestDropdownComponent {
isOpen: Boolean = false;
+ dropup: Boolean = false;
isDisabled: Boolean = false;
- addToggleClass: Boolean = false;
- autoClose = false;
- keyboardNav: Boolean = false;
+ autoClose: Boolean = true;
+ isOpenChangeValue: Boolean = false;
+ insideClick: Boolean = false;
+ container: String = '';
constructor(config: BsDropdownConfig) {
Object.assign(this, config);
@@ -21,27 +25,28 @@ class TestDropdownComponent {
}
const defaultHtml = `
-
-`;
-
-const htmlWithBinding = `
-
-
Dropdown
+
+
Title outside dropdown
`;
describe('Directive: Dropdown', () => {
- it('should be closed by default', () => {
+ let fixture: ComponentFixture
;
+ let element: HTMLElement;
+ let context: TestDropdownComponent;
+ let directive: BsDropdownDirective;
+ beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TestDropdownComponent],
imports: [BsDropdownModule.forRoot()]
@@ -49,24 +54,31 @@ describe('Directive: Dropdown', () => {
TestBed.overrideComponent(TestDropdownComponent, {
set: {template: defaultHtml}
});
- const fixture = TestBed.createComponent(TestDropdownComponent);
+ }));
+ beforeEach(() => {
+ fixture = TestBed.createComponent(TestDropdownComponent);
+ element = fixture.nativeElement;
+ context = fixture.componentInstance;
+ // get the typeahead directive instance
+ const inputs = fixture.debugElement.queryAll(
+ By.directive(BsDropdownDirective)
+ );
+ directive = inputs.map(
+ (de: DebugElement) =>
+ de.injector.get(BsDropdownDirective)
+ )[0];
fixture.detectChanges();
- const element = fixture.nativeElement;
+ });
+
+ it('should be closed by default', () => {
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
});
+ it('autoClose value should be true by default', () => {
+ expect(directive.autoClose).toBeTruthy();
+ });
+
it('should be opened if isOpen === true and toggle on isOpen changes', () => {
- TestBed.configureTestingModule({
- declarations: [TestDropdownComponent],
- imports: [BsDropdownModule.forRoot()]
- });
- TestBed.overrideComponent(TestDropdownComponent, {
- set: {template: htmlWithBinding}
- });
- const 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');
@@ -79,16 +91,6 @@ describe('Directive: Dropdown', () => {
});
it('should toggle by click', () => {
- TestBed.configureTestingModule({
- declarations: [TestDropdownComponent],
- imports: [BsDropdownModule.forRoot()]
- });
- TestBed.overrideComponent(TestDropdownComponent, {
- set: {template: defaultHtml}
- });
- const fixture = TestBed.createComponent(TestDropdownComponent);
- fixture.detectChanges();
- const element = fixture.nativeElement;
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
element.querySelector('button').click();
fixture.detectChanges();
@@ -99,17 +101,6 @@ describe('Directive: Dropdown', () => {
});
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}
- });
- const 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();
@@ -119,275 +110,215 @@ describe('Directive: Dropdown', () => {
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}
- });
- const 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);
- tick();
- 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 any element inside the dropdown', fakeAsync(() => {
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ tick();
+ element.querySelector('li').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ tick();
+ element.querySelector('a').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ }));
+
+ it('should close by click on any element outside the dropdown', () => {
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ element.querySelector('h1').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ });
- it(
- 'should close by click on nonInput menu item',
- fakeAsync(() => {
- const html = `
-
- `;
- TestBed.configureTestingModule({
- declarations: [TestDropdownComponent],
- imports: [BsDropdownModule.forRoot()]
- });
- TestBed.overrideComponent(TestDropdownComponent, {
- set: {template: html}
- });
- const fixture = TestBed.createComponent(TestDropdownComponent);
- fixture.detectChanges();
- tick();
- const element = fixture.nativeElement;
- fixture.detectChanges();
- element.querySelector('button').click();
- fixture.detectChanges();
- tick();
- expect(element.querySelector('[dropdown]').classList).toContain('open');
- element.querySelector('li').click();
- fixture.detectChanges();
- expect(element.querySelector('[dropdown]').classList).not.toContain(
- 'open'
- );
- })
- );
+ it('should be opened if isOpen === true and toggle on isOpen changes', () => {
+ context.isOpen = true;
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ context.isOpen = false;
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ });
- xit(
- 'should not close by click on input or textarea menu item',
- fakeAsync(() => {
- const html = `
-
- `;
- TestBed.configureTestingModule({
- declarations: [TestDropdownComponent],
- imports: [BsDropdownModule.forRoot()]
- });
- TestBed.overrideComponent(TestDropdownComponent, {
- set: {template: html}
- });
- const 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');
- element.querySelector('input').click();
- fixture.detectChanges();
- expect(element.querySelector('[dropdown]').classList).toContain('open');
- element.querySelector('textarea').click();
- fixture.detectChanges();
- expect(element.querySelector('[dropdown]').classList).toContain('open');
- })
- );
+ it('should change and update isOpen when it is opened or closed', fakeAsync(() => {
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ expect(context.isOpen).toBe(true);
+ tick();
+ element.querySelector('li').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain(
+ 'open'
+ );
+ expect(context.isOpen).toBe(false);
+ }));
- it(
- 'should not close by click on menu item if autoClose === false',
- fakeAsync(() => {
- const html = `
-
- `;
- TestBed.configureTestingModule({
- declarations: [TestDropdownComponent],
- imports: [BsDropdownModule.forRoot()]
- });
- TestBed.overrideComponent(TestDropdownComponent, {
- set: {template: html}
- });
- const fixture = TestBed.createComponent(TestDropdownComponent);
- fixture.detectChanges();
- const element = fixture.nativeElement;
- const context = fixture.componentInstance;
- context.autoClose = false;
- tick();
- fixture.detectChanges();
- element.querySelector('button').click();
- fixture.detectChanges();
- expect(element.querySelector('[dropdown]').classList).toContain('open');
- tick();
- element.querySelector('li').click();
- fixture.detectChanges();
- expect(element.querySelector('[dropdown]').classList).toContain('open');
- })
- );
+ it('should has class dropup if property dropup equal true', () => {
+ context.dropup = true;
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('dropup');
+ });
- xit('should close by click on input in menu if autoClose === always', () => {
- const html = `
-
- `;
- TestBed.configureTestingModule({
- declarations: [TestDropdownComponent],
- imports: [BsDropdownModule.forRoot()]
- });
- TestBed.overrideComponent(TestDropdownComponent, {
- set: {template: html}
- });
- const fixture = TestBed.createComponent(TestDropdownComponent);
+ it('should not open if isDisabled equal true', () => {
+ context.isDisabled = true;
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ context.isDisabled = false;
fixture.detectChanges();
- const element = fixture.nativeElement;
- const context = fixture.componentInstance;
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ });
+
+ it('should close if only dropdown button was clicked if autoClose equal false', fakeAsync(() => {
+ context.autoClose = false;
+ fixture.detectChanges();
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ tick();
+ element.querySelector('a').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ element.querySelector('h1').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ }));
+
+ it('should not close by click on menu item if autoClose equal true', fakeAsync(() => {
context.autoClose = true;
fixture.detectChanges();
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]').classList).toContain('open');
- element.querySelector('input').click();
+ tick();
+ element.querySelector('li').click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ }));
+
+ it('value isOpenChange emits event', () => {
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ expect(context.isOpenChangeValue).toBeTruthy();
});
- xit('should close by click on any element outside the dropdown', () => {
- const html = `
-
- outside
- `;
- TestBed.configureTestingModule({
- declarations: [TestDropdownComponent],
- imports: [BsDropdownModule.forRoot()]
- });
- TestBed.overrideComponent(TestDropdownComponent, {
- set: {template: html}
- });
- const fixture = TestBed.createComponent(TestDropdownComponent);
+ it('should close if only dropdown button was clicked if autoClose equal false', fakeAsync(() => {
+ context.autoClose = false;
fixture.detectChanges();
- const element = fixture.nativeElement;
- const context = fixture.componentInstance;
- context.autoClose = true;
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ tick();
+ element.querySelector('a').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ element.querySelector('h1').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ }));
+
+ it('should not close by click on menu item if insideClick equal true', fakeAsync(() => {
+ context.insideClick = true;
fixture.detectChanges();
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]').classList).toContain('open');
+ tick();
+ element.querySelector('a').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
element.querySelector('li').click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]').classList).toContain('open');
- element.querySelector('span').click();
+ element.querySelector('h1').click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
- });
+ }));
- xit(
- 'should enable navigation of dropdown list elements with the arrow keys if keyboardNav is true',
- () => {
- const html = `
-
- `;
- TestBed.configureTestingModule({
- declarations: [TestDropdownComponent],
- imports: [BsDropdownModule.forRoot()]
- });
- TestBed.overrideComponent(TestDropdownComponent, {
- set: {template: html}
- });
- const fixture = TestBed.createComponent(TestDropdownComponent);
- fixture.detectChanges();
- const element = fixture.nativeElement;
- const context = fixture.componentInstance;
- context.keyboardNav = true;
- fixture.detectChanges();
- element.querySelector('button').click();
- fixture.detectChanges();
- expect(element.querySelector('[dropdown]').classList).toContain('open');
- // todo: emulate keypress, check if item has hover
- }
- );
-});
-describe('Directive: dropdownToggle', () => {
- it('should not open if toggle isDisabled', () => {
- const html = `
-
- `;
- TestBed.configureTestingModule({
- declarations: [TestDropdownComponent],
- imports: [BsDropdownModule.forRoot()]
- });
- TestBed.overrideComponent(TestDropdownComponent, {
- set: {template: html}
- });
- const fixture = TestBed.createComponent(TestDropdownComponent);
+ it('should close by click on menu item if insideClick equal false', fakeAsync(() => {
+ context.insideClick = false;
fixture.detectChanges();
- const element = fixture.nativeElement;
- const context = fixture.componentInstance;
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ tick();
+ element.querySelector('li').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ }));
+
+ it('should close by click on menu item if insideClick equal false', fakeAsync(() => {
+ context.insideClick = false;
+ fixture.detectChanges();
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ tick();
+ element.querySelector('li').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ }));
+
+ it('should change aria-expanded property, when dropdown was opened', fakeAsync(() => {
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ expect(element.querySelector('[dropdownToggle]').getAttribute('aria-expanded')).toEqual('true');
+ tick();
+ element.querySelector('li').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdownToggle]').getAttribute('aria-expanded')).toEqual('false');
+ }));
+
+ it('should change disabled property, when dropdown was opened', fakeAsync(() => {
context.isDisabled = true;
fixture.detectChanges();
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]').classList).not.toContain('open');
- context.isDisabled = false;
+ expect(element.querySelector('[dropdownToggle]').getAttribute('disabled')).toEqual('true');
+ }));
+
+ it('should open if container is body', () => {
+ context.container = 'body';
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ element.querySelector('button').click();
fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).toContain('open');
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ });
+
+ it('should open if isBs3 method return true', () => {
+ const tempVal = window.__theme;
+ window.__theme = 'bs4';
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
element.querySelector('button').click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]').classList).toContain('open');
+ element.querySelector('button').click();
+ fixture.detectChanges();
+ expect(element.querySelector('[dropdown]').classList).not.toContain('open');
+ window.__theme = tempVal;
});
});