|
import { FormForTesting } from '@epic/testing/react'; |
|
import { render, waitFor } from '@testing-library/react'; |
|
import { useForm } from 'react-hook-form'; |
|
import { EpicDatePicker } from './EpicDatePicker'; |
|
import { EpicDatePickerProps } from './EpicDatePickerProps'; |
|
import AdapterDateFns from '@mui/lab/AdapterDateFns'; |
|
import { LocalizationProvider } from '@mui/lab'; |
|
import userEvent from '@testing-library/user-event'; |
|
import { endOfDay } from 'date-fns'; |
|
|
|
type Model = { |
|
date?: Date; |
|
}; |
|
beforeAll(() => { |
|
// add window.matchMedia |
|
// this is necessary for the date picker to be rendered in desktop mode. |
|
// if this is not provided, the mobile mode is rendered, which might lead to unexpected behavior |
|
Object.defineProperty(window, 'matchMedia', { |
|
writable: true, |
|
value: (query: any) => ({ |
|
media: query, |
|
// this is the media query that @material-ui/pickers uses to determine if a device is a desktop device |
|
matches: query === '(pointer: fine)', |
|
onchange: () => {}, |
|
addEventListener: () => {}, |
|
removeEventListener: () => {}, |
|
addListener: () => {}, |
|
removeListener: () => {}, |
|
dispatchEvent: () => false, |
|
}), |
|
}); |
|
}); |
|
|
|
afterAll(() => { |
|
// @ts-ignore |
|
delete window.matchMedia; |
|
}); |
|
const onSubmit = jest.fn(); |
|
|
|
function TestComponent({ |
|
initialValue, |
|
...props |
|
}: Omit<EpicDatePickerProps, 'formContext' | 'name' | 'label'> & { initialValue?: Model }) { |
|
const formContext = useForm<Model>({ |
|
defaultValues: initialValue, |
|
}); |
|
|
|
const { |
|
formState: { errors }, |
|
} = formContext; |
|
const submit = (d: Model) => { |
|
onSubmit(d); |
|
}; |
|
return ( |
|
<LocalizationProvider dateAdapter={AdapterDateFns}> |
|
<FormForTesting submit={submit} formContext={formContext}> |
|
<EpicDatePicker |
|
formContext={formContext} |
|
name={'date'} |
|
label={'Date'} |
|
{...props} |
|
error={!!errors} |
|
helperText={errors.date?.message} |
|
/> |
|
<button type="submit">Submit</button> |
|
</FormForTesting> |
|
</LocalizationProvider> |
|
); |
|
} |
|
|
|
describe('Appearance', function () { |
|
it('should set size to small by default and can be set to medium', function () { |
|
const { getByLabelText, rerender } = render(<TestComponent canEdit />); |
|
const input = getByLabelText('Date'); |
|
|
|
expect(input.className).toMatch(/inputSizeSmall/i); |
|
|
|
rerender(<TestComponent canEdit={false} />); |
|
const input1 = getByLabelText('Date'); |
|
|
|
expect(input1.className).toMatch(/inputSizeSmall/i); |
|
|
|
rerender(<TestComponent size={'medium'} />); |
|
const input2 = getByLabelText('Date'); |
|
|
|
expect(input2.className).not.toMatch(/inputSizeSmall/i); |
|
}); |
|
|
|
it('should always shrink label by default', function () { |
|
const { getByText } = render(<TestComponent />); |
|
const label = getByText('Date', { selector: 'label' }); |
|
|
|
expect(label).toHaveAttribute('data-shrink', 'true'); |
|
}); |
|
|
|
it('should be full width by default', function () { |
|
const { getByLabelText } = render(<TestComponent />); |
|
const input = getByLabelText('Date'); |
|
|
|
expect(input.closest('div')?.className).toMatch(/fullwidth/i); |
|
}); |
|
|
|
it('should render outlined style in edit mode', function () { |
|
const { getByLabelText } = render(<TestComponent />); |
|
const input = getByLabelText('Date'); |
|
|
|
expect(input.className).toMatch(/outlined/i); |
|
}); |
|
|
|
it('should apple standard style(underline) in read mode', function () { |
|
const { getByLabelText } = render(<TestComponent canEdit={false} />); |
|
const input = getByLabelText('Date'); |
|
|
|
expect(input.closest('div')?.className).toMatch(/underline/i); |
|
}); |
|
|
|
it('should not show * on the label on required field in read mode', function () { |
|
const { getByLabelText, queryByLabelText, rerender } = render( |
|
<TestComponent required canEdit={false} /> |
|
); |
|
|
|
expect(getByLabelText(/Date/i)).toBeInTheDocument(); |
|
expect(queryByLabelText(/\*/i)).toBeNull(); |
|
|
|
// should show * with required and edit mode |
|
rerender(<TestComponent required canEdit />); |
|
expect(getByLabelText(/Date/i, { selector: 'input' })).toBeInTheDocument(); |
|
expect(queryByLabelText(/\*/i)).toBeInTheDocument(); |
|
}); |
|
}); |
|
|
|
describe('Behaviours', () => { |
|
it('should be disabled and not show choose date icon button in non edit mode', async function () { |
|
const { getByLabelText, queryByLabelText } = render(<TestComponent canEdit={false} />); |
|
const input = getByLabelText('Date'); |
|
|
|
expect(input).toBeDisabled(); |
|
expect(queryByLabelText(/Choose Date/i)).toBeNull(); |
|
}); |
|
|
|
it('should not be disabled and show choose date icon button in edit mode', function () { |
|
const { getByLabelText } = render(<TestComponent canEdit={true} />); |
|
const input = getByLabelText('Date'); |
|
|
|
expect(input).not.toBeDisabled(); |
|
expect(getByLabelText(/Choose Date/i)).toBeInTheDocument(); |
|
}); |
|
|
|
it('should set default value', function () { |
|
const { getByLabelText } = render(<TestComponent defaultValue={new Date(2022, 0, 1)} />); |
|
const input = getByLabelText('Date'); |
|
|
|
expect(input).toHaveValue('2022-01-01'); |
|
}); |
|
|
|
it('should apply styles', function () { |
|
const { getByLabelText } = render(<TestComponent style={{ fontSize: '10px' }} />); |
|
const input = getByLabelText('Date'); |
|
|
|
expect(input.closest('div[style="font-size: 10px;"]')).toBeInTheDocument(); |
|
}); |
|
|
|
it('should have default mask of yyyy-MM-dd', () => { |
|
const { getByLabelText } = render(<TestComponent />); |
|
const input = getByLabelText('Date'); |
|
|
|
userEvent.type(input, '2020-01-01'); |
|
|
|
expect(input).toHaveValue('2020-01-01'); |
|
}); |
|
|
|
it('should format date to default format of yyyy-MM-dd', () => { |
|
const { getByLabelText } = render( |
|
<TestComponent initialValue={{ date: new Date(2022, 1, 1) }} /> |
|
); |
|
const input = getByLabelText('Date'); |
|
|
|
expect(input).toHaveValue('2022-02-01'); |
|
}); |
|
|
|
it('should format date to given format', () => { |
|
const { getByLabelText } = render( |
|
<TestComponent |
|
initialValue={{ date: new Date(2022, 1, 1) }} |
|
mask={'__/__/____'} |
|
inputFormat={'dd/MM/yyyy'} |
|
/> |
|
); |
|
const input = getByLabelText('Date'); |
|
|
|
expect(input).toHaveValue('01/02/2022'); |
|
}); |
|
}); |
|
|
|
describe('Validations', function () { |
|
it('should validate date', async function () { |
|
const { getByLabelText, getByText, findByText } = render(<TestComponent />); |
|
const input = getByLabelText('Date'); |
|
|
|
userEvent.type(input, '010101'); |
|
userEvent.click(getByText('Submit')); |
|
|
|
expect(await findByText('Date is not valid')).toBeInTheDocument(); |
|
}); |
|
|
|
it('should validate required', async function () { |
|
const { getByLabelText, getByText, findByText } = render(<TestComponent required />); |
|
getByLabelText(/\*/); |
|
|
|
userEvent.click(getByText('Submit')); |
|
|
|
expect(await findByText('Required')).toBeInTheDocument(); |
|
}); |
|
|
|
it('should emit end of day date', async function () { |
|
const { getByLabelText, getByText } = render(<TestComponent />); |
|
const input = getByLabelText('Date'); |
|
|
|
userEvent.type(input, '2020-01-01'); |
|
userEvent.click(getByText('Submit')); |
|
|
|
await waitFor(() => |
|
expect(onSubmit).toHaveBeenCalledWith({ date: new Date(2020, 0, 1, 23, 59, 59, 999) }) |
|
); |
|
}); |
|
|
|
it('should enforce rules', async function () { |
|
const afterDate = { |
|
validate: (v: Date) => { |
|
return ( |
|
endOfDay(v).getTime() > new Date(2020, 0, 1, 23, 59, 59, 999).getTime() || |
|
'Date must be after 2020-01-01' |
|
); |
|
}, |
|
}; |
|
const { getByLabelText, getByText, findByText } = render(<TestComponent rules={afterDate} />); |
|
const input = getByLabelText('Date'); |
|
|
|
userEvent.type(input, '2020-01-01'); |
|
userEvent.click(getByText('Submit')); |
|
|
|
expect(await findByText('Date must be after 2020-01-01')).toBeInTheDocument(); |
|
}); |
|
}); |
Top comments (0)