diff --git a/webapp/graphql/inviteCodes.js b/webapp/graphql/inviteCodes.js new file mode 100644 index 000000000..9ff171759 --- /dev/null +++ b/webapp/graphql/inviteCodes.js @@ -0,0 +1,19 @@ +import gql from 'graphql-tag' + +export const validateInviteCodeQuery = gql` + query ($code: String!) { + validateInviteCode(code: $code) { + invitedTo { + id + slug + groupType + } + } + } +` + +export const redeemInviteCodeMutation = gql` + mutation ($code: String!) { + redeemInviteCode(code: $code) + } +` diff --git a/webapp/pages/registration.spec.js b/webapp/pages/registration.spec.js index 8be08fa5e..9bc6f150b 100644 --- a/webapp/pages/registration.spec.js +++ b/webapp/pages/registration.spec.js @@ -2,6 +2,7 @@ import Vuex from 'vuex' import { mount } from '@vue/test-utils' import Registration from './registration.vue' import Vue from 'vue' +import { validateInviteCodeQuery, redeemInviteCodeMutation } from '~/graphql/inviteCodes' const localVue = global.localVue @@ -12,6 +13,18 @@ const stubs = { 'infinite-loading': true, } +const queryMock = jest.fn() +const mutationMock = jest.fn() + +const app = { + apolloProvider: { + defaultClient: { + query: queryMock, + mutation: mutationMock, + }, + }, +} + describe('Registration', () => { let wrapper let Wrapper @@ -20,6 +33,7 @@ describe('Registration', () => { let store let redirect let isLoggedIn + let route beforeEach(() => { mocks = { @@ -39,6 +53,9 @@ describe('Registration', () => { asyncData = false isLoggedIn = false redirect = jest.fn() + route = { + query: {}, + } }) describe('mount', () => { @@ -65,6 +82,8 @@ describe('Registration', () => { const aData = await Registration.asyncData({ store, redirect, + route, + app, }) Registration.data = function () { return { ...data, ...aData } @@ -330,6 +349,92 @@ describe('Registration', () => { expect(redirect).toHaveBeenCalledWith('/') }) + describe('already logged in', () => { + beforeEach(async () => { + asyncData = true + isLoggedIn = true + }) + + describe('route contains personal invite code', () => { + beforeEach(async () => { + jest.clearAllMocks() + queryMock.mockResolvedValue({ + data: { + validateInviteCode: { + invitedTo: null, + }, + }, + }) + route.query.inviteCode = 'ABCDEF' + wrapper = await Wrapper() + }) + + it('calls validate invite code', () => { + expect(queryMock).toHaveBeenCalledWith({ + query: validateInviteCodeQuery, + variables: { + code: 'ABCDEF', + }, + }) + }) + + it('redirects to index', () => { + expect(redirect).toHaveBeenCalledWith('/') + }) + + it('does not redeem the link', () => { + expect(mutationMock).not.toBeCalled() + }) + }) + + // no idea why this is not working + describe.skip('route contains group invite code to public group', () => { + beforeEach(async () => { + jest.clearAllMocks() + queryMock.mockResolvedValue({ + data: { + validateInviteCode: { + invitedTo: { + id: 'public-group', + slug: 'public-group', + groupType: 'public', + }, + }, + }, + }) + mutationMock.mockResolvedValue({ + data: { + redeemInviteCode: true, + }, + }) + route.query.inviteCode = 'ABCDEF' + wrapper = await Wrapper() + }) + + it('calls validate invite code', () => { + expect(queryMock).toHaveBeenCalledWith({ + query: validateInviteCodeQuery, + variables: { + code: 'ABCDEF', + }, + }) + }) + + it('redirects to group', () => { + expect(redirect).toHaveBeenCalledWith('/groups/public-group/public-group') + }) + + it('redeems the code', () => { + expect(mutationMock).toBeCalledWith({ + mutation: redeemInviteCodeMutation, + variables: { + code: 'ABCDEF', + }, + }) + }) + }) + }) + // copied from webapp/components/Registration/Signup.spec.js as testing template // describe('with invitation code', () => { // let action diff --git a/webapp/pages/registration.vue b/webapp/pages/registration.vue index c62d28c06..ec8d94adc 100644 --- a/webapp/pages/registration.vue +++ b/webapp/pages/registration.vue @@ -11,6 +11,7 @@