Merge pull request #1712 from SergioCrisostomo/add-more-datepicker-tests

Refactor cell click handler and add more date picker and date range picker tests
This commit is contained in:
Aresn 2017-09-01 11:20:13 +08:00 committed by GitHub
commit 68e3642119
3 changed files with 153 additions and 78 deletions

View file

@ -1,12 +1,11 @@
<template> <template>
<div <div
:class="classes" :class="classes"
@click="handleClick"
@mousemove="handleMouseMove"> @mousemove="handleMouseMove">
<div :class="[prefixCls + '-header']"> <div :class="[prefixCls + '-header']">
<span>{{ t('i.datepicker.weeks.sun') }}</span><span>{{ t('i.datepicker.weeks.mon') }}</span><span>{{ t('i.datepicker.weeks.tue') }}</span><span>{{ t('i.datepicker.weeks.wed') }}</span><span>{{ t('i.datepicker.weeks.thu') }}</span><span>{{ t('i.datepicker.weeks.fri') }}</span><span>{{ t('i.datepicker.weeks.sat') }}</span> <span>{{ t('i.datepicker.weeks.sun') }}</span><span>{{ t('i.datepicker.weeks.mon') }}</span><span>{{ t('i.datepicker.weeks.tue') }}</span><span>{{ t('i.datepicker.weeks.wed') }}</span><span>{{ t('i.datepicker.weeks.thu') }}</span><span>{{ t('i.datepicker.weeks.fri') }}</span><span>{{ t('i.datepicker.weeks.sat') }}</span>
</div> </div>
<span :class="getCellCls(cell)" v-for="(cell, index) in readCells"><em :index="index">{{ cell.text }}</em></span> <span :class="getCellCls(cell)" v-for="(cell, index) in readCells"><em :index="index" @click="handleClick(cell)">{{ cell.text }}</em></span>
</div> </div>
</template> </template>
<script> <script>
@ -106,6 +105,7 @@
const cell_tmpl = { const cell_tmpl = {
text: '', text: '',
type: '', type: '',
date: null,
selected: false, selected: false,
disabled: false, disabled: false,
range: false, range: false,
@ -117,14 +117,8 @@
const cell = deepCopy(cell_tmpl); const cell = deepCopy(cell_tmpl);
cell.type = 'prev-month'; cell.type = 'prev-month';
cell.text = dateCountOfLastMonth - (day - 1) + i; cell.text = dateCountOfLastMonth - (day - 1) + i;
cell.date = new Date(this.year, this.month - 1, cell.text);
let prevMonth = this.month - 1; const time = clearHours(cell.date);
let prevYear = this.year;
if (this.month === 0) {
prevMonth = 11;
prevYear -= 1;
}
const time = clearHours(new Date(prevYear, prevMonth, cell.text));
cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(time)); cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(time));
cells.push(cell); cells.push(cell);
} }
@ -132,9 +126,10 @@
for (let i = 1; i <= dateCountOfMonth; i++) { for (let i = 1; i <= dateCountOfMonth; i++) {
const cell = deepCopy(cell_tmpl); const cell = deepCopy(cell_tmpl);
const time = clearHours(new Date(this.year, this.month, i));
cell.type = time === today ? 'today' : 'normal';
cell.text = i; cell.text = i;
cell.date = new Date(this.year, this.month, cell.text);
const time = clearHours(cell.date);
cell.type = time === today ? 'today' : 'normal';
cell.selected = time === selectDay; cell.selected = time === selectDay;
cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(time)); cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(time));
cell.range = time >= minDay && time <= maxDay; cell.range = time >= minDay && time <= maxDay;
@ -149,14 +144,8 @@
const cell = deepCopy(cell_tmpl); const cell = deepCopy(cell_tmpl);
cell.type = 'next-month'; cell.type = 'next-month';
cell.text = i; cell.text = i;
cell.date = new Date(this.year, this.month + 1, cell.text);
let nextMonth = this.month + 1; const time = clearHours(cell.date);
let nextYear = this.year;
if (this.month === 11) {
nextMonth = 0;
nextYear += 1;
}
const time = clearHours(new Date(nextYear, nextMonth, cell.text));
cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(time)); cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(time));
cells.push(cell); cells.push(cell);
} }
@ -165,71 +154,39 @@
} }
}, },
methods: { methods: {
getDateOfCell (cell) { handleClick (cell) {
let year = this.year;
let month = this.month;
let day = cell.text;
const date = this.date; if (cell.disabled) return;
const hours = date.getHours(); const newDate = cell.date;
const minutes = date.getMinutes();
const seconds = date.getSeconds();
if (cell.type === 'prev-month') { if (this.selectionMode === 'range') {
if (month === 0) { if (this.minDate && this.maxDate) {
month = 11; const minDate = new Date(newDate.getTime());
year--; const maxDate = null;
} else { this.rangeState.selecting = true;
month--; this.markRange(this.minDate);
}
} else if (cell.type === 'next-month') {
if (month === 11) {
month = 0;
year++;
} else {
month++;
}
}
return new Date(year, month, day, hours, minutes, seconds); this.$emit('on-pick', {minDate, maxDate}, false);
}, } else if (this.minDate && !this.maxDate) {
handleClick (event) { if (newDate >= this.minDate) {
const target = event.target; const maxDate = new Date(newDate.getTime());
if (target.tagName === 'EM') { this.rangeState.selecting = false;
const cell = this.cells[parseInt(event.target.getAttribute('index'))];
if (cell.disabled) return;
const newDate = this.getDateOfCell(cell); this.$emit('on-pick', {minDate: this.minDate, maxDate});
} else {
if (this.selectionMode === 'range') {
if (this.minDate && this.maxDate) {
const minDate = new Date(newDate.getTime()); const minDate = new Date(newDate.getTime());
const maxDate = null;
this.rangeState.selecting = true;
this.markRange(this.minDate);
this.$emit('on-pick', {minDate, maxDate}, false);
} else if (this.minDate && !this.maxDate) {
if (newDate >= this.minDate) {
const maxDate = new Date(newDate.getTime());
this.rangeState.selecting = false;
this.$emit('on-pick', {minDate: this.minDate, maxDate});
} else {
const minDate = new Date(newDate.getTime());
this.$emit('on-pick', {minDate, maxDate: this.maxDate}, false);
}
} else if (!this.minDate) {
const minDate = new Date(newDate.getTime());
this.rangeState.selecting = true;
this.markRange(this.minDate);
this.$emit('on-pick', {minDate, maxDate: this.maxDate}, false); this.$emit('on-pick', {minDate, maxDate: this.maxDate}, false);
} }
} else { } else if (!this.minDate) {
this.$emit('on-pick', newDate); const minDate = new Date(newDate.getTime());
this.rangeState.selecting = true;
this.markRange(this.minDate);
this.$emit('on-pick', {minDate, maxDate: this.maxDate}, false);
} }
} else {
this.$emit('on-pick', newDate);
} }
this.$emit('on-pick-click'); this.$emit('on-pick-click');
}, },
@ -246,7 +203,7 @@
if (target.tagName === 'EM') { if (target.tagName === 'EM') {
const cell = this.cells[parseInt(event.target.getAttribute('index'))]; const cell = this.cells[parseInt(event.target.getAttribute('index'))];
// if (cell.disabled) return; // todo // if (cell.disabled) return; // todo
this.rangeState.endDate = this.getDateOfCell(cell); this.rangeState.endDate = cell.date;
} }
}, },
markRange (maxDate) { markRange (maxDate) {

View file

@ -1,4 +1,4 @@
import { createVue, destroyVM } from '../util'; import { createVue, destroyVM, stringToDate } from '../util';
describe('DatePicker.vue', () => { describe('DatePicker.vue', () => {
let vm; let vm;
@ -25,4 +25,112 @@ describe('DatePicker.vue', () => {
done(); done();
}); });
}); });
it('should create a DatePicker component of type="datetimerange"', done => {
vm = createVue(`
<Date-Picker type="datetimerange"></Date-Picker>
`);
const picker = vm.$children[0];
expect(picker.$children.length).to.equal(2);
expect(Array.isArray(picker.currentValue)).to.equal(true);
done();
});
it('should create a datetimerange component and pick 2 dates in the current month', done => {
vm = createVue(`
<Date-picker type="datetimerange"></Date-picker>
`);
const picker = vm.$children[0];
picker.handleIconClick();
vm.$nextTick(() => {
const displayField = vm.$el.querySelector('.ivu-input');
const clickableCells = vm.$el.querySelectorAll('.ivu-date-picker-cells-cell');
const lastMonthClass = 'ivu-date-picker-cells-cell-prev-month';
const firstDayInMonthIndex = [...clickableCells].findIndex(cell => !cell.classList.contains(lastMonthClass));
clickableCells[firstDayInMonthIndex].firstElementChild.click();
vm.$nextTick(() => {
clickableCells[firstDayInMonthIndex + 4].firstElementChild.click();
vm.$nextTick(() => {
const dayOne = new Date();
dayOne.setDate(1);
dayOne.setHours(0, 0, 0, 0);
const dayFive = new Date(dayOne.getTime());
dayFive.setDate(5);
dayFive.setHours(0, 0, 0, 0);
// check pickers internal value
const [startInternalValue, endInternalValue] = picker.currentValue; // Date Objects
expect(Math.abs(dayOne - startInternalValue)).to.equal(0);
expect(Math.abs(dayFive - endInternalValue)).to.equal(0);
// check pickers display value
const [startDisplayValue, endDisplayValue] = displayField.value.split(' - ').map(stringToDate); // Date Objects
expect(Math.abs(dayOne - startDisplayValue)).to.equal(0);
expect(Math.abs(dayFive - endDisplayValue)).to.equal(0);
done();
});
});
});
});
it('should have same behavior after a reset as before the reset', done => {
vm = createVue(`
<Date-picker type="datetimerange"></Date-picker>
`);
const picker = vm.$children[0];
picker.handleIconClick();
vm.$nextTick(() => {
const displayField = vm.$el.querySelector('.ivu-input');
const clickableCells = vm.$el.querySelectorAll('.ivu-date-picker-cells-cell');
const lastMonthClass = 'ivu-date-picker-cells-cell-prev-month';
const firstDayInMonthIndex = [...clickableCells].findIndex(cell => !cell.classList.contains(lastMonthClass));
// choose first date
clickableCells[firstDayInMonthIndex].firstElementChild.click();
vm.$nextTick(() => {
// choose second date
clickableCells[firstDayInMonthIndex + 4].firstElementChild.click();
vm.$nextTick(() => {
// cache first values
const [startInternalValue, endInternalValue] = picker.currentValue; // Date Objects
const [startDisplayValue, endDisplayValue] = displayField.value.split(' - ').map(stringToDate); // Date Objects
// clear picker
picker.handleClear();
vm.$nextTick(() => {
// it should be closed by now
expect(picker.visible).to.equal(false);
// open picker again
picker.handleIconClick();
vm.$nextTick(() => {
expect(picker.visible).to.equal(true);
expect(JSON.stringify(picker.currentValue)).to.equal('[null,null]');
expect(displayField.value).to.equal('');
clickableCells[firstDayInMonthIndex].firstElementChild.click();
vm.$nextTick(() => {
clickableCells[firstDayInMonthIndex + 4].firstElementChild.click();
vm.$nextTick(() => {
// recheck internal values
expect(Math.abs(picker.currentValue[0] - startInternalValue)).to.equal(0);
expect(Math.abs(picker.currentValue[1] - endInternalValue)).to.equal(0);
// recheck display value
const [_startDisplayValue, _endDisplayValue] = displayField.value.split(' - ').map(stringToDate); // Date Objects
expect(Math.abs(_startDisplayValue - startDisplayValue)).to.equal(0);
expect(Math.abs(_endDisplayValue - endDisplayValue)).to.equal(0);
done();
});
});
});
});
});
});
});
});
}); });

View file

@ -57,6 +57,16 @@ exports.createTest = function(Compo, propsData = {}, mounted = false) {
return new Ctor({ propsData }).$mount(mounted === false ? null : elm); return new Ctor({ propsData }).$mount(mounted === false ? null : elm);
}; };
/**
* Transform Date string (yyyy-mm-dd hh:mm:ss) to Date object
* @param {String}
*/
exports.stringToDate = function(str) {
const parts = str.split(/[^\d]/).filter(Boolean);
parts[1] = parts[1] - 1;
return new Date(...parts);
};
/** /**
* 触发一个事件 * 触发一个事件
* mouseenter, mouseleave, mouseover, keyup, change, click * mouseenter, mouseleave, mouseover, keyup, change, click