react-16-bootstrap-date-picker
Version:
React-Bootstrap based date picker.
1,105 lines (1,100 loc) • 45.3 kB
JSX
import React from "react";
import ReactDOM from "react-dom";
import DatePicker from "../src/index.jsx";
import assert from "assert";
import co from "co";
import ES6Promise from 'es6-promise';
import UUID from "node-uuid";
import TestUtils from 'react-dom/test-utils';
import createReactClass from 'create-react-class';
ES6Promise.polyfill();
const spanishDayLabels = ['Dom', 'Lu', 'Ma', 'Mx', 'Ju', 'Vi', 'Sab'];
const spanishMonthLabels = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
const assertIsoStringsHaveSameDate = (IsoStringA, IsoStringB) => {
const dateA = new Date(IsoStringA);
const dateB = new Date(IsoStringB);
assert.equal(dateA.getMonth(), dateB.getMonth());
assert.equal(dateA.getDate(), dateB.getDate());
assert.equal(dateA.getFullYear(), dateB.getFullYear());
}
describe("Date Picker", function() {
this.timeout(30000);
let container, calendarContainer;
before(function(){
container = document.createElement("div");
container.id = "react";
document.getElementsByTagName('body')[0].appendChild(container);
calendarContainer = document.createElement("div"); // optional container for the calendar popover
calendarContainer.id = "calendarContainer";
document.getElementsByTagName('body')[0].appendChild(calendarContainer);
});
after(function(){
document.getElementsByTagName('body')[0].removeChild(container);
document.getElementsByTagName('body')[0].removeChild(calendarContainer);
});
it("should render an empty date picker.", co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const hiddenInputElement = document.getElementById(id);
assert.equal(hiddenInputElement.value, "");
assert.equal(hiddenInputElement.getAttribute('data-formattedvalue'), "");
ReactDOM.unmountComponentAtNode(container);
}));
it("should render a date picker with a value.", co.wrap(function *(){
const id = UUID.v4();
const value = `${new Date().toISOString().slice(0,10)}T12:00:00.000Z`;
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} value={value} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const hiddenInputElement = document.getElementById(id);
assertIsoStringsHaveSameDate(hiddenInputElement.value, value);
assert.equal(hiddenInputElement.getAttribute('data-formattedvalue'), `${value.slice(5,7)}/${value.slice(8,10)}/${value.slice(0,4)}`);
ReactDOM.unmountComponentAtNode(container);
}));
it("should open the calendar and select a date.", co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const hiddenInputElement = document.getElementById(id);
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const dayElement = document.querySelector("table tbody tr:nth-child(2) td");
assert.equal(hiddenInputElement.value, '');
assert.equal(hiddenInputElement.getAttribute('data-formattedvalue'), "");
TestUtils.Simulate.click(dayElement);
assert.notEqual(hiddenInputElement.value, '');
assert.notEqual(hiddenInputElement.getAttribute('data-formattedvalue'), "");
ReactDOM.unmountComponentAtNode(container);
}));
it("should open the calendar, select a date, and trigger a change event.", co.wrap(function *(){
const id = UUID.v4();
let value = null;
let formattedValue = null;
const App = createReactClass({
handleChange: function(newValue, newFormattedValue){
value = newValue;
formattedValue = newFormattedValue;
},
render: function(){
return <div>
<DatePicker id={id} onChange={this.handleChange} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const dayElement = document.querySelector("table tbody tr:nth-child(2) td");
assert.equal(value, null);
assert.equal(formattedValue, null);
TestUtils.Simulate.click(dayElement);
assert(typeof value === "string");
assert(typeof formattedValue === "string");
ReactDOM.unmountComponentAtNode(container);
}));
it("should open the calendar and render 29 days on a leap year.", co.wrap(function *(){
const id = UUID.v4();
let value = "2016-02-15T00:00:00.000Z";
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} value={value} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const dayElement = document.querySelector("table tbody tr:nth-child(5) td:nth-of-type(2)");
assert.equal(dayElement.innerHTML, '29');
TestUtils.Simulate.click(dayElement);
ReactDOM.unmountComponentAtNode(container);
}));
it("should update via a change handler when the input is changed.", co.wrap(function *(){
const id = UUID.v4();
let value = null;
let formattedValue = null;
const App = createReactClass({
handleChange: function(newValue, newFormattedValue){
value = newValue;
formattedValue = newFormattedValue;
},
render: function(){
return <div>
<DatePicker id={id} onChange={this.handleChange} dateFormat="MM/DD/YYYY" />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
inputElement.value = "05/31/1980";
TestUtils.Simulate.change(inputElement);
const date = new Date(value);
assert.equal(date.getMonth(), 4);
assert.equal(date.getDate(), 31);
assert.equal(date.getFullYear(), 1980);
assert.equal(formattedValue, "05/31/1980");
ReactDOM.unmountComponentAtNode(container);
}));
it("should render with custom elements", co.wrap(function *(){
const id = UUID.v4();
const clearButtonElement = <div id="clear-button-element"></div>;
const previousButtonElement = <div id="previous-button-element"></div>;
const nextButtonElement = <div id="next-button-element"></div>;
const App = createReactClass({
render: function(){
return <div>
<DatePicker
id={id}
dayLabels={spanishDayLabels}
monthLabels={spanishMonthLabels}
clearButtonElement={clearButtonElement}
nextButtonElement={nextButtonElement}
previousButtonElement={previousButtonElement} />
</div>;
}
});
var spanishMonthLabel = spanishMonthLabels[new Date().getMonth()];
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const dayElement = document.querySelector("table tbody tr:nth-child(2) td");
TestUtils.Simulate.click(dayElement);
const popover = document.querySelector(".popover");
assert.notEqual(document.getElementById("clear-button-element"), null);
assert.notEqual(document.getElementById("previous-button-element"), null);
assert.notEqual(document.getElementById("next-button-element"), null);
assert.notEqual(popover.innerHTML.indexOf(spanishMonthLabel), -1);
assert.notEqual("Mx", -1);
ReactDOM.unmountComponentAtNode(container);
}));
it("should render without clear button element", co.wrap(function *(){
const id = UUID.v4();
const clearButtonElement = <div id="clear-button-element"></div>;
const App = createReactClass({
render: function(){
return <div>
<DatePicker
id={id}
clearButtonElement={clearButtonElement}
showClearButton={false}
/>
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
assert.equal(document.getElementById("clear-button-element"), null);
ReactDOM.unmountComponentAtNode(container);
}));
it("should go to the previous and next month.", co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const hiddenInputElement = document.getElementById(id);
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const previousButtonElement = document.querySelector(".pull-left");
const nextButtonElement = document.querySelector(".pull-right");
const dayElement = document.querySelector("table tbody tr:nth-child(2) td");
TestUtils.Simulate.click(previousButtonElement);
TestUtils.Simulate.click(dayElement);
var previousMonthISOString = hiddenInputElement.value;
TestUtils.Simulate.focus(inputElement);
TestUtils.Simulate.click(nextButtonElement);
TestUtils.Simulate.click(dayElement);
var currentMonthISOString = hiddenInputElement.value;
assert(previousMonthISOString < currentMonthISOString);
ReactDOM.unmountComponentAtNode(container);
}));
it("should cycle through every month in the year.", co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const nextButtonElement = document.querySelector(".pull-right");
for(let i = 0; i < 12; i++) {
TestUtils.Simulate.click(nextButtonElement);
}
ReactDOM.unmountComponentAtNode(container);
}));
it("should update via a change handler when cleared.", co.wrap(function *(){
const id = UUID.v4();
let value = null;
let formattedValue = null;
const App = createReactClass({
handleChange: function(newValue, newFormattedValue){
value = newValue;
formattedValue = newFormattedValue;
},
render: function(){
return <div>
<DatePicker id={id} onChange={this.handleChange} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const clearButtonElement = document.querySelector("span.input-group-addon");
const dayElement = document.querySelector("table tbody tr:nth-child(2) td");
TestUtils.Simulate.click(dayElement);
assert.notEqual(value, null);
assert.notEqual(formattedValue, null);
TestUtils.Simulate.click(clearButtonElement);
assert.equal(value, null);
assert.equal(formattedValue, null);
ReactDOM.unmountComponentAtNode(container);
}));
it("should call focus and blur handlers.", co.wrap(function *(){
const id = UUID.v4();
var results = {};
var value = `${new Date().toISOString().slice(0,10)}T12:00:00.000Z`;
const App = createReactClass({
getInitialState: function() {
return {
focused: false
}
},
focusHandler: function(e) {
assert.equal(e.target, document.querySelector("input[type=hidden]"));
assertIsoStringsHaveSameDate(e.target.value, value);
this.setState({
focused: true
});
},
blurHandler: function(e) {
assert.equal(e.target, document.querySelector("input[type=hidden]"));
assertIsoStringsHaveSameDate(e.target.value, value);
this.setState({
focused: false
});
},
render: function(){
return <div>
<div id='blurringClickTarget'>Blurring Click Target</div>
{this.state.focused ? <div id="focused">Focused</div> : <div id="blurred">Blurred</div>}
<DatePicker id={id} onBlur={this.blurHandler} onFocus={this.focusHandler} value={value} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
const blurringClickTarget = document.getElementById("blurringClickTarget");
assert.notEqual(document.getElementById("blurred"), null);
TestUtils.Simulate.focus(inputElement);
assert.notEqual(document.getElementById("focused"), null);
TestUtils.Simulate.blur(inputElement);
blurringClickTarget.click(); // React-overlays won't hide on a synthetic event so can't use TestUtils here.
assert.notEqual(document.getElementById("blurred"), null);
ReactDOM.unmountComponentAtNode(container);
}));
it('should trim extra characters.', co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
inputElement.value = "05/31/1980 extra";
TestUtils.Simulate.change(inputElement);
assert.equal(inputElement.value, "05/31/1980");
ReactDOM.unmountComponentAtNode(container);
}));
it("should automatically insert slashes.", co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
inputElement.value = "0";
TestUtils.Simulate.change(inputElement);
inputElement.value = "053";
TestUtils.Simulate.change(inputElement);
assert.equal(inputElement.value, "05/3");
inputElement.value = "05/311";
TestUtils.Simulate.change(inputElement);
assert.equal(inputElement.value, "05/31/1");
ReactDOM.unmountComponentAtNode(container);
}));
it("should automatically insert in YYYY/MM/DD format.", co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} dateFormat="YYYY/MM/DD" />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
inputElement.value = "0";
TestUtils.Simulate.change(inputElement);
inputElement.value = "19800";
TestUtils.Simulate.change(inputElement);
assert.equal(inputElement.value, "1980/0");
inputElement.value = "1980/053";
TestUtils.Simulate.change(inputElement);
assert.equal(inputElement.value, "1980/05/3");
ReactDOM.unmountComponentAtNode(container);
}));
it("should render dates in different formats.", co.wrap(function *(){
const mm_dd_yyyy_id = "_" + UUID.v4();
const dd_mm_yyyy_id = "_" + UUID.v4();
const yyyy_mm_dd_id = "_" + UUID.v4();
const values = {};
const formattedValues = {};
const getValues = {};
const getFormattedValues = {};
const App = createReactClass({
getInitialState: function(){
return {
value: null
}
},
handleChange(newValue, newFormattedValue, dateFormat){
this.setState({value:newValue});
values[dateFormat] = newValue;
formattedValues[dateFormat] = newFormattedValue;
},
componentDidUpdate() {
getValues["MM/DD/YYYY"] = this.refs["MM/DD/YYYY"].getValue();
getFormattedValues["MM/DD/YYYY"] = this.refs["MM/DD/YYYY"].getFormattedValue();
getValues["DD/MM/YYYY"] = this.refs["DD/MM/YYYY"].getValue();
getFormattedValues["DD/MM/YYYY"] = this.refs["DD/MM/YYYY"].getFormattedValue();
getValues["YYYY/MM/DD"] = this.refs["YYYY/MM/DD"].getValue();
getFormattedValues["YYYY/MM/DD"] = this.refs["YYYY/MM/DD"].getFormattedValue();
},
render: function(){
return <div>
<DatePicker ref="MM/DD/YYYY" id={mm_dd_yyyy_id} dateFormat="MM/DD/YYYY" onChange={(newValue, newFormattedValue) => this.handleChange(newValue, newFormattedValue, "MM/DD/YYYY")} value={this.state.value} />
<DatePicker ref="DD/MM/YYYY" id={dd_mm_yyyy_id} dateFormat="DD/MM/YYYY" onChange={(newValue, newFormattedValue) => this.handleChange(newValue, newFormattedValue, "DD/MM/YYYY")} value={this.state.value} />
<DatePicker ref="YYYY/MM/DD" id={yyyy_mm_dd_id} dateFormat="YYYY/MM/DD" onChange={(newValue, newFormattedValue) => this.handleChange(newValue, newFormattedValue, "YYYY/MM/DD")} value={this.state.value} />
</div>;
}
});
const app = <App />;
yield new Promise(function(resolve, reject){
ReactDOM.render(app, container, resolve);
});
const mm_dd_yyyy_inputElement = document.querySelector("#" + mm_dd_yyyy_id + "_group input.form-control");
const dd_mm_yyyy_inputElement = document.querySelector("#" + dd_mm_yyyy_id + "_group input.form-control");
const yyyy_mm_dd_inputElement = document.querySelector("#" + yyyy_mm_dd_id + "_group input.form-control");
let date;
mm_dd_yyyy_inputElement.value = "05/31/1980";
TestUtils.Simulate.change(mm_dd_yyyy_inputElement);
TestUtils.Simulate.change(dd_mm_yyyy_inputElement);
TestUtils.Simulate.change(yyyy_mm_dd_inputElement);
assert.equal(mm_dd_yyyy_inputElement.value, "05/31/1980");
assert.equal(dd_mm_yyyy_inputElement.value, "31/05/1980");
assert.equal(yyyy_mm_dd_inputElement.value, "1980/05/31");
assertIsoStringsHaveSameDate("1980-05-31T12:00:00.000Z", values["MM/DD/YYYY"]);
assertIsoStringsHaveSameDate("1980-05-31T12:00:00.000Z", values["DD/MM/YYYY"]);
assertIsoStringsHaveSameDate("1980-05-31T12:00:00.000Z", values["YYYY/MM/DD"]);
assertIsoStringsHaveSameDate("1980-05-31T12:00:00.000Z", getValues["MM/DD/YYYY"]);
assertIsoStringsHaveSameDate("1980-05-31T12:00:00.000Z", getValues["DD/MM/YYYY"]);
assertIsoStringsHaveSameDate("1980-05-31T12:00:00.000Z", getValues["YYYY/MM/DD"]);
assert.equal(formattedValues["MM/DD/YYYY"], "05/31/1980");
assert.equal(formattedValues["DD/MM/YYYY"], "31/05/1980");
assert.equal(formattedValues["YYYY/MM/DD"], "1980/05/31");
assert.equal(getFormattedValues["MM/DD/YYYY"], "05/31/1980");
assert.equal(getFormattedValues["DD/MM/YYYY"], "31/05/1980");
assert.equal(getFormattedValues["YYYY/MM/DD"], "1980/05/31");
dd_mm_yyyy_inputElement.value = "15/04/2015";
TestUtils.Simulate.change(dd_mm_yyyy_inputElement);
TestUtils.Simulate.change(mm_dd_yyyy_inputElement);
TestUtils.Simulate.change(yyyy_mm_dd_inputElement);
assert.equal(mm_dd_yyyy_inputElement.value, "04/15/2015");
assert.equal(dd_mm_yyyy_inputElement.value, "15/04/2015");
assert.equal(yyyy_mm_dd_inputElement.value, "2015/04/15");
assertIsoStringsHaveSameDate("2015-04-15T12:00:00.000Z", values["MM/DD/YYYY"]);
assertIsoStringsHaveSameDate("2015-04-15T12:00:00.000Z", values["DD/MM/YYYY"]);
assertIsoStringsHaveSameDate("2015-04-15T12:00:00.000Z", values["YYYY/MM/DD"]);
assertIsoStringsHaveSameDate("2015-04-15T12:00:00.000Z", getValues["MM/DD/YYYY"]);
assertIsoStringsHaveSameDate("2015-04-15T12:00:00.000Z", getValues["DD/MM/YYYY"]);
assertIsoStringsHaveSameDate("2015-04-15T12:00:00.000Z", getValues["YYYY/MM/DD"]);
assert.equal(formattedValues["MM/DD/YYYY"], "04/15/2015");
assert.equal(formattedValues["DD/MM/YYYY"], "15/04/2015");
assert.equal(formattedValues["YYYY/MM/DD"], "2015/04/15");
assert.equal(getFormattedValues["MM/DD/YYYY"], "04/15/2015");
assert.equal(getFormattedValues["DD/MM/YYYY"], "15/04/2015");
assert.equal(getFormattedValues["YYYY/MM/DD"], "2015/04/15");
yyyy_mm_dd_inputElement.value = "1999/12/31";
TestUtils.Simulate.change(yyyy_mm_dd_inputElement);
TestUtils.Simulate.change(mm_dd_yyyy_inputElement);
TestUtils.Simulate.change(dd_mm_yyyy_inputElement);
assert.equal(mm_dd_yyyy_inputElement.value, "12/31/1999");
assert.equal(dd_mm_yyyy_inputElement.value, "31/12/1999");
assert.equal(yyyy_mm_dd_inputElement.value, "1999/12/31");
assertIsoStringsHaveSameDate("1999-12-31T12:00:00.000Z", values["MM/DD/YYYY"]);
assertIsoStringsHaveSameDate("1999-12-31T12:00:00.000Z", values["DD/MM/YYYY"]);
assertIsoStringsHaveSameDate("1999-12-31T12:00:00.000Z", values["YYYY/MM/DD"]);
assertIsoStringsHaveSameDate("1999-12-31T12:00:00.000Z", getValues["MM/DD/YYYY"]);
assertIsoStringsHaveSameDate("1999-12-31T12:00:00.000Z", getValues["DD/MM/YYYY"]);
assertIsoStringsHaveSameDate("1999-12-31T12:00:00.000Z", getValues["YYYY/MM/DD"]);
assert.equal(formattedValues["MM/DD/YYYY"], "12/31/1999");
assert.equal(formattedValues["DD/MM/YYYY"], "31/12/1999");
assert.equal(formattedValues["YYYY/MM/DD"], "1999/12/31");
assert.equal(getFormattedValues["MM/DD/YYYY"], "12/31/1999");
assert.equal(getFormattedValues["DD/MM/YYYY"], "31/12/1999");
assert.equal(getFormattedValues["YYYY/MM/DD"], "1999/12/31");
ReactDOM.unmountComponentAtNode(container);
}));
it("week should start on Monday.", co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} weekStartsOn={1} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
assert.equal(document.querySelector("table thead tr:first-child td small").innerHTML, "Mon");
ReactDOM.unmountComponentAtNode(container);
}));
it("should allow placing the popover calendar in a container specified in the props.", co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} calendarContainer={calendarContainer} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
assert.notEqual(document.querySelector("#calendarContainer .date-picker-popover"), null);
ReactDOM.unmountComponentAtNode(container);
}));
it("should have no focus with autoFocus false.", co.wrap(function *(){
const id = UUID.v4();
const value = new Date().toISOString();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} value={value} autoFocus={false}/>
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
assert.notEqual(inputElement, document.activeElement);
ReactDOM.unmountComponentAtNode(container);
}));
it("should have focus with autoFocus true.", co.wrap(function *(){
const id = UUID.v4();
const value = new Date().toISOString();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} value={value} autoFocus={true}/>
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
assert.equal(inputElement, document.activeElement);
ReactDOM.unmountComponentAtNode(container);
}));
it("should disable the input.", co.wrap(function *(){
const id = UUID.v4();
const value = new Date().toISOString();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} value={value} disabled={true}/>
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const hiddenInputElement = document.getElementById(id);
const inputElement = document.querySelector("input.form-control");
assert.equal(inputElement.disabled, true);
ReactDOM.unmountComponentAtNode(container);
}));
it("should disable the input.", co.wrap(function *(){
const id = UUID.v4();
let value = new Date().toISOString();
let originalValue = value;
const App = createReactClass({
handleChange: function(newValue){
value = newValue;
},
render: function(){
return <div>
<DatePicker id={id} onChange={this.handleChange} disabled={true} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
assert.equal(inputElement.disabled, true);
const clearButtonElement = document.querySelector("span.input-group-addon");
TestUtils.Simulate.click(clearButtonElement);
assertIsoStringsHaveSameDate(value, originalValue);
ReactDOM.unmountComponentAtNode(container);
}));
it("should display the correct day of the week in the calendar.", co.wrap(function *(){
const id = UUID.v4();
let value = null;
let formattedValue = null;
const App = createReactClass({
handleChange: function(newValue, newFormattedValue){
value = newValue;
formattedValue = newFormattedValue;
},
render: function(){
return <div>
<DatePicker id={id} onChange={this.handleChange} dateFormat="MM/DD/YYYY" />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
const hiddenInputElement = document.getElementById(id);
const checkMonthAndYear = function(startValue) {
inputElement.value = `${startValue.slice(5,7)}/${startValue.slice(8,10)}/${startValue.slice(0,4)}`;
TestUtils.Simulate.change(inputElement);
TestUtils.Simulate.focus(inputElement);
const weekElements = document.querySelectorAll("table tbody tr");
for(let i = 0; i < weekElements.length; i++) {
const dayElements = weekElements[i].querySelectorAll("td");
for(let j = 0; j < dayElements.length; j++) {
const dayElement = dayElements[j];
if(dayElement.innerHTML === '') {
return;
}
TestUtils.Simulate.click(dayElement);
let date = new Date(hiddenInputElement.value);
assert.equal(date.getDay(), j);
}
}
}
const today = new Date();
for(let year = today.getFullYear() - 2; year < today.getFullYear() + 2; year++) {
for(let month = 0; month < 12; month++) {
const date = new Date();
date.setMonth(month);
date.setYear(year);
checkMonthAndYear(date.toISOString());
}
}
ReactDOM.unmountComponentAtNode(container);
}));
it("should display the correct day of the week in the calendar when starting on Monday.", co.wrap(function *(){
const id = UUID.v4();
let value = null;
let formattedValue = null;
const App = createReactClass({
handleChange: function(newValue, newFormattedValue){
value = newValue;
formattedValue = newFormattedValue;
},
render: function(){
return <div>
<DatePicker id={id} onChange={this.handleChange} dateFormat="MM/DD/YYYY" weekStartsOn={1} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
const hiddenInputElement = document.getElementById(id);
const checkMonthAndYear = function(startValue) {
inputElement.value = `${startValue.slice(5,7)}/${startValue.slice(8,10)}/${startValue.slice(0,4)}`;
TestUtils.Simulate.change(inputElement);
TestUtils.Simulate.focus(inputElement);
const weekElements = document.querySelectorAll("table tbody tr");
for(let i = 0; i < weekElements.length; i++) {
const dayElements = weekElements[i].querySelectorAll("td");
for(let j = 0; j < dayElements.length; j++) {
const dayElement = dayElements[j];
if(dayElement.innerHTML === '') {
return;
}
TestUtils.Simulate.click(dayElement);
let date = new Date(hiddenInputElement.value);
assert.equal(date.getDay(), j === 6 ? 0 : j + 1);
}
}
}
const today = new Date();
for(let year = today.getFullYear() - 2; year < today.getFullYear() + 2; year++) {
for(let month = 0; month < 12; month++) {
const date = new Date();
date.setMonth(month);
date.setYear(year);
checkMonthAndYear(date.toISOString());
}
}
ReactDOM.unmountComponentAtNode(container);
}));
it("should set a default value", co.wrap(function *(){
const id = UUID.v4();
const defaultValue = `${new Date().toISOString().slice(0,10)}T12:00:00.000Z`;
let value = null;
let formattedValue = null;
const App = createReactClass({
handleChange: function(newValue, newFormattedValue){
value = newValue;
formattedValue = newFormattedValue;
},
render: function(){
return <div>
<DatePicker defaultValue={defaultValue} id={id} onChange={this.handleChange} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const hiddenInputElement = document.getElementById(id);
assertIsoStringsHaveSameDate(hiddenInputElement.value, defaultValue);
assert.equal(value, null);
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.change(inputElement);
assert.notEqual(value, null);
ReactDOM.unmountComponentAtNode(container);
}));
it("should error if value and default value are both set.", co.wrap(function *(){
const value = new Date().toISOString();
const App = createReactClass({
render: function(){
return <div>
<DatePicker value={value} defaultValue={value} />
</div>;
}
});
try {
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
throw new Error("Value and default value should not be set simultaneously");
} catch (e) {
assert(e.message.indexOf("Conflicting") !== -1)
}
ReactDOM.unmountComponentAtNode(container);
}));
it('should render with today button element', co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker
id={id}
showTodayButton={true}
todayButtonLabel="Today is the day"
/>
</div>;
}
});
yield new Promise(function(resolve){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector('input.form-control');
TestUtils.Simulate.focus(inputElement);
const todayElement = document.querySelector('.u-today-button');
assert.equal(todayElement.innerText, 'Today is the day');
ReactDOM.unmountComponentAtNode(container);
}));
it('should render a custom button element', co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker
id={id}
customControl={<button id="test-btn">Test button</button>} />
</div>;
}
});
yield new Promise(function(resolve){
ReactDOM.render(<App />, container, resolve);
});
const customElement = document.getElementById('test-btn');
assert.notEqual(customElement, null);
assert.equal(customElement.innerText, 'Test button');
ReactDOM.unmountComponentAtNode(container);
}));
it("should set the FormControl className.", co.wrap(function *(){
const id = UUID.v4();
const className = `_${UUID.v4()}`;
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} className={className} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector(`input.${className}`);
assert.notEqual(inputElement, null);
ReactDOM.unmountComponentAtNode(container);
}));
it("should set the FormControl style.", co.wrap(function *(){
const backgroundColor = `rgb(${Math.round(Math.random() * 255, 0)}, ${Math.round(Math.random() * 255, 0)}, ${Math.round(Math.random() * 255, 0)})`;
const App = createReactClass({
render: function(){
return <div>
<DatePicker style={{backgroundColor: backgroundColor}}/>
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector('input.form-control');
assert.equal(inputElement.style.backgroundColor, backgroundColor);
ReactDOM.unmountComponentAtNode(container);
}));
it("should disable dates outside of min and max dates.", co.wrap(function *(){
const id = UUID.v4();
const originalValue = "2016-09-15T12:00:00.000Z"
const minDate = "2016-09-11T00:00:00.000Z";
const maxDate = "2016-09-17T00:00:00.000Z";
const justRightValue = "2016-09-11T12:00:00.000Z"
const App = createReactClass({
getInitialState: function(){
return {
value: originalValue
}
},
handleChange(value){
this.setState({value:value});
},
render: function(){
return <div>
<DatePicker id={id} onChange={this.handleChange} minDate={minDate} maxDate={maxDate} value={this.state.value} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const hiddenInputElement = document.getElementById(id);
const tooEarly = document.querySelector("table tbody tr:nth-child(2) td");
const justRight = document.querySelector("table tbody tr:nth-child(3) td");
const tooLate = document.querySelector("table tbody tr:nth-child(4) td");
assert.equal(hiddenInputElement.value, originalValue);
TestUtils.Simulate.click(tooEarly);
assert.equal(hiddenInputElement.value, originalValue);
TestUtils.Simulate.click(justRight);
assert.equal(hiddenInputElement.value, justRightValue);
TestUtils.Simulate.click(tooLate);
assert.equal(hiddenInputElement.value, justRightValue);
ReactDOM.unmountComponentAtNode(container);
}));
it("should show next and prev buttons if min and max dates are not set.", co.wrap(function *(){
const id = UUID.v4();
const displayDate = "2017-07-21T12:00:00.000Z"
const App = createReactClass({
getInitialState: function(){
return {
value: displayDate
}
},
handleChange(value){
this.setState({value:value});
},
render: function(){
return <div>
<DatePicker id={id} onChange={this.handleChange} value={this.state.value} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const prevButton = document.querySelector(".datepicker-previous-wrapper");
const nextButton = document.querySelector(".datepicker-next-wrapper");
assert.equal(prevButton.innerHTML, '<');
assert.equal(nextButton.innerHTML, '>');
ReactDOM.unmountComponentAtNode(container);
}));
it("should show next and prev buttons if min and max dates are set but not displayed.", co.wrap(function *(){
const id = UUID.v4();
const displayDate = "2017-07-21T12:00:00.000Z"
const minDate = "2017-01-01T12:00:00.000Z";
const maxDate = "2017-12-31T12:00:00.000Z";
const App = createReactClass({
getInitialState: function(){
return {
value: displayDate
}
},
handleChange(value){
this.setState({value:value});
},
render: function(){
return <div>
<DatePicker id={id} onChange={this.handleChange} minDate={minDate} maxDate={maxDate} value={this.state.value} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const prevButton = document.querySelector(".datepicker-previous-wrapper");
const nextButton = document.querySelector(".datepicker-next-wrapper");
assert.equal(prevButton.innerHTML, '<');
assert.equal(nextButton.innerHTML, '>');
ReactDOM.unmountComponentAtNode(container);
}));
it("should hide previousButtonElement if min date is set and being displayed.", co.wrap(function *(){
const id = UUID.v4();
const displayDate = "2017-01-15T12:00:00.000Z"
const minDate = "2017-01-01T12:00:00.000Z";
const maxDate = "2017-12-31T12:00:00.000Z";
const App = createReactClass({
getInitialState: function(){
return {
value: displayDate
}
},
handleChange(value){
this.setState({value:value});
},
render: function(){
return <div>
<DatePicker id={id} onChange={this.handleChange} minDate={minDate} maxDate={maxDate} value={this.state.value} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const prevButton = document.querySelector(".datepicker-previous-wrapper");
const nextButton = document.querySelector(".datepicker-next-wrapper");
assert.equal(prevButton.innerHTML, '');
assert.equal(nextButton.innerHTML, '>');
ReactDOM.unmountComponentAtNode(container);
}));
it("should hide nextButtonElement if max date is set and being displayed.", co.wrap(function *(){
const id = UUID.v4();
const displayDate = "2017-12-15T12:00:00.000Z"
const minDate = "2017-01-01T12:00:00.000Z";
const maxDate = "2017-12-31T12:00:00.000Z";
const App = createReactClass({
getInitialState: function(){
return {
value: displayDate
}
},
handleChange(value){
this.setState({value:value});
},
render: function(){
return <div>
<DatePicker id={id} onChange={this.handleChange} minDate={minDate} maxDate={maxDate} value={this.state.value} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const prevButton = document.querySelector(".datepicker-previous-wrapper");
const nextButton = document.querySelector(".datepicker-next-wrapper");
assert.equal(prevButton.innerHTML, '<');
assert.equal(nextButton.innerHTML, '');
ReactDOM.unmountComponentAtNode(container);
}));
it("should allow for rounded corners.", co.wrap(function *(){
const withoutRoundedCorners = "_" + UUID.v4();
const withRoundedCorners = "_" + UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={withoutRoundedCorners} />
<DatePicker id={withRoundedCorners} roundedCorners />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const withoutRoundedCorners_inputElement = document.querySelector("#" + withoutRoundedCorners + "_group input.form-control");
const withRoundedCorners_inputElement = document.querySelector("#" + withRoundedCorners + "_group input.form-control");
TestUtils.Simulate.focus(withoutRoundedCorners_inputElement);
const withoutRoundedCornersDayElement = document.querySelector("#" + withoutRoundedCorners + "_group table tbody tr:nth-child(2) td");
TestUtils.Simulate.click(withoutRoundedCornersDayElement);
assert.equal(withoutRoundedCornersDayElement.style.borderRadius, '0px');
TestUtils.Simulate.focus(withRoundedCorners_inputElement);
const withRoundedCornersDayElement = document.querySelector("#" + withRoundedCorners + "_group table tbody tr:nth-child(2) td");
TestUtils.Simulate.click(withRoundedCornersDayElement);
assert.equal(withRoundedCornersDayElement.style.borderRadius, '5px');
ReactDOM.unmountComponentAtNode(container);
}));
it("week should start on Thursday.", co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} weekStartsOn={4} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
assert.equal(document.querySelector("table thead tr:first-child td small").innerHTML, "Thu");
ReactDOM.unmountComponentAtNode(container);
}));
it("week should start on Saturday.", co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} weekStartsOn={6} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
assert.equal(document.querySelector("table thead tr:first-child td small").innerHTML, "Sat");
ReactDOM.unmountComponentAtNode(container);
}));
it("should allow for a string to determine calendar placement", co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
render: function(){
return <div>
<DatePicker id={id} calendarPlacement="right" />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const popover = document.querySelector(".date-picker-popover.right");
assert.notEqual(popover, null);
ReactDOM.unmountComponentAtNode(container);
}));
it("should allow for a function to determine calendar placement", co.wrap(function *(){
const id = UUID.v4();
const App = createReactClass({
handlePlacement(){
return "top";
},
render: function(){
return <div>
<DatePicker id={id} calendarPlacement={this.handlePlacement} />
</div>;
}
});
yield new Promise(function(resolve, reject){
ReactDOM.render(<App />, container, resolve);
});
const inputElement = document.querySelector("input.form-control");
TestUtils.Simulate.focus(inputElement);
const popover = document.querySelector(".date-picker-popover.top");
assert.notEqual(popover, null);
ReactDOM.unmountComponentAtNode(container);
}));
});