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

ShallowRenderer not considering contextTypes when rendering children #11862

Closed
Termit1975 opened this issue Dec 15, 2017 · 1 comment
Closed

Comments

@Termit1975
Copy link

Termit1975 commented Dec 15, 2017

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
ShallowRenderer not considering contextTypes.

**Note: I was not able to easily include react-test-renderer in a fiddle so I include a unit test.

   //Context used in shallow and normal rendering
   const context = { appName: 'abc', mode: 'def' };

   class TopLevelComponent extends React.Component {
     render() { return <div>{this.props.children}</div>; }
     getChildContext() { return context; }
   }
   TopLevelComponent.childContextTypes = { appName: PropTypes.string, mode: PropTypes.string };

   class Component1 extends React.Component {
     render() { return <div mode={this.context.mode} appname={this.context.appName}/>; }
   }
   Component1.contextTypes = { appName: PropTypes.string };

   //Use shallow renderer and assert that we got appName but not mode
   const shallowComponent1 = new ShallowRenderer().render(<Component1/>, context);
   expect(shallowComponent1.props.appname).toBe('abc'); //Pass
   expect(shallowComponent1.props.mode).toBeUndefined(); //This expectation fails

   //Render Component1 under a component with childContext
   const wrappedEl = React.createElement(() => <TopLevelComponent><Component1/></TopLevelComponent>);
   const domNode = document.createElement('div');
   ReactDOM.render(wrappedEl, domNode);
   const html = domNode.innerHTML;    
   expect(html).toContain('abc'); //Pass
   expect(html).not.toContain('def'); //Pass: As you can see this property is undefined

What is the expected behavior?
I would expect that when rendering Component1 with ShallowRenderer, render method would check Component1.contextTypes and mask any property that is not specified there just like function getMaskedContext(workInProgress, unmaskedContext) does in react-dom library.

I fixed this behavior by changing render method like this: (inpired again by getMaskedContext)

  const oldRender = ShallowRenderer.prototype.render;
  ShallowRenderer.prototype.render = function render(element) {

    const unmaskedContext = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

    if (element && element.type && unmaskedContext) {
      if (element.type.hasOwnProperty('contextTypes')) {
        const context = {};
        for (const key in element.type.contextTypes) {
          context[key] = unmaskedContext[key];
        }

        arguments[1] = context;
      }
    }

    return oldRender.apply(this, arguments);
  };

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
This bug is for version 16. We are upgrading from React 15, we were using enzyme shallow rendering and this wasn't the behavior. It is difficult to say which part of the code has changed between React 15 and enzyme at this point but my code sample includes only code from react libraries.

@gaearon
Copy link
Collaborator

gaearon commented Dec 15, 2017

Yeah, this looks like a minor bug. Happy to accept a fix for it but this probably won't be a priority as we're working on the new context API anyway: reactjs/rfcs#2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants