Compare commits

...

4 Commits

Author SHA1 Message Date
neverland
922872522e
docs(changelog): vant@4.0.0-rc.5 (#11125) 2022-10-07 23:35:26 +08:00
chenjiahan
bbb6a6ef2a release: 4.0.0-rc.5 2022-10-07 23:32:35 +08:00
neverland
9c6b416bfb
test(DatePicker): migrate legacy test cases (#11123) 2022-10-07 23:24:03 +08:00
neverland
baa9c33dd4
fix(DatePicker): format value when exceed max date (#11122) 2022-10-07 23:04:56 +08:00
11 changed files with 480 additions and 406 deletions

View File

@ -19,6 +19,23 @@ Vant follows [Semantic Versioning 2.0.0](https://semver.org/lang/zh-CN/).
## Details
### [v4.0.0-rc.5](https://github.com/vant-ui/vant/compare/v4.0.0-rc.4...v4.0.0-rc.5)
`2022-10-07`
**Feature**
- Field: support label-position top [#11102](https://github.com/vant-ui/vant/issues/11102)
- Loading: add icon slot [#11109](https://github.com/vant-ui/vant/issues/11109)
- NavBar: add clickable prop [#11048](https://github.com/vant-ui/vant/issues/11048)
- Stepper: add auto-fixed prop [#11071](https://github.com/vant-ui/vant/issues/11071)
**Bug Fixes**
- DatePicker: format value when exceed max date [#11122](https://github.com/vant-ui/vant/issues/11122)
- Tabs: incorrect nav scroll animation in some cases [#11116](https://github.com/vant-ui/vant/issues/11116)
- Tabs: scroll position when using nav-bottom slot [#11115](https://github.com/vant-ui/vant/issues/11115)
### [v4.0.0-rc.4](https://github.com/vant-ui/vant/compare/v4.0.0-rc.3...v4.0.0-rc.4)
`2022-09-25`

View File

@ -19,6 +19,23 @@ Vant 遵循 [Semver](https://semver.org/lang/zh-CN/) 语义化版本规范。
## 更新内容
### [v4.0.0-rc.5](https://github.com/vant-ui/vant/compare/v4.0.0-rc.4...v4.0.0-rc.5)
`2022-10-07`
**Feature**
- Field: 支持将 label-position 设置为 top [#11102](https://github.com/vant-ui/vant/issues/11102)
- Loading: 新增 icon 插槽 [#11109](https://github.com/vant-ui/vant/issues/11109)
- NavBar: 新增 clickable 属性 [#11048](https://github.com/vant-ui/vant/issues/11048)
- Stepper: 新增 auto-fixed 属性 [#11071](https://github.com/vant-ui/vant/issues/11071)
**Bug Fixes**
- DatePicker: 修复日期超出 maxDate 时格式化不正确的问题 [#11122](https://github.com/vant-ui/vant/issues/11122)
- Tabs: 修复开启 scrollspy 时个别情况下标题栏滚动位置错误的问题 [#11116](https://github.com/vant-ui/vant/issues/11116)
- Tabs: 修复开启 scrollspy 时 nav-bottom 插槽遮挡内容的问题 [#11115](https://github.com/vant-ui/vant/issues/11115)
### [v4.0.0-rc.4](https://github.com/vant-ui/vant/compare/v4.0.0-rc.3...v4.0.0-rc.4)
`2022-09-25`

View File

@ -1,6 +1,6 @@
{
"name": "vant",
"version": "4.0.0-rc.4",
"version": "4.0.0-rc.5",
"description": "Mobile UI Components built on Vue",
"main": "lib/vant.cjs.js",
"module": "es/index.mjs",

View File

@ -14,6 +14,7 @@ import {
sharedProps,
getMonthEndDay,
pickerInheritKeys,
formatValueRange,
} from './utils';
// Components
@ -143,9 +144,13 @@ export default defineComponent({
watch(
() => props.modelValue,
(newValues) => {
newValues = formatValueRange(newValues, columns.value);
if (!isSameValue(newValues, currentValues.value)) {
currentValues.value = newValues;
}
},
{
immediate: true,
}
);

View File

@ -0,0 +1,219 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should filter options when using filter prop 1`] = `
<div class="van-picker">
<div class="van-picker__toolbar">
<button type="button"
class="van-picker__cancel van-haptics-feedback"
>
Cancel
</button>
<button type="button"
class="van-picker__confirm van-haptics-feedback"
>
Confirm
</button>
</div>
<div class="van-picker__columns"
style="height: 264px;"
>
<div class="van-picker-column">
<ul style="transform: translate3d(0, 110px, 0); transition-duration: 0ms; transition-property: none;"
class="van-picker-column__wrapper"
>
<li role="button"
style="height: 44px;"
tabindex="0"
class="van-picker-column__item van-picker-column__item--selected"
>
<div class="van-ellipsis">
2000
</div>
</li>
<li role="button"
style="height: 44px;"
tabindex="0"
class="van-picker-column__item"
>
<div class="van-ellipsis">
2010
</div>
</li>
</ul>
</div>
<div class="van-picker-column">
<ul style="transform: translate3d(0, 110px, 0); transition-duration: 0ms; transition-property: none;"
class="van-picker-column__wrapper"
>
<li role="button"
style="height: 44px;"
tabindex="0"
class="van-picker-column__item van-picker-column__item--selected"
>
<div class="van-ellipsis">
10
</div>
</li>
</ul>
</div>
<div class="van-picker-column">
<ul style="transform: translate3d(0, 110px, 0); transition-duration: 0ms; transition-property: none;"
class="van-picker-column__wrapper"
>
<li role="button"
style="height: 44px;"
tabindex="0"
class="van-picker-column__item van-picker-column__item--selected"
>
<div class="van-ellipsis">
10
</div>
</li>
<li role="button"
style="height: 44px;"
tabindex="0"
class="van-picker-column__item"
>
<div class="van-ellipsis">
20
</div>
</li>
<li role="button"
style="height: 44px;"
tabindex="0"
class="van-picker-column__item"
>
<div class="van-ellipsis">
30
</div>
</li>
</ul>
</div>
<div class="van-picker__mask"
style="background-size: 100% 110px;"
>
</div>
<div class="van-hairline-unset--top-bottom van-picker__frame"
style="height: 44px;"
>
</div>
</div>
</div>
`;
exports[`should format options correctly when using formatter prop 1`] = `
<div class="van-picker">
<div class="van-picker__toolbar">
<button type="button"
class="van-picker__cancel van-haptics-feedback"
>
Cancel
</button>
<button type="button"
class="van-picker__confirm van-haptics-feedback"
>
Confirm
</button>
</div>
<div class="van-picker__columns"
style="height: 264px;"
>
<div class="van-picker-column">
<ul style="transform: translate3d(0, 110px, 0); transition-duration: 0ms; transition-property: none;"
class="van-picker-column__wrapper"
>
<li role="button"
style="height: 44px;"
tabindex="0"
class="van-picker-column__item van-picker-column__item--selected"
>
<div class="van-ellipsis">
2000 year
</div>
</li>
<li role="button"
style="height: 44px;"
tabindex="0"
class="van-picker-column__item"
>
<div class="van-ellipsis">
2010 year
</div>
</li>
</ul>
</div>
<div class="van-picker-column">
<ul style="transform: translate3d(0, 110px, 0); transition-duration: 0ms; transition-property: none;"
class="van-picker-column__wrapper"
>
<li role="button"
style="height: 44px;"
tabindex="0"
class="van-picker-column__item van-picker-column__item--selected"
>
<div class="van-ellipsis">
10 month
</div>
</li>
</ul>
</div>
<div class="van-picker-column">
<ul style="transform: translate3d(0, 110px, 0); transition-duration: 0ms; transition-property: none;"
class="van-picker-column__wrapper"
>
<li role="button"
style="height: 44px;"
tabindex="0"
class="van-picker-column__item van-picker-column__item--selected"
>
<div class="van-ellipsis">
10 day
</div>
</li>
<li role="button"
style="height: 44px;"
tabindex="0"
class="van-picker-column__item"
>
<div class="van-ellipsis">
20 day
</div>
</li>
<li role="button"
style="height: 44px;"
tabindex="0"
class="van-picker-column__item"
>
<div class="van-ellipsis">
30 day
</div>
</li>
</ul>
</div>
<div class="van-picker__mask"
style="background-size: 100% 110px;"
>
</div>
<div class="van-hairline-unset--top-bottom van-picker__frame"
style="height: 44px;"
>
</div>
</div>
</div>
`;
exports[`should render title slot correctly 1`] = `
<div class="van-picker__toolbar">
<button type="button"
class="van-picker__cancel van-haptics-feedback"
>
Cancel
</button>
Custom title
<button type="button"
class="van-picker__confirm van-haptics-feedback"
>
Confirm
</button>
</div>
`;

View File

@ -1,220 +0,0 @@
// 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<string, any>).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)
// );
// });

View File

@ -1,116 +0,0 @@
// 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 () => (
// <DatetimePicker
// v-model={state.date}
// minDate={state.minDate}
// onConfirm={(value: Date) => emit('confirm', value)}
// />
// );
// },
// });
// await later();
// (wrapper.vm as Record<string, any>).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)]);
// });

View File

@ -1,59 +0,0 @@
// 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);
// });

View File

@ -0,0 +1,200 @@
import { nextTick } from 'vue';
import { later, mount } from '../../../test';
import DatePicker from '..';
import type {
PickerOption,
PickerCancelEventParams,
PickerConfirmEventParams,
} from '../../picker';
test('should emit confirm event correctly', async () => {
const minDate = new Date(2030, 0, 1);
const wrapper = mount(DatePicker, {
props: {
minDate,
},
});
await later();
wrapper.find('.van-picker__confirm').trigger('click');
expect(wrapper.emitted<[PickerConfirmEventParams]>('confirm')![0][0]).toEqual(
{
selectedOptions: [
{ text: '2030', value: '2030' },
{ text: '01', value: '01' },
{ text: '01', value: '01' },
],
selectedValues: ['2030', '01', '01'],
}
);
});
test('should emit cancel event correctly', async () => {
const minDate = new Date(2030, 0, 1);
const wrapper = mount(DatePicker, {
props: {
minDate,
},
});
await later();
wrapper.find('.van-picker__cancel').trigger('click');
expect(wrapper.emitted<[PickerCancelEventParams]>('cancel')![0][0]).toEqual({
selectedOptions: [
{ text: '2030', value: '2030' },
{ text: '01', value: '01' },
{ text: '01', value: '01' },
],
selectedValues: ['2030', '01', '01'],
});
});
test('should allow to dynamically set value', async () => {
const wrapper = mount(DatePicker, {
props: {
modelValue: ['2020', '01', '01'],
minDate: new Date(2019, 0, 1),
},
});
await wrapper.setProps({ modelValue: ['2020', '02', '02'] });
await wrapper.find('.van-picker__confirm').trigger('click');
await wrapper.setProps({ modelValue: ['2020', '03', '03'] });
await wrapper.find('.van-picker__confirm').trigger('click');
expect(
wrapper.emitted<[PickerConfirmEventParams]>('confirm')![0][0].selectedValues
).toEqual(['2020', '02', '02']);
expect(
wrapper.emitted<[PickerConfirmEventParams]>('confirm')![1][0].selectedValues
).toEqual(['2020', '03', '03']);
});
test('should render with max-date correctly', async () => {
const maxDate = new Date(2010, 1, 1);
const minDate = new Date(2000, 1, 1);
const wrapper = mount(DatePicker, {
props: {
modelValue: ['2020', '10', '10'],
minDate,
maxDate,
'onUpdate:modelValue': (newVal: string[]) => {
nextTick(() => {
wrapper.setProps({
modelValue: newVal,
});
});
},
},
});
await later();
wrapper.find('.van-picker__confirm').trigger('click');
expect(
wrapper.emitted<[PickerConfirmEventParams]>('confirm')![0][0].selectedValues
).toEqual(['2010', '01', '10']);
});
test('should render with min-date correctly', async () => {
const maxDate = new Date(2010, 1, 1);
const minDate = new Date(2000, 1, 1);
const wrapper = mount(DatePicker, {
props: {
modelValue: ['1990', '10', '10'],
minDate,
maxDate,
'onUpdate:modelValue': (newVal: string[]) => {
nextTick(() => {
wrapper.setProps({
modelValue: newVal,
});
});
},
},
});
await later();
wrapper.find('.van-picker__confirm').trigger('click');
expect(
wrapper.emitted<[PickerConfirmEventParams]>('confirm')![0][0].selectedValues
).toEqual(['2000', '10', '10']);
});
test('should render title slot correctly', () => {
const wrapper = mount(DatePicker, {
slots: {
title: () => 'Custom title',
},
});
expect(wrapper.find('.van-picker__toolbar').html()).toMatchSnapshot();
});
function filter(type: string, options: PickerOption[]): PickerOption[] {
return options.filter((option) => Number(option.value) % 10 === 0);
}
test('should filter options when using filter prop', () => {
const maxDate = new Date(2010, 1, 1);
const minDate = new Date(2000, 1, 1);
const wrapper = mount(DatePicker, {
props: {
filter,
maxDate,
minDate,
modelValue: ['2005', '01', '01'],
},
});
expect(wrapper.html()).toMatchSnapshot();
});
test('should format options correctly when using formatter prop', async () => {
const formatter = (type: string, option: PickerOption): PickerOption => {
option.text = `${option.text} ${type}`;
return option;
};
const maxDate = new Date(2010, 1, 1);
const minDate = new Date(2000, 1, 1);
const wrapper = mount(DatePicker, {
props: {
filter,
formatter,
maxDate,
minDate,
modelValue: ['2005', '01', '01'],
},
});
expect(wrapper.html()).toMatchSnapshot();
});
test('should update value correctly when dynamically change min-date', async () => {
const maxDate = new Date(2050, 1, 1);
const minDate = new Date(2000, 1, 1);
const wrapper = mount(DatePicker, {
props: {
modelValue: ['2005', '10', '10'],
minDate,
maxDate,
'onUpdate:modelValue': (newVal: string[]) => {
nextTick(() => {
wrapper.setProps({
modelValue: newVal,
});
});
},
},
});
await later();
await wrapper.setProps({
minDate: new Date(2020, 11, 20),
});
wrapper.find('.van-picker__confirm').trigger('click');
expect(
wrapper.emitted<[PickerConfirmEventParams]>('confirm')![0][0].selectedValues
).toEqual(['2020', '12', '20']);
});

View File

@ -53,3 +53,15 @@ export const genOptions = <T extends string>(
});
return filter ? filter(type, options) : options;
};
export const formatValueRange = (values: string[], columns: PickerOption[]) =>
values.map((value, index) => {
const column = columns[index];
if (column.length) {
const maxValue = +column[column.length - 1].value!;
if (+value > maxValue) {
return String(maxValue);
}
}
return value;
});

View File

@ -19,6 +19,7 @@ import {
genOptions,
sharedProps,
pickerInheritKeys,
formatValueRange,
} from '../date-picker/utils';
// Components
@ -89,23 +90,21 @@ export default defineComponent({
})
);
watch(
currentValues,
(newValues) => {
if (!isSameValue(newValues, props.modelValue)) {
emit('update:modelValue', newValues);
}
},
{ immediate: true }
);
watch(currentValues, (newValues) => {
if (!isSameValue(newValues, props.modelValue)) {
emit('update:modelValue', newValues);
}
});
watch(
() => props.modelValue,
(newValues) => {
newValues = formatValueRange(newValues, columns.value);
if (!isSameValue(newValues, currentValues.value)) {
currentValues.value = newValues;
}
}
},
{ immediate: true }
);
const onChange = (...args: unknown[]) => emit('change', ...args);