mirror of
https://github.com/element-plus/element-plus.git
synced 2025-08-17 21:32:51 +08:00
291 lines
8.8 KiB
TypeScript
291 lines
8.8 KiB
TypeScript
import { nextTick, ref } from 'vue'
|
|
import { mount } from '@vue/test-utils'
|
|
import { afterEach, describe, expect, it } from 'vitest'
|
|
import dayjs from 'dayjs'
|
|
import customParseFormat from 'dayjs/plugin/customParseFormat.js'
|
|
import Select from '@element-plus/components/select'
|
|
import { ElFormItem } from '@element-plus/components/form'
|
|
import TimeSelect from '../src/time-select.vue'
|
|
|
|
dayjs.extend(customParseFormat)
|
|
|
|
const { Option } = Select
|
|
|
|
afterEach(() => {
|
|
document.documentElement.innerHTML = ''
|
|
})
|
|
|
|
const WRAPPER_CLASS_NAME = 'el-select__wrapper'
|
|
const PLACEHOLDER_CLASS_NAME = 'el-select__placeholder'
|
|
|
|
describe('TimeSelect', () => {
|
|
it('create', async () => {
|
|
const wrapper = mount(() => (
|
|
<TimeSelect style={{ color: 'red' }} class="customClass" />
|
|
))
|
|
|
|
const outerInput = wrapper.find('.el-select')
|
|
expect(outerInput.classes()).toContain('customClass')
|
|
expect(outerInput.attributes().style).toBeDefined()
|
|
})
|
|
|
|
it('set default value', async () => {
|
|
const value = ref('14:30')
|
|
const wrapper = mount(() => <TimeSelect v-model={value.value} />)
|
|
|
|
const input = wrapper.find('input')
|
|
input.trigger('blur')
|
|
input.trigger('focus')
|
|
await nextTick()
|
|
expect(document.querySelector('.is-selected')).toBeDefined()
|
|
expect(document.querySelector('.is-selected')?.textContent).toBe('14:30')
|
|
})
|
|
|
|
it('set minTime', async () => {
|
|
const wrapper = mount(() => <TimeSelect minTime="14:30" />)
|
|
|
|
const input = wrapper.find('input')
|
|
input.trigger('blur')
|
|
input.trigger('focus')
|
|
await nextTick()
|
|
const elms = document.querySelectorAll('.is-disabled')
|
|
const elm = elms[elms.length - 1]
|
|
expect(elm.textContent).toBe('14:30')
|
|
})
|
|
|
|
it('set maxTime', async () => {
|
|
const wrapper = mount(() => <TimeSelect maxTime="14:30" />)
|
|
|
|
const input = wrapper.find('input')
|
|
input.trigger('blur')
|
|
input.trigger('focus')
|
|
await nextTick()
|
|
const elm = document.querySelector('.is-disabled')
|
|
expect(elm?.textContent).toBe('14:30')
|
|
})
|
|
|
|
it('set value update', async () => {
|
|
const value = ref('10:00')
|
|
const wrapper = mount(() => <TimeSelect v-model={value.value} />)
|
|
|
|
await nextTick()
|
|
const input = wrapper.find('input')
|
|
|
|
expect(input.exists()).toBe(true)
|
|
expect(wrapper.find(`.${PLACEHOLDER_CLASS_NAME}`).text()).toBe('10:00')
|
|
|
|
value.value = '10:30'
|
|
await nextTick()
|
|
|
|
expect(wrapper.findComponent({ name: 'ElTimeSelect' }).vm.value).toBe(
|
|
'10:30'
|
|
)
|
|
expect(wrapper.find(`.${PLACEHOLDER_CLASS_NAME}`).text()).toBe('10:30')
|
|
})
|
|
|
|
it('update value', async () => {
|
|
const value = ref('10:00')
|
|
const wrapper = mount(() => <TimeSelect v-model={value.value} />)
|
|
|
|
await nextTick()
|
|
const vm = wrapper.findComponent({ name: 'ElTimeSelect' }).vm
|
|
expect(vm.value).toBe('10:00')
|
|
expect(wrapper.find(`.${PLACEHOLDER_CLASS_NAME}`).text()).toBe('10:00')
|
|
|
|
const option = wrapper
|
|
.findAllComponents(Option)
|
|
.find((w) => w.text().trim() === '11:00')
|
|
|
|
expect(option?.exists()).toBe(true)
|
|
option?.trigger('click')
|
|
await nextTick()
|
|
expect(vm.value).toBe('11:00')
|
|
expect(wrapper.find(`.${PLACEHOLDER_CLASS_NAME}`).text()).toBe('11:00')
|
|
})
|
|
|
|
it('set disabled', async () => {
|
|
const value = ref('10:00')
|
|
const disabled = ref(false)
|
|
const wrapper = mount(() => (
|
|
<TimeSelect v-model={value.value} disabled={disabled.value} />
|
|
))
|
|
|
|
const select = wrapper.findComponent({ name: 'ElSelect' })
|
|
expect(select.props().disabled).toBe(false)
|
|
|
|
disabled.value = true
|
|
await nextTick()
|
|
expect(select.props().disabled).toBe(true)
|
|
})
|
|
|
|
it('set editable', async () => {
|
|
const value = ref('10:00')
|
|
const editable = ref(false)
|
|
const wrapper = mount(() => (
|
|
<TimeSelect v-model={value.value} editable={editable.value} />
|
|
))
|
|
|
|
const select = wrapper.findComponent({ name: 'ElSelect' })
|
|
expect(select.props().filterable).toBe(false)
|
|
|
|
editable.value = true
|
|
await nextTick()
|
|
expect(select.props().filterable).toBe(true)
|
|
})
|
|
|
|
it('should include end time', async () => {
|
|
const wrapper = mount(() => (
|
|
<TimeSelect
|
|
start="00:00"
|
|
step="00:05"
|
|
end="23:59"
|
|
includeEndTime={true}
|
|
/>
|
|
))
|
|
const select = wrapper.findComponent({ name: 'ElTimeSelect' })
|
|
const input = wrapper.find('input')
|
|
await input.trigger('click')
|
|
const items = document.querySelectorAll('.el-select-dropdown__item>span')
|
|
|
|
expect(select.props().includeEndTime).toBe(true)
|
|
expect(items).toHaveLength(289)
|
|
expect([...items].at(-1)?.textContent).toBe('23:59')
|
|
})
|
|
|
|
it('should not include end time', async () => {
|
|
const wrapper = mount(() => (
|
|
<TimeSelect start="00:00" step="00:05" end="23:59" />
|
|
))
|
|
const select = wrapper.findComponent({ name: 'ElTimeSelect' })
|
|
const input = wrapper.find('input')
|
|
await input.trigger('click')
|
|
const items = document.querySelectorAll('.el-select-dropdown__item>span')
|
|
|
|
expect(select.props().includeEndTime).toBe(false)
|
|
expect(items).toHaveLength(288)
|
|
expect([...items].at(-1)?.textContent).toBe('23:55')
|
|
})
|
|
|
|
it('should include end whenever includeEndTime is false', async () => {
|
|
const wrapper = mount(() => (
|
|
<TimeSelect start="00:10" end="00:20" step="00:02" />
|
|
))
|
|
const select = wrapper.findComponent({ name: 'ElTimeSelect' })
|
|
const input = wrapper.find('input')
|
|
await input.trigger('click')
|
|
const items = document.querySelectorAll('.el-select-dropdown__item>span')
|
|
|
|
expect(select.props().includeEndTime).toBe(false)
|
|
expect(items).toHaveLength(6)
|
|
expect([...items].at(-1)?.textContent).toBe('00:20')
|
|
})
|
|
|
|
it('ref focus', async () => {
|
|
const wrapper = mount(() => <TimeSelect />, {
|
|
attachTo: document.body,
|
|
})
|
|
|
|
wrapper.findComponent(TimeSelect).vm.$.exposed!.focus()
|
|
const trigger = wrapper.find(`.${WRAPPER_CLASS_NAME}`)
|
|
await trigger.trigger('click')
|
|
|
|
await nextTick()
|
|
await nextTick()
|
|
|
|
const popperEl = document.querySelector('.el-select__popper')
|
|
const attr = popperEl?.getAttribute('aria-hidden')
|
|
expect(attr).toEqual('false')
|
|
})
|
|
|
|
it('ref blur', async () => {
|
|
const wrapper = mount(() => <TimeSelect />, {
|
|
attachTo: document.body,
|
|
})
|
|
|
|
wrapper.findComponent(TimeSelect).vm.$.exposed!.focus()
|
|
await wrapper.findComponent(TimeSelect).trigger('click')
|
|
await nextTick()
|
|
wrapper.findComponent(TimeSelect).vm.$.exposed!.blur()
|
|
|
|
await nextTick()
|
|
await nextTick()
|
|
|
|
const popperEl = document.querySelector('.el-select__popper')
|
|
const attr = popperEl?.getAttribute('aria-hidden')
|
|
expect(attr).toEqual('true')
|
|
})
|
|
|
|
it('set format', async () => {
|
|
const value = ref('')
|
|
const wrapper = mount(() => (
|
|
<TimeSelect
|
|
v-model={value.value}
|
|
start="13:00"
|
|
step="00:30"
|
|
end="13:30"
|
|
format="hh:mm A"
|
|
/>
|
|
))
|
|
|
|
const input = wrapper.find('input')
|
|
await input.trigger('click')
|
|
await nextTick()
|
|
const option = document.querySelector('.el-select-dropdown__item')
|
|
expect(option?.textContent).toBe('01:00 PM')
|
|
})
|
|
|
|
describe('form item accessibility integration', () => {
|
|
it('automatic id attachment', async () => {
|
|
const wrapper = mount(() => (
|
|
<ElFormItem label="Foobar" data-test-ref="item">
|
|
<TimeSelect />
|
|
</ElFormItem>
|
|
))
|
|
|
|
await nextTick()
|
|
const formItem = wrapper.find('[data-test-ref="item"]')
|
|
const formItemLabel = formItem.find('.el-form-item__label')
|
|
const timeSelectInput = wrapper.find('input')
|
|
expect(formItem.attributes().role).toBeFalsy()
|
|
expect(formItemLabel.attributes().for).toBe(
|
|
timeSelectInput.attributes().id
|
|
)
|
|
})
|
|
|
|
it('specified id attachment', async () => {
|
|
const wrapper = mount(() => (
|
|
<ElFormItem label="Foobar" data-test-ref="item">
|
|
<TimeSelect
|
|
// type checking failed as `id` is a fallthrough attribute
|
|
// @ts-ignore
|
|
id="foobar"
|
|
/>
|
|
</ElFormItem>
|
|
))
|
|
|
|
await nextTick()
|
|
const formItem = wrapper.find('[data-test-ref="item"]')
|
|
const formItemLabel = formItem.find('.el-form-item__label')
|
|
const timeSelectInput = wrapper.find('input')
|
|
expect(formItem.attributes().role).toBeFalsy()
|
|
expect(timeSelectInput.attributes().id).toBe('foobar')
|
|
expect(formItemLabel.attributes().for).toBe(
|
|
timeSelectInput.attributes().id
|
|
)
|
|
})
|
|
|
|
it('form item role is group when multiple inputs', async () => {
|
|
const wrapper = mount(() => (
|
|
<ElFormItem label="Foobar" data-test-ref="item">
|
|
<TimeSelect />
|
|
<TimeSelect />
|
|
</ElFormItem>
|
|
))
|
|
|
|
await nextTick()
|
|
const formItem = wrapper.find('[data-test-ref="item"]')
|
|
expect(formItem.attributes().role).toBe('group')
|
|
})
|
|
})
|
|
})
|