Optimize form validation

This commit is contained in:
Pig Fang 2019-07-08 13:10:34 +08:00
parent 0d005707bd
commit a4d4dcfa9c
11 changed files with 21 additions and 145 deletions

View File

@ -18,6 +18,7 @@
type="text" type="text"
class="form-control" class="form-control"
:placeholder="$t('auth.captcha')" :placeholder="$t('auth.captcha')"
required
> >
</div> </div>
</div> </div>

View File

@ -7,6 +7,7 @@
type="email" type="email"
class="form-control" class="form-control"
:placeholder="$t('auth.email')" :placeholder="$t('auth.email')"
required
> >
<span class="glyphicon glyphicon-envelope form-control-feedback" /> <span class="glyphicon glyphicon-envelope form-control-feedback" />
</div> </div>
@ -14,7 +15,6 @@
<captcha ref="captcha" /> <captcha ref="captcha" />
<div class="callout callout-success" :class="{ hide: !successMsg }">{{ successMsg }}</div> <div class="callout callout-success" :class="{ hide: !successMsg }">{{ successMsg }}</div>
<div class="callout callout-info" :class="{ hide: !infoMsg }">{{ infoMsg }}</div>
<div class="callout callout-warning" :class="{ hide: !warningMsg }">{{ warningMsg }}</div> <div class="callout callout-warning" :class="{ hide: !warningMsg }">{{ warningMsg }}</div>
<div class="row"> <div class="row">
@ -59,7 +59,6 @@ export default {
data: () => ({ data: () => ({
email: '', email: '',
successMsg: '', successMsg: '',
infoMsg: '',
warningMsg: '', warningMsg: '',
pending: false, pending: false,
}), }),
@ -67,30 +66,16 @@ export default {
async submit() { async submit() {
const { email } = this const { email } = this
if (!email) {
this.infoMsg = this.$t('auth.emptyEmail')
this.$refs.email.focus()
return
}
if (!/\S+@\S+\.\S+/.test(email)) {
this.infoMsg = this.$t('auth.invalidEmail')
this.$refs.email.focus()
return
}
this.pending = true this.pending = true
const { code, message } = await this.$http.post( const { code, message } = await this.$http.post(
'/auth/forgot', '/auth/forgot',
{ email, captcha: await this.$refs.captcha.execute() } { email, captcha: await this.$refs.captcha.execute() }
) )
if (code === 0) { if (code === 0) {
this.infoMsg = ''
this.warningMsg = '' this.warningMsg = ''
this.successMsg = message this.successMsg = message
this.pending = false this.pending = false
} else { } else {
this.infoMsg = ''
this.warningMsg = message this.warningMsg = message
this.pending = false this.pending = false
this.$refs.captcha.refresh() this.$refs.captcha.refresh()

View File

@ -6,6 +6,7 @@
v-model="identification" v-model="identification"
class="form-control" class="form-control"
:placeholder="$t('auth.identification')" :placeholder="$t('auth.identification')"
required
> >
<span class="glyphicon glyphicon-envelope form-control-feedback" /> <span class="glyphicon glyphicon-envelope form-control-feedback" />
</div> </div>
@ -16,13 +17,13 @@
type="password" type="password"
class="form-control" class="form-control"
:placeholder="$t('auth.password')" :placeholder="$t('auth.password')"
required
> >
<span class="glyphicon glyphicon-lock form-control-feedback" /> <span class="glyphicon glyphicon-lock form-control-feedback" />
</div> </div>
<captcha v-if="tooManyFails" ref="captcha" /> <captcha v-if="tooManyFails" ref="captcha" />
<div class="callout callout-info" :class="{ hide: !infoMsg }">{{ infoMsg }}</div>
<div class="callout callout-warning" :class="{ hide: !warningMsg }">{{ warningMsg }}</div> <div class="callout callout-warning" :class="{ hide: !warningMsg }">{{ warningMsg }}</div>
<div class="row"> <div class="row">
@ -78,7 +79,6 @@ export default {
tooManyFails: blessing.extra.tooManyFails, tooManyFails: blessing.extra.tooManyFails,
recaptcha: blessing.extra.recaptcha, recaptcha: blessing.extra.recaptcha,
invisible: blessing.extra.invisible, invisible: blessing.extra.invisible,
infoMsg: '',
warningMsg: '', warningMsg: '',
pending: false, pending: false,
} }
@ -89,18 +89,6 @@ export default {
identification, password, remember, identification, password, remember,
} = this } = this
if (!identification) {
this.infoMsg = this.$t('auth.emptyIdentification')
this.$refs.identification.focus()
return
}
if (!password) {
this.infoMsg = this.$t('auth.emptyPassword')
this.$refs.password.focus()
return
}
this.pending = true this.pending = true
const { const {
code, message, data: { login_fails: loginFails } = { login_fails: 0 }, code, message, data: { login_fails: loginFails } = { login_fails: 0 },
@ -131,7 +119,6 @@ export default {
} }
this.tooManyFails = true this.tooManyFails = true
} }
this.infoMsg = ''
this.warningMsg = message this.warningMsg = message
this.pending = false this.pending = false
this.$refs.captcha.refresh() this.$refs.captcha.refresh()

View File

@ -7,6 +7,7 @@
type="email" type="email"
class="form-control" class="form-control"
:placeholder="$t('auth.email')" :placeholder="$t('auth.email')"
required
> >
<span class="glyphicon glyphicon-envelope form-control-feedback" /> <span class="glyphicon glyphicon-envelope form-control-feedback" />
</div> </div>
@ -17,6 +18,9 @@
type="password" type="password"
class="form-control" class="form-control"
:placeholder="$t('auth.password')" :placeholder="$t('auth.password')"
required
minlength="8"
maxlength="32"
> >
<span class="glyphicon glyphicon-lock form-control-feedback" /> <span class="glyphicon glyphicon-lock form-control-feedback" />
</div> </div>
@ -27,6 +31,9 @@
type="password" type="password"
class="form-control" class="form-control"
:placeholder="$t('auth.repeat-pwd')" :placeholder="$t('auth.repeat-pwd')"
required
minlength="8"
maxlength="32"
> >
<span class="glyphicon glyphicon-log-in form-control-feedback" /> <span class="glyphicon glyphicon-log-in form-control-feedback" />
</div> </div>
@ -44,6 +51,7 @@
type="text" type="text"
class="form-control" class="form-control"
:placeholder="$t('auth.player-name')" :placeholder="$t('auth.player-name')"
required
> >
<span class="glyphicon glyphicon-pencil form-control-feedback" /> <span class="glyphicon glyphicon-pencil form-control-feedback" />
</div> </div>
@ -60,6 +68,7 @@
type="text" type="text"
class="form-control" class="form-control"
:placeholder="$t('auth.nickname')" :placeholder="$t('auth.nickname')"
required
> >
<span class="glyphicon glyphicon-pencil form-control-feedback" /> <span class="glyphicon glyphicon-pencil form-control-feedback" />
</div> </div>
@ -125,48 +134,12 @@ export default {
email, password, confirm, playerName, nickname, email, password, confirm, playerName, nickname,
} = this } = this
if (!email) {
this.infoMsg = this.$t('auth.emptyEmail')
this.$refs.email.focus()
return
}
if (!/\S+@\S+\.\S+/.test(email)) {
this.infoMsg = this.$t('auth.invalidEmail')
this.$refs.email.focus()
return
}
if (!password) {
this.infoMsg = this.$t('auth.emptyPassword')
this.$refs.password.focus()
return
}
if (password.length < 8 || password.length > 32) {
this.infoMsg = this.$t('auth.invalidPassword')
this.$refs.password.focus()
return
}
if (password !== confirm) { if (password !== confirm) {
this.infoMsg = this.$t('auth.invalidConfirmPwd') this.infoMsg = this.$t('auth.invalidConfirmPwd')
this.$refs.confirm.focus() this.$refs.confirm.focus()
return return
} }
if (this.requirePlayer && !playerName) {
this.infoMsg = this.$t('auth.emptyPlayerName')
this.$refs.playerName.focus()
return
}
if (!this.requirePlayer && !nickname) {
this.infoMsg = this.$t('auth.emptyNickname')
this.$refs.nickname.focus()
return
}
this.pending = true this.pending = true
const { code, message } = await this.$http.post( const { code, message } = await this.$http.post(
'/auth/register', '/auth/register',

View File

@ -7,6 +7,9 @@
type="password" type="password"
class="form-control" class="form-control"
:placeholder="$t('auth.password')" :placeholder="$t('auth.password')"
required
minlength="8"
maxlength="32"
> >
<span class="glyphicon glyphicon-lock form-control-feedback" /> <span class="glyphicon glyphicon-lock form-control-feedback" />
</div> </div>
@ -17,6 +20,9 @@
type="password" type="password"
class="form-control" class="form-control"
:placeholder="$t('auth.repeat-pwd')" :placeholder="$t('auth.repeat-pwd')"
required
minlength="8"
maxlength="32"
> >
<span class="glyphicon glyphicon-log-in form-control-feedback" /> <span class="glyphicon glyphicon-log-in form-control-feedback" />
</div> </div>
@ -65,18 +71,6 @@ export default {
async reset() { async reset() {
const { password, confirm } = this const { password, confirm } = this
if (!password) {
this.infoMsg = this.$t('auth.emptyPassword')
this.$refs.password.focus()
return
}
if (password.length < 8 || password.length > 32) {
this.infoMsg = this.$t('auth.invalidPassword')
this.$refs.password.focus()
return
}
if (password !== confirm) { if (password !== confirm) {
this.infoMsg = this.$t('auth.invalidConfirmPwd') this.infoMsg = this.$t('auth.invalidConfirmPwd')
this.$refs.confirm.focus() this.$refs.confirm.focus()

View File

@ -20,19 +20,9 @@ test('submit forgot form', async () => {
.mockResolvedValueOnce({ code: 0, message: 'ok' }) .mockResolvedValueOnce({ code: 0, message: 'ok' })
const wrapper = mount(Forgot, { stubs: { Captcha } }) const wrapper = mount(Forgot, { stubs: { Captcha } })
const form = wrapper.find('form') const form = wrapper.find('form')
const info = wrapper.find('.callout-info')
const warning = wrapper.find('.callout-warning') const warning = wrapper.find('.callout-warning')
const success = wrapper.find('.callout-success') const success = wrapper.find('.callout-success')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.emptyEmail')
wrapper.find('[type="email"]').setValue('a')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.invalidEmail')
wrapper.find('[type="email"]').setValue('a@b.c') wrapper.find('[type="email"]').setValue('a@b.c')
form.trigger('submit') form.trigger('submit')
await flushPromises() await flushPromises()

View File

@ -28,18 +28,9 @@ test('login', async () => {
.mockResolvedValueOnce({ code: 0, message: 'ok' }) .mockResolvedValueOnce({ code: 0, message: 'ok' })
const wrapper = mount(Login, { stubs: { Captcha } }) const wrapper = mount(Login, { stubs: { Captcha } })
const form = wrapper.find('form') const form = wrapper.find('form')
const info = wrapper.find('.callout-info')
const warning = wrapper.find('.callout-warning') const warning = wrapper.find('.callout-warning')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.emptyIdentification')
wrapper.find('input').setValue('a@b.c') wrapper.find('input').setValue('a@b.c')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.emptyPassword')
wrapper.find('[type="password"]').setValue('123') wrapper.find('[type="password"]').setValue('123')
form.trigger('submit') form.trigger('submit')
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()

View File

@ -34,32 +34,9 @@ test('register', async () => {
const info = wrapper.find('.callout-info') const info = wrapper.find('.callout-info')
const warning = wrapper.find('.callout-warning') const warning = wrapper.find('.callout-warning')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.emptyEmail')
wrapper.find('[type="email"]').setValue('a')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.invalidEmail')
wrapper.find('[type="email"]').setValue('a@b.c') wrapper.find('[type="email"]').setValue('a@b.c')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.emptyPassword')
wrapper.findAll('[type="password"]').at(0)
.setValue('123456')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.invalidPassword')
wrapper.findAll('[type="password"]').at(0) wrapper.findAll('[type="password"]').at(0)
.setValue('12345678') .setValue('12345678')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.invalidConfirmPwd')
wrapper.findAll('[type="password"]').at(1) wrapper.findAll('[type="password"]').at(1)
.setValue('123456') .setValue('123456')
form.trigger('submit') form.trigger('submit')
@ -68,10 +45,6 @@ test('register', async () => {
wrapper.findAll('[type="password"]').at(1) wrapper.findAll('[type="password"]').at(1)
.setValue('12345678') .setValue('12345678')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.emptyNickname')
wrapper.findAll('[type="text"]').at(0) wrapper.findAll('[type="text"]').at(0)
.setValue('abc') .setValue('abc')
form.trigger('submit') form.trigger('submit')
@ -99,17 +72,11 @@ test('register with player name', async () => {
Vue.prototype.$http.post.mockResolvedValue({ code: 0, message: 'ok' }) Vue.prototype.$http.post.mockResolvedValue({ code: 0, message: 'ok' })
const wrapper = mount(Register, { stubs: { Captcha } }) const wrapper = mount(Register, { stubs: { Captcha } })
const form = wrapper.find('form') const form = wrapper.find('form')
const info = wrapper.find('.callout-info')
wrapper.find('[type="email"]').setValue('a@b.c') wrapper.find('[type="email"]').setValue('a@b.c')
wrapper.findAll('[type="password"]').at(0) wrapper.findAll('[type="password"]').at(0)
.setValue('12345678') .setValue('12345678')
wrapper.findAll('[type="password"]').at(1) wrapper.findAll('[type="password"]').at(1)
.setValue('12345678') .setValue('12345678')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.emptyPlayerName')
wrapper.findAll('[type="text"]').at(0) wrapper.findAll('[type="text"]').at(0)
.setValue('abc') .setValue('abc')
form.trigger('submit') form.trigger('submit')

View File

@ -15,22 +15,8 @@ test('reset password', async () => {
const info = wrapper.find('.callout-info') const info = wrapper.find('.callout-info')
const warning = wrapper.find('.callout-warning') const warning = wrapper.find('.callout-warning')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.emptyPassword')
wrapper.findAll('[type="password"]').at(0)
.setValue('123456')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.invalidPassword')
wrapper.findAll('[type="password"]').at(0) wrapper.findAll('[type="password"]').at(0)
.setValue('12345678') .setValue('12345678')
form.trigger('submit')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(info.text()).toBe('auth.invalidConfirmPwd')
wrapper.findAll('[type="password"]').at(1) wrapper.findAll('[type="password"]').at(1)
.setValue('123456') .setValue('123456')
form.trigger('submit') form.trigger('submit')

View File

@ -6,6 +6,7 @@
- Push notifications to queue for performance. - Push notifications to queue for performance.
- Optimized exception stack of Ajax error. - Optimized exception stack of Ajax error.
- Optimized validating forms of pages like logining and registering.
## Fixed ## Fixed

View File

@ -6,6 +6,7 @@
- 发送通知时将任务推送到队列 - 发送通知时将任务推送到队列
- 优化 Ajax 中的错误显示 - 优化 Ajax 中的错误显示
- 优化登录、注册等页面的表单校验
## 修复 ## 修复