Home > Enterprise >  How to change the value of an MUI DatePicker in Jest (x-date-pickers)
How to change the value of an MUI DatePicker in Jest (x-date-pickers)

Time:02-04

Regarding { DatePicker } from '@mui/x-date-pickers':

I can't figure out how to change the value using Jest.

Here's my DatePicker-wrapper DatePickerX:

import React, { useState } from 'react';
import { DatePicker } from '@mui/x-date-pickers';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import AdapterDateFns from '@mui/lab/AdapterDateFns';
import { de } from 'date-fns/locale';
import { TextField } from '@mui/material';

export const DatePickerX: React.FC = () => {
  const [date, setDate] = useState<Date>(new Date());

  const changeDate = (newDate: Date | null) => {
    if (newDate) {
      setDate(newDate);
    }
  };

  return (
    <>
    <LocalizationProvider locale={de} dateAdapter={AdapterDateFns}>
        <DatePicker
          label="datepicker_label"
          value={date}
          inputFormat="yyyy/MM/dd"
          views={['year', 'month', 'day']}
          mask="____/__/__"
          onChange={changeDate}
          renderInput={(params) => (
            <TextField type="text"  {...params}  data-testid="textInput_testid" name="textInput_name"/>
          )}
        />
    </LocalizationProvider>
    </>

  );
}

This works perfectly fine on the UI.

Here are my attempts to change the date. All tests fail:

describe('change date picker value test 1', () => {
  test('use datepicker label; set string', async () => {
    render(<DatePickerX />);

    const input = screen.getByLabelText('datepicker_label');
    await act(async () => {
      await fireEvent.change(input, { target: { value: '3000/01/01' } });
    });

    expect(screen.getByText('3000/01/01')).toBeVisible();
  });
  test('use text input; set string', async () => {
    render(<DatePickerX />);

    const input2 = screen.getByTestId('textInput_testid');
    await act(async () => {
      await fireEvent.change(input2, { target: { value: '3000/01/01' } });
    });

    expect(screen.getByText('3000/01/01')).toBeVisible();
  });

  test('use datepicker label; set date', async () => {
    render(<DatePickerX />);

    const input = screen.getByLabelText('datepicker_label');
    await act(async () => {
      await fireEvent.change(input, { target: { value: new Date('3000/01/01') } });
    });

    expect(screen.getByText('3000/01/01')).toBeVisible();
  });

  test('use text input; set date', async () => {
    render(<DatePickerX />);

    const input2 = screen.getByTestId('textInput_testid');
    await act(async () => {
      await fireEvent.change(input2, { target: { value: new Date('3000/01/01') } });
    });

    expect(screen.getByText('3000/01/01')).toBeVisible();
  });
});

What am I doing wrong?

CodePudding user response:

Firstly: I wanted to note that @mui/lab adapter should not be used together with @mui/x pickers. I'd suggest syncing those usages by changing your adapter import to import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; (based on setup documentation).

Secondly: Have you checked which component is rendered during your test cases? I see that you are importing DatePicker, this component renders either Desktop or Mobile version of the picker depending on desktopModeMediaQuery prop. This rendering logic has some caveats in test environments, I'd suggested reading testing caveats doc section for more information on how to reach your desired result.

Lastly: Are those test cases you provided in the question your real project examples or just for illustration purposes? If they are real cases, I'd suggest thinking if it's worth testing behaviours, that are already tested by MUI on their end. Ideally, you should write tests asserting your own code.

CodePudding user response:

Before you render any component that has dependencies, is important to load those before.

So one of the issue that Test are failing could be that when you render the component en each case the test runner is looking for the provider, adapters and the others dependencies.

To solve this you can use the jest.mock function or just import them

This is one of the example the doc link include.

import axios from 'axios';
import Users from './users';

jest.mock('axios');

test('should fetch users', () => {
  const users = [{name: 'Bob'}];
  const resp = {data: users};
  axios.get.mockResolvedValue(resp);

  // or you could use the following depending on your use case:
  // axios.get.mockImplementation(() => Promise.resolve(resp))

  return Users.all().then(data => expect(data).toEqual(users));
})

Hope this help

  • Related