Skip to content

Commit

Permalink
[added] 添加注释, 测试用例
Browse files Browse the repository at this point in the history
  • Loading branch information
lanjingling0510 committed Jun 26, 2016
1 parent 4994536 commit 37441d7
Show file tree
Hide file tree
Showing 8 changed files with 310 additions and 50 deletions.
51 changes: 47 additions & 4 deletions lib/DatePicker.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @module DatePicker组件
*/
import './index.css';

import React, { Component, PropTypes } from 'react';
import { nextTime, getTimeName } from './time.js';
import {
Expand All @@ -26,9 +26,9 @@ class DatePicker extends Component {
};
});

this.animating = false;
this.touchY = 0;
this.angle = 0;
this.animating = false; // 判断是否在transition过渡动画之中
this.touchY = 0; // 保存touchstart的pageY
this.angle = 0; // 容器转过的角度
this.state = {
angle: 0,
dates,
Expand All @@ -41,16 +41,31 @@ class DatePicker extends Component {
this._moveToNext = this._moveToNext.bind(this);
}

/**
* 根据角度返回透明度(0-1之间)
* @param {number} angle 角度
* @return
*/
_setOpacity(angle) {
return angle > 0
? ((40 - angle) / 40 * 100 | 0) / 100
: ((40 + angle) / 40 * 100 | 0) / 100;
}

/**
* 清除对象的transition样式
* @param {Dom} obj 指定的对象
* @return {undefined}
*/
_clearTransition(obj) {
obj.style[TRANSITION] = ''; // eslint-disable-line
}

/**
* 滑动到下一日期
* @param {number} direction 滑动方向
* @return {undefined}
*/
_moveToNext(direction) {
const scroll = this.refs.scroll;
const angle = this.angle;
Expand All @@ -70,6 +85,12 @@ class DatePicker extends Component {
}
}

/**
* 添加滑动动画
* @param {DOM} obj DOM对象
* @param {number} angle 角度
* @return {undefined}
*/
_moveTo(obj, angle) {
this.animating = true;
obj.style[TRANSITION] = `${TRANSFORM_CSS} .2s ease-out`; // eslint-disable-line
Expand All @@ -78,11 +99,20 @@ class DatePicker extends Component {
});
}

/**
* 点击完成按钮事件
* @return {undefined}
*/
handleFinishBtnClick() {
const date = this.state.dates.find(value => value.angle + this.state.angle === 0);
this.props.onSelect(date.value);
}

/**
* 滑动日期选择器事件
* @param {Object} event 事件对象
* @return {undefined}
*/
handleContentTouch(event) {
event.preventDefault();
if (this.animating) return;
Expand All @@ -107,6 +137,10 @@ class DatePicker extends Component {
}
}

/**
* transition过渡完成事件
* @return {undefined}
*/
handleContentTransitionEnd() {
const { dates, angle } = this.state;
const date = dates.find(value => value.angle + angle === 0);
Expand All @@ -126,6 +160,11 @@ class DatePicker extends Component {
});
}

