Skip to content

Commit

Permalink
feat(facebook-auth):enable facebook login and signup
Browse files Browse the repository at this point in the history
- enable redirect upon successful authentication
- authenticate user
- write auth actions and reducers

[Finishes #162553610]
  • Loading branch information
augustineezinwa committed Dec 20, 2018
1 parent b58dba3 commit 0a21c77
Show file tree
Hide file tree
Showing 18 changed files with 190 additions and 37 deletions.
28 changes: 13 additions & 15 deletions app.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"name": "valinor-ah-frontend",
"scripts": {
},
"scripts": {},
"env": {
"API_BASE_URL": {
"required": true
Expand All @@ -11,17 +10,16 @@
},
"JWT_SECRET": {
"required": true
}
},
"formation": {
"web": {
"quantity": 1
}
},
"addons": [

],
"buildpacks": [

]
},
"FACEBOOK_APP_ID": {
"required": true
},
"formation": {
"web": {
"quantity": 1
}
},
"addons": [],
"buildpacks": []
}
}
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"query-string": "^5.1.1",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-facebook-login": "^4.1.1",
"react-google-login": "^4.0.0",
"react-quill": "^1.3.3",
"react-redux": "^5.1.1",
Expand Down
8 changes: 4 additions & 4 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ class App extends Component {

render() {
return (
<PersistGate persistor={persistor}>
<Provider store={store}>
<Provider store={store}>
<PersistGate persistor={persistor}>
<Router>
<Fragment>
<Header />
Expand Down Expand Up @@ -56,8 +56,8 @@ class App extends Component {
/>
</Fragment>
</Router>
</Provider>
</PersistGate>
</PersistGate>
</Provider>
);
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/actions/googleActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import requestOptions from '../utils/requestOptions';
const socialLogin = userObject => dispatch => fetch(`${process.env.API_BASE_URL}/auth/social`, requestOptions(userObject, 'POST', null))
.then(
res => res.json(),
error => dispatch(globalFailure(['An error has occured', error]))
(error) => {
dispatch(globalFailure(['An error has occured', error]));
toastr.error('An error has occured, please try again!');
}
)
.then((response) => {
dispatch(globalLoading(false));
Expand Down
28 changes: 28 additions & 0 deletions src/components/common/FacebookButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import FacebookLogin from 'react-facebook-login/dist/facebook-login-render-props';
import PropTypes from 'prop-types';

const FacebookButton = ({ responseFacebook, request, text }) => (
<FacebookLogin
appId={process.env.FACEBOOK_APP_ID}
autoLoad={false}
onClick={request}
fields="name,email,picture"
callback={responseFacebook}
// eslint-disable-next-line react/jsx-no-bind
render={renderProps => (
<button type="button" className="btn btn-primary w-100 facebook-btn" onClick={renderProps.onClick}>
<i className="fab fa-facebook-f mr-2" />
{text}
</button>
)}
/>
);

FacebookButton.propTypes = {
responseFacebook: PropTypes.func.isRequired,
request: PropTypes.func.isRequired,
text: PropTypes.string.isRequired
};

export default FacebookButton;
1 change: 0 additions & 1 deletion src/components/common/header/UserSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ export class UserSettings extends Component {
}
}


UserSettings.propTypes = {
isLoggedIn: PropTypes.bool.isRequired,
};
Expand Down
16 changes: 10 additions & 6 deletions src/components/login/LoginPage.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@

import React, { Component } from 'react';
import { Link, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

import GoogleButton from '../common/GoogleButton';
import FacebookButton from '../common/FacebookButton';
import emailIcon from '../../../public/assets/icons/mail-icon.svg';
import { globalLoading, globalFailure } from '../../actions/globalActions';
import login from '../../actions/googleActions';
import loginGoogle from '../../utils/loginGoogle';
import loginFacebook from '../../utils/loginFacebook';

export class LoginPage extends Component {
constructor(props) {
super(props);
this.responseGoogle = this.responseGoogle.bind(this);
this.responseFacebook = this.responseFacebook.bind(this);
}

responseGoogle(response) {
const { handleLogin, failure } = this.props;
loginGoogle(response, handleLogin, failure, 'google');
}

responseFacebook(response) {
const { handleLogin, failure } = this.props;
loginFacebook(response, handleLogin, failure);
}

render() {
const { isLoggedIn, request } = this.props;
if (isLoggedIn) {
Expand Down Expand Up @@ -57,14 +64,12 @@ export class LoginPage extends Component {
<div className="row social-buttons-row">

<div className="col-lg-4 social-button">

<GoogleButton responseGoogle={this.responseGoogle} text="Login with Google" request={request} />
</div>

<div className="col-lg-4 social-button">
<button type="button" className="btn btn-primary w-100 facebook-btn">
<i className="fab fa-facebook-f mr-2" />
Login with Facebook
</button>
<FacebookButton responseFacebook={this.responseFacebook} text="Login with Facebook" request={request} />
</div>

<div className="col-lg-4 social-button">
Expand Down Expand Up @@ -104,7 +109,6 @@ export class LoginPage extends Component {
}
}


LoginPage.propTypes = {
isLoggedIn: PropTypes.bool.isRequired,
handleLogin: PropTypes.func.isRequired,
Expand Down
16 changes: 11 additions & 5 deletions src/components/signup/SignUpPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,27 @@ import userIcon from '../../../public/assets/icons/user-icon.svg';
import { globalLoading, globalFailure } from '../../actions/globalActions';
import login from '../../actions/googleActions';
import loginGoogle from '../../utils/loginGoogle';
import loginFacebook from '../../utils/loginFacebook';
import FacebookButton from '../common/FacebookButton';

export class SignUp extends Component {
constructor(props) {
super(props);
this.responseGoogle = this.responseGoogle.bind(this);
this.responseFacebook = this.responseFacebook.bind(this);
}

responseGoogle(response) {
const { handleLogin, failure } = this.props;
loginGoogle(response, handleLogin, failure, 'google');
}

responseFacebook(response) {
const { handleLogin, failure } = this.props;
loginFacebook(response, handleLogin, failure);
}


render() {
const { isLoggedIn, request } = this.props;
if (isLoggedIn) {
Expand Down Expand Up @@ -58,11 +67,9 @@ export class SignUp extends Component {
<GoogleButton responseGoogle={this.responseGoogle} text="Signup with Google" request={request} />
</div>


<div className="col-lg-4 social-button">
<button type="button" className="btn btn-primary w-100 facebook-btn">
<i className="fab fa-facebook-f mr-2" />
Signup with Facebook
</button>
<FacebookButton responseFacebook={this.responseFacebook} text="Signup with Facebook" request={request} />
</div>

<div className="col-lg-4 social-button">
Expand Down Expand Up @@ -122,5 +129,4 @@ const mapDispatchToProps = dispatch => ({
failure: error => dispatch(globalFailure(error))
});


export default connect(mapStateToProps, mapDispatchToProps)(SignUp);
1 change: 0 additions & 1 deletion src/reducers/globalReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,4 @@ const globalReducer = (state = global, action) => {
}
};


export default globalReducer;
21 changes: 21 additions & 0 deletions src/utils/loginFacebook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { toastr } from 'react-redux-toastr';

const loginFacebook = (response, handleLogin, failure) => {
if (!response.id) {
toastr.error('There has been an error from the facebook server. Please try again');
return failure(['There has been an error from the facebook server. Please try again']);
}
const facebookName = response.name.toString().split(' ');
if (facebookName.length > 2) facebookName.pop();
const fullName = facebookName.join(' ');
const userObject = {
fullName,
email: response.email,
socialType: 'facebook',
socialId: response.userID,
avatarUrl: response.picture.data.url
};
return handleLogin(userObject);
};

export default loginFacebook;
23 changes: 23 additions & 0 deletions tests/src/components/common/FacebookButton.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import { shallow } from 'enzyme';
import FacebookButton from '../../../../src/components/common/FacebookButton';

const setup = () => {
const props = {
responseFacebook: jest.fn(),
request: jest.fn(),
text: 'Signup with Facebook'
};
const wrapper = shallow(<FacebookButton {...props} />);
return { wrapper, props };
};

test('should render facebook button', () => {
const { wrapper } = setup();
expect(wrapper).toMatchSnapshot();
});

test('should render facebook button without crashing', () => {
const { wrapper } = setup();
expect(wrapper.exists()).toBe(true);
});
6 changes: 3 additions & 3 deletions tests/src/components/common/Footer/Footer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { shallow } from 'enzyme';

import Footer from '../../../../../src/components/common/footer/Footer';

test('NavBar snapshot test', () => {
const component = shallow(<Footer />);
expect(component).toMatchSnapshot();
test('Footer snapshot test', () => {
const wrapper = shallow(<Footer />);
expect(wrapper).toMatchSnapshot();
});
1 change: 1 addition & 0 deletions tests/src/components/home/HomePage.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

import React from 'react';
import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Expand Down
13 changes: 13 additions & 0 deletions tests/src/components/login/LoginPage.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ const profileObj = {
googleId: '7698761582',
imageUrl: 'https://fake.com/'
};

const userFacebookInformation = {
name: 'fishes donkey',
email: 'doneky@apples.com',
userID: '34343434343',
picture: {
data: {
url: 'https://doneky.com'
}
}
};

test('should test LoginPage components', () => {
// eslint-disable-next-line max-len
const firstComponent = mount(<Router><LoginPage isLoggedIn={false} request={jest.fn()} failure={jest.fn()} handleLogin={jest.fn()} /></Router>);
Expand All @@ -26,6 +38,7 @@ test('should test LoginPage components', () => {

const instance = secondComponent.instance();
instance.responseGoogle({ profileObj });
instance.responseFacebook({ userFacebookInformation });
});


Expand Down
12 changes: 12 additions & 0 deletions tests/src/components/signup/SignupPage.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ const profileObj = {
imageUrl: 'https://fake.com/'
};

const userFacebookInformation = {
name: 'fishes donkey',
email: 'doneky@apples.com',
userID: '34343434343',
picture: {
data: {
url: 'https://doneky.com'
}
}
};

test('should test SignUpPage components', () => {
// eslint-disable-next-line max-len
const firstComponent = shallow(<SignUp isLoggedIn request={jest.fn()} failure={jest.fn()} handleLogin={jest.fn()} />);
Expand All @@ -27,6 +38,7 @@ test('should test SignUpPage components', () => {

const instance = firstComponent.instance();
instance.responseGoogle({ profileObj });
instance.responseFacebook({ userFacebookInformation });
});

describe('Signup snapshot test', () => {
Expand Down
Loading

0 comments on commit 0a21c77

Please sign in to comment.