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

Enzyme's wrapper.state() returns "null" when use react-onclickoutside #133

Closed
fupslot opened this issue Sep 19, 2016 · 15 comments
Closed

Enzyme's wrapper.state() returns "null" when use react-onclickoutside #133

fupslot opened this issue Sep 19, 2016 · 15 comments

Comments

@fupslot
Copy link

fupslot commented Sep 19, 2016

I use enzyme to test React components.
Recently, I've encountered a problem while testing some of my components where I used react-onclickoutside.

See following example.

// component.js - Define a basic React component.
export default class Component extends React.Component {
  constructor() {
    super();
    this.state = { value: 'Pineapple' };
  }

  // required by react-onclickoutside
  handleClickOutside() { }

  render() {
    return <h3>{ this.state.value }</h3>;
  }
}
// component.spec.js
import { mount } from 'enzyme';
import Component from '../component';

// This test will pass just fine
it('Component', function() {
  const wrapper = mount(<Component />);
  expect(typeof wrapper.state()).toEqual('object'); // 
  expect(wrapper.state().value).toEqual('Pineapple');
});


// Wrap Component using `react-onclickoutside`
const Enhancer = onClickOutside(Component);

// This test will fail
it('Enhancer', function() {
  const wrapper = mount(<Enhancer />);
  expect(typeof wrapper.state()).toEqual('object'); // throws an error. state = null
  expect(wrapper.state().value).toEqual('Pineapple');
});

screen shot 2016-09-19 at 13 09 33

As you can see from the example above. Wrapping Component into onClickOutside makes wrapper return null instead of a state object.

Any ideas?

@Pomax
Copy link
Owner

Pomax commented Sep 19, 2016

I hadn't even heard of Enzyme before now so unfortunately I think you might be more qualified than I am when it comes to knowing what's happening here =(

Might be something the Enzyme project maintainers can shed light on; if they have a github repo you can file an issue and then mention this one to set up an automatic cross-link

@Pomax
Copy link
Owner

Pomax commented Oct 18, 2016

closing this due to inactivity, but feel free to reopen or refile if there is new information

@Pomax Pomax closed this as completed Oct 18, 2016
@ammmze
Copy link

ammmze commented Oct 24, 2016

Bummer...i'm also experiencing this. Trying to write some unit tests on my react component using react-onclickoutside the the call to wrapper.state() returns null, but take out the onclickoutside stuff and it works properly. I'm not sure how to solve it yet.

@Pomax
Copy link
Owner

Pomax commented Oct 25, 2016

Maybe @lelandrichardson or @ljharb have seem this before and can shed light on what's wrong when you encounter this (might even warrant a little troubleshooting section on http://airbnb.io/enzyme/ but that's well beyond the scope of my involvement...)

@ammmze
Copy link

ammmze commented Oct 25, 2016

So far, I've found one workaround (by modifying this project).

In the componentDidMount, I use the following line:

this.state = instance.state;

Essentially setting this wrapper's state object to reference the state of the child instance (i.e. the real component).

@ammmze
Copy link

ammmze commented Oct 25, 2016

Reading more about similar scenarios here...sounds like its recommended to export the unwrapped class and just do tests around that. Then essentially you can have another export that contains the wrapped version.

@Pomax
Copy link
Owner

Pomax commented Oct 25, 2016

In that case you have getInstance() available on the wrapped component. Give that a shot and if that works we can come up with some troubleshooting text to add to the README.md for enzyme users.

@Pomax
Copy link
Owner

Pomax commented Dec 20, 2016

@ammmze did getInstance work for you? If so, I'd like to update the README.md so that others benefit from an explanation.

@jochenberger I see a merged PR, is any of the work done there of the kind that requires code changes in this library?

@jochenberger
Copy link
Contributor

@Pomax no, no changes are required, I only referenced this issue because I somehow had to work around it in the PR.

@Pomax
Copy link
Owner

Pomax commented Dec 27, 2016

ah, I see. Thanks for replying!

@Pomax
Copy link
Owner

Pomax commented Mar 28, 2017

closing this for now as it's been a few months and despite ~20k installs a day no one seems to have run into this as a problem large to +1 in the last three months. Should it pop again in the future, work can be done in that future issue.

@Pomax Pomax closed this as completed Mar 28, 2017
@ragesoss
Copy link

@Pomax that getInstance() is what I needed for an enzyme test of a component that uses onClickOutside: WikiEducationFoundation/WikiEduDashboard@462411a

Thanks for maintaining this component, which works really nicely in my project!

@abdennour
Copy link

If you have :

/*MyComponent.js*/
//....
export default ClickedOutSide(MyComponent);

Add another line of export :

/*MyComponent.js*/
//....
export { MyComponent }; // This export is useful in unit-tests 😉
export default ClickedOutSide(MyComponent);

Then in your test/spec file :

import { MyComponent } from './MyComponent';
// and NOT [  import  MyComponent  from './MyComponent'; ]

@ljharb
Copy link

ljharb commented Nov 12, 2017

@abdennour I strongly discourage doing that; that's what .dive() is for. You should never need to export a wrapped component just for tests - in fact, any character of production code you write solely for testing is a code smell.

@dabit1
Copy link

dabit1 commented Feb 1, 2018

I finally found a very good solution to get a wrapper from a decorated component. For shallowed components you can use dive() but there is no similar method for mounted components. This is the solution I did:

const wrapper = mount(shallow(<MyComponent />).get(0))

Works like a charm :)

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

8 participants