Simon Egersand
2018-02-07 de3fe15c59e7692eda6058a0dc8d0271acbcf3a3
test/tests.spec.js
@@ -9,1145 +9,1428 @@
Enzyme.configure({ adapter: new Adapter() });
describe('Datetime', () => {
   it('create component', () => {
      const component = utils.createDatetime({});
  it('create component', () => {
    const component = utils.createDatetime({});
      expect(component).toBeDefined();
      expect(component.find('.rdt > .form-control').length).toEqual(1);
      expect(component.find('.rdt > .rdtPicker').length).toEqual(1);
   });
    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.createDatetime({ viewMode: 'days', defaultValue: date });
      utils.openDatepicker(component);
  it('viewMode=days: renders days, week days, month, year', () => {
    const date = new Date(2000, 0, 15, 2, 2, 2, 2),
      component = utils.createDatetime({
        viewMode: 'days',
        defaultValue: date
      });
    utils.openDatepicker(component);
      // Month and year
      expect(component.find('.rdtSwitch').text()).toEqual('January 2000');
    // 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);
    // 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
    // "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();
      }
    // 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();
      });
   });
    // "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.createDatetime({});
  it('switch from day view to time view and back', () => {
    const component = utils.createDatetime({});
      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();
   });
    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.createDatetime({ viewMode: 'months', isValidDate: (current) =>
            current.isBefore(moment(dateBefore, 'YYYY-MM-DD'))
         });
  it('persistent valid months going monthView->yearView->monthView', () => {
    const dateBefore = '2018-06-01';
    const component = utils.createDatetime({
      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);
    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();
    // 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);
    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);
   });
    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.createDatetime({ viewMode: 'time' });
  it('step through views', () => {
    const component = utils.createDatetime({ 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();
   });
    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.createDatetime({ 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('toggles calendar when open prop changes', () => {
    const component = utils.createDatetime({ 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.createDatetime({ viewMode: 'years', defaultValue: date });
      expect(utils.isYearView(component)).toBeTruthy();
      expect(component.find('.rdtSwitch').text()).toEqual('2000-2009');
  it('selectYear', () => {
    const date = new Date(2000, 0, 15, 2, 2, 2, 2),
      component = utils.createDatetime({
        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');
   });
    // 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.createDatetime({ viewMode: 'years', defaultValue: date });
  it('increase decade', () => {
    const date = new Date(2000, 0, 15, 2, 2, 2, 2),
      component = utils.createDatetime({
        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');
   });
    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.createDatetime({ viewMode: 'years', defaultValue: date });
  it('decrease decade', () => {
    const date = new Date(2000, 0, 15, 2, 2, 2, 2),
      component = utils.createDatetime({
        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');
   });
    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.createDatetime({ viewMode: 'months', defaultValue: date });
  it('select month', () => {
    const date = new Date(2000, 0, 15, 2, 2, 2, 2),
      component = utils.createDatetime({
        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');
   });
    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.createDatetime({ viewMode: 'months', defaultValue: date });
  it('increase year', () => {
    const date = new Date(2000, 0, 15, 2, 2, 2, 2),
      component = utils.createDatetime({
        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');
   });
    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.createDatetime({ viewMode: 'months', defaultValue: date });
  it('decrease year', () => {
    const date = new Date(2000, 0, 15, 2, 2, 2, 2),
      component = utils.createDatetime({
        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');
   });
    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.createDatetime({ defaultValue: date });
  it('increase month', () => {
    const date = new Date(2000, 0, 15, 2, 2, 2, 2),
      component = utils.createDatetime({ 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');
   });
    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.createDatetime({ defaultValue: date });
  it('decrease month', () => {
    const date = new Date(2000, 0, 15, 2, 2, 2, 2),
      component = utils.createDatetime({ 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');
   });
    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.createDatetime();
      expect(utils.isOpen(component)).toBeFalsy();
      utils.openDatepicker(component);
      expect(utils.isOpen(component)).toBeTruthy();
   });
  it('open picker', () => {
    const component = utils.createDatetime();
    expect(utils.isOpen(component)).toBeFalsy();
    utils.openDatepicker(component);
    expect(utils.isOpen(component)).toBeTruthy();
  });
   it('opens picker when clicking on input', () => {
      const component = utils.createDatetime();
      expect(utils.isOpen(component)).toBeFalsy();
      component.find('.form-control').simulate('click');
      expect(utils.isOpen(component)).toBeTruthy();
   });
  it('opens picker when clicking on input', () => {
    const component = utils.createDatetime();
    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.createDatetime({ viewMode: 'days' });
      utils.openDatepicker(component);
      utils.clickNthDay(component, 13);
      expect(utils.getNthDay(component, 13).hasClass('rdtActive')).toBeTruthy();
   });
  it('sets CSS class on selected item (day)', () => {
    const component = utils.createDatetime({ 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.createDatetime({ 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 (month)', () => {
    const component = utils.createDatetime({
      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.createDatetime({ viewMode: 'years', dateFormat: 'YYYY' });
      utils.openDatepicker(component);
      utils.clickNthYear(component, 3);
      expect(utils.getNthYear(component, 3).hasClass('rdtActive')).toBeTruthy();
   });
  it('sets CSS class on selected item (year)', () => {
    const component = utils.createDatetime({
      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.createDatetime({ viewMode: 'days', defaultValue: date });
  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.createDatetime({
        viewMode: 'days',
        defaultValue: date
      });
      utils.openDatepicker(component);
    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();
      });
   });
    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.createDatetime({ viewMode: 'days', defaultValue: date });
  it('selected day persists (in UI) when navigating to prev month', () => {
    const date = new Date(2000, 0, 3, 2, 2, 2, 2),
      component = utils.createDatetime({
        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();
   });
    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.createDatetime({ defaultValue: specificDate });
  it('sets CSS class on today date', () => {
    const specificDate = moment('2015-04-19'),
      component = utils.createDatetime({ defaultValue: specificDate });
      // Mock the today date
      jasmine.clock().mockDate(specificDate.toDate());
    // Mock the today date
    jasmine.clock().mockDate(specificDate.toDate());
      utils.openDatepicker(component);
      expect(component.find('.rdtDay.rdtToday').text()).toEqual('19');
   });
    utils.openDatepicker(component);
    expect(component.find('.rdtDay.rdtToday').text()).toEqual('19');
  });
   // Proof of bug [FIXED]
   it('should show correct selected month when traversing view modes', () => {
      const date = new Date(2000, 4, 3, 2, 2, 2, 2),
         component = utils.createDatetime({ viewMode: 'days', defaultValue: date });
  // Proof of bug [FIXED]
  it('should show correct selected month when traversing view modes', () => {
    const date = new Date(2000, 4, 3, 2, 2, 2, 2),
      component = utils.createDatetime({
        viewMode: 'days',
        defaultValue: date
      });
      utils.openDatepicker(component);
    utils.openDatepicker(component);
      // Go to month view
      utils.clickOnElement(component.find('.rdtSwitch'));
    // Go to month view
    utils.clickOnElement(component.find('.rdtSwitch'));
      // Here the selected month is _May_, which is correct
      expect(component.find('.rdtMonth .rdtActive').text()).toEqual('May');
    // Here the selected month is _May_, which is correct
    expect(component.find('.rdtMonth .rdtActive').text()).toEqual('May');
      // Go to year view
      utils.clickOnElement(component.find('.rdtSwitch'));
    // Go to year view
    utils.clickOnElement(component.find('.rdtSwitch'));
      // Click the selected year (2000)
      utils.clickNthYear(component, 1);
    // Click the selected year (2000)
    utils.clickNthYear(component, 1);
      // The selected month is now _January_
      expect(component.find('.rdtMonth .rdtActive').text()).toEqual('May');
   });
    // The selected month is now _January_
    expect(component.find('.rdtMonth .rdtActive').text()).toEqual('May');
  });
   describe('with custom props', () => {
      it('input=false', () => {
         const component = utils.createDatetime({ input: false });
         expect(component.find('.rdt > .form-control').length).toEqual(0);
         expect(component.find('.rdt > .rdtPicker').length).toEqual(1);
      });
  describe('with custom props', () => {
    it('input=false', () => {
      const component = utils.createDatetime({ 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.createDatetime({ value: date, dateFormat: 'M&D' });
         expect(utils.getInputValue(component)).toEqual(mDate.format('M&D LT'));
      });
    it('dateFormat', () => {
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        mDate = moment(date),
        component = utils.createDatetime({ 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.createDatetime({ 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('dateFormat=false', () => {
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        mDate = moment(date),
        component = utils.createDatetime({ 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.createDatetime({ value: date, timeFormat: format });
         expect(utils.getInputValue(component)).toEqual(mDate.format('L ' + format));
      });
    it('timeFormat', () => {
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        mDate = moment(date),
        format = 'HH:mm:ss:SSS',
        component = utils.createDatetime({ 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.createDatetime({ 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=false', () => {
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        mDate = moment(date),
        component = utils.createDatetime({ 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.createDatetime({ value: date, timeFormat: format });
         expect(utils.getInputValue(component)).toEqual(expect.stringMatching('.*am$'));
      });
    it("timeFormat with lowercase 'am'", () => {
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        format = 'HH:mm:ss:SSS a',
        component = utils.createDatetime({ 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.createDatetime({ 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.createDatetime({ value: date, timeFormat: format });
      expect(utils.getInputValue(component)).toEqual(
        expect.stringMatching('.*AM$')
      );
    });
      it('viewMode=years', () => {
         const component = utils.createDatetime({ viewMode: 'years' });
         expect(utils.isYearView(component)).toBeTruthy();
      });
    it('viewMode=years', () => {
      const component = utils.createDatetime({ viewMode: 'years' });
      expect(utils.isYearView(component)).toBeTruthy();
    });
      it('viewMode=months', () => {
         const component = utils.createDatetime({ viewMode: 'months' });
         expect(utils.isMonthView(component)).toBeTruthy();
      });
    it('viewMode=months', () => {
      const component = utils.createDatetime({ viewMode: 'months' });
      expect(utils.isMonthView(component)).toBeTruthy();
    });
      it('viewMode=time', () => {
         const component = utils.createDatetime({ viewMode: 'time' });
         expect(utils.isTimeView(component)).toBeTruthy();
      });
    it('viewMode=time', () => {
      const component = utils.createDatetime({ viewMode: 'time' });
      expect(utils.isTimeView(component)).toBeTruthy();
    });
      xit('className -> type string', () => {
         const component = utils.createDatetime({ className: 'custom-class' });
         expect(component.find('.custom-class').length).toEqual(1);
      });
    xit('className -> type string', () => {
      const component = utils.createDatetime({ className: 'custom-class' });
      expect(component.find('.custom-class').length).toEqual(1);
    });
      it('className -> type string array', () => {
         const component = utils.createDatetime({ className: ['custom-class1', 'custom-class2'] });
         expect(component.find('.custom-class1').length).toEqual(1);
         expect(component.find('.custom-class2').length).toEqual(1);
      });
    it('className -> type string array', () => {
      const component = utils.createDatetime({
        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.createDatetime({
            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('inputProps', () => {
      const component = utils.createDatetime({
        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.createDatetime({ renderInput });
    it('renderInput', () => {
      const renderInput = (props, openCalendar) => {
        return (
          <div>
            <input {...props} />
            <button className="custom-open" onClick={openCalendar}>
              open calendar
            </button>
          </div>
        );
      };
      const component = utils.createDatetime({ 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();
      });
      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;
    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>;
            };
          return <td {...fnProps}>custom-content</td>;
        };
         const component = utils.createDatetime({ value: mDate, renderDay: renderDayFn });
      const component = utils.createDatetime({
        value: mDate,
        renderDay: renderDayFn
      });
         // Last day should be 6th of february
         expect(currentDate.day()).toEqual(6);
         expect(currentDate.month()).toEqual(1);
      // 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);
      // 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');
      // 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');
      });
      // 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;
    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>;
            };
          return <td {...fnProps}>custom-content</td>;
        };
         const component = utils.createDatetime({ value: mDate, viewMode: 'months', renderMonth: renderMonthFn });
      const component = utils.createDatetime({
        value: mDate,
        viewMode: 'months',
        renderMonth: renderMonthFn
      });
         expect(month).toEqual(11);
         expect(year).toEqual(2000);
      expect(month).toEqual(11);
      expect(year).toEqual(2000);
         // The date must be the same
         expect(selectedDate.isSame(mDate)).toEqual(true);
      // 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');
      // 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');
      });
      // 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;
    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>;
            };
          return <td {...fnProps}>custom-content</td>;
        };
         const component = utils.createDatetime({ value: mDate, viewMode: 'years', renderYear: renderYearFn });
      const component = utils.createDatetime({
        value: mDate,
        viewMode: 'years',
        renderYear: renderYearFn
      });
         expect(year).toEqual(2010);
      expect(year).toEqual(2010);
         // The date must be the same
         expect(selectedDate.isSame(mDate)).toEqual(true);
      // 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');
      // 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');
      });
      // 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.createDatetime({ value: date });
    it('closeOnTab=true', () => {
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        component = utils.createDatetime({ 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();
      });
      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.createDatetime({ value: date, closeOnTab: false });
    it('closeOnTab=false', () => {
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        component = utils.createDatetime({ 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();
      });
      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('increase time', () => {
         let i = 0;
         const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createDatetime({ 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();
                  }
               }});
    it('increase time', () => {
      let i = 0;
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        component = utils.createDatetime({
          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 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 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');
      });
      // 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.createDatetime({ 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();
                  }
               }});
    it('decrease time', () => {
      let i = 0;
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        component = utils.createDatetime({
          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 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 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');
      });
      // 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.createDatetime({ 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.createDatetime({ 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('long increase time', (done) => {
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        component = utils.createDatetime({
          timeFormat: 'HH:mm:ss:SSS',
          viewMode: 'time',
          defaultValue: date
        });
      it('timeConstraints -> increase time', () => {
         let i = 0;
         const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createDatetime({ 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);
      setTimeout(() => {
        expect(utils.getHours(component)).not.toEqual('2');
        expect(utils.getHours(component)).not.toEqual('3');
        done();
      }, 920);
    });
         utils.increaseHour(component);
         expect(utils.getHours(component)).toEqual('3');
    it('long decrease time', (done) => {
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        component = utils.createDatetime({
          timeFormat: 'HH:mm:ss:SSS',
          viewMode: 'time',
          defaultValue: date
        });
         utils.increaseMinute(component);
         expect(utils.getMinutes(component)).toEqual('17');
      utils.decreaseHour(component);
      setTimeout(() => {
        expect(utils.getHours(component)).not.toEqual('1');
        expect(utils.getHours(component)).not.toEqual('0');
        done();
      }, 920);
    });
         utils.increaseSecond(component);
         expect(utils.getSeconds(component)).toEqual('03');
      });
    it('timeConstraints -> increase time', () => {
      let i = 0;
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        component = utils.createDatetime({
          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();
            }
          }
        });
      it('timeConstraints -> decrease time', () => {
         let i = 0;
         const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createDatetime({ 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.increaseHour(component);
      expect(utils.getHours(component)).toEqual('3');
         utils.decreaseMinute(component);
         expect(utils.getMinutes(component)).toEqual('47');
      });
      utils.increaseMinute(component);
      expect(utils.getMinutes(component)).toEqual('17');
      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.createDatetime({ defaultValue: '', strictParsing: true,
               onChange: (updated) => {
                  expect(updated, invalidStrDate);
                  done();
               }});
      utils.increaseSecond(component);
      expect(utils.getSeconds(component)).toEqual('03');
    });
         component.find('.form-control').simulate('change', { target: { value: invalidStrDate }});
      });
    it('timeConstraints -> decrease time', () => {
      let i = 0;
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        component = utils.createDatetime({
          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();
            }
          }
        });
      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.createDatetime({ defaultValue: '', strictParsing: false,
               onChange: (updated) => {
                  expect(mDate.format('L LT')).toEqual(updated.format('L LT'));
                  done();
               }});
      utils.decreaseMinute(component);
      expect(utils.getMinutes(component)).toEqual('47');
    });
         component.find('.form-control').simulate('change', { target: { value: invalidStrDate }});
      });
    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.createDatetime({
          defaultValue: '',
          strictParsing: true,
          onChange: (updated) => {
            expect(updated, invalidStrDate);
            done();
          }
        });
      it('isValidDate -> disable months', () => {
         const dateBefore = new Date().getFullYear() + '-06-01',
            component = utils.createDatetime({ viewMode: 'months', isValidDate: (current) =>
               current.isBefore(moment(dateBefore, 'YYYY-MM-DD'))
            });
      component
        .find('.form-control')
        .simulate('change', { target: { value: invalidStrDate } });
    });
         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('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.createDatetime({
          defaultValue: '',
          strictParsing: false,
          onChange: (updated) => {
            expect(mDate.format('L LT')).toEqual(updated.format('L LT'));
            done();
          }
        });
      it('isValidDate -> disable years', () => {
         const component = utils.createDatetime({ viewMode: 'years', isValidDate: (current) =>
            current.isBefore(moment('2016-01-01', 'YYYY-MM-DD'))
         });
      component
        .find('.form-control')
        .simulate('change', { target: { value: invalidStrDate } });
    });
         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('isValidDate -> disable months', () => {
      const dateBefore = new Date().getFullYear() + '-06-01',
        component = utils.createDatetime({
          viewMode: 'months',
          isValidDate: (current) =>
            current.isBefore(moment(dateBefore, 'YYYY-MM-DD'))
        });
      it('locale', () => {
         const component = utils.createDatetime({ locale: 'nl' }),
            expectedWeekDays = ['ma', 'di', 'wo', 'do', 'vr', 'za', 'zo'],
            actualWeekDays = component.find('.rdtDays .dow').map((element) =>
               element.text().toLowerCase()
            );
      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
      );
    });
         expect(actualWeekDays).toEqual(expectedWeekDays);
      });
    it('isValidDate -> disable years', () => {
      const component = utils.createDatetime({
        viewMode: 'years',
        isValidDate: (current) =>
          current.isBefore(moment('2016-01-01', 'YYYY-MM-DD'))
      });
      it('locale with viewMode=months', () => {
         const component = utils.createDatetime({ locale: 'nl', viewMode: 'months' }),
            expectedMonths = ['Mrt', 'Mei'],
            actualMonths = [utils.getNthMonth(component, 2).text(), utils.getNthMonth(component, 4).text()];
      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
      );
    });
         expect(actualMonths).toEqual(expectedMonths);
      });
    it('locale', () => {
      const component = utils.createDatetime({ locale: 'nl' }),
        expectedWeekDays = ['ma', 'di', 'wo', 'do', 'vr', 'za', 'zo'],
        actualWeekDays = component
          .find('.rdtDays .dow')
          .map((element) => element.text().toLowerCase());
      it('closeOnSelect=false', (done) => {
         const component = utils.createDatetime({ closeOnSelect: false });
      expect(actualWeekDays).toEqual(expectedWeekDays);
    });
         // 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('locale with viewMode=months', () => {
      const component = utils.createDatetime({
          locale: 'nl',
          viewMode: 'months'
        }),
        expectedMonths = ['Mrt', 'Mei'],
        actualMonths = [
          utils.getNthMonth(component, 2).text(),
          utils.getNthMonth(component, 4).text()
        ];
      it('closeOnSelect=true', (done) => {
         const component = utils.createDatetime({ closeOnSelect: true });
      expect(actualMonths).toEqual(expectedMonths);
    });
         // 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);
      });
    it('closeOnSelect=false', (done) => {
      const component = utils.createDatetime({ closeOnSelect: false });
      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.createDatetime({ defaultValue: date });
            expect(utils.getInputValue(component)).toEqual(strDate);
         });
      // 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('moment', () => {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
               momentDate = moment(date),
               strDate = momentDate.format('L') + ' ' + momentDate.format('LT'),
               component = utils.createDatetime({ defaultValue: momentDate });
            expect(utils.getInputValue(component)).toEqual(strDate);
         });
    it('closeOnSelect=true', (done) => {
      const component = utils.createDatetime({ closeOnSelect: true });
         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.createDatetime({ defaultValue: strDate });
            expect(utils.getInputValue(component)).toEqual(strDate);
         });
      });
      // 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('timeFormat with', () => {
         it('milliseconds', () => {
            const component = utils.createDatetime({ 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
         });
    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.createDatetime({ defaultValue: date });
        expect(utils.getInputValue(component)).toEqual(strDate);
      });
         it('seconds', () => {
            const component = utils.createDatetime({ viewMode: 'time', timeFormat: 'HH:mm:ss' });
            expect(component.find('.rdtCounter').length).toEqual(3);
         });
      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.createDatetime({ defaultValue: momentDate });
        expect(utils.getInputValue(component)).toEqual(strDate);
      });
         it('minutes', () => {
            const component = utils.createDatetime({ viewMode: 'time', timeFormat: 'HH:mm' });
            expect(component.find('.rdtCounter').length).toEqual(2);
         });
      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.createDatetime({ defaultValue: strDate });
        expect(utils.getInputValue(component)).toEqual(strDate);
      });
    });
         it('hours', () => {
            const component = utils.createDatetime({ viewMode: 'time', timeFormat: 'HH' });
            expect(component.find('.rdtCounter').length).toEqual(1);
         });
      });
    describe('timeFormat with', () => {
      it('milliseconds', () => {
        const component = utils.createDatetime({
          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
      });
      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.createDatetime({
                  dateFormat: 'YYYY-MM-DD', timeFormat: false, defaultValue: date
               });
      it('seconds', () => {
        const component = utils.createDatetime({
          viewMode: 'time',
          timeFormat: 'HH:mm:ss'
        });
        expect(component.find('.rdtCounter').length).toEqual(3);
      });
            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);
      it('minutes', () => {
        const component = utils.createDatetime({
          viewMode: 'time',
          timeFormat: 'HH:mm'
        });
        expect(component.find('.rdtCounter').length).toEqual(2);
      });
               expect(valueBefore).not.toEqual(valueAfter);
               done();
            }, 0);
         });
      it('hours', () => {
        const component = utils.createDatetime({
          viewMode: 'time',
          timeFormat: 'HH'
        });
        expect(component.find('.rdtCounter').length).toEqual(1);
      });
    });
         it('UTC -> value should change format (true->false)', () => {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
               momentDate = moment(date),
               component = utils.createDatetime({ value: momentDate, utc: true });
    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.createDatetime({
            dateFormat: 'YYYY-MM-DD',
            timeFormat: false,
            defaultValue: date
          });
            const valueBefore = utils.getInputValue(component);
            component.setProps({ utc: false }, () => {
               const valueAfter = utils.getInputValue(component);
        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);
            });
         });
          expect(valueBefore).not.toEqual(valueAfter);
          done();
        }, 0);
      });
         it('UTC -> value should change format (false->true)', () => {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
               momentDate = moment(date),
               component = utils.createDatetime({ value: momentDate, utc: false });
      it('UTC -> value should change format (true->false)', () => {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
          momentDate = moment(date),
          component = utils.createDatetime({ value: momentDate, utc: true });
            const valueBefore = utils.getInputValue(component);
            component.setProps({ utc: true }, () => {
               const valueAfter = utils.getInputValue(component);
        const valueBefore = utils.getInputValue(component);
        component.setProps({ utc: false }, () => {
          const valueAfter = utils.getInputValue(component);
               expect(valueBefore).not.toEqual(valueAfter);
            });
         });
          expect(valueBefore).not.toEqual(valueAfter);
        });
      });
         it('locale -> picker should change language (viewMode=days)', () => {
            const component = utils.createDatetime({ viewMode: 'days', locale: 'nl' }),
               weekdaysBefore = component.find('.rdtDays .dow').map((element) =>
                  element.text()
               );
      it('UTC -> value should change format (false->true)', () => {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
          momentDate = moment(date),
          component = utils.createDatetime({ value: momentDate, utc: false });
            component.setProps({ locale: 'sv' });
            const weekdaysAfter = component.find('.rdtDays .dow').map((element) =>
               element.text()
            );
        const valueBefore = utils.getInputValue(component);
        component.setProps({ utc: true }, () => {
          const valueAfter = utils.getInputValue(component);
            expect(weekdaysBefore).not.toEqual(weekdaysAfter);
         });
          expect(valueBefore).not.toEqual(valueAfter);
        });
      });
         it('locale -> picker should change language (viewMode=months)', () => {
            const component = utils.createDatetime({ viewMode: 'months', locale: 'nl' }),
               monthsBefore = [utils.getNthMonth(component, 2).text(), utils.getNthMonth(component, 4).text()];
      it('locale -> picker should change language (viewMode=days)', () => {
        const component = utils.createDatetime({
            viewMode: 'days',
            locale: 'nl'
          }),
          weekdaysBefore = component
            .find('.rdtDays .dow')
            .map((element) => element.text());
            component.setProps({ locale: 'sv' });
            const monthsAfter = [utils.getNthMonth(component, 2).text(), utils.getNthMonth(component, 4).text()];
        component.setProps({ locale: 'sv' });
        const weekdaysAfter = component
          .find('.rdtDays .dow')
          .map((element) => element.text());
            expect(monthsBefore).not.toEqual(monthsAfter);
         });
      });
   });
        expect(weekdaysBefore).not.toEqual(weekdaysAfter);
      });
   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.createDatetime({ value: date, onBlur: onBlurFn, closeOnSelect: true });
      it('locale -> picker should change language (viewMode=months)', () => {
        const component = utils.createDatetime({
            viewMode: 'months',
            locale: 'nl'
          }),
          monthsBefore = [
            utils.getNthMonth(component, 2).text(),
            utils.getNthMonth(component, 4).text()
          ];
            utils.openDatepicker(component);
            // Close component by selecting a date
            utils.clickNthDay(component, 2);
            expect(onBlurFn).toHaveBeenCalledTimes(1);
         });
        component.setProps({ locale: 'sv' });
        const monthsAfter = [
          utils.getNthMonth(component, 2).text(),
          utils.getNthMonth(component, 4).text()
        ];
         it('when selecting date (value=null and closeOnSelect=true)', () => {
            const onBlurFn = jest.fn(),
               component = utils.createDatetime({ value: null, onBlur: onBlurFn, closeOnSelect: true });
        expect(monthsBefore).not.toEqual(monthsAfter);
      });
    });
  });
            utils.openDatepicker(component);
            // Close component by selecting a date
            utils.clickNthDay(component, 2);
            expect(onBlurFn).toHaveBeenCalledTimes(1);
         });
  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.createDatetime({
            value: date,
            onBlur: onBlurFn,
            closeOnSelect: true
          });
         it('when selecting date (value=null and closeOnSelect=false)', () => {
            const onBlurFn = jest.fn(),
               component = utils.createDatetime({ value: null, onBlur: onBlurFn, closeOnSelect: false });
        utils.openDatepicker(component);
        // Close component by selecting a date
        utils.clickNthDay(component, 2);
        expect(onBlurFn).toHaveBeenCalledTimes(1);
      });
            utils.openDatepicker(component);
            // Close component by selecting a date
            utils.clickNthDay(component, 2);
            expect(onBlurFn).not.toHaveBeenCalled();
         });
      });
      it('when selecting date (value=null and closeOnSelect=true)', () => {
        const onBlurFn = jest.fn(),
          component = utils.createDatetime({
            value: null,
            onBlur: onBlurFn,
            closeOnSelect: true
          });
      it('onFocus when opening datepicker', () => {
         const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            onFocusFn = jest.fn(),
            component = utils.createDatetime({ value: date, onFocus: onFocusFn });
        utils.openDatepicker(component);
        // Close component by selecting a date
        utils.clickNthDay(component, 2);
        expect(onBlurFn).toHaveBeenCalledTimes(1);
      });
         utils.openDatepicker(component);
         expect(onFocusFn).toHaveBeenCalledTimes(1);
      });
      it('when selecting date (value=null and closeOnSelect=false)', () => {
        const onBlurFn = jest.fn(),
          component = utils.createDatetime({
            value: null,
            onBlur: onBlurFn,
            closeOnSelect: false
          });
      describe('onViewModeChange', () => {
         it('when switch from days to time view mode', () => {
            const component = utils.createDatetime({ onViewModeChange: (viewMode) => {
               expect(viewMode).toEqual('time');
            }});
            expect(utils.isDayView(component)).toBeTruthy();
            utils.clickOnElement(component.find('.rdtTimeToggle'));
            expect(utils.isTimeView(component)).toBeTruthy();
         });
        utils.openDatepicker(component);
        // Close component by selecting a date
        utils.clickNthDay(component, 2);
        expect(onBlurFn).not.toHaveBeenCalled();
      });
    });
         it('when switch from time to days view mode', () => {
            const component = utils.createDatetime({ viewMode: 'time', onViewModeChange: (viewMode) => {
               expect(viewMode).toEqual('days');
            }});
            expect(utils.isTimeView(component)).toBeTruthy();
            utils.clickOnElement(component.find('.rdtSwitch'));
            expect(utils.isDayView(component)).toBeTruthy();
         });
    it('onFocus when opening datepicker', () => {
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        onFocusFn = jest.fn(),
        component = utils.createDatetime({ value: date, onFocus: onFocusFn });
         it('when switch from days to months view mode', () => {
            const component = utils.createDatetime({ onViewModeChange: (viewMode) => {
               expect(viewMode).toEqual('months');
            }});
            expect(utils.isDayView(component)).toBeTruthy();
            utils.clickOnElement(component.find('.rdtSwitch'));
            expect(utils.isMonthView(component)).toBeTruthy();
         });
      utils.openDatepicker(component);
      expect(onFocusFn).toHaveBeenCalledTimes(1);
    });
         it('when switch from months to years view mode', () => {
            const component = utils.createDatetime({ viewMode: 'months', onViewModeChange: (viewMode) => {
               expect(viewMode).toEqual('years');
            }});
            expect(utils.isMonthView(component)).toBeTruthy();
            utils.clickOnElement(component.find('.rdtSwitch'));
            expect(utils.isYearView(component)).toBeTruthy();
         });
    describe('onViewModeChange', () => {
      it('when switch from days to time view mode', () => {
        const component = utils.createDatetime({
          onViewModeChange: (viewMode) => {
            expect(viewMode).toEqual('time');
          }
        });
        expect(utils.isDayView(component)).toBeTruthy();
        utils.clickOnElement(component.find('.rdtTimeToggle'));
        expect(utils.isTimeView(component)).toBeTruthy();
      });
         it('only when switch from years to months view mode', () => {
            const component = utils.createDatetime({ 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 time to days view mode', () => {
        const component = utils.createDatetime({
          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 months to days view mode', () => {
            const component = utils.createDatetime({ viewMode: 'months', onViewModeChange: (viewMode) => {
               expect(viewMode).toEqual('days');
            }});
            expect(utils.isMonthView(component)).toBeTruthy();
            utils.clickNthMonth(component, 2);
            expect(utils.isDayView(component)).toBeTruthy();
         });
      });
      it('when switch from days to months view mode', () => {
        const component = utils.createDatetime({
          onViewModeChange: (viewMode) => {
            expect(viewMode).toEqual('months');
          }
        });
        expect(utils.isDayView(component)).toBeTruthy();
        utils.clickOnElement(component.find('.rdtSwitch'));
        expect(utils.isMonthView(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.createDatetime({ viewMode: 'years', onChange: onChangeFn });
      it('when switch from months to years view mode', () => {
        const component = utils.createDatetime({
          viewMode: 'months',
          onViewModeChange: (viewMode) => {
            expect(viewMode).toEqual('years');
          }
        });
        expect(utils.isMonthView(component)).toBeTruthy();
        utils.clickOnElement(component.find('.rdtSwitch'));
        expect(utils.isYearView(component)).toBeTruthy();
      });
            utils.openDatepicker(component);
      it('only when switch from years to months view mode', () => {
        const component = utils.createDatetime({
          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();
      });
            utils.clickNthYear(component, 2);
            expect(onChangeFn).not.toHaveBeenCalled();
      it('when switch from months to days view mode', () => {
        const component = utils.createDatetime({
          viewMode: 'months',
          onViewModeChange: (viewMode) => {
            expect(viewMode).toEqual('days');
          }
        });
        expect(utils.isMonthView(component)).toBeTruthy();
        utils.clickNthMonth(component, 2);
        expect(utils.isDayView(component)).toBeTruthy();
      });
    });
            utils.clickNthMonth(component, 2);
            expect(onChangeFn).not.toHaveBeenCalled();
    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.createDatetime({
            viewMode: 'years',
            onChange: onChangeFn
          });
            utils.clickNthDay(component, 2);
            expect(onChangeFn).toHaveBeenCalled();
         });
        utils.openDatepicker(component);
         it('when selecting date', (done) => {
            const date = new Date(2000, 0, 15, 2, 2, 2, 2),
               mDate = moment(date),
               component = utils.createDatetime({ defaultValue: date, onChange: (selected) => {
                  expect(selected.date()).toEqual(2);
                  expect(selected.month()).toEqual(mDate.month());
                  expect(selected.year()).toEqual(mDate.year());
                  done();
               }});
        utils.clickNthYear(component, 2);
        expect(onChangeFn).not.toHaveBeenCalled();
            utils.clickNthDay(component, 7);
         });
        utils.clickNthMonth(component, 2);
        expect(onChangeFn).not.toHaveBeenCalled();
         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.createDatetime({ 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, 2);
        expect(onChangeFn).toHaveBeenCalled();
      });
            utils.clickNthDay(component, 7);
            utils.clickNthDay(component, 8);
            utils.clickNthDay(component, 9);
         });
      it('when selecting date', (done) => {
        const date = new Date(2000, 0, 15, 2, 2, 2, 2),
          mDate = moment(date),
          component = utils.createDatetime({
            defaultValue: date,
            onChange: (selected) => {
              expect(selected.date()).toEqual(2);
              expect(selected.month()).toEqual(mDate.month());
              expect(selected.year()).toEqual(mDate.year());
              done();
            }
          });
         it('when selecting month', () => {
            const date = Date.UTC(2000, 0, 15, 2, 2, 2, 2),
               onChangeFn = jest.fn(),
               component = utils.createDatetime({ defaultValue: date, dateFormat: 'YYYY-MM', onChange: onChangeFn });
        utils.clickNthDay(component, 7);
      });
            utils.clickNthMonth(component, 2);
            expect(onChangeFn).toHaveBeenCalledTimes(1);
            expect(onChangeFn.mock.calls[0][0].toJSON()).toEqual('2000-03-15T02:02:02.002Z');
         });
      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.createDatetime({
            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();
              }
            }
          });
         xit('when selecting year', () => {
            const date = Date.UTC(2000, 0, 15, 2, 2, 2, 2),
               onChangeFn = jest.fn(),
               component = utils.createDatetime({ defaultValue: date, dateFormat: 'YYYY', onChange: onChangeFn });
        utils.clickNthDay(component, 7);
        utils.clickNthDay(component, 8);
        utils.clickNthDay(component, 9);
      });
            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 month', () => {
        const date = Date.UTC(2000, 0, 15, 2, 2, 2, 2),
          onChangeFn = jest.fn(),
          component = utils.createDatetime({
            defaultValue: date,
            dateFormat: 'YYYY-MM',
            onChange: onChangeFn
          });
         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);
         });
        utils.clickNthMonth(component, 2);
        expect(onChangeFn).toHaveBeenCalledTimes(1);
        expect(onChangeFn.mock.calls[0][0].toJSON()).toEqual(
          '2000-03-15T02:02:02.002Z'
        );
      });
      });
      xit('when selecting year', () => {
        const date = Date.UTC(2000, 0, 15, 2, 2, 2, 2),
          onChangeFn = jest.fn(),
          component = utils.createDatetime({
            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'
        );
      });
   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.createDatetime({ value: date });
         expect(utils.getInputValue(component)).toEqual(strDate);
      });
      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);
      });
    });
  });
      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.createDatetime({ value: mDate });
         expect(utils.getInputValue(component)).toEqual(strDate);
      });
  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.createDatetime({ value: date });
      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.createDatetime({ value: strDate });
         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.createDatetime({ value: mDate });
      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.createDatetime({ value: momentDate, utc: true });
         expect(utils.getInputValue(component)).toEqual(strDateUTC);
      });
    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.createDatetime({ value: strDate });
      expect(utils.getInputValue(component)).toEqual(strDate);
    });
      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.createDatetime({ value: momentDateUTC, utc: true });
         expect(utils.getInputValue(component)).toEqual(strDateUTC);
      });
    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.createDatetime({ value: momentDate, 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.createDatetime({ value: strDateUTC, 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.createDatetime({ value: momentDateUTC, utc: true });
      expect(utils.getInputValue(component)).toEqual(strDateUTC);
    });
      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.createDatetime({ defaultValue: 'invalid-value', onChange: (updated) => {
               expect(mDate.format('L LT')).toEqual(updated.format('L LT'));
               done();
            }});
    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.createDatetime({ value: strDateUTC, utc: true });
      expect(utils.getInputValue(component)).toEqual(strDateUTC);
    });
         expect(component.find('.form-control').getDOMNode().value).toEqual('invalid-value');
         component.find('.form-control').simulate('change', { target: { value: strDate }});
      });
    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.createDatetime({
          defaultValue: 'invalid-value',
          onChange: (updated) => {
            expect(mDate.format('L LT')).toEqual(updated.format('L LT'));
            done();
          }
        });
      it('delete invalid string value', (done) => {
         const date = new Date(2000, 0, 15, 2, 2, 2, 2),
            component = utils.createDatetime({ defaultValue: date, onChange: (date) => {
               expect(date).toEqual('');
               done();
            }});
      expect(component.find('.form-control').getDOMNode().value).toEqual(
        'invalid-value'
      );
      component
        .find('.form-control')
        .simulate('change', { target: { value: strDate } });
    });
         component.find('.form-control').simulate('change', { target: { value: '' }});
      });
    it('delete invalid string value', (done) => {
      const date = new Date(2000, 0, 15, 2, 2, 2, 2),
        component = utils.createDatetime({
          defaultValue: date,
          onChange: (date) => {
            expect(date).toEqual('');
            done();
          }
        });
      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.createDatetime({ value: invalidValue, onChange: (updated) => {
               expect(mDate.format('L LT')).toEqual(updated.format('L LT'));
               done();
            }});
      component
        .find('.form-control')
        .simulate('change', { target: { value: '' } });
    });
         expect(component.find('.form-control').getDOMNode().value).toEqual('');
         component.find('.form-control').simulate('change', { target: { value: strDate }});
      });
    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.createDatetime({
          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 } });
    });
  });
});