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

Components returning null with different results for render and shallow #139

Closed
ayrton opened this issue Jan 26, 2016 · 2 comments
Closed

Comments

@ayrton
Copy link
Contributor

ayrton commented Jan 26, 2016

I came across an interesting inconsistency, when using enzyme and chai-enzyme.

I'll demonstrate this with code, here's a simplified version of my ContentToggle component:

export default class ContentToggle extends React.Component {
  props: {
    component: Function|string,
    content: ?ReactElement,
    options: ?Array<ReactElement>,
  };

  render(): ?ReactElement {
    const {content, options, ...otherProps} = this.props;

    if (!content && !options) {
      return null;
    }

    return React.createElement('a', { href: '#', ...otherProps });
  }
}

Important to note is that I either need to pass on content or options as props or otherwise it will return null.

My initial tests I wrote:

describe(ContentToggle.displayName, () => {
  it('renders children if content is passed', () => {
    const children = 'FOO';
    const el = render(<ContentToggle content={<span />}>{children}</ContentToggle>);

    expect(el).to.have.text(children);
  });

  it('renders children if options are passed', () => {
    const children = 'FOO';
    const el = render(<ContentToggle options={[]}>{children}</ContentToggle>);

    expect(el).to.have.text(children);
  });

 it('renders nothing if no content or options are passed', () => {
    const children = 'FOO';
    const el = render(<ContentToggle>{children}</ContentToggle>);

    expect(el).to.not.have.text(children);
    expect(el).to.be.blank();
  });
});

The first two tests passed, but the third one did not:

  1) undefined renders nothing if no content or options are passed:
     AssertionError: expected the node in <??? /> to be empty

     HTML:

     <noscript></noscript>

When I change the 3rd test to use shallow vs render this test passes, or I can write the test as follow:

describe(ContentToggle.displayName, () => {
  it('renders nothing if no content or options are passed', () => {
    const children = 'FOO';
    const el = render(<ContentToggle>{children}</ContentToggle>);

    expect(el).to.not.have.text(children);
    expect(el.find('noscript')).to.be.blank();
  });
});

I would have expected expect(el).to.be.blank(); to work with both render as with shallow (or mount for that matter), or at least consistent behaviour across all 3.

We can either fix this on chai-enzyme level or in enzyme, what do you guys think?

/cc @vesln @ljharb @lelandrichardson

@lelandrichardson
Copy link
Collaborator

This is interesting and something I haven't considered yet. React wants every node in the tree to have an actual node in the DOM, so it renders null as <noscript></noscript>. However, cheerio doesn't have any knowledge of this and sees <noscript> as something that is non-empty.

It seems reasonable to have chai-enzyme treat this as a special case, however making cheerio think about things differently would be a lot of work.

@ayrton
Copy link
Contributor Author

ayrton commented Jan 27, 2016

Will tackle this in producthunt/chai-enzyme#17, thanks for your input Leland.

@ayrton ayrton closed this as completed Jan 27, 2016
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

2 participants