Skip to content

Commit

Permalink
[new] shallow: Support rendering and dive()ing createContext()
Browse files Browse the repository at this point in the history
…providers and consumers
  • Loading branch information
minznerjosh committed Apr 3, 2019
1 parent 0b3b142 commit 8fcf010
Show file tree
Hide file tree
Showing 3 changed files with 279 additions and 14 deletions.
201 changes: 201 additions & 0 deletions packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
Expand Up @@ -270,6 +270,55 @@ describe('shallow', () => {
expect(wrapper.text()).to.equal('Context says: I can be set!');
});

describeIf(is('>= 16.3'), 'with createContext()', () => {
let Context1;
let Context2;

function WrappingComponent(props) {
const { value1, value2, children } = props;
return (
<Context1.Provider value={value1}>
<Context2.Provider value={value2}>
{children}
</Context2.Provider>
</Context1.Provider>
);
}

function Component() {
return (
<Context1.Consumer>
{value1 => (
<Context2.Consumer>
{value2 => (
<div>Value 1: {value1}; Value 2: {value2}</div>
)}
</Context2.Consumer>
)}
</Context1.Consumer>
);
}

beforeEach(() => {
Context1 = createContext('default1');
Context2 = createContext('default2');
});

it('renders', () => {
const wrapper = shallow(<Component />, {
wrappingComponent: WrappingComponent,
wrappingComponentProps: {
value1: 'one',
value2: 'two',
},
});
const consumer1 = wrapper.find(Context1.Consumer).dive();
const consumer2 = consumer1.find(Context2.Consumer).dive();

expect(consumer2.text()).to.equal('Value 1: one; Value 2: two');
});
});

it('throws an error if the wrappingComponent does not render its children', () => {
class BadWrapper extends React.Component {
render() {
Expand Down Expand Up @@ -384,6 +433,158 @@ describe('shallow', () => {
expect(wrapper.find('.child2')).to.have.lengthOf(1);
});

describeIf(is('>= 16.3'), 'createContext()', () => {
describe('rendering as root:', () => {
let Context;

beforeEach(() => {
Context = createContext('cool');
});

describe('<Provider />', () => {
it('can be rendered as the root', () => {
const wrapper = shallow(
<Context.Provider value="hello">
<Context.Consumer>
{value => <div>{value}</div>}
</Context.Consumer>
</Context.Provider>,
);
expect(wrapper.debug()).to.eql(`
<ContextConsumer>
[function]
</ContextConsumer>
`.trim());
});

it('supports changing the value', () => {
const wrapper = shallow(
<Context.Provider value="hello">
<Context.Consumer>
{value => <div>{value}</div>}
</Context.Consumer>
</Context.Provider>,
);
wrapper.setProps({ value: 'world' });
expect(wrapper.find(Context.Consumer).dive().text()).to.eql('world');
});
});

describe('<Consumer />', () => {
function DivRenderer({ children }) {
return <div>{children}</div>;
}
it('can be rendered as the root', () => {
const wrapper = shallow(
<Context.Consumer>
{value => <DivRenderer>{value}</DivRenderer>}
</Context.Consumer>,
);
expect(wrapper.debug()).to.eql(`
<DivRenderer>
cool
</DivRenderer>
`.trim());
});

it('supports changing the children', () => {
const wrapper = shallow(
<Context.Consumer>
{value => <DivRenderer>{value}</DivRenderer>}
</Context.Consumer>,
);
wrapper.setProps({ children: value => <DivRenderer>Changed: {value}</DivRenderer> });
expect(wrapper.find(DivRenderer).dive().text()).to.eql('Changed: cool');
});
});
});

describe('dive() 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', () => {
expect(shallow(<MyComponent />)
.find(Provides)
.dive()
.find(Provider)
.dive()
.text()).to.equal('<Consumes />');
});

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

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

it('does not leak values across roots', () => {
const wrapper = shallow(<MyComponent />);

wrapper
.find(Provides)
.dive()
.find(Provider)
.dive();
expect(wrapper
.find(Consumes)
.dive()
.find(Consumer)
.dive()
.text()).to.equal('howdy!');
});
});
});

describeIf(is('> 0.13'), 'stateless function components (SFCs)', () => {
it('can pass in context', () => {
const SimpleComponent = (props, context) => (
Expand Down
Expand Up @@ -183,6 +183,32 @@ export default function describeGetWrappingComponent({
}
});

itIf(is('>= 16.3'), 'updates a <Provider /> if it is rendered as root', () => {
const Context = React.createContext();
function WrappingComponent(props) {
const { value, children } = props;
return (
<Context.Provider value={value}>
{children}
</Context.Provider>
);
}
const wrapper = Wrap(
<Context.Consumer>
{value => <div>{value}</div>}
</Context.Consumer>,
{
wrappingComponent: WrappingComponent,
wrappingComponentProps: { value: 'hello!' },
},
);
const wrappingComponent = wrapper.getWrappingComponent();
expect(wrapper.text()).to.equal('hello!');

wrappingComponent.setProps({ value: 'goodbye!' });
expect(wrapper.text()).to.equal('goodbye!');
});

itIf(!isShallow, 'handles a partial prop update', () => {
const wrapper = Wrap(<MyComponent />, {
wrappingComponent: MyWrappingComponent,
Expand Down

0 comments on commit 8fcf010

Please sign in to comment.