@coreui/vue-pro
Version:
UI Components Library for Vue.js
368 lines (312 loc) • 10.2 kB
text/typescript
import { mount, flushPromises } from '@vue/test-utils'
import { h } from 'vue'
import { CAutocompleteOptions } from '../CAutocompleteOptions'
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('CAutocompleteOptions', () => {
test('loads and displays CAutocompleteOptions component', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: null,
},
})
expect(wrapper.html()).toMatchSnapshot()
})
test('CAutocompleteOptions renders all options', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: null,
},
})
expect(wrapper.text()).toContain('Apple')
expect(wrapper.text()).toContain('Banana')
expect(wrapper.text()).toContain('Cherry')
expect(wrapper.text()).toContain('Date')
})
test('CAutocompleteOptions renders option groups', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptionsWithGroups,
selected: null,
},
})
expect(wrapper.text()).toContain('Fruits')
expect(wrapper.text()).toContain('Vegetables')
expect(wrapper.text()).toContain('Apple')
expect(wrapper.text()).toContain('Carrot')
})
test('CAutocompleteOptions marks selected option', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: mockOptions[0],
},
})
const selectedOption = wrapper.find('.autocomplete-option.selected')
expect(selectedOption.exists()).toBe(true)
expect(selectedOption.text()).toContain('Apple')
})
test('CAutocompleteOptions calls onOptionClick when option clicked', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: null,
},
})
const option = wrapper.find('.autocomplete-option')
await option.trigger('click')
await flushPromises()
expect(wrapper.emitted('optionClick')).toBeTruthy()
expect(wrapper.emitted('optionClick')![0]).toEqual([mockOptions[0]])
})
test('CAutocompleteOptions handles Enter key press', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: null,
},
})
const option = wrapper.find('.autocomplete-option')
await option.trigger('keydown', { key: 'Enter' })
await flushPromises()
expect(wrapper.emitted('optionClick')).toBeTruthy()
expect(wrapper.emitted('optionClick')![0]).toEqual([mockOptions[0]])
})
test('CAutocompleteOptions handles Space key press', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: null,
},
})
const option = wrapper.find('.autocomplete-option')
await option.trigger('keydown', { code: 'Space' })
await flushPromises()
expect(wrapper.emitted('optionClick')).toBeTruthy()
expect(wrapper.emitted('optionClick')![0]).toEqual([mockOptions[0]])
})
test('CAutocompleteOptions navigates with arrow keys', async () => {
// Mock the DOM navigation functions
const mockGetNextSibling = vi.fn().mockReturnValue({
focus: vi.fn(),
})
// Mock the utils import
vi.mock('../../utils', () => ({
getNextSibling: mockGetNextSibling,
getPreviousSibling: vi.fn(),
}))
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: null,
},
attachTo: document.body,
})
const firstOption = wrapper.find('.autocomplete-option')
await firstOption.trigger('keydown', { key: 'ArrowDown' })
expect(mockGetNextSibling).toHaveBeenCalled()
})
test('CAutocompleteOptions shows no results message', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: [],
selected: null,
searchNoResultsLabel: 'No options found',
},
})
expect(wrapper.text()).toContain('No options found')
expect(wrapper.find('.autocomplete-options-empty').exists()).toBe(true)
})
test('CAutocompleteOptions highlights search matches', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: null,
highlightOptionsOnSearch: true,
searchValue: 'app',
},
})
const option = wrapper.find('.autocomplete-option')
expect(option.exists()).toBe(true)
// Check if the option contains highlighted content
expect(option.html()).toContain('Apple')
})
test('CAutocompleteOptions uses custom option template', async () => {
const customTemplate = (option: any) =>
h('div', { class: 'custom-option' }, `${option.label} - ${option.value}`)
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: null,
optionsTemplate: customTemplate,
},
})
expect(wrapper.text()).toContain('Apple - 1')
expect(wrapper.text()).toContain('Banana - 2')
})
test('CAutocompleteOptions uses custom group template', async () => {
const customGroupTemplate = (group: any) =>
h('div', { class: 'custom-group' }, group.label.toUpperCase())
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptionsWithGroups,
selected: null,
optionsGroupsTemplate: customGroupTemplate,
},
})
expect(wrapper.text()).toContain('FRUITS')
expect(wrapper.text()).toContain('VEGETABLES')
})
test('CAutocompleteOptions shows loading state', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: null,
loading: true,
},
global: {
stubs: {
CElementCover: true,
},
},
})
expect(wrapper.findComponent({ name: 'CElementCover' }).exists()).toBe(true)
})
test('CAutocompleteOptions renders with virtual scroller', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: null,
virtualScroller: true,
visibleItems: 2,
},
global: {
stubs: {
CVirtualScroller: true,
},
},
})
expect(wrapper.findComponent({ name: 'CVirtualScroller' }).exists()).toBe(true)
})
test('CAutocompleteOptions sets max height', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: null,
optionsMaxHeight: 200,
},
})
const optionsContainer = wrapper.find('.autocomplete-options')
expect(optionsContainer.attributes('style')).toContain('max-height: 200px')
})
test('CAutocompleteOptions marks disabled options', async () => {
const optionsWithDisabled = [
{ label: 'Apple', value: 1 },
{ label: 'Banana', value: 2, disabled: true },
]
const wrapper = mount(CAutocompleteOptions, {
props: {
options: optionsWithDisabled,
selected: null,
},
})
const disabledOption = wrapper.find('.autocomplete-option.disabled')
expect(disabledOption.exists()).toBe(true)
expect(disabledOption.text()).toContain('Banana')
})
test('CAutocompleteOptions has correct accessibility attributes', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mockOptions,
selected: null,
},
})
const listbox = wrapper.find('[role="listbox"]')
expect(listbox.exists()).toBe(true)
const options = wrapper.findAll('.autocomplete-option')
expect(options).toHaveLength(4)
options.forEach((option) => {
expect(option.attributes('tabindex')).toBe('0')
})
})
test('CAutocompleteOptions handles string options', async () => {
const stringOptions = ['Apple', 'Banana', 'Cherry']
const wrapper = mount(CAutocompleteOptions, {
props: {
options: stringOptions,
selected: null,
},
})
expect(wrapper.text()).toContain('Apple')
expect(wrapper.text()).toContain('Banana')
expect(wrapper.text()).toContain('Cherry')
})
test('CAutocompleteOptions handles mixed option types', async () => {
const mixedOptions = [
'Simple String',
{ label: 'Object Option', value: 1 },
{
label: 'Group',
options: [
{ label: 'Grouped Option', value: 2 },
],
},
]
const wrapper = mount(CAutocompleteOptions, {
props: {
options: mixedOptions,
selected: null,
},
})
expect(wrapper.text()).toContain('Simple String')
expect(wrapper.text()).toContain('Object Option')
expect(wrapper.text()).toContain('Group')
expect(wrapper.text()).toContain('Grouped Option')
})
test('CAutocompleteOptions emits optionClick for all option types', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: ['String Option'],
selected: null,
},
})
const option = wrapper.find('.autocomplete-option')
await option.trigger('click')
await flushPromises()
expect(wrapper.emitted('optionClick')).toBeTruthy()
expect(wrapper.emitted('optionClick')![0]).toEqual(['String Option'])
})
test('CAutocompleteOptions handles empty searchNoResultsLabel correctly', async () => {
const wrapper = mount(CAutocompleteOptions, {
props: {
options: [],
selected: null,
searchNoResultsLabel: false,
},
})
expect(wrapper.find('.autocomplete-options-empty').exists()).toBe(true)
expect(wrapper.find('.autocomplete-options-empty').text()).toBe('false')
})
})