From 9f78c31f66cf0d1a882e8335a6d54569e95af6b8 Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Tue, 28 Aug 2018 08:12:30 +0200 Subject: [PATCH] fix: login modal validation (#958) --- src/webui/app.js | 4 +- src/webui/components/Login/index.js | 146 ++++++++++++------ .../__snapshots__/login.spec.js.snap | 4 +- test/unit/webui/components/login.spec.js | 27 ++-- 4 files changed, 115 insertions(+), 66 deletions(-) diff --git a/src/webui/app.js b/src/webui/app.js index 025b28279..7fd8d7302 100644 --- a/src/webui/app.js +++ b/src/webui/app.js @@ -64,7 +64,7 @@ export default class App extends Component { } /** - * Toogles the login modal + * Toggles the login modal * Required by:
*/ 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 diff --git a/src/webui/components/Login/index.js b/src/webui/components/Login/index.js index 5b6ea394d..fd76567b5 100644 --- a/src/webui/components/Login/index.js +++ b/src/webui/components/Login/index.js @@ -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: */ - 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 (
-
- - {this.renderLoginError(error)} -
- -
-
- -
- - - - -
+ +
+ + {this.renderLoginError(error)} + + + + + + + + + + + +
+
); diff --git a/test/unit/webui/components/__snapshots__/login.spec.js.snap b/test/unit/webui/components/__snapshots__/login.spec.js.snap index b5a6c3987..cbeb535fb 100644 --- a/test/unit/webui/components/__snapshots__/login.spec.js.snap +++ b/test/unit/webui/components/__snapshots__/login.spec.js.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` should load the component in default state 1`] = `"
Login



"`; +exports[` should load the component in default state 1`] = `"
Login
"`; -exports[` should load the component with props 1`] = `"
Login
Error Title

Error Description




"`; +exports[` should load the component with props 1`] = `"
Login
Error Title

Error Description

"`; diff --git a/test/unit/webui/components/login.spec.js b/test/unit/webui/components/login.spec.js index 850980a27..53fb76df5 100644 --- a/test/unit/webui/components/login.spec.js +++ b/test/unit/webui/components/login.spec.js @@ -35,7 +35,7 @@ describe('', () => { onSubmit: () => {} }; const wrapper = mount(); - 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('', () => { const props = { visibility: true, error: {}, - onCancel: () => { }, - onSubmit: () => { } + onCancel: () => {}, + onSubmit: () => {} }; const wrapper = mount(); 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(); 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'); }); });