UNPKG

@coreui/vue-pro

Version:

UI Components Library for Vue.js

429 lines (355 loc) 11.9 kB
import { mount, flushPromises } from '@vue/test-utils' import { nextTick } from 'vue' import { CAutocomplete } from '../CAutocomplete' const mockOptions = [ { label: 'Apple', value: 1 }, { label: 'Banana', value: 2 }, { label: 'Cherry', value: 3 }, { label: 'Date', value: 4 }, ] const mockOptionsWithGroups = [ { label: 'Fruits', options: [ { label: 'Apple', value: 1 }, { label: 'Banana', value: 2 }, ], }, { label: 'Vegetables', options: [ { label: 'Carrot', value: 3 }, { label: 'Spinach', value: 4 }, ], }, ] describe('CAutocomplete', () => { test('loads and displays CAutocomplete component', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, }, }) expect(wrapper.html()).toMatchSnapshot() }) test('CAutocomplete customize', async () => { const wrapper = mount(CAutocomplete, { props: { className: 'bazinga', disabled: true, size: 'lg', placeholder: 'Select option', options: mockOptions, cleaner: true, indicator: true, }, }) expect(wrapper.html()).toMatchSnapshot() expect(wrapper.find('.autocomplete').classes()).toContain('bazinga') expect(wrapper.find('.autocomplete').classes()).toContain('autocomplete-lg') expect(wrapper.find('.autocomplete').classes()).toContain('disabled') }) test('CAutocomplete renders input with placeholder', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, placeholder: 'Type to search...', }, }) const input = wrapper.find('input[role="combobox"]') expect(input.attributes('placeholder')).toBe('Type to search...') }) test('CAutocomplete opens dropdown on input click', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, }, }) const input = wrapper.find('input[role="combobox"]') await input.trigger('click') await flushPromises() const listbox = wrapper.find('[role="listbox"]') expect(listbox.exists()).toBe(true) expect(wrapper.find('.autocomplete').classes()).toContain('show') }) test('CAutocomplete filters options on input change', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, }, }) const input = wrapper.find('input[role="combobox"]') await input.setValue('app') await input.trigger('input') await flushPromises() expect(wrapper.text()).toContain('Apple') expect(wrapper.text()).not.toContain('Banana') }) test('CAutocomplete selects option on click', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, }, }) const input = wrapper.find('input[role="combobox"]') await input.trigger('click') await flushPromises() const option = wrapper.find('.autocomplete-option') await option.trigger('click') await flushPromises() expect(wrapper.emitted('change')).toBeTruthy() expect(wrapper.emitted('change')![0]).toEqual([mockOptions[0]]) }) test('CAutocomplete selects option on Enter key', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, }, }) const input = wrapper.find('input[role="combobox"]') await input.setValue('Apple') await input.trigger('input') await input.trigger('keydown', { key: 'Enter' }) await flushPromises() expect(wrapper.emitted('change')).toBeTruthy() expect(wrapper.emitted('change')![0]).toEqual([mockOptions[0]]) }) test('CAutocomplete closes dropdown on Escape key', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, }, }) const input = wrapper.find('input[role="combobox"]') await input.trigger('click') await flushPromises() expect(wrapper.find('.autocomplete').classes()).toContain('show') await input.trigger('keydown', { key: 'Escape' }) await flushPromises() expect(input.attributes('aria-expanded')).toBe('false') expect(wrapper.find('.autocomplete').classes()).not.toContain('show') }) test('CAutocomplete navigates options with arrow keys', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, }, attachTo: document.body, }) const input = wrapper.find('input[role="combobox"]') await input.trigger('click') await flushPromises() expect(wrapper.find('[role="listbox"]').exists()).toBe(true) await input.trigger('keydown', { key: 'ArrowDown' }) await nextTick() const firstOption = wrapper.find('.autocomplete-option') expect(firstOption.exists()).toBe(true) }) test('CAutocomplete shows cleaner button when option selected', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, cleaner: true, value: 1, }, }) await flushPromises() const cleanerButton = wrapper.find('.autocomplete-cleaner') expect(cleanerButton.exists()).toBe(true) }) test('CAutocomplete clears selection when cleaner clicked', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, cleaner: true, value: 1, }, }) await flushPromises() const cleanerButton = wrapper.find('.autocomplete-cleaner') await cleanerButton.trigger('click') await flushPromises() expect(wrapper.emitted('change')).toBeTruthy() expect(wrapper.emitted('change')![0]).toEqual([null]) }) test('CAutocomplete shows no results message', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, searchNoResultsLabel: 'No options found', }, }) const input = wrapper.find('input[role="combobox"]') await input.setValue('xyz') await input.trigger('input') await flushPromises() expect(wrapper.text()).toContain('No options found') }) test('CAutocomplete renders option groups', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptionsWithGroups, }, }) const input = wrapper.find('input[role="combobox"]') await input.trigger('click') await flushPromises() expect(wrapper.text()).toContain('Fruits') expect(wrapper.text()).toContain('Vegetables') expect(wrapper.text()).toContain('Apple') expect(wrapper.text()).toContain('Carrot') }) test('CAutocomplete shows hint when enabled', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, showHints: true, }, }) const input = wrapper.find('input[role="combobox"]') await input.setValue('ap') await input.trigger('input') await flushPromises() const hintInput = wrapper.find('.autocomplete-input-hint') expect(hintInput.exists()).toBe(true) }) test('CAutocomplete allows custom values when allowOnlyDefinedOptions is false', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, allowOnlyDefinedOptions: false, }, }) const input = wrapper.find('input[role="combobox"]') await input.setValue('Custom Value') await input.trigger('input') await input.trigger('keydown', { key: 'Enter' }) await flushPromises() expect(wrapper.emitted('change')).toBeTruthy() expect(wrapper.emitted('change')![0]).toEqual(['Custom Value']) }) test('CAutocomplete prevents custom values when allowOnlyDefinedOptions is true', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, allowOnlyDefinedOptions: true, }, }) const input = wrapper.find('input[role="combobox"]') await input.setValue('Custom Value') await input.trigger('input') await input.trigger('keydown', { key: 'Enter' }) await flushPromises() expect(wrapper.emitted('change')).toBeFalsy() }) test('CAutocomplete highlights search matches', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, highlightOptionsOnSearch: true, }, }) const input = wrapper.find('input[role="combobox"]') await input.setValue('app') await input.trigger('input') await flushPromises() const option = wrapper.find('.autocomplete-option') expect(option.exists()).toBe(true) }) test('CAutocomplete is disabled when disabled prop is true', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, disabled: true, }, }) const input = wrapper.find('input[role="combobox"]') expect(input.attributes('disabled')).toBeDefined() }) test('CAutocomplete is readonly when readOnly prop is true', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, readOnly: true, }, }) const input = wrapper.find('input[role="combobox"]') expect(input.attributes('readonly')).toBeDefined() }) test('CAutocomplete emits input event on search', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, }, }) const input = wrapper.find('input[role="combobox"]') await input.setValue('test') await input.trigger('input') await flushPromises() expect(wrapper.emitted('input')).toBeTruthy() expect(wrapper.emitted('input')![0]).toEqual(['test']) }) test('CAutocomplete emits show and hide events', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, }, }) const input = wrapper.find('input[role="combobox"]') // Test show event await input.trigger('click') await flushPromises() expect(wrapper.emitted('show')).toBeTruthy() // Test hide event await input.trigger('keydown', { key: 'Escape' }) await flushPromises() expect(wrapper.emitted('hide')).toBeTruthy() }) test('CAutocomplete handles string options correctly', async () => { const stringOptions = ['Apple', 'Banana', 'Cherry'] const wrapper = mount(CAutocomplete, { props: { options: stringOptions, }, }) const input = wrapper.find('input[role="combobox"]') await input.trigger('click') await flushPromises() expect(wrapper.text()).toContain('Apple') expect(wrapper.text()).toContain('Banana') expect(wrapper.text()).toContain('Cherry') }) test('CAutocomplete handles virtual scroller', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, virtualScroller: true, visibleItems: 2, }, }) const input = wrapper.find('input[role="combobox"]') await input.trigger('click') await flushPromises() expect(wrapper.find('[role="listbox"]').exists()).toBe(true) }) test('CAutocomplete clears search on select when clearSearchOnSelect is true', async () => { const wrapper = mount(CAutocomplete, { props: { options: mockOptions, clearSearchOnSelect: true, }, }) const input = wrapper.find('input[role="combobox"]') await input.setValue('app') await input.trigger('input') await input.trigger('click') await flushPromises() const option = wrapper.find('.autocomplete-option') await option.trigger('click') await flushPromises() expect(wrapper.emitted('input')).toBeTruthy() // Should emit empty string when clearing search const inputEvents = wrapper.emitted('input') as string[][] expect(inputEvents[inputEvents.length - 1]).toEqual(['']) }) })