From cdf80ccd5eb4c31ea36ca16ffacf241fa6beac69 Mon Sep 17 00:00:00 2001 From: Mahmoud Abdulazim Date: Thu, 17 Jan 2019 17:40:29 +0200 Subject: [PATCH 1/2] [WIP] generate LoginPage container and LoginForm component --- app/components/LoginForm/index.js | 44 ++++++++++++++++++++++++++++ app/containers/App/index.js | 2 ++ app/containers/LoginPage/Loadable.js | 6 ++++ app/containers/LoginPage/index.js | 31 ++++++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 app/components/LoginForm/index.js create mode 100644 app/containers/LoginPage/Loadable.js create mode 100644 app/containers/LoginPage/index.js diff --git a/app/components/LoginForm/index.js b/app/components/LoginForm/index.js new file mode 100644 index 0000000..2186a56 --- /dev/null +++ b/app/components/LoginForm/index.js @@ -0,0 +1,44 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const LoginForm = props => { + console.log({ props }); + return ( +
+
+ + +
+
+ + +
+ +
+ ); +}; + +LoginForm.propTypes = { + username: PropTypes.string.isRequired, + password: PropTypes.string.isRequired, + onSubmit: PropTypes.func.isRequired, + onChange: PropTypes.func.isRequired, +}; + +export default LoginForm; diff --git a/app/containers/App/index.js b/app/containers/App/index.js index 5a84634..b969ac2 100755 --- a/app/containers/App/index.js +++ b/app/containers/App/index.js @@ -12,6 +12,7 @@ import { Switch, Route } from 'react-router-dom'; import HomePage from 'containers/HomePage/Loadable'; import NotFoundPage from 'containers/NotFoundPage/Loadable'; +import LoginPage from 'containers/LoginPage/Loadable'; import '../../global-styles.scss'; @@ -20,6 +21,7 @@ export default function App() {
+
diff --git a/app/containers/LoginPage/Loadable.js b/app/containers/LoginPage/Loadable.js new file mode 100644 index 0000000..36a2b2b --- /dev/null +++ b/app/containers/LoginPage/Loadable.js @@ -0,0 +1,6 @@ +/** + * Asynchronously loads the component for LoginPage + */ +import loadable from 'loadable-components'; + +export default loadable(() => import('./index')); diff --git a/app/containers/LoginPage/index.js b/app/containers/LoginPage/index.js new file mode 100644 index 0000000..f5a0224 --- /dev/null +++ b/app/containers/LoginPage/index.js @@ -0,0 +1,31 @@ +import React from 'react'; +import LoginForm from 'components/LoginForm'; + +/* eslint-disable react/prefer-stateless-function */ +export default class LoginPage extends React.PureComponent { + state = { + username: '', + password: '', + }; + + handleSubmit = event => { + event.preventDefault(); + console.log('Submitted: ', this.state); + }; + + handleChange = event => { + this.setState({ [event.target.name]: event.target.value }); + }; + + render() { + const { username, password } = this.state; + return ( + + ); + } +} From 20eef83dc365e08b4eb502ff1edea9db803aeab1 Mon Sep 17 00:00:00 2001 From: Mahmoud Abdulazim Date: Thu, 17 Jan 2019 19:12:05 +0200 Subject: [PATCH 2/2] [WIP] fix LoginPage shadow test and add boilreplate of redux to container --- app/components/LoginForm/index.js | 44 --------------- app/containers/LoginPage/actions.js | 14 +++++ app/containers/LoginPage/constants.js | 11 ++++ app/containers/LoginPage/index.js | 57 ++++++++++++++++---- app/containers/LoginPage/reducer.js | 25 +++++++++ app/containers/LoginPage/tests/index.test.js | 39 ++++++++++++++ app/utils/localStorage.js | 11 ++++ 7 files changed, 148 insertions(+), 53 deletions(-) delete mode 100644 app/components/LoginForm/index.js create mode 100644 app/containers/LoginPage/actions.js create mode 100644 app/containers/LoginPage/constants.js create mode 100644 app/containers/LoginPage/reducer.js create mode 100644 app/containers/LoginPage/tests/index.test.js create mode 100644 app/utils/localStorage.js diff --git a/app/components/LoginForm/index.js b/app/components/LoginForm/index.js deleted file mode 100644 index 2186a56..0000000 --- a/app/components/LoginForm/index.js +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const LoginForm = props => { - console.log({ props }); - return ( -
-
- - -
-
- - -
- -
- ); -}; - -LoginForm.propTypes = { - username: PropTypes.string.isRequired, - password: PropTypes.string.isRequired, - onSubmit: PropTypes.func.isRequired, - onChange: PropTypes.func.isRequired, -}; - -export default LoginForm; diff --git a/app/containers/LoginPage/actions.js b/app/containers/LoginPage/actions.js new file mode 100644 index 0000000..4093c91 --- /dev/null +++ b/app/containers/LoginPage/actions.js @@ -0,0 +1,14 @@ +/* + * + * LoginPage actions + * + */ + +import { AUTHENTICATION } from './constants'; + +export function login(credentials) { + console.log({ credentials }); + return { + type: AUTHENTICATION.LOGIN_REQUEST, + }; +} diff --git a/app/containers/LoginPage/constants.js b/app/containers/LoginPage/constants.js new file mode 100644 index 0000000..89b0017 --- /dev/null +++ b/app/containers/LoginPage/constants.js @@ -0,0 +1,11 @@ +/* + * + * LoginPage constants + * + */ + +export const AUTHENTICATION = { + LOGIN_REQUEST: 'USER_LOGIN_REQUEST', + LOGIN_SUCCESS: 'USER_LOGIN_SUCCESS', + LOGIN_FAILURE: 'USER_LOGIN_FAILURE', +}; diff --git a/app/containers/LoginPage/index.js b/app/containers/LoginPage/index.js index f5a0224..a58da50 100644 --- a/app/containers/LoginPage/index.js +++ b/app/containers/LoginPage/index.js @@ -1,8 +1,15 @@ import React from 'react'; -import LoginForm from 'components/LoginForm'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; + +import { login } from './actions'; /* eslint-disable react/prefer-stateless-function */ -export default class LoginPage extends React.PureComponent { +class LoginPage extends React.PureComponent { + static propTypes = { + login: PropTypes.func.isRequired, + }; + state = { username: '', password: '', @@ -10,7 +17,7 @@ export default class LoginPage extends React.PureComponent { handleSubmit = event => { event.preventDefault(); - console.log('Submitted: ', this.state); + this.props.login(this.state); }; handleChange = event => { @@ -19,13 +26,45 @@ export default class LoginPage extends React.PureComponent { render() { const { username, password } = this.state; + return ( - +
+
+ + +
+
+ + +
+ +
); } } + +const mapStateToProps = state => ({ + username: state.username, + password: state.password, +}); + +export default connect( + mapStateToProps, + { login }, +)(LoginPage); diff --git a/app/containers/LoginPage/reducer.js b/app/containers/LoginPage/reducer.js new file mode 100644 index 0000000..f7cf8cc --- /dev/null +++ b/app/containers/LoginPage/reducer.js @@ -0,0 +1,25 @@ +/* + * + * LoginPage reducer + * + */ + +import { fromJS } from 'immutable'; + +import { AUTHENTICATION } from './constants'; +import { retrieveFromLocalStorage } from '../../utils/localStorage'; + +export const initialState = fromJS({ + isAuthenticated: !!retrieveFromLocalStorage('xSessionToken'), +}); + +function loginPageReducer(state = initialState, action) { + switch (action.type) { + case AUTHENTICATION.LOGIN_REQUEST: + return state.set('isAuthenticated', false); + default: + return state; + } +} + +export default loginPageReducer; diff --git a/app/containers/LoginPage/tests/index.test.js b/app/containers/LoginPage/tests/index.test.js new file mode 100644 index 0000000..af6e74e --- /dev/null +++ b/app/containers/LoginPage/tests/index.test.js @@ -0,0 +1,39 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import { browserHistory } from 'react-router-dom'; +import { Provider } from 'react-redux'; + +import LoginPage from 'containers/LoginPage'; + +import configureStore from '../../../configureStore'; + +describe('', () => { + let mountedLoginPage; + + let store; + + beforeAll(() => { + store = configureStore({}, browserHistory); + }); + + beforeEach(() => { + mountedLoginPage = mount( + + + , + ); + }); + + it('should render without crashing', () => { + mount( + + + , + ); + }); + + it('should renders its children ', () => { + const children = mountedLoginPage.find('form.login-form'); + expect(children.length).toBe(1); + }); +}); diff --git a/app/utils/localStorage.js b/app/utils/localStorage.js new file mode 100644 index 0000000..eb005a6 --- /dev/null +++ b/app/utils/localStorage.js @@ -0,0 +1,11 @@ +export function storeInLocalStorage({ label, value }) { + localStorage.setItem(label, value); +} + +export function retrieveFromLocalStorage(item) { + return localStorage.getItem(item); +} + +export function removeFromLocalStorage(item) { + return localStorage.removeItem(item); +}