diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 939e311f..4e504111 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -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'], ], ], diff --git a/resources/assets/src/components/EmailVerification.vue b/resources/assets/src/components/EmailVerification.vue deleted file mode 100644 index 9617aa2d..00000000 --- a/resources/assets/src/components/EmailVerification.vue +++ /dev/null @@ -1,41 +0,0 @@ - - - diff --git a/resources/assets/src/scripts/app.ts b/resources/assets/src/scripts/app.ts index 5128438b..69c7cb93 100644 --- a/resources/assets/src/scripts/app.ts +++ b/resources/assets/src/scripts/app.ts @@ -5,6 +5,7 @@ import './i18n' import './net' import './event' import './notification' +import './emailVerification' import './logout' window.addEventListener('load', () => { diff --git a/resources/assets/src/scripts/emailVerification.tsx b/resources/assets/src/scripts/emailVerification.tsx new file mode 100644 index 00000000..2389fa59 --- /dev/null +++ b/resources/assets/src/scripts/emailVerification.tsx @@ -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(, container) +} diff --git a/resources/assets/src/views/widgets/EmailVerification.tsx b/resources/assets/src/views/widgets/EmailVerification.tsx new file mode 100644 index 00000000..72b6538b --- /dev/null +++ b/resources/assets/src/views/widgets/EmailVerification.tsx @@ -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( + '/user/email-verification', + ) + if (code === 0) { + toast.success(message) + } else { + toast.error(message) + } + setIsSending(false) + } + + return ( +
+

+ {t('user.verification.title')} +

+

+ {t('user.verification.message')} + {isSending ? ( + <> + + {t('user.verification.sending')} + + ) : ( + + {t('user.verification.resend')} + + )} +

+
+ ) +} + +export default EmailVerification diff --git a/resources/assets/tests/components/EmailVerification.test.ts b/resources/assets/tests/components/EmailVerification.test.ts deleted file mode 100644 index 58032fa8..00000000 --- a/resources/assets/tests/components/EmailVerification.test.ts +++ /dev/null @@ -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') -}) diff --git a/resources/assets/tests/views/widgets/EmailVerification.test.tsx b/resources/assets/tests/views/widgets/EmailVerification.test.tsx new file mode 100644 index 00000000..8e0793fa --- /dev/null +++ b/resources/assets/tests/views/widgets/EmailVerification.test.tsx @@ -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() + + 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() + + 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') + }) +})