import Popper from 'popper.js'
import Dropdown from '../../src/dropdown'
import EventHandler from '../../src/dom/event-handler'
/** Test helpers */
import { getFixture, clearFixture, createEvent, jQueryMock } from '../helpers/fixture'
describe('Dropdown', () => {
let fixtureEl
beforeAll(() => {
fixtureEl = getFixture()
})
afterEach(() => {
clearFixture()
})
describe('VERSION', () => {
it('should return plugin version', () => {
expect(Dropdown.VERSION).toEqual(jasmine.any(String))
})
})
describe('Default', () => {
it('should return plugin default config', () => {
expect(Dropdown.Default).toEqual(jasmine.any(Object))
})
})
describe('DefaultType', () => {
it('should return plugin default type config', () => {
expect(Dropdown.DefaultType).toEqual(jasmine.any(Object))
})
})
describe('constructor', () => {
it('should create offset modifier correctly when offset option is a function', () => {
fixtureEl.innerHTML = [
'
',
' ',
' ',
'
'
].join('')
const getOffset = offsets => offsets
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdown = new Dropdown(btnDropdown, {
offset: getOffset
})
const offset = dropdown._getOffset()
expect(offset.offset).toBeUndefined()
expect(typeof offset.fn).toEqual('function')
})
it('should create offset modifier correctly when offset option is not a function', () => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const myOffset = 7
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdown = new Dropdown(btnDropdown, {
offset: myOffset
})
const offset = dropdown._getOffset()
expect(offset.offset).toEqual(myOffset)
expect(offset.fn).toBeUndefined()
})
it('should add a listener on trigger which do not have data-toggle="dropdown"', () => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('.btn')
const dropdown = new Dropdown(btnDropdown)
spyOn(dropdown, 'toggle')
btnDropdown.click()
expect(dropdown.toggle).toHaveBeenCalled()
})
it('should allow to pass config to popper.js with `popperConfig`', () => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdown = new Dropdown(btnDropdown, {
popperConfig: {
placement: 'left'
}
})
const popperConfig = dropdown._getPopperConfig()
expect(popperConfig.placement).toEqual('left')
})
})
describe('toggle', () => {
it('should toggle a dropdown', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
done()
})
dropdown.toggle()
})
it('should destroy old popper references on toggle', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
',
'',
' ',
' ',
'
'
].join('')
const btnDropdown1 = fixtureEl.querySelector('.firstBtn')
const btnDropdown2 = fixtureEl.querySelector('.secondBtn')
const firstDropdownEl = fixtureEl.querySelector('.first')
const secondDropdownEl = fixtureEl.querySelector('.second')
const dropdown1 = new Dropdown(btnDropdown1)
const dropdown2 = new Dropdown(btnDropdown2)
firstDropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown1.classList.contains('show')).toEqual(true)
spyOn(dropdown1._popper, 'destroy')
dropdown2.toggle()
})
secondDropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(dropdown1._popper.destroy).toHaveBeenCalled()
done()
})
dropdown1.toggle()
})
it('should toggle a dropdown and add/remove event listener on mobile', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const defaultValueOnTouchStart = document.documentElement.ontouchstart
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
document.documentElement.ontouchstart = () => {}
spyOn(EventHandler, 'on')
spyOn(EventHandler, 'off')
dropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
expect(EventHandler.on).toHaveBeenCalled()
dropdown.toggle()
})
dropdownEl.addEventListener('hidden.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(false)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('false')
expect(EventHandler.off).toHaveBeenCalled()
document.documentElement.ontouchstart = defaultValueOnTouchStart
done()
})
dropdown.toggle()
})
it('should toggle a dropdown at the right', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
done()
})
dropdown.toggle()
})
it('should toggle a dropup', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropupEl = fixtureEl.querySelector('.dropup')
const dropdown = new Dropdown(btnDropdown)
dropupEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
done()
})
dropdown.toggle()
})
it('should toggle a dropup at the right', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropupEl = fixtureEl.querySelector('.dropup')
const dropdown = new Dropdown(btnDropdown)
dropupEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
done()
})
dropdown.toggle()
})
it('should toggle a dropright', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const droprightEl = fixtureEl.querySelector('.dropright')
const dropdown = new Dropdown(btnDropdown)
droprightEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
done()
})
dropdown.toggle()
})
it('should toggle a dropleft', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropleftEl = fixtureEl.querySelector('.dropleft')
const dropdown = new Dropdown(btnDropdown)
dropleftEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
done()
})
dropdown.toggle()
})
it('should toggle a dropdown with parent reference', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown, {
reference: 'parent'
})
dropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
done()
})
dropdown.toggle()
})
it('should toggle a dropdown with a dom node reference', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown, {
reference: fixtureEl
})
dropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
done()
})
dropdown.toggle()
})
it('should toggle a dropdown with a jquery object reference', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown, {
reference: { 0: fixtureEl, jquery: 'jQuery' }
})
dropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
done()
})
dropdown.toggle()
})
it('should not toggle a dropdown if the element is disabled', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('shown.bs.dropdown', () => {
throw new Error('should not throw shown.bs.dropdown event')
})
dropdown.toggle()
setTimeout(() => {
expect().nothing()
done()
})
})
it('should not toggle a dropdown if the element contains .disabled', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('shown.bs.dropdown', () => {
throw new Error('should not throw shown.bs.dropdown event')
})
dropdown.toggle()
setTimeout(() => {
expect().nothing()
done()
})
})
it('should not toggle a dropdown if the menu is shown', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('shown.bs.dropdown', () => {
throw new Error('should not throw shown.bs.dropdown event')
})
dropdown.toggle()
setTimeout(() => {
expect().nothing()
done()
})
})
it('should not toggle a dropdown if show event is prevented', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('show.bs.dropdown', e => {
e.preventDefault()
})
dropdownEl.addEventListener('shown.bs.dropdown', () => {
throw new Error('should not throw shown.bs.dropdown event')
})
dropdown.toggle()
setTimeout(() => {
expect().nothing()
done()
})
})
})
describe('show', () => {
it('should show a dropdown', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
done()
})
dropdown.show()
})
it('should not show a dropdown if the element is disabled', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('shown.bs.dropdown', () => {
throw new Error('should not throw shown.bs.dropdown event')
})
dropdown.show()
setTimeout(() => {
expect().nothing()
done()
}, 10)
})
it('should not show a dropdown if the element contains .disabled', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('shown.bs.dropdown', () => {
throw new Error('should not throw shown.bs.dropdown event')
})
dropdown.show()
setTimeout(() => {
expect().nothing()
done()
}, 10)
})
it('should not show a dropdown if the menu is shown', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('shown.bs.dropdown', () => {
throw new Error('should not throw shown.bs.dropdown event')
})
dropdown.show()
setTimeout(() => {
expect().nothing()
done()
}, 10)
})
it('should not show a dropdown if show event is prevented', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('show.bs.dropdown', e => {
e.preventDefault()
})
dropdownEl.addEventListener('shown.bs.dropdown', () => {
throw new Error('should not throw shown.bs.dropdown event')
})
dropdown.show()
setTimeout(() => {
expect().nothing()
done()
}, 10)
})
})
describe('hide', () => {
it('should hide a dropdown', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdownMenu = fixtureEl.querySelector('.dropdown-menu')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('hidden.bs.dropdown', () => {
expect(dropdownMenu.classList.contains('show')).toEqual(false)
done()
})
dropdown.hide()
})
it('should hide a dropdown and destroy popper', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('shown.bs.dropdown', () => {
spyOn(dropdown._popper, 'destroy')
dropdown.hide()
})
dropdownEl.addEventListener('hidden.bs.dropdown', () => {
expect(dropdown._popper.destroy).toHaveBeenCalled()
done()
})
dropdown.show()
})
it('should not hide a dropdown if the element is disabled', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdownMenu = fixtureEl.querySelector('.dropdown-menu')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('hidden.bs.dropdown', () => {
throw new Error('should not throw hidden.bs.dropdown event')
})
dropdown.hide()
setTimeout(() => {
expect(dropdownMenu.classList.contains('show')).toEqual(true)
done()
}, 10)
})
it('should not hide a dropdown if the element contains .disabled', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdownMenu = fixtureEl.querySelector('.dropdown-menu')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('hidden.bs.dropdown', () => {
throw new Error('should not throw hidden.bs.dropdown event')
})
dropdown.hide()
setTimeout(() => {
expect(dropdownMenu.classList.contains('show')).toEqual(true)
done()
}, 10)
})
it('should not hide a dropdown if the menu is not shown', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('hidden.bs.dropdown', () => {
throw new Error('should not throw hidden.bs.dropdown event')
})
dropdown.hide()
setTimeout(() => {
expect().nothing()
done()
}, 10)
})
it('should not hide a dropdown if hide event is prevented', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdownMenu = fixtureEl.querySelector('.dropdown-menu')
const dropdown = new Dropdown(btnDropdown)
dropdownEl.addEventListener('hide.bs.dropdown', e => {
e.preventDefault()
})
dropdownEl.addEventListener('hidden.bs.dropdown', () => {
throw new Error('should not throw hidden.bs.dropdown event')
})
dropdown.hide()
setTimeout(() => {
expect(dropdownMenu.classList.contains('show')).toEqual(true)
done()
})
})
})
describe('dispose', () => {
it('should dispose dropdown', () => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdown = new Dropdown(btnDropdown)
expect(dropdown._popper).toBeNull()
expect(dropdown._menu).toBeDefined()
expect(dropdown._element).toBeDefined()
dropdown.dispose()
expect(dropdown._menu).toBeNull()
expect(dropdown._element).toBeNull()
})
it('should dispose dropdown with popper.js', () => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdown = new Dropdown(btnDropdown)
dropdown.toggle()
expect(dropdown._popper).toBeDefined()
expect(dropdown._menu).toBeDefined()
expect(dropdown._element).toBeDefined()
spyOn(Popper.prototype, 'destroy')
dropdown.dispose()
expect(dropdown._popper).toBeNull()
expect(dropdown._menu).toBeNull()
expect(dropdown._element).toBeNull()
expect(Popper.prototype.destroy).toHaveBeenCalled()
})
})
describe('update', () => {
it('should call popper.js and detect navbar on update', () => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdown = new Dropdown(btnDropdown)
dropdown.toggle()
expect(dropdown._popper).toBeDefined()
spyOn(dropdown._popper, 'scheduleUpdate')
spyOn(dropdown, '_detectNavbar')
dropdown.update()
expect(dropdown._popper.scheduleUpdate).toHaveBeenCalled()
expect(dropdown._detectNavbar).toHaveBeenCalled()
})
it('should just detect navbar on update', () => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdown = new Dropdown(btnDropdown)
spyOn(dropdown, '_detectNavbar')
dropdown.update()
expect(dropdown._popper).toBeNull()
expect(dropdown._detectNavbar).toHaveBeenCalled()
})
})
describe('data-api', () => {
it('should not add class position-static to dropdown if boundary not set', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
dropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(dropdownEl.classList.contains('position-static')).toEqual(false)
done()
})
btnDropdown.click()
})
it('should add class position-static to dropdown if boundary not scrollParent', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
dropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(dropdownEl.classList.contains('position-static')).toEqual(true)
done()
})
btnDropdown.click()
})
it('should show and hide a dropdown', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
let showEventTriggered = false
let hideEventTriggered = false
dropdownEl.addEventListener('show.bs.dropdown', () => {
showEventTriggered = true
})
dropdownEl.addEventListener('shown.bs.dropdown', e => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
expect(showEventTriggered).toEqual(true)
expect(e.relatedTarget).toEqual(btnDropdown)
document.body.click()
})
dropdownEl.addEventListener('hide.bs.dropdown', () => {
hideEventTriggered = true
})
dropdownEl.addEventListener('hidden.bs.dropdown', e => {
expect(btnDropdown.classList.contains('show')).toEqual(false)
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('false')
expect(hideEventTriggered).toEqual(true)
expect(e.relatedTarget).toEqual(btnDropdown)
done()
})
btnDropdown.click()
})
it('should not use popper.js in navbar', done => {
fixtureEl.innerHTML = [
''
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdownMenu = fixtureEl.querySelector('.dropdown-menu')
dropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(dropdownMenu.getAttribute('style')).toEqual(null, 'no inline style applied by popper.js')
done()
})
btnDropdown.click()
})
it('should not use popper.js if display set to static', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
const dropdownMenu = fixtureEl.querySelector('.dropdown-menu')
dropdownEl.addEventListener('shown.bs.dropdown', () => {
// popper.js add this attribute when we use it
expect(dropdownMenu.getAttribute('x-placement')).toEqual(null)
done()
})
btnDropdown.click()
})
it('should remove "show" class if tabbing outside of menu', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdownEl = fixtureEl.querySelector('.dropdown')
dropdownEl.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(true)
const keyup = createEvent('keyup')
keyup.key = 'Tab'
document.dispatchEvent(keyup)
})
dropdownEl.addEventListener('hidden.bs.dropdown', () => {
expect(btnDropdown.classList.contains('show')).toEqual(false)
done()
})
btnDropdown.click()
})
it('should remove "show" class if body is clicked, with multiple dropdowns', done => {
fixtureEl.innerHTML = [
'',
' ',
'
',
'',
' ',
' ',
' ',
'
'
].join('')
const triggerDropdownList = fixtureEl.querySelectorAll('[data-toggle="dropdown"]')
expect(triggerDropdownList.length).toEqual(2)
const first = triggerDropdownList[0]
const last = triggerDropdownList[1]
const dropdownTestMenu = first.parentNode
const btnGroup = last.parentNode
dropdownTestMenu.addEventListener('shown.bs.dropdown', () => {
expect(first.classList.contains('show')).toEqual(true)
expect(fixtureEl.querySelectorAll('.dropdown-menu.show').length).toEqual(1)
document.body.click()
})
dropdownTestMenu.addEventListener('hidden.bs.dropdown', () => {
expect(fixtureEl.querySelectorAll('.dropdown-menu.show').length).toEqual(0)
last.click()
})
btnGroup.addEventListener('shown.bs.dropdown', () => {
expect(last.classList.contains('show')).toEqual(true)
expect(fixtureEl.querySelectorAll('.dropdown-menu.show').length).toEqual(1)
document.body.click()
})
btnGroup.addEventListener('hidden.bs.dropdown', () => {
expect(fixtureEl.querySelectorAll('.dropdown-menu.show').length).toEqual(0)
done()
})
first.click()
})
it('should remove "show" class if body if tabbing outside of menu, with multiple dropdowns', done => {
fixtureEl.innerHTML = [
'',
'',
' ',
' ',
' ',
'
'
].join('')
const triggerDropdownList = fixtureEl.querySelectorAll('[data-toggle="dropdown"]')
expect(triggerDropdownList.length).toEqual(2)
const first = triggerDropdownList[0]
const last = triggerDropdownList[1]
const dropdownTestMenu = first.parentNode
const btnGroup = last.parentNode
dropdownTestMenu.addEventListener('shown.bs.dropdown', () => {
expect(first.classList.contains('show')).toEqual(true, '"show" class added on click')
expect(fixtureEl.querySelectorAll('.dropdown-menu.show').length).toEqual(1, 'only one dropdown is shown')
const keyup = createEvent('keyup')
keyup.key = 'Tab'
document.dispatchEvent(keyup)
})
dropdownTestMenu.addEventListener('hidden.bs.dropdown', () => {
expect(fixtureEl.querySelectorAll('.dropdown-menu.show').length).toEqual(0, '"show" class removed')
last.click()
})
btnGroup.addEventListener('shown.bs.dropdown', () => {
expect(last.classList.contains('show')).toEqual(true, '"show" class added on click')
expect(fixtureEl.querySelectorAll('.dropdown-menu.show').length).toEqual(1, 'only one dropdown is shown')
const keyup = createEvent('keyup')
keyup.key = 'Tab'
document.dispatchEvent(keyup)
})
btnGroup.addEventListener('hidden.bs.dropdown', () => {
expect(fixtureEl.querySelectorAll('.dropdown-menu.show').length).toEqual(0, '"show" class removed')
done()
})
first.click()
})
it('should fire hide and hidden event without a clickEvent if event type is not click', done => {
fixtureEl.innerHTML = [
'',
' ',
' ',
'
'
].join('')
const triggerDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
const dropdown = fixtureEl.querySelector('.dropdown')
dropdown.addEventListener('hide.bs.dropdown', e => {
expect(e.clickEvent).toBeUndefined()
})
dropdown.addEventListener('hidden.bs.dropdown', e => {
expect(e.clickEvent).toBeUndefined()
done()
})
dropdown.addEventListener('shown.bs.dropdown', () => {
const keydown = createEvent('keydown')
keydown.key = 'Escape'
triggerDropdown.dispatchEvent(keydown)
})
triggerDropdown.click()
})
it('should ignore keyboard events within s and