Reputation: 446
In the Writing Tests section of Redux,http://rackt.org/redux/docs/recipes/WritingTests.html, how does the store.dispatch(actions.fetchTodos())
not invoke the fetch method, if store.dispatch is literally calling actions.fetchTodos?
it('creates FETCH_TODOS_SUCCESS when fetching todos has been done', (done) => {
nock('http://example.com/')
.get('/todos')
.reply(200, { todos: ['do something'] })
const expectedActions = [
{ type: types.FETCH_TODOS_REQUEST },
{ type: types.FETCH_TODOS_SUCCESS, body: { todos: ['do something'] } }
]
const store = mockStore({ todos: [] }, expectedActions, done)
store.dispatch(actions.fetchTodos())
})
Everytime I try to run something similar to this, I keep getting a fetch is not defined. Even if I use nock. So I have to spy my action to not get the call to fetch.
Here is my unit test:
it('should request a password reset, and then return success on 200', (done) => {
nock('http://localhost:8080/')
.post('/password-reset-requests')
.reply(200);
var email = "[email protected]";
const expectedActions=[
{type: REQUEST_ADD_PASSWORD_RESET_REQUEST},
{type: REQUEST_ADD_PASSWORD_RESET_REQUEST_SUCCESS}
];
const store = mockStore({}, expectedActions, done);
store.dispatch(Actions.addPasswordResetRequest());
here is the action:
export default function addPasswordResetRequest(email){
return dispatch => {
dispatch(requestAddPasswordResetRequest(email));
return addPasswordResetRequestAPI(email)
.then(() =>{
dispatch(requestAddPasswordResetRequestSuccess());
})
.catch((error) => {
dispatch(requestAddPasswordResetRequestFailure(error));
});
};
}
and the function that calls fetch:
export const addPasswordResetRequestAPI = (email) => {
return fetch(
SETTINGS.API_ROOT + '/password-reset-requests',
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: email,
code: NC_SETTINGS.GROUP.code
})
}
)
.then(handleResponse);
};
I'm not sure if the way I am doing is sufficient for the purpose of just testing actions, but then I do run into the problem of store.dispatch only returning the first element of expectedActions, and it doesn't equal the list I supply in the spied addPasswordResetRequest. Below includes the spied action.
it('should request a password reset, and then return success on 200', (done) => {
nock('http://localhost:8080/')
.post('/password-reset-requests')
.reply(200);
Actions.addPasswordResetRequest = spy(() => {
return ([
{type: REQUEST_ADD_PASSWORD_RESET_REQUEST},
{type: REQUEST_ADD_PASSWORD_RESET_REQUEST_SUCCESS}
]
);
});
var email = "[email protected]";
const expectedActions=[
{type: REQUEST_ADD_PASSWORD_RESET_REQUEST},
{type: REQUEST_ADD_PASSWORD_RESET_REQUEST_SUCCESS}
];
const store = mockStore({}, expectedActions, done);
store.dispatch(Actions.addPasswordResetRequest());
Upvotes: 4
Views: 1073
Reputation: 650
The action "addPasswordResetRequest" isn't an action per-say.
it's a composite action with 3 sub-actions
startAction =requestAddPasswordResetRequest,
successAction =requestAddPasswordResetRequestSuccess
failAction =requestAddPasswordResetRequestFailure
I generally tests each action separately. so i would have something like
describe("requestAddPasswordResetRequest", () => {
it("shows the loading spinner or whatever", ...);
it("does some other state change maybe", ...);
});
describe("requestAddPasswordResetRequestSuccess", () => {
it("hides the loading spinner or whatever", ...);
it("changes the password state or something", ...);
});
describe("requestAddPasswordResetRequestFailure", () => {
it("hides the loading spinner or whatever", ...);
it("shows the error somehow", ...);
});
//each test would be something like
it("changes the password state or something", ()=>{
const action = requestAddPasswordResetRequestSuccess({
some : "payload from the server"
});
const newState = myReducer({ state : "somestate" }, action);
expect(newState).to.be.eql("expected result for that action");
});
Notice how in the test i don't need the store or any async logic. thats the beauty of redux (and functional stuff in general), it's simple :)
after this i would have a separate test for the whole thing and make sure that the correct simple actions get dispatched by the composite action, in which i would mock everything (including store and the "fetch" thing, since i just want to test that the actions get fired in the correct order).
if the actions are dispatched in the correct order and each action work separably i would be pretty confident that the thing works as expected.
Hope this helps.
Upvotes: 2