Skip to content
This repository has been archived by the owner on May 28, 2018. It is now read-only.

Commit

Permalink
Add LoginForm shell accessible at /login
Browse files Browse the repository at this point in the history
  • Loading branch information
nbrohee committed Nov 10, 2016
1 parent 6c7bd8e commit 4fa612e
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 0 deletions.
28 changes: 28 additions & 0 deletions client/src/components/login/LoginForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, {PropTypes} from 'react'
import { FormGroup, ControlLabel, FormControl, Button, HelpBlock } from 'react-bootstrap'
import ValidatedFormControl from '../common/ValidatedFormControl'

const LoginForm = ({user, onLoginClick, errors, onChange}) => {
return (
<form>
<FormGroup>
<ControlLabel className="required">Email</ControlLabel>
<ValidatedFormControl name="email" type="email" placeholder="Email" onChange={onChange} value={user.email} error={errors.email}/>
</FormGroup>
<FormGroup>
<ControlLabel className="required">Mot de passe</ControlLabel>
<ValidatedFormControl name="password" type="password" placeholder="Mot de passe" onChange={onChange} value={user.password} error={errors.password} />
</FormGroup>
<Button bsStyle="primary" onClick={onLoginClick}>Connexion</Button>
</form>
)
}

LoginForm.propTypes = {
user: PropTypes.object.isRequired,
onLoginClick: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
errors: PropTypes.object
}

export default LoginForm
35 changes: 35 additions & 0 deletions client/src/components/login/LoginForm.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import expect from 'expect'
import React from 'react'
import {shallow} from 'enzyme'
import LoginForm from './LoginForm'

function setup(user = {}) {
const props = {
user: Object.assign({
email: '',
password: ''
}, user),
errors: {},
onLoginClick: () => { },
onChange: () => { },
}
return shallow(<LoginForm {...props} />)
}

describe('<LoginForm>', () => {
it('renders form', () => {
const wrapper = setup()
expect(wrapper.find('form').length).toBe(1)
})
it('renders given email', () => {
const testEmail = 'testEmail@mail.com'
const wrapper = setup({email: testEmail})
expect(wrapper.find('[name="email"]').props().value).toEqual(testEmail)
})
it('renders given password', () => {
const testPassword = 'testPassword'
const wrapper = setup({password: testPassword})
expect(wrapper.find('form').length).toBe(1)
expect(wrapper.find('[name="password"]').props().value).toEqual(testPassword)
})
})
61 changes: 61 additions & 0 deletions client/src/components/login/LoginPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { PropTypes } from 'react'
import LoginForm from './LoginForm'
import Validation from '../common/Validation'
import {userValidationConstraints} from './userValidationConstraints'

export class LoginPage extends React.Component {
constructor(props, context) {
super(props, context)
this.state = {
user: {
email: '',
password: ''
},
errors: {},
}
this.updateUserState = this.updateUserState.bind(this)
this.loginUser = this.loginUser.bind(this)
this.userValidation = new Validation(userValidationConstraints)
}

updateUserState(event) {
const field = event.target.name
let user = this.state.user
user[field] = event.target.value
this.validateUserField(field, event.target.value)
return this.setState({ user })
}

loginUser(event) {
event.preventDefault()
}

validateUserField(field, value) {
let errors = this.state.errors
errors[field] = this.userValidation.validateField(field, value)
if (errors[field] == null) {
delete errors[field]
}
return this.setState({ errors })
}

render() {
return (
<div className="container">
<div className="page-header">
<h1>Connexion à l'espace PEPITE</h1>
</div>
<LoginForm
user={this.state.user}
onLoginClick={this.loginUser}
onChange={this.updateUserState}
errors={this.state.errors} />
</div>
)
}
}

LoginPage.propTypes = {
}

export default LoginPage
112 changes: 112 additions & 0 deletions client/src/components/login/LoginPage.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import expect from 'expect'
import React from 'react'
import { mount } from 'enzyme'
import { LoginPage } from './LoginPage'

