UNPKG

uiv

Version:

Bootstrap 3 components implemented by Vue.

928 lines (909 loc) 35.5 kB
import { createWrapper, keyCodes, triggerEvent, triggerKey, } from '../../__test__/utils'; import _ from 'lodash'; describe('MultiSelect', () => { it('should be able to render with no options', async () => { const wrapper = createWrapper( '<div><multi-select v-model="selected" :options="options"/></div>', { selected: [], options: [], } ); const vm = wrapper.vm; await vm.$nextTick(); const trigger = vm.$el.querySelector('.dropdown-toggle'); trigger.click(); await vm.$nextTick(); expect(vm.$el.querySelectorAll('li > a').length).toEqual(0); }); it('should be able to use custom placeholder', async () => { const wrapper = createWrapper( `<div> <multi-select v-model="selected" :options="options" placeholder="someplaceholder..."/> </div>`, { selected: [], options: [{ value: 1, label: 'Option1' }], } ); const vm = wrapper.vm; await vm.$nextTick(); expect( vm.$el.querySelector('[data-role="trigger"] .text-muted').textContent ).toEqual('someplaceholder...'); }); it('should be able to open dropdown and select options', async () => { const wrapper = createWrapper( `<div> <multi-select v-model="selected" :options="options"/> </div>`, { selected: [], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3' }, { value: 4, label: 'Option4' }, { value: 5, label: 'Option5' }, ], } ); const vm = wrapper.vm; const dropdown = vm.$el.querySelector('.dropdown'); const trigger = dropdown.querySelector('.dropdown-toggle'); const display = dropdown.querySelectorAll('.dropdown-toggle > div')[1]; expect(dropdown.className).not.toContain('open'); trigger.click(); await vm.$nextTick(); expect(dropdown.className).toContain('open'); expect(_.isEmpty(vm.selected)).toBeTruthy(); expect(display.textContent).toEqual('Select...'); expect(dropdown.querySelectorAll('li > a')[0].textContent).toEqual( 'Option1' ); expect(dropdown.querySelectorAll('li > a')[1].textContent).toEqual( 'Option2' ); expect(dropdown.querySelectorAll('li > a')[2].textContent).toEqual( 'Option3' ); expect(dropdown.querySelectorAll('li > a')[3].textContent).toEqual( 'Option4' ); expect(dropdown.querySelectorAll('li > a')[4].textContent).toEqual( 'Option5' ); // select option 1 dropdown.querySelectorAll('li')[0].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1'); expect(_.isEqual(vm.selected, [1])).toBeTruthy(); // select option 2 dropdown.querySelectorAll('li')[1].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2'); expect(_.isEqual(vm.selected, [1, 2])).toBeTruthy(); // select option 3 dropdown.querySelectorAll('li')[2].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2, Option3'); expect(_.isEqual(vm.selected, [1, 2, 3])).toBeTruthy(); // select option 4 dropdown.querySelectorAll('li')[3].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2, Option3, Option4'); expect(_.isEqual(vm.selected, [1, 2, 3, 4])).toBeTruthy(); // select option 5 dropdown.querySelectorAll('li')[4].click(); await vm.$nextTick(); expect(display.textContent).toEqual( 'Option1, Option2, Option3, Option4, Option5' ); expect(_.isEqual(vm.selected, [1, 2, 3, 4, 5])).toBeTruthy(); // unselect option 1 dropdown.querySelectorAll('li')[0].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option2, Option3, Option4, Option5'); expect(_.isEqual(vm.selected, [2, 3, 4, 5])).toBeTruthy(); // unselect option 2 dropdown.querySelectorAll('li')[1].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option3, Option4, Option5'); expect(_.isEqual(vm.selected, [3, 4, 5])).toBeTruthy(); // unselect option 3 dropdown.querySelectorAll('li')[2].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option4, Option5'); expect(_.isEqual(vm.selected, [4, 5])).toBeTruthy(); // unselect option 4 dropdown.querySelectorAll('li')[3].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option5'); expect(_.isEqual(vm.selected, [5])).toBeTruthy(); // unselect option 5 dropdown.querySelectorAll('li')[4].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Select...'); expect(_.isEmpty(vm.selected)).toBeTruthy(); }); it('should be able to use custom `itemSelectedClass`', async () => { const wrapper = createWrapper( `<div> <multi-select v-model="selected" :options="options" item-selected-class="someclass"/> </div>`, { selected: [], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3' }, { value: 4, label: 'Option4' }, { value: 5, label: 'Option5' }, ], } ); const vm = wrapper.vm; const dropdown = vm.$el.querySelector('.dropdown'); const trigger = dropdown.querySelector('.dropdown-toggle'); const display = dropdown.querySelectorAll('.dropdown-toggle > div')[1]; trigger.click(); await vm.$nextTick(); expect(dropdown.className).toContain('open'); // select option 1 dropdown.querySelectorAll('li')[2].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option3'); expect(dropdown.querySelectorAll('li')[2].className).toContain('someclass'); expect(_.isEqual(vm.selected, [3])).toBeTruthy(); }); it('should be able to limit selected length', async () => { const wrapper = createWrapper( `<div> <multi-select v-model="selected" :options="options" :limit="3"/> </div>`, { selected: [], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3' }, { value: 4, label: 'Option4' }, { value: 5, label: 'Option5' }, ], } ); const vm = wrapper.vm; const dropdown = vm.$el.querySelector('.dropdown'); const trigger = dropdown.querySelector('.dropdown-toggle'); const display = dropdown.querySelectorAll('.dropdown-toggle > div')[1]; trigger.click(); await vm.$nextTick(); expect(_.isEmpty(vm.selected)).toBeTruthy(); // select option 1 dropdown.querySelectorAll('li')[0].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1'); expect(_.isEqual(vm.selected, [1])).toBeTruthy(); // select option 2 dropdown.querySelectorAll('li')[1].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2'); expect(_.isEqual(vm.selected, [1, 2])).toBeTruthy(); // select option 3 dropdown.querySelectorAll('li')[2].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2, Option3'); expect(_.isEqual(vm.selected, [1, 2, 3])).toBeTruthy(); // select option 4 (should not work) dropdown.querySelectorAll('li')[3].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2, Option3'); expect(_.isEqual(vm.selected, [1, 2, 3])).toBeTruthy(); // select option 5 (should not work) dropdown.querySelectorAll('li')[4].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2, Option3'); expect(_.isEqual(vm.selected, [1, 2, 3])).toBeTruthy(); // unselect option 1 dropdown.querySelectorAll('li')[0].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option2, Option3'); expect(_.isEqual(vm.selected, [2, 3])).toBeTruthy(); // unselect option 2 dropdown.querySelectorAll('li')[1].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option3'); expect(_.isEqual(vm.selected, [3])).toBeTruthy(); // unselect option 3 dropdown.querySelectorAll('li')[2].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Select...'); expect(_.isEmpty(vm.selected)).toBeTruthy(); }); it('should be able to render optional sizes', async () => { const wrapper = createWrapper( ` <section> <multi-select v-model="selected" :options="options" size="sm"/> <multi-select v-model="selected" :options="options"/> <multi-select v-model="selected" :options="options" size="lg"/> <multi-select v-model="selected" :options="options" size="lg" block/> </section>`, { selected: [], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3' }, { value: 4, label: 'Option4' }, { value: 5, label: 'Option5' }, ], } ); const vm = wrapper.vm; const _el = vm.$el; const dropdown1 = _el.querySelectorAll('.dropdown')[0]; const dropdown2 = _el.querySelectorAll('.dropdown')[1]; const dropdown3 = _el.querySelectorAll('.dropdown')[2]; const dropdown4 = _el.querySelectorAll('.dropdown')[3]; const className1 = dropdown1.querySelector('.form-control').className; const className2 = dropdown2.querySelector('.form-control').className; const className3 = dropdown3.querySelector('.form-control').className; const className4 = dropdown4.querySelector('.form-control').className; // sm size expect(dropdown1.style.width).toEqual(''); expect(className1).toContain('input-sm'); expect(className1).not.toContain('input-lg'); // normal expect(dropdown2.style.width).toEqual(''); expect(className2).not.toContain('input-sm'); expect(className2).not.toContain('input-lg'); // lg size expect(dropdown3.style.width).toEqual(''); expect(className3).not.toContain('input-sm'); expect(className3).toContain('input-lg'); // block + lg size expect(dropdown4.style.width).toEqual('100%'); expect(className4).not.toContain('input-sm'); expect(className4).toContain('input-lg'); }); it('should be able to disable options', async () => { const wrapper = createWrapper( `<div> <multi-select v-model="selected" :options="options"/> </div>`, { selected: [], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3', disabled: true }, { value: 4, label: 'Option4' }, { value: 5, label: 'Option5', disabled: true }, ], } ); const vm = wrapper.vm; const dropdown = vm.$el.querySelector('.dropdown'); const trigger = dropdown.querySelector('.dropdown-toggle'); const display = dropdown.querySelectorAll('.dropdown-toggle > div')[1]; trigger.click(); await vm.$nextTick(); expect(_.isEmpty(vm.selected)).toBeTruthy(); // select option 1 dropdown.querySelectorAll('li')[0].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1'); expect(_.isEqual(vm.selected, [1])).toBeTruthy(); // select option 2 dropdown.querySelectorAll('li')[1].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2'); expect(_.isEqual(vm.selected, [1, 2])).toBeTruthy(); // select option 3 (should not work) dropdown.querySelectorAll('li')[2].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2'); expect(_.isEqual(vm.selected, [1, 2])).toBeTruthy(); // select option 4 dropdown.querySelectorAll('li')[3].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2, Option4'); expect(_.isEqual(vm.selected, [1, 2, 4])).toBeTruthy(); // select option 5 (should not work) dropdown.querySelectorAll('li')[4].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2, Option4'); expect(_.isEqual(vm.selected, [1, 2, 4])).toBeTruthy(); }); it('should be able to disable dropdown', async () => { const wrapper = createWrapper( `<div> <multi-select v-model="selected" :options="options" disabled/> </div>`, { selected: [], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3' }, { value: 4, label: 'Option4' }, { value: 5, label: 'Option5' }, ], } ); const vm = wrapper.vm; const dropdown = vm.$el.querySelector('.dropdown'); const trigger = dropdown.querySelector('.dropdown-toggle'); expect( dropdown.querySelector('.form-control').getAttribute('disabled') ).toEqual('true'); expect(dropdown.className).not.toContain('open'); trigger.click(); await vm.$nextTick(); expect(dropdown.className).not.toContain('open'); }); it('should be able to collapse selected', async () => { const wrapper = createWrapper( `<div> <multi-select v-model="selected" :options="options" collapse-selected/> </div>`, { selected: [], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3' }, { value: 4, label: 'Option4' }, { value: 5, label: 'Option5' }, ], } ); const vm = wrapper.vm; const dropdown = vm.$el.querySelector('.dropdown'); const trigger = dropdown.querySelector('.dropdown-toggle'); const display = dropdown.querySelectorAll('.dropdown-toggle > div')[1]; expect(dropdown.className).not.toContain('open'); trigger.click(); await vm.$nextTick(); expect(dropdown.className).toContain('open'); expect(_.isEmpty(vm.selected)).toBeTruthy(); expect(display.textContent).toEqual('Select...'); // select option 1 dropdown.querySelectorAll('li')[0].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1'); expect(_.isEqual(vm.selected, [1])).toBeTruthy(); // select option 2 dropdown.querySelectorAll('li')[1].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, +1'); expect(_.isEqual(vm.selected, [1, 2])).toBeTruthy(); // select option 3 dropdown.querySelectorAll('li')[2].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, +2'); expect(_.isEqual(vm.selected, [1, 2, 3])).toBeTruthy(); // select option 4 dropdown.querySelectorAll('li')[3].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, +3'); expect(_.isEqual(vm.selected, [1, 2, 3, 4])).toBeTruthy(); // select option 5 dropdown.querySelectorAll('li')[4].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, +4'); expect(_.isEqual(vm.selected, [1, 2, 3, 4, 5])).toBeTruthy(); // unselect option 1 dropdown.querySelectorAll('li')[0].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option2, +3'); expect(_.isEqual(vm.selected, [2, 3, 4, 5])).toBeTruthy(); // unselect option 2 dropdown.querySelectorAll('li')[1].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option3, +2'); expect(_.isEqual(vm.selected, [3, 4, 5])).toBeTruthy(); // unselect option 3 dropdown.querySelectorAll('li')[2].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option4, +1'); expect(_.isEqual(vm.selected, [4, 5])).toBeTruthy(); // unselect option 4 dropdown.querySelectorAll('li')[3].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Option5'); expect(_.isEqual(vm.selected, [5])).toBeTruthy(); // unselect option 5 dropdown.querySelectorAll('li')[4].click(); await vm.$nextTick(); expect(display.textContent).toEqual('Select...'); expect(_.isEmpty(vm.selected)).toBeTruthy(); }); it('should be able to filter options', async () => { const wrapper = createWrapper( `<div> <multi-select v-model="selected" :options="options" filterable/> </div>`, { selected: [], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3' }, { value: 4, label: 'Option4' }, { value: 5, label: 'Option5' }, ], } ); const vm = wrapper.vm; const dropdown = vm.$el.querySelector('.dropdown'); const trigger = dropdown.querySelector('.dropdown-toggle'); const searchInput = dropdown.querySelector('.form-control.input-sm'); trigger.click(); await vm.$nextTick(); expect(dropdown.className).toContain('open'); // + 1 is the search box expect(dropdown.querySelectorAll('li').length).toEqual(5 + 1); searchInput.value = 'option'; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(5 + 1); searchInput.value = '1'; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(1 + 1); expect(dropdown.querySelector('li > a').textContent).toEqual('Option1'); searchInput.value = 'Option1'; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(1 + 1); expect(dropdown.querySelector('li > a').textContent).toEqual('Option1'); searchInput.value = '5'; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(1 + 1); expect(dropdown.querySelector('li > a').textContent).toEqual('Option5'); searchInput.value = ''; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(5 + 1); }); it('should be able to use custom filter placeholder', async () => { const wrapper = createWrapper( `<div> <multi-select v-model="selected" :options="options" filterable filter-placeholder="someplaceholder..."/> </div>`, { selected: [], options: [{ value: 1, label: 'Option1' }], } ); const vm = wrapper.vm; const dropdown = vm.$el.querySelector('.dropdown'); const searchInput = dropdown.querySelector('.form-control.input-sm'); expect(searchInput.getAttribute('placeholder')).toEqual( 'someplaceholder...' ); }); it('should be able to use custom labelKey and valueKey', async () => { const wrapper = createWrapper( `<div> <multi-select v-model="selected" :options="options" filterable label-key="someLabel" value-key="someVal"/> </div>`, { selected: [], options: [ { someVal: 1, someLabel: 'Option1' }, { someVal: 2, someLabel: 'Option2' }, { someVal: 3, someLabel: 'Option3' }, { someVal: 4, someLabel: 'Option4' }, { someVal: 5, someLabel: 'Option5' }, ], } ); const vm = wrapper.vm; const dropdown = vm.$el.querySelector('.dropdown'); const trigger = dropdown.querySelector('.dropdown-toggle'); const searchInput = dropdown.querySelector('.form-control.input-sm'); trigger.click(); await vm.$nextTick(); expect(dropdown.className).toContain('open'); // + 1 is the search box expect(dropdown.querySelectorAll('li').length).toEqual(5 + 1); searchInput.value = 'option'; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(5 + 1); searchInput.value = '1'; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(1 + 1); expect(dropdown.querySelector('li > a').textContent).toEqual('Option1'); searchInput.value = 'Option1'; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(1 + 1); expect(dropdown.querySelector('li > a').textContent).toEqual('Option1'); searchInput.value = '5'; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(1 + 1); expect(dropdown.querySelector('li > a').textContent).toEqual('Option5'); searchInput.value = ''; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(5 + 1); }); it('should be ok if value not present in options', async () => { const wrapper = createWrapper( `<div> <multi-select v-model="selected" :options="options"/> </div>`, { selected: [5], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3' }, { value: 4, label: 'Option4' }, ], } ); const vm = wrapper.vm; await vm.$nextTick(); expect( vm.$el.querySelectorAll('.dropdown-toggle > div')[1].textContent ).toEqual('5'); }); it('should be able use custom filter function', async () => { const wrapper = createWrapper( '<multi-select v-model="selected" :options="options" filterable :filter-function="filterFunction"/>', { selected: [], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3' }, { value: 4, label: 'Option4' }, { value: 5, label: 'Option5' }, ], }, { methods: { filterFunction(query) { // always return option 1 and 5 return [this.options[0], this.options[4]]; }, }, } ); const vm = wrapper.vm; const dropdown = vm.$el; const trigger = dropdown.querySelector('.dropdown-toggle'); const searchInput = dropdown.querySelector('.form-control.input-sm'); trigger.click(); await vm.$nextTick(); expect(dropdown.className).toContain('open'); // + 1 is the search box expect(dropdown.querySelectorAll('li').length).toEqual(5 + 1); searchInput.value = 'option'; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(2 + 1); expect(dropdown.querySelectorAll('li > a')[0].textContent).toEqual( 'Option1' ); expect(dropdown.querySelectorAll('li > a')[1].textContent).toEqual( 'Option5' ); searchInput.value = '3'; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(2 + 1); expect(dropdown.querySelectorAll('li > a')[0].textContent).toEqual( 'Option1' ); expect(dropdown.querySelectorAll('li > a')[1].textContent).toEqual( 'Option5' ); searchInput.value = ''; triggerEvent(searchInput, 'input'); await vm.$nextTick(); expect(dropdown.querySelectorAll('li').length).toEqual(5 + 1); }); it.skip('should be able to use keyboard nav & select', async () => { const wrapper = createWrapper( `<div> <multi-select v-model="selected" :options="options"/> </div>`, { selected: [], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3' }, { value: 4, label: 'Option4' }, { value: 5, label: 'Option5' }, ], } ); const vm = wrapper.vm; const dropdown = vm.$el.querySelector('.dropdown'); const trigger = dropdown.querySelector('.dropdown-toggle'); const display = dropdown.querySelectorAll('.dropdown-toggle > div')[1]; expect(dropdown.className).not.toContain('open'); // nothing happens triggerKey(trigger, keyCodes.up); await vm.$nextTick(); // nothing happens triggerKey(trigger, keyCodes.down); await vm.$nextTick(); // open dropdown triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); expect(dropdown.className).toContain('open'); expect(_.isEmpty(vm.selected)).toBeTruthy(); // nothing happens triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); expect(_.isEmpty(vm.selected)).toBeTruthy(); // select option 1 triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[0].className).toContain('active'); triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); expect(display.textContent).toEqual('Option1'); expect(_.isEqual(vm.selected, [1])).toBeTruthy(); // select option 2 triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[1].className).toContain('active'); triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2'); expect(_.isEqual(vm.selected, [1, 2])).toBeTruthy(); // select option 3 triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[2].className).toContain('active'); triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2, Option3'); expect(_.isEqual(vm.selected, [1, 2, 3])).toBeTruthy(); // select option 4 triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[3].className).toContain('active'); triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); expect(display.textContent).toEqual('Option1, Option2, Option3, Option4'); expect(_.isEqual(vm.selected, [1, 2, 3, 4])).toBeTruthy(); // select option 5 triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[4].className).toContain('active'); triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); expect(display.textContent).toEqual( 'Option1, Option2, Option3, Option4, Option5' ); expect(_.isEqual(vm.selected, [1, 2, 3, 4, 5])).toBeTruthy(); // unselect option 1 // go next (option 1) triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[0].className).toContain('active'); // go prev (option 5) triggerKey(trigger, keyCodes.up); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[4].className).toContain('active'); // go prev (option 4) triggerKey(trigger, keyCodes.up); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[3].className).toContain('active'); // go next (option 5) triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[4].className).toContain('active'); // go next (option 1) triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[0].className).toContain('active'); // todo: why failed? // triggerKey(trigger, keyCodes.enter) // await vm.$nextTick() // expect(display.textContent).toEqual('Option2, Option3, Option4, Option5') // expect(_.isEqual(vm.selected, [2, 3, 4, 5])).toBeTruthy() // // unselect option 2 // triggerKey(trigger, keyCodes.down) // await vm.$nextTick() // expect(dropdown.querySelectorAll('li.active').length).toEqual(1) // expect(dropdown.querySelectorAll('li')[1].className).toContain('active') // triggerKey(trigger, keyCodes.enter) // await vm.$nextTick() // expect(display.textContent).toEqual('Option3, Option4, Option5') // expect(_.isEqual(vm.selected, [3, 4, 5])).toBeTruthy() // // unselect option 3 // triggerKey(trigger, keyCodes.down) // await vm.$nextTick() // expect(dropdown.querySelectorAll('li.active').length).toEqual(1) // expect(dropdown.querySelectorAll('li')[2].className).toContain('active') // triggerKey(trigger, keyCodes.enter) // await vm.$nextTick() // expect(display.textContent).toEqual('Option4, Option5') // expect(_.isEqual(vm.selected, [4, 5])).toBeTruthy() // // unselect option 4 // triggerKey(trigger, keyCodes.down) // await vm.$nextTick() // expect(dropdown.querySelectorAll('li.active').length).toEqual(1) // expect(dropdown.querySelectorAll('li')[3].className).toContain('active') // triggerKey(trigger, keyCodes.enter) // await vm.$nextTick() // expect(display.textContent).toEqual('Option5') // expect(_.isEqual(vm.selected, [5])).toBeTruthy() // // unselect option 5 // triggerKey(trigger, keyCodes.down) // await vm.$nextTick() // expect(dropdown.querySelectorAll('li.active').length).toEqual(1) // expect(dropdown.querySelectorAll('li')[4].className).toContain('active') // triggerKey(trigger, keyCodes.enter) // await vm.$nextTick() // expect(display.textContent).toEqual('Select...') // expect(_.isEmpty(vm.selected)).toBeTruthy() }); it('should behave like single toggle while limit=1', async () => { const wrapper = createWrapper( '<multi-select v-model="selected" :options="options" :limit="1"/>', { selected: [], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3' }, { value: 4, label: 'Option4' }, { value: 5, label: 'Option5' }, ], } ); const vm = wrapper.vm; const dropdown = vm.$el; const trigger = dropdown.querySelector('.dropdown-toggle'); trigger.click(); await vm.$nextTick(); expect(dropdown.className).toContain('open'); // select option 1 dropdown.querySelectorAll('li')[0].click(); await vm.$nextTick(); expect(_.isEqual(vm.selected, [1])).toBeTruthy(); // select option 2 dropdown.querySelectorAll('li')[1].click(); await vm.$nextTick(); expect(_.isEqual(vm.selected, [2])).toBeTruthy(); // select option 3 dropdown.querySelectorAll('li')[2].click(); await vm.$nextTick(); expect(_.isEqual(vm.selected, [3])).toBeTruthy(); // un-select option 3 dropdown.querySelectorAll('li')[2].click(); await vm.$nextTick(); expect(_.isEqual(vm.selected, [])).toBeTruthy(); }); it.skip('should be able to display grouped options', async () => { const wrapper = createWrapper( '<div><multi-select v-model="selected" :options="options"/></div>', { selected: [], options: [ { value: 1, label: 'Apple', group: 'Fruit' }, { value: 2, label: 'Banana', group: 'Fruit' }, { value: 3, label: 'Orange', group: 'Fruit' }, { value: 4, label: 'Red', group: 'Color' }, { value: 5, label: 'Green', group: 'Color' }, ], } ); const vm = wrapper.vm; const dropdown = vm.$el.querySelector('.dropdown'); const trigger = dropdown.querySelector('.dropdown-toggle'); const display = dropdown.querySelectorAll('.dropdown-toggle > div')[1]; expect(dropdown.className).not.toContain('open'); expect(dropdown.querySelectorAll('.dropdown-header').length).toEqual(2); expect( dropdown.querySelectorAll('.dropdown-header')[0].textContent ).toEqual('Fruit'); expect( dropdown.querySelectorAll('.dropdown-header')[1].textContent ).toEqual('Color'); // open dropdown triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); // select option 1 triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[1].className).toContain('active'); triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); expect(display.textContent).toEqual('Apple'); expect(_.isEqual(vm.selected, [1])).toBeTruthy(); // select option 2 triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[2].className).toContain('active'); triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); expect(display.textContent).toEqual('Apple, Banana'); expect(_.isEqual(vm.selected, [1, 2])).toBeTruthy(); // select option 3 triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[3].className).toContain('active'); triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); expect(display.textContent).toEqual('Apple, Banana, Orange'); expect(_.isEqual(vm.selected, [1, 2, 3])).toBeTruthy(); // select option 4 triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[5].className).toContain('active'); triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); expect(display.textContent).toEqual('Apple, Banana, Orange, Red'); expect(_.isEqual(vm.selected, [1, 2, 3, 4])).toBeTruthy(); // select option 5 triggerKey(trigger, keyCodes.down); await vm.$nextTick(); expect(dropdown.querySelectorAll('li.active').length).toEqual(1); expect(dropdown.querySelectorAll('li')[6].className).toContain('active'); triggerKey(trigger, keyCodes.enter); await vm.$nextTick(); expect(display.textContent).toEqual('Apple, Banana, Orange, Red, Green'); expect(_.isEqual(vm.selected, [1, 2, 3, 4, 5])).toBeTruthy(); }); it('should be able to use option slot', async () => { const wrapper = createWrapper( ` <multi-select v-model="selected" :options="options"> <template v-slot:option="slotProps"> <i>{{ slotProps.item.label }}</i> </template> </multi-select>`, { selected: [], options: [ { value: 1, label: 'Option1' }, { value: 2, label: 'Option2' }, { value: 3, label: 'Option3' }, { value: 4, label: 'Option4' }, { value: 5, label: 'Option5' }, ], } ); const vm = wrapper.vm; const dropdown = vm.$el; const trigger = dropdown.querySelector('.dropdown-toggle'); trigger.click(); await vm.$nextTick(); expect(dropdown.className).toContain('open'); expect(dropdown.querySelectorAll('li a i').length).toEqual(5); }); });