Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to change a checkbox value using simulate api? #216

Closed
sathishsoundharajan opened this issue Feb 26, 2016 · 25 comments
Closed

How to change a checkbox value using simulate api? #216

sathishsoundharajan opened this issue Feb 26, 2016 · 25 comments

Comments

@sathishsoundharajan
Copy link

Hi,

I am using jsdom with enzyme.

When the component mounts first time it is set to "checked":"checked", the input element has "onChange" event which will change the state and re-renders the check box as uncheked.

if(this.state.field_value === "True"){
<input 
     type="checkbox"
     className="form-control"
     name={this.state.field_name}
     title={this.state.help_text}
     checked="checked"
      onChange={this.handleChange} />
}else{
<input 
     type="checkbox"
     className="form-control"
     name={this.state.field_name}
     title={this.state.help_text}
      onChange={this.handleChange} />
}
onChange function:

handleChange: function(event) {
    var checked = event.target.checked ? "True":"False";
    this.setState({field_value:checked});
  }

Now to test this with enzyme, I tried doing this.

  it('Renders and Simulates Click Event ', () => {

    const CheckBoxProps =  {
      "field_name": "Howareyou",
      "input_type": "Checkbox"
      "field_value": "True"
    };

    const Wrapper = mount(<CheckBox
      dataObj={CheckBoxProps} />);

      // This one works  -- But doesn't seem like a simulation..
      expect(Wrapper.find('input[type="checkbox"][checked="checked"]')).to.have.length(1);
      Wrapper.setState({'field_value':'false'})
      expect(Wrapper.find('input[type="checkbox"][checked="checked"]')).to.have.length(0);

      // This one not works
      Wrapper.find('input[type="checkbox"][checked="checked"]').simulate('change');
      console.log(Wrapper.find('input[type="checkbox"][checked="checked"]')); // still length is 1

  });

Even this also not working,

      Wrapper.find('input[type="checkbox"]').simulate('change');
      expect(Wrapper.state('field_value')).to.equal("False");

P.S : How to do simulation for all the events like input type text,radio,textarea etc.. is there any resource available.

@sathishsoundharajan
Copy link
Author

@marlonbernardes I need to make it work for change event.. Well, will give a try for 'click'.

@sathishsoundharajan
Copy link
Author

@marlonbernardes Still not working...

@marlonbernardes
Copy link
Contributor

You should bind the value of this when you call your handleChange function, because it's not pointing to your react component:

 onChange={this.handleChange.bind(this)}  

Try this and let me know if it works for you. I also have some tips on how to make your component's code more concise, but lets focus on one thing at a time.

@sathishsoundharajan
Copy link
Author

@marlonbernardes Sorry for the late reply. Still it is not working... Can you post me a sample of how to test a checkbox with jsdom and enzyme ? That would be a great help.

@ljharb
Copy link
Member

ljharb commented Mar 2, 2016

(of course, you shouldn't create functions and pass them as props in the render path - so you'd want this.handleChange = this.handleChange.bind(this) in your constructor)

@sathishsoundharajan
Copy link
Author

@ljharb @marlonbernardes This is the full code https://gist.github.com/bboysathish/8c78d6c295c0613d08b6.

Edit: That's not the best code though.. But it should work.

The following is the error,

 1) checkbox Renders and Simulates Click Event :

      AssertionError: expected 'True' to equal 'False'
      + expected - actual

      -True
      +False

      at Context.<anonymous> (checkbox_component_test.js:25:47)
      at callFn (C:\Users\sathishkumar_so\Downloads\SSBT\Admin-UI\Feb24\Code\node_modules\mocha\lib\runnable.js:315:21)
      at Test.Runnable.run (C:\Users\sathishkumar_so\Downloads\SSBT\Admin-UI\Feb24\Code\node_modules\mocha\lib\runnable.js:308:7)
      at Runner.runTest (C:\Users\sathishkumar_so\Downloads\SSBT\Admin-UI\Feb24\Code\node_modules\mocha\lib\runner.js:422:10)
      at C:\Users\sathishkumar_so\Downloads\SSBT\Admin-UI\Feb24\Code\node_modules\mocha\lib\runner.js:533:12
      at next (C:\Users\sathishkumar_so\Downloads\SSBT\Admin-UI\Feb24\Code\node_modules\mocha\lib\runner.js:342:14)
      at C:\Users\sathishkumar_so\Downloads\SSBT\Admin-UI\Feb24\Code\node_modules\mocha\lib\runner.js:352:7
      at next (C:\Users\sathishkumar_so\Downloads\SSBT\Admin-UI\Feb24\Code\node_modules\mocha\lib\runner.js:284:14)
      at Immediate._onImmediate (C:\Users\sathishkumar_so\Downloads\SSBT\Admin-UI\Feb24\Code\node_modules\mocha\lib\runner.js:320:5)

