Skip to content

Commit

Permalink
make private routes protected
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyak99 committed Nov 13, 2019
1 parent 0ec474a commit c927cdf
Show file tree
Hide file tree
Showing 25 changed files with 316 additions and 115 deletions.
173 changes: 96 additions & 77 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/components/ContentList/ContentList.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import React from 'react';
import { arrayOf, object } from 'prop-types';
import './contentList.scss';

const ContentList = ({ contents }) => contents.map((content) => (
const ContentList = ({ contents }) => contents.map(content => (
<div key={content.id} className="content-item">
<a href={content.link}>
<p>{content.name}</p>
</a>
</div>)
)
</div>
));

ContentList.propTypes = {
contents: arrayOf(object),
Expand Down
14 changes: 10 additions & 4 deletions src/components/Header/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { connect } from 'react-redux';
import './header.scss';
import Button from '../Button';
import logo from '../../assets/images/logo.png';
import { logoutUser } from '../../../store/actions/authActions';

export class Header extends React.Component {
constructor(props) {
Expand All @@ -27,7 +28,7 @@ export class Header extends React.Component {
}

render() {
const { isAuthenticated } = this.props;
const { isAuthenticated, logout } = this.props;
let display = (
<NavItem>
<Link to="/login">
Expand All @@ -44,8 +45,8 @@ export class Header extends React.Component {
<Link to="/profile">
<Button type="button" text="Profile" classname="button-style" />
</Link>
<Link to="/logout">
<Button type="button" text="Sign out" classname="button-style" />
<Link to="/">
<Button type="button" text="Sign out" classname="button-style" onClick={() => logout()} />
</Link>
</NavItem>
);
Expand Down Expand Up @@ -78,8 +79,13 @@ Header.defaultProps = {

Header.propTypes = {
isAuthenticated: PropTypes.bool,
logout: PropTypes.func,
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated,
});
export default connect(mapStateToProps)(Header);

const mapDispatchToprops = dispatch => ({
logout: () => dispatch(logoutUser()),
});
export default connect(mapStateToProps, mapDispatchToprops)(Header);
33 changes: 33 additions & 0 deletions src/components/PrivateRoute/PrivateRoute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

export class PrivateRoute extends React.Component {
constructor(props) {
super(props);
this.state = { };
}

render() {
const { component: Component, isAuthenticated, ...rest } = this.props;
return (
<Route
{...rest}
render={props => (isAuthenticated ? <Component {...props} />
: <Redirect to={{ pathname: '/login', state: { referrer: props.location } }} />)}
/>
);
}
}


PrivateRoute.propTypes = {
component: PropTypes.elementType,
isAuthenticated: PropTypes.bool,
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated,
});

export default connect(mapStateToProps)(PrivateRoute);
33 changes: 33 additions & 0 deletions src/components/PublicRoute/PublicRoute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

export class PublicRoute extends React.Component {
constructor(props) {
super(props);
this.state = { };
}

render() {
const { component: Component, isAuthenticated, ...rest } = this.props;
return (
<Route
{...rest}
render={props => (!isAuthenticated ? <Component {...props} />
: <Redirect to="/dashboard" />)}
/>
);
}
}


PublicRoute.propTypes = {
component: PropTypes.elementType,
isAuthenticated: PropTypes.bool,
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated,
});

export default connect(mapStateToProps)(PublicRoute);
22 changes: 12 additions & 10 deletions src/routes/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,24 @@ import VerifyUserPage from '../views/VerifyUser/verifyUser';
import CommunityPage from '../views/Community/CommunityPage';
import Test from '../views/ModuleTest/ModuleTest';

import PrivateRoute from '../components/PrivateRoute/PrivateRoute';
import PublicRoute from '../components/PublicRoute/PublicRoute';
import About from '../views/AboutUs/AboutUs';

const Routes = () => (
<Switch>
<Route path="/" exact component={Home} />
<Route path="/signup" component={signUpPage} />
<Route path="/login" component={Login} />
<Route path="/aboutus" component={About} />
<Route path="/profile" component={Profile} />
<Route path="/password-reset" component={ResetPassword} />
<Route path="/change-password" component={changePassword} />
<Route path="/dashboard" component={Dashboard} />
<Route path="/verify" component={VerifyUserPage} />
<Route path="/test/:moduleId" component={Test} />
<Route path="/view-module/:moduleId" component={ViewModule} />
<Route path="/community" component={CommunityPage} />
<PrivateRoute path="/test/:moduleId" component={Test} />
<PrivateRoute path="/community" component={CommunityPage} />
<PrivateRoute path="/view-module/:moduleId" component={ViewModule} />
<PublicRoute path="/verify" component={VerifyUserPage} />
<PublicRoute path="/signup" component={signUpPage} />
<PublicRoute path="/login" component={Login} />
<PublicRoute path="/password-reset" component={ResetPassword} />
<PublicRoute path="/change-password" component={changePassword} />
<PrivateRoute path="/profile" component={Profile} />
<PrivateRoute path="/dashboard" component={Dashboard} />
<Route component={NotFound} />
</Switch>
);
Expand Down
13 changes: 9 additions & 4 deletions src/test/Home/Home.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
import React from 'react';
import { mount } from 'enzyme';
import { BrowserRouter as Router } from 'react-router-dom';

import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducers from '../../../store/reducers/index';
import Home from '../../views/Home/Home';

const store = createStore(reducers);
describe('test Landing Page component', () => {
const landingPage = mount(<Router>
<Home />
</Router>);
const landingPage = mount(<Provider store={store}>
<Router>
<Home />
</Router>
</Provider>);
it('should ensure that home page exists, and it includes header and footer components', () => {
expect(landingPage.find('Header').exists()).toBe(true);
expect(landingPage.find('Footer').exists()).toBe(true);
Expand Down
8 changes: 8 additions & 0 deletions src/test/actions/__snapshots__/authAction.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,11 @@ Array [
},
]
`;

exports[`authAction test lougout action 1`] = `
Array [
Object {
"type": "LOGOUT",
},
]
`;
4 changes: 2 additions & 2 deletions src/test/actions/__snapshots__/profileAction.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Array [
"url": "https://freyja-ah-backend.herokuapp.com/api/profiles/4",
"headers": {
"accept": "application/json, text/plain, */*",
"authorization": {},
"authorization": "null",
"user-agent": "axios/0.19.0"
}
}],
Expand All @@ -88,7 +88,7 @@ Array [
"url": "https://freyja-ah-backend.herokuapp.com/api/profiles/45",
"headers": {
"accept": "application/json, text/plain, */*",
"authorization": {},
"authorization": "null",
"user-agent": "axios/0.19.0"
}
}],
Expand Down
7 changes: 6 additions & 1 deletion src/test/actions/authAction.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import nock from 'nock';
import { registerUser, loginUser } from '../../../store/actions/authActions';
import { registerUser, loginUser, logoutUser } from '../../../store/actions/authActions';

const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
Expand Down Expand Up @@ -95,4 +95,9 @@ describe('authAction', () => {
expect(actionTypes).toEqual(expectedActions);
});
});
it('test lougout action', (done) => {
store.dispatch(logoutUser());
expect(store.getActions()).toMatchSnapshot();
done();
});
});
9 changes: 6 additions & 3 deletions src/test/components/Header.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { shallow } from 'enzyme';
import sinon from 'sinon';
import { Header } from '../../components/Header/Header';

const props = {
logout: () => {},
};
describe('component: Header', () => {
beforeEach(() => {
sinon.spy(Header.prototype, 'toggle');
Expand All @@ -11,13 +14,13 @@ describe('component: Header', () => {
Header.prototype.toggle.restore();
});
it('should render correctly', (done) => {
const wrapper = shallow(<Header />);
const wrapper = shallow(<Header {...props} />);
expect(wrapper.find('Navbar').hasClass('nav-style')).toBe(true);
shallow(<Header />);
shallow(<Header {...props} />);
done();
});
it('should update the isOpen state property to true when navtoggler is clicked', (done) => {
const wrapper = shallow(<Header />);
const wrapper = shallow(<Header {...props} />);
const button = wrapper.find('NavbarToggler');
button.simulate('click');
expect(Header.prototype.toggle.calledOnce).toBe(true);
Expand Down
21 changes: 21 additions & 0 deletions src/test/components/PrivateRoute.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { shallow } from 'enzyme';
import { PrivateRoute } from '../../components/PrivateRoute/PrivateRoute';
import { Dashboard } from '../../views/Dashboard/Dashboard';

const props = {
component: Dashboard,
isAuthenticated: true,
};
describe('component: PrivateRoute', () => {
it('should render correctly', (done) => {
const wrapper = shallow(<PrivateRoute />);
expect(wrapper).toMatchSnapshot();
done();
});
it('should render when user is Authenticated', (done) => {
const wrapper = shallow(<PrivateRoute {...props} />);
expect(wrapper).toMatchSnapshot();
done();
});
});
21 changes: 21 additions & 0 deletions src/test/components/PublicRoute.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import { shallow } from 'enzyme';
import { PublicRoute } from '../../components/PublicRoute/PublicRoute';
import { Dashboard } from '../../views/Dashboard/Dashboard';

const props = {
component: Dashboard,
isAuthenticated: false,
};
describe('component: PublicRoute', () => {
it('should render correctly', (done) => {
const wrapper = shallow(<PublicRoute />);
expect(wrapper).toMatchSnapshot();
done();
});
it('should render correctly when isAuthenticated is false', (done) => {
const wrapper = shallow(<PublicRoute {...props} />);
expect(wrapper).toMatchSnapshot();
done();
});
});
5 changes: 5 additions & 0 deletions src/test/components/__snapshots__/PrivateRoute.spec.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`component: PrivateRoute should render correctly 1`] = `ShallowWrapper {}`;

exports[`component: PrivateRoute should render when user is Authenticated 1`] = `ShallowWrapper {}`;
5 changes: 5 additions & 0 deletions src/test/components/__snapshots__/PublicRoute.spec.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`component: PublicRoute should render correctly 1`] = `ShallowWrapper {}`;

exports[`component: PublicRoute should render correctly when isAuthenticated is false 1`] = `ShallowWrapper {}`;
15 changes: 15 additions & 0 deletions src/test/reducers/__snapshots__/authReducer.spec.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Auth Reducers should handle logout 1`] = `
Object {
"errors": Object {},
"isAuthenticated": false,
"isLoading": false,
"passwordChangeError": "",
"passwordChangeSuccess": "",
"passwordResetError": "",
"passwordResetSuccess": "",
"user": Object {},
"verified": "",
}
`;
4 changes: 4 additions & 0 deletions src/test/reducers/authReducer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,8 @@ describe('Auth Reducers', () => {
errors: { error: 'Invalid login credentials' },
});
});
it('should handle logout', (done) => {
expect(authReducer(initialState, { type: 'LOGOUT' })).toMatchSnapshot();
done();
});
});
4 changes: 1 addition & 3 deletions src/test/views/__snapshots__/aboutus.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

exports[`Aboutus component should render without errors 1`] = `
<Fragment>
<Header
isAuthenticated={false}
/>
<Connect(Header) />
<div
className="wrapper"
>
Expand Down
2 changes: 2 additions & 0 deletions src/test/views/login.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ function shallowSetup() {
},
},
loginUser,
location: { state: { referrer: '/' } },
socialSignOn: () => {},
};
const enzymeWrapper = shallow(<Login {...props} />);

Expand Down
2 changes: 1 addition & 1 deletion src/views/AboutUs/AboutUs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
import { Link } from 'react-router-dom';
import { Button, Form, FormGroup, Input } from 'reactstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Header } from '../../components/Header/Header';
import Header from '../../components/Header/Header';
import Footer from '../../components/Footer/Footer';
import './aboutus.scss';

Expand Down
2 changes: 1 addition & 1 deletion src/views/Home/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { Fragment } from 'react';
import { Link } from 'react-router-dom';
import { HashLink } from 'react-router-hash-link';
import { Card, CardTitle, CardText, CardBody, CardImg } from 'reactstrap';
import { Header } from '../../components/Header/Header';
import Header from '../../components/Header/Header';
import Button from '../../components/Button';
import Footer from '../../components/Footer/Footer';
import './home.scss';
Expand Down
Loading

0 comments on commit c927cdf

Please sign in to comment.