0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-01-27 22:59:51 -05:00

fix: login modal validation (#958)

This commit is contained in:
Ayush Sharma 2018-08-28 08:12:30 +02:00 committed by Juan Picado @jotadeveloper
parent 431e7608d2
commit 9f78c31f66
4 changed files with 115 additions and 66 deletions

View file

@ -64,7 +64,7 @@ export default class App extends Component {
}
/**
* Toogles the login modal
* Toggles the login modal
* Required by: <LoginModal /> <Header />
*/
toggleLoginModal() {
@ -94,7 +94,7 @@ export default class App extends Component {
storage.setItem('username', username);
storage.setItem('token', token);
// close login modal after successful login
// set userLoggined to true
// set isUserLoggedin to true
this.setState({
isUserLoggedIn: true,
showLoginModal: false

View file

@ -1,4 +1,4 @@
import React, {Component} from 'react';
import React, {Component, createRef} from 'react';
import PropTypes from 'prop-types';
import {Form, Button, Dialog, Input, Alert} from 'element-react';
@ -15,15 +15,34 @@ export default class LoginModal extends Component {
error: {},
onCancel: () => {},
onSubmit: () => {}
}
};
state = {
username: '',
password: ''
}
form: {
username: '',
password: ''
},
rules: {
username: [
{
required: true,
message: 'Please input the username',
trigger: 'change'
}
],
password: [
{
required: true,
message: 'Please input the password',
trigger: 'change'
}
]
}
};
constructor(props) {
super(props);
this.formRef = createRef();
this.submitCredentials = this.submitCredentials.bind(this);
this.setCredentials = this.setCredentials.bind(this);
}
@ -32,20 +51,34 @@ export default class LoginModal extends Component {
* set login modal's username and password to current state
* Required by: <LoginModal />
*/
setCredentials(name, e) {
this.setState({
[name]: e
});
setCredentials(key, value) {
this.setState(
(prevState) => ({
form: {...prevState.form, [key]: value}
})
);
}
async submitCredentials(event) {
// prevents default submit behaviour
/**
* Clears the username and password field.
*/
handleReset() {
this.formRef.current.resetFields();
}
submitCredentials(event) {
// prevents default submit behavior
event.preventDefault();
const {username, password} = this.state;
await this.props.onSubmit(username, password);
// let's wait for API response and then set
// username and password filed to empty state
this.setState({username: '', password: ''});
this.formRef.current.validate((valid) => {
if (valid) {
const {username, password} = this.state.form;
this.props.onSubmit(username, password);
this.setState({
form: {username}
});
}
return false;
});
}
renderLoginError({type, title, description} = {}) {
@ -56,13 +89,16 @@ export default class LoginModal extends Component {
description={description}
showIcon={true}
closable={false}
style={{lineHeight: '10px'}}
/>
) : '';
) : (
''
);
}
render() {
const {visibility, onCancel, error} = this.props;
const {username, password} = this.state;
const {username, password} = this.state.form;
return (
<div className="login-dialog">
<Dialog
@ -71,39 +107,47 @@ export default class LoginModal extends Component {
visible={visibility}
onCancel={onCancel}
>
<Form className="login-form">
<Dialog.Body>
{this.renderLoginError(error)}
<br />
<Input
name="username"
placeholder="Username"
value={username}
onChange={this.setCredentials.bind(this, 'username')}
/>
<br />
<br />
<Input
name="password"
type="password"
placeholder="Type your password"
value={password}
onChange={this.setCredentials.bind(this, 'password')}
/>
</Dialog.Body>
<Dialog.Footer className="dialog-footer">
<Button onClick={onCancel} className="cancel-login-button">
Cancel
</Button>
<Button
nativeType="submit"
className="login-button"
onClick={this.submitCredentials}
>
Login
</Button>
</Dialog.Footer>
</Form>
<Dialog.Body>
<Form
className="login-form"
ref={this.formRef}
model={this.state.form}
rules={this.state.rules}
>
<Form.Item>
{this.renderLoginError(error)}
</Form.Item>
<Form.Item prop="username" labelPosition="top">
<Input
name="username"
placeholder="Type your username"
value={username}
onChange={this.setCredentials.bind(this, 'username')}
/>
</Form.Item>
<Form.Item prop="password">
<Input
name="password"
type="password"
placeholder="Type your password"
value={password}
onChange={this.setCredentials.bind(this, 'password')}
/>
</Form.Item>
<Form.Item style={{float: 'right'}}>
<Button onClick={onCancel} className="cancel-login-button">
Cancel
</Button>
<Button
nativeType="submit"
className="login-button"
onClick={this.submitCredentials}
>
Login
</Button>
</Form.Item>
</Form>
</Dialog.Body>
</Dialog>
</div>
);

View file

@ -1,5 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<LoginModal /> should load the component in default state 1`] = `"<div class=\\"login-dialog\\"><div><div style=\\"z-index: 1013;\\" class=\\"el-dialog__wrapper\\"><div style=\\"top: 15%;\\" class=\\"el-dialog el-dialog--tiny\\"><div class=\\"el-dialog__header\\"><span class=\\"el-dialog__title\\">Login</span><button type=\\"button\\" class=\\"el-dialog__headerbtn\\"><i class=\\"el-dialog__close el-icon el-icon-close\\"></i></button></div><form class=\\"el-form el-form--label-right login-form\\"><div class=\\"el-dialog__body\\"><br><div class=\\"el-input\\"><input name=\\"username\\" placeholder=\\"Username\\" type=\\"text\\" class=\\"el-input__inner\\" autocomplete=\\"off\\" value=\\"\\"></div><br><br><div class=\\"el-input\\"><input name=\\"password\\" placeholder=\\"Type your password\\" type=\\"password\\" class=\\"el-input__inner\\" autocomplete=\\"off\\" value=\\"\\"></div></div><div class=\\"el-dialog__footer dialog-footer\\"><button class=\\"el-button el-button--default cancel-login-button\\" type=\\"button\\"><span>Cancel</span></button><button class=\\"el-button el-button--default login-button\\" type=\\"submit\\"><span>Login</span></button></div></form></div></div><div class=\\"v-modal\\" style=\\"z-index: 1012;\\"></div></div></div>"`;
exports[`<LoginModal /> should load the component in default state 1`] = `"<div class=\\"login-dialog\\"><div><div style=\\"z-index: 1013;\\" class=\\"el-dialog__wrapper\\"><div style=\\"top: 15%;\\" class=\\"el-dialog el-dialog--tiny\\"><div class=\\"el-dialog__header\\"><span class=\\"el-dialog__title\\">Login</span><button type=\\"button\\" class=\\"el-dialog__headerbtn\\"><i class=\\"el-dialog__close el-icon el-icon-close\\"></i></button></div><div class=\\"el-dialog__body\\"><form class=\\"el-form el-form--label-right login-form\\"><div class=\\"el-form-item\\"><div class=\\"el-form-item__content\\"></div></div><div class=\\"el-form-item is-required\\"><div class=\\"el-form-item__content\\"><div class=\\"el-input\\"><input name=\\"username\\" placeholder=\\"Type your username\\" type=\\"text\\" class=\\"el-input__inner\\" autocomplete=\\"off\\" value=\\"\\"></div></div></div><div class=\\"el-form-item is-required\\"><div class=\\"el-form-item__content\\"><div class=\\"el-input\\"><input name=\\"password\\" placeholder=\\"Type your password\\" type=\\"password\\" class=\\"el-input__inner\\" autocomplete=\\"off\\" value=\\"\\"></div></div></div><div style=\\"float: right;\\" class=\\"el-form-item\\"><div class=\\"el-form-item__content\\"><button class=\\"el-button el-button--default cancel-login-button\\" type=\\"button\\"><span>Cancel</span></button><button class=\\"el-button el-button--default login-button\\" type=\\"submit\\"><span>Login</span></button></div></div></form></div></div></div><div class=\\"v-modal\\" style=\\"z-index: 1012;\\"></div></div></div>"`;
exports[`<LoginModal /> should load the component with props 1`] = `"<div class=\\"login-dialog\\"><div><div style=\\"z-index: 1013;\\" class=\\"el-dialog__wrapper\\"><div style=\\"top: 15%;\\" class=\\"el-dialog el-dialog--tiny\\"><div class=\\"el-dialog__header\\"><span class=\\"el-dialog__title\\">Login</span><button type=\\"button\\" class=\\"el-dialog__headerbtn\\"><i class=\\"el-dialog__close el-icon el-icon-close\\"></i></button></div><form class=\\"el-form el-form--label-right login-form\\"><div class=\\"el-dialog__body\\"><div class=\\"el-alert el-alert--error\\"><i class=\\"el-alert__icon el-icon-circle-cross is-big\\"></i><div class=\\"el-alert__content\\"><span class=\\"el-alert__title is-bold\\">Error Title</span><p class=\\"el-alert__description\\">Error Description</p><i class=\\"el-alert__closebtn el-icon-close\\" style=\\"display: none;\\"></i></div></div><br><div class=\\"el-input\\"><input name=\\"username\\" placeholder=\\"Username\\" type=\\"text\\" class=\\"el-input__inner\\" autocomplete=\\"off\\" value=\\"\\"></div><br><br><div class=\\"el-input\\"><input name=\\"password\\" placeholder=\\"Type your password\\" type=\\"password\\" class=\\"el-input__inner\\" autocomplete=\\"off\\" value=\\"\\"></div></div><div class=\\"el-dialog__footer dialog-footer\\"><button class=\\"el-button el-button--default cancel-login-button\\" type=\\"button\\"><span>Cancel</span></button><button class=\\"el-button el-button--default login-button\\" type=\\"submit\\"><span>Login</span></button></div></form></div></div><div class=\\"v-modal\\" style=\\"z-index: 1012;\\"></div></div></div>"`;
exports[`<LoginModal /> should load the component with props 1`] = `"<div class=\\"login-dialog\\"><div><div style=\\"z-index: 1013;\\" class=\\"el-dialog__wrapper\\"><div style=\\"top: 15%;\\" class=\\"el-dialog el-dialog--tiny\\"><div class=\\"el-dialog__header\\"><span class=\\"el-dialog__title\\">Login</span><button type=\\"button\\" class=\\"el-dialog__headerbtn\\"><i class=\\"el-dialog__close el-icon el-icon-close\\"></i></button></div><div class=\\"el-dialog__body\\"><form class=\\"el-form el-form--label-right login-form\\"><div class=\\"el-form-item\\"><div class=\\"el-form-item__content\\"><div style=\\"line-height: 10px;\\" class=\\"el-alert el-alert--error\\"><i class=\\"el-alert__icon el-icon-circle-cross is-big\\"></i><div class=\\"el-alert__content\\"><span class=\\"el-alert__title is-bold\\">Error Title</span><p class=\\"el-alert__description\\">Error Description</p><i class=\\"el-alert__closebtn el-icon-close\\" style=\\"display: none;\\"></i></div></div></div></div><div class=\\"el-form-item is-required\\"><div class=\\"el-form-item__content\\"><div class=\\"el-input\\"><input name=\\"username\\" placeholder=\\"Type your username\\" type=\\"text\\" class=\\"el-input__inner\\" autocomplete=\\"off\\" value=\\"\\"></div></div></div><div class=\\"el-form-item is-required\\"><div class=\\"el-form-item__content\\"><div class=\\"el-input\\"><input name=\\"password\\" placeholder=\\"Type your password\\" type=\\"password\\" class=\\"el-input__inner\\" autocomplete=\\"off\\" value=\\"\\"></div></div></div><div style=\\"float: right;\\" class=\\"el-form-item\\"><div class=\\"el-form-item__content\\"><button class=\\"el-button el-button--default cancel-login-button\\" type=\\"button\\"><span>Cancel</span></button><button class=\\"el-button el-button--default login-button\\" type=\\"submit\\"><span>Login</span></button></div></div></form></div></div></div><div class=\\"v-modal\\" style=\\"z-index: 1012;\\"></div></div></div>"`;

View file

@ -35,7 +35,7 @@ describe('<LoginModal />', () => {
onSubmit: () => {}
};
const wrapper = mount(<LoginModal {...props} />);
wrapper.find('.el-dialog__footer > .cancel-login-button').simulate('click');
wrapper.find('button.cancel-login-button').simulate('click');
expect(props.onCancel).toHaveBeenCalled();
wrapper.find('.el-dialog__headerbtn > .el-dialog__close').simulate('click');
expect(props.onCancel).toHaveBeenCalled();
@ -45,35 +45,40 @@ describe('<LoginModal />', () => {
const props = {
visibility: true,
error: {},
onCancel: () => { },
onSubmit: () => { }
onCancel: () => {},
onSubmit: () => {}
};
const wrapper = mount(<LoginModal {...props} />);
const { setCredentials } = wrapper.instance();
expect(setCredentials('username', 'xyz')).toBeUndefined();
expect(wrapper.state('username')).toEqual('xyz');
expect(wrapper.state('form').username).toEqual('xyz');
expect(setCredentials('password', '1234')).toBeUndefined();
expect(wrapper.state('password')).toEqual('1234');
expect(wrapper.state('form').password).toEqual('1234');
});
it('submitCredential: should call the onSubmit', async () => {
it('submitCredential: should call the onSubmit', () => {
const props = {
visibility: true,
error: {},
onCancel: () => { },
onCancel: () => {},
onSubmit: jest.fn()
};
const event = {
preventDefault: jest.fn()
}
};
const wrapper = mount(<LoginModal {...props} />);
const { submitCredentials } = wrapper.instance();
wrapper.setState({username: 'sam', password: 1234})
await submitCredentials(event);
expect(props.onSubmit).toHaveBeenCalledWith('sam', 1234);
wrapper
.find('input[type="text"]')
.simulate('change', { target: { value: 'sam' } });
wrapper
.find('input[type="password"]')
.simulate('change', { target: { value: '1234' } });
submitCredentials(event);
expect(event.preventDefault).toHaveBeenCalled();
expect(props.onSubmit).toHaveBeenCalledWith('sam', '1234');
});
});