How to unit test masked input?
Asked Answered
V

2

7

How to unit test the masked input field using react-testing-library. That component has developed using material ui and react-hook-form. Here you can find the code and worked on examples from my side. Thanks in advance

Test file:

 let Phone_Input = getByTestId("phone-input");

  fireEvent.change(
      <InputMask mask="(999) 999-9999">{() => Phone_Input}</InputMask>,
      {
        target: { value: "9500902621" }
      }
    );

Component:

                      <InputMask mask="(999) 999-9999">
                          {() => (
                            <TextField
                              id="standard-required"
                              name="phone"
                              label="phone"
                              placeholder="Enter Phone"
                              inputProps={{
                                "data-testid": "phone-input"
                              }}

                            />
                          )}
                        </InputMask>

Error:

    The given element does not have a value setter

    expect(received).toBe(expected) // Object.is equality

    Expected: "(950) 090-2621"
    Received: "(___) ___-____"
Verdun answered 25/2, 2020 at 12:43 Comment(1)
Did you find any solution? Facing this same problem,Tabithatablature
M
2

So, I had the same problem using react-input-mask. After a long search, I found this post: https://github.com/sanniassin/react-input-mask/issues/174. (still remains an unresolved problem by the library)

People there discussed two possible solutions:

  1. Change the library (react-text-mask, react-imask ...)

  2. Use the workaround made by the post creator:

Ex:

import userEvent from '@testing-library/user-event';
import TestUtils from 'react-dom/test-utils';

function changeInputMaskValue(element, value) {
  element.value = value;
  element.selectionStart = element.selectionEnd = value.length;
  TestUtils.Simulate.change(element);
};

it('example test', async () => {
  render(
    <MyComponent
      amount="100.00"
    />,
  );

  act(() => {
    // Both lines of codes are required
    userEvent.type(screen.getByLabelText('Amount'), '300');
    changeInputMaskValue(screen.getByLabelText('Amount'), '300');
  });

  act(() => {
    // Do not move the form submitting to the previous `act`, it must be in two
    // separate `act` calls.
    userEvent.click(screen.getByText('Next'));
  });

  // You must use `findByText`
  const error = await screen.findByText(/\$100.00 to redeem/);
  expect(error).toBeInTheDocument();
});
Moersch answered 10/3, 2022 at 20:7 Comment(0)
A
-1

My component is different than yours, but might lead you to the right direction.

This is how my test looks like:

const propsMock = { mask: sampleMask };
const { getByTestId } = render(<MaskedTextField {...propsMock} />);

const input = getByTestId('maskedtextfield-');
fireEvent.change(input, { target: { value: '9999999999' } });
expect(getByTestId('maskedtextfield-').value).toEqual('(999) 999-9999');

Component important part:

<Input
      placeholder={placeholder}
      disabled={disabled}
      onChange={onChange}
      onKeyUp={onKeyUp}
      onBlur={onBlur}
      inputRef={inputRef}
      inputComponent={TextMaskCustom as any}
      inputProps={{
        'data-testid': dataTestId || `maskedtextfield-${label}`,
        defaultValue: defaultValue || '',
        ...getMaskProps(mask),
      }}
    />

My deps are: Input is a material-ui component and TextMaskCustom is an implementation of react-text-mask. Working fine here.

Ataractic answered 21/7, 2020 at 16:56 Comment(2)
Why asking for getByTestId('maskedtextfield-').value twice? Isn't it already loaded on input?Susette
Probably just a leftover from the tests I was doing. In theory you can use input and it should work fineAtaractic

© 2022 - 2024 — McMap. All rights reserved.