mirror of
https://github.com/m-lamonaca/dev-notes.git
synced 2025-06-09 03:07:13 +00:00
feat: restructure docs into "chapters" (#12)
* feat(docker, k8s): create containers folder and kubernetes notes
This commit is contained in:
parent
b1cb858508
commit
2725e3cb70
92 changed files with 777 additions and 367 deletions
156
docs/languages/javascript/react/redux-tests.md
Normal file
156
docs/languages/javascript/react/redux-tests.md
Normal file
|
@ -0,0 +1,156 @@
|
|||
# Redux Testing
|
||||
|
||||
## Tests for Connected Components
|
||||
|
||||
Connected components are wrapped 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 unconnected 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 iteration
|
||||
dom.find("selector").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
|
||||
|
||||
it("test description", () => {
|
||||
const data = /* mock data */
|
||||
const expectedAction = { type: TYPE, /* ... */ };
|
||||
|
||||
const actualAction = actions.actionCreator(data);
|
||||
|
||||
expect(actualAction).toEqual(expectedAction);
|
||||
});
|
||||
```
|
||||
|
||||
## Tests for Reducers
|
||||
|
||||
```js
|
||||
import reducer from "path/to/reducer";
|
||||
import * as actions from "path/to/actionCreators";
|
||||
|
||||
it("test description", () => {
|
||||
const initialState = /* state before the action */;
|
||||
const finalState = /* expected state after the action */
|
||||
const data = /* data passed to the action creator */;
|
||||
|
||||
const action = actions.actionCreator(data);
|
||||
const newState = reducer(initialState, action);
|
||||
|
||||
expect(newState).toEqual(finalState);
|
||||
});
|
||||
```
|
||||
|
||||
## 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(storeReducer, initialState);
|
||||
|
||||
const expectedState = /* state after the update */
|
||||
|
||||
const data = /* action creator input */;
|
||||
const action = actions.actionCreator(data);
|
||||
store.dispatch(action);
|
||||
|
||||
const state = store.getState();
|
||||
expect(state).toEqual(expectedState);
|
||||
});
|
||||
```
|
||||
|
||||
## 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 "fetch-mock";
|
||||
import configureMockStore from "redux-mock-store";
|
||||
|
||||
// needed for testing async thunks
|
||||
const middleware = [thunk]; // mock middlewares
|
||||
const mockStore = configureMockStore(middleware); // mock the store
|
||||
|
||||
import * as actions from "path/to/actionCreators";
|
||||
// import eventual action types constants
|
||||
// import mock data
|
||||
|
||||
describe("Async Actions", () => {
|
||||
afterEach(() => {
|
||||
fetchMock.restore(); // init fetch mock for each test
|
||||
});
|
||||
|
||||
it("test description", () => {
|
||||
// mimic API call
|
||||
fetchMock.mock(
|
||||
"*", // capture any fetch call
|
||||
{
|
||||
body: /* body contents */,
|
||||
headers: { "content-type": "application/json" }
|
||||
}
|
||||
);
|
||||
|
||||
// expected action fired from the thunk
|
||||
const expectedActions = [
|
||||
{ type: TYPE, /* ... */ },
|
||||
{ type: TYPE, /* ... */ }
|
||||
];
|
||||
|
||||
const store = mockStore({ data: value, ... }); // init mock store
|
||||
|
||||
return store.dispatch(actions.actionCreator()) // act
|
||||
.then(() => {
|
||||
expect(store.getActions()).toEqual(expectedActions); // assert
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue