Vue-test-utils wrapper undefined - javascript

I have the following test suite in Jest for a component. I have successfully written unit tests for several other components that follow a similar structure:
import { createLocalVue, mount } from '#vue/test-utils'
import Vuex from 'vuex'
import storeMock from '#mocks/store'
import RequestProposalsContainer from '#/components/RequestProposals/RequestProposalsContainer'
describe('ProviderComparison component', () => {
let localVue, store, wrapper, storeSetup
beforeEach(() => {
localVue = createLocalVue()
localVue.use(Vuex)
storeSetup = storeMock()
store = new Vuex.Store(storeSetup)
/* wrapper is undefined and I'm not sure why */
wrapper = mount(RequestProposalsContainer, {
localVue,
store
})
})
it('renders correct structure', () => {
/* undefined */
console.log('wrapper: ', wrapper)
})
})
By inspection, the component being mounted, the store, and localVue instance are well-defined.

I was in a similar situation where the wrapper would come back undefined.
While testing, you have to give the component everything it needs to render.
It was (as #Adam Freymiller has already alluded to) that all the required values (props, store values, etc) were not set in the test, so the component would error out, much like how it would in a real life scenario.

Related

Redux Container Unit Testing - Unable to access props for wrapped component

Following the React v6 upgrade, my existing test cases for the component are failing.
Here is my component container code TodoContainer.jsx:
import { connect } from 'react-redux';
import Todo from './Todo';
import { initialLoadExecuted } from '../../actions/LoadActions';
const mapStateToProps = state => ({
isCollapsed: true,
pinnedTiles: false,
});
const mapDispatchToProps = dispatch => ({
dispatchInitialLoadExecuted: (tiles) => {
dispatch(initialLoadExecuted(tiles));
},
});
export default connect(mapStateToProps, mapDispatchToProps)(Todo);
Here is my test code TodoContainer.test.jsx:
import React from 'react';
import configureStore from 'redux-mock-store';
import {Provider} from 'react-redux';
import TodoContainer from '../../../../src/todo-component/components/Todo/TodoContainer';
import { initialLoadExecuted } from '../../../../src/todo-component/actions/LoadActions';
const mockStore = configureStore();
let store;
describe('Todo Container', () => {
beforeEach(() => {
store = mockStore({
});
it('maps state props correctly', () => {
const wrapper = shallow(<TodoContainer store={store}/>);
wrapper.prop('dispatchInitialLoadExecuted')('Test String);
// Expect statements
});
});
The error i am getting is :
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: . You may also pass a {context : MyContext} option to connect.
Is there a way to to pass store through provider while accessing the props, the same way?
It appears that react-redux v6.0.0 now supports the new Context API added to React v 16.4.0 (and also requires that verson of react now).
I was able to resolve the issue and keep the mockStore pattern by installing react-redux#5.1.1 and react#16.3.0 (before they introduced the Context API).
Further testing: I can use react#16.7.0 as long as I use react-redux#5.1.1
There's an ongoing discussion on the react-redux github issues tab: https://github.com/reduxjs/react-redux/issues/1161
Not a long term solution as I'd be stuck at this version of React, but it does pass the test and I was able to get my 100% code coverage.

How can I test areStatesEqual in a redux connected component

I have a redux connected component that is utilising areStatesEqual in the options argument in the redux connect api to avoid re-rendering.
shouldComponentUpdate does the same job, but a lot slower in my use case.
I'm struggling to test multiple state updates, asserting that under certain conditions this component believes the states are equal, and shouldn't re-render.
I'm using react-mock-store for other components, but that only deals with static state, not dynamic. Also using mocha & enzyme elsewhere too.
Does anyone have any ideas how I can test this behaviour?
(This is a simplified version of a more complicated component)
import { connect } from 'react-redux';
import { compose } from 'redux';
import MyComponent from './my-component';
const mapStateToProps = (state, props) => ({
text: state.a.text[props.id],
});
const areStatesEqual = (next, prev) => {
return next.a === prev.a;
};
const options = { areStatesEqual };
export default connect(mapStateToProps, undefined, undefined, options)(MyComponent);
MyComponent is a simple functional component that just accepts props and renders:
export default function Label({ text }) {
return <p>{text}</p>;
}
In the end I managed to test the logic by exporting the areStatesEqual function and doing a simple test.
export const areStatesEqual = (next, prev) => {
return next.a === prev.a;
};
I haven't figured out a way to test the flow of the lifecycle of a component

Jest mock redux-store getState() used in module with redux-mock-store

So my implementation of the redux-store might not be the best and my knowledge of Jest is minimum-to-none..
I have three files which consists of...
A module
A React Component
The (a normal) store, exported as default
My test file looks like this:
// file.test.js
jest.mock( 'store', () => jest.fn() )
// external
import React from 'react'
import configureStore from 'redux-mock-store'
// internal
import Component from 'components/Component'
import store from 'store'
describe( 'Test My Component', () => {
const mockStore = configureStore()
it ( 'should equal true', () => {
const initialState = { active: true }
store.mockImplementation(() => mockStore( initialState ))
expect( store.getState().active ).toBe( true )
} )
} );
The reason why I am mocking store is because inside <Component /> I am using a module which itself imports the same store and holds a few function that are making use of store.getState()...
So what this returns is
TypeError: _store2.default.getState is not a function
I did get around this by mocking the module call (which is used by the <Component />) instead, but I feel like I "should" be able to do this, as I have different initial states I want to try and not all are dependent on the module.
This is my very first post on SO, let me know If I should clarify anything!
Do not import the store. We want to mock the store:
const store = mockStore(initialState);

Unable to set context when rendering child components

I'm trying to test a custom Material-ui React component with Enzyme but getting the following error:
ERROR: 'Warning: Failed context type: Required context 'muiTheme' was not specified in 'ChildComponent'.
What I've tried is to set a context according to this. The component that I want to reach and test is a child component.
const root = shallow(<RootComponent />, {context: {muiTheme}, childContextTypes: {muiTheme: React.PropTypes.object}})
const child = root.find(ChildComponent)
child.render() // <--- this line is throwing the error
update: this is related
I'm not sure this is the solution but it's one step closer to the goal.
const root = mount(<RootComponent />, {
context: {muiTheme},
childContextTypes: {muiTheme: React.PropTypes.object}
})
const child = root.find(ChildComponent)
Notice, I use mount instead of shallow. The issue is with this I can't use child.find({prop: 'value'}) any longer - return 0 items...
You need to provide the <muiThemeProvider> component.
Here is an example on how to do :
import React from 'react';
import { mount } from 'enzyme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import Input from './Input';
describe('<Input />', () => {
const mountWithTheme = (node) => mount(<MuiThemeProvider>{node}</MuiThemeProvider>);
it('calls componentDidMount', () => {
sinon.spy(Input.prototype, 'componentDidMount');
mountWithTheme(<Input />);
expect(Input.prototype.componentDidMount.calledOnce).to.equal(true);
});
});

How would I unit test this utility that connects Redux to React components?

I have a "utility" called "reduxify" that automatically does a lot of the Redux/React boilerplate for you, so that instead of writing "mapStateToProps" and "mapDispatchToProps" functions on every component, you just write your component like this:
// usage.
class Foo extends Component {
// component stuff
}
export default reduxify(actions, Foo);
The reduxify function (with comments) are at this gist:
https://gist.github.com/brianboyko/904d87da2a75c98e8cd5f5352dd69d57
Without the comments (for brevity), it's produced below:
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { getStore } from '../store/storeConfig'
export function reduxify(actions, component){
let mapStateToProps = (state) => {
state = Object.assign({}, state, {store: state}, {getStore: getStore});
return (state);
}
let prepareActions = (actions) => (dispatch) =>
({ actions: bindActionCreators(actions.default, dispatch),
dispatch: dispatch,
})
let mapDispatchToProps = (dispatch) => (prepareActions(actions, dispatch))
return connect(mapStateToProps, mapDispatchToProps)(component);
}
So, here's the question: What's the best way to mock a component (one that will have access to the Provider) so that I can unit test this sucker, put it out there for people to use and enjoy, and not feel like a hack?
Have a look at the unit tests used by react-redux for an example of how to test a component that is wrapped by <Provider>: https://github.com/reactjs/react-redux/blob/master/test/components/Provider.spec.js#L50-64. Basically, they just declared a component and then wrapped it with a <Provider> component whose store prop is a mocked Redux store. (They're using 'react-addons-test-utils' to do their test component rendering, but it would be even easier with enzyme.)
In your case, you could spy on the mocked store's dispatch() method to ensure that your component's action-dispatching props are calling it as expected.

Categories