UNPKG

uiv

Version:

Bootstrap 3 components implemented by Vue.

577 lines (539 loc) 19.8 kB
import { createWrapper, nextTick, sleep, triggerEvent, } from '../../__test__/utils'; function baseVm(d = new Date()) { return createWrapper('<div><time-picker v-model="time"/></div>', { time: d, }); } function h24Vm(d = new Date()) { return createWrapper( '<div><time-picker v-model="time" :show-meridian="false"/></div>', { time: d, } ); } describe('TimePicker', () => { it('should be able to toggle meridian', async () => { const d = new Date(); d.setHours(9); const wrapper = baseVm(d); const vm = wrapper.vm; const toggleBtn = vm.$el.querySelector('[data-action="toggleMeridian"]'); const meridianText = toggleBtn.textContent; expect(meridianText).toEqual('AM'); triggerEvent(toggleBtn, 'click'); await vm.$nextTick(); const meridianTextAfterClick = toggleBtn.textContent; expect(meridianTextAfterClick).toEqual('PM'); triggerEvent(toggleBtn, 'click'); await vm.$nextTick(); const meridianTextAfterTwoClick = toggleBtn.textContent; expect(meridianTextAfterTwoClick).toEqual('AM'); }); it('should be able to add 1 hour', async () => { const wrapper = baseVm(); const vm = wrapper.vm; await vm.$nextTick(); const beforeText = vm.$el.querySelectorAll('input')[0].value; const hourPlus = vm.$el.querySelectorAll('td')[0].querySelector('button'); triggerEvent(hourPlus, 'click'); await vm.$nextTick(); let afterText = vm.$el.querySelectorAll('input')[0].value; if (parseInt(beforeText) !== 12) { expect(parseInt(afterText)).toEqual(parseInt(beforeText) + 1); } else { expect(parseInt(afterText)).toEqual(1); } vm.time.setHours(23); vm.time = new Date(vm.time); await vm.$nextTick(); triggerEvent(hourPlus, 'click'); await vm.$nextTick(); afterText = vm.$el.querySelectorAll('input')[0].value; expect(parseInt(afterText)).toEqual(12); }); it('should be able to add 1 minute', async () => { const wrapper = baseVm(); const vm = wrapper.vm; await vm.$nextTick(); const beforeText = vm.$el.querySelectorAll('input')[1].value; const minutesPlus = vm.$el.querySelectorAll('tr td button')[1]; triggerEvent(minutesPlus, 'click'); await vm.$nextTick(); const afterText = vm.$el.querySelectorAll('input')[1].value; if (parseInt(beforeText) !== 59) { expect(parseInt(afterText)).toEqual(parseInt(beforeText) + 1); } else { expect(parseInt(afterText)).toEqual(0); } }); it('should be able to minus 1 hour', async () => { const wrapper = baseVm(); const vm = wrapper.vm; await vm.$nextTick(); const beforeText = vm.$el.querySelectorAll('input')[0].value; const hourMinus = vm.$el .querySelectorAll('tr')[2] .querySelector('td button'); triggerEvent(hourMinus, 'click'); await vm.$nextTick(); let afterText = vm.$el.querySelectorAll('input')[0].value; if (parseInt(beforeText) !== 1) { expect(parseInt(afterText)).toEqual(parseInt(beforeText) - 1); } else { expect(parseInt(afterText)).toEqual(12); } vm.time.setHours(0); vm.time = new Date(vm.time); await vm.$nextTick(); triggerEvent(hourMinus, 'click'); await vm.$nextTick(); afterText = vm.$el.querySelectorAll('input')[0].value; expect(parseInt(afterText)).toEqual(11); }); it('should be able to minus 1 minute', async () => { const wrapper = baseVm(); const vm = wrapper.vm; await vm.$nextTick(); const beforeText = vm.$el.querySelectorAll('input')[1].value; const minutesMinus = vm.$el .querySelectorAll('tr')[2] .querySelectorAll('td button')[1]; triggerEvent(minutesMinus, 'click'); await vm.$nextTick(); const afterText = vm.$el.querySelectorAll('input')[1].value; if (parseInt(beforeText) !== 0) { expect(parseInt(afterText)).toEqual(parseInt(beforeText) - 1); } else { expect(parseInt(afterText)).toEqual(59); } }); it('should be able to use 24h mode', async () => { const wrapper = h24Vm(); const vm = wrapper.vm; await vm.$nextTick(); const toggleBtn = vm.$el.querySelector('[data-action="toggleMeridian"]'); expect(toggleBtn).toBeNull(); }); it('should be able to display correctly when hour = 0', async () => { const d = new Date(); d.setHours(0); const wrapper = baseVm(d); const vm = wrapper.vm; await nextTick(); const hourText = vm.$el.querySelectorAll('input')[0].value; const toggleBtn = vm.$el.querySelector('[data-action="toggleMeridian"]'); expect(parseInt(hourText)).toEqual(12); expect(toggleBtn.textContent).toEqual('AM'); }); it('should be able to display correctly when hour = 12', async () => { const d = new Date(); d.setHours(12); const wrapper = baseVm(d); await nextTick(); const vm = wrapper.vm; const hourText = vm.$el.querySelectorAll('input')[0].value; const toggleBtn = vm.$el.querySelector('[data-action="toggleMeridian"]'); expect(parseInt(hourText)).toEqual(12); expect(toggleBtn.textContent).toEqual('PM'); }); it('should be able to set hour using input in 24h mode', async () => { const wrapper = h24Vm(); const vm = wrapper.vm; vm.time.setHours(12); vm.time = new Date(vm.time); await vm.$nextTick(); const hoursInput = vm.$el.querySelectorAll('input')[0]; hoursInput.value = 12; await vm.$nextTick(); expect(parseInt(hoursInput.value)).toEqual(12); hoursInput.value = 13; await vm.$nextTick(); expect(parseInt(hoursInput.value)).toEqual(13); }); it('should be able to set hour using input in 12h mode', async () => { const d = new Date(); d.setHours(12); const wrapper = baseVm(d); const vm = wrapper.vm; await vm.$nextTick(); const hoursInput = vm.$el.querySelectorAll('input')[0]; expect(parseInt(hoursInput.value)).toEqual(12); hoursInput.value = 5; await vm.$nextTick(); expect(parseInt(hoursInput.value)).toEqual(5); }); it('should be able to set minute using input', async () => { const d = new Date(); d.setHours(12); d.setMinutes(0); const wrapper = baseVm(d); const vm = wrapper.vm; await vm.$nextTick(); const minutesInput = vm.$el.querySelectorAll('input')[1]; expect(parseInt(minutesInput.value)).toEqual(0); minutesInput.value = 5; await vm.$nextTick(); expect(parseInt(minutesInput.value)).toEqual(5); }); it('should add hour when minute is 60', async () => { const d = new Date(); d.setHours(12); d.setMinutes(59); const wrapper = baseVm(d); const vm = wrapper.vm; await vm.$nextTick(); const beforeHourText = vm.$el.querySelectorAll('input')[0].value; const minutesPlus = vm.$el.querySelectorAll('tr td button')[1]; triggerEvent(minutesPlus, 'click'); await vm.$nextTick(); const afterHourText = vm.$el.querySelectorAll('input')[0].value; const afterMinutesText = vm.$el.querySelectorAll('input')[1].value; expect(parseInt(afterHourText)).toEqual(1); expect(parseInt(afterMinutesText)).toEqual(0); }); it('should minus hour when minute is -1', async () => { const d = new Date(); d.setHours(9); d.setMinutes(0); const wrapper = baseVm(d); const vm = wrapper.vm; await vm.$nextTick(); const beforeHourText = vm.$el.querySelectorAll('input')[0].value; const minutesMinus = vm.$el .querySelectorAll('tr')[2] .querySelectorAll('td button')[1]; triggerEvent(minutesMinus, 'click'); await vm.$nextTick(); const afterHourText = vm.$el.querySelectorAll('input')[0].value; const afterMinutesText = vm.$el.querySelectorAll('input')[1].value; expect(parseInt(afterHourText)).toEqual(parseInt(beforeHourText) - 1); expect(parseInt(afterMinutesText)).toEqual(59); }); it('can be set to 9:00', async () => { const d = new Date(); d.setHours(9); d.setMinutes(0); const wrapper = baseVm(d); const vm = wrapper.vm; await vm.$nextTick(); const hourText = vm.$el.querySelectorAll('input')[0].value; const minutesText = vm.$el.querySelectorAll('input')[1].value; const toggleBtn = vm.$el.querySelector('[data-action="toggleMeridian"]'); expect(hourText).toEqual('09'); expect(minutesText).toEqual('00'); expect(toggleBtn.textContent).toEqual('AM'); }); it('should not be able to update time bigger than max', async () => { const d = new Date(); d.setHours(20); const wrapper = createWrapper( '<div><time-picker v-model="time" :max="max" :min="min"/></div>', { time: d, min: new Date('2017/01/01 8:00'), // date doesn't matter max: new Date('2017/01/01 20:00'), } ); const vm = wrapper.vm; await vm.$nextTick(); const hourText = vm.$el.querySelectorAll('input')[0]; const hourPlus = vm.$el.querySelectorAll('td')[0].querySelector('button'); expect(hourText.value).toEqual('08'); triggerEvent(hourPlus, 'click'); await vm.$nextTick(); expect(hourText.value).toEqual('08'); }); it('should not be able to update time smaller than min', async () => { const d = new Date(); d.setHours(8); d.setMinutes(30); const wrapper = createWrapper( '<div><time-picker v-model="time" :max="max" :min="min"/></div>', { time: d, min: new Date('2017/01/01 8:00'), // date doesn't matter max: new Date('2017/01/01 20:00'), } ); const vm = wrapper.vm; await vm.$nextTick(); const hourText = vm.$el.querySelectorAll('input')[0]; expect(hourText.value).toEqual('08'); const hourMinus = vm.$el .querySelectorAll('tr')[2] .querySelector('td button'); triggerEvent(hourMinus, 'click'); await vm.$nextTick(); const minutesText = vm.$el.querySelectorAll('input')[1]; expect(hourText.value).toEqual('08'); expect(minutesText.value).toEqual('00'); }); it('should be able to use custom icons', async () => { const wrapper = createWrapper( '<div><time-picker v-model="time" icon-control-up="glyphicon glyphicon-plus" icon-control-down="glyphicon glyphicon-minus"/></div>', { time: new Date(), } ); const vm = wrapper.vm; const $el = vm.$el; expect($el.querySelector('tr:first-child .btn > i').className).toContain( 'glyphicon-plus' ); expect($el.querySelector('tr:last-child .btn > i').className).toContain( 'glyphicon-minus' ); }); it('should be able to toggle meridian in runtime', async () => { const wrapper = createWrapper( '<time-picker v-model="time" :show-meridian="meridian"/>', { time: new Date(), meridian: true, } ); const vm = wrapper.vm; const $el = vm.$el; await vm.$nextTick(); expect( $el.querySelectorAll('[data-action="toggleMeridian"]').length ).toEqual(1); const timeBefore = new Date(vm.time); // toggle meridian vm.meridian = false; await vm.$nextTick(); expect( $el.querySelectorAll('[data-action="toggleMeridian"]').length ).toEqual(0); const timeAfter = new Date(vm.time); expect(timeAfter.getTime()).toEqual(timeBefore.getTime()); // toggle meridian vm.meridian = true; await vm.$nextTick(); expect( $el.querySelectorAll('[data-action="toggleMeridian"]').length ).toEqual(1); const timeAfterAgain = new Date(vm.time); expect(timeAfterAgain.getTime()).toEqual(timeBefore.getTime()); }); it('should not be able to change time while readonly', async () => { const wrapper = createWrapper( '<time-picker ref="timepicker" v-model="time" readonly/>', { time: new Date(), } ); const vm = wrapper.vm; await vm.$nextTick(); const timeBefore = new Date(vm.time); // on click & keydown vm.$refs.timepicker.changeTime(1, 1); await vm.$nextTick(); const timeAfter = new Date(vm.time); expect(timeAfter.getTime()).toEqual(timeBefore.getTime()); // on wheel vm.$refs.timepicker.onWheel( { deltaY: -1, preventDefault: () => null }, true ); await vm.$nextTick(); const timeAfterAgain = new Date(vm.time); expect(timeAfterAgain.getTime()).toEqual(timeBefore.getTime()); }); it('should be able to change hour use wheel', async () => { const wrapper = createWrapper( '<time-picker ref="timepicker" v-model="time"/>', { time: new Date(), } ); const vm = wrapper.vm; await vm.$nextTick(); const timeBefore = new Date(vm.time); // add hour vm.$refs.timepicker.onWheel( { deltaY: -1, preventDefault: () => null }, true ); await vm.$nextTick(); const timeAfter = new Date(vm.time); expect(timeAfter.getTime()).toEqual(timeBefore.getTime() + 60 * 60 * 1000); // minus hour vm.$refs.timepicker.onWheel( { deltaY: 1, preventDefault: () => null }, true ); await vm.$nextTick(); const timeAfterAgain = new Date(vm.time); expect(timeAfterAgain.getTime()).toEqual(timeBefore.getTime()); }); it('should be able to change minute use wheel', async () => { const wrapper = createWrapper( '<time-picker ref="timepicker" v-model="time"/>', { time: new Date(), } ); const vm = wrapper.vm; await vm.$nextTick(); const timeBefore = new Date(vm.time); // add hour vm.$refs.timepicker.onWheel( { deltaY: -1, preventDefault: () => null }, false ); await vm.$nextTick(); const timeAfter = new Date(vm.time); expect(timeAfter.getTime()).toEqual(timeBefore.getTime() + 60 * 1000); // minus hour vm.$refs.timepicker.onWheel( { deltaY: 1, preventDefault: () => null }, false ); await vm.$nextTick(); const timeAfterAgain = new Date(vm.time); expect(timeAfterAgain.getTime()).toEqual(timeBefore.getTime()); }); it('should be able to select input content on mouseup', async () => { const wrapper = createWrapper('<time-picker v-model="time"/>', { time: new Date(), }); const vm = wrapper.vm; await vm.$nextTick(); const hoursInput = vm.$el.querySelectorAll('input')[0]; const hoursInputSpy = jest.spyOn(hoursInput, 'setSelectionRange'); triggerEvent(hoursInput, 'mouseup'); await vm.$nextTick(); expect(hoursInputSpy).toBeCalledTimes(1); const minutesInput = vm.$el.querySelectorAll('input')[1]; const minutesInputSpy = jest.spyOn(minutesInput, 'setSelectionRange'); triggerEvent(minutesInput, 'mouseup'); await vm.$nextTick(); expect(minutesInputSpy).toBeCalledTimes(1); }); it('should show controls by default', async () => { const wrapper = baseVm(); const vm = wrapper.vm; const $el = vm.$el; expect($el.querySelectorAll('tr:first-child .btn').length).toEqual(2); expect($el.querySelectorAll('tr:last-child .btn').length).toEqual(2); }); it('should be able to hide controls', async () => { const wrapper = createWrapper( '<div> <time-picker v-model="time" :controls="false"/></div>', { time: new Date(), } ); const vm = wrapper.vm; const $el = vm.$el; // We could still have a button for the AM/PM toggle expect($el.querySelectorAll('tr:first-child .btn').length).not.toEqual(2); expect($el.querySelectorAll('tr:last-child .btn').length).not.toEqual(2); }); it('should display empty fields when date provided is invalid', async () => { const wrapper = createWrapper('<div><time-picker v-model="time"/></div>', { time: new Date(''), }); const vm = wrapper.vm; await vm.$nextTick(); const hourText = vm.$el.querySelectorAll('input')[0]; const minutesText = vm.$el.querySelectorAll('input')[1]; const toggleBtn = vm.$el.querySelector('[data-action="toggleMeridian"]'); expect(hourText.value).toEqual(''); expect(minutesText.value).toEqual(''); expect(toggleBtn.textContent).toEqual('AM'); triggerEvent(toggleBtn, 'click'); await vm.$nextTick(); expect(hourText.value).toEqual('12'); expect(minutesText.value).toEqual('00'); expect(toggleBtn.textContent).toEqual('PM'); }); it('should display empty fields when date provided is invalid and minutes button still work', async () => { const wrapper = createWrapper('<div><time-picker v-model="time"/></div>', { time: new Date(''), }); const vm = wrapper.vm; await vm.$nextTick(); const hourText = vm.$el.querySelectorAll('input')[0]; const minutesText = vm.$el.querySelectorAll('input')[1]; const toggleBtn = vm.$el.querySelector('[data-action="toggleMeridian"]'); expect(hourText.value).toEqual(''); expect(minutesText.value).toEqual(''); expect(toggleBtn.textContent).toEqual('AM'); await vm.$nextTick(); const minutesPlus = vm.$el.querySelectorAll('tr td button')[1]; triggerEvent(minutesPlus, 'click'); await vm.$nextTick(); expect(hourText.value).toEqual('12'); expect(minutesText.value).toEqual('01'); expect(toggleBtn.textContent).toEqual('AM'); }); it('should display empty fields when date provided is invalid and hour button still work', async () => { const wrapper = createWrapper('<div><time-picker v-model="time"/></div>', { time: new Date(''), }); const vm = wrapper.vm; await vm.$nextTick(); const hourText = vm.$el.querySelectorAll('input')[0]; const minutesText = vm.$el.querySelectorAll('input')[1]; const toggleBtn = vm.$el.querySelector('[data-action="toggleMeridian"]'); const hourPlus = vm.$el.querySelectorAll('tr td button')[0]; expect(hourText.value).toEqual(''); expect(minutesText.value).toEqual(''); expect(toggleBtn.textContent).toEqual('AM'); triggerEvent(hourPlus, 'click'); await vm.$nextTick(); expect(hourText.value).toEqual('01'); expect(minutesText.value).toEqual('00'); expect(toggleBtn.textContent).toEqual('AM'); }); it('should display empty fields when date is reset at runtime', async () => { const wrapper = createWrapper( '<div> <time-picker v-model="time" :controls="false"/></div>', { time: new Date(), } ); const vm = wrapper.vm; await vm.$nextTick(); // Set an invalid date at runtime (not via the initial config) vm.time = new Date(''); await vm.$nextTick(); const hourText = vm.$el.querySelectorAll('input')[0]; const minutesText = vm.$el.querySelectorAll('input')[1]; expect(hourText.value).toEqual(''); expect(minutesText.value).toEqual(''); }); it('should have a default input width to 50px', async () => { const wrapper = baseVm(); const vm = wrapper.vm; const hoursInput = vm.$el.querySelectorAll('input')[0]; expect(hoursInput.style.width).toEqual('50px'); const minutesInput = vm.$el.querySelectorAll('input')[1]; expect(minutesInput.style.width).toEqual('50px'); }); it('should accept an input-width prop that sets the specified width to the hours and minutes input', async () => { const wrapper = createWrapper( '<div><time-picker v-model="time" :input-width="inputWidth"/></div>', { time: new Date(''), inputWidth: 180, } ); const vm = wrapper.vm; const inputWidth = vm.inputWidth; // Check that the passed value is not the default value expect(inputWidth).not.toEqual(50); const hoursInput = vm.$el.querySelectorAll('input')[0]; expect(hoursInput.style.width).toEqual(`${inputWidth}px`); const minutesInput = vm.$el.querySelectorAll('input')[1]; expect(minutesInput.style.width).toEqual(`${inputWidth}px`); }); });