mardi 12 juin 2018

Testing failling async calls

I am trying to test an asynchronous thunk action. I am using fetch to handle http calls. This is how my actions look like currently:

export function fetchItems(): ThunkAction<Promise<{}>, {}, {}>  {
  return (dispatch: Dispatch<{}>) => {
    dispatch(requestAction(ItemsActions.FETCH_ITEMS));
    return fetch("http://example.com", {
      method: "GET",
      headers: {
        Authorization: "Signature testTenandId|testUserID",
        [HeadersKey.ContentType]: MediaType.APPLICATION_JSON
      }
    })
    .then(response => {
      if (response.status !== 200) {
        dispatch(withErrorAction(ItemsActions.FETCH_ITEMS_FAILURE, response.statusText));
      }
      return response.json();
    })
    .then(body => {
      return dispatch(withDataAction(ItemsActions.FETCH_ITEMS_SUCCESS, { body }));
    })
    .catch(error => dispatch(withErrorAction(ItemsActions.FETCH_ITEMS_FAILURE, error)));
  };
}

As far as my tests go, I would like to test the action for success and failure. This is what I am attempting: import thunk from "redux-thunk"; import configureMockStore from "redux-mock-store";

import * as actions from "../actions";
import { ItemsActions } from "../constants/ActionTypes";
import { Item } from "../model";;

const mockStore = configureMockStore([thunk]);
const errorResponse = { response: undefined, error: "You did it wrong" };

const item: Item = {
  displayName: "foo",
  domain: "bar",
};

const initialState = item;
const store = mockStore(initialState);

describe("Items actions", () => {
  describe("Async actions", () => {
    afterEach(() => {
      jest.resetAllMocks();
      jest.restoreAllMocks();
      store.clearActions();
    });

    it("Creates an action to fetch items on success", () => {
      const item: Item = {
        displayName: "foo",
        domain: "bar",
      };

      const mockResponse = (status, response) => {
        return new (window as any).Response(response, {
          status,
          headers: {
            Authorization: "Signature testTenandId|ttUserID",
            "Content-Type": "application/json"
          }
        });
      };

      window.fetch = jest.fn().mockImplementation(() =>
        Promise.resolve(mockResponse(200, JSON.stringify(item))));

      return store.dispatch(actions.fetchItems()).then(() => {
        expect(store.getActions()).toEqual([
          { type: ItemsActions.FETCH_ITEMS },
          { type: ItemsActions.FETCH_ITEMS_SUCCESS, data: { body : items } }
        ]);
      });
    });


    it("Creates an action to fetch items on falure", () => {
      const expectedActions = [
        { type: ItemsActions.FETCH_ITEMS },
        {
          type: ItemsActions.FETCH_ITEMS_FAILURE,
          error: errorResponse.error
        }
      ];

      const mockResponse = (status, response) => {
        return new (window as any).Response(response, {
          status,
          headers: {
            Authorization: "Signature testTenandId|ttUserID",
            "Content-Type": "application/json"
          }
        });
      };

      window.fetch = jest.fn().mockImplementation(() =>
        Promise.resolve(mockResponse(400, errorResponse)));

      return store.dispatch(actions.fetchItems()).then(() => {
        expect(store.getActions()).toEqual(expectedActions);
      });
    });
  });
});

I am getting this error in the console when I run the tests

Expected value to equal:
      [{"type": "ITEMS/FETCH_ITEMS"}, {"error": "You did it wrong", "type": "ITEMS/FETCH_ITEMS_FAILURE"}]
    Received:
      [{"type": "ITEMS/FETCH_ITEMS"}, {"error": "Bad Request", "type": "ITEMS/FETCH_ITEMS_FAILURE"}, {"error": [TypeError: self.body.on is not a function], "type": "ITEMS/FETCH_ITEMS_FAILURE"}]

I am wondering if I am mocking the response correctly in my tests or if the way I am parsing the response and handling errors in my actions in incorrect? Does anybody know what I am missing here?

Aucun commentaire:

Enregistrer un commentaire