Reputation: 4537
I'm trying to pass context to a React component, but because I am testing with Enzyme, I'd like to add the component to its parent dynamically so I can examine its state. The test looks like this:
describe('<BeaconConfig />', () => {
it('inherits the config from BeaconConfig', () => {
mount(<BeaconConfig persistent><div id="parent"></div></BeaconConfig>, { attachTo: document.body });
const wrapper = mount(<Beacon/>, { attachTo: document.getElementById('parent') });
expect(wrapper.state('persistent')).to.be(true);
});
});
The test fails because the persistent
property of the Beacon
component's state is undefined
, although it should be inherited from BeaconConfig
via context.
When I try putting Beacon
directly inside the JSX when I mount BeaconConfig
then it works fine, but in this case Enzyme won't let me get at the Beacon
component state since it isn't the root.
Is it normal that React isn't propagating the context to my component when I add it dynamically to its parent?
Upvotes: 1
Views: 722
Reputation: 4537
Here is the complete test I ended up using:
describe('Context', () => {
let wrapper;
let parent;
const open = stub().returns({});
const mockIndexedDB = { open };
const config = mount(<BeaconConfig persistent position="bottom" indexedDB={mockIndexedDB} />);
beforeEach(() => {
parent = document.createElement('div');
document.body.appendChild(parent);
wrapper = mount(<Beacon>some text</Beacon>, {
attachTo: parent,
context: config.instance().getChildContext()
});
});
afterEach(() => {
wrapper.detach();
document.body.removeChild(document.body.firstChild);
});
it('overrides the default values with the context if any', () => {
expect(wrapper.state('persistent')).to.be(true);
expect(wrapper.state('position')).to.be('bottom');
expect(open.calledOnce).to.equal(true);
});
});
@STRML had a good suggestion but I don't think that it is possible to access the state of a non-root component.
Instead I instantiate BeaconConfig
in isolation and grab it's child context, passing that manually to Beacon
using the options
parameter of mount
. This tests that BeaconConfig
creates the right child context and that Beacon
uses the context correctly. It doesn't test that BeaconConfig
passes the config down to Beacon
when the latter is a descendant, but we can presumably take that for granted since it is basic React functionality.
Upvotes: 0
Reputation: 942
It is normal that React isn't propagating the context - it doesn't look at the DOM and diff it with its VDOM in that way.
You'll want make it a child in the initial mount, and use the .find()
or .children()
methods of the MountWrapper (docs) to dig through the children, find the Beacon and do your assertions.
Upvotes: 1