I am attempting to test that I am calling one of my mapDispatchToProps
functions with args, however I can't seem to get it to work...
I attempted to follow this previous question, but it didn't seem to work for me.
Component.jsx
const mapDispatchToProps = dispatch => ({
myFunction: (data) => dispatch(myAction(data))
});
const Component = ({buttonText, myFunction}) => (
<button data-testid="test" onClick={() => myFunction(123)}>{buttonText}</button>
)
export default connect(null, mapDispatchToProps)(Component);
Actions.js
export const myAction = agentData => ({
type: `MY_ACTION`,
agentData
});
Test.js
import createMockStore from "redux-mock-store";
it('Should pass', () => {
const mockStore = createMockStore();
const store = mockStore({});
const mockUpdate = jest.fn(data => console.log('HIT FUNCTION with ' data));
const props = {buttonText: 'Click me', myFunction: mockUpdate};
render(
<Provider store={store}>
<Component {...props}/>
</Provider>
);
userEvent.click(screen.queryByTestId('test'));
expect(mockUpdate).toHaveBeenCalled();
expect(mockUpdate).toHaveBeenCalledWith(123);
});
I have also tried moving the myFunction: mockUpdate
from the props
object into the mockStore({})
initial object, but still no luck...
CodePudding user response:
Your mock myFunction
didn't invoke when you click the button. Because the returned value of mapDispatchToProps
will become the props of the component.
You can get the mock myFunction
via the second parameter of mapDispatchToProps
function named ownProps
. You may want to call the mock myFunction
when dispatching the action. If so, expect(mockUpdate).toHaveBeenCalled();
assertion will work.
component.tsx
:
import React from 'react';
import { connect } from 'react-redux';
import { myAction } from './actions';
const mapDispatchToProps = (dispatch, ownProps) => {
console.log('Your mock myFunction is here:', ownProps.myFunction);
// But below myFunction is not a mock function and is passed into your component finally.
return {
myFunction: (data) => dispatch(myAction(data)),
};
};
const Component = ({ buttonText, myFunction }) => (
<button data-testid="test" onClick={() => myFunction(123)}>
{buttonText}
</button>
);
export default connect(null, mapDispatchToProps)(Component);
import React from 'react';
import { render, screen } from '@testing-library/react';
import { Provider } from 'react-redux';
import createMockStore from 'redux-mock-store';
import userEvent from '@testing-library/user-event';
import Component from './component';
it('Should pass', async () => {
const mockStore = createMockStore();
const store = mockStore();
render(
<Provider store={store}>
<Component buttonText="Click me" />
</Provider>
);
await userEvent.click(screen.getByTestId('test'));
expect(store.getActions()).toEqual([{ type: 'MY_ACTION', agentData: 123 }]);
});
Test result:
PASS stackoverflow/75173986/component.test.tsx (8.625 s)
✓ Should pass (92 ms)
console.log
Your mock myFunction is here: [Function: mockConstructor] {
_isMockFunction: true,
getMockImplementation: [Function (anonymous)],
mock: [Getter/Setter],
mockClear: [Function (anonymous)],
mockReset: [Function (anonymous)],
mockRestore: [Function (anonymous)],
mockReturnValueOnce: [Function (anonymous)],
mockResolvedValueOnce: [Function (anonymous)],
mockRejectedValueOnce: [Function (anonymous)],
mockReturnValue: [Function (anonymous)],
mockResolvedValue: [Function (anonymous)],
mockRejectedValue: [Function (anonymous)],
mockImplementationOnce: [Function (anonymous)],
mockImplementation: [Function (anonymous)],
mockReturnThis: [Function (anonymous)],
mockName: [Function (anonymous)],
getMockName: [Function (anonymous)]
}
at Function.mapDispatchToProps [as mapToProps] (stackoverflow/75173986/component.tsx:6:11)
---------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
actions.ts | 100 | 100 | 100 | 100 |
component.tsx | 100 | 100 | 100 | 100 |
---------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.103 s, estimated 10 s
Ran all test suites related to changed files.
CodePudding user response:
I found a solution by combining something similar to @Lin Du and also some other resources I found online (that I can't seem to find in my search history to link to at the moment).
This solution doesn't require any additional args such as testProps to be added to the mapDispatchToProps
function.
import configureStore from 'redux-mock-store';
...
it('Should call next step with both call plan and caller display', () => {
const store = { /* any mapStateToProps data here */ };
const mockStore = configureStore()(store);
mockStore.dispatch = jest.fn(); // Can add callback in here to update the non-mock store
const props = {buttonText: 'Click me'};
provider = getComponentProvider(ChooseCallPlan, store, {wizard}, true);
render(
<Provider store={mockStore}>
<Component {...props}/>
</Provider>
);
userEvent.click(screen.queryByTestId('test'));
export(mockStore.dispatch).toHaveBeenCalled();
expect(mockStore.dispatch)
.toHaveBeenCalledWith(myAction(123));
});