import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { BsDropdownConfig, BsDropdownDirective, BsDropdownModule } from '../index';
@Component({
selector: 'dropdown-test',
template: ''
})
class TestDropdownComponent {
isOpen = false;
dropup = false;
isDisabled = false;
autoClose = true;
isOpenChangeValue = false;
insideClick = false;
container = '';
placement = '';
constructor(config: BsDropdownConfig) {
Object.assign(this, config);
}
}
const defaultHtml = `
Title outside dropdown
`;
describe('Directive: Dropdown', () => {
let fixture: ComponentFixture;
let element: HTMLElement;
let context: TestDropdownComponent;
let directive: BsDropdownDirective;
beforeEach((() => {
TestBed.configureTestingModule({
declarations: [TestDropdownComponent],
imports: [
BsDropdownModule.forRoot(),
BrowserAnimationsModule
]
});
TestBed.overrideComponent(TestDropdownComponent, {
set: {template: defaultHtml}
});
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();
}));
afterAll(async () => {
await new Promise(resolve => setTimeout(() => resolve(), 500)); // avoid jest open handle error
});
it('should be closed by default', () => {
const dropdown = element.querySelector('[dropdown]');
expect(dropdown?.classList).not.toContain('open');
});
it('autoClose value should be true by default', () => {
expect(directive.autoClose).toBeTruthy();
});
it('insideClick value should be true by default', () => {
expect(directive.insideClick).toBeFalsy();
});
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');
context.isOpen = true;
fixture.detectChanges();
expect(element.querySelector('[dropdown]')?.classList).toContain('open');
});
it('should toggle by click', () => {
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 be closed if was opened by click and then isOpen === false was set', () => {
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 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');
tick();
element.querySelector('button')?.click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]')?.classList).toContain('open');
tick();
element.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 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');
});
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 has class dropup if property dropup equal true', () => {
context.dropup = true;
fixture.detectChanges();
expect(element.querySelector('[dropdown]')?.classList).toContain('dropup');
});
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();
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.click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]')?.classList).toContain('open');
tick();
element.querySelector('h1')?.click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]')?.classList).toContain('open');
tick();
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');
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();
});
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.click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]')?.classList).toContain('open');
tick();
element.querySelector('h1')?.click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]')?.classList).toContain('open');
tick();
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('li')?.click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]')?.classList).toContain('open');
tick();
element.querySelector('ul')?.click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]')?.classList).toContain('open');
tick();
element.querySelector('h1')?.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 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');
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', fakeAsync(() => {
context.placement = 'bottom';
const tempVal = (window as never)['__theme'];
// eslint-disable-next-line
(window as any)['__theme'] = 'bs4';
fixture.detectChanges();
element.querySelector('button')?.click();
fixture.detectChanges();
expect(element.querySelector('[dropdown]')?.classList).toContain('open');
expect(element.querySelector('[dropdownToggle]')?.getAttribute('aria-expanded')).toEqual('true');
tick();
expect(element.querySelector('[dropdown]')?.classList).toContain('open');
// eslint-disable-next-line
(window as any)['__theme'] = tempVal;
}));
});