From 16338728711084f4a7feb26a7d9e7dd2f2b2eb22 Mon Sep 17 00:00:00 2001 From: Gatilin Maxim Date: Tue, 24 Oct 2017 21:28:06 +0300 Subject: [PATCH 1/4] #HT2 Add sign in logic --- src/components/auth/SignIn.js | 15 +++++++-------- src/components/auth/SignUp.js | 14 +------------- src/components/auth/utils.js | 13 +++++++++++++ src/components/routes/Auth.js | 6 +++--- src/config.js | 8 ++++---- src/ducks/auth.js | 35 +++++++++++++++++++++++++++++++++-- 6 files changed, 61 insertions(+), 30 deletions(-) create mode 100644 src/components/auth/utils.js diff --git a/src/components/auth/SignIn.js b/src/components/auth/SignIn.js index 57e09b9..bb8cb75 100644 --- a/src/components/auth/SignIn.js +++ b/src/components/auth/SignIn.js @@ -1,5 +1,7 @@ import React, { Component } from 'react' import {reduxForm, Field} from 'redux-form' +import {validate} from './utils'; +import ErrorField from "../common/ErrorField"; class SignIn extends Component { static propTypes = { @@ -11,14 +13,10 @@ class SignIn extends Component {

Sign In

+ +
- email: -
-
- password: -
-
- +
@@ -27,5 +25,6 @@ class SignIn extends Component { } export default reduxForm({ - form: 'auth' + form: 'auth', + validate })(SignIn) \ No newline at end of file diff --git a/src/components/auth/SignUp.js b/src/components/auth/SignUp.js index 706f7ae..34841f9 100644 --- a/src/components/auth/SignUp.js +++ b/src/components/auth/SignUp.js @@ -1,6 +1,6 @@ import React, { Component } from 'react' import {reduxForm, Field} from 'redux-form' -import emailValidator from 'email-validator' +import {validate} from './utils' import ErrorField from '../common/ErrorField' class SignUp extends Component { @@ -24,18 +24,6 @@ class SignUp extends Component { } } -const validate = ({ email, password }) => { - const errors = {} - - if (!email) errors.email = 'email is a required field' - if (!password) errors.password = 'password is a required field' - - if (email && !emailValidator.validate(email)) errors.email = 'invalid email' - if (password && password.length < 8) errors.password = 'to short' - - return errors -} - export default reduxForm({ form: 'auth', validate diff --git a/src/components/auth/utils.js b/src/components/auth/utils.js new file mode 100644 index 0000000..3d22d95 --- /dev/null +++ b/src/components/auth/utils.js @@ -0,0 +1,13 @@ +import emailValidator from "email-validator/index"; + +export const validate = ({ email, password }) => { + const errors = {} + + if (!email) errors.email = 'email is a required field' + if (!password) errors.password = 'password is a required field' + + if (email && !emailValidator.validate(email)) errors.email = 'invalid email' + if (password && password.length < 8) errors.password = 'to short' + + return errors +} \ No newline at end of file diff --git a/src/components/routes/Auth.js b/src/components/routes/Auth.js index a183ff9..ec4898e 100644 --- a/src/components/routes/Auth.js +++ b/src/components/routes/Auth.js @@ -1,7 +1,7 @@ import React, { Component } from 'react' import {Route, NavLink} from 'react-router-dom' import {connect} from 'react-redux' -import {signUp} from '../../ducks/auth' +import {signUp, signIn} from '../../ducks/auth' import SignIn from '../auth/SignIn' import SignUp from '../auth/SignUp' @@ -22,8 +22,8 @@ class AuthPage extends Component { ) } - handleSignIn = (values) => console.log('---', 'sign in', values) + handleSignIn = ({email, password}) => this.props.signIn(email, password) handleSignUp = ({email, password}) => this.props.signUp(email, password) } -export default connect(null, { signUp })(AuthPage) \ No newline at end of file +export default connect(null, { signUp, signIn })(AuthPage) \ No newline at end of file diff --git a/src/config.js b/src/config.js index 2782a0b..161087f 100644 --- a/src/config.js +++ b/src/config.js @@ -1,12 +1,12 @@ import firebase from 'firebase' -export const appName = 'advreact-1610' +export const appName = 'react-course-f262b' firebase.initializeApp({ - apiKey: "AIzaSyB31xpTtp4Jln_hb2kAbE4PGf6Mi8EgLyA", authDomain: `${appName}.firebaseapp.com`, databaseURL: `https://${appName}.firebaseio.com`, projectId: appName, - storageBucket: "", - messagingSenderId: "397157634637" + apiKey: "AIzaSyAt-smU_1tqNdkj9pmSpVLxqaOjhDwf4dk", + storageBucket: "react-course-f262b.appspot.com", + messagingSenderId: "447165438476" }) \ No newline at end of file diff --git a/src/ducks/auth.js b/src/ducks/auth.js index 25f3bf7..8c9d02f 100644 --- a/src/ducks/auth.js +++ b/src/ducks/auth.js @@ -14,7 +14,9 @@ export const SIGN_UP_START = `${prefix}/SIGN_UP_START` export const SIGN_UP_SUCCESS = `${prefix}/SIGN_UP_SUCCESS` export const SIGN_UP_ERROR = `${prefix}/SIGN_UP_ERROR` +export const SIGN_IN_START = `${prefix}/SIGN_IN_START` export const SIGN_IN_SUCCESS = `${prefix}/SIGN_IN_SUCCESS` +export const SIGN_IN_ERROR = `${prefix}/SIGN_IN_ERROR` /** * Reducer @@ -60,6 +62,13 @@ export function signUp(email, password) { } } +export function signIn(email, password) { + return { + type: SIGN_IN_START, + payload: { email, password } + } +} + firebase.auth().onAuthStateChanged(user => { if (!user) return @@ -81,7 +90,6 @@ export function * signUpSaga() { try { const user = yield call([auth, auth.createUserWithEmailAndPassword], payload.email, payload.password) - //const user = apply(auth, createUserWithEmailAndPassword, [email, password]) yield put({ type: SIGN_UP_SUCCESS, @@ -96,8 +104,31 @@ export function * signUpSaga() { } } +export function * signInSaga() { + const auth = firebase.auth() + + while (true) { + const {payload} = yield take(SIGN_IN_START) + + try { + const user = yield call([auth, auth.signInWithEmailAndPassword], payload.email, payload.password) + + yield put({ + type: SIGN_IN_SUCCESS, + payload: {user} + }) + } catch (error) { + yield put({ + type: SIGN_IN_ERROR, + payload: {error} + }) + } + } +} + export function * saga() { yield all([ - signUpSaga() + signUpSaga(), + signInSaga() ]) } \ No newline at end of file From af4ba8b7272dfa59650a1a73f9b1ebd9f67543f6 Mon Sep 17 00:00:00 2001 From: Gatilin Maxim Date: Wed, 25 Oct 2017 19:45:08 +0300 Subject: [PATCH 2/4] #HT2 Add tests for auth module --- src/ducks/auth.test.js | 124 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/ducks/auth.test.js diff --git a/src/ducks/auth.test.js b/src/ducks/auth.test.js new file mode 100644 index 0000000..1aff820 --- /dev/null +++ b/src/ducks/auth.test.js @@ -0,0 +1,124 @@ +import { + signIn, + signUp, + signInSaga, + signUpSaga, + SIGN_IN_START, + SIGN_IN_SUCCESS, + SIGN_IN_ERROR, + SIGN_UP_START, + SIGN_UP_SUCCESS, + SIGN_UP_ERROR +} from './auth' +import {call, put, take} from 'redux-saga/effects' +import firebase from 'firebase'; + +/** + * Sign in + * */ + +it('should sign in successfully', async () => { + const authData = { + email: 'test@test.com', + password: '12345678' + } + + const mockUser = { + name: 'Ivan', + age: 22 + } + + const auth = firebase.auth() + + const requestAction = signIn(authData) + + const gen = signInSaga(requestAction) + + expect(gen.next().value).toEqual(take(SIGN_IN_START)) + + expect(gen.next({payload: authData}).value).toEqual(call([auth, auth.signInWithEmailAndPassword], authData.email, authData.password)) + + expect(gen.next(mockUser).value).toEqual(put({ + type: SIGN_IN_SUCCESS, + payload: {user: mockUser} + })) +}) + +it('should sign in with error', async () => { + const authData = { + email: 'test@test.com', + password: '12345678' + } + + const mockError = new Error('error'); + + const auth = firebase.auth() + + const requestAction = signIn(authData) + + const gen = signInSaga(requestAction) + + expect(gen.next().value).toEqual(take(SIGN_IN_START)) + + expect(gen.next({payload: authData}).value).toEqual(call([auth, auth.signInWithEmailAndPassword], authData.email, authData.password)) + + expect(gen.throw(mockError).value).toEqual(put({ + type: SIGN_IN_ERROR, + payload: {error: mockError} + })) +}) + +/** + * Sign up + * */ + +it('should sign up successfully', async () => { + const authData = { + email: 'test@test.com', + password: '12345678' + } + + const mockUser = { + name: 'Ivan', + age: 22 + } + + const auth = firebase.auth() + + const requestAction = signUp(authData) + + const gen = signUpSaga(requestAction) + + expect(gen.next().value).toEqual(take(SIGN_UP_START)) + + expect(gen.next({payload: authData}).value).toEqual(call([auth, auth.createUserWithEmailAndPassword], authData.email, authData.password)) + + expect(gen.next(mockUser).value).toEqual(put({ + type: SIGN_UP_SUCCESS, + payload: {user: mockUser} + })) +}) + +it('should sign up with error', async () => { + const authData = { + email: 'test@test.com', + password: '12345678' + } + + const mockError = new Error('error'); + + const auth = firebase.auth() + + const requestAction = signUp(authData) + + const gen = signUpSaga(requestAction) + + expect(gen.next().value).toEqual(take(SIGN_UP_START)) + + expect(gen.next({payload: authData}).value).toEqual(call([auth, auth.createUserWithEmailAndPassword], authData.email, authData.password)) + + expect(gen.throw(mockError).value).toEqual(put({ + type: SIGN_UP_ERROR, + payload: {error: mockError} + })) +}) \ No newline at end of file From 6939f97d7dee8f45bad6b2417c2394687f243191 Mon Sep 17 00:00:00 2001 From: Gatilin Maxim Date: Wed, 25 Oct 2017 21:47:32 +0300 Subject: [PATCH 3/4] #HT2 Add tests for auth module --- src/ducks/auth.js | 5 +++++ src/ducks/auth.test.js | 13 +++++++++---- src/ducks/people.js | 3 +++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/ducks/auth.js b/src/ducks/auth.js index 8c9d02f..464d030 100644 --- a/src/ducks/auth.js +++ b/src/ducks/auth.js @@ -3,6 +3,7 @@ import {Record} from 'immutable' import firebase from 'firebase' import {createSelector} from 'reselect' import {call, put, all, take} from 'redux-saga/effects' +import {reset} from 'redux-form' /** * Constants @@ -95,6 +96,8 @@ export function * signUpSaga() { type: SIGN_UP_SUCCESS, payload: {user} }) + + yield put(reset('auth')) } catch (error) { yield put({ type: SIGN_UP_ERROR, @@ -117,6 +120,8 @@ export function * signInSaga() { type: SIGN_IN_SUCCESS, payload: {user} }) + + yield put(reset('auth')) } catch (error) { yield put({ type: SIGN_IN_ERROR, diff --git a/src/ducks/auth.test.js b/src/ducks/auth.test.js index 1aff820..02bd4f5 100644 --- a/src/ducks/auth.test.js +++ b/src/ducks/auth.test.js @@ -12,12 +12,13 @@ import { } from './auth' import {call, put, take} from 'redux-saga/effects' import firebase from 'firebase'; +import {reset} from "redux-form"; /** * Sign in * */ -it('should sign in successfully', async () => { +it('should sign in successfully', () => { const authData = { email: 'test@test.com', password: '12345678' @@ -42,9 +43,11 @@ it('should sign in successfully', async () => { type: SIGN_IN_SUCCESS, payload: {user: mockUser} })) + + expect(gen.next().value).toEqual(put(reset('auth'))); }) -it('should sign in with error', async () => { +it('should sign in with error', () => { const authData = { email: 'test@test.com', password: '12345678' @@ -72,7 +75,7 @@ it('should sign in with error', async () => { * Sign up * */ -it('should sign up successfully', async () => { +it('should sign up successfully', () => { const authData = { email: 'test@test.com', password: '12345678' @@ -97,9 +100,11 @@ it('should sign up successfully', async () => { type: SIGN_UP_SUCCESS, payload: {user: mockUser} })) + + expect(gen.next().value).toEqual(put(reset('auth'))); }) -it('should sign up with error', async () => { +it('should sign up with error', () => { const authData = { email: 'test@test.com', password: '12345678' diff --git a/src/ducks/people.js b/src/ducks/people.js index 9a2d814..ac0de77 100644 --- a/src/ducks/people.js +++ b/src/ducks/people.js @@ -2,6 +2,7 @@ import {appName} from '../config' import {Record, List} from 'immutable' import {put, call, takeEvery} from 'redux-saga/effects' import {generateId} from './utils' +import {reset} from 'redux-form'; /** * Constants @@ -66,6 +67,8 @@ export function * addPersonSaga(action) { console.log('---', effect) yield effect + + yield put(reset('person')) } export function * saga() { From bacfdab9f69d8ac29e5ef0eb5075327ff332284c Mon Sep 17 00:00:00 2001 From: Gatilin Maxim Date: Wed, 25 Oct 2017 22:08:17 +0300 Subject: [PATCH 4/4] #HT2 Redirect to people page after log in --- .idea/workspace.xml | 499 ++++++++++++++++++++++------------------- src/ducks/auth.js | 12 +- src/ducks/auth.test.js | 23 +- 3 files changed, 299 insertions(+), 235 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 91aa02f..82b7a15 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -3,7 +3,8 @@ - + + @@ -15,45 +16,118 @@ + + + - + - - + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - + + + + + + + + + + + @@ -66,6 +140,9 @@ appName + signInWithEmailAndPassword + signUp + .reset @@ -78,22 +155,24 @@ @@ -109,8 +188,8 @@ - @@ -122,42 +201,42 @@ - + - + - - + + - - + + - - + + - - + + - +