function setup() {
const props = {
}
return mount(<LoginPage {...props} />)
}

describe('<LoginPage>', () => {
it('does not have any error on first load', () => {
const wrapper = setup()
const blockInError = wrapper.find('.has-error')
expect(blockInError.length).toBe(0)
})

describe('Password Field', () => {
it('set in error when left empty', () => {
const wrapper = setup()
const passwordInput = wrapper.find('input[name="password"]')
passwordInput.simulate('change', {
target: {
name: 'password',
value: ''
}
})
const blockInError = wrapper.find('.has-error')
expect(blockInError.length).toBe(1)
expect(blockInError.contains(<div className="help-block">obligatoire</div>)).toBe(true)
})
it('does not have any error after one caracter', () => {
const wrapper = setup()
const passwordInput = wrapper.find('input[name="password"]')
passwordInput.simulate('change', {
target: {
name: 'password',
value: 'c'
}
})
const blockInError = wrapper.find('.has-error')
expect(blockInError.length).toBe(0)
})
it('does not show inputed information', () => {
const wrapper = setup()
const inputedPassword = 'secret'
const passwordInput = wrapper.find('input[name="password"]')
passwordInput.simulate('change', {
target: {
name: 'password',
value: inputedPassword
}
})
expect(passwordInput.text()).toNotEqual(inputedPassword)
})
})

describe('Email Field', () => {
it('set in error when left empty', () => {
const wrapper = setup()
const emailInput = wrapper.find('input[name="email"]')
emailInput.simulate('change', {
target: {
name: 'email',
value: ''
}
})
const blockInError = wrapper.find('.has-error')
expect(blockInError.length).toBe(1)
expect(blockInError.contains(<div className="help-block">Tu dois renseigner une adresse email valide</div>)).toBe(true)
})
it('set in error when email is invalid', () => {
const wrapper = setup()
const emailInput = wrapper.find('input[name="email"]')
emailInput.simulate('change', {
target: {
name: 'email',
value: 'invalidmailmail.com'
}
})
const blockInError = wrapper.find('.has-error')
expect(blockInError.length).toBe(1)
expect(blockInError.contains(<div className="help-block">Tu dois renseigner une adresse email valide</div>)).toBe(true)
})
it('does not have any error when it\'s a valid email', () => {
const wrapper = setup()
const emailInput = wrapper.find('input[name="email"]')
emailInput.simulate('change', {
target: {
name: 'email',
value: 'validmail@mail.com'
}
})
const blockInError = wrapper.find('.has-error')
expect(blockInError.length).toBe(0)
})
it('does not show inputed information', () => {
const wrapper = setup()
const inputedEmail = 'secret'
const emailInput = wrapper.find('input[name="email"]')
emailInput.simulate('change', {
target: {
name: 'email',
value: inputedEmail
}
})
expect(emailInput.text()).toNotEqual(inputedEmail)
})
})

})
16 changes: 16 additions & 0 deletions client/src/components/login/userValidationConstraints.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import validator from 'validator'

function isNotEmpty(value) {
return (value && value.length && value.trim())
}

export const userValidationConstraints = {
email: {
isValid: validator.isEmail,
errorMessage: "Tu dois renseigner une adresse email valide"
},
password: {
isValid: isNotEmpty,
errorMessage: "obligatoire"
}
}
2 changes: 2 additions & 0 deletions client/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import App from './components/App'
import HomePage from './components/home/HomePage'
import ApplicationPage from './components/application/ApplicationPage'
import PrintPage from './components/application/PrintPage'
import LoginPage from './components/login/LoginPage'
import NotFound from './components/error/NotFound'

export default (
<Route path="/" component={App}>
<IndexRoute component={HomePage} />
<Route path="application/:id/print" component={PrintPage}/>
<Route path="application(/:id)" component={ApplicationPage}/>
<Route path="login" component={LoginPage}/>
<Route path="*" component={NotFound} />
</Route>
)

0 comments on commit 4fa612e

Please sign in to comment.