Full code here: https://gist.github.com/js08/0ec3d70dfda76d7e9fb4
Hi,
- I have an application where it shows different templates for desktop and mobile on basis of build environment.
- I am successfully able to develop it where I need to hide the navigation menu for my mobile template.
- right now I am able to write one test case where it fetches all the values through the proptypes and renders correctly
- but not sure how to write the unit test cases when its mobile it should not render nav component.
- I tried but I am facing an error...can you tell me how to fix it.
- provding code below.
Test case
import {expect} from 'chai';
import React from 'react';
import TestUtils from 'react-addons-test-utils';
import {SportsTopPortion} from '../../../src/components/sports-top-portion/sports-top-portion.jsx';
require('../../test-utils/dom');
describe('"sports-top-portion" Unit Tests', function() {
let shallowRenderer = TestUtils.createRenderer();
let sportsContentContainerLayout ='mobile';
let sportsContentContainerProfile = {'exists': 'hasSidebar'};
let sportsContentContainerAuthExchange = {hasValidAccessToken: true};
let sportsContentContainerHasValidAccessToken ='test';
it('should render correctly', () => {
shallowRenderer.render(<SportsTopPortion sportsWholeFramework={sportsContentContainerLayout} sportsPlayers={sportsContentContainerProfile} sportsAuthentication={sportsContentContainerAuthExchange} sportsUpperBar={{activeSportsLink:'test'}} />);
//shallowRenderer.render(<SportsTopPortion sportsWholeFramework={sportsContentContainerLayout} sportsPlayers={sportsContentContainerProfile} hasValidAccessToken={sportsContentContainerHasValidAccessToken} />);
let renderedElement = shallowRenderer.getRenderOutput();
console.log("renderedElement------->" + JSON.stringify(renderedElement));
expect(renderedElement).to.exist;
});
it('should not render sportsNavigationComponent when sports.build is mobile', () => {
let sportsNavigationComponent = TestUtils.renderIntoDocument(<SportsTopPortion sportsWholeFramework={sportsContentContainerLayout} sportsPlayers={sportsContentContainerProfile} sportsAuthentication={sportsContentContainerAuthExchange} sportsUpperBar={{activeSportsLink:'test'}} />);
console.log("sportsNavigationComponent------->" + JSON.stringify(sportsNavigationComponent));
//let footnoteContainer = TestUtils.findRenderedDOMComponentWithClass(sportsNavigationComponent, 'linkPack--standard');
//expect(footnoteContainer).to.exist;
});
});
Code snippet where test case need to be written
if (sports.build === 'mobile') {
sportsNavigationComponent = <div />;
sportsSideMEnu = <div />;
searchComponent = <div />;
sportsPlayersWidget = <div />;
}
Error
1) "sports-top-portion" Unit Tests should not render sportsNavigationComponent when sports.build is mobile:
Invariant Violation: Could not find "store" in either the context or props of "Connect(SportsDatabase)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(SportsDatabase)".
at Object.invariant [as default] (C:\sports-whole-page\node_modules\invariant\invariant.js:42:15)
at new Connect (C:\sports-whole-page\node_modules\react-redux\lib\components\createConnect.js:135:33)
at [object Object].ReactCompositeComponentMixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactCompositeComponent.js:148:18)
at [object Object].wrapper [as mountComponent] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21)
at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35)
at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (C:\sports-whole-page\node_modules\react\lib\ReactMultiChild.js:241:44)
at ReactDOMComponent.Mixin._createContentMarkup (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:591:32)
at ReactDOMComponent.Mixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:479:29)
at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35)
at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (C:\sports-whole-page\node_modules\react\lib\ReactMultiChild.js:241:44)
at ReactDOMComponent.Mixin._createContentMarkup (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:591:32)
at ReactDOMComponent.Mixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:479:29)
at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35)
at [object Object].ReactCompositeComponentMixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactCompositeComponent.js:225:34)
at [object Object].wrapper [as mountComponent] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21)
at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35)
at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (C:\sports-whole-page\node_modules\react\lib\ReactMultiChild.js:241:44)
at ReactDOMComponent.Mixin._createContentMarkup (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:591:32)
at ReactDOMComponent.Mixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:479:29)
at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35)
at [object Object].ReactCompositeComponentMixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactCompositeComponent.js:225:34)
at [object Object].wrapper [as mountComponent] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21)
at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35)
at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (C:\sports-whole-page\node_modules\react\lib\ReactMultiChild.js:241:44)
at ReactDOMComponent.Mixin._createContentMarkup (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:591:32)
at ReactDOMComponent.Mixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:479:29)
at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35)
at [object Object].ReactCompositeComponentMixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactCompositeComponent.js:225:34)
at [object Object].wrapper [as mountComponent] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21)
at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35)
at [object Object].ReactCompositeComponentMixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactCompositeComponent.js:225:34)
at [object Object].wrapper [as mountComponent] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21)
at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35)
at mountComponentIntoNode (C:\sports-whole-page\node_modules\react\lib\ReactMount.js:266:32)
at ReactReconcileTransaction.Mixin.perform (C:\sports-whole-page\node_modules\react\lib\Transaction.js:136:20)
at batchedMountComponentIntoNode (C:\sports-whole-page\node_modules\react\lib\ReactMount.js:282:15)
at ReactDefaultBatchingStrategyTransaction.Mixin.perform (C:\sports-whole-page\node_modules\react\lib\Transaction.js:136:20)
at Object.ReactDefaultBatchingStrategy.batchedUpdates (C:\sports-whole-page\node_modules\react\lib\ReactDefaultBatchingStrategy.js:62:19)
at Object.batchedUpdates (C:\sports-whole-page\node_modules\react\lib\ReactUpdates.js:94:20)
at Object.ReactMount._renderNewRootComponent (C:\sports-whole-page\node_modules\react\lib\ReactMount.js:476:18)
at Object.wrapper [as _renderNewRootComponent] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21)
at Object.ReactMount._renderSubtreeIntoContainer (C:\sports-whole-page\node_modules\react\lib\ReactMount.js:550:32)
at Object.ReactMount.render (C:\sports-whole-page\node_modules\react\lib\ReactMount.js:570:23)
at Object.wrapper [as render] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21)
at Object.ReactTestUtils.renderIntoDocument (C:\sports-whole-page\node_modules\react\lib\ReactTestUtils.js:76:21)
at Context.<anonymous> (C:/codebase/sports-whole-page/test/components/sports-top-portion/sports-top-portion-unit-tests.js:28:41)
at callFn (C:\sports-whole-page\node_modules\mocha\lib\runnable.js:286:21)
at Test.Runnable.run (C:\sports-whole-page\node_modules\mocha\lib\runnable.js:279:7)
at Runner.runTest (C:\sports-whole-page\node_modules\mocha\lib\runner.js:421:10)
at C:\sports-whole-page\node_modules\mocha\lib\runner.js:528:12
at next (C:\sports-whole-page\node_modules\mocha\lib\runner.js:341:14)
at C:\sports-whole-page\node_modules\mocha\lib\runner.js:351:7
at next (C:\sports-whole-page\node_modules\mocha\lib\runner.js:283:14)
at Immediate._onImmediate (C:\sports-whole-page\node_modules\mocha\lib\runner.js:319:5)
in my case just
shallow(<Login />, { context: { store } });
As the official docs of redux suggest, better to export the unconnected component as well.
In order to be able to test the App component itself without having to deal with the decorator, we recommend you to also export the undecorated component:
Since the default export is still the decorated component, the import statement pictured above will work as before so you won't have to change your application code. However, you can now import the undecorated App components in your test file like this:
And if you need both:
In the app itself, you would still import it normally:
You would only use the named export for tests.
This happened to me when I upgraded. I had to downgrade back.
react-redux ^5.0.6 → ^7.1.3
It's pretty simple. You're trying to test the wrapper component generated by calling
connect()(MyPlainComponent)
. That wrapper component expects to have access to a Redux store. Normally that store is available ascontext.store
, because at the top of your component hierarchy you'd have a<Provider store={myStore} />
. However, you're rendering your connected component by itself, with no store, so it's throwing an error.You've got a few options:
<Provider>
around your connected component<MyConnectedComponent store={store} />
, as the connected component will also accept "store" as a propmapStateToProps
function, you can safely assume the connected version will work correctly.You probably want to read through the "Testing" page in the Redux docs: https://redux.js.org/recipes/writing-tests.
edit:
After actually seeing that you posted source, and re-reading the error message, the real problem is not with the SportsTopPane component. The problem is that you're trying to "fully" render SportsTopPane, which also renders all of its children, rather than doing a "shallow" render like you were in the first case. The line
searchComponent = <SportsDatabase sportsWholeFramework="desktop" />;
is rendering a component that I assume is also connected, and therefore expects a store to be available in React's "context" feature.At this point, you have two new options:
Overall, I would note that you might be trying to do too much in this one component and might want to consider breaking it into smaller pieces with less logic per component.
When we put together a react-redux application we should expect to see a structure where at the top we have the
Provider
tag which has an instance of a redux store.That
Provider
tag then renders your parent component, lets call it theApp
component which in turn renders every other component inside the application.Here is the key part, when we wrap a component with the
connect()
function, thatconnect()
function expects to see some parent component within the hierarchy that has theProvider
tag.So the instance you put the
connect()
function in there, it will look up the hierarchy and try to find theProvider
.Thats what you want to have happen, but in your test environment that flow is breaking down.
Why?
Why?
When we go back over to the assumed sportsDatabase test file, you must be the sportsDatabase component by itself and then trying to render that component by itself in isolation.
So essentially what you are doing inside that test file is just taking that component and just throwing it off in the wild and it has no ties to any
Provider
or store above it and thats why you are seeing this message.There is not store or
Provider
tag in the context or prop of that component and so the component throws an error because it want to see aProvider
tag or store in its parent hierarchy.So that’s what that error means.
For me it was import issue, hope it helps. default import by WebStorm was wrong.
replace
with