Created
June 6, 2017 21:01
-
-
Save ahlusar1989/38f1ea6dc8c379c7424b3dc995acf730 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { graphql } from 'react-apollo'; | |
import { connect } from 'react-redux'; | |
import { compose } from 'redux'; | |
import { | |
change, | |
getFormSubmitErrors, | |
getFormValues, | |
reduxForm, | |
stopAsyncValidation, | |
SubmissionError, | |
} from 'redux-form'; | |
import validator from 'validate.js'; | |
// components | |
import Form from './Form'; | |
// mutations | |
import createTokenMutation from '../../../mutations/createToken'; | |
import createUserMutation from '../../../mutations/createUser'; | |
// form | |
const formName = 'users/new'; | |
// rules | |
const emailRules = { | |
presence: { | |
message: 'Please enter an email address', | |
}, | |
email: { | |
message: 'Please enter a valid email address', | |
}, | |
}; | |
const passwordRules = { | |
presence: { | |
message: 'Please enter a password', | |
}, | |
length: { | |
message: 'Passwords must be at least 8 characters', | |
minimum: 8, | |
}, | |
}; | |
async function createUser(variables, props) { | |
try { | |
await props.createUser({ variables }); | |
} catch (err) { | |
const error = err.graphQLErrors[0]; | |
if (error && error.code === 422) { | |
throw new SubmissionError({ email: error.details.email[0].message }); | |
} else { | |
throw new SubmissionError( | |
{ | |
_error: ` | |
Yikes! There was a problem creating your account. Please try again. | |
`, | |
}, | |
); | |
} | |
} | |
} | |
async function createToken(variables, props) { | |
try { | |
await props.createToken({ variables }); | |
} catch (err) { | |
throw new SubmissionError( | |
{ | |
_error: ` | |
The good news is that your account has been created! The bad | |
news is that we ran into an unexpected error logging in to your | |
account. | |
`, | |
}, | |
); | |
} | |
} | |
function handleChange(e = {}, dispatch) { | |
const target = e.target || {}; | |
const { id, value } = target; | |
dispatch(change(formName, id, value)); | |
dispatch(stopAsyncValidation(formName, {})); | |
} | |
async function handleSubmit(values, dispatch, props) { | |
const { email, password } = values; | |
const variables = { email, password }; | |
validate(values); | |
await createUser(variables, props); | |
await createToken(variables, props); | |
} | |
function validate(values) { | |
const { email, password, passwordStrength } = values; | |
const messages = {}; | |
Object.assign(messages, validateEmail(email)); | |
Object.assign(messages, validatePassword(password, passwordStrength)); | |
if (Object.keys(messages).length > 0) { | |
throw new SubmissionError(messages); | |
} | |
} | |
function validateEmail(email) { | |
const results = validator.single(email, emailRules); | |
let message; | |
if (results) message = { email: results[0] }; | |
return message; | |
} | |
function validatePassword(password, passwordStrength) { | |
const results = validator.single(password, passwordRules); | |
let message; | |
if (results) { | |
message = { password: results[0] }; | |
} else if (passwordStrength && passwordStrength.score === 0) { | |
const { feedback } = passwordStrength; | |
const { suggestions, warning } = feedback; | |
message = { password: `${warning}. ${suggestions}` }; | |
} | |
return message; | |
} | |
function mapStateToProps(state) { | |
return { | |
formErrors: getFormSubmitErrors(formName)(state), | |
formValues: getFormValues(formName)(state), | |
}; | |
} | |
function mapDispatchToProps(dispatch) { | |
return { | |
onChange(e) { | |
handleChange(e, dispatch); | |
}, | |
}; | |
} | |
export default compose( | |
connect(mapStateToProps, mapDispatchToProps), | |
graphql(createTokenMutation, { name: 'createToken' }), | |
graphql(createUserMutation, { name: 'createUser' }), | |
reduxForm({ form: formName, onSubmit: handleSubmit, pure: false }), | |
)(Form); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable no-unused-expressions */ | |
import { expect } from 'chai'; | |
import { mount } from 'enzyme'; | |
import faker from 'faker'; | |
import React from 'react'; | |
import { addTypenameToDocument } from 'react-apollo'; | |
import { MockedProvider } from 'react-apollo/lib/test-utils'; | |
import { change, submit } from 'redux-form'; | |
import createStore from '../../../lib/redux/createStore'; | |
import createTokenMutation from '../../../mutations/createToken'; | |
import createUserMutation from '../../../mutations/createUser'; | |
import FormContainer from './FormContainer'; | |
describe('users', () => { | |
describe('New', () => { | |
describe('<FormContainer />', () => { | |
let dispatch; | |
let mocks; | |
let mountedContainer; | |
let props; | |
let store; | |
const container = () => { | |
if (!mountedContainer) { | |
mountedContainer = mount( | |
<MockedProvider mocks={ mocks } store={ store }> | |
<FormContainer { ...props } /> | |
</MockedProvider>, | |
); | |
} | |
return mountedContainer; | |
}; | |
const submitErrors = () => { | |
const state = store.getState() || {}; | |
const form = state.form['users/new'] || {}; | |
return form.submitErrors || {}; | |
}; | |
beforeEach(() => { | |
mocks = []; | |
mountedContainer = undefined; | |
props = {}; | |
store = createStore(); | |
dispatch = store.dispatch; | |
}); | |
it('renders without exploding', () => { | |
expect(container().length).to.be.above(0); | |
}); | |
describe('when form is valid', () => { | |
beforeEach(() => { | |
const variables = { | |
email: faker.internet.email(), | |
password: faker.internet.password(), | |
}; | |
const query1 = addTypenameToDocument(createUserMutation); | |
const result1 = { data: { createUser: { email: variables.email, __typename: 'User' } } }; | |
const query2 = addTypenameToDocument(createTokenMutation); | |
const result2 = { data: { createToken: { access: faker.lorem.text, __typename: 'Token' } } }; | |
mocks = [ | |
{ request: { variables, query: query1 }, result: result1 }, | |
{ request: { variables, query: query2 }, result: result2 }, | |
]; | |
container(); | |
dispatch(change('users/new', 'email', variables.email)); | |
dispatch(change('users/new', 'password', variables.password)); | |
dispatch(submit('users/new')); | |
}); | |
it('finishes successfully', (done) => { | |
setTimeout(() => { | |
const state = store.getState(); | |
const form = state.form['users/new']; | |
expect(form.submitSucceeded).to.eql(true); | |
done(); | |
}, 16); | |
}); | |
}); | |
describe('when `email` is not present', () => { | |
beforeEach(() => { | |
container(); | |
dispatch(change('users/new', 'email', '')); | |
dispatch(submit('users/new')); | |
}); | |
it('generates an error message', (done) => { | |
process.nextTick(() => { | |
expect(submitErrors().email).to.not.be.null; | |
done(); | |
}); | |
}); | |
}); | |
describe('when `email` is in an improper format', () => { | |
beforeEach(() => { | |
container(); | |
dispatch(change('users/new', 'email', faker.lorem.word())); | |
dispatch(submit('users/new')); | |
}); | |
it('generates an error message', (done) => { | |
process.nextTick(() => { | |
expect(submitErrors().email).to.not.be.null; | |
done(); | |
}); | |
}); | |
}); | |
describe('when `password` is not present', () => { | |
beforeEach(() => { | |
container(); | |
dispatch(change('users/new', 'password', '')); | |
dispatch(submit('users/new')); | |
}); | |
it('generates an error message', (done) => { | |
process.nextTick(() => { | |
expect(submitErrors().password).to.not.be.null; | |
done(); | |
}); | |
}); | |
}); | |
describe('when `password` is less than 8 characters', () => { | |
beforeEach(() => { | |
container(); | |
dispatch(change('users/new', 'password', faker.internet.password(7))); | |
dispatch(submit('users/new')); | |
}); | |
it('generates an error message', (done) => { | |
process.nextTick(() => { | |
expect(submitErrors().password).to.not.be.null; | |
done(); | |
}); | |
}); | |
}); | |
describe('when `password` is too common', () => { | |
beforeEach(() => { | |
container(); | |
dispatch(change('users/new', 'password', 'password')); | |
dispatch(submit('users/new')); | |
}); | |
it('generates an error message', (done) => { | |
process.nextTick(() => { | |
expect(submitErrors().password).to.not.be.null; | |
done(); | |
}); | |
}); | |
}); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment