Reputation: 133
I have a component which uses the react-datepicker
package.
I am writing to write a unit test which will edits the dates and thereafter run some logic. However, i am unable to detect the field which for me to change using userEvent.type()
. I have tried to use getByText, getByRole, getAllByText.
Form.tsx
import React, { useState } from 'react';
import DatePicker from "react-datepicker";
import { Form } from 'react-bootstrap';
import "react-datepicker/dist/react-datepicker.css";
const Form = () => {
const [data, setData] = useState({ date1: new Date(), date2: new Date() })
return (
<div>
<Form>
...some other fields
<Form.Group controlId="date1">
<Form.Label>Date1</Form.Label>
<DatePicker name='date1'selected={data.date1} onChange={(date: Date) => setData({...data, date1: date})}
</Form.Group>
<Form.Group controlId="date2">
<Form.Label>Date2</Form.Label>
<DatePicker name='date2' selected={data.date2} onChange={(date: Date) => setData({...data, date2: date})}
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</div>
)
}
export default Form
Form.test.tsx
import React from 'react';
import Form from './Form';
import {render} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
describe('Form Component', () => {
it('able to change the date', () => {
const { getByRole } = render(<Form/>)
const date1Field = getByRole('textbox', { name: /date1/i })
act(() => userEvent.type(date1Field, '01/01/1990'))
... any other action to submit the form
})
})
However, my terminal showed me, which is the same for both date, which it was unable to detect the input field:
TestingLibraryElementError: Unable to find an accessible element with the role"textbox" and name "/date1/i"
textbox:
Name=""
<input
class=''
name='date1'
type='text'
value='05/23/2021'
/>
Name=""
<input
class=''
name='date2'
type='text'
value='05/23/2021'
/>
Upvotes: 3
Views: 15365
Reputation: 4033
I used for
attribute on the label
tag and then used getByLabelText
.
<div>
<label for="date-picker">Delivery date:</label>
<DatePicker
id="date-picker"
dateFormat="yyyy-MM-dd"
selected={selectedDate}
onChange={(date) => {
...
}}
/>
</div>
it('fireEvent onchange of Date of Birth', async () => {
const datepicker = screen.getByLabelText("Delivery date:");
fireEvent.change(datepicker, {
target: {
value: "2021-10-01",
},
});
}
Upvotes: 0
Reputation: 1
I found a solution that works perfectly for me.
React Code:
<DatePicker
id="dob"
placeholderText='Date of Birth'
selected={dateofBirth}
onChange={(date: Date): void => {setDateofBirth(date)}}
popperProps={{ strategy: 'fixed' }}
dateFormat="dd-MM-yyyy"
/>
Test Case Code:
it('fireEvent onchange of Date of Birth', async () => {
const props: LoginProps = {
dateofBirth: new Date(),
setDateofBirth: () => { },
setUniqueRefNumber: () => { },
showErrorMessage: "yes",
}
render(<LoginScreen {...props} />);
const dob = screen.getByPlaceholderText('Date of Birth')
fireEvent.change(dob, { target: { value: new Date() } })
await waitFor(() => {
expect(dob).toBeEnabled();
});
Upvotes: 0
Reputation: 102
After Trying many solution, and trying and error.
I found a solution that work perfectly fine for me.
describe('Date Picker Test', () => {
let wrapper;
beforeEach(() => {
wrapper = mount(
<Provider store={store}>
<Router>
<DatePikerFunction />
</Router>
</Provider>,
);
});
it('Date Picker Change', async () => {
const datePicker = await wrapper.find('.ant-picker-input input').first();
await datePicker.simulate('mousedown');
await waitFor(async () => {
await wrapper.update();
const today = await wrapper.find('.ant-picker-cell-today'); // put classname that is used to select the perticular date
const next = today.nextElementSibling;
await next.click();
});
});
});
Here I have find the today's date and then selected tomorrow date. You can find base on class or any thing you want and use it.
Hope It will work for you too. Thanks
Upvotes: 1
Reputation: 1
try this solution, this perfectly works for me
const startDate = await container.find('.ant-picker-input input').first();
await startDate.simulate('mousedown');
await waitFor(async () => {
await container.update();
const dateChart = await container.find('.ant-picker-today-btn');
await dateChart.simulate('click');
});
Upvotes: 0
Reputation: 667
It might not be needed but in case, you can pass a prop placeholderText='some text' and then get the input using screen.getByPlaceholderText('some text');
Upvotes: 0
Reputation: 1395
There is an issue with the library itself and not being able to pass in any ARIA props into the datepicker in react-datepicker
.
With using the other library you mentioned react-day-picker
it is possible to pass props into the input and set aria labels.
import DayPickerInput from 'react-day-picker/DayPickerInput';
<DayPickerInput inputProps={{'aria-label':'Date input 2'}} />
Sandbox: https://codesandbox.io/s/react-day-picker-examplesinput-forked-lj8pp
Upvotes: 1
Reputation: 133
For anyone who is looking for a solution which I have adopted Jonathan S. answer,
Form.tsx
import React, { useState } from 'react';
import DayPickerInput from "react-datepicker/DayPickerInput";
import { Form } from 'react-bootstrap';
import "react-day-picker/lib/style.css";
const Form = () => {
const [data, setData] = useState({ date1: new Date(), date2: new Date() })
return (
<div>
<Form>
...some other fields
<Form.Group controlId="date1">
<Form.Label>Date1</Form.Label>
<DayPickerInput inputProps={{ 'aria-label': 'date1' }} value={data.date1} onChange={(date: Date) => setData({...data, date1: date})}/>
</Form.Group>
<Form.Group controlId="date2">
<Form.Label>Date2</Form.Label>
<DayPickerInput inputProps={{ 'aria-label': 'date2' }} value={data.date2} onChange={(date: Date) => setData({...data, date2: date})}/>
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</div>
)
}
export default Form
Form.test.tsx
import React from 'react';
import Form from './Form';
import {render} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
describe('Form Component', () => {
it('able to change the date', () => {
const { getByLabelText } = render(<Form/>)
let date1Field = getByLabelText('date1') as HTMLInputElement
// Selects your default value of the date field
date1Field.setSelectRange(0, date1Field.value.length)
// Replaces it
userEvent.type(date1Field, '1990-01-01')
... any other action to submit the form
})
})
Upvotes: 1