Detect synthetic click in React during testing with Jest/Enzyme

陌路散爱 提交于 2019-12-24 06:48:54

问题


I am building an app with React. I am hiding a file input element (<input type="file"/>) "behind" a react-bootstrap Button to be able to control styling. So, when the button is clicked I turn around and fire a synthetic click event on the text input element, as shown below.

class OpenFileButton extends React.Component {
  ...
  clickHandler() {
    this.refs['input'].click();
  }

  render() {
    return (
      <ButtonGroup>
        <div>
          <input type="file" onChange={this.props.someCallback}
            ref="input" style={{display: 'none'}}/>
          <Button onClick={this.clickHandler}>Open File</Button>
        </div>
      </ButtonGroup>
    );
  }
}

I want to be able to test this with Jest/Enzyme. However, while I can simulate a click event on the button, I haven't figured out how to detect a synthetic click event on the file input element.

I have tried using Jest/Enzyme to mock the click method on the input element.

const component = mount(<OpenFileButton/>);
const fileInput = component.find('input');
const button    = component.find('Button');
fileInput.click = jest.fn();
button.simulate('click');
expect(fileInput.click).toHaveBeenCalled();

However, mocking the click method this way does not work. I also can't add an onClick attribute, i.e. fileInput.props().onClick = jest.fn() does not work.

This question is about detecting synthetic click events in the code itself, not in the test code, and so is not relevant.

So, how can I detect a (synthetic) click event on a DOM element using Jest/Enzyme?


回答1:


<input /> or this.refs.input is an instance of HTMLInputElement.

Then you can test if HTMLInputElement.prototype.click is called .

Using sinon you will have :

import sinon from 'sinon';
import {mount} from 'enzyme';

const clickInputSpy = sinon.spy(HTMLInputElement.prototype, 'click')
const component = mount(<OpenFileButton/>);

const button    = component.find('Button');

button.simulate('click');
expect(clickInputSpy.called).toBeTruthy();
clickInputSpy.restore();

const clickInputSpy = sinon.spy(HTMLInputElement.prototype, 'click');


console.log(
 'Is <input /> clicked ? ', clickInputSpy.called 
);
document.querySelector('input').click();


console.log(
 'Is <input /> clicked ? ', clickInputSpy.called 
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>


<script src="https://cdnjs.cloudflare.com/ajax/libs/sinon.js/1.15.4/sinon.min.js"></script>

<input />



回答2:


The solution here involves spying on the click method of the particular file input element that I'm interested in. I can thus check to see if this file-input-element-click-spy was called after a click is simulated on the button element, as follows:

const openFileButtonWrapper = mount(<OpenFileButton/>);
const buttonWrapper = openFileButtonWrapper.find(Button);
const fileInputWrapper = openFileButtonWrapper.find('input [type="file"]');
const fileInput = fileInputWrapper.get(0);
const clickInputSpy = spyOn(fileInput, 'click');
buttonWrapper.simulate('click');
expect(clickInputSpy).toHaveBeenCalled();

The answer by @AbdennourTOUMI used Sinon's spy method which reminded me that Jest uses some Jasmine functionality, including its spyOn method, that isn't obvious from the Jest documentation. So, even though that other answer ended up spying on _all_ input elements, which is not ideal, it did send me in the right direction, so thank you, Adbennour.



来源:https://stackoverflow.com/questions/42600805/detect-synthetic-click-in-react-during-testing-with-jest-enzyme

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!