import { elementUpdated, fixture, html } from '@open-wc/testing-helpers'
import { describe, expect, it, vi } from 'vitest'
import './UsSelect'
import '../../list/UsList'
import type { UsSelect } from './UsSelect'
describe('UsSelect', () => {
let select: UsSelect
const mockHandleSelectChange = vi.fn(e => e)
const getListItems = () => {
const list = select.shadowRoot?.querySelector('us-list')
const listItems = list?.shadowRoot?.querySelectorAll('ul > li.list-item')
return listItems || []
}
const options = [
{ id: '1', label: 'Option 1', value: 'option-1', checked: false, originalValue: 'option-1' },
{ id: '2', label: 'Option 2', value: 'option-2', checked: false, originalValue: 'option-2' },
]
beforeEach(async () => {
select = await fixture(html``)
})
it('should be defined', () => {
expect(select).to.exist
expect(select.tagName).to.equal('US-SELECT')
})
it('should have correct initial properties', async () => {
expect(select.options).toEqual([])
expect(select.placeholder).toEqual('')
expect(select.disabled).toBe(false)
expect(select.required).toBe(false)
expect(select.multiple).toBe(false)
expect(select.filterable).toBe(false)
expect(select.emitSearch).toBe(false)
expect(select.label).toBe('')
expect(select.propertyLabel).toBe('')
expect(select.propertyValue).toBe('')
expect(select.filterDebounce).toBe(0)
expect(select.showTitle).toBe(false)
expect(select.openAbove).toBe(false)
expect(select.filterableProperty).toBe('value')
expect(select.selectedValue).toBeNull()
expect(select.heightList).toBe('235')
expect(select.ariaLabel).toBe('aria-label')
expect(select.dataTestId).toBe('select')
})
it('should update options correctly', async () => {
select.options = options
await elementUpdated(select)
expect(select.options).toEqual(options)
})
it('should update properties correctly', async () => {
const placeholder = 'Select an option'
const disabled = true
const required = true
const multiple = true
const filterable = true
const emitSearch = true
const label = 'Select Label'
const propertyLabel = 'label'
const propertyValue = 'value'
const filterDebounce = 500
const showTitle = true
const openAbove = true
const filterableProperty = 'label'
const heightList = '300'
const ariaLabel = 'test-aria'
const dataTestId = 'select2'
select.placeholder = placeholder
select.disabled = disabled
select.required = required
select.multiple = multiple
select.filterable = filterable
select.emitSearch = emitSearch
select.label = label
select.propertyLabel = propertyLabel
select.propertyValue = propertyValue
select.filterDebounce = filterDebounce
select.showTitle = showTitle
select.openAbove = openAbove
select.filterableProperty = filterableProperty
select.heightList = heightList
select.ariaLabel = ariaLabel
select.dataTestId = dataTestId
await elementUpdated(select)
expect(select.placeholder).toEqual(placeholder)
expect(select.disabled).toEqual(disabled)
expect(select.required).toEqual(required)
expect(select.multiple).toEqual(multiple)
expect(select.filterable).toEqual(filterable)
expect(select.emitSearch).toEqual(emitSearch)
expect(select.label).toEqual(label)
expect(select.propertyLabel).toEqual(propertyLabel)
expect(select.propertyValue).toEqual(propertyValue)
expect(select.filterDebounce).toEqual(filterDebounce)
expect(select.showTitle).toEqual(showTitle)
expect(select.openAbove).toEqual(openAbove)
expect(select.filterableProperty).toEqual(filterableProperty)
expect(select.heightList).toEqual(heightList)
expect(select.ariaLabel).toEqual(ariaLabel)
expect(select.dataTestId).toEqual(dataTestId)
})
it('should set selected value correctly', async () => {
const selectedValue = options[1]
select.selectedValue = selectedValue
await select.updateComplete
expect(select.selectedItem).toEqual(selectedValue)
})
it('should handle multiple selection', async () => {
select.options = options
select.multiple = true
select.showListItems()
await select.updateComplete
const listItems = getListItems()
listItems?.forEach((item, index) => index > 0 && item.click())
expect(select.selectedItems.length).toBe(2)
expect(select.selectedItems[0]).toEqual(options[1])
expect(select.selectedItems[1]).toEqual(options[2])
})
it('should filter options correctly', async () => {
select.options = options
select.filterable = true
select.filterableProperty = 'label'
select.inputValue = '2'
await select.updateComplete
const listItems = getListItems()
expect(listItems?.length).toBe(1)
expect(listItems[0].innerText.trim()).toContain('Option 2')
})
it('should validate correctly', async () => {
select.options = options
select.required = true
select.showListItems() // open options list
select.showListItems() // close options list
await select.updateComplete
const isValid = select.isValid
expect(isValid).toBe(false)
select.showListItems() // open options list
select.selectedItem = options[0]
select.showListItems() // close options list
await select.updateComplete
const updatedIsValid = select.isValid
expect(updatedIsValid).toBe(true)
})
it('should fire change event correctly', async () => {
select.options = options
select.showListItems()
select.addEventListener('change', (e: any) => mockHandleSelectChange(e))
await select.updateComplete
const listItems = getListItems()
listItems[1].click()
await select.updateComplete
expect(mockHandleSelectChange).toHaveBeenCalled()
})
})