6
votes

I'm working on a POC with React, Redux and Firebase. I'm currently looking at how to test action creators. I've followed this - https://redux.js.org/recipes/writing-tests#async-action-creators guide and it's been helpful so far. However, as a simple example I want to test that an action is dispatched after successfully authenticating with Firebase like so -

Action creator

export const authenticate = (username, password) => {
  return dispatch => {
    firebase.auth().signInWithEmailAndPassword(username, password)
      .then(() => {
        dispatch(authenticationSuccessful())
      })
      .catch(() => {

      });
  }
};

Action

const authenticationSuccessful = () => {
  return {
    type: actionTypes.AUTHENTICATION_SUCCESSFUL
  };
};

For the testing side of things I have jest, redux-mock-store and expect. I've researched as to what other people are using for this scenario and I haven't found a definitive answer, I've also looked at https://www.npmjs.com/package/firebase-mock but I don't know if this is a popular choice within the community.

Really appreciate any help in advance!

1

1 Answers

3
votes

This answer fits the bill Best way to unit test code that depends on http calls using Jest?

According to that answer, this will overwrite the signInWithEmailAndPassword allowing your code to pass without hitting firebase. The below example may need some tweaking. Not sure of the scope of dispatch.

jest.mock('pathToFireBase', () => ({
   signInWithEmailAndPassword(email, password) {
     return Promise.resolve({name: 'someUser'})
   }
}))

const dispatch = jest.fn();
firebase.auth().signInWithEmailAndPassword(username, password)
expect(dispatch.mock.calls.length).toBe(1);

Another option (for Node.js) is to use something like VCR. An option being sepia. Its built by LinkedIn so probably better maintained and tested. With this tool you record your requests once, saving responses, and replaying when called. This option avoids mocking, but keeps the uint tests speedy with predefined responses. I'm unaware of a frontend option like this though.


Firebasemock looks like a great option. Although I can't see a signInWithEmailAndPassword. Authentication is done by explicitly setting the state. authentication example.

mocksdk.auth().changeAuthState({
  uid: 'testUid',
  provider: 'custom',
  token: 'authToken',
  expires: Math.floor(new Date() / 1000) + 24 * 60 * 60,
  auth: {
    isAdmin: true
  }
});
mocksdk.auth().flush();
console.assert(document.location.href === '#/admin', 'redirected to admin');