samuelchvez/redux-jwt

View on GitHub
src/actions.test.js

Summary

Maintainability
C
1 day
Test Coverage
import 'whatwg-fetch';
import fetchMock from 'fetch-mock';
import deepFreeze from 'deep-freeze';
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import jwt_decode from 'jwt-decode';

import * as actions from './actions';
import * as types from './types';


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

// Mock api
const api = {
  login(username, password) {
    return fetch(
      'http://localhost:8000/jwt-auth/',
      {
        method: 'POST',
        body: { username, password }
      }
    ).then(res => res.json()
    ).then(({ token }) => token)
  }
}

const login = actions.login(api.login);

describe('redux-jwt actions', () => {
  it('should get a logout action.', () =>
    expect(actions.logout()).toEqual({
      type: types.LOGOUT,
      payload: {}
    }));

  it('should get a login start action.', () =>
    expect(actions.loginStart('test')).toEqual({
      type: types.LOGIN_START,
      payload: {
        username: 'test'
      }
    }));

  it('should get a login success action.', () =>
    expect(actions.loginSuccess('123', { a: 1 })).toEqual({
      type: types.LOGIN_SUCCESS,
      payload: {
        token: '123',
        decoded: { a: 1 }
      }
    }));

  it('should get a login error action.', () =>
    expect(actions.loginError('Test', { b: 1 })).toEqual({
      type: types.LOGIN_ERROR,
      payload: {
        message: 'Test',
        extra: { b: 1 }
      }
    }));

  it('generates a sequence of actions when successful login request.', () => {
    const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InJvb3QiLCJ1c2VyX2lkIjoxLCJlbWFpbCI6InJvb3RAcm9vdC5jb20iLCJleHAiOjE1NTMwMDYyOTF9.xW_yz51nfNASkEPyYiUlEDAQ_CKkWSB9tqjsixkGHsg';
    const username = 'test';
    const password = 'pass123';
    const decoded = jwt_decode(token);

    // Intercept posts to jwt-auth
    fetchMock.once(
      'http://localhost:8000/jwt-auth/',
      {
        token
      }
    );

    // Expected action sequence
    const expectedActions = [
      {
        type: types.LOGIN_START,
        payload: { username }
      },
      {
        type: types.LOGIN_SUCCESS,
        payload: { token, decoded  }
      }
    ]

    // Store mock
    const store = mockStore({
      token: null,
      decoded: null,
      error: {
        message: null,
        extra: null
      }
    })

    return store.dispatch(login(username, password))
      .then(() => {
        expect(store.getActions()).toEqual(expectedActions)
      })
  })

  it('generates a sequence of actions when login request fails and handle error promise.', () => {
    const username = 'test';
    const password = 'pass123';
    const errorStatusMessage = "Bad Request"
    const promiseResolvedValue = {
      errors: ["Unable to login. Invalid credentialls"]
    }

    // Intercept posts to jwt-auth
    fetchMock.once(
      'http://localhost:8000/jwt-auth/',
      {
        throws: {
          message: errorStatusMessage,
          promise: Promise.resolve(promiseResolvedValue)
        }
      }
    );

    // Expected action sequence
    const expectedActions = [
      {
        type: types.LOGIN_START,
        payload: { username }
      },
      {
        type: types.LOGIN_ERROR,
        payload: {
          message: errorStatusMessage,
          extra: promiseResolvedValue
        }
      }
    ]

    // Store mock
    const store = mockStore({
      token: null,
      decoded: null,
      error: {
        message: null,
        extra: null
      }
    })

    return store.dispatch(login(username, password))
      .then(() => {
        expect(store.getActions()).toEqual(expectedActions)
      })
  })

  it('generates a sequence of actions when login request fails and doesn\'t handle error promise.', () => {
    const username = 'test';
    const password = 'pass123';
    const errorStatusMessage = "Bad Request"
    const promiseResolvedValue = {
      errors: ["Unable to login. Invalid credentialls"]
    }

    // Intercept posts to jwt-auth
    fetchMock.once(
      'http://localhost:8000/jwt-auth/',
      {
        throws: {
          message: errorStatusMessage
        }
      }
    );

    // Expected action sequence
    const expectedActions = [
      {
        type: types.LOGIN_START,
        payload: { username }
      },
      {
        type: types.LOGIN_ERROR,
        payload: {
          message: errorStatusMessage,
          extra: {
            message: errorStatusMessage
          }
        }
      }
    ]

    // Store mock
    const store = mockStore({
      token: null,
      decoded: null,
      error: {
        message: null,
        extra: null
      }
    })

    return store.dispatch(login(username, password))
      .then(() => {
        expect(store.getActions()).toEqual(expectedActions)
      })
  })
});