Enzyme: Testing select element value with enzyme

Created on 12 Apr 2018  路  8Comments  路  Source: enzymejs/enzyme

Hi Ive been struggling with this and cant seem to get it to work.

Im try to test the value of a select element after a simulate.

it('should select transmission',() =>{

  const wrapper = mount(<Transmission/>);
  const select = wrapper.find('select').first();
  select.simulate('change',{target: {value:"manual"}});
  expect(select.props().value).toEqual('manual');
});
const Transmission=(props) =>{
return(

<select name="transmission" onChange={props.handleChange}>
  <option value="automatic">Automatic</option>
  <option value="manual">Manual</option>
</select>
);
}
export default Transmission;

Even if I remove the onChange method from the select, the error is the same:

Expected value to equal:
"manual"
Received:
undefined

Difference:

Comparing two different types of values. Expected string but received undefined.
Appreciate some help.

Most helpful comment

simulate does not actually simulate anything; all it does is invoke a prop for you.

I recommend avoiding it entirely, and doing .prop('onChange')() if that's what you want.

All 8 comments

simulate does not actually simulate anything; all it does is invoke a prop for you.

I recommend avoiding it entirely, and doing .prop('onChange')() if that's what you want.

Excellent solution, @ljharb. Thank you!

@ljharb I've seen you suggest this in various posts but there are times when just running on change is worthless, because this doesnt actually change the value of the select, so if something depends on the value of the selected option that will not work. this is for UNCONTROLLED selects that do not have a value prop. I have state that is bound to the selects state, I do not change this state in the "onChange" method, this is done automagically by HTML when you select an option in an uncontrolled select, this is what will work in those cases:

await act(async () => {
  const option = wrapper.find('.curriculum select option').at(2);
  // actually change the selected value of the select
  option.simulate('click');
  // trigger the change handler, as event propagation is not something enzyme does I believe
  wrapper.find('select').simulate('change', {
    target: { value: option.prop('value') },
  });
});
// update wrapper to reflect these changes
wrapper = await wrapper.update();

@vanor89 i'm not sure what you mean. the onChange indeed does not change the value - the change is what triggers onChange. You, however, can set the value directly, or you can just pass a custom event object into onChange.

You cant set a value of an undefined property. value does not exist in the props of the element, because it is uncontrolled, I only have a defaultValue on it

Right, but in the enzyme tree, you can set the value prop directly on the resulting select, and then invoke onChange. In most cases, you won't need to actually set the value (because you won't be reading it off of the select's ref), so passing it into onChange's event object param would be sufficient.

You cannot set the value prop directly in the resulting select, that throws an error, "value" is undefined.

That is exactly my problem, I am using the selects ref in some testing further on, I have some other selects that populate their options depending on the actual value of the previous selects, if the value of these selects does not change, I cannot expect the other ones to be populated accurately

gotcha. simulate doesn't do that either, though, so either way you have to manually do it.

If you find the select, it's a DOM node - you can .setAttribute('value', 'whatever') directly. Does that not work?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

timhonders picture timhonders  路  3Comments

heikkimu picture heikkimu  路  3Comments

abe903 picture abe903  路  3Comments

amcmillan01 picture amcmillan01  路  3Comments

ahuth picture ahuth  路  3Comments