mirror of
https://github.com/m-lamonaca/dev-notes.git
synced 2025-04-08 11:56:41 +00:00
Redux Tests Notes
This commit is contained in:
parent
7d7737ec06
commit
09f4571fde
1 changed files with 151 additions and 0 deletions
151
JavaScript/React/Redux Tests.md
Normal file
151
JavaScript/React/Redux Tests.md
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
# Redux Testing
|
||||||
|
|
||||||
|
## Tests for Connected Components
|
||||||
|
|
||||||
|
Connected components are warpped in a call to `connect`. Way of solving the problem:
|
||||||
|
|
||||||
|
- Wrap component with `<Provider>`. Added benefit: new store dedicated to tests.
|
||||||
|
- Add named export for unconncted component.
|
||||||
|
|
||||||
|
In `Component.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export function Component(props) { /* ... */ } // export unconnected component
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(Component) // default export of connected component
|
||||||
|
```
|
||||||
|
|
||||||
|
In `Component.test.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import React from "react";
|
||||||
|
// import enzyme or react testing library
|
||||||
|
|
||||||
|
// import mock data
|
||||||
|
import { Component } from "path/to/Component"; // import unconnected component
|
||||||
|
|
||||||
|
// factory to setup test easily
|
||||||
|
function testHelper(args) {
|
||||||
|
const defaultProps = {
|
||||||
|
/* default value for props in each test and required props */,
|
||||||
|
history = {} // normally injected by react-router, could also import the router
|
||||||
|
};
|
||||||
|
|
||||||
|
const props = { ...defaultProps, ...args };
|
||||||
|
return mount(<Component {...props} />); // or render if using react testing library
|
||||||
|
}
|
||||||
|
|
||||||
|
it("test description", () => {
|
||||||
|
const dom = testHelper();
|
||||||
|
|
||||||
|
// simulate page interation
|
||||||
|
dom.find("selctor").simulate("<event>");
|
||||||
|
|
||||||
|
// find changed component
|
||||||
|
// test expected behaviour of component
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests for Action Creators
|
||||||
|
|
||||||
|
```js
|
||||||
|
import * as actions from "path/to/actionCreators";
|
||||||
|
// import eventual action types constants
|
||||||
|
// import mock data
|
||||||
|
|
||||||
|
describe("Async Actions", () => {
|
||||||
|
afterEach(() => {
|
||||||
|
fetchMock.restore(); // init fecth mok for each test
|
||||||
|
});
|
||||||
|
|
||||||
|
it("test description", () => {
|
||||||
|
// mimic API call
|
||||||
|
fetchMock.mock(
|
||||||
|
"*", // capture any fetch call
|
||||||
|
{
|
||||||
|
body: /* body contents */,
|
||||||
|
headers: { "content-type": "application/json" }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const expectedActions = [
|
||||||
|
{ type: TYPE, /* ... */ },
|
||||||
|
{ type: TYPE, /* ... */ }
|
||||||
|
];
|
||||||
|
|
||||||
|
const store = mockStore({ data: value, ... });
|
||||||
|
return store.dispatch(actions.actionCreator())
|
||||||
|
.then(() => {
|
||||||
|
expect(store.getActions()).toEqual(expectedActions);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests for Reducers
|
||||||
|
|
||||||
|
```js
|
||||||
|
import reducer from "path/to/reducer";
|
||||||
|
import * as actions from "path/to/actionCreators";
|
||||||
|
|
||||||
|
it("test description", () => {
|
||||||
|
const initialState = /* satte before the action */;
|
||||||
|
const stateUpdate = /* modified state */;
|
||||||
|
|
||||||
|
const action = actions.actionCreator(stateUpdate);
|
||||||
|
|
||||||
|
const newState = reducer(initialState, action);
|
||||||
|
|
||||||
|
expect(newState.property).toEqual(actual);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests for the Store
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createStore } from "redux";
|
||||||
|
|
||||||
|
import rootReducer from "path/to/rootReducer";
|
||||||
|
import initialState from "path/to/initialState";
|
||||||
|
import * as actions from "path/to/actionCreators";
|
||||||
|
|
||||||
|
it("test description", () => {
|
||||||
|
const store = createStore(toorReducer, initialState);
|
||||||
|
|
||||||
|
const stateUpdate = /* modified state */;
|
||||||
|
const action = actions.actionCreator(stateUpdate);
|
||||||
|
store.dispatch(action);
|
||||||
|
|
||||||
|
const state = store.getState();
|
||||||
|
expect(state).toEqual(stateUpdate);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests for Thunks
|
||||||
|
|
||||||
|
Thunk testing requires the mocking of:
|
||||||
|
|
||||||
|
- store (using `redux-mock-store`)
|
||||||
|
- HTTP calls (using `fetch-mock`)
|
||||||
|
|
||||||
|
```js
|
||||||
|
import thunk from "redux-thunk";
|
||||||
|
import fetchMock from "getch-mock";
|
||||||
|
import configureMockStore from "redux-mock-store";
|
||||||
|
|
||||||
|
import * as actions from "path/to/actionCreators";
|
||||||
|
// import eventual action types constants
|
||||||
|
// import mock data
|
||||||
|
|
||||||
|
const middleware = [thunk]; // mock middlewares
|
||||||
|
const mockStore = configureMockStore(middleware); // mock the store
|
||||||
|
|
||||||
|
it("test description", () => {
|
||||||
|
const data = /* mock data */
|
||||||
|
const expectedAction = { type: TYPE, /* ... */ };
|
||||||
|
|
||||||
|
const actualAction = actions.actionCreator(data);
|
||||||
|
|
||||||
|
expect(actualAction).toEqual(expectedAction);
|
||||||
|
});
|
||||||
|
```
|
Loading…
Add table
Reference in a new issue