From 8c6b05aa62a7799b16d1c98cfd1cc3c67c07647e Mon Sep 17 00:00:00 2001 From: neverland Date: Mon, 29 Jul 2019 20:20:09 +0800 Subject: [PATCH] [improvement] DatetimePicker: split into two components (#3995) --- src/datetime-picker/DatePicker.js | 210 +++++++++++ src/datetime-picker/TimePicker.js | 118 +++++++ src/datetime-picker/index.js | 326 +----------------- src/datetime-picker/shared.js | 71 ++++ .../__snapshots__/date-picker.spec.js.snap | 125 +++++++ .../test/__snapshots__/demo.spec.js.snap | 10 +- .../__snapshots__/time-picker.spec.js.snap | 125 +++++++ src/datetime-picker/test/date-picker.spec.js | 112 ++++++ src/datetime-picker/test/time-picker.spec.js | 94 +++++ src/picker/test/index.spec.js | 6 +- 10 files changed, 873 insertions(+), 324 deletions(-) create mode 100644 src/datetime-picker/DatePicker.js create mode 100644 src/datetime-picker/TimePicker.js create mode 100644 src/datetime-picker/shared.js create mode 100644 src/datetime-picker/test/__snapshots__/date-picker.spec.js.snap create mode 100644 src/datetime-picker/test/__snapshots__/time-picker.spec.js.snap create mode 100644 src/datetime-picker/test/date-picker.spec.js create mode 100644 src/datetime-picker/test/time-picker.spec.js diff --git a/src/datetime-picker/DatePicker.js b/src/datetime-picker/DatePicker.js new file mode 100644 index 000000000..6d6b12e75 --- /dev/null +++ b/src/datetime-picker/DatePicker.js @@ -0,0 +1,210 @@ +import { createNamespace } from '../utils'; +import { isDate } from '../utils/validate/date'; +import { padZero } from '../utils/format/string'; +import { pickerProps } from '../picker/shared'; +import { getTrueValue, getMonthEndDay } from './utils'; +import { sharedProps, TimePickerMixin } from './shared'; +import Picker from '../picker'; + +const currentYear = new Date().getFullYear(); +const [createComponent, bem] = createNamespace('date-picker'); + +export default createComponent({ + mixins: [TimePickerMixin], + + props: { + ...sharedProps, + type: { + type: String, + default: 'datetime' + }, + minDate: { + type: Date, + default: () => new Date(currentYear - 10, 0, 1), + validator: isDate + }, + maxDate: { + type: Date, + default: () => new Date(currentYear + 10, 11, 31), + validator: isDate + } + }, + + watch: { + value(val) { + val = this.formatValue(val); + + if (val.valueOf() !== this.innerValue.valueOf()) { + this.innerValue = val; + } + } + }, + + computed: { + ranges() { + const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = this.getBoundary( + 'max', + this.innerValue + ); + + const { minYear, minDate, minMonth, minHour, minMinute } = this.getBoundary( + 'min', + this.innerValue + ); + + const result = [ + { + type: 'year', + range: [minYear, maxYear] + }, + { + type: 'month', + range: [minMonth, maxMonth] + }, + { + type: 'day', + range: [minDate, maxDate] + }, + { + type: 'hour', + range: [minHour, maxHour] + }, + { + type: 'minute', + range: [minMinute, maxMinute] + } + ]; + + if (this.type === 'date') result.splice(3, 2); + if (this.type === 'year-month') result.splice(2, 3); + return result; + } + }, + + methods: { + formatValue(value) { + if (!isDate(value)) { + value = this.minDate; + } + + value = Math.max(value, this.minDate.getTime()); + value = Math.min(value, this.maxDate.getTime()); + + return new Date(value); + }, + + getBoundary(type, value) { + const boundary = this[`${type}Date`]; + const year = boundary.getFullYear(); + let month = 1; + let date = 1; + let hour = 0; + let minute = 0; + + if (type === 'max') { + month = 12; + date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1); + hour = 23; + minute = 59; + } + + if (value.getFullYear() === year) { + month = boundary.getMonth() + 1; + if (value.getMonth() + 1 === month) { + date = boundary.getDate(); + if (value.getDate() === date) { + hour = boundary.getHours(); + if (value.getHours() === hour) { + minute = boundary.getMinutes(); + } + } + } + } + + return { + [`${type}Year`]: year, + [`${type}Month`]: month, + [`${type}Date`]: date, + [`${type}Hour`]: hour, + [`${type}Minute`]: minute + }; + }, + + onChange(picker) { + const values = picker.getValues(); + const year = getTrueValue(values[0]); + const month = getTrueValue(values[1]); + const maxDate = getMonthEndDay(year, month); + + let date = getTrueValue(values[2]); + if (this.type === 'year-month') { + date = 1; + } + + date = date > maxDate ? maxDate : date; + + let hour = 0; + let minute = 0; + + if (this.type === 'datetime') { + hour = getTrueValue(values[3]); + minute = getTrueValue(values[4]); + } + + const value = new Date(year, month - 1, date, hour, minute); + + this.innerValue = this.formatValue(value); + + this.$nextTick(() => { + this.$nextTick(() => { + this.$emit('change', picker); + }); + }); + }, + + updateColumnValue(value) { + const { formatter } = this; + let values = [ + formatter('year', `${value.getFullYear()}`), + formatter('month', padZero(value.getMonth() + 1)), + formatter('day', padZero(value.getDate())) + ]; + + if (this.type === 'datetime') { + values.push( + formatter('hour', padZero(value.getHours())), + formatter('minute', padZero(value.getMinutes())) + ); + } + + if (this.type === 'year-month') { + values = values.slice(0, 2); + } + + this.$nextTick(() => { + this.$refs.picker.setValues(values); + }); + } + }, + + render() { + const props = {}; + Object.keys(pickerProps).forEach(key => { + props[key] = this[key]; + }); + + return ( + { + this.$emit('cancel'); + }} + {...{ props }} + /> + ); + } +}); diff --git a/src/datetime-picker/TimePicker.js b/src/datetime-picker/TimePicker.js new file mode 100644 index 000000000..8d2a4554a --- /dev/null +++ b/src/datetime-picker/TimePicker.js @@ -0,0 +1,118 @@ +import { createNamespace } from '../utils'; +import { padZero } from '../utils/format/string'; +import { range } from '../utils/format/number'; +import { pickerProps } from '../picker/shared'; +import { sharedProps, TimePickerMixin } from './shared'; +import Picker from '../picker'; + +const [createComponent, bem] = createNamespace('time-picker'); + +export default createComponent({ + mixins: [TimePickerMixin], + + props: { + ...sharedProps, + minHour: { + type: Number, + default: 0 + }, + maxHour: { + type: Number, + default: 23 + }, + minMinute: { + type: Number, + default: 0 + }, + maxMinute: { + type: Number, + default: 59 + } + }, + + computed: { + ranges() { + return [ + { + type: 'hour', + range: [this.minHour, this.maxHour] + }, + { + type: 'minute', + range: [this.minMinute, this.maxMinute] + } + ]; + } + }, + + watch: { + value(val) { + val = this.formatValue(val); + + if (val !== this.innerValue) { + this.innerValue = val; + this.updateColumnValue(val); + } + } + }, + + methods: { + formatValue(value) { + if (!value) { + value = `${padZero(this.minHour)}:${padZero(this.minMinute)}`; + } + + let [hour, minute] = value.split(':'); + hour = padZero(range(hour, this.minHour, this.maxHour)); + minute = padZero(range(minute, this.minMinute, this.maxMinute)); + + return `${hour}:${minute}`; + }, + + onChange(picker) { + const indexes = picker.getIndexes(); + const hour = this.originColumns[0].values[indexes[0]]; + const minute = this.originColumns[1].values[indexes[1]]; + const value = `${hour}:${minute}`; + + this.innerValue = this.formatValue(value); + + this.$nextTick(() => { + this.$nextTick(() => { + this.$emit('change', picker); + }); + }); + }, + + updateColumnValue(value) { + const { formatter } = this; + const pair = value.split(':'); + const values = [formatter('hour', pair[0]), formatter('minute', pair[1])]; + + this.$nextTick(() => { + this.$refs.picker.setValues(values); + }); + } + }, + + render() { + const props = {}; + Object.keys(pickerProps).forEach(key => { + props[key] = this[key]; + }); + + return ( + { + this.$emit('cancel'); + }} + {...{ props }} + /> + ); + } +}); diff --git a/src/datetime-picker/index.js b/src/datetime-picker/index.js index d4fbeb7bc..85f142f6d 100644 --- a/src/datetime-picker/index.js +++ b/src/datetime-picker/index.js @@ -1,333 +1,25 @@ import { createNamespace } from '../utils'; -import { range } from '../utils/format/number'; -import { isDate } from '../utils/validate/date'; -import { padZero } from '../utils/format/string'; -import Picker from '../picker'; -import { pickerProps } from '../picker/shared'; -import { times, getTrueValue, getMonthEndDay } from './utils'; +import TimePicker from './TimePicker'; +import DatePicker from './DatePicker'; const [createComponent, bem] = createNamespace('datetime-picker'); -const currentYear = new Date().getFullYear(); export default createComponent({ props: { - ...pickerProps, - value: null, - filter: Function, - minHour: { - type: Number, - default: 0 - }, - minMinute: { - type: Number, - default: 0 - }, - type: { - type: String, - default: 'datetime' - }, - showToolbar: { - type: Boolean, - default: true - }, - formatter: { - type: Function, - default: (type, value) => value - }, - minDate: { - type: Date, - default: () => new Date(currentYear - 10, 0, 1), - validator: isDate - }, - maxDate: { - type: Date, - default: () => new Date(currentYear + 10, 11, 31), - validator: isDate - }, - maxHour: { - type: Number, - default: 23 - }, - maxMinute: { - type: Number, - default: 59 - } - }, - - data() { - return { - innerValue: this.correctValue(this.value) - }; - }, - - watch: { - value(val) { - val = this.correctValue(val); - - const isEqual = - this.type === 'time' - ? val === this.innerValue - : val.valueOf() === this.innerValue.valueOf(); - - if (!isEqual) { - this.innerValue = val; - - if (this.type === 'time') { - this.updateColumnValue(val); - } - } - }, - - innerValue(val) { - this.$emit('input', val); - }, - - columns() { - this.updateColumnValue(this.innerValue); - } - }, - - computed: { - ranges() { - if (this.type === 'time') { - return [ - { - type: 'hour', - range: [this.minHour, this.maxHour] - }, - { - type: 'minute', - range: [this.minMinute, this.maxMinute] - } - ]; - } - - const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = this.getBoundary( - 'max', - this.innerValue - ); - - const { minYear, minDate, minMonth, minHour, minMinute } = this.getBoundary( - 'min', - this.innerValue - ); - - const result = [ - { - type: 'year', - range: [minYear, maxYear] - }, - { - type: 'month', - range: [minMonth, maxMonth] - }, - { - type: 'day', - range: [minDate, maxDate] - }, - { - type: 'hour', - range: [minHour, maxHour] - }, - { - type: 'minute', - range: [minMinute, maxMinute] - } - ]; - - if (this.type === 'date') result.splice(3, 2); - if (this.type === 'year-month') result.splice(2, 3); - return result; - }, - - originColumns() { - return this.ranges.map(({ type, range: rangeArr }) => { - let values = times(rangeArr[1] - rangeArr[0] + 1, index => { - const value = padZero(rangeArr[0] + index); - return value; - }); - - if (this.filter) { - values = this.filter(type, values); - } - - return { - type, - values - }; - }); - }, - - columns() { - return this.originColumns.map(column => ({ - values: column.values.map(value => this.formatter(column.type, value)) - })); - } - }, - - mounted() { - this.updateColumnValue(this.innerValue); - }, - - methods: { - correctValue(value) { - // validate value - const isDateType = this.type !== 'time'; - - if (isDateType && !isDate(value)) { - value = this.minDate; - } else if (!value) { - value = `${padZero(this.minHour)}:00`; - } - - // time type - if (!isDateType) { - let [hour, minute] = value.split(':'); - hour = padZero(range(hour, this.minHour, this.maxHour)); - minute = padZero(range(minute, this.minMinute, this.maxMinute)); - - return `${hour}:${minute}`; - } - - // date type - value = Math.max(value, this.minDate.getTime()); - value = Math.min(value, this.maxDate.getTime()); - - return new Date(value); - }, - - getBoundary(type, value) { - const boundary = this[`${type}Date`]; - const year = boundary.getFullYear(); - let month = 1; - let date = 1; - let hour = 0; - let minute = 0; - - if (type === 'max') { - month = 12; - date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1); - hour = 23; - minute = 59; - } - - if (value.getFullYear() === year) { - month = boundary.getMonth() + 1; - if (value.getMonth() + 1 === month) { - date = boundary.getDate(); - if (value.getDate() === date) { - hour = boundary.getHours(); - if (value.getHours() === hour) { - minute = boundary.getMinutes(); - } - } - } - } - - return { - [`${type}Year`]: year, - [`${type}Month`]: month, - [`${type}Date`]: date, - [`${type}Hour`]: hour, - [`${type}Minute`]: minute - }; - }, - - onConfirm() { - this.$emit('confirm', this.innerValue); - }, - - onChange(picker) { - let value; - - if (this.type === 'time') { - const indexes = picker.getIndexes(); - const hour = this.originColumns[0].values[indexes[0]]; - const minute = this.originColumns[1].values[indexes[1]]; - - value = `${hour}:${minute}`; - } else { - const values = picker.getValues(); - const year = getTrueValue(values[0]); - const month = getTrueValue(values[1]); - const maxDate = getMonthEndDay(year, month); - - let date = getTrueValue(values[2]); - if (this.type === 'year-month') { - date = 1; - } - - date = date > maxDate ? maxDate : date; - - let hour = 0; - let minute = 0; - - if (this.type === 'datetime') { - hour = getTrueValue(values[3]); - minute = getTrueValue(values[4]); - } - - value = new Date(year, month - 1, date, hour, minute); - } - - this.innerValue = this.correctValue(value); - - this.$nextTick(() => { - this.$nextTick(() => { - this.$emit('change', picker); - }); - }); - }, - - updateColumnValue(value) { - let values = []; - const { formatter } = this; - - if (this.type === 'time') { - const pair = value.split(':'); - values = [formatter('hour', pair[0]), formatter('minute', pair[1])]; - } else { - values = [ - formatter('year', `${value.getFullYear()}`), - formatter('month', padZero(value.getMonth() + 1)), - formatter('day', padZero(value.getDate())) - ]; - - if (this.type === 'datetime') { - values.push( - formatter('hour', padZero(value.getHours())), - formatter('minute', padZero(value.getMinutes())) - ); - } - - if (this.type === 'year-month') { - values = values.slice(0, 2); - } - } - - this.$nextTick(() => { - this.$refs.picker.setValues(values); - }); - } + ...TimePicker.props, + ...DatePicker.props }, render() { - const props = {}; - Object.keys(pickerProps).forEach(key => { - props[key] = this[key]; - }); + const Component = this.type === 'time' ? TimePicker : DatePicker; return ( - { - this.$emit('cancel'); + {...{ + props: this.$props, + listeners: this.$listeners }} - {...{ props }} /> ); } diff --git a/src/datetime-picker/shared.js b/src/datetime-picker/shared.js new file mode 100644 index 000000000..5e0491a65 --- /dev/null +++ b/src/datetime-picker/shared.js @@ -0,0 +1,71 @@ +import { times } from './utils'; +import { padZero } from '../utils/format/string'; +import { pickerProps } from '../picker/shared'; + +export const sharedProps = { + ...pickerProps, + value: null, + filter: Function, + showToolbar: { + type: Boolean, + default: true + }, + formatter: { + type: Function, + default: (type, value) => value + } +}; + +export const TimePickerMixin = { + data() { + return { + innerValue: this.formatValue(this.value) + }; + }, + + computed: { + originColumns() { + return this.ranges.map(({ type, range: rangeArr }) => { + let values = times(rangeArr[1] - rangeArr[0] + 1, index => { + const value = padZero(rangeArr[0] + index); + return value; + }); + + if (this.filter) { + values = this.filter(type, values); + } + + return { + type, + values + }; + }); + }, + + columns() { + return this.originColumns.map(column => ({ + values: column.values.map(value => this.formatter(column.type, value)) + })); + } + }, + + watch: { + innerValue(val) { + this.$emit('input', val); + }, + + columns() { + this.updateColumnValue(this.innerValue); + } + }, + + mounted() { + this.updateColumnValue(this.innerValue); + }, + + methods: { + onConfirm() { + this.$emit('confirm', this.innerValue); + } + } +}; diff --git a/src/datetime-picker/test/__snapshots__/date-picker.spec.js.snap b/src/datetime-picker/test/__snapshots__/date-picker.spec.js.snap new file mode 100644 index 000000000..d4d51a215 --- /dev/null +++ b/src/datetime-picker/test/__snapshots__/date-picker.spec.js.snap @@ -0,0 +1,125 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`filter prop 1`] = ` +
+
+
取消
+
确认
+
+ +
+
+
    +
  • 2010
  • +
  • 2020
  • +
+
+
+
    +
  • 05
  • +
  • 10
  • +
+
+
+
    +
  • 05
  • +
  • 10
  • +
  • 15
  • +
  • 20
  • +
  • 25
  • +
  • 30
  • +
+
+
+
    +
  • 00
  • +
  • 05
  • +
  • 10
  • +
  • 15
  • +
  • 20
  • +
+
+
+
    +
  • 00
  • +
  • 05
  • +
  • 10
  • +
  • 15
  • +
  • 20
  • +
  • 25
  • +
  • 30
  • +
  • 35
  • +
  • 40
  • +
  • 45
  • +
  • 50
  • +
  • 55
  • +
+
+
+
+
+ +
+`; + +exports[`formatter prop 1`] = ` +
+
+
取消
+
确认
+
+ +
+
+
    +
  • 2010 year
  • +
  • 2020 year
  • +
+
+
+
    +
  • 05 month
  • +
  • 10 month
  • +
+
+
+
    +
  • 05 day
  • +
  • 10 day
  • +
  • 15 day
  • +
  • 20 day
  • +
  • 25 day
  • +
  • 30 day
  • +
+
+
+
    +
  • 00 hour
  • +
  • 05 hour
  • +
  • 10 hour
  • +
  • 15 hour
  • +
  • 20 hour
  • +
+
+
+
    +
  • 00 minute
  • +
  • 05 minute
  • +
  • 10 minute
  • +
  • 15 minute
  • +
  • 20 minute
  • +
  • 25 minute
  • +
  • 30 minute
  • +
  • 35 minute
  • +
  • 40 minute
  • +
  • 45 minute
  • +
  • 50 minute
  • +
  • 55 minute
  • +
+
+
+
+
+ +
+`; diff --git a/src/datetime-picker/test/__snapshots__/demo.spec.js.snap b/src/datetime-picker/test/__snapshots__/demo.spec.js.snap index f6511f935..6bd494dc1 100644 --- a/src/datetime-picker/test/__snapshots__/demo.spec.js.snap +++ b/src/datetime-picker/test/__snapshots__/demo.spec.js.snap @@ -3,7 +3,7 @@ exports[`renders demo correctly 1`] = `
-
+
取消
确认
@@ -166,7 +166,7 @@ exports[`renders demo correctly 1`] = `
-
+
取消
确认
@@ -247,7 +247,7 @@ exports[`renders demo correctly 1`] = `
-
+
取消
确认
@@ -293,7 +293,7 @@ exports[`renders demo correctly 1`] = `
-
+
取消
确认
@@ -386,7 +386,7 @@ exports[`renders demo correctly 1`] = `
-
+
取消
确认
diff --git a/src/datetime-picker/test/__snapshots__/time-picker.spec.js.snap b/src/datetime-picker/test/__snapshots__/time-picker.spec.js.snap new file mode 100644 index 000000000..cf775ff1d --- /dev/null +++ b/src/datetime-picker/test/__snapshots__/time-picker.spec.js.snap @@ -0,0 +1,125 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`filter prop 1`] = ` +
+
+
取消
+
确认
+
+ +
+
+
    +
  • 00
  • +
  • 05
  • +
  • 10
  • +
  • 15
  • +
  • 20
  • +
+
+
+
    +
  • 00
  • +
  • 10
  • +
  • 20
  • +
  • 30
  • +
  • 40
  • +
  • 50
  • +
+
+
+
+
+ +
+`; + +exports[`format initial value 1`] = ` +
+
+
取消
+
确认
+
+ +
+
+
    +
  • 22
  • +
  • 23
  • +
+
+
+
    +
  • 58
  • +
  • 59
  • +
+
+
+
+
+ +
+`; + +exports[`formatter prop 1`] = ` +
+
+
取消
+
确认
+
+ +
+
+
    +
  • 00 hour
  • +
  • 05 hour
  • +
  • 10 hour
  • +
  • 15 hour
  • +
  • 20 hour
  • +
+
+
+
    +
  • 00 minute
  • +
  • 10 minute
  • +
  • 20 minute
  • +
  • 30 minute
  • +
  • 40 minute
  • +
  • 50 minute
  • +
+
+
+
+
+ +
+`; + +exports[`max-hour & max-minute 1`] = ` +
+
+
取消
+
确认
+
+ +
+
+
    +
  • 00
  • +
  • 01
  • +
  • 02
  • +
+
+
+
    +
  • 00
  • +
  • 01
  • +
  • 02
  • +
+
+
+
+
+ +
+`; diff --git a/src/datetime-picker/test/date-picker.spec.js b/src/datetime-picker/test/date-picker.spec.js new file mode 100644 index 000000000..fca326e97 --- /dev/null +++ b/src/datetime-picker/test/date-picker.spec.js @@ -0,0 +1,112 @@ +import DatePicker from '../DatePicker'; +import { mount, later, triggerDrag } from '../../../test/utils'; + +function filter(type, options) { + const mod = type === 'year' ? 10 : 5; + return options.filter(option => option % mod === 0); +} + +function formatter(type, value) { + return `${value} ${type}`; +} + +test('filter prop', () => { + const wrapper = mount(DatePicker, { + propsData: { + filter, + value: new Date(2019, 10, 1, 0, 0) + } + }); + + expect(wrapper).toMatchSnapshot(); +}); + +test('formatter prop', async () => { + const wrapper = mount(DatePicker, { + propsData: { + filter, + formatter, + value: new Date(2019, 10, 1, 0, 0) + } + }); + + expect(wrapper).toMatchSnapshot(); + + triggerDrag(wrapper.find('.van-picker-column'), 0, -100); + wrapper.find('.van-picker-column ul').trigger('transitionend'); + await later(); + + expect(wrapper.emitted('change')[0][0].getValues()).toEqual([ + '2020 year', + '05 month', + '05 day', + '00 hour', + '00 minute' + ]); +}); + +test('confirm event', () => { + const date = new Date(2019, 10, 1, 0, 0); + + const wrapper = mount(DatePicker, { + propsData: { + value: date + } + }); + + wrapper.find('.van-picker__confirm').trigger('click'); + expect(wrapper.emitted('confirm')[0][0].getFullYear()).toEqual(2019); + + triggerDrag(wrapper.find('.van-picker-column'), 0, -100); + wrapper.find('.van-picker__confirm').trigger('click'); + expect(wrapper.emitted('confirm')[1][0].getFullYear()).toEqual(2029); +}); + +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, { + propsData: { + value: new Date(2020, 10, 30, 30, 30), + maxDate + } + }); + + wrapper.find('.van-picker__confirm').trigger('click'); + expect(wrapper.emitted('confirm')[0][0]).toEqual(maxDate); +}); + +test('min-date prop', () => { + const minDate = new Date(2030, 0, 0, 0, 0); + const wrapper = mount(DatePicker, { + propsData: { + value: new Date(2020, 0, 0, 0, 0), + minDate + } + }); + + wrapper.find('.van-picker__confirm').trigger('click'); + expect(wrapper.emitted('confirm')[0][0]).toEqual(minDate); +}); + +test('dynamic set value', () => { + const wrapper = mount(DatePicker, { + propsData: { + value: new Date(2019, 1, 1) + } + }); + + wrapper.setProps({ value: new Date(2019, 1, 1) }); + wrapper.find('.van-picker__confirm').trigger('click'); + wrapper.setProps({ value: new Date(2025, 1, 1) }); + wrapper.find('.van-picker__confirm').trigger('click'); + + expect(wrapper.emitted('confirm')[0][0].getFullYear()).toEqual(2019); + expect(wrapper.emitted('confirm')[1][0].getFullYear()).toEqual(2025); +}); diff --git a/src/datetime-picker/test/time-picker.spec.js b/src/datetime-picker/test/time-picker.spec.js new file mode 100644 index 000000000..25887226e --- /dev/null +++ b/src/datetime-picker/test/time-picker.spec.js @@ -0,0 +1,94 @@ +import TimePicker from '../TimePicker'; +import { mount, later, triggerDrag } from '../../../test/utils'; + +function filter(type, options) { + const mod = type === 'minute' ? 10 : 5; + return options.filter(option => option % mod === 0); +} + +function formatter(type, value) { + return `${value} ${type}`; +} + +test('format initial value', () => { + const wrapper = mount(TimePicker, { + propsData: { + minHour: 22, + minMinute: 58 + } + }); + + expect(wrapper).toMatchSnapshot(); +}); + +test('max-hour & max-minute', () => { + const wrapper = mount(TimePicker, { + propsData: { + value: '23:59', + maxHour: 2, + maxMinute: 2 + } + }); + + expect(wrapper).toMatchSnapshot(); +}); + +test('filter prop', () => { + const wrapper = mount(TimePicker, { + propsData: { + filter, + value: '12:00' + } + }); + + expect(wrapper).toMatchSnapshot(); +}); + +test('formatter prop', async () => { + const wrapper = mount(TimePicker, { + propsData: { + filter, + formatter, + value: '12:00' + } + }); + + expect(wrapper).toMatchSnapshot(); + + triggerDrag(wrapper.find('.van-picker-column'), 0, -100); + wrapper.find('.van-picker-column ul').trigger('transitionend'); + await later(); + + expect(wrapper.emitted('change')[0][0].getValues()).toEqual(['20 hour', '00 minute']); +}); + +test('confirm event', () => { + const wrapper = mount(TimePicker, { + propsData: { + value: '12:00' + } + }); + + triggerDrag(wrapper.find('.van-picker-column'), 0, -100); + wrapper.find('.van-picker__confirm').trigger('click'); + expect(wrapper.emitted('confirm')[0][0]).toEqual('23:00'); +}); + +test('cancel event', () => { + const wrapper = mount(TimePicker); + + wrapper.find('.van-picker__cancel').trigger('click'); + expect(wrapper.emitted('cancel')).toBeTruthy(); +}); + +test('dynamic set value', () => { + const wrapper = mount(TimePicker); + + wrapper.setProps({ value: '00:00' }); + wrapper.find('.van-picker__confirm').trigger('click'); + wrapper.setProps({ value: '22:30' }); + wrapper.find('.van-picker__confirm').trigger('click'); + + expect(wrapper.emitted('confirm')[0][0]).toEqual('00:00'); + expect(wrapper.emitted('confirm')[1][0]).toEqual('22:30'); +}); diff --git a/src/picker/test/index.spec.js b/src/picker/test/index.spec.js index c19e4e99e..1e1253c4b 100644 --- a/src/picker/test/index.spec.js +++ b/src/picker/test/index.spec.js @@ -80,12 +80,13 @@ test('set picker values', () => { expect(vm.getColumnValue(2)).toEqual(undefined); }); -test('drag columns', async () => { +test('drag columns', () => { const wrapper = mount(Picker, { propsData: { columns } }); + triggerDrag(wrapper.find('.van-picker-column'), 0, -100); wrapper.find('.van-picker-column ul').trigger('transitionend'); @@ -94,12 +95,13 @@ test('drag columns', async () => { expect(wrapper.emitted('change')[0][1]).toEqual(['normal', '1990']); }); -test('drag simple columns', async () => { +test('drag simple columns', () => { const wrapper = mount(Picker, { propsData: { columns: simpleColumn } }); + triggerDrag(wrapper.find('.van-picker-column'), 0, -100); wrapper.find('.van-picker-column ul').trigger('transitionend');