diff --git a/_test_/App.spec.js b/_test_/App.spec.js
index f77c3d4..55eee89 100644
--- a/_test_/App.spec.js
+++ b/_test_/App.spec.js
@@ -26,6 +26,6 @@ describe('App', () => {
expect(app.find('Switch').length).toBe(1);
});
it('renders a Route component', () => {
- expect(app.find('Route').length).toBe(17);
+ expect(app.find('Route').length).toBe(19);
});
});
diff --git a/_test_/Navbar.spec.js b/_test_/Navbar.spec.js
index 8ef2465..f55f1b6 100644
--- a/_test_/Navbar.spec.js
+++ b/_test_/Navbar.spec.js
@@ -1,6 +1,7 @@
import React from 'react';
import expect from 'expect';
-import Enzyme, { shallow } from 'enzyme';
+import Enzyme, { mount } from 'enzyme';
+import { BrowserRouter } from 'react-router-dom';
import Adapter from 'enzyme-adapter-react-16';
import Navbar, { Navbar as Nav } from '../src/components/NavigationBar';
@@ -25,8 +26,12 @@ describe('Navbar', () => {
user: {},
},
});
- app = shallow();
- res = app.dive().dive();
+ app = mount(
+
+
+ ,
+ );
+ res = app.find('Navbar');
});
it('renders successfully', () => {
diff --git a/_test_/authReducer.spec.js b/_test_/authReducer.spec.js
index a8d1122..6e8b960 100644
--- a/_test_/authReducer.spec.js
+++ b/_test_/authReducer.spec.js
@@ -22,7 +22,7 @@ describe('Login reducer', () => {
...initialState,
isAuthenticated: false,
user: {},
- loading: true,
+ loading: false,
});
});
diff --git a/_test_/errorReducer.spec.js b/_test_/errorReducer.spec.js
index c484220..01c1974 100644
--- a/_test_/errorReducer.spec.js
+++ b/_test_/errorReducer.spec.js
@@ -1,13 +1,13 @@
import errorReducer from '../src/reducers/errorReducer';
import {
- GET_ERRORS, LOGIN_LOADING,
+ GET_ERRORS, AUTH_LOADING,
} from '../src/actions/types';
describe('Error reducer', () => {
it('should set loading to true before displaying error', () => {
expect(
errorReducer({}, {
- type: LOGIN_LOADING,
+ type: AUTH_LOADING,
loading: true,
}),
).toEqual({
diff --git a/_test_/loginAction.spec.js b/_test_/loginAction.spec.js
index 7bf874b..191453c 100644
--- a/_test_/loginAction.spec.js
+++ b/_test_/loginAction.spec.js
@@ -1,10 +1,9 @@
import moxios from 'moxios';
import thunk from 'redux-thunk';
import configureMockStore from 'redux-mock-store';
-import { SET_CURRENT_USER, GET_ERRORS, LOGIN_LOADING } from '../src/actions/types';
+import { SET_CURRENT_USER, GET_ERRORS, AUTH_LOADING } from '../src/actions/types';
import mockLoginData from '../src/utils/loginMockStore';
import { loginUser, socialLogin } from '../src/actions/authActions';
-import axios from '../src/config/axiosInstance';
const mockStore = configureMockStore([thunk]);
let store = mockStore();
@@ -12,11 +11,11 @@ const { successResponse, errorResponse } = mockLoginData;
describe('Login actions', () => {
beforeEach(() => {
- moxios.install(axios);
+ moxios.install();
store.clearActions();
});
- afterEach(() => moxios.uninstall(axios));
+ afterEach(() => moxios.uninstall());
it('Returns failure if login was unsuccessful', (done) => {
moxios.stubRequest('https://ah-nyati-backend-staging.herokuapp.com/api/v1/auth/login', {
status: 400,
@@ -24,7 +23,7 @@ describe('Login actions', () => {
});
const expectedActions = [
{
- type: LOGIN_LOADING,
+ type: AUTH_LOADING,
},
{
payload: errorResponse.message,
@@ -45,7 +44,7 @@ describe('Login actions', () => {
});
const expectedActions = [
{
- type: LOGIN_LOADING,
+ type: AUTH_LOADING,
},
{
payload: successResponse.data[0],
diff --git a/src/actions/authActions.js b/src/actions/authActions.js
index a5df68d..fa6bde8 100644
--- a/src/actions/authActions.js
+++ b/src/actions/authActions.js
@@ -1,13 +1,14 @@
import { toast } from 'react-toastify';
-import axios from '../config/axiosInstance';
+import axios from '../api/axios';
import {
- GET_ERRORS, SET_CURRENT_USER, LOGIN_LOADING,
+ GET_ERRORS, SET_CURRENT_USER, AUTH_LOADING, REMOVE_CURRENT_USER,
} from './types';
import setAuthToken from '../utils/setAuthToken';
+
// set logged in user
export const setLoginLoading = () => ({
- type: LOGIN_LOADING,
+ type: AUTH_LOADING,
});
// set logged in user
@@ -16,9 +17,19 @@ export const setCurrentUser = decoded => ({
payload: decoded,
});
+// remove logged in user
+export const removeCurrentUser = () => ({
+ type: REMOVE_CURRENT_USER,
+});
+
+export const logoutError = error => ({
+ type: GET_ERRORS,
+ payload: error.message,
+});
+
export const loginUser = userData => (dispatch) => {
dispatch(setLoginLoading());
- return axios
+ return axios()
.post('/auth/login', userData)
.then((res) => {
// save token to local storage
@@ -45,6 +56,19 @@ export const loginUser = userData => (dispatch) => {
});
});
};
+
+export const logoutUser = (history, user) => (dispatch) => {
+ return axios()
+ .post('/auth/logout', user)
+ .then(() => {
+ localStorage.removeItem('jwtToken');
+ localStorage.removeItem('user');
+ dispatch(removeCurrentUser());
+ history.push('/');
+ })
+ .catch(error => dispatch(logoutError(error)));
+};
+
/**
* @description - logs in a user his using social account details
* @param {string} token - the request token
diff --git a/src/actions/types.js b/src/actions/types.js
index 36002b6..beda714 100644
--- a/src/actions/types.js
+++ b/src/actions/types.js
@@ -18,7 +18,7 @@ export const GET_CURRENT_USER = 'GET_CURRENT_USER';
export const CREATE_ARTICLE_START = 'CREATE_ARTICLE_START';
export const CREATE_ARTICLE_SUCCESS = 'CREATE_ARTICLE_SUCCESS';
export const CREATE_ARTICLE_FAILURE = 'CREATE_ARTICLE_FAILURE';
-export const LOGIN_LOADING = 'LOGGIN_LOADING';
+export const AUTH_LOADING = 'AUTH_LOADING';
export const SUCCESS = 'SUCCESS';
export const SIGNUP_LOADING = 'SIGNUP_LOADING';
export const VIEW_SINGLE_ARTICLE = 'VIEW_SINGLE_ARTICLE';
@@ -28,3 +28,4 @@ export const PROFILE_LOADING = 'PROFILE_LOADING';
export const PROFILE_NOT_FOUND = 'PROFILE_NOT_FOUND';
export const FETCH_PROFILE_ARTICLE = 'FETCH_ALL_ARTICLE';
export const PROFILE_ARTICLE_LOADING = 'PROFILE_ARTICLE_LOADING';
+export const REMOVE_CURRENT_USER = 'REMOVE_CURRENT_USER';
diff --git a/src/components/App.js b/src/components/App.js
index 9792640..9e423a8 100644
--- a/src/components/App.js
+++ b/src/components/App.js
@@ -59,12 +59,14 @@ const App = () => (
-
-
+
+
+
+
diff --git a/src/components/NavigationBar/index.jsx b/src/components/NavigationBar/index.jsx
index 8e4cabe..5f29444 100644
--- a/src/components/NavigationBar/index.jsx
+++ b/src/components/NavigationBar/index.jsx
@@ -1,8 +1,9 @@
import React from 'react';
-import { Link } from 'react-router-dom';
+import { Link, withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import getUser from '../../actions/getUserAction';
+import { logoutUser } from '../../actions/authActions';
import '../../variables.scss';
import './index.scss';
@@ -25,14 +26,18 @@ export class Navbar extends React.Component {
userName,
},
} = user;
-
this.props.getUser(userName);
}
}
+ logOut = () => {
+ const { logoutUser, history } = this.props;
+ logoutUser(history);
+ }
+
componentDidUpdate(prevProps) {
const { authUser: { userName } } = this.props;
- if (prevProps.authUser.userName !== userName) {
+ if (userName && (prevProps.authUser.userName !== userName)) {
this.props.getUser(userName);
}
}
@@ -90,13 +95,7 @@ export class Navbar extends React.Component {
notification,
} = this.state;
- const {
- authUser,
- loggedInUser: {
- userName,
- imageUrl,
- },
- } = this.props;
+ const { authUser : {userName, imageUrl }, authUser } = this.props;
const article = this.checkWidth(, 'Articles');
const notify = this.checkWidth(, 'Notifications');
@@ -206,7 +205,11 @@ export class Navbar extends React.Component {
Create Article
My Articles
Edit Profile
- Log Out
+
+
+ Log Out
+
+
@@ -227,4 +230,4 @@ const mapStateToProps = state => ({
authUser: state.auth.user,
});
-export default connect(mapStateToProps, { getUser })(Navbar);
+export default withRouter(connect(mapStateToProps, { getUser, logoutUser })(Navbar));
diff --git a/src/reducers/authReducer.js b/src/reducers/authReducer.js
index f817a65..c9cad80 100644
--- a/src/reducers/authReducer.js
+++ b/src/reducers/authReducer.js
@@ -1,6 +1,6 @@
import isEmpty from '../validations/isEmpty';
import {
- SET_CURRENT_USER, LOGIN_LOADING,
+ SET_CURRENT_USER, AUTH_LOADING, REMOVE_CURRENT_USER,
} from '../actions/types';
const initialState = {
@@ -10,7 +10,7 @@ const initialState = {
};
const reducer = (state = initialState, action) => {
switch (action.type) {
- case LOGIN_LOADING:
+ case AUTH_LOADING:
return {
...state,
loading: true,
@@ -22,6 +22,11 @@ const reducer = (state = initialState, action) => {
user: action.payload,
loading: false,
};
+ case REMOVE_CURRENT_USER:
+ return {
+ ...initialState,
+ loading: false,
+ };
default:
return state;
}
diff --git a/src/reducers/errorReducer.js b/src/reducers/errorReducer.js
index ff85d92..55d2a13 100644
--- a/src/reducers/errorReducer.js
+++ b/src/reducers/errorReducer.js
@@ -1,4 +1,4 @@
-import { GET_ERRORS, LOGIN_LOADING } from '../actions/types';
+import { GET_ERRORS, AUTH_LOADING } from '../actions/types';
const initialState = {
error: {
@@ -10,7 +10,7 @@ const initialState = {
export default function (state = initialState, action) {
switch (action.type) {
- case LOGIN_LOADING:
+ case AUTH_LOADING:
return {
...state,
loading: true,
diff --git a/src/reducers/index.js b/src/reducers/index.js
index e2cd3a7..f078ac1 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -29,6 +29,5 @@ export default combineReducers({
toastr: toastrReducer,
fetchCategoryReducer,
updateArticlesReducer,
-
profile: profileReducer,
});