/* global it, xit, describe, expect, jasmine, done, jest */
import React from "react"; // eslint-disable-line no-unused-vars
import moment from "moment";
import _momentTimezone from "moment-timezone"; // eslint-disable-line no-unused-vars
import utils from "./testUtils";
import Enzyme from "enzyme";
import Adapter from "enzyme-adapter-react-15";

Enzyme.configure({ adapter: new Adapter() });

describe("Calendar", () => {
    it("create component", () =>
    {
        const component = utils.createCalendar({ });

        expect(component).toBeDefined();
        expect(component.find(".rdt > .form-control").length).toEqual(1);
        expect(component.find(".rdt > .rdtPicker").length).toEqual(1);
    });

    it("viewMode=days: renders days, week days, month, year", () =>
    {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createCalendar({ viewMode: "days", defaultValue: date });
        utils.openDatepicker(component);

        // Month and year
        expect(component.find(".rdtSwitch").text()).toEqual("January 2000");

        // Week days
        const expectedWeekDays = [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ],
            actualWeekdays = component.find(".rdtDays .dow").map((element) =>
            element.text()
        );
        expect(actualWeekdays).toEqual(expectedWeekDays);

        // Dates
        // "Old" dates belonging to prev month
        const oldDatesIndexes = [ 0, 1, 2, 3, 4, 5 ];
        oldDatesIndexes.forEach((index) => {
            expect(utils.getNthDay(component, index).hasClass("rdtOld")).toBeTruthy();
        });

        // Dates belonging to current month
        for (let i = 6; i < 37; i++) {
            expect(utils.getNthDay(component, i).hasClass("rdtDay")).toBeTruthy();
            expect(utils.getNthDay(component, i).hasClass("rdtOld")).toBeFalsy();
            expect(utils.getNthDay(component, i).hasClass("rdtNew")).toBeFalsy();
        }

        // "New" dates belonging to next month
        const nextDatesIndexes = [ 37, 38, 39, 40, 41 ];
        nextDatesIndexes.forEach((index) => {
            expect(utils.getNthDay(component, index).hasClass("rdtNew")).toBeTruthy();
        });
    });

    it("switch from day view to time view and back", () =>
    {
        const component = utils.createCalendar({ });

        expect(utils.isDayView(component)).toBeTruthy();
        utils.clickOnElement(component.find(".rdtTimeToggle"));
        expect(utils.isTimeView(component)).toBeTruthy();
        utils.clickOnElement(component.find(".rdtSwitch"));
        expect(utils.isDayView(component)).toBeTruthy();
    });

    it("persistent valid months going monthView->yearView->monthView", () =>
    {
        const dateBefore = "2018-06-01";
        const component = utils.createCalendar({ viewMode: "months", isValidDate: (current) =>
                current.isBefore(moment(dateBefore, "YYYY-MM-DD"))
        });

        expect(utils.isMonthView(component)).toBeTruthy();
        expect(utils.getNthMonth(component, 4).hasClass("rdtDisabled")).toEqual(false);
        expect(utils.getNthMonth(component, 5).hasClass("rdtDisabled")).toEqual(true);

        // Go to year view
        utils.clickOnElement(component.find(".rdtSwitch"));
        expect(utils.isYearView(component)).toBeTruthy();

        expect(utils.getNthYear(component, 0).hasClass("rdtDisabled")).toEqual(false);
        expect(utils.getNthYear(component, 10).hasClass("rdtDisabled")).toEqual(true);

        utils.clickNthYear(component, 9);
        expect(utils.getNthMonth(component, 4).hasClass("rdtDisabled")).toEqual(false);
        expect(utils.getNthMonth(component, 5).hasClass("rdtDisabled")).toEqual(true);
    });

    it("step through views", () => {
        const component = utils.createCalendar({ viewMode: "time" });

        expect(utils.isTimeView(component)).toBeTruthy();
        utils.clickOnElement(component.find(".rdtSwitch"));
        expect(utils.isDayView(component)).toBeTruthy();
        utils.clickOnElement(component.find(".rdtSwitch"));
        expect(utils.isMonthView(component)).toBeTruthy();
        utils.clickOnElement(component.find(".rdtSwitch"));
        expect(utils.isYearView(component)).toBeTruthy();
    });

    it("toggles calendar when open prop changes", () =>
    {
        const component = utils.createCalendar({ open: false });
        expect(utils.isOpen(component)).toBeFalsy();
        // expect(component.find(".rdtOpen").length).toEqual(0);
        component.setProps({ open: true });
        expect(utils.isOpen(component)).toBeTruthy();
        // expect(component.find(".rdtOpen").length).toEqual(1);
        component.setProps({ open: false });
        expect(utils.isOpen(component)).toBeFalsy();
        // expect(component.find(".rdtOpen").length).toEqual(0);
    });

    it("selectYear", () =>
    {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createCalendar({ viewMode: "years", defaultValue: date });
        expect(utils.isYearView(component)).toBeTruthy();
        expect(component.find(".rdtSwitch").text()).toEqual("2000-2009");

        // Click first year (1999)
        utils.clickOnElement(component.find(".rdtYear").at(0));
        expect(utils.isMonthView(component)).toBeTruthy();
        expect(component.find(".rdtSwitch").text()).toEqual("1999");
    });

    it("increase decade", () =>
    {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createCalendar({ viewMode: "years", defaultValue: date });

        expect(component.find(".rdtSwitch").text()).toEqual("2000-2009");
        utils.clickOnElement(component.find(".rdtNext span").at(0));
        expect(component.find(".rdtSwitch").text()).toEqual("2010-2019");
        utils.clickOnElement(component.find(".rdtNext span").at(0));
        expect(component.find(".rdtSwitch").text()).toEqual("2020-2029");
    });

    it("decrease decade", () =>
    {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createCalendar({ viewMode: "years", defaultValue: date });

        expect(component.find(".rdtSwitch").text()).toEqual("2000-2009");
        utils.clickOnElement(component.find(".rdtPrev span").at(0));
        expect(component.find(".rdtSwitch").text()).toEqual("1990-1999");
        utils.clickOnElement(component.find(".rdtPrev span").at(0));
        expect(component.find(".rdtSwitch").text()).toEqual("1980-1989");
    });

    it("select month", () =>
    {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createCalendar({ viewMode: "months", defaultValue: date });

        expect(utils.isMonthView(component)).toBeTruthy();
        expect(component.find(".rdtSwitch").text()).toEqual("2000");
        // Click any month to enter day view
        utils.clickNthMonth(component, 1);
        expect(utils.isDayView(component)).toBeTruthy();
        expect(component.find(".rdtSwitch").getDOMNode().getAttribute("data-value")).toEqual("1");
    });

    it("increase year", () =>
    {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createCalendar({ viewMode: "months", defaultValue: date });

        expect(component.find(".rdtSwitch").text()).toEqual("2000");
        utils.clickOnElement(component.find(".rdtNext span").at(0));
        expect(component.find(".rdtSwitch").text()).toEqual("2001");
        utils.clickOnElement(component.find(".rdtNext span").at(0));
        expect(component.find(".rdtSwitch").text()).toEqual("2002");
    });

    it("decrease year", () =>
    {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createCalendar({ viewMode: "months", defaultValue: date });

        expect(component.find(".rdtSwitch").text()).toEqual("2000");
        utils.clickOnElement(component.find(".rdtPrev span").at(0));
        expect(component.find(".rdtSwitch").text()).toEqual("1999");
        utils.clickOnElement(component.find(".rdtPrev span").at(0));
        expect(component.find(".rdtSwitch").text()).toEqual("1998");
    });

    it("increase month", () =>
    {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createCalendar({ defaultValue: date });

        expect(component.find(".rdtSwitch").text()).toEqual("January 2000");
        expect(component.find(".rdtSwitch").getDOMNode().getAttribute("data-value")).toEqual("0");
        utils.clickOnElement(component.find(".rdtNext span").at(0));
        expect(component.find(".rdtSwitch").text()).toEqual("February 2000");
        expect(component.find(".rdtSwitch").getDOMNode().getAttribute("data-value")).toEqual("1");
        utils.clickOnElement(component.find(".rdtNext span").at(0));
        expect(component.find(".rdtSwitch").text()).toEqual("March 2000");
        expect(component.find(".rdtSwitch").getDOMNode().getAttribute("data-value")).toEqual("2");
    });

    it("decrease month", () =>
    {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createCalendar({ defaultValue: date });

        expect(component.find(".rdtSwitch").text()).toEqual("January 2000");
        expect(component.find(".rdtSwitch").getDOMNode().getAttribute("data-value")).toEqual("0");
        utils.clickOnElement(component.find(".rdtPrev span").at(0));
        expect(component.find(".rdtSwitch").text()).toEqual("December 1999");
        expect(component.find(".rdtSwitch").getDOMNode().getAttribute("data-value")).toEqual("11");
        utils.clickOnElement(component.find(".rdtPrev span").at(0));
        expect(component.find(".rdtSwitch").text()).toEqual("November 1999");
        expect(component.find(".rdtSwitch").getDOMNode().getAttribute("data-value")).toEqual("10");
    });

    it("open picker", () =>
    {
        const component = utils.createCalendar();
        expect(utils.isOpen(component)).toBeFalsy();
        utils.openDatepicker(component);
        expect(utils.isOpen(component)).toBeTruthy();
    });

    it("opens picker when clicking on input", () =>
    {
        const component = utils.createCalendar();
        expect(utils.isOpen(component)).toBeFalsy();
        component.find(".form-control").simulate("click");
        expect(utils.isOpen(component)).toBeTruthy();
    });

    it("sets CSS class on selected item (day)", () =>
    {
        const component = utils.createCalendar({ viewMode: "days" });
        utils.openDatepicker(component);
        utils.clickNthDay(component, 13);
        expect(utils.getNthDay(component, 13).hasClass("rdtActive")).toBeTruthy();
    });

    it("sets CSS class on selected item (month)", () =>
    {
        const component = utils.createCalendar({ viewMode: "months", dateFormat: "YYYY-MM" });
        utils.openDatepicker(component);
        utils.clickNthMonth(component, 4);
        expect(utils.getNthMonth(component, 4).hasClass("rdtActive")).toBeTruthy();
    });

    it("sets CSS class on selected item (year)", () =>
    {
        const component = utils.createCalendar({ viewMode: "years", dateFormat: "YYYY" });
        utils.openDatepicker(component);
        utils.clickNthYear(component, 3);
        expect(utils.getNthYear(component, 3).hasClass("rdtActive")).toBeTruthy();
    });

    it("sets CSS class on days outside of month", () =>
    {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            prevMonthDaysIndexes = [ 0, 1, 2, 3, 4, 5 ],
            nextMonthDaysIndexes = [ 37, 38, 39, 40, 41 ],
            component = utils.createCalendar({ viewMode: "days", defaultValue: date });

        utils.openDatepicker(component);

        prevMonthDaysIndexes.forEach((index) => {
            expect(utils.getNthDay(component, index).hasClass("rdtOld")).toBeTruthy();
        });
        nextMonthDaysIndexes.forEach((index) => {
            expect(utils.getNthDay(component, index).hasClass("rdtNew")).toBeTruthy();
        });
    });

    it("selected day persists (in UI) when navigating to prev month", () =>
    {
        const date = new Date(2000, 0, 3, 2, 2, 2, 2),
            component = utils.createCalendar({ viewMode: "days", defaultValue: date });

        utils.openDatepicker(component);
        expect(utils.getNthDay(component, 8).hasClass("rdtActive")).toBeTruthy();
        // Go to previous month
        utils.clickOnElement(component.find(".rdtDays .rdtPrev span"));
        expect(utils.getNthDay(component, 36).hasClass("rdtActive")).toBeTruthy();
    });

    it("sets CSS class on today date", () =>
    {
        const specificDate = moment("2015-04-19"),
            component = utils.createCalendar({ defaultValue: specificDate });

        // Mock the today date
        jasmine.clock().mockDate(specificDate.toDate());

        utils.openDatepicker(component);
        expect(component.find(".rdtDay.rdtToday").text()).toEqual("19");
    });

    describe("with custom props", () =>
    {
        it("input=false", () =>
        {
            const component = utils.createCalendar({ input: false });
            expect(component.find(".rdt > .form-control").length).toEqual(0);
            expect(component.find(".rdt > .rdtPicker").length).toEqual(1);
        });

        it("dateFormat", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                component = utils.createCalendar({ value: date, dateFormat: "M&D" });
            expect(utils.getInputValue(component)).toEqual(mDate.format("M&D LT"));
        });

        it("dateFormat=false", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                component = utils.createCalendar({ value: date, dateFormat: false });
            expect(utils.getInputValue(component)).toEqual(mDate.format("LT"));
            // Make sure time view is active
            expect(utils.isTimeView(component)).toBeTruthy();
            // Make sure the date toggle is not rendered
            expect(component.find("thead").length).toEqual(0);
        });

        it("timeFormat", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                format = "HH:mm:ss:SSS",
                component = utils.createCalendar({ value: date, timeFormat: format });
            expect(utils.getInputValue(component)).toEqual(mDate.format("L " + format));
        });

        it("timeFormat=false", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                component = utils.createCalendar({ value: date, timeFormat: false });
            expect(utils.getInputValue(component)).toEqual(mDate.format("L"));
            // Make sure day view is active
            expect(utils.isDayView(component)).toBeTruthy();
            // Make sure the time toggle is not rendered
            expect(component.find(".timeToggle").length).toEqual(0);
        });

        it("timeFormat with lowercase \"am\"", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                format = "HH:mm:ss:SSS a",
                component = utils.createCalendar({ value: date, timeFormat: format });
            expect(utils.getInputValue(component)).toEqual(expect.stringMatching(".*am$"));
        });

        it("timeFormat with uppercase \"AM\"", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                format = "HH:mm:ss:SSS A",
                component = utils.createCalendar({ value: date, timeFormat: format });
            expect(utils.getInputValue(component)).toEqual(expect.stringMatching(".*AM$"));
        });

        it("viewMode=years", () =>
        {
            const component = utils.createCalendar({ viewMode: "years" });
            expect(utils.isYearView(component)).toBeTruthy();
        });

        it("viewMode=months", () =>
        {
            const component = utils.createCalendar({ viewMode: "months" });
            expect(utils.isMonthView(component)).toBeTruthy();
        });

        it("viewMode=time", () =>
        {
            const component = utils.createCalendar({ viewMode: "time" });
            expect(utils.isTimeView(component)).toBeTruthy();
        });

        it("className -> type string", () =>
        {
            const component = utils.createCalendarShallow({ className: "custom-class" });
            expect(component.find(".custom-class").length).toEqual(1);
        });

        it("className -> type string array", () =>
        {
            const component = utils.createCalendarShallow({ className: [ "custom-class1", "custom-class2" ] });
            expect(component.find(".custom-class1").length).toEqual(1);
            expect(component.find(".custom-class2").length).toEqual(1);
        });

        it("inputProps", () =>
        {
            const component = utils.createCalendar({
                inputProps: { className: "custom-class", type: "email", placeholder: "custom-placeholder" }
            });
            expect(component.find("input.custom-class").length).toEqual(1);
            expect(component.find("input").getDOMNode().type).toEqual("email");
            expect(component.find("input").getDOMNode().placeholder).toEqual("custom-placeholder");
        });

        it("renderInput", () =>
        {
            const renderInput = (props, openCalendar) => {
                return (
                    <div>
                        <input {...props} />
                        <button className="custom-open" onClick={openCalendar}>open calendar</button>
                    </div>
                    );
            };
            const component = utils.createCalendar({ renderInput });

            expect(component.find("button.custom-open").length).toEqual(1);
            expect(utils.isOpen(component)).toBeFalsy();
            utils.clickOnElement(component.find("button.custom-open"));
            expect(utils.isOpen(component)).toBeTruthy();
        });

        it("renderDay", () =>
        {
            let props = { },
                currentDate = "",
                selectedDate = "";
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                renderDayFn = (fnProps, current, selected) => {
                props = fnProps;
                currentDate = current;
                selectedDate = selected;

                return <td {...fnProps}>custom-content</td>;
            };

            const component = utils.createCalendar({ value: mDate, renderDay: renderDayFn });

            // Last day should be 6th of february
            expect(currentDate.day()).toEqual(6);
            expect(currentDate.month()).toEqual(1);

            // The date must be the same
            expect(selectedDate.isSame(mDate)).toEqual(true);

            // There should be a onClick function in the props
            expect(typeof props.onClick).toEqual("function");

            // The cell text should match
            expect(component.find(".rdtDay").at(0).text()).toEqual("custom-content");
        });

        it("renderMonth", () =>
        {
            let props = { },
                month = "",
                year = "",
                selectedDate = "";

            const
                date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                renderMonthFn = (fnProps, fnMonth, fnYear, selected) =>
                {
                    props = fnProps;
                    month = fnMonth;
                    year = fnYear;
                    selectedDate = selected;

                    return <td {...fnProps}>custom-content</td>;
                };

            const component = utils.createCalendar({ value: mDate, viewMode: "months", renderMonth: renderMonthFn });

            expect(month).toEqual(11);
            expect(year).toEqual(2000);

            // The date must be the same
            expect(selectedDate.isSame(mDate)).toEqual(true);

            // There should be a onClick function in the props
            expect(typeof props.onClick).toEqual("function");

            // The cell text should match
            expect(component.find(".rdtMonth").at(0).text()).toEqual("custom-content");
        });

        it("renderYear", () =>
        {
            let props = { },
                year = "",
                selectedDate = "";
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                renderYearFn = (fnProps, fnYear, selected) => {
                props = fnProps;
                year = fnYear;
                selectedDate = selected;

                return <td {...fnProps}>custom-content</td>;
            };

            const component = utils.createCalendar({ value: mDate, viewMode: "years", renderYear: renderYearFn });

            expect(year).toEqual(2010);

            // The date must be the same
            expect(selectedDate.isSame(mDate)).toEqual(true);

            // There should be a onClick function in the props
            expect(typeof props.onClick).toEqual("function");

            // The cell text should match
            expect(component.find(".rdtYear").at(0).text()).toEqual("custom-content");
        });

        it("closeOnTab=true", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                component = utils.createCalendar({ value: date });

            expect(utils.isOpen(component)).toBeFalsy();
            utils.openDatepicker(component);
            expect(utils.isOpen(component)).toBeTruthy();
            component.find(".form-control").simulate("keyDown", { key: "Tab", keyCode: 9, which: 9 });
            expect(utils.isOpen(component)).toBeFalsy();
        });

        it("closeOnTab=false", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                component = utils.createCalendar({ value: date, closeOnTab: false });

            expect(utils.isOpen(component)).toBeFalsy();
            utils.openDatepicker(component);
            expect(utils.isOpen(component)).toBeTruthy();
            component.find(".form-control").simulate("keyDown", { key: "Tab", keyCode: 9, which: 9 });
            expect(utils.isOpen(component)).toBeTruthy();
        });

        it("disableCloseOnClickOutside=true", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                component = utils.createCalendar({ value: date, disableCloseOnClickOutside: true });

            expect(utils.isOpen(component)).toBeFalsy();
            utils.openDatepicker(component);
            expect(utils.isOpen(component)).toBeTruthy();
            document.dispatchEvent(new Event("mousedown"));
            component.update();
            expect(utils.isOpen(component)).toBeTruthy();
        });

        it("disableCloseOnClickOutside=false", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                component = utils.createCalendar({ value: date, disableCloseOnClickOutside: false });

            expect(utils.isOpen(component)).toBeFalsy();
            utils.openDatepicker(component);
            expect(utils.isOpen(component)).toBeTruthy();
            document.dispatchEvent(new Event("mousedown"));
            component.update();
            expect(utils.isOpen(component)).toBeFalsy();
        });

        it("increase time", () =>
        {
            let i = 0;
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                component = utils.createCalendar({ timeFormat: "HH:mm:ss:SSS", viewMode: "time",
                    defaultValue: date, onChange: (selected) =>
                    {
                        // TODO: Trigger onChange when increasing time
                        i++;
                        if (i > 2) {
                            expect(true).toEqual(false); // Proof that this is not called
                            expect(selected.hour()).toEqual(3);
                            expect(selected.minute()).toEqual(3);
                            expect(selected.second()).toEqual(3);
                            done();
                        }
                    } });

            // Check hour
            expect(utils.getHours(component)).toEqual("2");
            utils.increaseHour(component);
            expect(utils.getHours(component)).toEqual("3");

            // Check minute
            expect(utils.getMinutes(component)).toEqual("02");
            utils.increaseMinute(component);
            expect(utils.getMinutes(component)).toEqual("03");

            // Check second
            expect(utils.getSeconds(component)).toEqual("02");
            utils.increaseSecond(component);
            expect(utils.getSeconds(component)).toEqual("03");
        });

        it("decrease time", () =>
        {
            let i = 0;
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                component = utils.createCalendar({ timeFormat: "HH:mm:ss:SSS", viewMode: "time",
                    defaultValue: date, onChange: (selected) =>
                    {
                        // TODO: Trigger onChange when increasing time
                        i++;
                        if (i > 2) {
                            expect(true).toEqual(false); // Proof that this is not called
                            expect(selected.hour()).toEqual(1);
                            expect(selected.minute()).toEqual(1);
                            expect(selected.second()).toEqual(1);
                            done();
                        }
                    }
                });

            // Check hour
            expect(utils.getHours(component)).toEqual("2");
            utils.decreaseHour(component);
            expect(utils.getHours(component)).toEqual("1");

            // Check minute
            expect(utils.getMinutes(component)).toEqual("02");
            utils.decreaseMinute(component);
            expect(utils.getMinutes(component)).toEqual("01");

            // Check second
            expect(utils.getSeconds(component)).toEqual("02");
            utils.decreaseSecond(component);
            expect(utils.getSeconds(component)).toEqual("01");
        });

        it("long increase time", (done) =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                component = utils.createCalendar({ timeFormat: "HH:mm:ss:SSS", viewMode: "time", defaultValue: date });

            utils.increaseHour(component);
            setTimeout(() =>
            {
                expect(utils.getHours(component)).not.toEqual("2");
                expect(utils.getHours(component)).not.toEqual("3");
                done();
            }, 920);
        });

        it("long decrease time", (done) =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                component = utils.createCalendar({ timeFormat: "HH:mm:ss:SSS", viewMode: "time", defaultValue: date });

            utils.decreaseHour(component);
            setTimeout(() => {
                expect(utils.getHours(component)).not.toEqual("1");
                expect(utils.getHours(component)).not.toEqual("0");
                done();
            }, 920);
        });

        it("timeConstraints -> increase time", () =>
        {
            let i = 0;
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                component = utils.createCalendar({ timeFormat: "HH:mm:ss:SSS", viewMode: "time",
                    defaultValue: date, timeConstraints: { hours: { max: 6, step: 8 }, minutes: { step: 15 } },
                    onChange: (selected) => {
                        // TODO
                        i++;
                        if (i > 2) {
                            expect(selected.minute()).toEqual(17);
                            expect(selected.second()).toEqual(3);
                            done();
                        }
                    }
                });

            utils.increaseHour(component);
            expect(utils.getHours(component)).toEqual("3");

            utils.increaseMinute(component);
            expect(utils.getMinutes(component)).toEqual("17");

            utils.increaseSecond(component);
            expect(utils.getSeconds(component)).toEqual("03");
        });

        it("timeConstraints -> decrease time", () =>
        {
            let i = 0;
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                component = utils.createCalendar({ timeFormat: "HH:mm:ss:SSS", viewMode: "time",
                    defaultValue: date, timeConstraints: { minutes: { step: 15 } }, onChange: (selected) =>
                    {
                        // TODO
                        i++;
                        if (i > 2) {
                            expect(selected.minute()).toEqual(17);
                            expect(selected.second()).toEqual(3);
                            done();
                        }
                    }
                });

            utils.decreaseMinute(component);
            expect(utils.getMinutes(component)).toEqual("47");
        });

        it("strictParsing=true", (done) =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                strDate = mDate.format("L") + " " + mDate.format("LT"),
                invalidStrDate = strDate + "x",
                component = utils.createCalendar({ defaultValue: "", strictParsing: true,
                    onChange: (updated) => {
                        expect(updated, invalidStrDate);
                        done();
                    } });

            component.find(".form-control").simulate("change", { target: { value: invalidStrDate } });
        });

        it("strictParsing=false", (done) =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                strDate = mDate.format("L") + " " + mDate.format("LT"),
                invalidStrDate = strDate + "x",
                component = utils.createCalendar({ defaultValue: "", strictParsing: false,
                    onChange: (updated) => {
                        expect(mDate.format("L LT")).toEqual(updated.format("L LT"));
                        done();
                    } });

            component.find(".form-control").simulate("change", { target: { value: invalidStrDate } });
        });

        it("isValidDate -> disable months", () =>
        {
            const dateBefore = new Date().getFullYear() + "-06-01",
                component = utils.createCalendar({ viewMode: "months", isValidDate: (current) =>
                        current.isBefore(moment(dateBefore, "YYYY-MM-DD"))
                });

            expect(utils.getNthMonth(component, 0).hasClass("rdtDisabled")).toEqual(false);
            expect(utils.getNthMonth(component, 4).hasClass("rdtDisabled")).toEqual(false);
            expect(utils.getNthMonth(component, 5).hasClass("rdtDisabled")).toEqual(true);
            expect(utils.getNthMonth(component, 11).hasClass("rdtDisabled")).toEqual(true);
        });

        it("isValidDate -> disable years", () =>
        {
            const component = utils.createCalendar({ viewMode: "years", isValidDate: (current) =>
                current.isBefore(moment("2016-01-01", "YYYY-MM-DD"))
            });

            expect(utils.getNthYear(component, 0).hasClass("rdtDisabled")).toEqual(false);
            expect(utils.getNthYear(component, 6).hasClass("rdtDisabled")).toEqual(false);
            expect(utils.getNthYear(component, 7).hasClass("rdtDisabled")).toEqual(true);
        });

        it("locale", () => {
            const component = utils.createCalendar({ locale: "nl" }),
                expectedWeekDays = [ "ma", "di", "wo", "do", "vr", "za", "zo" ],
                actualWeekDays = component.find(".rdtDays .dow").map((element) =>
                element.text().toLowerCase()
            );

            expect(actualWeekDays).toEqual(expectedWeekDays);
        });

        it("locale with viewMode=months", () => {
            const component = utils.createCalendar({ locale: "nl", viewMode: "months" }),
                expectedMonths = [ "Mrt", "Mei" ],
                actualMonths = [ utils.getNthMonth(component, 2).text(), utils.getNthMonth(component, 4).text() ];

            expect(actualMonths).toEqual(expectedMonths);
        });

        it("closeOnSelect=false", (done) =>
        {
            const component = utils.createCalendar({ closeOnSelect: false });

            // A unknown race condition is causing this test to fail without this time out,
            // and when the test fails it says:
            // "Timeout - Async callback was not invoked within timeout"
            // Ideally it would say something else but at least we know the tests are passing now
            setTimeout(() => {
                expect(utils.isOpen(component)).toBeFalsy();
                utils.openDatepicker(component);
                expect(utils.isOpen(component)).toBeTruthy();
                utils.clickNthDay(component, 2);
                expect(utils.isOpen(component)).toBeTruthy();
                done();
            }, 0);
        });

        it("closeOnSelect=true", (done) =>
        {
            const component = utils.createCalendar({ closeOnSelect: true });

            // A unknown race condition is causing this test to fail without this time out,
            // and when the test fails it says:
            // "Timeout - Async callback was not invoked within timeout"
            // Ideally it would say something else but at least we know the tests are passing now
            setTimeout(() =>
            {
                expect(utils.isOpen(component)).toBeFalsy();
                utils.openDatepicker(component);
                expect(utils.isOpen(component)).toBeTruthy();
                utils.clickNthDay(component, 2);
                expect(utils.isOpen(component)).toBeFalsy();
                done();
            }, 0);
        });

        describe("defaultValue of type", () =>
        {
            it("date", () => {
                const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                    momentDate = moment(date),
                    strDate = momentDate.format("L") + " " + momentDate.format("LT"),
                    component = utils.createCalendar({ defaultValue: date });
                expect(utils.getInputValue(component)).toEqual(strDate);
            });

            it("moment", () =>
            {
                const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                    momentDate = moment(date),
                    strDate = momentDate.format("L") + " " + momentDate.format("LT"),
                    component = utils.createCalendar({ defaultValue: momentDate });
                expect(utils.getInputValue(component)).toEqual(strDate);
            });

            it("string", () =>
            {
                const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                    momentDate = moment(date),
                    strDate = momentDate.format("L") + " " + momentDate.format("LT"),
                    component = utils.createCalendar({ defaultValue: strDate });
                expect(utils.getInputValue(component)).toEqual(strDate);
            });
        });

        describe("timeFormat with", () =>
        {
            it("milliseconds", () =>
            {
                const component = utils.createCalendar({ viewMode: "time", timeFormat: "HH:mm:ss:SSS" });
                expect(component.find(".rdtCounter").length).toEqual(4);
                // TODO: Test that you can input a value in milli seconds input
            });

            it("seconds", () =>
            {
                const component = utils.createCalendar({ viewMode: "time", timeFormat: "HH:mm:ss" });
                expect(component.find(".rdtCounter").length).toEqual(3);
            });

            it("minutes", () =>
            {
                const component = utils.createCalendar({ viewMode: "time", timeFormat: "HH:mm" });
                expect(component.find(".rdtCounter").length).toEqual(2);
            });

            it("hours", () =>
            {
                const component = utils.createCalendar({ viewMode: "time", timeFormat: "HH" });
                expect(component.find(".rdtCounter").length).toEqual(1);
            });
        });

        describe("being updated and should trigger update", () =>
        {
            it("dateFormat -> value should change format", (done) =>
            {
                const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                    component = utils.createCalendar({
                        dateFormat: "YYYY-MM-DD", timeFormat: false, defaultValue: date
                    });

                const valueBefore = utils.getInputValue(component);
                // A unknown race condition is causing this test to fail without this time out,
                // and when the test fails it says:
                // "Timeout - Async callback was not invoked within timeout"
                // Ideally it would say something else but at least we know the tests are passing now
                setTimeout(() => {
                    component.setProps({ dateFormat: "DD.MM.YYYY" });
                    const valueAfter = utils.getInputValue(component);

                    expect(valueBefore).not.toEqual(valueAfter);
                    done();
                }, 0);
            });

            it("UTC -> value should change format (true->false)", () =>
            {
                const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                    momentDate = moment(date),
                    component = utils.createCalendar({ value: momentDate, utc: true });

                const valueBefore = utils.getInputValue(component);
                component.setProps({ utc: false }, () => {
                    const valueAfter = utils.getInputValue(component);

                    expect(valueBefore).not.toEqual(valueAfter);
                });
            });

            it("UTC -> value should change format (false->true)", () =>
            {
                const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                    momentDate = moment(date),
                    component = utils.createCalendar({ value: momentDate, utc: false });

                const valueBefore = utils.getInputValue(component);
                component.setProps({ utc: true }, () => {
                    const valueAfter = utils.getInputValue(component);

                    expect(valueBefore).not.toEqual(valueAfter);
                });
            });

            it("displayTimeZone -> value should change format (undefined->America/New_York)", () =>
            {
                const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                    momentDate = moment(date),
                    component = utils.createCalendar({ value: momentDate }),
                    displayTimeZone = (moment.tz.guess() === "America/New_York" ? "America/Los_Angeles" : "America/New_York");

                const valueBefore = utils.getInputValue(component);
                component.setProps({ displayTimeZone: displayTimeZone }, () =>
                {
                    const valueAfter = utils.getInputValue(component);

                    expect(valueBefore).not.toEqual(valueAfter);
                });
            });

            it("displayTimeZone -> value should change format (America/New_York->undefined)", () =>
            {
                const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                    momentDate = moment(date),
                    displayTimeZone = (moment.tz.guess() === "America/New_York" ? "America/Los_Angeles" : "America/New_York"),
                    component = utils.createCalendar({ value: momentDate, displayTimeZone: displayTimeZone });

                const valueBefore = utils.getInputValue(component);
                component.setProps({ displayTimeZone: undefined }, () =>
                {
                    const valueAfter = utils.getInputValue(component);

                    expect(valueBefore).not.toEqual(valueAfter);
                });
            });

            it("locale -> picker should change language (viewMode=days)", () =>
            {
                const component = utils.createCalendar({ viewMode: "days", locale: "nl" }),
                    weekdaysBefore = component.find(".rdtDays .dow").map((element) =>
                    element.text()
                );

                component.setProps({ locale: "sv" });
                const weekdaysAfter = component.find(".rdtDays .dow").map((element) =>
                    element.text()
                );

                expect(weekdaysBefore).not.toEqual(weekdaysAfter);
            });

            it("locale -> picker should change language (viewMode=months)", () => {
                const component = utils.createCalendar({ viewMode: "months", locale: "nl" }),
                    monthsBefore = [ utils.getNthMonth(component, 2).text(), utils.getNthMonth(component, 4).text() ];

                component.setProps({ locale: "sv" });
                const monthsAfter = [ utils.getNthMonth(component, 2).text(), utils.getNthMonth(component, 4).text() ];

                expect(monthsBefore).not.toEqual(monthsAfter);
            });
        });
    });

    describe("event listeners", () =>
    {
        describe("onBlur", () =>
        {
            it("when selecting a date", () =>
            {
                const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                    onBlurFn = jest.fn(),
                    component = utils.createCalendar({ value: date, onBlur: onBlurFn, closeOnSelect: true });

                utils.openDatepicker(component);
                // Close component by selecting a date
                utils.clickNthDay(component, 2);
                expect(onBlurFn).toHaveBeenCalledTimes(1);
            });

            it("when selecting date (value=null and closeOnSelect=true)", () =>
            {
                const onBlurFn = jest.fn(),
                    component = utils.createCalendar({ value: null, onBlur: onBlurFn, closeOnSelect: true });

                utils.openDatepicker(component);
                // Close component by selecting a date
                utils.clickNthDay(component, 2);
                expect(onBlurFn).toHaveBeenCalledTimes(1);
            });

            it("when selecting date (value=null and closeOnSelect=false)", () =>
            {
                const onBlurFn = jest.fn(),
                    component = utils.createCalendar({ value: null, onBlur: onBlurFn, closeOnSelect: false });

                utils.openDatepicker(component);
                // Close component by selecting a date
                utils.clickNthDay(component, 2);
                expect(onBlurFn).not.toHaveBeenCalled();
            });
        });

        it("onFocus when opening datepicker", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                onFocusFn = jest.fn(),
                component = utils.createCalendar({ value: date, onFocus: onFocusFn });

            utils.openDatepicker(component);
            expect(onFocusFn).toHaveBeenCalledTimes(1);
        });

        describe("onViewModeChange", () =>
        {
            it("when switch from days to time view mode", () =>
            {
                const component = utils.createCalendar({ onViewModeChange: (viewMode) =>
                    {
                        expect(viewMode).toEqual("time");
                    }
                });

                expect(utils.isDayView(component)).toBeTruthy();
                utils.clickOnElement(component.find(".rdtTimeToggle"));
                expect(utils.isTimeView(component)).toBeTruthy();
            });

            it("when switch from time to days view mode", () =>
            {
                const component = utils.createCalendar({ viewMode: "time", onViewModeChange: (viewMode) =>
                    {
                        expect(viewMode).toEqual("days");
                    }
                });

                expect(utils.isTimeView(component)).toBeTruthy();
                utils.clickOnElement(component.find(".rdtSwitch"));
                expect(utils.isDayView(component)).toBeTruthy();
            });

            it("when switch from days to months view mode", () =>
            {
                const component = utils.createCalendar({ onViewModeChange: (viewMode) =>
                    {
                        expect(viewMode).toEqual("months");
                    }
                });

                expect(utils.isDayView(component)).toBeTruthy();
                utils.clickOnElement(component.find(".rdtSwitch"));
                expect(utils.isMonthView(component)).toBeTruthy();
            });

            it("when switch from months to years view mode", () =>
            {
                const component = utils.createCalendar({ viewMode: "months", onViewModeChange: (viewMode) =>
                    {
                        expect(viewMode).toEqual("years");
                    }
                });

                expect(utils.isMonthView(component)).toBeTruthy();
                utils.clickOnElement(component.find(".rdtSwitch"));
                expect(utils.isYearView(component)).toBeTruthy();
            });

            it("only when switch from years to months view mode", () =>
            {
                const component = utils.createCalendar({ viewMode: "years", onViewModeChange: (viewMode) =>
                    {
                        expect(viewMode).toEqual("months");
                    }
                });

                expect(utils.isYearView(component)).toBeTruthy();
                utils.clickOnElement(component.find(".rdtSwitch"));
                expect(utils.isYearView(component)).toBeTruthy();
                utils.clickNthYear(component, 2);
                expect(utils.isMonthView(component)).toBeTruthy();
            });

            it("when switch from months to days view mode", () =>
            {
                const component = utils.createCalendar({ viewMode: "months", onViewModeChange: (viewMode) =>
                    {
                        expect(viewMode).toEqual("days");
                    }
                });

                expect(utils.isMonthView(component)).toBeTruthy();
                utils.clickNthMonth(component, 2);
                expect(utils.isDayView(component)).toBeTruthy();
            });
        });

        describe("onChange", () =>
        {
            it("trigger only when last selection type is selected", () =>
            {
                // By selection type I mean if you CAN select day, then selecting a month
                // should not trigger onChange
                const onChangeFn = jest.fn(),
                    component = utils.createCalendar({ viewMode: "years", onChange: onChangeFn });

                utils.openDatepicker(component);

                utils.clickNthYear(component, 2);
                expect(onChangeFn).not.toHaveBeenCalled();

                utils.clickNthMonth(component, 2);
                expect(onChangeFn).not.toHaveBeenCalled();

                utils.clickNthDay(component, 2);
                expect(onChangeFn).toHaveBeenCalled();
            });

            it("when selecting date", (done) =>
            {
                const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                    mDate = moment(date),
                    component = utils.createCalendar({ defaultValue: date, onChange: (selected) =>
                        {
                            expect(selected.date()).toEqual(2);
                            expect(selected.month()).toEqual(mDate.month());
                            expect(selected.year()).toEqual(mDate.year());
                            done();
                        }
                    });

                utils.clickNthDay(component, 7);
            });

            it("when selecting multiple date in a row", (done) => {
                let i = 0;
                const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                    mDate = moment(date),
                    component = utils.createCalendar({ defaultValue: date, onChange: (selected) =>
                        {
                            i++;
                            if (i > 2) {
                                expect(selected.date()).toEqual(4);
                                expect(selected.month()).toEqual(mDate.month());
                                expect(selected.year()).toEqual(mDate.year());
                                done();
                            }
                        }
                    });

                utils.clickNthDay(component, 7);
                utils.clickNthDay(component, 8);
                utils.clickNthDay(component, 9);
            });

            it("when selecting month", () =>
            {
                const date = Date.UTC(2000, 0, 15, 2, 2, 2, 2),
                    onChangeFn = jest.fn(),
                    component = utils.createCalendar({ defaultValue: date, dateFormat: "YYYY-MM", onChange: onChangeFn });

                utils.clickNthMonth(component, 2);
                expect(onChangeFn).toHaveBeenCalledTimes(1);
                expect(onChangeFn.mock.calls[0][0].toJSON()).toEqual("2000-03-15T02:02:02.002Z");
            });

            // Passes locally but not on Travis
            xit("when selecting year", () =>
            {
                const date = Date.UTC(2000, 0, 15, 2, 2, 2, 2),
                    onChangeFn = jest.fn(),
                    component = utils.createCalendar({ defaultValue: date, dateFormat: "YYYY", onChange: onChangeFn });

                utils.clickNthYear(component, 2);
                expect(onChangeFn).toHaveBeenCalledTimes(1);
                expect(onChangeFn.mock.calls[0][0].toJSON()).toEqual("2001-01-15T02:02:02.002Z");
            });

            it("when selecting time", () =>
            {
                // Did not manage to be able to get onChange to trigger, even though I know it does.
                // The listener for the time buttons are set up differently because of having to handle both
                // onMouseDown and onMouseUp. Not sure how to test it.
                expect(true).toEqual(true);
            });
        });
    });

    describe("onNavigateForward", () =>
    {
        it("when moving to next month", () =>
        {
            const component = utils.createCalendar({ onNavigateForward: (amount, type) =>
                {
                    expect(amount).toEqual(1);
                    expect(type).toEqual("months");
                }
            });

            utils.clickOnElement(component.find(".rdtNext"));
        });

        it("when moving to next year", () =>
        {
            const component = utils.createCalendar({ viewMode: "months", onNavigateForward: (amount, type) =>
                {
                    expect(amount).toEqual(1);
                    expect(type).toEqual("years");
                }
            });

            utils.clickOnElement(component.find(".rdtNext"));
        });

        it("when moving decade forward", () =>
        {
            const component = utils.createCalendar({ viewMode: "years", onNavigateForward: (amount, type) =>
                {
                    expect(amount).toEqual(10);
                    expect(type).toEqual("years");
                }
            });

            utils.clickOnElement(component.find(".rdtNext"));
        });
    });

    describe("onNavigateBack", () =>
    {
        it("when moving to previous month", () =>
        {
            const component = utils.createCalendar({ onNavigateBack: (amount, type) =>
                {
                    expect(amount).toEqual(1);
                    expect(type).toEqual("months");
                }
            });

            utils.clickOnElement(component.find(".rdtPrev"));
        });

        it("when moving to previous year", () =>
        {
            const component = utils.createCalendar({ viewMode: "months", onNavigateBack: (amount, type) =>
                {
                    expect(amount).toEqual(1);
                    expect(type).toEqual("years");
                }
            });

            utils.clickOnElement(component.find(".rdtPrev"));
        });

        it("when moving decade back", () =>
        {
            const component = utils.createCalendar({ viewMode: "years", onNavigateBack: (amount, type) =>
                {
                    expect(amount).toEqual(10);
                    expect(type).toEqual("years");
                }
            });

            utils.clickOnElement(component.find(".rdtPrev"));
        });
    });

    describe("with set value", () =>
    {
        it("date value", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                strDate = mDate.format("L") + " " + mDate.format("LT"),
                component = utils.createCalendar({ value: date });

            expect(utils.getInputValue(component)).toEqual(strDate);
        });

        it("moment value", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                strDate = mDate.format("L") + " " + mDate.format("LT"),
                component = utils.createCalendar({ value: mDate });
            expect(utils.getInputValue(component)).toEqual(strDate);
        });

        it("string value", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                strDate = mDate.format("L") + " " + mDate.format("LT"),
                component = utils.createCalendar({ value: strDate });

            expect(utils.getInputValue(component)).toEqual(strDate);
        });

        it("UTC value from local moment", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                momentDate = moment(date),
                momentDateUTC = moment.utc(date),
                strDateUTC = momentDateUTC.format("L") + " " + momentDateUTC.format("LT"),
                component = utils.createCalendar({ value: momentDate, utc: true });

            expect(utils.getInputValue(component)).toEqual(strDateUTC);
        });

        it("UTC value from UTC moment", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                momentDateUTC = moment.utc(date),
                strDateUTC = momentDateUTC.format("L") + " " + momentDateUTC.format("LT"),
                component = utils.createCalendar({ value: momentDateUTC, utc: true });

            expect(utils.getInputValue(component)).toEqual(strDateUTC);
        });

        it("UTC value from UTC string", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                momentDateUTC = moment.utc(date),
                strDateUTC = momentDateUTC.format("L") + " " + momentDateUTC.format("LT"),
                component = utils.createCalendar({ value: strDateUTC, utc: true });

            expect(utils.getInputValue(component)).toEqual(strDateUTC);
        });

        it("TZ value from local moment", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                displayTimeZone = "America/New_York",
                momentDate = moment(date),
                momentDateTZ = moment.tz(date, displayTimeZone),
                strDateTZ = momentDateTZ.format("L") + " " + momentDateTZ.format("LT"),
                component = utils.createCalendar({ value: momentDate, displayTimeZone: displayTimeZone });

            expect(utils.getInputValue(component)).toEqual(strDateTZ);
        });

        it("TZ value from UTC moment", () =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                displayTimeZone = "America/New_York",
                momentDateUTC = moment.utc(date),
                momentDateTZ = moment.tz(date, displayTimeZone),
                strDateTZ = momentDateTZ.format("L") + " " + momentDateTZ.format("LT"),
                component = utils.createCalendar({ value: momentDateUTC, displayTimeZone: displayTimeZone });

            expect(utils.getInputValue(component)).toEqual(strDateTZ);
        });

        it("invalid string value", (done) =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                strDate = mDate.format("L") + " " + mDate.format("LT"),
                component = utils.createCalendar({ defaultValue: "invalid-value", onChange: (updated) =>
                    {
                        expect(mDate.format("L LT")).toEqual(updated.format("L LT"));
                        done();
                    }
                });

            expect(component.find(".form-control").getDOMNode().value).toEqual("invalid-value");
            component.find(".form-control").simulate("change", { target: { value: strDate } });
        });

        it("delete invalid string value", (done) =>
        {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
                component = utils.createCalendar({ defaultValue: date, onChange: (date) =>
                    {
                        expect(date).toEqual("");
                        done();
                    }
                });

            component.find(".form-control").simulate("change", { target: { value: "" } });
        });

        it("invalid moment object", (done) =>
        {
            const invalidValue = moment(null),
                date = new Date(2000, 0, 15, 2, 2, 2, 2),
                mDate = moment(date),
                strDate = mDate.format("L") + " " + mDate.format("LT"),
                component = utils.createCalendar({ value: invalidValue, onChange: (updated) =>
                    {
                        expect(mDate.format("L LT")).toEqual(updated.format("L LT"));
                        done();
                    }
                });

            expect(component.find(".form-control").getDOMNode().value).toEqual("");
            component.find(".form-control").simulate("change", { target: { value: strDate } });
        });
    });
});
