UNPKG

vuetify

Version:

Vue Material Component Framework

469 lines (354 loc) 11.6 kB
// Components import VAutocomplete from '../VAutocomplete' // Utilities import { mount, Wrapper, } from '@vue/test-utils' import { compileToFunctions } from 'vue-template-compiler' describe('VAutocomplete.ts', () => { type Instance = InstanceType<typeof VAutocomplete> let mountFunction: (options?: object) => Wrapper<Instance> beforeEach(() => { document.body.setAttribute('data-app', 'true') mountFunction = (options = {}) => { return mount(VAutocomplete, { // https://github.com/vuejs/vue-test-utils/issues/1130 sync: false, mocks: { $vuetify: { lang: { t: (val: string) => val, }, theme: { dark: false, }, }, }, ...options, }) } }) // https://github.com/vuetifyjs/vuetify/issues/3793 it('should reset menu index after selection', async () => { const wrapper = mountFunction({ propsData: { items: ['foo', 'bar'], value: 'foo', }, }) expect(wrapper.vm.isMenuActive).toBe(false) const slot = wrapper.find('.v-input__slot') slot.trigger('click') expect(wrapper.vm.isMenuActive).toBe(true) expect(wrapper.vm.getMenuIndex()).toBe(-1) }) it('should not remove a disabled item', () => { const wrapper = mountFunction({ propsData: { chips: true, multiple: true, items: [ { text: 'foo', value: 'foo', disabled: true }, { text: 'bar', value: 'bar' }, ], value: ['foo', 'bar'], }, }) const chips = wrapper.find('.v-chip') const input = wrapper.find('input') expect(chips.element.classList.contains('v-chip--disabled')).toBe(true) input.trigger('focus') input.trigger('keydown.left') expect(wrapper.vm.selectedIndex).toBe(1) input.trigger('keydown.delete') expect(wrapper.vm.internalValue).toEqual(['foo']) input.trigger('keydown.delete') expect(wrapper.vm.internalValue).toEqual(['foo']) }) it('should not filter results', async () => { const wrapper = mountFunction({ propsData: { items: ['foo', 'bar'], }, }) const input = wrapper.find('input') const element = input.element as HTMLInputElement element.value = 'foo' input.trigger('input') expect(wrapper.vm.filteredItems).toHaveLength(1) wrapper.setProps({ noFilter: true }) await wrapper.vm.$nextTick() expect(wrapper.vm.filteredItems).toHaveLength(2) }) it.skip('should hide menu when no data', async () => { const wrapper = mountFunction() const input = wrapper.find('input') const element = input.element as HTMLInputElement input.trigger('focus') element.value = 'foo' input.trigger('input') expect(wrapper.vm.menuCanShow).toBe(true) wrapper.setProps({ hideNoData: true }) await wrapper.vm.$nextTick() expect(wrapper.vm.menuCanShow).toBe(false) wrapper.setProps({ hideNoData: false }) await wrapper.vm.$nextTick() expect(wrapper.vm.menuCanShow).toBe(true) // If we are hiding selected // filtered will have a positive length // but the hidden items will not show // check to make sure when all values are // selected to close the menu wrapper.setProps({ hideNoData: true, hideSelected: true, items: [1, 2, 3, 4], multiple: true, value: [1, 2, 3], }) await wrapper.vm.$nextTick() expect(wrapper.vm.menuCanShow).toBe(true) wrapper.setProps({ value: [1, 2, 3, 4] }) await wrapper.vm.$nextTick() expect(wrapper.vm.menuCanShow).toBe(false) }) it('should not hide menu when no data but has no-data slot', async () => { const wrapper = mountFunction({ propsData: { combobox: true, }, slots: { 'no-data': [compileToFunctions('<span>show me</span>')], }, }) const input = wrapper.find('input') input.trigger('focus') await wrapper.vm.$nextTick() expect(wrapper.vm.menuCanShow).toBe(true) }) // https://github.com/vuetifyjs/vuetify/issues/2834 it('should not update search if selectedIndex is > -1', () => { const wrapper = mountFunction() const input = wrapper.find('input') const element = input.element as HTMLInputElement input.trigger('focus') element.value = 'foo' input.trigger('input') expect(wrapper.vm.internalSearch).toBe('foo') wrapper.setData({ lazySearch: '', selectedIndex: 0, }) expect(wrapper.vm.internalSearch).toBe('') element.value = 'bar' input.trigger('input') expect(wrapper.vm.internalSearch).toBe('') }) it('should clear search input on clear callback', async () => { const wrapper = mountFunction({ propsData: { clearable: true, items: ['foo'], value: 'foo', }, }) const icon = wrapper.find('.v-input__append-inner .v-icon') const input = wrapper.find('input') const element = input.element as HTMLInputElement element.value = 'foobar' input.trigger('input') expect(wrapper.vm.internalSearch).toBe('foobar') icon.trigger('click') expect(wrapper.vm.internalSearch).toBeUndefined() }) it('should propagate content class', () => { const wrapper = mountFunction({ propsData: { menuProps: { contentClass: 'foobar', eager: true }, }, }) const content = wrapper.find('.v-autocomplete__content') expect(content.element.classList.contains('foobar')).toBe(true) }) // TODO: this fails without sync, nextTick doesn't help // https://github.com/vuejs/vue-test-utils/issues/1130 it.skip('should update the displayed value when items changes', async () => { const wrapper = mountFunction({ propsData: { value: 1, items: [], }, }) const input = wrapper.find('input') const element = input.element as HTMLInputElement await wrapper.vm.$nextTick() wrapper.setProps({ items: [{ text: 'foo', value: 1 }] }) await wrapper.vm.$nextTick() expect(element.value).toBe('foo') }) // TODO: this fails without sync, nextTick doesn't help // https://github.com/vuejs/vue-test-utils/issues/1130 it.skip('should show menu when items are added for the first time and hide-no-data is enabled', async () => { const wrapper = mountFunction({ propsData: { hideNoData: true, items: [], }, }) const input = wrapper.find('input') input.trigger('focus') expect(wrapper.vm.isMenuActive).toBe(false) expect(wrapper.vm.isFocused).toBe(true) wrapper.setProps({ items: ['Foo', 'Bar'], }) await wrapper.vm.$nextTick() expect(wrapper.vm.isMenuActive).toBe(true) }) it('should not show menu when items are updated and hide-no-data is enabled', async () => { const wrapper = mountFunction({ propsData: { hideNoData: true, items: ['Something first'], }, }) const input = wrapper.find('input') input.trigger('focus') expect(wrapper.vm.isMenuActive).toBe(false) expect(wrapper.vm.isFocused).toBe(true) wrapper.setProps({ items: ['Foo', 'Bar'], }) await wrapper.vm.$nextTick() expect(wrapper.vm.isMenuActive).toBe(false) }) // https://github.com/vuetifyjs/vuetify/issues/5110 // TODO: this fails without sync, nextTick doesn't help // https://github.com/vuejs/vue-test-utils/issues/1130 it.skip('should set internal search', async () => { const wrapper = mountFunction({ propsData: { value: undefined, items: [0, 1, 2], }, }) // Initial value expect(wrapper.vm.internalSearch).toBeUndefined() wrapper.vm.setSearch() await wrapper.vm.$nextTick() // !this.selectedItem expect(wrapper.vm.internalSearch).toBeNull() wrapper.setData({ internalSearch: undefined }) wrapper.setProps({ multiple: true, value: 1 }) await wrapper.vm.$nextTick() expect(wrapper.vm.selectedItems).toHaveLength(1) wrapper.vm.setSearch() await wrapper.vm.$nextTick() // this.multiple expect(wrapper.vm.internalSearch).toBeNull() wrapper.setData({ internalSearch: undefined }) wrapper.setProps({ multiple: false, value: 0 }) await wrapper.vm.$nextTick() expect(wrapper.vm.internalSearch).toBe(0) }) it('should auto select first', async () => { const wrapper = mountFunction({ propsData: { autoSelectFirst: true, items: [ 'foo', 'foobar', 'bar', ], }, }) await wrapper.vm.$nextTick() const input = wrapper.find('input') const element = input.element as HTMLInputElement input.trigger('focus') element.value = 'fo' input.trigger('input') input.trigger('keydown.enter') await wrapper.vm.$nextTick() expect(wrapper.vm.getMenuIndex()).toBe(0) }) // https://github.com/vuetifyjs/vuetify/issues/4580 it('should display menu when hide-no-date and hide-selected are enabled and selected item does not match search', async () => { const wrapper = mountFunction({ propsData: { items: [1, 2], value: 1, hideNoData: true, hideSelected: true, }, }) const input = wrapper.find('input') const element = input.element as HTMLInputElement input.trigger('focus') await wrapper.vm.$nextTick() element.value = '2' input.trigger('input') await wrapper.vm.$nextTick() expect(wrapper.vm.menuCanShow).toBe(true) }) it('should retain search value when item selected and multiple is enabled', async () => { const wrapper = mountFunction({ propsData: { items: ['Sandra Adams', 'Ali Connors', 'Trevor Hansen', 'Tucker Smith'], multiple: true, }, }) await wrapper.vm.$nextTick() const input = wrapper.find('input') const element = input.element as HTMLInputElement input.trigger('focus') element.value = 't' input.trigger('input') wrapper.vm.selectItem('Trevor Hansen') await wrapper.vm.$nextTick() expect(wrapper.vm.selectedItems).toHaveLength(1) expect(wrapper.vm.internalSearch).toBe('t') }) it('should update render dynamically when itemText changes', async () => { const wrapper = mountFunction({ propsData: { returnObject: true, itemText: 'labels.1033', items: [ { id: 1, labels: { 1033: 'ID 1 English', 1036: 'ID 1 French' }, }, { id: 2, labels: { 1033: 'ID 2 English', 1036: 'ID 2 French' }, }, ], }, }) await wrapper.vm.$nextTick() wrapper.vm.selectItem(wrapper.vm.items[0]) await wrapper.vm.$nextTick() expect(wrapper.vm.internalSearch).toEqual('ID 1 English') wrapper.setProps({ itemText: 'labels.1036' }) await wrapper.vm.$nextTick() expect(wrapper.vm.computedItems).toHaveLength(2) expect(wrapper.vm.internalSearch).toEqual('ID 1 French') }) it('should not replicate html select hotkeys in v-autocomplete', async () => { const onKeyPress = jest.fn() const wrapper = mountFunction({ propsData: { items: ['aaa', 'foo', 'faa'], }, methods: { onKeyPress }, }) const input = wrapper.find('input') input.trigger('focus') await wrapper.vm.$nextTick() input.trigger('keypress', { key: 'f' }) await wrapper.vm.$nextTick() expect(onKeyPress).not.toHaveBeenCalled() }) })