diff --git a/packages/vant/src/calendar/CalendarMonth.tsx b/packages/vant/src/calendar/CalendarMonth.tsx index f52448da1..5148e45f3 100644 --- a/packages/vant/src/calendar/CalendarMonth.tsx +++ b/packages/vant/src/calendar/CalendarMonth.tsx @@ -15,7 +15,7 @@ import { createNamespace, makeRequiredProp, } from '../utils'; -import { getMonthEndDay } from '../datetime-picker/utils'; +import { getMonthEndDay } from '../date-picker/utils'; import { t, bem, diff --git a/packages/vant/src/date-picker/DatePicker.tsx b/packages/vant/src/date-picker/DatePicker.tsx index d77dde992..cc8a613c2 100644 --- a/packages/vant/src/date-picker/DatePicker.tsx +++ b/packages/vant/src/date-picker/DatePicker.tsx @@ -17,12 +17,7 @@ import { makeArrayProp, createNamespace, } from '../utils'; -import { - times, - sharedProps, - getMonthEndDay, - pickerInheritKeys, -} from '../datetime-picker/utils'; +import { times, sharedProps, getMonthEndDay, pickerInheritKeys } from './utils'; // Components import { Picker } from '../picker'; @@ -88,8 +83,21 @@ export default defineComponent({ month === props.maxDate.getMonth() + 1; const getValue = (type: DatePickerColumnType) => { - const index = props.columnsType.indexOf(type); - return +currentValues.value[index]; + const { minDate, columnsType } = props; + const index = columnsType.indexOf(type); + const value = currentValues.value[index]; + if (value) { + return +value; + } + + switch (type) { + case 'year': + return minDate.getFullYear(); + case 'month': + return minDate.getMonth() + 1; + case 'day': + return minDate.getDate(); + } }; const genMonthOptions = () => { diff --git a/packages/vant/src/date-picker/test/__snapshots__/demo.spec.ts.snap b/packages/vant/src/date-picker/test/__snapshots__/demo.spec.ts.snap new file mode 100644 index 000000000..38c6c2e0c --- /dev/null +++ b/packages/vant/src/date-picker/test/__snapshots__/demo.spec.ts.snap @@ -0,0 +1,1016 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render demo and match snapshot 1`] = ` +
+
+
+ +
+ Choose Date +
+ +
+
+
+
    +
  • +
    + 2020 +
    +
  • +
  • +
    + 2021 +
    +
  • +
  • +
    + 2022 +
    +
  • +
  • +
    + 2023 +
    +
  • +
  • +
    + 2024 +
    +
  • +
  • +
    + 2025 +
    +
  • +
+
+
+
    +
  • +
    + 01 +
    +
  • +
  • +
    + 02 +
    +
  • +
  • +
    + 03 +
    +
  • +
  • +
    + 04 +
    +
  • +
  • +
    + 05 +
    +
  • +
  • +
    + 06 +
    +
  • +
  • +
    + 07 +
    +
  • +
  • +
    + 08 +
    +
  • +
  • +
    + 09 +
    +
  • +
  • +
    + 10 +
    +
  • +
  • +
    + 11 +
    +
  • +
  • +
    + 12 +
    +
  • +
+
+
+
    +
  • +
    + 01 +
    +
  • +
  • +
    + 02 +
    +
  • +
  • +
    + 03 +
    +
  • +
  • +
    + 04 +
    +
  • +
  • +
    + 05 +
    +
  • +
  • +
    + 06 +
    +
  • +
  • +
    + 07 +
    +
  • +
  • +
    + 08 +
    +
  • +
  • +
    + 09 +
    +
  • +
  • +
    + 10 +
    +
  • +
  • +
    + 11 +
    +
  • +
  • +
    + 12 +
    +
  • +
  • +
    + 13 +
    +
  • +
  • +
    + 14 +
    +
  • +
  • +
    + 15 +
    +
  • +
  • +
    + 16 +
    +
  • +
  • +
    + 17 +
    +
  • +
  • +
    + 18 +
    +
  • +
  • +
    + 19 +
    +
  • +
  • +
    + 20 +
    +
  • +
  • +
    + 21 +
    +
  • +
  • +
    + 22 +
    +
  • +
  • +
    + 23 +
    +
  • +
  • +
    + 24 +
    +
  • +
  • +
    + 25 +
    +
  • +
  • +
    + 26 +
    +
  • +
  • +
    + 27 +
    +
  • +
  • +
    + 28 +
    +
  • +
  • +
    + 29 +
    +
  • +
  • +
    + 30 +
    +
  • +
  • +
    + 31 +
    +
  • +
+
+
+
+
+
+
+
+
+
+
+
+ +
+ Choose Year-Month +
+ +
+
+
+
    +
  • +
    + 2020 +
    +
  • +
  • +
    + 2021 +
    +
  • +
  • +
    + 2022 +
    +
  • +
  • +
    + 2023 +
    +
  • +
  • +
    + 2024 +
    +
  • +
  • +
    + 2025 +
    +
  • +
+
+
+
    +
  • +
    + 01 +
    +
  • +
  • +
    + 02 +
    +
  • +
  • +
    + 03 +
    +
  • +
  • +
    + 04 +
    +
  • +
  • +
    + 05 +
    +
  • +
  • +
    + 06 +
    +
  • +
  • +
    + 07 +
    +
  • +
  • +
    + 08 +
    +
  • +
  • +
    + 09 +
    +
  • +
  • +
    + 10 +
    +
  • +
  • +
    + 11 +
    +
  • +
  • +
    + 12 +
    +
  • +
+
+
+
+
+
+
+
+
+
+
+
+ +
+ Choose Year-Month +
+ +
+
+
+
    +
  • +
    + 2020 Year +
    +
  • +
  • +
    + 2021 Year +
    +
  • +
  • +
    + 2022 Year +
    +
  • +
  • +
    + 2023 Year +
    +
  • +
  • +
    + 2024 Year +
    +
  • +
  • +
    + 2025 Year +
    +
  • +
+
+
+
    +
  • +
    + 01 Month +
    +
  • +
  • +
    + 02 Month +
    +
  • +
  • +
    + 03 Month +
    +
  • +
  • +
    + 04 Month +
    +
  • +
  • +
    + 05 Month +
    +
  • +
  • +
    + 06 Month +
    +
  • +
  • +
    + 07 Month +
    +
  • +
  • +
    + 08 Month +
    +
  • +
  • +
    + 09 Month +
    +
  • +
  • +
    + 10 Month +
    +
  • +
  • +
    + 11 Month +
    +
  • +
  • +
    + 12 Month +
    +
  • +
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
    +
  • +
    + 2020 +
    +
  • +
  • +
    + 2021 +
    +
  • +
  • +
    + 2022 +
    +
  • +
  • +
    + 2023 +
    +
  • +
  • +
    + 2024 +
    +
  • +
  • +
    + 2025 +
    +
  • +
+
+
+
    +
  • +
    + 06 +
    +
  • +
  • +
    + 12 +
    +
  • +
+
+
+
+
+
+
+
+
+`; diff --git a/packages/vant/src/date-picker/test/date-picker.legacy.ts b/packages/vant/src/date-picker/test/date-picker.legacy.ts new file mode 100644 index 000000000..a4dff6036 --- /dev/null +++ b/packages/vant/src/date-picker/test/date-picker.legacy.ts @@ -0,0 +1,220 @@ +// import DatePicker from '../../datetime-picker/DatePicker'; +// import { mount, later, triggerDrag } from '../../../test'; + +// function filter(type: string, options: string[]): string[] { +// const mod = type === 'year' ? 10 : 5; +// return options.filter((option: string) => Number(option) % mod === 0); +// } + +// function formatter(type: string, value: string): string { +// return `${value} ${type}`; +// } + +// test('filter prop', async () => { +// const wrapper = mount(DatePicker, { +// props: { +// filter, +// minDate: new Date(2020, 0, 1), +// maxDate: new Date(2025, 10, 1), +// modelValue: new Date(2020, 10, 1, 0, 0), +// }, +// }); + +// expect(wrapper.html()).toMatchSnapshot(); +// }); + +// test('formatter prop', async () => { +// const wrapper = mount(DatePicker, { +// props: { +// filter, +// formatter, +// minDate: new Date(2010, 0, 1), +// maxDate: new Date(2025, 10, 1), +// modelValue: new Date(2020, 10, 1, 0, 0), +// }, +// }); + +// expect(wrapper.html()).toMatchSnapshot(); + +// triggerDrag(wrapper.find('.van-picker-column'), 0, -100); +// wrapper.find('.van-picker-column ul').trigger('transitionend'); +// await later(); + +// expect((wrapper.vm as Record).getPicker().getValues()).toEqual([ +// '2020 year', +// '05 month', +// '05 day', +// '00 hour', +// '00 minute', +// ]); +// }); + +// test('confirm event', () => { +// const date = new Date(2020, 10, 1, 0, 0); + +// const wrapper = mount(DatePicker, { +// props: { +// modelValue: date, +// minDate: new Date(2020, 0, 1), +// maxDate: new Date(2025, 10, 1), +// }, +// }); + +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![0][0].getFullYear()).toEqual(2020); + +// triggerDrag(wrapper.find('.van-picker-column'), 0, -100); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![1][0].getFullYear()).toEqual(2025); +// }); + +// test('year-month type', async () => { +// const date = new Date(2020, 10, 1, 0, 0); + +// const wrapper = mount(DatePicker, { +// props: { +// type: 'year-month', +// modelValue: date, +// minDate: new Date(2020, 0, 1), +// maxDate: new Date(2025, 10, 1), +// }, +// }); + +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![0][0].getFullYear()).toEqual(2020); +// expect(wrapper.emitted<[Date]>('confirm')![0][0].getMonth()).toEqual(10); + +// triggerDrag(wrapper.find('.van-picker-column'), 0, -100); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![1][0].getFullYear()).toEqual(2025); +// expect(wrapper.emitted<[Date]>('confirm')![1][0].getMonth()).toEqual(0); + +// triggerDrag(wrapper.findAll('.van-picker-column')[0], 0, -100); +// await later(); +// triggerDrag(wrapper.findAll('.van-picker-column')[1], 0, -100); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![2][0].getFullYear()).toEqual(2025); +// expect(wrapper.emitted<[Date]>('confirm')![2][0].getMonth()).toEqual(10); +// }); + +// test('month-day type', async () => { +// const date = new Date(2020, 10, 1, 0, 0); + +// const wrapper = mount(DatePicker, { +// props: { +// type: 'month-day', +// modelValue: date, +// minDate: new Date(2020, 0, 1), +// maxDate: new Date(2025, 10, 1), +// }, +// }); + +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![0][0].getMonth()).toEqual(10); +// expect(wrapper.emitted<[Date]>('confirm')![0][0].getDate()).toEqual(1); + +// triggerDrag(wrapper.find('.van-picker-column'), 0, -300); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![1][0].getMonth()).toEqual(11); +// expect(wrapper.emitted<[Date]>('confirm')![1][0].getDate()).toEqual(1); + +// triggerDrag(wrapper.find('.van-picker-column'), 0, -300); +// await later(); +// triggerDrag(wrapper.findAll('.van-picker-column')[1], 0, -300); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![2][0].getMonth()).toEqual(11); +// expect(wrapper.emitted<[Date]>('confirm')![2][0].getDate()).toEqual(31); +// }); + +// test('datehour type', () => { +// const wrapper = mount(DatePicker, { +// props: { +// minDate: new Date(2010, 0, 1), +// maxDate: new Date(2025, 10, 1), +// modelValue: new Date(2020, 10, 1, 0, 0), +// }, +// }); + +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![0][0].getHours()).toEqual(0); + +// triggerDrag(wrapper.findAll('.van-picker-column')[3], 0, -300); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![1][0].getHours()).toEqual(23); +// }); + +// test('cancel event', () => { +// const wrapper = mount(DatePicker); + +// wrapper.find('.van-picker__cancel').trigger('click'); +// expect(wrapper.emitted('cancel')).toBeTruthy(); +// }); + +// test('max-date prop', () => { +// const maxDate = new Date(2010, 5, 0, 0, 0); +// const wrapper = mount(DatePicker, { +// props: { +// modelValue: new Date(2020, 10, 30, 30, 30), +// maxDate, +// }, +// }); + +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual(maxDate); +// }); + +// test('min-date prop', () => { +// const minDate = new Date(2030, 0, 0, 0, 0); +// const wrapper = mount(DatePicker, { +// props: { +// modelValue: new Date(2020, 0, 0, 0, 0), +// minDate, +// }, +// }); + +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual(minDate); +// }); + +// test('dynamic set value', async () => { +// const wrapper = mount(DatePicker, { +// props: { +// modelValue: new Date(2019, 1, 1), +// }, +// }); + +// await wrapper.setProps({ modelValue: new Date(2019, 1, 1) }); +// wrapper.find('.van-picker__confirm').trigger('click'); +// await wrapper.setProps({ modelValue: new Date(2025, 1, 1) }); +// wrapper.find('.van-picker__confirm').trigger('click'); + +// expect(wrapper.emitted<[Date]>('confirm')![0][0].getFullYear()).toEqual(2019); +// expect(wrapper.emitted<[Date]>('confirm')![1][0].getFullYear()).toEqual(2025); +// }); + +// test('use min-date with filter', async () => { +// const minDate = new Date(2030, 0, 0, 0, 3); +// const maxDate = new Date(2040, 0, 0, 0, 0); + +// const wrapper = mount(DatePicker, { +// props: { +// minDate, +// maxDate, +// modelValue: new Date(2020, 0, 0, 0, 0), +// filter(type: string, values: string[]) { +// if (type === 'minute') { +// return values.filter((value) => Number(value) % 30 === 0); +// } + +// return values; +// }, +// }, +// }); + +// await later(); + +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual( +// new Date(2030, 0, 0, 0, 30) +// ); +// }); diff --git a/packages/vant/src/date-picker/test/datetime-picker.legacy.tsx b/packages/vant/src/date-picker/test/datetime-picker.legacy.tsx new file mode 100644 index 000000000..1313053be --- /dev/null +++ b/packages/vant/src/date-picker/test/datetime-picker.legacy.tsx @@ -0,0 +1,116 @@ +// import { DatetimePicker } from '../../datetime-picker'; +// import { mount, later } from '../../../test'; +// import { reactive } from 'vue'; +// import { useExpose } from '../../composables/use-expose'; + +// test('should emit confirm event after clicking the confirm button', () => { +// const onConfirm = jest.fn(); +// const wrapper = mount(DatetimePicker, { +// props: { +// onConfirm, +// }, +// }); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(onConfirm).toHaveBeenCalledTimes(1); +// }); + +// test('should emit cancel event after clicking the confirm button', () => { +// const onCancel = jest.fn(); +// const wrapper = mount(DatetimePicker, { +// props: { +// onCancel, +// }, +// }); +// wrapper.find('.van-picker__cancel').trigger('click'); +// expect(onCancel).toHaveBeenCalledTimes(1); +// }); + +// test('should allow to call getPicker method', () => { +// const wrapper = mount(DatetimePicker); + +// expect(wrapper.vm.getPicker()).toBeTruthy(); +// }); + +// test('should render title slot correctly', () => { +// const wrapper = mount(DatetimePicker, { +// props: { +// showToolbar: true, +// }, +// slots: { +// title: () => 'Custom title', +// }, +// }); + +// expect(wrapper.find('.van-picker__toolbar').html()).toMatchSnapshot(); +// }); + +// test('should emit value correctly when dynamic change min-date', async () => { +// const defaultValue = new Date(2020, 10, 2, 10, 30); +// const wrapper = mount({ +// emits: ['confirm'], +// setup(_, { emit }) { +// const state = reactive({ +// date: defaultValue, +// minDate: new Date(2010, 0, 1, 10, 30), +// }); + +// const onChange = () => { +// state.minDate = state.date; +// }; + +// useExpose({ +// onChange, +// }); + +// return () => ( +// emit('confirm', value)} +// /> +// ); +// }, +// }); + +// await later(); +// (wrapper.vm as Record).onChange(); +// await later(); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual(defaultValue); +// }); + +// test('should update value correctly after calling setColumnIndex method', async () => { +// const onConfirm = jest.fn(); +// const defaultDate = new Date(2020, 0, 1); +// const wrapper = mount(DatetimePicker, { +// props: { +// type: 'date', +// minDate: defaultDate, +// maxDate: new Date(2020, 0, 30), +// modelValue: defaultDate, +// onConfirm, +// }, +// }); + +// wrapper.vm.getPicker().setColumnIndex(2, 14); +// await wrapper.find('.van-picker__confirm').trigger('click'); +// expect(onConfirm.mock.calls[0]).toEqual([new Date(2020, 0, 15)]); +// }); + +// test('should update value correctly after calling setColumnValue method', async () => { +// const onConfirm = jest.fn(); +// const defaultDate = new Date(2020, 0, 1); +// const wrapper = mount(DatetimePicker, { +// props: { +// type: 'date', +// minDate: defaultDate, +// maxDate: new Date(2020, 0, 30), +// modelValue: defaultDate, +// onConfirm, +// }, +// }); + +// wrapper.vm.getPicker().setColumnValue(2, '15'); +// await wrapper.find('.van-picker__confirm').trigger('click'); +// expect(onConfirm.mock.calls[0]).toEqual([new Date(2020, 0, 15)]); +// }); diff --git a/packages/vant/src/date-picker/test/demo.spec.ts b/packages/vant/src/date-picker/test/demo.spec.ts new file mode 100644 index 000000000..c0e0c95b9 --- /dev/null +++ b/packages/vant/src/date-picker/test/demo.spec.ts @@ -0,0 +1,4 @@ +import Demo from '../demo/index.vue'; +import { snapshotDemo } from '../../../test/demo'; + +snapshotDemo(Demo); diff --git a/packages/vant/src/date-picker/test/index.legacy.ts b/packages/vant/src/date-picker/test/index.legacy.ts new file mode 100644 index 000000000..f490ec9c2 --- /dev/null +++ b/packages/vant/src/date-picker/test/index.legacy.ts @@ -0,0 +1,59 @@ +// import { later, mount, triggerDrag } from '../../../test'; +// import DatePicker from '../../datetime-picker/DatePicker'; + +// test('month-day type', async () => { +// const date = new Date(2020, 10, 1, 0, 0); + +// const wrapper = mount(DatePicker, { +// props: { +// type: 'month-day', +// modelValue: date, +// minDate: new Date(2020, 0, 1), +// maxDate: new Date(2025, 10, 1), +// }, +// }); + +// await later(); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![0][0].getMonth()).toEqual(10); +// expect(wrapper.emitted<[Date]>('confirm')![0][0].getDate()).toEqual(1); + +// await later(); +// triggerDrag(wrapper.find('.van-picker-column'), 0, -300); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![1][0].getMonth()).toEqual(11); +// expect(wrapper.emitted<[Date]>('confirm')![1][0].getDate()).toEqual(1); + +// await later(); +// triggerDrag(wrapper.findAll('.van-picker-column')[1], 0, -300); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![2][0].getMonth()).toEqual(11); +// expect(wrapper.emitted<[Date]>('confirm')![2][0].getDate()).toEqual(31); +// }); + +// test('v-model', async () => { +// const minDate = new Date(2030, 0, 0, 0, 3); + +// const wrapper = mount(DatePicker, { +// props: { +// minDate, +// }, +// }); + +// await later(); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual(minDate); +// }); + +// test('value has an initial value', async () => { +// const defaultValue = new Date(2020, 0, 0, 0, 0); +// const wrapper = mount(DatePicker, { +// propsData: { +// modelValue: defaultValue, +// }, +// }); + +// await later(); +// wrapper.find('.van-picker__confirm').trigger('click'); +// expect(wrapper.emitted<[Date]>('confirm')![0][0]).toEqual(defaultValue); +// }); diff --git a/packages/vant/src/date-picker/utils.ts b/packages/vant/src/date-picker/utils.ts new file mode 100644 index 000000000..4f2d701b0 --- /dev/null +++ b/packages/vant/src/date-picker/utils.ts @@ -0,0 +1,38 @@ +import { extend } from '../utils'; +import { pickerSharedProps } from '../picker/Picker'; +import type { PropType } from 'vue'; +import type { PickerOption } from '../picker'; + +export const sharedProps = extend({}, pickerSharedProps, { + filter: Function as PropType< + (columnType: string, options: PickerOption[]) => PickerOption[] + >, + formatter: { + type: Function as PropType< + (type: string, option: PickerOption) => PickerOption + >, + default: (type: string, option: PickerOption) => option, + }, +}); + +export const pickerInheritKeys = Object.keys(pickerSharedProps) as Array< + keyof typeof pickerSharedProps +>; + +export function times(n: number, iteratee: (index: number) => T) { + if (n < 0) { + return []; + } + + const result: T[] = Array(n); + + let index = -1; + while (++index < n) { + result[index] = iteratee(index); + } + + return result; +} + +export const getMonthEndDay = (year: number, month: number): number => + 32 - new Date(year, month - 1, 32).getDate(); diff --git a/packages/vant/src/time-picker/TimePicker.tsx b/packages/vant/src/time-picker/TimePicker.tsx index 34d67b5a4..7086238cc 100644 --- a/packages/vant/src/time-picker/TimePicker.tsx +++ b/packages/vant/src/time-picker/TimePicker.tsx @@ -15,11 +15,7 @@ import { createNamespace, makeNumericProp, } from '../utils'; -import { - times, - sharedProps, - pickerInheritKeys, -} from '../datetime-picker/utils'; +import { times, sharedProps, pickerInheritKeys } from '../date-picker/utils'; // Components import { Picker } from '../picker';