Skip to content

Commit

Permalink
[New] render: add support for context
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed Feb 27, 2017
1 parent 4579fe2 commit 7f21229
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 2 deletions.
15 changes: 14 additions & 1 deletion docs/api/render.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ constructors.
import { render } from 'enzyme';

describe('<Foo />', () => {

it('renders three `.foo-bar`s', () => {
const wrapper = render(<Foo />);
expect(wrapper.find('.foo-bar')).to.have.length(3);
Expand All @@ -30,5 +29,19 @@ describe('<Foo />', () => {
expect(wrapper.text()).to.contain("unique");
});

it('can pass in context', () => {
const SimpleComponent = React.createClass({
contextTypes: {
name: React.PropTypes.string,
},
render() {
return <div>{this.context.name}</div>;
},
});

const context = { name: 'foo' };
const wrapper = render(<SimpleComponent />, { context });
expect(wrapper.text()).to.equal('foo');
});
});
```
29 changes: 28 additions & 1 deletion src/render.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import React from 'react';
import objectAssign from 'object.assign';
import cheerio from 'cheerio';
import { renderToStaticMarkup } from './react-compat';

Expand All @@ -11,9 +13,34 @@ import { renderToStaticMarkup } from './react-compat';
* thus I'd like to keep this API in here even though it's not really "ours".
*
* @param node
* @param options
* @returns {Cheerio}
*/
export default function render(node) {

function createContextWrapperForNode(node, context, childContextTypes) {
class ContextWrapper extends React.Component {
getChildContext() {
return context;
}
render() {
return node;
}
}
ContextWrapper.childContextTypes = childContextTypes;
return ContextWrapper;
}

export default function render(node, options = {}) {
if (options.context && (node.type.contextTypes || options.childContextTypes)) {
const childContextTypes = objectAssign(
{},
node.type.contextTypes || {},
options.childContextTypes,
);
const ContextWrapper = createContextWrapperForNode(node, options.context, childContextTypes);
const html = renderToStaticMarkup(<ContextWrapper />);
return cheerio.load(html).root();
}
const html = renderToStaticMarkup(node);
return cheerio.load(html).root();
}
57 changes: 57 additions & 0 deletions test/staticRender-spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import { expect } from 'chai';
import { describeWithDOM, describeIf } from './_helpers';
import { render } from '../src/';
import { REACT013 } from '../src/version';

describeWithDOM('render', () => {
describeIf(!REACT013, 'context', () => {
it('can pass in context', () => {
const SimpleComponent = React.createClass({
contextTypes: {
name: React.PropTypes.string,
},
render() {
return <div>{this.context.name}</div>;
},
});

const context = { name: 'foo' };
const wrapper = render(<SimpleComponent />, { context });
expect(wrapper.text()).to.equal('foo');
});
it('can pass context to the child of mounted component', () => {
const SimpleComponent = React.createClass({
contextTypes: {
name: React.PropTypes.string,
},
render() {
return <div>{this.context.name}</div>;
},
});
const ComplexComponent = React.createClass({
render() {
return <div><SimpleComponent /></div>;
},
});

const childContextTypes = {
name: React.PropTypes.string.isRequired,
};
const context = { name: 'foo' };
const wrapper = render(<ComplexComponent />, { context, childContextTypes });
expect(wrapper.children()).to.have.length(1);
expect(wrapper.children().first().text()).to.equal('foo');
});
it('should not throw if context is passed in but contextTypes is missing', () => {
const SimpleComponent = React.createClass({
render() {
return <div>{this.context.name}</div>;
},
});

const context = { name: 'foo' };
expect(() => render(<SimpleComponent />, { context })).to.not.throw(Error);
});
});
});

0 comments on commit 7f21229

Please sign in to comment.