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 @@
-
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
+
@@ -171,8 +250,8 @@
-
+
@@ -271,6 +350,10 @@
+
+
+
+
1508432208309
@@ -335,43 +418,54 @@
1508781611663
-
+
+ 1508869686959
+
+
+
+ 1508869686959
+
+
+ 1508949908245
+
+
+
+ 1508949908245
+
+
+ 1508957252520
+
+
+
+ 1508957252520
+
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
@@ -411,49 +505,19 @@
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -461,9 +525,6 @@
-
-
-
@@ -471,7 +532,6 @@
-
@@ -487,9 +547,7 @@
-
-
-
+
@@ -497,7 +555,6 @@
-
@@ -505,9 +562,7 @@
-
-
-
+
@@ -521,24 +576,11 @@
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
@@ -546,7 +588,6 @@
-
@@ -554,9 +595,6 @@
-
-
-
@@ -564,9 +602,6 @@
-
-
-
@@ -574,7 +609,6 @@
-
@@ -582,9 +616,7 @@
-
-
-
+
@@ -600,9 +632,7 @@
-
-
-
+
@@ -620,9 +650,7 @@
-
-
-
+
@@ -630,9 +658,7 @@
-
-
-
+
@@ -648,7 +674,6 @@
-
@@ -660,13 +685,6 @@
-
-
-
-
-
-
-
@@ -681,20 +699,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -702,13 +706,6 @@
-
-
-
-
-
-
-
@@ -723,65 +720,59 @@
-
-
+
-
-
-
+
+
-
+
-
-
-
+
+
-
+
-
-
+
+
+
-
+
-
-
-
+
+
-
+
-
-
-
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
@@ -791,83 +782,129 @@
-
+
-
+
-
-
+
+
-
+
-
+
-
-
+
+
-
+
-
-
-
-
-
+
+
+
-
+
-
-
-
-
-
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
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 {
@@ -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..a783566 100644
--- a/src/ducks/auth.js
+++ b/src/ducks/auth.js
@@ -3,6 +3,8 @@ 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'
+import {push} from 'react-router-redux'
/**
* Constants
@@ -14,7 +16,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 +64,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,12 +92,13 @@ 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,
payload: {user}
})
+
+ yield put(reset('auth'))
} catch (error) {
yield put({
type: SIGN_UP_ERROR,
@@ -96,8 +108,42 @@ 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}
+ })
+
+ yield put(reset('auth'))
+ } catch (error) {
+ yield put({
+ type: SIGN_IN_ERROR,
+ payload: {error}
+ })
+ }
+ }
+}
+
+export function * redirectSaga() {
+ while (true) {
+ yield take(SIGN_IN_SUCCESS)
+
+ yield put(push('/people'))
+ }
+}
+
export function * saga() {
yield all([
- signUpSaga()
+ signUpSaga(),
+ signInSaga(),
+ redirectSaga()
])
}
\ No newline at end of file
diff --git a/src/ducks/auth.test.js b/src/ducks/auth.test.js
new file mode 100644
index 0000000..56fd5e5
--- /dev/null
+++ b/src/ducks/auth.test.js
@@ -0,0 +1,146 @@
+import {
+ signIn,
+ signUp,
+ signInSaga,
+ signUpSaga,
+ redirectSaga,
+ 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'
+import {reset} from 'redux-form'
+import {push} from 'react-router-redux'
+
+/**
+ * Sign in
+ * */
+
+it('should sign in successfully', () => {
+ 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}
+ }))
+
+ expect(gen.next().value).toEqual(put(reset('auth')));
+})
+
+it('should sign in with error', () => {
+ 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', () => {
+ 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}
+ }))
+
+ expect(gen.next().value).toEqual(put(reset('auth')));
+})
+
+it('should sign up with error', () => {
+ 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}
+ }))
+})
+
+
+/**
+ * Redirect
+ * */
+
+it('should redirect after successful login', () => {
+ const gen = redirectSaga()
+
+ expect(gen.next().value).toEqual(take(SIGN_IN_SUCCESS));
+
+ expect(gen.next().value).toEqual(put(push('/people')))
+})
+
+
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() {