Skip to content

Commit

Permalink
[Fix] shallow: Share child context logic between shallow and dive
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew Howard authored and ljharb committed Nov 26, 2019
1 parent e57dbe8 commit 696a272
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 13 deletions.
61 changes: 61 additions & 0 deletions packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,67 @@ describe('shallow', () => {
expect(consumer.text()).to.equal('howdy!');
});
});

describe('shallow() on Provider and Consumer', () => {
let Provider;
let Consumer;

beforeEach(() => {
({ Provider, Consumer } = React.createContext('howdy!'));
});

class Consumes extends React.Component {
render() {
return (
<span>
<Consumer>{(value) => <span>{value}</span>}</Consumer>
</span>
);
}
}

class Provides extends React.Component {
render() {
const { children } = this.props;

return (
<Provider value="foo"><div><div />{children}</div></Provider>
);
}
}

class MyComponent extends React.Component {
render() {
return (
<Provides><Consumes /></Provides>
);
}
}

it('works on a Provider', () => {
const wrapper = shallow(<MyComponent />);
const provides = wrapper.find(Provides).dive();
const provider = provides.find(Provider).shallow();
expect(provider.text()).to.equal('<Consumes />');
});

it('always gives the default provider value if shallow() rendering a <Consumer /> directly', () => {
// Diving directly on a consumer will give you the default value
const wrapper = shallow(<MyComponent />);
const consumes = wrapper.find(Consumes).shallow();
const consumer = consumes.find(Consumer).shallow();
expect(consumer.text()).to.equal('howdy!');
});

it('gives the actual <Provider /> value if one dive()s it', () => {
const wrapper = shallow(<MyComponent />);
const provides = wrapper.find(Provides).shallow();
const provider = provides.find(Provider).shallow();
const consumes = provider.find(Consumes).shallow();
const consumer = consumes.find(Consumer).shallow();
expect(consumer.text()).to.equal('foo');
});
});
});

describeIf(is('> 0.13'), 'stateless function components (SFCs)', () => {
Expand Down
33 changes: 20 additions & 13 deletions packages/enzyme/src/ShallowWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,20 @@ function makeShallowOptions(nodes, root, passedOptions, wrapper) {
}


function makeInheritedChildOptions(wrapper, options = {}) {
const childOptions = {
...wrapper[OPTIONS],
...options,
context: options.context || {
...wrapper[OPTIONS].context,
...wrapper[ROOT][CHILD_CONTEXT],
},
};
privateSet(childOptions, PROVIDER_VALUES, wrapper[ROOT][PROVIDER_VALUES]);
return childOptions;
}


/**
* @class ShallowWrapper
*/
Expand Down Expand Up @@ -1280,10 +1294,11 @@ class ShallowWrapper {
* @param {Object} options
* @returns {ShallowWrapper}
*/
shallow(options) {
return this.single('shallow', (n) => (
this.wrap(getAdapter(this[OPTIONS]).nodeToElement(n), null, options)
));
shallow(options = {}) {
return this.single('shallow', (n) => {
const childOptions = makeInheritedChildOptions(this, options);
return this.wrap(getAdapter(this[OPTIONS]).nodeToElement(n), null, childOptions);
});
}

/**
Expand Down Expand Up @@ -1694,15 +1709,7 @@ class ShallowWrapper {
if (!isCustomComponentElement(el, adapter)) {
throw new TypeError(`ShallowWrapper::${name}() can only be called on components`);
}
const childOptions = {
...this[OPTIONS],
...options,
context: options.context || {
...this[OPTIONS].context,
...this[ROOT][CHILD_CONTEXT],
},
};
privateSet(childOptions, PROVIDER_VALUES, this[ROOT][PROVIDER_VALUES]);
const childOptions = makeInheritedChildOptions(this, options);
return this.wrap(el, null, childOptions);
});
}
Expand Down

0 comments on commit 696a272

Please sign in to comment.