JEST testing on redux is not working as expected - reactjs

I have a code in redux which i exported as
export default connect(mapStateToLinkProps, mapDispatchToLinkProps)(Link);
And in jest test case i have written to test this exported component
//imported the above component as Link
describe('Dashboard component testing', () => {
test('1. Must be an Instance of CreateAssest', () => {
const wrapper = shallow(<FilterLink />);
const inst = wrapper.instance();
expect(inst).toBeInstanceOf(Link);
});
});
For this i'm getting error
Invariant Violation: Could not find "store" in either the context or
props of "Connect(Link)". Either wrap the root component in a
, or explicitly pass "store" as a prop to "Connect(Link)".
When not using redux and exporting only as react component the test cases were working.Now in redux some store issue is coming.please can anyone guide a little in this issue what's happening

You need to wrap your component in Provider in order to be able to use store, like so:
import { Provider, connect } from "react-redux";
let store = createStore(reducer, defaultStoreItems);
<Provider store={store}>
<App />
</Provider>

Related

Using React-Redux: How to Access Variables in the Store, within Nested Components

I am using React-Redux, but I am not able to figure out how to access a variable in the Redux store inside of my nested components.
How can I share a variable between components, using React-Redux?
For example:
I have an 'index.js' file and 30 nested components. Managing these components becomes difficult after a while.
I have a 'C1.js' component. Let's just say I wrote this code in it.
function Reducer(state = 'example' , action) {
return state;
}
const store = createStore(Reducer)
index.js file:
<Provider store = {store}>
<App/>, document.getElementById('root')
</Provider>
How do I pass the 'store' variable to the 'C1.js' component to the index.js file?
Thanks...
You need to use something called "Connect" to connect your various components to the provider.
In the file that contains your C1.js component:
import {connect} from 'react-redux'
const MyComponent = () => {
let someData = props.someData
return(
//all of your JSX for your component here
)
}
const mapState = state => {
return {
someData: state.someData
}
}
export default connect(mapState)(MyComponent)
In the code above, notice the mapStateFunction. Connect is hooking that up with the Provider, and the state that is on the Provider. So that is where you are able to link whatever properties are on your Provider (React-Redux) state with this particular data.
Now, in your component, you will now have prop.someData
-
In the index file, you have your Provider in the wrong place, you need to change your code to this:
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('app')
)
See, the difference there? The is the React Element (and all of its children that you are asking React to render to the DOM). It is the first parameter of the ReactDOM.render function.
The second parameter to the ReactDom.render function is the element in the DOM where you want it to put all of your React elements.
You did not configure well redux and react. You need to go over the doc of redux to setup correctly. Should get working after that.

"Could not find store" after wrapping component with context provider in Jest

After wrapping a React Component with the appropriate provider, the store is still not found within the jest testing environment. Is there something that I am missing, or another cleaner way to go about this?
This is the practice that is functional for other stores, and I have used with other components, so I don't see a reason why this shouldn't work. The renderer should be creating an object wrapped with the TextContext that it needs to read from in order to populate fields.
Context
import { connect } from 'react-redux';
import React, { createContext } from 'react';
export const TextContext = createContext({});
export function TextProvider({ children, text }) {
return <TextContext.Provider value={text}>{children}</TextContext.Provider>;
}
export const TextConsumer = TextContext.Consumer;
function renderComposition(props) {
const text = {
... // some text objects
};
return (
<TextProvider text={text}>
<Composition {...props} />
</TextProvider>
);
}
target failing line
beforeEach(() => {
...
subject = mount(renderer.create(renderComposition(props)));
...
)};
with error of
Invariant Violation: Could not find "store" in either the context or props of "Connect(Composition)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(Composition)".
I guess your component requires mocked store, you can provide it by creating mockReduxState.js
import configureMockStore from "redux-mock-store";
export const createMockStore = state => configureMockStore()(state);
Updating the failing test by passing mockedStore.
beforeEach(() => {
...
let updatedProp = {...props, store:createMockStore};
subject = mount(renderer.create(renderComposition(updatedProp)));
...
)};
Turns out the issue was unrelated, I was importing the component rather than the connected container, so the store was never getting set. Names are half of the battle turns out. The mocking the store option is also a great way to handle this đź‘Ť thanks paragxvii

Error while doing unit test in react-redux connected component