/**
* 渲染一个日期DOM对象
* @param {Object} date date数据
* @return {Object} JSX对象
*/
renderDatepickerItem(date) {
const itemStyle = {
[TRANSFORM]: `rotateX(${date.angle}deg) translate3d(0,0,100px)`,
Expand All @@ -141,6 +180,10 @@ class DatePicker extends Component {
);
}

/**
* render函数
* @return {Object} JSX对象
*/
render() {
const { layerBackground, btnColor } = this.props;
const scrollStyle = {
Expand Down
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import './index.css';
import DatePicker from './DatePicker.js';
export default DatePicker;
15 changes: 14 additions & 1 deletion lib/time.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @module time工具
*/

function convertDate(timestamp, formate) {
const date = new Date(timestamp);
const year = date.getFullYear();
Expand All @@ -16,7 +20,11 @@ function convertDate(timestamp, formate) {
.replace(/s+/, second);
}


/**
* 获取相对日期的偏移日期
* @param {Date} 日期
* @return {number} 相对的天数
*/
export function nextTime(now = new Date(), index = 1) {
if (Object.prototype.toString.call(now, null) !== '[object Date]') {
throw new Error('参数类型不对');
Expand All @@ -27,6 +35,11 @@ export function nextTime(now = new Date(), index = 1) {
return date;
}

/**
* 获取指定日期的格式化日期名称
* @param {Date} 日期
* @return {String} 格式化日期名称
*/
export function getTimeName(now) {
if (Object.prototype.toString.call(now, null) !== '[object Date]') {
throw new Error('参数类型不对');
Expand Down
4 changes: 2 additions & 2 deletions lib/transition.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ if (typeof document.body.style.transition === 'string') {
TRANSITIONEND = 'transitionend';
TRANSITION_CSS = 'transition';
} else if (typeof document.body.style.webkitTransition === 'string') {
TRANSITION = 'webkitTransition';
TRANSITION = 'WebkitTransition';
TRANSITION_CSS = '-webkit-transition';
TRANSITIONEND = 'webkitTransitionEnd';
}
Expand All @@ -17,7 +17,7 @@ if (typeof document.body.style.transform === 'string') {
TRANSFORM = 'transform';
TRANSFORM_CSS = 'transform';
} else if (typeof document.body.style.webkitTransform === 'string') {
TRANSFORM = 'webkitTransform';
TRANSFORM = 'WebkitTransform';
TRANSFORM_CSS = '-webkit-transform';
}

Expand Down
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"scripts": {
"build": "webpack",
"start": "webpack-dev-server",
"release": "scripts/release",
"release": "npm install build;scripts/release",
"preview-release": "scripts/preview-release",
"mocha": "./node_modules/.bin/mocha --compilers js:babel-core/register --require ./test/helper.js --recursive",
"test": "./node_modules/.bin/nyc npm run mocha",
Expand All @@ -20,13 +20,15 @@
"babel-core": "^6.9.0",
"babel-eslint": "^6.0.4",
"babel-loader": "^6.2.4",
"babel-polyfill": "^6.9.1",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-0": "^6.5.0",
"chai": "^3.5.0",
"coveralls": "^2.11.9",
"css-loader": "^0.23.1",
"cssnext": "^1.8.4",
"enzyme": "^2.3.0",
"eslint": "^2.10.2",
"eslint-config-airbnb": "9.0.1",
"eslint-plugin-import": "^1.8.0",
Expand All @@ -41,7 +43,9 @@
"postcss-cssnext": "^2.5.2",
"postcss-loader": "^0.9.1",
"postcss-nested": "^1.0.0",
"react-addons-test-utils": "^15.1.0",
"rf-release": "^0.4.0",
"sinon": "^1.17.4",
"style-loader": "^0.13.1",
"webpack": "^1.13.1",
"webpack-dev-server": "^1.14.1",
Expand All @@ -52,4 +56,4 @@
"react-dom": "^15.1.0"
},
"license": "ISC"
}
}
177 changes: 177 additions & 0 deletions test/functional/DatePicker_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@

import React from 'react';
import { assert, expect } from 'chai';
import sinon from 'sinon';
import { mount, shallow } from 'enzyme';
import DatePicker from '../../lib/DatePicker';
import {nextTime} from '../../lib/time';

describe('时间选择器组件DatePicker', () => {
describe('测试初始化的过程:', () => {
it('测试传入_setOpacity的参数', () => {
const spyFunction = sinon.spy(DatePicker.prototype, '_setOpacity');
const datePicker = mount(
<DatePicker />
);

const list = [
spyFunction.getCall(0).args[0],
spyFunction.getCall(1).args[0],
spyFunction.getCall(2).args[0],
spyFunction.getCall(3).args[0],
spyFunction.getCall(4).args[0],
];

const expectList = [45, 22.5, 0, -22.5, -45];
expect(list).to.deep.equals(expectList);
spyFunction.restore();
})
})


describe('测试方法:', () => {
it('_setOpacity应该返回相应的值,当传入不同的临界值', () => {
const datePicker = mount(
<DatePicker />
);
const inst = datePicker.instance();

const test1 = [0, 1];
const test2 = [40, 0];
const test3 = [-40, 0];

expect(inst._setOpacity(test1[0])).to.equals(test1[1]);
expect(inst._setOpacity(test2[0])).to.equals(test2[1]);
expect(inst._setOpacity(test3[0])).to.equals(test3[1]);
})

it('应该滑动到上一个日期,当调用_moveToNext方法', () => {
const spyFunction = sinon.spy();
const datePicker = mount(
<DatePicker
onSelect={spyFunction}/>
);
datePicker.instance()._moveToNext(-1);
datePicker.find('.datepicker-finish-btn').simulate('click');
sinon.assert.calledWith(spyFunction, nextTime(new Date(), -1));
})


it('应该向_moveToNext传入-1, 当滑动到上一个日期', () => {
const spyFunction = sinon.spy(DatePicker.prototype, '_moveToNext');
const datePicker = mount(
<DatePicker />
);
const touchstartEvent = {
type: 'touchstart',
targetTouches: [{ pageY: 0 }],
};
const touchendEvent = {
type: 'touchend',
changedTouches: [{ pageY: 50 }],
};


datePicker.find('.datepicker-content').simulate('touchStart', touchstartEvent);
datePicker.find('.datepicker-content').simulate('touchEnd', touchendEvent);
sinon.assert.calledWith(spyFunction, -1);
spyFunction.restore();
})

})

describe('测试交互事件:', () => {
it('应该触发handleContent3次, 在触摸屏幕之后', () => {
const spyFunction = sinon.spy(DatePicker.prototype, 'handleContentTouch');
const datePicker = mount(
<DatePicker />
);

datePicker.find('.datepicker-content').simulate('touchStart');
datePicker.find('.datepicker-content').simulate('touchMove');
datePicker.find('.datepicker-content').simulate('touchEnd');
sinon.assert.callCount(spyFunction, 3);
spyFunction.restore();
})

it('应该触发onSelect, 在点击完成按钮之后', () => {
const spyFunction = sinon.spy();
const datePicker = mount(
<DatePicker
onSelect={spyFunction}/>
);
datePicker.find('.datepicker-finish-btn').simulate('click');
sinon.assert.calledOnce(spyFunction);
})


it('应该向onSelect传入上一个日期, 当向下滑动超过touchLen', () => {
const spyFunction = sinon.spy();
const datePicker = mount(
<DatePicker
onSelect={spyFunction}/>
);
const touchstartEvent = {
type: 'touchstart',
targetTouches: [{ pageY: 0 }],
};
const touchendEvent = {
type: 'touchend',
changedTouches: [{ pageY: 50 }],
};

datePicker.find('.datepicker-content').simulate('touchStart', touchstartEvent);
datePicker.find('.datepicker-content').simulate('touchEnd', touchendEvent);
datePicker.find('.datepicker-content').simulate('transitionEnd');
datePicker.find('.datepicker-finish-btn').simulate('click');
sinon.assert.calledWith(spyFunction, nextTime(new Date(), -1));
})

it('应该向onSelect传入下一个日期, 当向上滑动超过touchLen', () => {
const spyFunction = sinon.spy();
const datePicker = mount(
<DatePicker
maxDate={nextTime(new Date(), 1)}
onSelect={spyFunction}/>
);
const touchstartEvent = {
type: 'touchstart',
targetTouches: [{ pageY: 0 }],
};
const touchendEvent = {
type: 'touchend',
changedTouches: [{ pageY: -50 }],
};

datePicker.find('.datepicker-content').simulate('touchStart', touchstartEvent);
datePicker.find('.datepicker-content').simulate('touchEnd', touchendEvent);
datePicker.find('.datepicker-content').simulate('transitionEnd');
datePicker.find('.datepicker-finish-btn').simulate('click');
sinon.assert.calledWith(spyFunction, nextTime(new Date(), 1));
})

it('应该恢复当前日期, 但滑动超过touchLen但上一个日期小于minDate', () => {
const spyFunction = sinon.spy();
const datePicker = mount(
<DatePicker
minDate={nextTime(new Date())}
onSelect={spyFunction}/>
);
const touchstartEvent = {
type: 'touchstart',
targetTouches: [{ pageY: 0 }],
};
const touchendEvent = {
type: 'touchend',
changedTouches: [{ pageY: 50 }],
};

datePicker.find('.datepicker-content').simulate('touchStart', touchstartEvent);
datePicker.find('.datepicker-content').simulate('touchEnd', touchendEvent);
datePicker.find('.datepicker-content').simulate('transitionEnd');
datePicker.find('.datepicker-finish-btn').simulate('click');
sinon.assert.calledWith(spyFunction, nextTime(new Date(), 0));
})
})

});
Loading

0 comments on commit 37441d7

Please sign in to comment.