lundi 21 décembre 2015

Redux Async Action Testing timing out

I've read the Async Action Testing section on the redux doc page. But I am having a hard time wrapping my head around testing these actions. This is my action: forgot-password.

function requestAddPasswordResetRequest(){
    return {
        type: REQUEST_ADD_PASSWORD_RESET_REQUEST
    };
}


function requestAddPasswordResetRequestSuccess(){
    return {
        type: REQUEST_ADD_PASSWORD_RESET_REQUEST_SUCCESS

    };
}

function requestAddPasswordResetRequestFailure(error){
    return {
        type: REQUEST_ADD_PASSWORD_RESET_REQUEST_FAILURE,
        payload: error,
        error:true
    };
}

export default function addPasswordResetRequest(email){
    return dispatch => {
        dispatch(requestAddPasswordResetRequest(email));
        return addPasswordResetRequestAPI(email)
            .then(() =>{
                dispatch(requestAddPasswordResetRequestSuccess());
            })
            .catch((error) => {
            dispatch(requestAddPasswordResetRequestFailure(error));
        });
    };
}

this is the function: addPasswordResetRequestAPI(email):

export const addPasswordResetRequest = (email) => {
    return fetch(
        NC_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);
};

handleResponse, just returns a response to see if the email is valid or not.

Here is my test page:

/* globals global, describe, it */

"use strict";


import forOwn from 'lodash/object/forOwn';
import { assert, expect, should } from 'chai';
import { spy } from 'sinon';
import { applyMiddleware } from 'redux';
//import fetch from 'isomorphic-fetch';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import {
    REQUEST_ADD_PASSWORD_RESET_REQUEST,
    REQUEST_ADD_PASSWORD_RESET_REQUEST_SUCCESS,
    REQUEST_ADD_PASSWORD_RESET_REQUEST_FAILURE
} from 'actions/types';
import nock from 'nock';


const middlewares = [ thunk ];
const mockStore = configureMockStore(middlewares);

import Actions from 'actions';

describe('forgot password async actions', () => {

    afterEach(() => {
        nock.cleanAll();
    });

    it('should create an action to request a password reset', (done) => {
        nock('http://localhost:8080/')
        .post('/password-reset-requests')
        .reply(200);

        var email = "test@gmail.com"

        var addPasswordResetRequest = spy(() => {

            return [
                {type: REQUEST_ADD_PASSWORD_RESET_REQUEST},
                {type: REQUEST_ADD_PASSWORD_RESET_REQUEST_SUCCESS}];
            });


        const expectedActions= [
            {type: REQUEST_ADD_PASSWORD_RESET_REQUEST},
            {type: REQUEST_ADD_PASSWORD_RESET_REQUEST_SUCCESS}
        ];

        const store = mockStore({}, expectedActions, done);
        store.dispatch(Actions.addPasswordResetRequest());


  });

});

So when I try to test with the above code: I get a fetch is not defined ReferenceError.

When I try to use a try,catch ala:

try{
        const store = mockStore({}, expectedActions, done);
        store.dispatch(Actions.addPasswordResetRequest(email));
        done();
    } catch(x) {
        done(x);
    }

I still get the same fetch is not defined error. Notice that I am the using Actions version, not the spied one.

When I use the spy() function, and do

const store = mockStore({}, expectedActions, done);
store.dispatch(addPasswordResetRequest());

Then I get the error:

 Error: Expected [ { type: 'REQUEST_ADD_PASSWORD_RESET_REQUEST' }, { type: 'REQUEST_ADD_PASSWORD_RESET_REQUEST_SUCCESS' } ] to equal { type: 'REQUEST_ADD_PASSWORD_RESET_REQUEST' }


Not good, since the expected Action is the same as the return action. However if I do

 var addPasswordResetRequest = spy(() => {

        return {type: REQUEST_ADD_PASSWORD_RESET_REQUEST};
        });

It times out, even after 30000ms.

But if I do:

    describe('forgot password async actions', () => {

    afterEach(() => {
        nock.cleanAll();
    });

    it('should create an action to request a password reset', (done) => {
        nock('http://localhost:8080/')
        .post('/password-reset-requests')
        .reply(200);

        var email = "test@gmail.com"

        var addPasswordResetRequest = spy(() => {

            return {type: REQUEST_ADD_PASSWORD_RESET_REQUEST};
            });


        const expectedActions= [
            {type: REQUEST_ADD_PASSWORD_RESET_REQUEST},
            {type: REQUEST_ADD_PASSWORD_RESET_REQUEST_SUCCESS}
        ];

        //const store = mockStore({}, expectedActions, done);
        //store.dispatch(addPasswordResetRequest());




        try{
            const store = mockStore({}, expectedActions, done);
            store.dispatch(addPasswordResetRequest(email));
            done();
        } catch(x) {
            done(x);
        }

        //console.log(actions);
        //expect(actions.addPasswordResetRequest("email")).to.equal(expectedAction);

  });

});

It passes. I don't know if that is considered sufficient for testing an asynchronous action because I am expecting to get both actions in order.

Also, if I do the above version without the try and catch, then it also times out.

I know I must be missing something very simple. I assume using nock would mock fetch when I was doing Actions.addPasswordResetRequest, but it still is being called. Is it because I am not calling fetch in the Action, but rather in a different file?

I also am a little hazy about the purpose of unit testing an asynchronous action. We just want to ensure that the correct sequence of actions is returned as a result of the input. So if we nock a 200 reply, we want a request, and then a success action to appear. Right?

Aucun commentaire:

Enregistrer un commentaire