@ljharb
Copy link
Member

ljharb commented Mar 2, 2016

@bboysathish calling .simulate('change') doesn't change the value though - have you tried .simulate('change', { target: { checked: true } }) or something similar?

@sathishsoundharajan
Copy link
Author

@ljharb Worked like a charm, Thanks Wrapper.find('input[type="checkbox"]').simulate('change',{ target: { checked: false } }); . But is there a documentation for this target argument ? or list of arguments I can pass to simulate. As per this documentation, http://airbnb.io/enzyme/docs/api/ReactWrapper/simulate.html. I don't see anything.

@ljharb
Copy link
Member

ljharb commented Mar 2, 2016

@sathishsoundharajan
Copy link
Author

@ljharb R u referring this ...args (Any [optional]): A mock event object that will get passed through to the event handlers.? Can you please point me, how does mock event object will look like ? (Kinda what are the properties it accepts)

@ljharb
Copy link
Member

ljharb commented Mar 2, 2016

@bboysathish it's any object you like. whatever you pass there, will be passed as arguments to the event handler. there's no magic.

@sathishsoundharajan
Copy link
Author

@ljharb So, for input[type="text"] to simulate a change event with some text I can do something like this?
Wrapper.find('input[type="text"]').simulate('change',{ target: { value: "I need model target object :)" } })

@ljharb
Copy link
Member

ljharb commented Mar 2, 2016

Looks right to me - try it and see! :-)

@sathishsoundharajan
Copy link
Author

Great!! Will try.. Thanks @ljharb ...

@besrabasant
Copy link

besrabasant commented Mar 1, 2018

Wrapper.find('input[type="checkbox"]').simulate('change',{ target: { checked: true } });

Now, this isn't working for me.

@Burkazoid
Copy link

I hit some problems when I was using e.currentTarget in the onChange function. If I specified .simulate('change',{ currentTarget: { checked: true } });, it seemed to get overwritten by the time it reached the onChange function, giving unexpected results. Changing currentTarget to target in both the onChange function and the test fixed this.

@yoni-tock
Copy link

In case someone else hits this. If you're using typescript, React.SyntheticEvent doesn't have event.target.checked. Given that I'd like my tests to work, I don't have a solution to this other than casting in the event handler :(.

@luyizhao
Copy link

As a variation on @Burkazoid's suggestion, a workaround that doesn't require changing currentTarget to target in the code would be to use onChange instead of simulate in your tests and pass in your desired event, i.e.:

.prop('onChange')({currentTarget: { checked: false }})

@HunderlineK
Copy link

HunderlineK commented Aug 29, 2018

Is there a way to simulate checking a checkbox that is within in a select?

Edit: My use case is that I have a select with a bunch of checkboxes in them; instead of passing the change event directly to the select, I wanted to simulate clicking the checkboxes, because I wanted to make sure the values that I have passed to the checkboxes are correct.

The current test setup that I have has two steps: 1. Test passing a change event to select 2. Getting all of the checkboxes and testing the props().value; in a nutshell, I want to combine these two together.

The problem that I have is that the rendered DOM of select does not have any checkboxes, I assume because it is hidden unless you click on it, but I simulating click on the select does not open it.

I am using Material-UI components, but that shouldn't change the scenario.

@ljharb
Copy link
Member

ljharb commented Aug 29, 2018

@HunderlineK no, you can't simulate anything. You can explicitly invoke the onClick or onChange prop; you can explicitly set the state so that it's open, but what you want to do requires a full browser integration test, and can't be done properly with enzyme.

@Duongasaur

This comment has been minimized.

@ljharb

This comment has been minimized.

@surya-art
Copy link

     wrapper = mount(<customCheckboxToConfigure store={store}/>);
  wrapper.setProps({checked:false});
  wrapper.find('input[type="checkbox"]').simulate('change', {target:{checked:true}})
  expect(wrapper.state(checked)).toBe(true);

@ljharb this shows an error like

Method “simulate” is only meant to be run on a single node. 0 found instead.

@ljharb
Copy link
Member

ljharb commented Nov 26, 2019

@surya-art sounds like there's no checkboxes then. Remember to wrapper.update() after the setProps, and then what does wrapper.debug() print out?

(Please file a new issue with your comment and your response, if that doesn't solve it for you)

@ashrash
Copy link

ashrash commented May 29, 2020

As a variation on @Burkazoid's suggestion, a workaround that doesn't require changing currentTarget to target in the code would be to use onChange instead of simulate in your tests and pass in your desired event, i.e.:

.prop('onChange')({currentTarget: { checked: false }})

change currentTarget to target if you're using .prop

.prop('onChange')({target: { checked: false }})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests