Skip to content
This repository has been archived by the owner on Apr 15, 2019. It is now read-only.

Commit

Permalink
Merge pull request #509 from alepop/499-enhancments-in-routing
Browse files Browse the repository at this point in the history
Enhancements in routing - Closes #499
  • Loading branch information
yasharAyari authored Jul 26, 2017
2 parents 3be47c5 + a3f6ad8 commit 26d172c
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 33 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"babel-plugin-syntax-trailing-function-commas": "=6.22.0",
"babel-preset-es2015": "=6.18.0",
"babel-preset-react": "=6.16.0",
"babel-preset-stage-3": "=6.24.1",
"chai": "=3.5.0",
"chai-as-promised": "=6.0.0",
"chai-enzyme": "=0.6.1",
Expand Down Expand Up @@ -96,6 +97,7 @@
"react-hot-loader": "^1.3.1",
"react-test-renderer": "=15.6.1",
"react-waypoint": "^7.0.4",
"redux-mock-store": "=1.2.3",
"should": "=11.2.0",
"sinon": "=2.0.0",
"sinon-chai": "=2.8.0",
Expand Down
51 changes: 25 additions & 26 deletions src/components/app/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import { Route, Link } from 'react-router-dom';
import Header from '../header';
import PrivateRoutes from '../privateRoute';
import Account from '../account';
import Header from '../header';
import Login from '../login';
import Transactions from '../transactions';
import Voting from '../voting';
Expand All @@ -11,32 +12,30 @@ import Metronome from '../../utils/metronome';
import Dialog from '../dialog';
// temporary, will be deleted with #347

const App = () => {
// start dispatching sync ticks
const metronome = new Metronome();
metronome.init();
// start dispatching sync ticks
const metronome = new Metronome();
metronome.init();

return (
<section className={styles['body-wrapper']}>
<Header />
<main className=''>
<Route path="/main" render={({ match }) => (
<main className=''>
<Account />
<Link to='/main/transactions'>Transactions</Link>
<Link to='/main/voting'>Voting</Link>
<Link to='/main/forging'>Forging</Link>
<Route path={`${match.url}/transactions`} component={Transactions}/>
<Route path={`${match.url}/voting`} component={Voting}/>
<Route path={`${match.url}/forging`} component={Forging}/>
</main>
)} />
<Route exact path="/" component={Login} />
</main>
const App = () => (
<section className={styles['body-wrapper']}>
<Header />
<main>
<PrivateRoutes path='/main' render={ ({ match }) => (
<main>
<Account />
<Link to={`${match.url}/transactions`}>Transactions</Link>
<Link to={`${match.url}/voting`}>Voting</Link>
<Link to={`${match.url}/forging`}>Forging</Link>

<Dialog />
</section>
);
};
<Route path={`${match.url}/transactions`} component={Transactions} />
<Route path={`${match.url}/voting`} component={Voting} />
<Route path={`${match.url}/forging`} component={Forging} />
</main>
)} />
<Route exact path="/" component={Login} />
</main>
<Dialog />
</section>
);

export default App;
59 changes: 54 additions & 5 deletions src/components/app/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { mount } from 'enzyme';
import { MemoryRouter } from 'react-router';
import { Provider } from 'react-redux';
import { expect } from 'chai';
import store from '../../store';
import configureStore from 'redux-mock-store';
import App from './';
import Login from '../login';
import Transactions from '../transactions';
import Voting from '../voting';
import Forging from '../forging';

const fakeStore = configureStore();

const addRouter = Component => (props, path) =>
mount(
<Provider {...props}>
Expand All @@ -19,18 +21,65 @@ const addRouter = Component => (props, path) =>
</Provider>,
);