I am trying to test the connected component(react-redux) with jest-enzyme. I am using react-redux-mock store. When I run my test to find one div in the component it gives me this error.
Invariant Violation: Passing redux store in props has been removed and does not do anything. To use a custom Redux store for specific components, create a custom React context with React.createContext(), and pass the context object to React-Redux's Provider and specific components like: <Provider context={MyContext}><ConnectedComponent context={MyContext} /></Provider>. You may also pass a {context : MyContext} option to connect
I did mount and tested just component without redux it works but I want to do a > shallow test.
describe("Input Component", () => {
let wrapper;
let store;
beforeEach(() => {
store = mockStore(initialState);
wrapper = shallow(<Input store={store} />);
});
it("should rendder without error", () => {
expect(wrapper.find("div")).toHaveLength(1);
});
});
How do you import your component?
if your are importing it with import App from './yourpath/App' for example, ou're actually holding the wrapper component returned by connect(), and not the App component itself.
In order to be able to test the App component itself without having to deal with the decorator, you must to also export the undecorated component:
import { connect } from 'react-redux'
// Use named export for unconnected component (for tests)
export class App extends Component {
/* ... */
}
// Use default export for the connected component (for app)
export default connect(mapStateToProps)(App)
And import it in your test file like that:
import { App } from './yourpath/App'

Mocking Redux store when testing React components?

I'm using React and Redux. I have a component which loads ChildComponent and depending on Redux's state will also load MainComponent
const ChooseIndex = ({ appInitMount }) => {
return (
<>
<ChildComponent />
{!appInitMount && <MainComponent />}
</>
);
};
const mapStateToProps = ({ main }) => {
return {
appInitMount: main.appInitMount
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(ChooseIndex);
I'm trying to write a test to check that ChildComponent is loaded:
import React from "react";
import { render } from "react-testing-library";
import ChooseIndex from "../choose-index";
test("ChooseIndex should call ChildComponent", () => {
const wrapper = render(
<ChooseIndex />
);
});
I get this error:
Error: Uncaught [Invariant Violation: Could not find "store" in either
the context or props of "Connect(ChooseIndex)". Either wrap the root
component in a , or explicitly pass "store" as a prop to
"Connect(ChooseIndex)".]
Should I mock Redux by passing an object literal to ChooseIndex? Or should I create a Redux store (as my real application does) for every test?
Try to render your component like this:
render(
<Provider store={store}>
<ChooseIndex />
</Provider>
)
And pass the actual store you use in your app. In this way, you're testing the real logic that you'll use in production. You also don't care what actions get dispatched and what's in the state. You look at what gets rendered and interact with the UI—which is what matters in the end.
Separating the component from Redux and testing the two in isolation is against the whole point of react-testing-library. You want to test your app as a real user would.
If you check out the writing tests section of the redux docs, there is an example of testing a connected component.
when you import it [A redux connected component], you're actually holding the wrapper component returned by connect(), and not the App component itself. If you want to test its interaction with Redux, this is good news: you can wrap it in a with a store created specifically for this unit test. But sometimes you want to test just the rendering of the component, without a Redux store.
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
As with most unit tests, you really want to be testing your components, and not that redux is working correctly. So the solution for you is to export both the component and the connected component, while only testing the component itself, and providing whatever props redux is passing to your component.
import { connect } from 'react-redux'
// Use named export for unconnected component (for tests)
export class App extends Component {
/* ... */
}
// Use default export for the connected component (for app)
export default connect(mapStateToProps)(App)

Jest test component's inner method

I'm using react native 0.40 with jest 20. When trying to test the inner method of a component I fail because I cannot get the instance of it and then call the method.
For example I can test the rendered component using the snapshots like
it('renders correctly', () => {
var store = mockStore(initialState);
const tree = renderer.create(
<Provider store={store}>
<App/>
</Provider>
).toJSON()
expect(tree).toMatchSnapshot()
})
But if I try to test an inner method of the App component I don't find any way to access it.
So the following code will not run
it("checks version number correctly", () => {
var store = mockStore(initialState);
const tree = renderer.create(
<Provider store={store}>
<App/>
</Provider>
)
expect(tree.needsUpdate("1.0.0")).toBe(true)
})
The solution some people used was "react-test-renderer/shallow" or "enzyme" to shallow render the component and access the inner method, but the first one cannot be found when I import it (maybe related to RN version?) and enzyme cannot be installed properly (maybe again, a dependency issue). So what I wonder is, what's the best way to test an inner method.
You don't have to actually wrap your component in a provider. If you just want to test your component, you can export it without connect()(). For instance:
export class App extends React.Component {
// your things
}
export default connect()(App);
Inside your test file, you can import your app like so:
import ConnectedApp, { App } from "../App";
Then when you want to test your encapsulated App, you can treat it like any other standard component:
const props = {
// mocked-out props your store would provide
};
const component = shallow(<App {...props} />);
component.instance().whateverMethodYouWant();
Personally, I never wrap a component in a mock provider unless I need to render and deeper components are connected.

Resources