diff --git a/client/src/tests/redux/actions/auth/authAction.test.jsx b/client/src/tests/redux/actions/auth/authAction.test.jsx new file mode 100644 index 0000000..8b99367 --- /dev/null +++ b/client/src/tests/redux/actions/auth/authAction.test.jsx @@ -0,0 +1,221 @@ +import moxios from 'moxios'; +import thunk from 'redux-thunk'; +import configureMockStore from 'redux-mock-store'; +import { data, response, LocalStorage, errorResponse, expiredToken } from './authActionMockData'; +import instance from '../../../../config/axios'; +import * as types from '../../../../redux/actions/types'; + +import { signIn, signOut, signUp } from "../../../../redux/actions/auth"; + + +const middleware = [thunk]; +const mockStore = configureMockStore(middleware); + +window.localStorage = new LocalStorage(); + +describe('Authorization redux actions test', () => { + beforeEach(() => { + moxios.install(instance); + }); + + afterEach(() => { + moxios.uninstall(instance); + }); + + it('Test the signUp dispatch action', (done) => { + const store = mockStore({}); + moxios.wait(() => { + const request = moxios.requests.mostRecent(); + request.respondWith({ + status: 200, + response + }); + }); + return store.dispatch(signUp(data)).then(() => { + expect(store.getActions()[0]).toEqual({ + type: types.IS_LOGGED_IN, + payload: false + }); + expect(store.getActions()[1]).toEqual({ + type: types.IS_LOADING, + payload: true + }); + expect(store.getActions()[2]).toEqual({ + type: types.SIGN_UP, + payload: response + }); + done(); + }); + }); + + it('Test for signUp errors dispatch action', (done) => { + localStorage.removeItem('aTeamsToken'); + moxios.wait(() => { + const request = moxios.requests.mostRecent(); + request.respondWith({ + status: 401, + response + }); + }); + + const store = mockStore({}); + return store.dispatch(signUp(data)).then(() => { + expect(store.getActions()[0]).toEqual({ + type: types.IS_LOGGED_IN, + payload: false + }); + expect(store.getActions()[1]).toEqual({ + type: types.IS_LOADING, + payload: true + }); + expect(store.getActions()[2].type).toEqual(types.SIGN_UP); + expect(store.getActions()[3]).toEqual({ + type: types.IS_LOADING, + payload: false + }); + done(); + }); + }); + + it('should test dispatch action for incorrect email', (done) => { + localStorage.removeItem('aTeamsToken'); + moxios.wait(() => { + const request = moxios.requests.mostRecent(); + request.respondWith({ + status: 200, + response: errorResponse + }); + }); + + const store = mockStore({}); + return store.dispatch(signUp(data)).then(() => { + expect(store.getActions()[0]).toEqual({ + type: types.IS_LOGGED_IN, + payload: false + }); + expect(store.getActions()[1]).toEqual({ + type: types.IS_LOADING, + payload: true + }); + expect(store.getActions()[2].payload).toEqual({ "message": "login with an andela email" }); + expect(store.getActions()[3]).toEqual({ + type: types.IS_LOADING, + payload: false + }); + expect(store.getActions()[4]).toEqual({ + type: types.IS_LOGGED_IN, + payload: false + }); + done(); + }); + }); + + it('Should test dispatch action for signIn ', (done) => { + localStorage.removeItem('aTeamsToken'); + + moxios.wait(() => { + const request = moxios.requests.mostRecent(); + request.respondWith({ + status: 200, + response + }); + }); + + const store = mockStore({}); + return store.dispatch(signIn(data)).then(() => { + expect(store.getActions()[0]).toEqual({ + type: types.IS_LOGGED_IN, + payload: false + }); + expect(store.getActions()[1]).toEqual({ + type: types.IS_LOADING, + payload: true + }); + expect(store.getActions()[2]).toEqual({ + type: types.SIGN_IN, + payload: response + }); + expect(store.getActions()[3]).toEqual({ + type: types.IS_LOADING, + payload: false + }); + expect(store.getActions()[4]).toEqual({ + type: types.IS_LOGGED_IN, + payload: true, + name: 'TEST' + }); + done(); + }); + }); + + it('Should test dispatch action for signIn with expired token', (done) => { + localStorage.removeItem('aTeamsToken'); + moxios.wait(() => { + const request = moxios.requests.mostRecent(); + request.respondWith({ + status: 200, + response: expiredToken + }); + }); + const store = mockStore({}); + return store.dispatch(signIn(data)).then(() => { + const actual = localStorage.getItem('aTeamsToken'); + expect(actual).toEqual(null); + done(); + }); + }); + + it('should test dispatch action for signIn errors', (done) => { + localStorage.removeItem('aTeamsToken'); + moxios.wait(() => { + const request = moxios.requests.mostRecent(); + request.respondWith({ + status: 401, + response + }); + }); + + const store = mockStore({}); + return store.dispatch(signIn(data)).then(() => { + expect(store.getActions()[0]).toEqual({ + type: types.IS_LOGGED_IN, + payload: false + }); + expect(store.getActions()[1]).toEqual({ + type: types.IS_LOADING, + payload: true + }); + expect(store.getActions()[2].type).toEqual(types.SIGN_IN); + expect(store.getActions()[3]).toEqual({ + type: types.IS_LOADING, + payload: false + }); + done(); + }); + }); + + it('should test dispatch action for signOut', (done) => { + const store = mockStore({}); + localStorage.setItem('aTeamsToken', response.data.userToken); + store.dispatch(signOut()); + + expect(store.getActions()[0]).toEqual({ + type: types.IS_LOGGED_IN, + payload: true, + name: 'TEST' + }); + expect(store.getActions()[1]).toEqual({ + type: types.IS_LOADING, + payload: true + }); + expect(store.getActions()[2]).toEqual({ + type: types.IS_LOADING, + payload: false + }); + expect(store.getActions()[3]).toEqual({ + type: types.IS_LOGGED_IN, + payload: false + }); + done(); + }); +}); diff --git a/client/src/tests/redux/actions/auth/authActionMockData.js b/client/src/tests/redux/actions/auth/authActionMockData.js new file mode 100644 index 0000000..06b2a00 --- /dev/null +++ b/client/src/tests/redux/actions/auth/authActionMockData.js @@ -0,0 +1,56 @@ +const data = { + displayName: 'Testing', + email: 'test.test@andela.com', + googleId: '123456', + photo: 'http://photo.com' +}; + +const response = { + data: { + userToken: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ0YXBzLWNsaWVudC10ZXN0aW5nIiwiaWF0IjoxNTM5MTk2NzQ4LCJleHAiOjI3MDY4MDYzNDgsImF1ZCI6ImFuZGVsYS5jb20iLCJzdWIiOiJhbmRlbGFAZXhhbXBsZS5jb20iLCJlbWFpbCI6InRlc3QudGVzdEBhbmRlbGEuY29tIn0.KfCtjrxw2e-Jmntlc2Cjv0qn9A9ClzOhJJUz4VLIUZw', + user: { + id: '1', + role: 'member' + } + } +}; +const expiredToken = { + data: { + userToken: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ0YXBzLWNsaWVudC10ZXN0aW5nIiwiaWF0IjoxNTM5MTk2NzQ4LCJleHAiOjExNjA1MDU1NDgsImF1ZCI6ImFuZGVsYS5jb20iLCJzdWIiOiJhbmRlbGFAZXhhbXBsZS5jb20iLCJlbWFpbCI6InRlc3QudGVzdEBnbWFpbC5jb20ifQ.D2B8J1nIYo-h0yz_GpYTabNVINEpF4SIXN5ifv32X4o', + user: { + id: '1', + role: 'member' + } + } +}; + +const errorResponse = { + errors: 'Andela emails only' +}; + +// Sourced from https://github.com/facebook/jest/issues/2098 +class LocalStorage { + store = {}; + setItem = (key, val) => { + this.store[key] = val; + return this.store; + }; + getItem = key => this.store[key]; + removeItem = key => { + Reflect.deleteProperty(this.store[key]); + }; + clear = () => { + this.store = {}; + return this.store; + }; +} + + +export { + data, + response, + errorResponse, + expiredToken, + LocalStorage +}; + diff --git a/client/src/tests/redux/reducers/authReducer.test.jsx b/client/src/tests/redux/reducers/authReducer.test.jsx new file mode 100644 index 0000000..504e795 --- /dev/null +++ b/client/src/tests/redux/reducers/authReducer.test.jsx @@ -0,0 +1,33 @@ +import authReducer from '../../../redux/reducers/authReducer'; +import * as types from '../../../redux/actions/types'; + +describe('Authorization Reducer Test', () => { + it('should update auth object on sign up state', (done) => { + const action = { + type: types.SIGN_UP, + payload: true + }; + expect(authReducer({ auth: {} }, action)).toEqual({ "auth": true }); + done(); + }); + + it('should update state if is logged in', (done) => { + const action = { + type: types.IS_LOGGED_IN, + payload: true, + name: 'TEST' + }; + const expected = { "auth": {}, "loggedIn": true, "name": "TEST" }; + expect(authReducer({ auth: {} }, action)).toEqual(expected); + done(); + }); + + it('should return the state on default', (done) => { + const action = { + type: types.DEFAULT + }; + expect(authReducer({ auth: {} }, action)).toEqual({ "auth": {} }); + done(); + }); +}); +