const routesComponent = [
const publicComponent = [
{ route: '/', component: Login },
];

const privateComponent = [
{ route: '/main/transactions', component: Transactions },
{ route: '/main/voting', component: Voting },
{ route: '/main/forging', component: Forging },
];

describe('App', () => {
const navigateTo = addRouter(App);
describe('renders correct routes', () => {
const navigateTo = addRouter(App);
routesComponent.forEach(({ route, component }) => {
it.skip(`should render ${component.name} component at "${route}" route`, () => {
const store = fakeStore({
account: {},
dialog: {},
peers: {},
});
publicComponent.forEach(({ route, component }) => {
it(`should render ${component.name} component at "${route}" route`, () => {
const wrapper = navigateTo({ store }, [route]);
expect(wrapper.find(component).exists()).to.be.equal(true);
});
});

privateComponent.forEach(({ route, component }) => {
it(`should redirect from ${component.name} component if user is not authenticated`, () => {
const wrapper = navigateTo({ store }, [route]);
expect(wrapper.find(component).exists()).to.be.equal(false);
expect(wrapper.find(Login).exists()).to.be.equal(true);
});
});
});

// These tests are skipped because App component use many components and all of them need
// specific data to render. Each time you will add new components to App, this tests can be fall.
// Need solution for these kinds of tests.
describe.skip('allow to render private components after logged in', () => {
const store = fakeStore({
account: {
publicKey: '000',
},
forging: {
statics: {},
},
dialog: {},
peers: {
status: {
online: true,
},
data: {
options: {
name: 'Test',
},
},
},
});
privateComponent.forEach(({ route, component }) => {
it(`should reder ${component.name} component at "${route}" route if user is authenticated`, () => {
const wrapper = navigateTo({ store }, [route]);
expect(wrapper.find(component).exists()).to.be.equal(true);
});
Expand Down
2 changes: 1 addition & 1 deletion src/components/login/loginFormComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class LoginFormComponent extends React.Component {
onAccountUpdated({ delegate: {}, isDelegate: false });
});
// redirect to main/transactions
this.props.history.push('/main/transactions');
this.props.history.replace('/main/transactions');
});
}, 5);
}
Expand Down
15 changes: 15 additions & 0 deletions src/components/privateRoute/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { Route, Redirect, withRouter } from 'react-router-dom';
import { connect } from 'react-redux';

export const PrivateRouteRender = ({ render, isAuthenticated, ...rest }) => (
<Route {...rest} render={ matchProps => (
isAuthenticated ? render(matchProps) : <Redirect to='/' />
)}/>
);

const mapStateToProps = state => ({
isAuthenticated: !!state.account.publicKey,
});

export default withRouter(connect(mapStateToProps)(PrivateRouteRender));
33 changes: 33 additions & 0 deletions src/components/privateRoute/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import { expect } from 'chai';
import { mount } from 'enzyme';
import { MemoryRouter, Route } from 'react-router';
import { PrivateRouteRender } from './index';

const Public = () => <h1>Public</h1>;
const Private = () => <h1>Private</h1>;

describe('PrivateRouteRender', () => {
const isAuth = isAuthenticated => (
mount(
<MemoryRouter initialEntries={['/private/test']}>
<div>
<Route path='/' component={Public} />
<PrivateRouteRender
path='/private'
render={({ match }) => <Route to={`${match.url}/test`} component={Private}/>}
isAuthenticated={isAuthenticated} />
</div>
</MemoryRouter>,
)
);
it('should render Component if user is authenticated', () => {
const wrapper = isAuth(true);
expect(wrapper.find(Private)).to.have.length(1);
});

it('should redirect to root path if user is not authenticated', () => {
const wrapper = isAuth(false);
expect(wrapper.find(Public)).to.have.length(1);
});
});
2 changes: 1 addition & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ module.exports = (env) => {
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: ['es2015', 'react'],
presets: ['es2015', 'react', 'stage-3'],
plugins: ['syntax-trailing-function-commas'],
env: {
test: {
Expand Down

0 comments on commit 26d172c

Please sign in to comment.