diff --git a/docs/api/mount.md b/docs/api/mount.md index 8a6ae6468..d862cc313 100644 --- a/docs/api/mount.md +++ b/docs/api/mount.md @@ -45,6 +45,7 @@ describe('', () => { 2. `options` (`Object` [optional]): - `options.context`: (`Object` [optional]): Context to be passed into the component - `options.attachTo`: (`DOMElement` [optional]): DOM Element to attach the component to. +- `options.childContextTypes`: (`Object` [optional]): Merged contextTypes for all children of the wrapper. #### Returns diff --git a/src/ReactWrapperComponent.jsx b/src/ReactWrapperComponent.jsx index a599be69d..be63c27ed 100644 --- a/src/ReactWrapperComponent.jsx +++ b/src/ReactWrapperComponent.jsx @@ -71,12 +71,18 @@ export default function createWrapperComponent(node, options = {}) { }, }; - if (options.context && node.type.contextTypes) { + if (options.context && (node.type.contextTypes || options.childContextTypes)) { // For full rendering, we are using this wrapper component to provide context if it is - // specified in both the options AND the child component defines `contextTypes` statically. + // specified in both the options AND the child component defines `contextTypes` statically + // OR the merged context types for all children (the node component or deeper children) are + // specified in options parameter under childContextTypes. // In that case, we define both a `getChildContext()` function and a `childContextTypes` prop. + const childContextTypes = node.type.contextTypes || {}; + if (options.childContextTypes) { + objectAssign(childContextTypes, options.childContextTypes); + } objectAssign(spec, { - childContextTypes: node.type.contextTypes, + childContextTypes, getChildContext() { return this.state.context; }, diff --git a/src/__tests__/ReactWrapper-spec.js b/src/__tests__/ReactWrapper-spec.js index f322a79ea..7ad458d6f 100644 --- a/src/__tests__/ReactWrapper-spec.js +++ b/src/__tests__/ReactWrapper-spec.js @@ -28,6 +28,28 @@ describeWithDOM('mount', () => { 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
{this.context.name}
; + }, + }); + const ComplexComponent = React.createClass({ + render() { + return
; + }, + }); + + const childContextTypes = { + name: React.PropTypes.string.isRequired, + }; + const wrapper = mount(, { context, childContextTypes }); + expect(wrapper.find(SimpleComponent)).to.have.length(1); + }); + it('should not throw if context is passed in but contextTypes is missing', () => { const SimpleComponent = React.createClass({ render() {