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

shallow rendering / testing components with 'render callbacks' #4127

Closed
threepointone opened this issue Jun 15, 2015 · 3 comments
Closed

shallow rendering / testing components with 'render callbacks' #4127

threepointone opened this issue Jun 15, 2015 · 3 comments

Comments

@threepointone
Copy link
Contributor

based on this comment and this thread, starting this thread to discuss how to test components with 'render callbacks'.

Consider the following 'app'.

class Double{
  render(){
    return this.props.children(this.props.value * 2);
  }
}

class App extends React.Component{
  render(){
    return <Double value={this.props.input}>{
      doubled => <div>{doubled}</div>
    }</A>;
  }
}

React.render(<App input={10}/>, el);  // will output '20', as expected

Now, if we wanted to test this, we could write something like -

var stateful = TestUtils.renderIntoDocument(<App input={50}/>);

var div = TestUtils.findRenderedDOMComponentWithTag(stateful, 'div');
div.getDOMNode().textContent.should.eql('100');

However, we can't test beyond the callback boundary with ReactShallowRenderer.

// this doesn't work, of course
TestUtils.createRenderer().render(<App input={50}/>).getRenderOutput()
  .should.eql(<Double value={this.props.input}>
    <div>{100}</div>
  </A>)

Unclear how to approach this, frankly. Should ShallowRenderer 'recognize' components like this? Or should they be marked with a flag? (this.rendersCallback = true ?). The only workaround for now is to not use the ShallowRenderer :(

/cc @pspeter3

@pspeter3
Copy link

The way that we are handling it is to avoid render callbacks entirely and just use React.cloneElement. This way you must pass a component to the boundary. This allows the developer to test the parent and the child separately knowing that there will not be arbitrary code being executed.

@sophiebits
Copy link
Collaborator

This doesn't work because after one shallow render, the rendered output is

<Double value={50}>{doubled => <div>{doubled}</div>}</Double>

and if that were rendered, you'd get

<div>{100}</div>

(At no point would you have <Double value={50}><div>{100}</div></Double>.)

You could try

var double =TestUtils.createRenderer().render(<App input={50}/>).getRenderOutput();

and verify that double.type is Double and that double.props.children(50) is <div>{100}</div> or something along those lines.

Let me know if that doesn't make sense.

@threepointone
Copy link
Contributor Author

Hi @spicyj, thanks for the response. That would 'work', but it would still require manually doing so for each case. I was hoping for some help in writing a somewhat-shallow renderer that could 'recognize' when a rendered child has a render-callback, and just render 'through'. I started with a naive implementation that just swapped in .children on these element, but it did't work. I'll investigate more, thank you for your time.

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

3 participants