UNPKG

uiv

Version:

Bootstrap 3 components implemented by Vue.

336 lines (315 loc) 13.1 kB
import { createWrapper, nextTick, triggerEvent, windowClick, } from '../../__test__/utils'; import Dropdown from './Dropdown'; function appendToBodyVm() { return createWrapper(`<div><dropdown append-to-body> <btn class="dropdown-toggle">Dropdown <span class="caret"></span></btn> <template #dropdown> <li><a role="button">Action</a></li> <li><a role="button">Another action</a></li> <li><a role="button">Something else here</a></li> <li role="separator" class="divider"></li> <li><a role="button">Separated link</a></li> </template> </dropdown> <!-- dropdown with append-to-body + menu-right --> <dropdown append-to-body menu-right> <btn class="dropdown-toggle">Menu-Right <span class="caret"></span></btn> <template #dropdown> <li><a role="button">Action</a></li> <li><a role="button">Another action</a></li> <li><a role="button">Something else here</a></li> <li role="separator" class="divider"></li> <li><a role="button">Separated link</a></li> </template> </dropdown> <!-- dropdown with append-to-body + dropup --> <dropdown append-to-body dropup> <btn class="dropdown-toggle">Dropup <span class="caret"></span></btn> <template #dropdown> <li><a role="button">Action</a></li> <li><a role="button">Another action</a></li> <li><a role="button">Something else here</a></li> <li role="separator" class="divider"></li> <li><a role="button">Separated link</a></li> </template> </dropdown></div>`); } function baseVm() { return createWrapper(`<div><dropdown ref="dropdown"> <btn type="primary" class="dropdown-toggle">Dropdown <span class="caret"></span></btn> <template #dropdown> <li><a role="button">Action</a></li> <li><a role="button">Another action</a></li> <li><a role="button">Something else here</a></li> <li role="separator" class="divider"></li> <li><a role="button">Separated link</a></li> </template> </dropdown> <dropdown> <btn type="info">Split Button</btn> <btn type="info" class="dropdown-toggle"><span class="caret"></span></btn> <template #dropdown> <li><a role="button">Action</a></li> <li><a role="button">Another action</a></li> <li><a role="button">Something else here</a></li> <li role="separator" class="divider"></li> <li><a role="button">Separated link</a></li> </template> </dropdown></div>`); } async function assertKeyboardNav( trigger, wrapper, index, keyCode, called = true ) { const spy = jest.spyOn(wrapper.findAll('li > a')[index].element, 'focus'); await triggerEvent(trigger, `keydown.${keyCode}`); if (called) { expect(spy).toBeCalled(); } else { expect(spy).not.toBeCalled(); } spy.mockRestore(); // wrapper.find('li > a').removeAttr('focus') // wrapper.find('li > a').at(index).attr('focus', true) } describe('Dropdown', () => { it('should be able to open dropdown on trigger click', async () => { const wrapper = baseVm(); const dropdown = wrapper.find('.dropdown'); const trigger = dropdown.find('button'); expect(dropdown.element.tagName.toLowerCase()).toEqual('div'); expect(dropdown.classes()).not.toContain('open'); await triggerEvent(trigger, 'click'); await nextTick(); expect(dropdown.classes()).toContain('open'); }); it('should be able to close dropdown using keyboard esc', async () => { const wrapper = baseVm(); const dropdown = wrapper.find('.dropdown'); const trigger = dropdown.find('button'); expect(dropdown.element.tagName.toLowerCase()).toEqual('div'); expect(dropdown.classes()).not.toContain('open'); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).toContain('open'); await triggerEvent(trigger, 'keydown.esc'); expect(dropdown.classes()).not.toContain('open'); }); it('should be able to navigate between items using keyboard up & down', async () => { const wrapper = baseVm(); const dropdown = wrapper.find('.dropdown'); const trigger = dropdown.find('button'); expect(dropdown.element.tagName.toLowerCase()).toEqual('div'); expect(dropdown.classes()).not.toContain('open'); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).toContain('open'); await assertKeyboardNav(trigger, dropdown, 0, 'down'); await assertKeyboardNav(trigger, dropdown, 1, 'down'); await assertKeyboardNav(trigger, dropdown, 0, 'up'); await assertKeyboardNav(trigger, dropdown, 0, 'up', false); await assertKeyboardNav(trigger, dropdown, 1, 'down'); await assertKeyboardNav(trigger, dropdown, 2, 'down'); await assertKeyboardNav(trigger, dropdown, 3, 'down'); await assertKeyboardNav(trigger, dropdown, 3, 'down', false); }); it('should not be able to navigate between items using keyboard up & down when dropdown is not open', async () => { const wrapper = baseVm(); const dropdown = wrapper.find('.dropdown'); const trigger = dropdown.find('button'); expect(dropdown.element.tagName.toLowerCase()).toEqual('div'); expect(dropdown.classes()).not.toContain('open'); await assertKeyboardNav(trigger, dropdown, 0, 'down', false); }); it('should be able to navigate between items and select with keyboard enter', async () => { const wrapper = baseVm(); const dropdown = wrapper.find('.dropdown'); const trigger = dropdown.find('button'); expect(dropdown.element.tagName.toLowerCase()).toEqual('div'); expect(dropdown.classes()).not.toContain('open'); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).toContain('open'); await assertKeyboardNav(trigger, dropdown, 0, 'down'); const spy = jest.spyOn(dropdown.findAll('li > a')[0].element, 'click'); await triggerEvent(trigger, 'keydown.enter'); expect(spy).toBeCalled(); }); it('should ignore other keys when open', async () => { const wrapper = baseVm(); const dropdown = wrapper.find('.dropdown'); const trigger = dropdown.find('button'); expect(dropdown.element.tagName.toLowerCase()).toEqual('div'); expect(dropdown.classes()).not.toContain('open'); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).toContain('open'); await assertKeyboardNav(trigger, dropdown, 0, 'down'); await assertKeyboardNav(trigger, dropdown, 1, 'left', false); }); it('should be able to close dropdown on trigger click', async () => { const wrapper = baseVm(); const dropdown = wrapper.find('.dropdown'); const trigger = dropdown.find('button'); expect(dropdown.element.tagName.toLowerCase()).toEqual('div'); expect(dropdown.classes()).not.toContain('open'); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).toContain('open'); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).not.toContain('open'); }); it('should be able to close dropdown on window click', async () => { const wrapper = baseVm(); const dropdown = wrapper.find('.dropdown'); const trigger = dropdown.find('button'); expect(dropdown.element.tagName.toLowerCase()).toEqual('div'); expect(dropdown.classes()).not.toContain('open'); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).toContain('open'); windowClick(document.body); await nextTick(); expect(dropdown.classes()).not.toContain('open'); }); it('should not close dropdown on self click if not-close-elements contains component ref and with append-to-body', async () => { const wrapper = createWrapper( `<dropdown v-model="show" ref="test" append-to-body :not-close-elements="eles"> <button class="btn btn-default dropdown-toggle" type="button"> <span>Dropdown 1</span><span class="caret"></span> </button> <template #dropdown> <li ref="li1"><a href="#">Action</a></li> <li ref="li2"><a href="#">Action2</a></li> </template> </dropdown>`, { show: true, eles: [], }, { mounted() { this.eles.push(this.$refs.li1); }, } ); await nextTick(); const dropdown = wrapper; expect(dropdown.element.tagName.toLowerCase()).toEqual('div'); expect(dropdown.classes()).toContain('open'); windowClick(wrapper.vm.$refs.li1); await nextTick(); expect(dropdown.classes()).toContain('open'); windowClick(document.body); await nextTick(); expect(dropdown.classes()).not.toContain('open'); wrapper.vm.show = true; await nextTick(); windowClick(wrapper.vm.$refs.li2); await nextTick(); expect(dropdown.classes()).not.toContain('open'); }); it('should be able to open dropdown append to body on trigger click', async () => { const wrapper = appendToBodyVm(); const dropdown = wrapper.find('.dropdown'); const trigger = dropdown.find('button'); expect(dropdown.classes()).not.toContain('open'); // console.log(wrapper.html()) expect(dropdown.find('.dropdown-menu')).toBeDefined(); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).toContain('open'); expect(document.querySelectorAll('body>.dropdown-menu').length).toEqual(1); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).not.toContain('open'); expect(dropdown.find('.dropdown-menu')).toBeDefined(); }); it('should be able to use dropup style', async () => { const wrapper = createWrapper(`<div><dropdown dropup> <btn class="dropdown-toggle">Dropup <span class="caret"></span></btn> <template #dropdown> <li><a role="button">Action</a></li> <li><a role="button">Another action</a></li> <li><a role="button">Something else here</a></li> <li role="separator" class="divider"></li> <li><a role="button">Separated link</a></li> </template> </dropdown></div>`); await nextTick(); const dropup = wrapper.find('.dropup'); expect(dropup.classes()).not.toContain('open'); expect(dropup.find('.dropdown-menu')).toBeDefined(); }); it('should be able to use menu-right style', async () => { const wrapper = createWrapper(`<div><dropdown menu-right> <btn class="dropdown-toggle">Menu-Right <span class="caret"></span></btn> <template #dropdown> <li><a role="button">Action</a></li> <li><a role="button">Another action</a></li> <li><a role="button">Something else here</a></li> <li role="separator" class="divider"></li> <li><a role="button">Separated link</a></li> </template> </dropdown></div>`); await nextTick(); const menuRight = wrapper.find('.dropdown'); expect(menuRight.find('.dropdown-menu').classes()).toContain( 'dropdown-menu-right' ); }); it('should be able to open dropdown append to body & menu-right on trigger click', async () => { const wrapper = appendToBodyVm(); const dropdown = wrapper.findAll('.dropdown')[1]; const trigger = dropdown.find('button'); expect(dropdown.classes()).not.toContain('open'); expect(dropdown.findAll('.dropdown-menu-right').length).toEqual(1); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).toContain('open'); expect( document.querySelectorAll('body > .dropdown-menu-right').length ).toEqual(1); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).not.toContain('open'); expect(dropdown.find('.dropdown-menu-right')).toBeDefined(); }); it('should be able to open dropdown append to body & dropup on trigger click', async () => { const wrapper = appendToBodyVm(); const dropdown = wrapper.find('.dropup'); const trigger = dropdown.find('button'); expect(dropdown.classes()).not.toContain('open'); expect(dropdown.findAll('.dropdown-menu').length).toEqual(1); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).toContain('open'); expect(document.querySelectorAll('body>.dropdown-menu').length).toEqual(1); await triggerEvent(trigger, 'click'); expect(dropdown.classes()).not.toContain('open'); expect(dropdown.find('.dropdown-menu')).toBeDefined(); }); it('should be able to open dropdown on init', async () => { const wrapper = createWrapper( '<dropdown v-model="show"><button class="btn btn-default dropdown-toggle" type="button"><span>Dropdown 1</span><span class="caret"></span></button><template #dropdown><li><a href="#">Action</a></li></template></dropdown>', { show: true, } ); await nextTick(); const dropdown = wrapper; expect(dropdown.classes()).toContain('open'); }); it('should be able to disable dropdown', async () => { const wrapper = createWrapper( '<dropdown v-model="show" disabled><button class="btn btn-default dropdown-toggle" type="button"><span>Dropdown 1</span><span class="caret"></span></button><template #dropdown><li><a href="#">Action</a></li></template></dropdown>', { show: true, } ); await nextTick(); const dropdown = wrapper; expect(dropdown.classes()).not.toContain('open'); }); it('should be able to init with no trigger', async () => { const wrapper = createWrapper('<dropdown/>'); await nextTick(); }); });