Enzyme: Testing interactive components

Created on 1 Mar 2016  路  17Comments  路  Source: enzymejs/enzyme

I'm trying to test a form containing a date-picker from material-ui. The test would need to do something along these lines:

  1. Simulate a click in the input field
  2. Wait for the dialog to open
  3. Click on a day in the date-picker-dialog
  4. Click on the OK button
  5. Check if the onChange event has been fired

Is this doable with enzyme or should this rather be done using something like selenium?

question

Most helpful comment

I wonder if it's worth us trying to call the method on props if it doesn't exist within the react ecosystem.

We get a lot of these 3rd party lib questions like this where simulating a prop "event" _doesn't work._

// psuedo code
simulate(eventName, args) {
  const onEventName = normalizeEvent(eventName);

  if (reactEvents[eventName]) {
    return Simulate(eventName);
  }

  if (this.props[onEventName]) {
    return this.props[onEventName](args);
  }

  // else
  throw new Error;
}

All 17 comments

Looks doable. Although, it seems like you'd be testing some of the internals of the date-picker component which is likely tested internally on their side. So I'm not sure you need to test all of that, but maybe just the last part.

I have similar challenge with testing multiselect (checkboxes inside Popover). I can open it, but cant access the checkbox with:

component.find('.multiselect-btn').find('Checkbox').simulate('click');

Same here:

  it('tests a checkbox', () => {
    const wrapper = mount(
      <input type='checkbox' />
    );

    expect(wrapper.find('input').get(0).checked).toBeFalsy();
    wrapper.find('input').simulate('click');
    expect(wrapper.find('input').get(0).checked).toBeTruthy();
  })

returns

Expected value to be truthy, instead received
      false

Doing:

  it.only('test a checkbox', () => {
    const wrapper = mount(
      <input type='checkbox' onClick={() => console.log('clicked')} />
    );

    expect(wrapper.find('input').get(0).checked).toBeFalsy();
    wrapper.find('input').simulate('click');
    expect(wrapper.find('input').get(0).checked).toBeTruthy();
  })

will log "clicked" in the console as expected though

I'm trying to test the material-ui Checkbox with enzyme.
simulate('click') doesn't call the onCheck method, while doing simulate('check') returns the error: ReactWrapper::simulate() event 'check' does not exist .

Is onCheck part of react?

onCheck is not a valid event callback in react: https://facebook.github.io/react/docs/events.html

I wonder if it's worth us trying to call the method on props if it doesn't exist within the react ecosystem.

We get a lot of these 3rd party lib questions like this where simulating a prop "event" _doesn't work._

// psuedo code
simulate(eventName, args) {
  const onEventName = normalizeEvent(eventName);

  if (reactEvents[eventName]) {
    return Simulate(eventName);
  }

  if (this.props[onEventName]) {
    return this.props[onEventName](args);
  }

  // else
  throw new Error;
}

enzyme is testing for _React_, not testing for "insert arbitrary jsx lib here".

I'd recommend unit testing onCheck, and then asserting that the onCheck prop calls your unit-tested function, rather than worrying about trying to integration-test your lib.

@blainekasten @ldabiralai Though onCheck itsn't a valid callback, it acts like a callback in material-ui. It gets an event as an argument just like a valid event. As you suggested (If I understood), I can separate my logic and the event system, but this is true for valid events also.

I like this library, and think that many users face this problem cause 3rd libraries are very common. So it would be nice to implement @blainekasten's suggestion. Is a contribution of this functionality would be accepted?

I don't think "very" common is something that can be claimed; this is the first issue I've seen where someone was using a non-react jsx framework with enzyme.

If we did want to support this, then instead of just allowing any arbitrary method - which for the vast majority of jsx users who use React, could be a bug - I'd want an explicit opt-in for additional methods. I'm not sure what that might look like in a practical sense to enable all of material-ui's deviances from React (or all of whichever framework), and I'm not sure it's worth the added complexity in enzyme.

@blainekasten hm, #400 is about normal react; #147 is about custom events, which is normal react; #572 and #607 are about trying to trigger non-event callbacks with .simulate, which is normal react. What am I missing?

400 is not normal react, it's react-select and triggering their components onChange prop.

147 is about custom events, but that's basically the same as #400. Custom events in react are just props with a semi standard naming scheme, which are #572 and #607.

If i'm beating a dead horse I'll drop it. :)

@blainekasten react-select is just a component, it's not a React alternative. Perhaps I'm misunderstanding what material-ui is, but I've understood it to be something you use instead of React.

My comment is saying that if you're using simulate, it should be for native events only - and if you're using something that's not React, such that you have arbitrary event names, that by default these should not work - since for the majority (who uses normal React + html events), they will be bugs.

Perhaps I'm misunderstanding what material-ui is, but I've understood it to be something you use instead of React.

Material UI is just a component library built on top of React.

@Aweary thanks - i was basing my assumption on https://github.com/airbnb/enzyme/issues/222#issuecomment-256620820, which implies that a "click" event would fire something other than an "onClick" handler.

I got the same issue, anyone get the solution?

Was this page helpful?
0 / 5 - 0 ratings