rewrite "EmailVerification" UI widget

This commit is contained in:
Pig Fang 2020-02-12 10:02:15 +08:00
parent 19ad09920b
commit ca7db2585f
7 changed files with 93 additions and 72 deletions

View File

@ -61,7 +61,10 @@ class UserController extends Controller
],
'widgets' => [
[
['user.widgets.dashboard.usage'],
[
'user.widgets.email-verification',
'user.widgets.dashboard.usage',
],
['user.widgets.dashboard.announcement'],
],
],

View File

@ -1,41 +0,0 @@
<template>
<div v-if="!verified" class="callout callout-info">
<h4><i class="fas fa-envelope" /> {{ $t('user.verification.title') }}</h4>
<p>
{{ $t('user.verification.message') }}
<span v-if="pending">
<i class="fas fa-spin fa-spinner" />
{{ $t('user.verification.sending') }}
</span>
<a v-else href="#" @click="resend">
{{ $t('user.verification.resend') }}
</a>
</p>
</div>
</template>
<script>
import { toast } from '../scripts/notify'
export default {
name: 'EmailVerification',
data() {
return {
verified: !blessing.extra.unverified,
pending: false,
}
},
methods: {
async resend() {
this.pending = true
const { code, message } = await this.$http.post('/user/email-verification')
if (code === 0) {
toast.success(message)
} else {
toast.error(message)
}
this.pending = false
},
},
}
</script>

View File

@ -5,6 +5,7 @@ import './i18n'
import './net'
import './event'
import './notification'
import './emailVerification'
import './logout'
window.addEventListener('load', () => {

View File

@ -0,0 +1,9 @@
import React from 'react'
import ReactDOM from 'react-dom'
import EmailVerification from '@/views/widgets/EmailVerification'
const container = document.querySelector('#email-verification')
if (blessing.extra.unverified && container) {
ReactDOM.render(<EmailVerification />, container)
}

View File

@ -0,0 +1,44 @@
import React, { useState } from 'react'
import { t } from '@/scripts/i18n'
import * as fetch from '@/scripts/net'
import { toast } from '@/scripts/notify'
const EmailVerification: React.FC = () => {
const [isSending, setIsSending] = useState(false)
const send = async () => {
setIsSending(true)
const { code, message } = await fetch.post<fetch.ResponseBody>(
'/user/email-verification',
)
if (code === 0) {
toast.success(message)
} else {
toast.error(message)
}
setIsSending(false)
}
return (
<div className="callout callout-info">
<h4>
<i className="fas fa-envelope"></i> {t('user.verification.title')}
</h4>
<p>
{t('user.verification.message')}
{isSending ? (
<>
<i className="fas fa-spin fa-spinner mr-1"></i>
{t('user.verification.sending')}
</>
) : (
<a href="#" onClick={send}>
{t('user.verification.resend')}
</a>
)}
</p>
</div>
)
}
export default EmailVerification

View File

@ -1,30 +0,0 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import { flushPromises } from '../utils'
import { toast } from '@/scripts/notify'
import EmailVerification from '@/components/EmailVerification.vue'
jest.mock('@/scripts/notify')
test('message box should not be render if verified', () => {
window.blessing.extra = { unverified: false }
const wrapper = mount(EmailVerification)
expect(wrapper.isEmpty()).toBeTrue()
})
test('resend email', async () => {
window.blessing.extra = { unverified: true }
Vue.prototype.$http.post
.mockResolvedValueOnce({ code: 1, message: '1' })
.mockResolvedValueOnce({ code: 0, message: '0' })
const wrapper = mount(EmailVerification)
const button = wrapper.find('a')
button.trigger('click')
await flushPromises()
expect(toast.error).toBeCalledWith('1')
button.trigger('click')
await flushPromises()
expect(toast.success).toBeCalledWith('0')
})

View File

@ -0,0 +1,35 @@
import React from 'react'
import { render, fireEvent, wait } from '@testing-library/react'
import { t } from '@/scripts/i18n'
import * as fetch from '@/scripts/net'
import EmailVerification from '@/views/widgets/EmailVerification'
jest.mock('@/scripts/net')
describe('send email', async () => {
it('succeeded', async () => {
fetch.post.mockResolvedValue({ code: 0, message: 'success' })
const { getByText, getByRole, queryByText } = render(<EmailVerification />)
fireEvent.click(getByText(t('user.verification.resend')))
await wait()
expect(fetch.post).toBeCalledWith('/user/email-verification')
expect(queryByText('success')).toBeInTheDocument()
expect(getByRole('status')).toHaveClass('alert-success')
})
it('failed', async () => {
fetch.post.mockResolvedValue({ code: 1, message: 'failed' })
const { getByText, getByRole, queryByText } = render(<EmailVerification />)
fireEvent.click(getByText(t('user.verification.resend')))
await wait()
expect(fetch.post).toBeCalledWith('/user/email-verification')
expect(queryByText('failed')).toBeInTheDocument()
expect(getByRole('alert')).toHaveClass('alert-danger')
})
})