import React, { useState } from 'react' import { render, screen, waitFor, within } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { FilterButton } from '~components/Filter/FilterButton' import { FilterDatePicker, type FilterDatePickerProps } from '.' const user = userEvent.setup() const FilterDatePickerWrapper = ({ selectedDate, ...restProps }: Partial): JSX.Element => { const [isOpen, setIsOpen] = useState(false) const [selectedValue, setSelectedValue] = useState(selectedDate) return ( } label="Drank" selectedDate={selectedValue} onDateChange={setSelectedValue} defaultMonth={new Date('2022-05-01')} locale="en-AU" {...restProps} /> ) } describe('', () => { it('should not show the calendar initially', () => { render() expect(screen.queryByRole('dialog')).not.toBeInTheDocument() }) describe('Filter button', () => { it('should show the selected date in the button', async () => { render() await waitFor(() => { const filterButton = screen.getByRole('button', { name: 'Drank : 1 May 2022', }) expect(filterButton).toBeVisible() }) }) it('should show the calendar when the filter button is clicked', async () => { render() const filterButton = screen.getByRole('button', { name: 'Drank', }) await user.click(filterButton) await waitFor(() => { expect(screen.getByText('May 2022')).toBeVisible() }) }) }) it('closes the popover when a valid date has been submitted via the calendar picker', async () => { const { getByRole } = render() const triggerButton = getByRole('button', { name: 'Drank', }) await user.click(triggerButton) const dialog = getByRole('dialog') await waitFor(() => { expect(dialog).toBeInTheDocument() }) const targetMonth = screen.getByRole('grid', { name: 'May 2022' }) const targetDay = within(targetMonth).getByRole('gridcell', { name: '2' }) const targetBtn = within(targetDay).getByRole('button') await user.click(targetBtn) await waitFor(() => { expect(dialog).not.toBeInTheDocument() }) }) describe('Text input', () => { it('validates the date on blur', async () => { const { getByRole, getByLabelText, getByText } = render() const triggerButton = getByRole('button', { name: 'Drank', }) await user.click(triggerButton) const dialog = getByRole('dialog') await waitFor(() => { expect(dialog).toBeInTheDocument() }) const inputDate = getByLabelText('Date') await user.clear(inputDate) await user.type(inputDate, '32/13/2022') await user.tab() await waitFor(() => { expect(getByText('32/13/2022 is an invalid date')).toBeInTheDocument() }) }) describe('Pressing Enter in the text input', () => { it('closes the popover when a valid date has been submitted via the text input field', async () => { const { getByRole, getByLabelText } = render() const triggerButton = getByRole('button', { name: 'Drank', }) await user.click(triggerButton) const dialog = getByRole('dialog') await waitFor(() => { expect(dialog).toBeInTheDocument() }) const inputDate = getByLabelText('Date') await user.clear(inputDate) await user.type(inputDate, '07/06/2022') await user.keyboard('{Enter}') await waitFor(() => { expect(dialog).not.toBeInTheDocument() }) }) it('does not close the popover when an invalid date has been submitted via the text input field', async () => { const { getByRole, getByLabelText, getByText } = render() const triggerButton = getByRole('button', { name: 'Drank', }) await user.click(triggerButton) const dialog = getByRole('dialog') await waitFor(() => { expect(dialog).toBeInTheDocument() }) const inputDate = getByLabelText('Date') await user.clear(inputDate) await user.type(inputDate, '32/13/2022') await user.keyboard('{Enter}') await waitFor(() => { expect(getByText('32/13/2022 is an invalid date')).toBeInTheDocument() }) }) }) }) it('does not close the popover when the text input field has been cleared', async () => { const { getByRole, getByLabelText, getByText, queryByText } = render( , ) const triggerButton = getByRole('button', { name: 'Drank : Invalid Date', }) await user.click(triggerButton) const dialog = getByRole('dialog') await waitFor(() => { expect(dialog).toBeInTheDocument() expect(getByText('Invalid Date is an invalid date')).toBeInTheDocument() }) const inputDate = getByLabelText('Date') await user.clear(inputDate) await user.tab() await waitFor(() => { expect(queryByText('Invalid Date is an invalid date')).not.toBeInTheDocument() // We are double checking that the popover has not closed expect(dialog).toBeInTheDocument() }) }) it('does not close the popover when there is a selected date and the user navigates months', async () => { const { getByRole } = render() const triggerButton = getByRole('button', { name: 'Drank : 1 Jan 2022', }) await user.click(triggerButton) const dialog = getByRole('dialog') await waitFor(() => { expect(dialog).toBeInTheDocument() }) const navigateMonthsButton = getByRole('button', { name: /Go to the next month/i, }) await user.click(navigateMonthsButton) await waitFor(() => { expect(dialog).toBeInTheDocument() }) }) it('updates the selected value in the trigger button when typing a date', async () => { const { getByRole, getByLabelText } = render( , ) const triggerButton = getByRole('button', { name: 'Drank : 6 Jun 2022', }) await user.click(triggerButton) await waitFor(() => { const dialog = getByRole('dialog') expect(dialog).toBeInTheDocument() }) const inputDate = getByLabelText('Date') await user.clear(inputDate) await user.type(inputDate, '07/06/2022') // TODO: note that this should work without having to trigger a tab. update this test when fixed. await user.tab() await user.click(document.body) await waitFor(() => { expect(getByRole('button', { name: 'Drank : 7 Jun 2022' })).toBeInTheDocument() }) }) })