enzymejs / enzyme

JavaScript Testing utilities for React
https://enzymejs.github.io/enzyme/
MIT License
19.95k stars 2.01k forks source link

Testing interactive components #222

Open pulse00 opened 8 years ago

pulse00 commented 8 years ago

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?

blainekasten commented 8 years ago

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.

tb commented 8 years ago

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');
mathieuseguin commented 8 years ago

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

leonprou commented 8 years ago

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 .

ljharb commented 8 years ago

Is onCheck part of react?

kevinzwhuang commented 8 years ago

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

blainekasten commented 8 years ago

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;
}
ljharb commented 8 years ago

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.

leonprou commented 8 years ago

@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?

ljharb commented 8 years ago

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 commented 7 years ago

@ljharb this isn't the first:

https://github.com/airbnb/enzyme/issues/400 https://github.com/airbnb/enzyme/issues/147 https://github.com/airbnb/enzyme/issues/572 https://github.com/airbnb/enzyme/issues/607

ljharb commented 7 years ago

@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?

blainekasten commented 7 years ago

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. :)

ljharb commented 7 years ago

@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.

aweary commented 7 years ago

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.

ljharb commented 7 years ago

@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.

github-herve-bourzeix commented 7 years ago

I got the same issue, anyone get the solution?