import React from 'react'; import { mount } from 'enzyme'; import Calendar from '../Calendar'; import { getBeginOfMonth } from '../shared/dates'; /* eslint-disable comma-dangle */ const { format } = new Intl.DateTimeFormat('en-US', { day: 'numeric', month: 'long', year: 'numeric' }); describe('Calendar', () => { it('renders navigation', () => { const component = mount( ); const navigation = component.find('.react-calendar__navigation'); expect(navigation).toHaveLength(1); }); it('does not render navigation when showNavigation flag is set to false', () => { const component = mount( ); const navigation = component.find('.react-calendar__navigation'); expect(navigation).toHaveLength(0); }); it('renders month view by default', () => { const component = mount( ); const monthView = component.find('.react-calendar__month-view'); expect(monthView).toHaveLength(1); }); it('renders maximum allowed view when given maxDetail', () => { const component = mount( ); const yearView = component.find('.react-calendar__year-view'); expect(yearView).toHaveLength(1); }); it('renders maximum allowed view when given view that is not allowed', () => { const component = mount( ); const yearView = component.find('.react-calendar__year-view'); expect(yearView).toHaveLength(1); }); it('renders maximum allowed view when attempting to externally switch to a view that is not allowed', () => { const component = mount( ); component.setProps({ view: 'month' }); component.update(); const yearView = component.find('.react-calendar__year-view'); expect(yearView).toHaveLength(1); }); it('renders maximum allowed view when given changed maxDetail', () => { const component = mount( ); component.setProps({ maxDetail: 'year' }); component.update(); const yearView = component.find('.react-calendar__year-view'); expect(yearView).toHaveLength(1); }); it('renders month view when given view = "month"', () => { const component = mount( ); const monthView = component.find('.react-calendar__month-view'); expect(monthView).toHaveLength(1); }); it('renders month view with week numbers when given view = "month" and showWeekNumbers flag set to true', () => { const component = mount( ); const monthView = component.find('.react-calendar__month-view--weekNumbers'); expect(monthView).toHaveLength(1); }); it('renders year view when given view = "year"', () => { const component = mount( ); const yearView = component.find('.react-calendar__year-view'); expect(yearView).toHaveLength(1); }); it('renders decade view when given view = "decade"', () => { const component = mount( ); const decadeView = component.find('.react-calendar__decade-view'); expect(decadeView).toHaveLength(1); }); it('renders century view when given view = "century"', () => { const component = mount( ); const centuryView = component.find('.react-calendar__century-view'); expect(centuryView).toHaveLength(1); }); it('displays a view with a given value when value is given', () => { const value = new Date(2017, 0, 1); const component = mount( ); const monthView = component.find('.react-calendar__month-view'); const firstDayTile = monthView.find('.react-calendar__tile').first(); const firstDayTileTimeAbbr = firstDayTile.find('abbr').prop('aria-label'); expect(firstDayTileTimeAbbr).toBe(format(value)); }); it('displays a view with activeStartDate when no value is given and activeStartDate is given', () => { const activeStartDate = new Date(2017, 0, 1); const component = mount( ); const monthView = component.find('.react-calendar__month-view'); const firstDayTile = monthView.find('.react-calendar__tile').first(); const firstDayTileTimeAbbr = firstDayTile.find('abbr').prop('aria-label'); expect(firstDayTileTimeAbbr).toBe(format(activeStartDate)); }); it('displays a view with today\'s date when no value and no activeStartDate is given', () => { const today = new Date(); const beginOfCurrentMonth = getBeginOfMonth(today); const component = mount( ); const monthView = component.find('.react-calendar__month-view'); const firstDayTile = monthView.find('.react-calendar__tile').first(); const firstDayTileTimeAbbr = firstDayTile.find('abbr').prop('aria-label'); expect(firstDayTileTimeAbbr).toBe(format(beginOfCurrentMonth)); }); it('drills up when allowed', () => { const component = mount( ); component.instance().drillUp(); expect(component.state().view).toBe('year'); }); it('calls onDrillUp on drill up', () => { const onDrillUp = jest.fn(); const component = mount( ); component.instance().drillUp(); expect(onDrillUp).toHaveBeenCalledWith({ activeStartDate: new Date(2017, 0, 1), view: 'year', }); }); it('refuses to drill up when already on minimum allowed detail', () => { const onDrillUp = jest.fn(); const component = mount( ); component.instance().drillUp(); expect(onDrillUp).not.toHaveBeenCalled(); }); it('drills down when allowed', () => { const component = mount( ); component.instance().drillDown(new Date(2011, 0, 1)); expect(component.state().view).toBe('decade'); }); it('calls onDrillDown on drill down', () => { const onDrillDown = jest.fn(); const component = mount( ); component.instance().drillDown(new Date(2011, 0, 1)); expect(onDrillDown).toHaveBeenCalledWith({ activeStartDate: new Date(2011, 0, 1), view: 'decade', }); }); it('refuses to drill down when already on minimum allowed detail', () => { const onDrillDown = jest.fn(); const component = mount( ); component.instance().drillUp(); expect(onDrillDown).not.toHaveBeenCalled(); }); it('calls onChange function returning the beginning of selected period by default', () => { const onChange = jest.fn(); const component = mount( ); component.instance().onChange(new Date(2017, 0, 1)); expect(onChange).toHaveBeenCalledWith(new Date(2017, 0, 1)); }); it('calls onChange function returning the beginning of the selected period when returnValue is set to "start"', () => { const onChange = jest.fn(); const component = mount( ); component.instance().onChange(new Date(2017, 0, 1)); expect(onChange).toHaveBeenCalledWith(new Date(2017, 0, 1)); }); it('calls onChange function returning the beginning of the selected period when returnValue is set to "start"', () => { const onChange = jest.fn(); const component = mount( ); component.instance().onChange(new Date(2017, 0, 1)); expect(onChange).toHaveBeenCalledWith(new Date(2017, 0, 1)); }); it('calls onChange function returning the end of the selected period when returnValue is set to "end"', () => { const onChange = jest.fn(); const component = mount( ); component.instance().onChange(new Date(2017, 0, 1)); expect(onChange).toHaveBeenCalledWith(new Date(2017, 0, 1, 23, 59, 59, 999)); }); it('calls onChange function returning the beginning of selected period when returnValue is set to "range"', () => { const onChange = jest.fn(); const component = mount( ); component.instance().onChange(new Date(2017, 0, 1)); expect(onChange).toHaveBeenCalledWith([ new Date(2017, 0, 1), new Date(2017, 0, 1, 23, 59, 59, 999), ]); }); it('calls onChange function returning the beginning of selected period, but no earlier than minDate', () => { const onChange = jest.fn(); const component = mount( ); component.instance().onChange(new Date(2017, 0, 1)); expect(onChange).toHaveBeenCalledWith(new Date(2017, 0, 1, 12)); }); it('calls onChange function returning the beginning of selected period, but no later than maxDate', () => { const onChange = jest.fn(); const component = mount( ); component.instance().onChange(new Date(2017, 0, 2)); expect(onChange).toHaveBeenCalledWith(new Date(2017, 0, 1, 12)); }); it('calls onChange function returning the end of selected period, but no earlier than minDate', () => { const onChange = jest.fn(); const component = mount( ); component.instance().onChange(new Date(2017, 0, 1)); expect(onChange).toHaveBeenCalledWith(new Date(2017, 0, 2, 12)); }); it('calls onChange function returning the end of selected period, but no later than maxDate', () => { const onChange = jest.fn(); const component = mount( ); component.instance().onChange(new Date(2017, 0, 2)); expect(onChange).toHaveBeenCalledWith(new Date(2017, 0, 1, 12)); }); it('calls onChange function returning a range when selected two pieces of a range', () => { const onChange = jest.fn(); const component = mount( ); component.instance().onChange(new Date(2018, 0, 1)); component.instance().onChange(new Date(2018, 6, 1)); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith([ new Date(2018, 0, 1), new Date(2018, 6, 1, 23, 59, 59, 999), ]); }); it('calls onChange function returning a range when selected reversed two pieces of a range', () => { const onChange = jest.fn(); const component = mount( ); component.instance().onChange(new Date(2018, 6, 1)); component.instance().onChange(new Date(2018, 0, 1)); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith([ new Date(2018, 0, 1), new Date(2018, 6, 1, 23, 59, 59, 999), ]); }); it('calls onActiveDateChange on activeStartDate change', () => { const activeStartDate = new Date(2017, 0, 1); const newActiveStartDate = new Date(2018, 0, 1); const onActiveDateChange = jest.fn(); const component = mount( ); component.instance().setActiveStartDate(newActiveStartDate); expect(onActiveDateChange).toHaveBeenCalledWith({ activeStartDate: newActiveStartDate, view: 'year', }); }); it('changes Calendar view given new activeStartDate value', () => { const activeStartDate = new Date(2017, 0, 1); const newActiveStartDate = new Date(2018, 0, 1); const component = mount( ); component.setProps({ activeStartDate: newActiveStartDate }); const monthView = component.find('.react-calendar__month-view'); const firstDayTile = monthView.find('.react-calendar__tile').first(); const firstDayTileTimeAbbr = firstDayTile.find('abbr').prop('aria-label'); expect(firstDayTileTimeAbbr).toBe(format(newActiveStartDate)); }); it('displays calendar with custom weekdays formatting', () => { const component = mount( 'Weekday'} /> ); const monthView = component.find('.react-calendar__month-view'); const firstWeekdayTile = monthView.find('.react-calendar__month-view__weekdays__weekday').first(); expect(firstWeekdayTile.text()).toBe('Weekday'); }); it('displays calendar with custom month year navigation label', () => { const component = mount( 'MonthYear'} /> ); const navigationLabel = component.find('.react-calendar__navigation__label').first(); expect(navigationLabel.text()).toBe('MonthYear'); }); });