diff --git a/webapp/pages/settings/my-email-address/verify.spec.js b/webapp/pages/settings/my-email-address/verify.spec.js new file mode 100644 index 000000000..9280685d1 --- /dev/null +++ b/webapp/pages/settings/my-email-address/verify.spec.js @@ -0,0 +1,164 @@ +import { config, mount, createLocalVue } from '@vue/test-utils' +import EmailVerifyPage from './verify.vue' +import Vuex from 'vuex' +import Styleguide from '@human-connection/styleguide' + +const localVue = createLocalVue() + +localVue.use(Vuex) +localVue.use(Styleguide) + +config.stubs['client-only'] = '' +config.stubs['sweetalert-icon'] = '' + +describe('EmailVerifyPage', () => { + let store + let mocks + let wrapper + let setUser + + beforeEach(() => { + setUser = jest.fn() + wrapper = null + store = new Vuex.Store({ + getters: { + 'auth/user': () => { + return { id: 'u23', email: 'some-mail@example.org' } + }, + }, + mutations: { + 'auth/SET_USER': setUser, + }, + }) + mocks = { + $t: jest.fn(t => t), + $toast: { + success: jest.fn(), + error: jest.fn(), + }, + $router: { + replace: jest.fn(), + }, + store, + } + }) + + describe('asyncData', () => { + const asyncDataAction = () => { + const context = { + store: mocks.store, + query: {}, + app: { + apolloProvider: { + defaultClient: mocks.$apollo, + }, + }, + } + return EmailVerifyPage.asyncData(context) + } + + describe('backend sends successful response', () => { + beforeEach(() => { + mocks = { + ...mocks, + $apollo: { + mutate: jest.fn().mockResolvedValue({ + data: { + VerifyEmailAddress: { + email: 'verified-email@example.org', + }, + }, + }), + }, + } + }) + + it('sets `success` to true', async () => { + await expect(asyncDataAction()).resolves.toEqual({ + success: true, + }) + }) + + it("updates current user's email", async () => { + await asyncDataAction() + expect(setUser).toHaveBeenCalledWith({}, { id: 'u23', email: 'verified-email@example.org' }) + }) + }) + + describe('backend sends unsuccessful response', () => { + beforeEach(() => { + mocks = { + ...mocks, + $apollo: { + mutate: jest.fn().mockRejectedValue({ + data: { VerifyEmailAddress: null }, + errors: [{ message: 'User account already exists with that email' }], + }), + }, + } + }) + + it('sets `success` to false', async () => { + await expect(asyncDataAction()).resolves.toEqual({ + success: false, + }) + }) + + it('does not updates current user', async () => { + await asyncDataAction() + expect(setUser).not.toHaveBeenCalled() + }) + }) + }) + + describe('mount', () => { + beforeEach(jest.useFakeTimers) + const Wrapper = () => { + return mount(EmailVerifyPage, { + store, + mocks, + localVue, + }) + } + + describe('given successful verification', () => { + beforeEach(() => { + mocks = { ...mocks, success: true } + wrapper = Wrapper() + }) + + it('shows success message', () => { + expect(wrapper.text()).toContain('settings.email.change-successful') + }) + + describe('after timeout', () => { + beforeEach(jest.runAllTimers) + + it('redirects to email settings page', () => { + expect(mocks.$router.replace).toHaveBeenCalledWith({ + name: 'settings-my-email-address', + }) + }) + }) + }) + + describe('given unsuccessful verification', () => { + beforeEach(() => { + mocks = { ...mocks, success: false } + wrapper = Wrapper() + }) + + it('shows success message', () => { + expect(wrapper.text()).toContain('settings.email.change-error') + }) + + describe('after timeout', () => { + beforeEach(jest.runAllTimers) + + it('does not redirect', () => { + expect(mocks.$router.replace).not.toHaveBeenCalledWith() + }) + }) + }) + }) +}) diff --git a/webapp/pages/settings/my-email-address/verify.vue b/webapp/pages/settings/my-email-address/verify.vue index f4c42bcb1..adf243355 100644 --- a/webapp/pages/settings/my-email-address/verify.vue +++ b/webapp/pages/settings/my-email-address/verify.vue @@ -38,19 +38,29 @@ export default { }, async asyncData(context) { const { + store, query, app: { apolloProvider }, } = context const client = apolloProvider.defaultClient let success const { email = '', nonce = '' } = query + const currentUser = store.getters['auth/user'] try { - await client.mutate({ + const response = await client.mutate({ mutation: VerifyEmailAddressMutation, variables: { email, nonce }, }) + const { + data: { VerifyEmailAddress }, + } = response success = true + store.commit( + 'auth/SET_USER', + { ...currentUser, email: VerifyEmailAddress.email }, + { root: true }, + ) } catch (error) { success = false }