import { useState } from 'react'; import { act, fireEvent, render, screen } from '@testing-library/react'; import { DeviceTypeProvider } from 'morphe'; import DatePicker from './DatePicker'; const initialDate = new Date(2018, 11, 14); function DatePickerWrap({ showMonthYearDropdown, disableMobileUI, label, }: { showMonthYearDropdown?: boolean; disableMobileUI?: boolean; label?: string; }) { const [date, setDate] = useState(initialDate); return ( setDate(value)} selectLists={showMonthYearDropdown ? ['year', 'month'] : undefined} value={date} /> ); } describe('DatePicker', () => { const mockOnChange = jest.fn< [ { event: React.ChangeEvent; value: Date | null; }, ], // @ts-expect-error - TS2344 - Type 'undefined' does not satisfy the constraint 'any[]'. undefined >(); global.document.createRange = () => ({ setStart: () => {}, setEnd: () => {}, // @ts-expect-error - TS2740 - Type '{ nodeName: string; ownerDocument: Document; }' is missing the following properties from type 'Node': baseURI, childNodes, firstChild, isConnected, and 44 more. commonAncestorContainer: { nodeName: 'BODY', ownerDocument: document, }, }); it('displays TextField with given initial date', () => { render( {}} value={initialDate} />); // We only check for selected value upon rendering, // because onChange logic is outside DatePicker // So initial date value does not change upon firing click event expect(screen.getByDisplayValue('12/14/2018')).toBeInTheDocument(); }); it('passes clicked date to onChange prop', () => { const newDate = new Date(2018, 11, 13); render( , ); fireEvent.focus(screen.getByDisplayValue('12/14/2018')); // eslint-disable-next-line testing-library/prefer-presence-queries -- Please fix the next time this file is touched! expect(screen.queryByText('December 2018')).toBeInTheDocument(); const selectedDay = screen.getByText('13'); fireEvent.click(selectedDay); expect(mockOnChange).toHaveBeenCalledWith(expect.objectContaining({ value: newDate })); }); test('opens and closes DatePicker popover correctly', async () => { render(); // eslint-disable-next-line testing-library/no-unnecessary-act -- We have to wrap the focus event in `act` since it does change the component's internal state await act(async () => { await fireEvent.focus(screen.getByDisplayValue('12/14/2018')); }); // Test correct render of DatePicker popover // eslint-disable-next-line testing-library/prefer-presence-queries -- Please fix the next time this file is touched! expect(screen.queryByText('December 2018')).toBeInTheDocument(); // Test that initial passed value is styled as selected expect(screen.getByText('14')).toHaveClass( 'react-datepicker__day react-datepicker__day--014 react-datepicker__day--selected', ); const selectedDay = screen.getByText('13'); fireEvent.click(selectedDay); // Test correct unmount of DatePicker popover expect(screen.getByDisplayValue('12/13/2018')).toBeInTheDocument(); // eslint-disable-next-line testing-library/no-unnecessary-act -- We have to wrap the focus event in `act` since it does change the component's internal state await act(async () => { await fireEvent.click(screen.getByDisplayValue('12/13/2018')); }); // Test correct render of DatePicker popover // eslint-disable-next-line testing-library/prefer-presence-queries -- Please fix the next time this file is touched! expect(screen.queryByText('December 2018')).toBeInTheDocument(); }); test('accepts entering manual dates', async () => { render(); // eslint-disable-next-line testing-library/no-unnecessary-act -- We have to wrap the focus event in `act` since it does change the component's internal state await act(async () => { fireEvent.focus(screen.getByDisplayValue('12/14/2018')); }); const selectedInput = screen.getByDisplayValue('12/14/2018'); fireEvent.change(selectedInput, { target: { value: '12/13/2018' } }); // Test correct unmount of DatePicker popover expect(screen.getByDisplayValue('12/13/2018')).toBeInTheDocument(); fireEvent.focus(screen.getByDisplayValue('12/13/2018')); // Test correct render of DatePicker popover // eslint-disable-next-line testing-library/prefer-presence-queries -- Please fix the next time this file is touched! expect(screen.queryByText('December 2018')).toBeInTheDocument(); expect(screen.getByText('13')).toHaveClass( 'react-datepicker__day react-datepicker__day--013 react-datepicker__day--selected', ); }); test('has year and month select list options', async () => { render(); // eslint-disable-next-line testing-library/no-unnecessary-act -- We have to wrap the focus event in `act` since it does change the component's internal state await act(async () => { fireEvent.focus(screen.getByDisplayValue('12/14/2018')); }); expect(screen.queryAllByRole('option', { name: 'January' })).toHaveLength(1); expect(screen.queryAllByRole('option', { name: '2017' })).toHaveLength(1); }); test('Mobile Datepicker renders', async () => { const { baseElement } = render( , ); fireEvent.focus(screen.getByDisplayValue('12/14/2018')); expect(baseElement).toMatchSnapshot(); expect(screen.getByText('Close')).toBeInTheDocument(); }); });