UNPKG

vuetify

Version:

Vue Material Component Framework

493 lines (376 loc) 12.4 kB
// Components import VSelect from '../VSelect' // Utilities import { mount, Wrapper, } from '@vue/test-utils' // eslint-disable-next-line max-statements describe('VSelect.ts', () => { type Instance = InstanceType<typeof VSelect> let mountFunction: (options?: object) => Wrapper<Instance> let el beforeEach(() => { el = document.createElement('div') el.setAttribute('data-app', 'true') document.body.appendChild(el) mountFunction = (options = {}) => { return mount(VSelect, { // https://github.com/vuejs/vue-test-utils/issues/1130 sync: false, mocks: { $vuetify: { lang: { t: (val: string) => val, }, theme: { dark: false, }, }, }, ...options, }) } }) afterEach(() => { document.body.removeChild(el) }) it('should select an item !multiple', async () => { const wrapper = mountFunction() const input = jest.fn() const change = jest.fn() wrapper.vm.$on('input', input) wrapper.vm.$on('change', change) wrapper.vm.selectItem('foo') expect(wrapper.vm.internalValue).toBe('foo') expect(input).toHaveBeenCalledWith('foo') expect(input).toHaveBeenCalledTimes(1) await wrapper.vm.$nextTick() expect(change).toHaveBeenCalledWith('foo') expect(change).toHaveBeenCalledTimes(1) wrapper.setProps({ returnObject: true }) const item = { foo: 'bar' } wrapper.vm.selectItem(item) expect(wrapper.vm.internalValue).toBe(item) expect(input).toHaveBeenCalledWith(item) expect(input).toHaveBeenCalledTimes(2) await wrapper.vm.$nextTick() expect(change).toHaveBeenCalledWith(item) expect(change).toHaveBeenCalledTimes(2) }) // TODO: this fails without sync, nextTick doesn't help // https://github.com/vuejs/vue-test-utils/issues/1130 it.skip('should disable v-list-item', async () => { const selectItem = jest.fn() const wrapper = mountFunction({ propsData: { eager: true, items: [{ text: 'foo', disabled: true, id: 0 }], }, methods: { selectItem }, }) const el = wrapper.find('.v-list-item') el.element.click() expect(selectItem).not.toHaveBeenCalled() wrapper.setProps({ items: [{ text: 'foo', disabled: false, id: 0 }], }) await wrapper.vm.$nextTick() el.element.click() expect(selectItem).toHaveBeenCalled() }) it('should update menu status and focus when menu closes', async () => { const wrapper = mountFunction() const menu = wrapper.vm.$refs.menu wrapper.setData({ isMenuActive: true, isFocused: true, }) expect(wrapper.vm.isMenuActive).toBe(true) expect(wrapper.vm.isFocused).toBe(true) await wrapper.vm.$nextTick() expect(menu.isActive).toBe(true) menu.isActive = false await wrapper.vm.$nextTick() expect(wrapper.vm.isMenuActive).toBe(false) expect(wrapper.vm.isFocused).toBe(false) }) // TODO: this fails without sync, nextTick doesn't help // https://github.com/vuejs/vue-test-utils/issues/1130 it.skip('should update model when chips are removed', async () => { const selectItem = jest.fn() const wrapper = mountFunction({ propsData: { chips: true, deletableChips: true, items: ['foo'], value: 'foo', }, methods: { selectItem }, }) const input = jest.fn() const change = jest.fn() wrapper.vm.$on('input', input) expect(wrapper.vm.internalValue).toEqual('foo') wrapper.find('.v-chip__close').trigger('click') expect(input).toHaveBeenCalledTimes(1) wrapper.setProps({ items: ['foo', 'bar'], multiple: true, value: ['foo', 'bar'], }) wrapper.vm.$on('change', change) await wrapper.vm.$nextTick() expect(wrapper.vm.internalValue).toEqual(['foo', 'bar']) wrapper.find('.v-chip__close').trigger('click') await wrapper.vm.$nextTick() expect(selectItem).toHaveBeenCalledTimes(1) }) // TODO: this fails without sync, nextTick doesn't help // https://github.com/vuejs/vue-test-utils/issues/1130 it.skip('should set selected index', async () => { const wrapper = mountFunction({ propsData: { chips: true, deletableChips: true, multiple: true, items: ['foo', 'bar', 'fizz', 'buzz'], value: ['foo', 'bar', 'fizz', 'buzz'], }, }) expect(wrapper.vm.selectedIndex).toBe(-1) const foo = wrapper.find('.v-chip') foo.trigger('click') expect(wrapper.vm.selectedIndex).toBe(0) wrapper.findAll('.v-chip').at(1).trigger('click') expect(wrapper.vm.selectedIndex).toBe(1) wrapper.setProps({ disabled: true }) wrapper.find('.v-chip').trigger('click') expect(wrapper.vm.selectedIndex).toBe(1) }) it('should not duplicate items after items update when caching is turned on', async () => { const wrapper = mountFunction({ propsData: { cacheItems: true, returnObject: true, itemText: 'text', itemValue: 'id', items: [], }, }) wrapper.setProps({ items: [{ id: 1, text: 'A' }] }) expect(wrapper.vm.computedItems).toHaveLength(1) wrapper.setProps({ items: [{ id: 1, text: 'A' }] }) expect(wrapper.vm.computedItems).toHaveLength(1) }) // TODO: this fails without sync, nextTick doesn't help // https://github.com/vuejs/vue-test-utils/issues/1130 it.skip('should cache items', async () => { const wrapper = mountFunction({ propsData: { cacheItems: true, items: [], }, }) wrapper.setProps({ items: ['bar', 'baz'] }) await wrapper.vm.$nextTick() expect(wrapper.vm.computedItems).toHaveLength(2) wrapper.setProps({ items: ['foo'] }) await wrapper.vm.$nextTick() expect(wrapper.vm.computedItems).toHaveLength(3) wrapper.setProps({ items: ['bar'] }) await wrapper.vm.$nextTick() expect(wrapper.vm.computedItems).toHaveLength(3) }) it('should cache items passed via prop', async () => { const wrapper = mountFunction({ propsData: { cacheItems: true, items: [1, 2, 3, 4], }, }) expect(wrapper.vm.computedItems).toHaveLength(4) wrapper.setProps({ items: [5] }) expect(wrapper.vm.computedItems).toHaveLength(5) }) it('should have an affix', async () => { const wrapper = mountFunction({ propsData: { prefix: '$', suffix: 'lbs', }, }) expect(wrapper.find('.v-text-field__prefix').element.innerHTML).toBe('$') expect(wrapper.find('.v-text-field__suffix').element.innerHTML).toBe('lbs') wrapper.setProps({ prefix: undefined, suffix: undefined }) await wrapper.vm.$nextTick() expect(wrapper.findAll('.v-text-field__prefix')).toHaveLength(0) expect(wrapper.findAll('.v-text-field__suffix')).toHaveLength(0) }) it('should use custom clear icon cb', async () => { const clearIconCb = jest.fn() const wrapper = mountFunction({ propsData: { clearable: true, items: ['foo'], value: 'foo', }, }) wrapper.vm.$on('click:clear', clearIconCb) wrapper.find('.v-input__icon--clear .v-icon').trigger('click') expect(clearIconCb).toHaveBeenCalled() }) it('should populate select[multiple=false] when using value as an object', async () => { const wrapper = mountFunction({ attachToDocument: true, propsData: { items: [ { text: 'foo', value: { id: { subid: 1 } } }, { text: 'foo', value: { id: { subid: 2 } } }, ], multiple: false, value: { id: { subid: 2 } }, }, }) const selections = wrapper.findAll('.v-select__selection') expect(selections).toHaveLength(1) }) it('should add color to selected index', async () => { const wrapper = mountFunction({ propsData: { multiple: true, items: ['foo', 'bar'], value: ['foo'], }, }) wrapper.vm.selectedIndex = 0 await wrapper.vm.$nextTick() expect(wrapper.html()).toMatchSnapshot() }) it('should not react to click when disabled', async () => { const wrapper = mountFunction({ propsData: { items: ['foo', 'bar'] }, }) const slot = wrapper.find('.v-input__slot') expect(wrapper.vm.isMenuActive).toBe(false) slot.trigger('click') expect(wrapper.vm.isMenuActive).toBe(true) wrapper.setData({ isMenuActive: false }) wrapper.setProps({ disabled: true }) await wrapper.vm.$nextTick() expect(wrapper.vm.isMenuActive).toBe(false) slot.trigger('click') expect(wrapper.vm.isMenuActive).toBe(false) }) it('should set the menu index', async () => { const wrapper = mountFunction() expect(wrapper.vm.getMenuIndex()).toBe(-1) wrapper.vm.setMenuIndex(1) expect(wrapper.vm.getMenuIndex()).toBe(1) }) // Inspired by https://github.com/vuetifyjs/vuetify/pull/1425 - Thanks @kevmo314 it('should open the select when enter is pressed', async () => { const wrapper = mountFunction({ propsData: { items: ['foo', 'bar'], }, }) wrapper.find('input').trigger('keydown.enter') await wrapper.vm.$nextTick() expect(document.body.querySelector('[data-app="true"]')).toMatchSnapshot() }) it('should open the select when space is pressed', async () => { const wrapper = mountFunction({ propsData: { items: ['foo', 'bar'], }, }) wrapper.find('input').trigger('keydown.space') await wrapper.vm.$nextTick() expect(document.body.querySelector('[data-app="true"]')).toMatchSnapshot() }) it('should open the select is multiple and key up is pressed', async () => { const wrapper = mountFunction({ propsData: { multiple: true, items: ['foo', 'bar'], }, }) wrapper.find('input').trigger('keydown.up') await wrapper.vm.$nextTick() expect(document.body.querySelector('[data-app="true"]')).toMatchSnapshot() }) it('should open the select is multiple and key down is pressed', async () => { const wrapper = mountFunction({ propsData: { multiple: true, items: ['foo', 'bar'], }, }) wrapper.find('input').trigger('keydown.down') await wrapper.vm.$nextTick() expect(document.body.querySelector('[data-app="true"]')).toMatchSnapshot() }) it('should return full items if using auto prop', async () => { const wrapper = mountFunction({ propsData: { items: [...Array(100).keys()], }, }) expect(wrapper.vm.virtualizedItems).toHaveLength(20) wrapper.setProps({ menuProps: 'auto' }) expect(wrapper.vm.virtualizedItems).toHaveLength(100) }) it('should fallback to using text as value if none present', async () => { const wrapper = mountFunction({ propsData: { items: [{ text: 'foo', }], }, }) expect(wrapper.vm.getValue(wrapper.vm.items[0])).toBe('foo') }) it('should accept arrays as values', async () => { const wrapper = mountFunction({ propsData: { items: [ { text: 'Foo', value: ['bar'] }, ], }, }) const input = jest.fn() wrapper.vm.$on('input', input) wrapper.vm.selectItem(wrapper.vm.items[0]) await wrapper.vm.$nextTick() expect(input).toHaveBeenCalledWith(['bar']) expect(wrapper.vm.selectedItems).toEqual([ { text: 'Foo', value: ['bar'] }, ]) }) it('should update inner input element', async () => { const wrapper = mountFunction({ propsData: { items: ['foo', 'bar', 'fizz', 'buzz'], value: ['fizz'], }, }) const inputs = wrapper.findAll('input') const element = inputs.at(1).element expect(element.value).toEqual('fizz') wrapper.vm.selectItem(wrapper.vm.items[1]) await wrapper.vm.$nextTick() expect(element.value).toEqual('bar') }) it('should pass the name attribute to the inner input element', async () => { const wrapper = mountFunction({ propsData: { items: ['foo'], name: ['bar'], }, }) const inputs = wrapper.findAll('input') const element = inputs.at(1).element expect(element.name).toEqual('bar') }) })