import React from 'react'; import { waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import renderWithTheme from '../../../testUtils/renderWithTheme'; import DateRangePicker from '../DateRangePicker'; describe('rendering', () => { it('renders two inputs and calendar', async () => { const { getByDisplayValue, getAllByText, getByTestId } = renderWithTheme( ); await waitFor(() => { expect(getByDisplayValue('02/05/2021')).toBeInTheDocument(); expect(getByDisplayValue('10/05/2021')).toBeInTheDocument(); }); userEvent.click(getByDisplayValue('02/05/2021')); await waitFor(() => { const firstMonthSelect = getByTestId('first-month-select'); const firstYearSelect = getByTestId('first-year-select'); const secondMonthSelect = getByTestId('second-month-select'); const secondYearSelect = getByTestId('second-year-select'); expect(firstMonthSelect).toSelectItem('May'); expect(firstYearSelect).toSelectItem('2021'); expect(secondMonthSelect).toSelectItem('Jun'); expect(secondYearSelect).toSelectItem('2021'); expect(getAllByText('10').length).toBe(3); }); }); it('renders two inputs with correct format', async () => { const { getByDisplayValue } = renderWithTheme( ); await waitFor(() => { expect(getByDisplayValue('2021/05/02')).toBeInTheDocument(); expect(getByDisplayValue('2021/05/10')).toBeInTheDocument(); }); }); }); describe('interaction', () => { it('allows to blur', async () => { const onBlur = jest.fn(); const { getByPlaceholderText } = renderWithTheme( ); userEvent.click(getByPlaceholderText('Start')); userEvent.click(document.body); expect(onBlur).toHaveBeenCalledTimes(1); }); it('allows to pick start date and then end date', async () => { const onChange = jest.fn(); const { getByPlaceholderText, getAllByText, queryByText } = renderWithTheme( ); userEvent.click(getByPlaceholderText('Start')); await waitFor(() => { // Calendar is open expect(getAllByText('Su')[0]).toBeVisible(); }); userEvent.click(getAllByText('9')[0]); await waitFor(() => { expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith({ startDate: '09/05/2021', endDate: '10/05/2021', }); // Calendar is still open expect(getAllByText('Su')[1]).toBeVisible(); }); userEvent.click(getAllByText('15')[0]); await waitFor(() => { expect(onChange).toHaveBeenCalledTimes(2); expect(onChange).toHaveBeenCalledWith({ startDate: '02/05/2021', endDate: '15/05/2021', }); // Calendar is closed expect(queryByText('Su')).not.toBeInTheDocument(); }); }); it('allows to pick end date and then start date', async () => { const onChange = jest.fn(); const { getByPlaceholderText, getAllByText, queryByText } = renderWithTheme( ); userEvent.click(getByPlaceholderText('End')); await waitFor(() => { // Calendar is open expect(getAllByText('Su')[0]).toBeVisible(); }); userEvent.click(getAllByText('9')[0]); await waitFor(() => { expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith({ startDate: '02/05/2021', endDate: '09/05/2021', }); // Calendar is still open expect(getAllByText('Su')[1]).toBeVisible(); }); userEvent.click(getAllByText('8')[0]); await waitFor(() => { expect(onChange).toHaveBeenCalledTimes(2); expect(onChange).toHaveBeenCalledWith({ startDate: '08/05/2021', endDate: '10/05/2021', }); // Calendar is closed expect(queryByText('Su')).not.toBeInTheDocument(); }); }); it('resets end date when new start date is after end date', async () => { const onChange = jest.fn(); const { getByPlaceholderText, getAllByText } = renderWithTheme( ); userEvent.click(getByPlaceholderText('Start')); await waitFor(() => { // Calendar is open expect(getAllByText('Su')[0]).toBeVisible(); }); userEvent.click(getAllByText('12')[0]); await waitFor(() => { expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith({ startDate: '12/05/2021', endDate: undefined, }); // Calendar is still open expect(getAllByText('Su')[1]).toBeVisible(); }); }); it('resets start date when new end date is before start date', async () => { const onChange = jest.fn(); const { getByPlaceholderText, getAllByText } = renderWithTheme( ); userEvent.click(getByPlaceholderText('End')); await waitFor(() => { // Calendar is open expect(getAllByText('Su')[0]).toBeVisible(); }); userEvent.click(getAllByText('1')[0]); await waitFor(() => { expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith({ startDate: undefined, endDate: '01/05/2021', }); // Calendar is still open expect(getAllByText('Su')[1]).toBeVisible(); }); }); it('does not allow to pick a date out of range', async () => { const onChange = jest.fn(); const { getByPlaceholderText, getAllByText } = renderWithTheme( ); userEvent.click(getByPlaceholderText('Start')); await waitFor(() => { // Calendar is open expect(getAllByText('Su')[0]).toBeVisible(); }); await waitFor(() => { expect(() => userEvent.click(getAllByText('1')[0])).toThrowError( 'unable to click element as it has or inherits pointer-events set to "none"' ); }); await waitFor(() => { expect(() => userEvent.click(getAllByText('21')[0])).toThrowError( 'unable to click element as it has or inherits pointer-events set to "none"' ); }); }); it('does not allow to edit disabled DateRangePicker', async () => { const { queryByText, getByDisplayValue } = renderWithTheme( ); userEvent.click(getByDisplayValue('11/05/2021')); await waitFor(() => { expect(queryByText('Su')).not.toBeInTheDocument(); }); }); it('does not allow invalid value', () => { jest.spyOn(console, 'error').mockImplementation(() => ''); expect(() => renderWithTheme( ) ).toThrowError('Invalid time value'); }); it('does not allow to clear value when clearable is false', () => { const { getByTestId, queryByTestId } = renderWithTheme( ); expect(queryByTestId('remove-icon')).not.toBeInTheDocument(); userEvent.hover(getByTestId('date-range-picker')); expect(queryByTestId('remove-icon')).not.toBeInTheDocument(); }); it('does not allow to clear value when value is undefined', () => { const { getByTestId, queryByTestId } = renderWithTheme( ); expect(queryByTestId('remove-icon')).not.toBeInTheDocument(); userEvent.hover(getByTestId('date-range-picker')); expect(queryByTestId('remove-icon')).not.toBeInTheDocument(); }); it('allows to clear value when startDate is not undefined', () => { const onChange = jest.fn(); const { getByTestId, queryByTestId } = renderWithTheme( ); expect(queryByTestId('remove-icon')).not.toBeInTheDocument(); userEvent.hover(getByTestId('date-range-picker')); expect(queryByTestId('remove-icon')).toBeInTheDocument(); }); it('allows to clear value when endDate is not undefined', () => { const onChange = jest.fn(); const { getByTestId, queryByTestId } = renderWithTheme( ); expect(queryByTestId('remove-icon')).not.toBeInTheDocument(); userEvent.hover(getByTestId('date-range-picker')); expect(queryByTestId('remove-icon')).toBeInTheDocument(); }); it('allows to clear value', async () => { const onChange = jest.fn(); const { getByTestId, queryByTestId, container } = renderWithTheme( ); expect(queryByTestId('remove-icon')).not.toBeInTheDocument(); expect(container.querySelector('.hero-icon-calendar')).toBeInTheDocument(); userEvent.hover(getByTestId('date-range-picker')); expect(container.querySelector('.hero-icon-calendar')).toBeNull(); userEvent.click(getByTestId('remove-icon')); await waitFor(() => { expect(onChange).toHaveBeenCalledWith({ startDate: undefined, endDate: undefined, }); }); }); });