Skip to content

Instantly share code, notes, and snippets.

@therealparmesh
Created January 24, 2019 00:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save therealparmesh/9f7ab1ed35e4b14d96e0236a46c9e0bf to your computer and use it in GitHub Desktop.
Save therealparmesh/9f7ab1ed35e4b14d96e0236a46c9e0bf to your computer and use it in GitHub Desktop.
Redux Saga example
const { REQUEST, SUCCESS, FAILURE } = makeApiActionTypes('GET_USERS');
// register the reducer somewhere
const usersReducer = makeApiReducer({ REQUEST, SUCCESS, FAILURE });
const makeSelectUserById = id => state => state.users.byId[id];
function* getUsersSaga() {
try {
const { data } = yield call(axios, {
method: 'GET',
url: '/users',
});
// normalize server response if need be
// example: yield call(normalizeResponse, response);
const { response: users } = data;
yield put({
type: SUCCESS,
payload: users,
});
} catch (error) {
yield put({
type: FAILURE,
payload: error,
error: true,
});
}
}
// register the saga somewhere
takeLatest(REQUEST, getUsersSaga);
// test helper
const axiosParameters = {
method: 'GET',
url: '/users',
};
// test helper
const axiosResponse = {
data: {
response: usersByIdJson,
},
};
// example saga integration tests (including the reducer)
describe('get user saga', async () => {
it('gets the users', () => {
const { storeState } = expectSaga(getUsersSaga)
.provide([[call(axios, axiosParameters), axiosResponse]])
.withReducer(usersReducer)
.put({
type: SUCCESS,
payload: axiosResponse.data.response,
})
.run();
expect(storeState).toEqual({
byId: usersByIdJson,
_loading: false,
_error: false,
_errorMessage: '',
});
});
it('handles errors', async () => {
const error = new Error('error');
const { storeState } = expectSaga(getUsersSaga)
.provide([[call(axios, axiosParameters), throwError(error)]])
.withReducer(usersReducer)
.put({
type: FAILURE,
payload: error,
error: true,
})
.run();
expect(storeState).toEqual({
byId: {},
_loading: false,
_error: true,
_errorMessage: 'error',
});
});
});
// example makeApiActionTypes
function makeApiActionTypes(actionType) {
const suffixes = ['REQUEST', 'SUCCESS', 'FAILURE'];
return suffixes.reduce((previous, suffix) => {
previous[suffix] = `${actionType}_${suffix}`;
return previous;
}, {});
}
// example makeApiReducer
function makeApiReducer({ REQUEST, SUCCESS, FAILURE }) {
const initialState = {
byId: {},
_loading: false,
_error: false,
_errorMessage: '',
};
return (state = initialState, { type, payload }) => {
switch (type) {
case REQUEST:
return {
...state,
_loading: true,
_error: false,
_errorMessage: '',
};
case SUCCESS:
return {
byId: payload,
_loading: false,
_error: false,
_errorMessage: '',
};
case FAILURE:
return {
...state,
_loading: false,
_error: true,
_errorMessage: payload.message,
};
default:
return state;
}
};
}
// example usage
dispatch({ type: REQUEST });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment