import { shallowMount, createWrapper, mount } from '@vue/test-utils'; import { format, parse } from 'date-fns'; import Popup from '../src/popup'; import DatePicker from '../src/date-picker'; let wrapper; afterEach(() => { wrapper.destroy(); }); describe('DatePicker', () => { it('feat: open and close the popup', async () => { wrapper = mount(DatePicker, { attachTo: document.body, }); expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(false); // expect click input should show the popup const input = wrapper.find('input'); await input.trigger('mousedown'); expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(true); // expect click out side should hide the popup const bodyWrapper = createWrapper(document.body); await bodyWrapper.trigger('mousedown'); expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(false); // expect focus input should show the popop await input.trigger('focus'); expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(true); // expoce keydown tab should hide the popup await input.trigger('keydown.tab'); expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(false); }); it('feat: should init panel and calendar when reopen', async () => { wrapper = mount(DatePicker, { propsData: { defaultValue: new Date(2019, 9, 1), open: true, }, }); const yearBtn = wrapper.find('.mx-btn-current-year'); await yearBtn.trigger('click'); // change to year panel expect(wrapper.find('.mx-calendar-panel-year').exists()).toBe(true); await wrapper.setProps({ open: false }); await wrapper.setProps({ open: true }); expect(wrapper.find('.mx-calendar-panel-year').exists()).toBe(false); }); it('prop: open', async () => { wrapper = mount(DatePicker, { propsData: { open: false, }, }); const { vm } = wrapper; vm.openPopup(); expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(false); await wrapper.setProps({ open: true }); expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(true); vm.closePopup(); expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(true); const emitted = wrapper.emitted(); expect(emitted['update:open'][0][0]).toBe(true); expect(emitted['update:open'][1][0]).toBe(false); }); it('prop: disabled(should not show the popup)', () => { wrapper = mount(DatePicker, { propsData: { disabled: true, }, }); const input = wrapper.find('input'); expect(input.attributes('disabled')).toBe('disabled'); input.trigger('click'); expect(wrapper.find('.mx-datepicker-popup').exists()).toBe(false); }); it('prop: clearable', () => { wrapper = shallowMount(DatePicker, { propsData: { value: new Date(2019, 4, 10), defaultValue: new Date(2019, 4, 10), clearable: false, }, // calendar-panel: default-value="Fri May 10 2019 00:00:00 GMT+0800 (CST)" // Exclude the impact of timezone scopedSlots: { content: '
', }, }); expect(wrapper.element).toMatchSnapshot(); }); it('prop: editable', () => { wrapper = shallowMount(DatePicker, { propsData: { value: new Date(2019, 4, 10), defaultValue: new Date(2019, 4, 10), editable: false, }, scopedSlots: { content: '', }, }); expect(wrapper.element).toMatchSnapshot(); }); it('prop: attrs of input', () => { wrapper = shallowMount(DatePicker, { propsData: { defaultValue: new Date(2019, 4, 10), placeholder: 'test placeholder', inputClass: 'test', inputAttr: { type: 'number', name: 'test', }, }, scopedSlots: { content: '', }, }); expect(wrapper.element).toMatchSnapshot(); }); it('prop: format', () => { wrapper = shallowMount(DatePicker, { propsData: { format: 'YYYY/MM/DD', value: new Date(2019, 9, 10), }, }); const input = wrapper.find('input').element; expect(input.value).toBe('2019/10/10'); }); it('prop: formatter', () => { wrapper = mount(DatePicker, { propsData: { valueType: 'format', value: '13/10/2019', open: true, type: 'week', formatter: { stringify(date) { return format(date, 'dd/MM/yyyy'); }, parse(value) { return parse(value, 'dd/MM/yyyy', new Date()); }, getWeek(date) { return date.getDate(); }, }, }, }); const input = wrapper.find('input').element; expect(input.value).toBe('13/10/2019'); const tableDate = wrapper.find('.mx-table-date'); expect(tableDate.element).toMatchSnapshot(); }); it('prop: valueType', async () => { const value = new Date(2019, 9, 20); const emitValue = new Date(2019, 9, 22); wrapper = shallowMount(DatePicker, { propsData: { value, format: 'YYYY/MM/DD', }, }); const { vm } = wrapper; expect(vm.text).toBe('2019/10/20'); vm.emitValue(emitValue); await wrapper.setProps({ valueType: 'format', value: '2019/10/20' }); expect(vm.text).toBe('2019/10/20'); vm.emitValue(emitValue); await wrapper.setProps({ valueType: 'timestamp', value: value.getTime() }); expect(vm.text).toBe('2019/10/20'); vm.emitValue(emitValue); await wrapper.setProps({ valueType: 'DD/MM/YYYY', value: '20/10/2019' }); expect(vm.text).toBe('2019/10/20'); vm.emitValue(emitValue); const emitted = wrapper.emitted(); expect(emitted.input).toEqual([ [emitValue], ['2019/10/22'], [emitValue.getTime()], ['22/10/2019'], ]); }); it('prop: shortcut', async () => { const date = new Date(2019, 4, 10); wrapper = shallowMount(DatePicker, { propsData: { open: true, valueType: 'YYYY/MM/DD', range: false, shortcuts: [ { text: 'Today', onClick() { return date; }, }, ], }, }); const btn = wrapper.find('.mx-btn-shortcut'); await btn.trigger('click'); const emitted = wrapper.emitted(); expect(emitted.input).toEqual([['2019/05/10']]); await wrapper.setProps({ range: true, shortcuts: [ { text: 'range', onClick() { return [date, date]; }, }, ], }); btn.trigger('click'); expect(emitted.input[1]).toEqual([['2019/05/10', '2019/05/10']]); }); it('prop: popupClass', () => { wrapper = mount(DatePicker, { propsData: { open: true, popupClass: 'test', }, }); const popup = wrapper.findComponent(Popup); expect(popup.classes()).toContain('test'); }); it('prop: popupStyle', () => { wrapper = mount(DatePicker, { propsData: { open: true, popupStyle: { color: 'red', }, }, }); const popup = wrapper.findComponent(Popup); expect(popup.element.style.color).toBe('red'); }); it('prop: confirm', async () => { wrapper = shallowMount(DatePicker, { propsData: { confirm: true, }, }); const { vm } = wrapper; await wrapper.find('input').trigger('focus'); const btn = wrapper.find('.mx-datepicker-btn-confirm'); expect(btn.exists()).toBe(true); // click the date expect popup don't close vm.handleSelectDate(new Date(2018, 5, 5)); expect(wrapper.emitted().input).toBeUndefined(); expect(vm.popupVisible).toBe(true); await btn.trigger('click'); expect(wrapper.emitted().input[0][0]).toEqual(new Date(2018, 5, 5)); expect(vm.popupVisible).toBe(false); }); it('prop: confirmText', () => { wrapper = shallowMount(DatePicker, { propsData: { open: true, confirm: true, confirmText: 'test', }, }); const btn = wrapper.find('.mx-datepicker-btn-confirm'); expect(btn.text()).toBe('test'); }); it('prop: appendToBody', () => { wrapper = mount(DatePicker, { propsData: { open: true, appendToBody: true, }, }); const popup = wrapper.findComponent(Popup); expect(popup.element.parentNode).toBe(document.body); }); it('feat: should emit clear event when click clear button', () => { wrapper = shallowMount(DatePicker, { propsData: { value: new Date(2019, 10, 9), }, }); const clearButton = wrapper.find('.mx-icon-clear'); clearButton.trigger('mousedown'); const emitted = wrapper.emitted(); expect(emitted.clear).toBeTruthy(); expect(emitted.input[0][0]).toBe(null); }); it('feat: should emit [null, null] when clear range', () => { wrapper = shallowMount(DatePicker, { propsData: { range: true, value: [new Date(2019, 10, 9), new Date(2019, 11, 9)], }, }); const clearButton = wrapper.find('.mx-icon-clear'); clearButton.trigger('mousedown'); const emitted = wrapper.emitted(); expect(emitted.input[0][0]).toEqual([null, null]); }); it('feat: should close popup when click time in datetime mode', () => { wrapper = mount(DatePicker, { propsData: { type: 'datetime', timePickerOptions: { start: '00:00', step: '00:30', end: '23:30', }, open: true, showTimePanel: true, }, }); const el = wrapper.find('.mx-time-option'); el.trigger('click'); expect(wrapper.emitted().close).toBeTruthy(); }); // present the button submit form it('the type of all buttons should be button', () => { wrapper = mount(DatePicker, { propsData: { open: true, showTimePanel: true, }, }); const els = wrapper.findAll('button'); els.wrappers.forEach(v => { expect(v.element.type).toBe('button'); }); }); it('should emit pick event on first click', () => { wrapper = mount(DatePicker, { propsData: { range: true, open: true, defaultValue: new Date(2019, 9, 1), }, }); const td = wrapper.find('.mx-table-date td'); td.trigger('click'); expect(wrapper.emitted().pick[0][0]).toEqual(new Date(2019, 8, 29)); }); it('Ignore whitespace around separator on manual range input', async () => { const rangeSeparator = ' ~ '; const text = '2020-02-12'; wrapper = mount(DatePicker, { propsData: { range: true, rangeSeparator: ' ~ ', valueType: 'format', }, }); const input = wrapper.find('input'); await input.setValue(`${text} ${rangeSeparator} ${text}`); await input.trigger('change'); await input.setValue(`${text}${rangeSeparator.trim()}${text}`); await input.trigger('change'); await wrapper.setProps({ rangeSeparator: ' - ' }); await input.setValue(`${text} - ${text}`); await input.trigger('change'); expect(wrapper.emitted().input).toEqual([[[text, text]], [[text, text]], [[text, text]]]); }); it('prop: multiple', () => { const value = [new Date(2020, 5, 6), new Date(2020, 6, 7)]; wrapper = mount(DatePicker, { propsData: { multiple: true, open: true, value, }, }); wrapper.find('.mx-date-row .active').trigger('click'); expect(wrapper.emitted().input[0][0]).toEqual(value.slice(0, 1)); wrapper.find('[title="2020-07-15"]').trigger('click'); expect(wrapper.emitted().input[1][0]).toEqual(value.concat(new Date(2020, 6, 15))); }); it('prop: invalid multiple', () => { wrapper = shallowMount(DatePicker, { propsData: { multiple: true, range: true, }, }); const { vm } = wrapper; expect(vm.validMultipleType).toBe(false); wrapper.setProps({ range: false, type: 'datetime', }); expect(vm.validMultipleType).toBe(false); }); it('If the value entered manually is in the disabled range should be invalid', () => { const someday = new Date(2020, 6, 1); wrapper = shallowMount(DatePicker, { format: 'YYYY-MM-DD', propsData: { disabledDate: date => { return date < someday; }, }, }); const textInput = wrapper.find('input'); textInput.setValue('2020-08-01'); textInput.trigger('change'); expect(wrapper.emitted().input[0][0]).toEqual(new Date(2020, 7, 1)); textInput.setValue('2020-05-01'); textInput.trigger('change'); expect(wrapper.emitted().input[1]).toBe(undefined); expect(wrapper.emitted()['input-error'][0][0]).toBe('2020-05-01'); }); it('panel-change event should be emitd', async () => { wrapper = mount(DatePicker, { propsData: { open: true, }, }); const yearBtn = wrapper.find('.mx-btn-current-year'); await yearBtn.trigger('click'); expect(wrapper.emitted()['panel-change'][0]).toEqual(['year', 'date']); }); });