// @ts-nocheck import { nextTick } from 'vue' import { mount } from '@vue/test-utils' import { afterEach, describe, expect, it, vi } from 'vitest' import dayjs from 'dayjs' import { rAF } from '@element-plus/test-utils/tick' import ConfigProvider from '@element-plus/components/config-provider' import { CommonPicker } from '@element-plus/components/time-picker' import Input from '@element-plus/components/input' import zhCn from '@element-plus/locale/lang/zh-cn' import enUs from '@element-plus/locale/lang/en' import 'dayjs/locale/zh-cn' import { EVENT_CODE } from '@element-plus/constants' import { ElFormItem } from '@element-plus/components/form' import DatePicker from '../src/date-picker' const _mount = (template: string, data = () => ({}), otherObj?) => mount( { components: { 'el-date-picker': DatePicker, 'el-form-item': ElFormItem, }, template, data, ...otherObj, }, { attachTo: 'body', } ) afterEach(() => { document.documentElement.innerHTML = '' }) const testDatePickerPanelChange = async (type: 'date' | 'daterange') => { let mode const wrapper = _mount( ``, () => ({ value: type === 'daterange' ? [] : '' }), { methods: { onPanelChange(value, _mode) { mode = _mode }, }, } ) const reset = () => { mode = undefined } const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() const prevMonth = document.querySelector('button.arrow-left') const prevYear = document.querySelector('button.d-arrow-left') const nextMonth = document.querySelector('button.arrow-right') const nextYear = document.querySelector('button.d-arrow-right') prevMonth.click() await nextTick() expect(mode).toBe('month') reset() nextMonth.click() await nextTick() expect(mode).toBe('month') reset() prevYear.click() await nextTick() expect(mode).toBe('year') reset() nextYear.click() await nextTick() expect(mode).toBe('year') } describe('DatePicker', () => { it('create & custom class & style', async () => { const popperClassName = 'popper-class-test' const customClassName = 'custom-class-test' const wrapper = _mount( ``, () => ({ popperClassName, customClassName }) ) const input = wrapper.find('input') expect(input.attributes('placeholder')).toBe('test_') expect(input.attributes('readonly')).not.toBeUndefined() const outterInput = wrapper.find('.el-input') expect(outterInput.classes()).toContain(customClassName) expect(outterInput.attributes().style).toBeDefined() input.trigger('blur') input.trigger('focus') await nextTick() expect( document .querySelector('.el-picker__popper') .classList.contains(popperClassName) ).toBe(true) }) it('select date', async () => { const wrapper = _mount( ``, () => ({ value: '' }) ) const date = dayjs() const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() const spans = document.querySelectorAll('.el-date-picker__header-label') const arrowLeftElm = document.querySelector( '.el-date-picker__prev-btn .arrow-left' ) as HTMLElement const arrowRightElm = document.querySelector( '.el-date-picker__next-btn .arrow-right' ) as HTMLElement expect(spans[0].textContent).toContain(date.year()) expect(spans[1].textContent).toContain(date.format('MMMM')) const arrowLeftYeayElm = document.querySelector( '.el-date-picker__prev-btn .d-arrow-left' ) as HTMLElement arrowLeftYeayElm.click() let count = 20 while (--count) { arrowLeftElm.click() } count = 20 while (--count) { arrowRightElm.click() } await nextTick() expect(spans[0].textContent).toContain(date.add(-1, 'year').year()) expect(spans[1].textContent).toContain(date.format('MMMM')) ;(document.querySelector('td.available') as HTMLElement).click() await nextTick() const vm = wrapper.vm as any expect(vm.value).toBeDefined() }) it('defaultTime and clear value', async () => { const wrapper = _mount( ``, () => ({ value: '' }) ) const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() ;(document.querySelector('td.available') as HTMLElement).click() await nextTick() const vm = wrapper.vm as any expect(vm.value).toBeDefined() expect(vm.value.getHours()).toBe(12) expect(vm.value.getMinutes()).toBe(0) expect(vm.value.getSeconds()).toBe(1) const picker = wrapper.findComponent(CommonPicker) ;(picker.vm as any).showClose = true await nextTick() ;(document.querySelector('.clear-icon') as HTMLElement).click() expect(vm.value).toBeNull() }) it('defaultValue', async () => { const wrapper = _mount( ``, () => ({ value: '', defaultValue: new Date(2011, 10, 1), }) ) const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() document.querySelector('td.available').click() await nextTick() const vm = wrapper.vm as any expect(vm.value).toBeDefined() expect(vm.value.getFullYear()).toBe(2011) expect(vm.value.getMonth()).toBe(10) expect(vm.value.getDate()).toBe(1) const picker = wrapper.findComponent(CommonPicker) ;(picker.vm as any).showClose = true await nextTick() document.querySelector('.clear-icon').click() expect(vm.value).toBeNull() vm.defaultValue = new Date(2031, 5, 1) input.trigger('blur') input.trigger('focus') await nextTick() document.querySelector('td.available').click() await nextTick() expect(vm.value).toBeDefined() expect(vm.value.getFullYear()).toBe(2031) expect(vm.value.getMonth()).toBe(5) expect(vm.value.getDate()).toBe(1) }) it('event change, focus, blur, keydown', async () => { const changeHandler = vi.fn() const focusHandler = vi.fn() const blurHandler = vi.fn() const keydownHandler = vi.fn() let onChangeValue: Date | undefined const wrapper = _mount( ``, () => ({ value: new Date(2016, 9, 10, 18, 40) }), { methods: { onChange(e) { onChangeValue = e return changeHandler(e) }, onFocus(e) { return focusHandler(e) }, onBlur(e) { return blurHandler(e) }, onKeydown(e) { return keydownHandler(e) }, }, } ) const input = wrapper.find('input') input.trigger('focus') input.trigger('blur') input.trigger('keydown') await nextTick() await rAF() expect(focusHandler).toHaveBeenCalledTimes(1) expect(blurHandler).toHaveBeenCalledTimes(1) expect(keydownHandler).toHaveBeenCalledTimes(1) input.trigger('focus') await nextTick() ;(document.querySelector('td.available') as HTMLElement).click() await nextTick() await rAF() expect(changeHandler).toHaveBeenCalledTimes(1) expect(onChangeValue?.getTime()).toBe(new Date(2016, 9, 1).getTime()) }) it('emits focus on click when not currently focused', async () => { const focusHandler = vi.fn() const wrapper = _mount( ``, () => ({ value: new Date(2016, 9, 10, 18, 40) }), { methods: { onFocus(e: Event) { return focusHandler(e) }, }, } ) const input = wrapper.find('input') input.trigger('mousedown') input.trigger('focus') await nextTick() await rAF() expect(focusHandler).toHaveBeenCalledTimes(1) }) it('opens popper on click when input is focused', async () => { const wrapper = _mount( ``, () => ({ value: new Date(2016, 9, 10, 18, 40) }) ) const popperEl = document.querySelector('.el-picker__popper') as HTMLElement expect(popperEl.style.display).toBe('none') const input = wrapper.find('input') input.element.focus() input.trigger('mousedown') await nextTick() await rAF() expect(popperEl.style.display).not.toBe('none') }) it('shortcuts', async () => { const text = 'Yesterday' const value = new Date(Date.now() - 86400000) value.setHours(0, 0, 0, 0) const wrapper = _mount( ``, () => ({ value: '', shortcuts: [ { text, value, }, ], }) ) const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() const shortcut = document.querySelector('.el-picker-panel__shortcut') expect(shortcut.textContent).toBe(text) expect(document.querySelector('.el-picker-panel__sidebar')).not.toBeNull() ;(shortcut as HTMLElement).click() await nextTick() const vm = wrapper.vm as any expect(vm.value.valueOf()).toBe(value.valueOf()) }) it('disabledDate', async () => { const wrapper = _mount( ``, () => ({ value: '', disabledDate(time) { return time.getTime() < Date.now() - 8.64e7 }, }) ) const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() expect(document.querySelector('.disabled')).not.toBeNull() }) it('ref focus', async () => { _mount( ``, () => ({ value: '' }), { mounted() { this.$refs.input.focus() }, } ) await nextTick() await rAF() const popperEl = document.querySelector('.el-picker__popper') const attr = popperEl.getAttribute('aria-hidden') expect(attr).toEqual('false') }) it('ref handleOpen', async () => { _mount( ``, () => ({ value: '' }), { mounted() { this.$refs.input.handleOpen() }, } ) await nextTick() const popperEl = document.querySelector('.el-picker__popper') const attr = popperEl.getAttribute('aria-hidden') expect(attr).toEqual('false') }) it('ref handleClose', async () => { vi.useFakeTimers() _mount( ``, () => ({ value: '' }), { mounted() { this.$refs.input.handleOpen() setTimeout(() => { this.$refs.input.handleClose() }, 1000000) }, } ) vi.runAllTimers() await nextTick() const popperEl = document.querySelector('.el-picker__popper') const attr = popperEl.getAttribute('aria-hidden') expect(attr).toEqual('true') vi.useRealTimers() }) it('custom content', async () => { const wrapper = _mount( ` `, () => ({ value: '' }), { mounted() { this.$refs.input.focus() }, } ) await nextTick() const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() { ;(document.querySelector('td.available .cell') as HTMLElement).click() } input.trigger('focus') await nextTick() expect( document.querySelector('td.available .cell').classList.contains('current') ).toBeTruthy() }) it('custom content comment', async () => { _mount( ` `, () => ({ value: '' }), { mounted() { this.$refs.input.focus() }, } ) await nextTick() const el = document.querySelector('td.available .el-date-table-cell') const text = el.textContent expect(text.includes('csw')).toBeFalsy() }) it('custom content value validate', async () => { _mount( ` `, () => ({ value: '' }), { mounted() { this.$refs.input.focus() }, } ) await nextTick() const el = document.querySelector('td.available .cell') const text = el.textContent expect(text.includes('csw')).toBeTruthy() }) it('custom content bail out slot compoent', async () => { _mount( ` `, () => ({ value: '' }), { mounted() { this.$refs.input.focus() }, } ) await nextTick() const el = document.querySelector('td.available') const text = el.textContent expect(!!text).toBeTruthy() }) describe('value-format', () => { it('with literal string', async () => { const day = dayjs() const format = 'YYYY-MM-DD' const valueFormat = '[Element-Plus] DD/MM YYYY' const value = day.format(valueFormat) const wrapper = _mount( ` `, () => { return { value, } }, { methods: { changeValue() { this.value = '[Element-Plus] 31/05 2021' }, }, } ) const vm = wrapper.vm as any const input = wrapper.find('input') await input.trigger('blur') await input.trigger('focus') await nextTick() { ;(document.querySelector('td.available') as HTMLElement).click() } await nextTick() expect(vm.value).toBe( dayjs( `[Element-Plus] 01/${`0${day.month() + 1}`.slice(-2)} ${day.year()}`, valueFormat ).format(valueFormat) ) await wrapper.find('button').trigger('click') await nextTick() expect(wrapper.findComponent(Input).vm.modelValue).toBe('2021-05-31') }) it('with "x"', async () => { const format = 'YYYY/MM/DD' const dateStr = '2021/05/31' const valueFormat = 'x' const value = Date.now() const wrapper = _mount( ` `, () => { return { value, } }, { methods: { changeValue() { this.value = +new Date(dateStr) }, }, } ) const vm = wrapper.vm as any const input = wrapper.find('input') await input.trigger('blur') await input.trigger('focus') await nextTick() ;(document.querySelector('td.available') as HTMLElement).click() await nextTick() expect(vm.value).toBe(+dayjs().startOf('M')) await wrapper.find('button').trigger('click') await nextTick() expect(wrapper.findComponent(Input).vm.modelValue).toBe(dateStr) }) }) }) describe('DatePicker Navigation', () => { let prevMonth, prevYear, nextMonth, nextYear, getYearLabel, getMonthLabel const initNavigationTest = async (value) => { const wrapper = _mount( ``, () => ({ value }) ) const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() prevMonth = document.querySelector('button.arrow-left') prevYear = document.querySelector('button.d-arrow-left') nextMonth = document.querySelector('button.arrow-right') nextYear = document.querySelector('button.d-arrow-right') getYearLabel = () => document.querySelectorAll('.el-date-picker__header-label')[0].textContent getMonthLabel = () => document.querySelectorAll('.el-date-picker__header-label')[1].textContent } it('month, year', async () => { await initNavigationTest(new Date(2000, 0, 1)) expect(getYearLabel()).toContain('2000') expect(getMonthLabel()).toContain('January') prevMonth.click() await nextTick() expect(getYearLabel()).toContain('1999') expect(getMonthLabel()).toContain('December') prevYear.click() await nextTick() expect(getYearLabel()).toContain('1998') expect(getMonthLabel()).toContain('December') nextMonth.click() await nextTick() expect(getYearLabel()).toContain('1999') expect(getMonthLabel()).toContain('January') nextYear.click() await nextTick() expect(getYearLabel()).toContain('2000') expect(getMonthLabel()).toContain('January') }) it('month with fewer dates', async () => { // July has 31 days, June has 30 await initNavigationTest(new Date(2000, 6, 31)) prevMonth.click() await nextTick() expect(getYearLabel()).toContain('2000') expect(getMonthLabel()).toContain('June') }) it('year with fewer Feburary dates', async () => { // Feburary 2008 has 29 days, Feburary 2007 has 28 await initNavigationTest(new Date(2008, 1, 29)) prevYear.click() await nextTick() expect(getYearLabel()).toContain('2007') expect(getMonthLabel()).toContain('February') }) it('month label with fewer dates', async () => { await initNavigationTest(new Date(2000, 6, 31)) const yearLabel = document.querySelectorAll( '.el-date-picker__header-label' )[0] ;(yearLabel as HTMLElement).click() await nextTick() const year1999Label = document.querySelectorAll('.el-year-table td')[1] ;(year1999Label as HTMLElement).click() await nextTick() const juneLabel = document.querySelectorAll('.el-month-table td')[5] ;(juneLabel as HTMLElement).click() await nextTick() expect(getYearLabel()).toContain('2001') expect(getMonthLabel()).toContain('June') const monthLabel = document.querySelectorAll( '.el-date-picker__header-label' )[1] ;(monthLabel as HTMLElement).click() await nextTick() const janLabel = document.querySelectorAll('.el-month-table td')[0] ;(janLabel as HTMLElement).click() await nextTick() expect(getYearLabel()).toContain('2001') expect(getMonthLabel()).toContain('January') }) it('panel change event', async () => { await testDatePickerPanelChange('date') }) }) describe('MonthPicker', () => { it('basic', async () => { const wrapper = _mount( ``, () => ({ value: new Date(2020, 7, 1) }) ) const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() expect( (document.querySelector('.el-month-table') as HTMLElement).style.display ).toBe('') expect(document.querySelector('.el-year-table')).toBeNull() ;(document.querySelector('.el-month-table .cell') as HTMLElement).click() await nextTick() const vm = wrapper.vm as any expect(vm.value.getMonth()).toBe(0) }) it('value-format', async () => { const valueFormat = '[Element-Plus] YYYY.MM' const wrapper = _mount( ` `, () => ({ value: dayjs(new Date(2020, 7, 1)).format(valueFormat) }) ) await nextTick() expect(wrapper.findComponent(Input).vm.modelValue).toBe('2020-08') const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() { ;(document.querySelector('.el-month-table .cell') as HTMLElement).click() } await nextTick() expect(wrapper.findComponent(Input).vm.modelValue).toBe('2020-01') expect((wrapper.vm as any).value).toBe( dayjs(new Date(2020, 0, 1)).format(valueFormat) ) }) }) describe('YearPicker', () => { it('basic', async () => { const wrapper = _mount( ``, () => ({ value: new Date(2020, 7, 1) }) ) const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() expect( (document.querySelector('.el-year-table') as HTMLElement).style.display ).toBe('') expect(document.querySelector('.el-month-table')).toBeNull() const leftBtn = document.querySelector('.d-arrow-left') as HTMLElement const rightBtn = document.querySelector('.d-arrow-right') as HTMLElement let count = 2 while (--count) { leftBtn.click() } count = 3 while (--count) { rightBtn.click() } await nextTick() ;(document.querySelector('.el-year-table .cell') as HTMLElement).click() await nextTick() const vm = wrapper.vm as any expect(vm.value.getFullYear()).toBe(2030) }) it('value-format', async () => { const valueFormat = '[Element-Plus] YYYY' const wrapper = _mount( ` `, () => ({ value: dayjs(new Date(2005, 7, 1)).format(valueFormat) }) ) await nextTick() expect(wrapper.findComponent(Input).vm.modelValue).toBe('2005') const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() const cell = document.querySelector('.el-year-table .cell') as HTMLElement cell.click() await nextTick() expect((wrapper.vm as any).value).toBe( dayjs(new Date(Number.parseInt(cell.innerHTML.trim()), 0, 1)).format( valueFormat ) ) }) }) describe('WeekPicker', () => { it('create', async () => { const wrapper = _mount( ``, () => ({ value: new Date(2020, 7, 15) }) ) const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() expect(document.querySelector('.is-week-mode')).not.toBeNull() // select month still is in week-mode ;( document.querySelectorAll( '.el-date-picker__header-label' )[1] as HTMLElement ).click() await nextTick() ;( document.querySelectorAll('.el-month-table .cell')[7] as HTMLElement ).click() await nextTick() expect(document.querySelector('.is-week-mode')).not.toBeNull() const numberOfHighlightRows = () => document.querySelectorAll('.el-date-table__row.current').length ;( document.querySelector( '.el-date-table__row ~ .el-date-table__row td.available' ) as HTMLElement ).click() await nextTick() const vm = wrapper.vm as any expect(vm.value).not.toBeNull() input.trigger('blur') input.trigger('focus') await nextTick() expect(numberOfHighlightRows()).toBe(1) // test: next month should not have highlight ;(document.querySelector('.arrow-right') as HTMLElement).click() await nextTick() expect(numberOfHighlightRows()).toBe(0) // test: next year should not have highlight ;(document.querySelector('.arrow-left') as HTMLElement).click() await nextTick() ;(document.querySelector('.d-arrow-right') as HTMLElement).click() await nextTick() expect(numberOfHighlightRows()).toBe(0) }) ;[ { locale: enUs, name: 'Sunday', value: 0 }, { locale: zhCn, name: 'Monday', value: 1 }, ].forEach((loObj) => { it(`emit first day of the week, ${loObj.locale.name} locale, ${loObj.name}`, async () => { const wrapper = mount( { components: { 'el-date-picker': DatePicker, 'el-config-provider': ConfigProvider, }, template: ` `, data() { return { locale: loObj.locale, value: '', } }, }, { attachTo: 'body', } ) const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() // click Wednesday ;( document.querySelectorAll( '.el-date-table__row ~ .el-date-table__row td' )[3] as HTMLElement ).click() await nextTick() const vm = wrapper.vm as any expect(vm.value).not.toBeNull() expect(+dayjs(vm.value).locale(loObj.locale.name)).toBe( +dayjs(vm.value).locale(loObj.locale.name).startOf('week') ) expect(dayjs(vm.value).locale(loObj.locale.name).day()).toBe(loObj.value) // Sunday or Monday }) }) }) describe('DatePicker dates', () => { it('create', async () => { const wrapper = _mount( ``, () => ({ value: '' }) ) const input = wrapper.find('input') input.trigger('blur') input.trigger('focus') await nextTick() const td = document.querySelectorAll( '.el-date-table__row .available' ) as NodeListOf const vm = wrapper.vm as any td[0].click() await nextTick() expect(vm.value.length).toBe(1) td[1].click() await nextTick() expect(vm.value.length).toBe(2) expect( document.querySelectorAll('.el-date-table__row .selected').length ).toBe(2) td[0].click() await nextTick() expect(vm.value.length).toBe(1) td[1].click() await nextTick() expect(vm.value.length).toBe(0) }) }) describe('DatePicker keyboard events', () => { it('enter', async () => { const wrapper = _mount( ``, () => ({ value: '' }) ) const input = wrapper.find('.el-input__inner') await input.trigger('focus') await input.trigger('click') await nextTick() const popperEl = document.querySelectorAll('.el-picker__popper')[0] const attr = popperEl.getAttribute('aria-hidden') expect(attr).toEqual('false') await input.trigger('keydown', { code: EVENT_CODE.enter, }) const popperEl2 = document.querySelectorAll('.el-picker__popper')[0] const attr2 = popperEl2.getAttribute('aria-hidden') expect(attr2).toEqual('true') }) it('numpadEnter', async () => { const wrapper = _mount( ``, () => ({ value: '' }) ) const input = wrapper.find('.el-input__inner') await input.trigger('focus') await input.trigger('click') await nextTick() const popperEl = document.querySelectorAll('.el-picker__popper')[0] const attr = popperEl.getAttribute('aria-hidden') expect(attr).toEqual('false') await input.trigger('keydown', { code: EVENT_CODE.numpadEnter, }) const popperEl2 = document.querySelectorAll('.el-picker__popper')[0] const attr2 = popperEl2.getAttribute('aria-hidden') expect(attr2).toEqual('true') }) }) describe('DateRangePicker', () => { it('create & custom class & style', async () => { let calendarChangeValue = null const changeHandler = vi.fn() const popperClassName = 'popper-class-test' const customClassName = 'custom-class-test' const wrapper = _mount( ``, () => ({ value: '', popperClassName, customClassName }), { methods: { onCalendarChange(e) { calendarChangeValue = e changeHandler(e) }, }, } ) const inputs = wrapper.findAll('input') inputs[0].trigger('blur') inputs[0].trigger('focus') await nextTick() const outterInput = wrapper.find('.el-range-editor.el-input__wrapper') expect(outterInput.classes()).toContain(customClassName) expect(outterInput.attributes().style).toBeDefined() const panels = document.querySelectorAll('.el-date-range-picker__content') expect(panels.length).toBe(2) ;(panels[0].querySelector('td.available') as HTMLElement).click() await nextTick() ;(panels[1].querySelector('td.available') as HTMLElement).click() await nextTick() inputs[0].trigger('blur') inputs[0].trigger('focus') await nextTick() // popperClassName expect( document .querySelector('.el-picker__popper') .classList.contains(popperClassName) ).toBe(true) // correct highlight const startDate = document.querySelectorAll('.start-date') const endDate = document.querySelectorAll('.end-date') const inRangeDate = document.querySelectorAll('.in-range') expect(startDate.length).toBe(1) expect(endDate.length).toBe(1) expect(inRangeDate.length).toBeGreaterThan(28) // value is array const vm = wrapper.vm as any expect(Array.isArray(vm.value)).toBeTruthy() // input text is something like date string expect(inputs[0].element.value.length).toBe(10) expect(inputs[1].element.value.length).toBe(10) // calendar-change event expect(changeHandler).toHaveBeenCalledTimes(2) expect(calendarChangeValue.length).toBe(2) expect(calendarChangeValue[0]).toBeInstanceOf(Date) expect(calendarChangeValue[1]).toBeInstanceOf(Date) }) it('reverse selection', async () => { const wrapper = _mount( ``, () => ({ value: '' }) ) const inputs = wrapper.findAll('input') inputs[0].trigger('blur') inputs[0].trigger('focus') await nextTick() const panels = document.querySelectorAll('.el-date-range-picker__content') ;(panels[1].querySelector('td.available') as HTMLElement).click() await nextTick() ;(panels[0].querySelector('td.available') as HTMLElement).click() await nextTick() inputs[0].trigger('blur') inputs[0].trigger('focus') await nextTick() // correct highlight const startDate = document.querySelectorAll('.start-date') const endDate = document.querySelectorAll('.end-date') const inRangeDate = document.querySelectorAll('.in-range') expect(startDate.length).toBe(1) expect(endDate.length).toBe(1) expect(inRangeDate.length).toBeGreaterThan(28) const vm = wrapper.vm as any expect(vm.value[0].getTime() < vm.value[1].getTime()).toBeTruthy() }) it('reset selection', async () => { const wrapper = _mount( ``, () => ({ value: '' }) ) const inputs = wrapper.findAll('input') inputs[0].trigger('blur') inputs[0].trigger('focus') await nextTick() const panels = document.querySelectorAll('.el-date-range-picker__content') ;(panels[1].querySelector('td.available') as HTMLElement).click() await nextTick() ;(panels[0].querySelector('td.available') as HTMLElement).click() await nextTick() ;(wrapper.vm as any).value = '' inputs[0].trigger('blur') inputs[0].trigger('focus') await nextTick() const inRangeDate = document.querySelectorAll('.in-range') expect(inRangeDate.length).toBe(0) }) it('range, start-date and end-date', async () => { _mount( ``, () => ({ value: '' }) ) const table = document.querySelector('.el-date-table') const availableTds = (table as HTMLTableElement).querySelectorAll( 'td.available' ) ;(availableTds[0] as HTMLElement).click() await nextTick() ;(availableTds[1] as HTMLElement).click() await nextTick() expect(availableTds[0].classList.contains('in-range')).toBeTruthy() expect(availableTds[0].classList.contains('start-date')).toBeTruthy() expect(availableTds[1].classList.contains('in-range')).toBeTruthy() expect(availableTds[1].classList.contains('end-date')).toBeTruthy() ;(availableTds[1] as HTMLElement).click() await nextTick() ;(availableTds[0] as HTMLElement).click() await nextTick() expect(availableTds[0].classList.contains('in-range')).toBeTruthy() expect(availableTds[0].classList.contains('start-date')).toBeTruthy() expect(availableTds[1].classList.contains('in-range')).toBeTruthy() expect(availableTds[1].classList.contains('end-date')).toBeTruthy() const startDate = document.querySelectorAll('.start-date') const endDate = document.querySelectorAll('.end-date') const inRangeDate = document.querySelectorAll('.in-range') expect(startDate.length).toBe(1) expect(endDate.length).toBe(1) expect(inRangeDate.length).toBe(2) }) it('unlink:true', async () => { const wrapper = _mount( ``, () => ({ value: [new Date(2000, 9, 1), new Date(2000, 11, 2)] }) ) const inputs = wrapper.findAll('input') inputs[0].trigger('blur') inputs[0].trigger('focus') await nextTick() const panels = document.querySelectorAll('.el-date-range-picker__content') const left = panels[0].querySelector('.el-date-range-picker__header') const right = panels[1].querySelector( '.is-right .el-date-range-picker__header' ) expect(left.textContent).toBe('2000 October') expect(right.textContent).toBe('2000 December') ;(panels[1].querySelector('.d-arrow-right') as HTMLElement).click() await nextTick() ;(panels[1].querySelector('.arrow-right') as HTMLElement).click() await nextTick() expect(left.textContent).toBe('2000 October') expect(right.textContent).toBe('2002 January') }) it('daylight saving time highlight', async () => { // Run test with environment variable TZ=Australia/Sydney // The following test uses Australian Eastern Daylight Time (AEDT) // AEST -> AEDT shift happened on 2016-10-02 02:00:00 const wrapper = _mount( ``, () => ({ value: [new Date(2016, 9, 1), new Date(2016, 9, 3)] }) ) const inputs = wrapper.findAll('input') inputs[0].trigger('blur') inputs[0].trigger('focus') await nextTick() const startDate = document.querySelectorAll('.start-date') const endDate = document.querySelectorAll('.end-date') expect(startDate.length).toBe(1) expect(endDate.length).toBe(1) }) it('value-format', async () => { const valueFormat = 'DD/MM YYYY' const wrapper = _mount( ` `, () => ({ value: [ dayjs(new Date(2021, 4, 2)).format(valueFormat), dayjs(new Date(2021, 4, 12)).format(valueFormat), ], }) ) await nextTick() const [startInput, endInput] = wrapper.findAll('input') expect(startInput.element.value).toBe('2021-05-02') expect(endInput.element.value).toBe('2021-05-12') startInput.trigger('blur') startInput.trigger('focus') await nextTick() const panels = document.querySelectorAll('.el-date-range-picker__content') expect(panels.length).toBe(2) ;(panels[0].querySelector('td.available') as HTMLElement).click() await nextTick() ;(panels[1].querySelector('td.available') as HTMLElement).click() await nextTick() expect((wrapper.vm as any).value.toString()).toBe( ['01/05 2021', '01/06 2021'].toString() ) }) it('panel change event', async () => { await testDatePickerPanelChange('daterange') }) it('display value', async () => { const wrapper = _mount( ` `, () => ({ value: [undefined, undefined], }) ) await nextTick() const [startInput, endInput] = wrapper.findAll('input') expect(startInput.element.value).toBe('') expect(endInput.element.value).toBe('') }) }) describe('MonthRange', () => { it('works', async () => { const wrapper = _mount( ``, () => ({ value: '' }) ) const inputs = wrapper.findAll('input') inputs[0].trigger('blur') inputs[0].trigger('focus') await nextTick() const panels = document.querySelectorAll('.el-date-range-picker__content') expect(panels.length).toBe(2) const p0 = panels[0].querySelector('td:not(.disabled)') p0.click() await nextTick() const p1 = panels[1].querySelector('td:not(.disabled)') p1.click() await nextTick() inputs[0].trigger('blur') inputs[0].trigger('focus') // correct highlight const startDate = document.querySelectorAll('.start-date') const endDate = document.querySelectorAll('.end-date') const inRangeDate = document.querySelectorAll('.in-range') expect(startDate.length).toBe(1) expect(endDate.length).toBe(1) expect(inRangeDate.length).toBeGreaterThan(0) // value is array const vm = wrapper.vm as any expect(Array.isArray(vm.value)).toBeTruthy() // input text is something like date string expect(inputs[0].element.value.length).toBe(7) expect(inputs[1].element.value.length).toBe(7) // reverse selection p1.click() await nextTick() p0.click() await nextTick() expect(vm.value[0].getTime() < vm.value[1].getTime()).toBeTruthy() }) it('range, start-date and end-date', async () => { _mount( ``, () => ({ value: '' }) ) const table = document.querySelector('.el-month-table') const tds = (table as HTMLTableElement).querySelectorAll('td') ;(tds[0] as HTMLElement).click() await nextTick() ;(tds[1] as HTMLElement).click() await nextTick() expect(tds[0].classList.contains('in-range')).toBeTruthy() expect(tds[0].classList.contains('start-date')).toBeTruthy() expect(tds[1].classList.contains('in-range')).toBeTruthy() expect(tds[1].classList.contains('end-date')).toBeTruthy() ;(tds[1] as HTMLElement).click() await nextTick() ;(tds[0] as HTMLElement).click() await nextTick() expect(tds[0].classList.contains('in-range')).toBeTruthy() expect(tds[0].classList.contains('start-date')).toBeTruthy() expect(tds[1].classList.contains('in-range')).toBeTruthy() expect(tds[1].classList.contains('end-date')).toBeTruthy() const startDate = document.querySelectorAll('.start-date') const endDate = document.querySelectorAll('.end-date') const inRangeDate = document.querySelectorAll('.in-range') expect(startDate.length).toBe(1) expect(endDate.length).toBe(1) expect(inRangeDate.length).toBe(2) }) it('type:monthrange unlink:true', async () => { const wrapper = _mount( ``, () => ({ value: [new Date(2000, 9), new Date(2002, 11)] }) ) const inputs = wrapper.findAll('input') inputs[0].trigger('blur') inputs[0].trigger('focus') await nextTick() const panels = document.querySelectorAll('.el-date-range-picker__content') const left = panels[0].querySelector('.el-date-range-picker__header') const right = panels[1].querySelector( '.is-right .el-date-range-picker__header' ) expect(left.textContent).toContain(2000) expect(right.textContent).toContain(2002) ;(panels[1].querySelector('.d-arrow-right') as HTMLElement).click() await nextTick() expect(left.textContent).toContain(2000) expect(right.textContent).toContain(2003) }) it('daylight saving time highlight', async () => { const wrapper = _mount( ``, () => ({ value: [new Date(2016, 6), new Date(2016, 12)] }) ) const inputs = wrapper.findAll('input') inputs[0].trigger('blur') inputs[0].trigger('focus') await nextTick() const startDate = document.querySelectorAll('.start-date') const endDate = document.querySelectorAll('.end-date') expect(startDate.length).toBe(1) expect(endDate.length).toBe(1) }) it('should accept popper options and pass down', async () => { const ElPopperOptions = { strategy: 'fixed', } const wrapper = _mount( ``, () => ({ value: [new Date(2016, 6), new Date(2016, 12)], options: ElPopperOptions, }), { provide() { return { ElPopperOptions, } }, } ) await nextTick() expect( (wrapper.findComponent(CommonPicker).vm as any).elPopperOptions ).toEqual(ElPopperOptions) }) describe('form item accessibility integration', () => { it('automatic id attachment', async () => { const wrapper = _mount( ` `, () => ({}) ) await nextTick() const formItem = wrapper.find('[data-test-ref="item"]') const formItemLabel = formItem.find('.el-form-item__label') const datePickerInput = wrapper.find('.el-input__inner') expect(formItem.attributes().role).toBeFalsy() expect(formItemLabel.attributes().for).toBe( datePickerInput.attributes().id ) }) it('specified id attachment', async () => { const wrapper = _mount( ` `, () => ({}) ) await nextTick() const formItem = wrapper.find('[data-test-ref="item"]') const formItemLabel = formItem.find('.el-form-item__label') const datePickerInput = wrapper.find('.el-input__inner') expect(formItem.attributes().role).toBeFalsy() expect(datePickerInput.attributes().id).toBe('foobar') expect(formItemLabel.attributes().for).toBe( datePickerInput.attributes().id ) }) it('form item role is group when multiple inputs', async () => { const wrapper = _mount( ` `, () => ({}) ) await nextTick() const formItem = wrapper.find('[data-test-ref="item"]') expect(formItem.attributes().role).toBe('group') }) }) it('The year which is disabled should not be selectable', async () => { const pickHandler = vi.fn() const wrapper = _mount( ``, () => ({ yearValue: '2022', validateYear: (date) => { if (date.getFullYear() > 2022) { return true } else { return false } }, onPick(e) { return pickHandler(e) }, }) ) const input = wrapper.find('input') input.trigger('focus') await nextTick() ;(document.querySelector('td.disabled') as HTMLElement).click() await nextTick() expect(pickHandler).toHaveBeenCalledTimes(0) ;(document.querySelector('td.available') as HTMLElement).click() await nextTick() expect(pickHandler).toHaveBeenCalledTimes(1) }) })