0

When I have

expect(result.toJSON())
.toEqual(<button className="btn btn-prev" onClick="{[Function onClick]}" type="button">Prev</button>);

it is close but not quite right - just missing the Function onClick:

expect(received).toEqual(expected) // deep equality
- Expected
+ Received

  <button
    className="btn btn-prev"
-   onClick="{[]}"
+   onClick={[Function onClick]} // <--- the difference, Function onClick is missing
    type="button"
  >
    Prev
  </button>

However if I try and add in the missing "Function onClick", i.e.

expect(result.toJSON())
.toEqual(<button className="btn btn-prev" onClick="{[Function onClick]}" type="button">Prev</button>);

I get

-   onClick="{[Function onClick]}"
+   onClick={[Function onClick]}

and if I remove the quotes i get a parsing error at onClick !

What is the right way to deal with this issue which must be a problem for others

Michael Durrant
  • 93,410
  • 97
  • 333
  • 497
  • Are you trying to write [snapshot tests](https://jestjs.io/docs/en/snapshot-testing)? Note that they are not high quality tests, they just detect implementation changes and tell you very little about behaviour. For this specific issue [Function onClick] is the *representation* of a function that was passed as the prop value, not an actual value you can compare - `onClick="{[Function onClick]}"` makes no sense as a prop for the comparison. – jonrsharpe Jun 21 '20 at 07:42

2 Answers2

1

Jest is just a test runner and mocking tool. It can not accesses your react components.

You can try Enzyme lib which is for React.

And you can do something like:

import React from 'react';
import { shallow } from 'enzyme';
import MyComponent from './someComponent'

describe('<MyComponent />', () => {
  const someClickFunc = Jest.fn();
  it('renders xxx components', () => {
    const wrapper = shallow(<MyComponent />);
    expect(wrapper.find(xxx)).to.have.lengthOf(x);
  });

  it('simulates click', () => {
    const wrapper = shallow(<MyComponent onClick={someClicFunc} />);
    wrapper.find(MyComponent).simulate('click');
    expect(someClicFunc).toBeCalled();
    // or find the target dom and compare the value
    // expect(wrapper.find('input').value).toEqaul('somevalue u expected')
  });
SPG
  • 6,109
  • 14
  • 48
  • 79
0

The test is failing because {[Function onClick]} is the string representation of the onClick method, but it isn't actually a string that is rendered. You need to compare the onClick to an actual function during that test.

While you can create a mock of the onClick and use it in the assertion, it is not required. If you do not need (or want) mock the onClick functionality: use expect.any(Function). This will signal to jest that a function is being passed but not require it to be mocked.

For instance, this test will render your component (I'm calling it <PreviousButton>), and get the rendered JSX/TSX. It then asserts that the rendered button has the proper className and type while allowing any function to be passed as the onClick method.

import ShallowRenderer from 'react-test-renderer/shallow';

describe('Previous Button', () => {
  test('renders clickable button', () => {
    const wrapper = ShallowRenderer.createRenderer();
    wrapper.render(<PreviousButton />);

    const result = wrapper.getRenderOutput();
    expect(result).toEqual([
      <button className="btn btn-prev" onClick={expect.any(Function)} type="button">Prev</button>
    ]);
  });
});

I used the Shallow Renderer from the React Testing Library (17.0.2+) since it now recommended over Enzyme for later versions of React. react-test-renderer needs to be installed via npm/yarn before use.

TheLandolorien
  • 568
  • 4
  • 11