Skip to content

Commit

Permalink
Merge pull request #43 from andela/ft-implement-logout-functionality-…
Browse files Browse the repository at this point in the history
…168221047

#168221047 Setup user logout functionality
  • Loading branch information
fob413 authored Sep 3, 2019
2 parents 859c1a2 + a36b964 commit 6fdce5a
Show file tree
Hide file tree
Showing 12 changed files with 75 additions and 37 deletions.
2 changes: 1 addition & 1 deletion _test_/App.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
11 changes: 8 additions & 3 deletions _test_/Navbar.spec.js
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -25,8 +26,12 @@ describe('Navbar', () => {
user: {},
},
});
app = shallow(<Navbar store={store} user={user} />);
res = app.dive().dive();
app = mount(
<BrowserRouter>
<Navbar store={store} user={user} />
</BrowserRouter>,
);
res = app.find('Navbar');
});

it('renders successfully', () => {
Expand Down
2 changes: 1 addition & 1 deletion _test_/authReducer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('Login reducer', () => {
...initialState,
isAuthenticated: false,
user: {},
loading: true,
loading: false,
});
});

Expand Down
4 changes: 2 additions & 2 deletions _test_/errorReducer.spec.js
Original file line number Diff line number Diff line change
@@ -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({
Expand Down
11 changes: 5 additions & 6 deletions _test_/loginAction.spec.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
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();
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,
response: errorResponse,
});
const expectedActions = [
{
type: LOGIN_LOADING,
type: AUTH_LOADING,
},
{
payload: errorResponse.message,
Expand All @@ -45,7 +44,7 @@ describe('Login actions', () => {
});
const expectedActions = [
{
type: LOGIN_LOADING,
type: AUTH_LOADING,
},
{
payload: successResponse.data[0],
Expand Down
32 changes: 28 additions & 4 deletions src/actions/authActions.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/actions/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
6 changes: 4 additions & 2 deletions src/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,14 @@ const App = () => (
<Route path="/newpassword" component={PasswordReset} />
<Route path="/socialAuth" component={SocialAuth} />
<Route path="/article" component={CreateArticlePage} />
<Route exact path="/articles" component={Articles} />
<Route exact path="/articles/:slug" component={SingleArticle} />
<Route path="/articles" component={Articles} />
<Route path="/articles/:slug" component={SingleArticle} />
<Route path="/comments/" component={Comments} />
<Route path="/updatearticle/:slug" component={UpdateArticlePage} />
<Route path="/articles" component={Articles} />
<Route path="/profile/:userId" component={Profile} />
<Route path="/comments/" component={Comments} />
<Route path="/updatearticle/:slug" component={UpdateArticlePage} />

<Route component={NotFound} />
</Switch>
Expand Down
27 changes: 15 additions & 12 deletions src/components/NavigationBar/index.jsx
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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(<i className="fas fa-book-reader" />, 'Articles');
const notify = this.checkWidth(<i className="fas fa-bell" />, 'Notifications');
Expand Down Expand Up @@ -206,7 +205,11 @@ export class Navbar extends React.Component {
<li className="navbar-login-user-dropdown-item"><Link to="/article" className="navbar-login-user-dropdown-link">Create Article</Link></li>
<li className="navbar-login-user-dropdown-item"><Link to="/articles" className="navbar-login-user-dropdown-link">My Articles</Link></li>
<li className="navbar-login-user-dropdown-item"><Link to="/notification" className="navbar-login-user-dropdown-link">Edit Profile</Link></li>
<li className="navbar-login-user-dropdown-item"><Link to="/notification" className="navbar-login-user-dropdown-link">Log Out</Link></li>
<li className="navbar-login-user-dropdown-item">
<Link to="/" onClick={this.logOut} className="navbar-login-user-dropdown-link">
Log Out
</Link>
</li>
</ul>
</div>
</div>
Expand All @@ -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));
9 changes: 7 additions & 2 deletions src/reducers/authReducer.js
Original file line number Diff line number Diff line change
@@ -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 = {
Expand All @@ -10,7 +10,7 @@ const initialState = {
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case LOGIN_LOADING:
case AUTH_LOADING:
return {
...state,
loading: true,
Expand All @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions src/reducers/errorReducer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GET_ERRORS, LOGIN_LOADING } from '../actions/types';
import { GET_ERRORS, AUTH_LOADING } from '../actions/types';

const initialState = {
error: {
Expand All @@ -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,
Expand Down
1 change: 0 additions & 1 deletion src/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,5 @@ export default combineReducers({
toastr: toastrReducer,
fetchCategoryReducer,
updateArticlesReducer,

profile: profileReducer,
});

0 comments on commit 6fdce5a

Please sign in to comment.