react-number-format icon indicating copy to clipboard operation
react-number-format copied to clipboard

How to uint test NumberFormat using Jest and Enzyme?

Open leifoolsen opened this issue 6 years ago • 5 comments

Hello,

I'm trying to unit test a component that uses the NumberFormat component. The unit test fails with the following error: "TypeError: el.focus is not a function".

Example code for the test:

import React from 'react';
import {mount} from 'enzyme';
import NumberFormat from 'react-number-format';

describe('NumberFormat', () => {
  it('<input>, onChange - WORKS', () => {
    const spy = jest.fn();
    const wrapper = mount(
      <div>
        <input
          value="8"
          id="fn1"
          onChange={spy}
        />
      </div>
    );
    const cb = wrapper.find('input');
    cb.simulate('change', {target: {value: '9'}});
    expect(spy).toHaveBeenCalled();
  });

  it('<NumberFormat>, onChange - FAILS', () => {
    const spy = jest.fn();
    const wrapper = mount(
      <NumberFormat
        value={1001.2}
        thousandSeparator=" "
        decimalSeparator=","
        decimalScale={2}
        fixedDecimalScale
        id="fn1"
        onChange={spy}
      />
    );
    const cb = wrapper.find('input');
    cb.simulate('change', {target: {value: '9'}}); // Fails on this stmt
    expect(spy).toHaveBeenCalled();
  });
});

What is the correct way to set up a unit test to simulate onChange/onValueChange ?

Regards Leif Olsen

leifoolsen avatar Jan 10 '19 13:01 leifoolsen

Just solved this myself.

Replace: cb.simulate('change', {target: {value: '9'}}); with...

cb.simulate('change', {target: {value: '9', focus: () => {}}});

Basically just add an empty focus function.

sross0988 avatar Feb 28 '19 20:02 sross0988

@sross0988 solution worked great with the inputs which are empty initially, but not with inputs with has some default value in it. So i firstly set value to '' and then set to expected value to make it run correctly for the prefilled inputs.

sedatbasar avatar Sep 23 '20 10:09 sedatbasar

For anyone looking to test with react-testing-library (@testing-library/react) and its accessible getByLabelText, you need to set name/id property for the input. For some reason these props are not being passed down to the input, so I had to hack with

getInputRef={(input) => {
    if (input) {
        input.name = name;
        input.id = id;
    }
})}

Only then getByLabelText matched and returned an input element in tests.

v1adko avatar Aug 25 '22 15:08 v1adko

@v1adko Do you have an example of a unit test using react-testing-library for this ?

CodeguruEdison avatar Jun 08 '23 19:06 CodeguruEdison

Just solved this myself.

Replace: cb.simulate('change', {target: {value: '9'}}); with...

cb.simulate('change', {target: {value: '9', focus: () => {}}});

Basically just add an empty focus function.

This didn't work in our case, so we ended up patching the react-number-format.cjs.js file.

diff --git a/node_modules/react-number-format/dist/react-number-format.cjs.js b/node_modules/react-number-format/dist/react-number-format.cjs.js
index 9a3be81..6a9872b 100644
--- a/node_modules/react-number-format/dist/react-number-format.cjs.js
+++ b/node_modules/react-number-format/dist/react-number-format.cjs.js
@@ -232,7 +232,7 @@ function setCaretPosition(el, caretPos) {
             return true;
         }
         // fail city, fortunately this never happens (as far as I've tested) :)
-        el.focus();
+        el && el.focus && el.focus();
         return false;
     }
 }

joaocarmo avatar Jun 20 '23 08:06 joaocarmo