diff options
Diffstat (limited to 'spec/frontend/invite_members/components/invite_members_modal_spec.js')
-rw-r--r-- | spec/frontend/invite_members/components/invite_members_modal_spec.js | 495 |
1 files changed, 157 insertions, 338 deletions
diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js index 3ab89b3dff2..15a366474e4 100644 --- a/spec/frontend/invite_members/components/invite_members_modal_spec.js +++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js @@ -1,28 +1,19 @@ -import { - GlDropdown, - GlDropdownItem, - GlDatepicker, - GlFormGroup, - GlSprintf, - GlLink, - GlModal, -} from '@gitlab/ui'; +import { GlLink, GlModal, GlSprintf } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import { stubComponent } from 'helpers/stub_component'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import Api from '~/api'; import ExperimentTracking from '~/experimentation/experiment_tracking'; import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue'; +import InviteModalBase from '~/invite_members/components/invite_modal_base.vue'; import ModalConfetti from '~/invite_members/components/confetti.vue'; import MembersTokenSelect from '~/invite_members/components/members_token_select.vue'; import { INVITE_MEMBERS_FOR_TASK, - CANCEL_BUTTON_TEXT, - INVITE_BUTTON_TEXT, MEMBERS_MODAL_CELEBRATE_INTRO, MEMBERS_MODAL_CELEBRATE_TITLE, - MEMBERS_MODAL_DEFAULT_TITLE, MEMBERS_PLACEHOLDER, MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT, LEARN_GITLAB, @@ -32,9 +23,16 @@ import axios from '~/lib/utils/axios_utils'; import httpStatus from '~/lib/utils/http_status'; import { getParameterValues } from '~/lib/utils/url_utility'; import { apiPaths, membersApiResponse, invitationsApiResponse } from '../mock_data/api_responses'; - -let wrapper; -let mock; +import { + propsData, + inviteSource, + newProjectPath, + user1, + user2, + user3, + user4, + GlEmoji, +} from '../mock_data/member_modal'; jest.mock('~/experimentation/experiment_tracking'); jest.mock('~/lib/utils/url_utility', () => ({ @@ -42,211 +40,125 @@ jest.mock('~/lib/utils/url_utility', () => ({ getParameterValues: jest.fn(() => []), })); -const id = '1'; -const name = 'test name'; -const isProject = false; -const inviteeType = 'members'; -const accessLevels = { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 }; -const defaultAccessLevel = 10; -const inviteSource = 'unknown'; -const helpLink = 'https://example.com'; -const tasksToBeDoneOptions = [ - { text: 'First task', value: 'first' }, - { text: 'Second task', value: 'second' }, -]; -const newProjectPath = 'projects/new'; -const projects = [ - { text: 'First project', value: '1' }, - { text: 'Second project', value: '2' }, -]; - -const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' }; -const user2 = { id: 2, name: 'Name Two', username: 'one_2', avatar_url: '' }; -const user3 = { - id: 'user-defined-token', - name: 'email@example.com', - username: 'one_2', - avatar_url: '', -}; -const user4 = { - id: 'user-defined-token', - name: 'email4@example.com', - username: 'one_4', - avatar_url: '', -}; -const sharedGroup = { id: '981' }; -const GlEmoji = { template: '<img/>' }; - -const createComponent = (data = {}, props = {}) => { - wrapper = shallowMountExtended(InviteMembersModal, { - provide: { - newProjectPath, - }, - propsData: { - id, - name, - isProject, - inviteeType, - accessLevels, - defaultAccessLevel, - tasksToBeDoneOptions, - projects, - helpLink, - ...props, - }, - data() { - return data; - }, - stubs: { - GlModal: stubComponent(GlModal, { - template: - '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-footer"></slot></div>', - }), - GlDropdown: true, - GlDropdownItem: true, - GlEmoji, - GlSprintf, - GlFormGroup: stubComponent(GlFormGroup, { - props: ['state', 'invalidFeedback', 'description'], - }), - }, - }); -}; - -const createInviteMembersToProjectWrapper = () => { - createComponent({ inviteeType: 'members' }, { isProject: true }); -}; - -const createInviteMembersToGroupWrapper = () => { - createComponent({ inviteeType: 'members' }, { isProject: false }); -}; +describe('InviteMembersModal', () => { + let wrapper; + let mock; + + const createComponent = (props = {}) => { + wrapper = shallowMountExtended(InviteMembersModal, { + provide: { + newProjectPath, + }, + propsData: { + ...propsData, + ...props, + }, + stubs: { + InviteModalBase, + GlSprintf, + GlModal: stubComponent(GlModal, { + template: '<div><slot></slot><slot name="modal-footer"></slot></div>', + }), + GlEmoji, + }, + }); + }; -const createInviteGroupToProjectWrapper = () => { - createComponent({ inviteeType: 'group' }, { isProject: true }); -}; + const createInviteMembersToProjectWrapper = () => { + createComponent({ isProject: true }); + }; -const createInviteGroupToGroupWrapper = () => { - createComponent({ inviteeType: 'group' }, { isProject: false }); -}; + const createInviteMembersToGroupWrapper = () => { + createComponent({ isProject: false }); + }; -beforeEach(() => { - gon.api_version = 'v4'; - mock = new MockAdapter(axios); -}); + beforeEach(() => { + gon.api_version = 'v4'; + mock = new MockAdapter(axios); + }); -afterEach(() => { - wrapper.destroy(); - wrapper = null; - mock.restore(); -}); + afterEach(() => { + wrapper.destroy(); + wrapper = null; + mock.restore(); + }); -describe('InviteMembersModal', () => { - const findDropdown = () => wrapper.findComponent(GlDropdown); - const findDropdownItems = () => findDropdown().findAllComponents(GlDropdownItem); - const findDatepicker = () => wrapper.findComponent(GlDatepicker); - const findLink = () => wrapper.findComponent(GlLink); - const findIntroText = () => wrapper.find({ ref: 'introText' }).text(); + const findBase = () => wrapper.findComponent(InviteModalBase); + const findIntroText = () => wrapper.findByTestId('modal-base-intro-text').text(); const findCancelButton = () => wrapper.findByTestId('cancel-button'); const findInviteButton = () => wrapper.findByTestId('invite-button'); const clickInviteButton = () => findInviteButton().vm.$emit('click'); const clickCancelButton = () => findCancelButton().vm.$emit('click'); const findMembersFormGroup = () => wrapper.findByTestId('members-form-group'); - const membersFormGroupInvalidFeedback = () => findMembersFormGroup().props('invalidFeedback'); - const membersFormGroupDescription = () => findMembersFormGroup().props('description'); + const membersFormGroupInvalidFeedback = () => + findMembersFormGroup().attributes('invalid-feedback'); + const membersFormGroupDescription = () => findMembersFormGroup().attributes('description'); const findMembersSelect = () => wrapper.findComponent(MembersTokenSelect); const findTasksToBeDone = () => wrapper.findByTestId('invite-members-modal-tasks-to-be-done'); const findTasks = () => wrapper.findByTestId('invite-members-modal-tasks'); const findProjectSelect = () => wrapper.findByTestId('invite-members-modal-project-select'); const findNoProjectsAlert = () => wrapper.findByTestId('invite-members-modal-no-projects-alert'); - const findCelebrationEmoji = () => wrapper.findComponent(GlModal).find(GlEmoji); - - describe('rendering the modal', () => { - beforeEach(() => { - createComponent(); - }); - - it('renders the modal with the correct title', () => { - expect(wrapper.findComponent(GlModal).props('title')).toBe(MEMBERS_MODAL_DEFAULT_TITLE); - }); - - it('renders the Cancel button text correctly', () => { - expect(findCancelButton().text()).toBe(CANCEL_BUTTON_TEXT); - }); - - it('renders the Invite button text correctly', () => { - expect(findInviteButton().text()).toBe(INVITE_BUTTON_TEXT); - }); - - it('renders the Invite button modal without isLoading', () => { - expect(findInviteButton().props('loading')).toBe(false); - }); - - describe('rendering the access levels dropdown', () => { - it('sets the default dropdown text to the default access level name', () => { - expect(findDropdown().attributes('text')).toBe('Guest'); - }); - - it('renders dropdown items for each accessLevel', () => { - expect(findDropdownItems()).toHaveLength(5); - }); - }); - - describe('rendering the help link', () => { - it('renders the correct link', () => { - expect(findLink().attributes('href')).toBe(helpLink); - }); - }); - - describe('rendering the access expiration date field', () => { - it('renders the datepicker', () => { - expect(findDatepicker().exists()).toBe(true); - }); - }); - }); + const findCelebrationEmoji = () => wrapper.findComponent(GlEmoji); + const triggerOpenModal = async ({ mode = 'default', source }) => { + eventHub.$emit('openModal', { mode, source }); + await nextTick(); + }; + const triggerMembersTokenSelect = async (val) => { + findMembersSelect().vm.$emit('input', val); + await nextTick(); + }; + const triggerTasks = async (val) => { + findTasks().vm.$emit('input', val); + await nextTick(); + }; + const triggerAccessLevel = async (val) => { + findBase().vm.$emit('access-level', val); + await nextTick(); + }; describe('rendering the tasks to be done', () => { - const setupComponent = ( - extraData = {}, - props = {}, - urlParameter = ['invite_members_for_task'], - ) => { - const data = { - selectedAccessLevel: 30, - selectedTasksToBeDone: ['ci', 'code'], - ...extraData, - }; + const setupComponent = async (props = {}, urlParameter = ['invite_members_for_task']) => { getParameterValues.mockImplementation(() => urlParameter); - createComponent(data, props); + createComponent(props); + + await triggerAccessLevel(30); + }; + + const setupComponentWithTasks = async (...args) => { + await setupComponent(...args); + await triggerTasks(['ci', 'code']); }; afterAll(() => { getParameterValues.mockImplementation(() => []); }); - it('renders the tasks to be done', () => { - setupComponent(); + it('renders the tasks to be done', async () => { + await setupComponent(); expect(findTasksToBeDone().exists()).toBe(true); }); describe('when the selected access level is lower than 30', () => { - it('does not render the tasks to be done', () => { - setupComponent({ selectedAccessLevel: 20 }); + it('does not render the tasks to be done', async () => { + await setupComponent(); + await triggerAccessLevel(20); expect(findTasksToBeDone().exists()).toBe(false); }); }); describe('when the url does not contain the parameter `open_modal=invite_members_for_task`', () => { - it('does not render the tasks to be done', () => { - setupComponent({}, {}, []); + it('does not render the tasks to be done', async () => { + await setupComponent({}, []); expect(findTasksToBeDone().exists()).toBe(false); }); describe('when opened from the Learn GitLab page', () => { - it('does render the tasks to be done', () => { - setupComponent({ source: LEARN_GITLAB }, {}, []); + it('does render the tasks to be done', async () => { + await setupComponent({}, []); + await triggerOpenModal({ source: LEARN_GITLAB }); expect(findTasksToBeDone().exists()).toBe(true); }); @@ -254,27 +166,27 @@ describe('InviteMembersModal', () => { }); describe('rendering the tasks', () => { - it('renders the tasks', () => { - setupComponent(); + it('renders the tasks', async () => { + await setupComponent(); expect(findTasks().exists()).toBe(true); }); - it('does not render an alert', () => { - setupComponent(); + it('does not render an alert', async () => { + await setupComponent(); expect(findNoProjectsAlert().exists()).toBe(false); }); describe('when there are no projects passed in the data', () => { - it('does not render the tasks', () => { - setupComponent({}, { projects: [] }); + it('does not render the tasks', async () => { + await setupComponent({ projects: [] }); expect(findTasks().exists()).toBe(false); }); - it('renders an alert with a link to the new projects path', () => { - setupComponent({}, { projects: [] }); + it('renders an alert with a link to the new projects path', async () => { + await setupComponent({ projects: [] }); expect(findNoProjectsAlert().exists()).toBe(true); expect(findNoProjectsAlert().findComponent(GlLink).attributes('href')).toBe( @@ -285,23 +197,23 @@ describe('InviteMembersModal', () => { }); describe('rendering the project dropdown', () => { - it('renders the project select', () => { - setupComponent(); + it('renders the project select', async () => { + await setupComponentWithTasks(); expect(findProjectSelect().exists()).toBe(true); }); describe('when the modal is shown for a project', () => { - it('does not render the project select', () => { - setupComponent({}, { isProject: true }); + it('does not render the project select', async () => { + await setupComponentWithTasks({ isProject: true }); expect(findProjectSelect().exists()).toBe(false); }); }); describe('when no tasks are selected', () => { - it('does not render the project select', () => { - setupComponent({ selectedTasksToBeDone: [] }); + it('does not render the project select', async () => { + await setupComponent(); expect(findProjectSelect().exists()).toBe(false); }); @@ -309,8 +221,8 @@ describe('InviteMembersModal', () => { }); describe('tracking events', () => { - it('tracks the view for invite_members_for_task', () => { - setupComponent(); + it('tracks the view for invite_members_for_task', async () => { + await setupComponentWithTasks(); expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name); expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith( @@ -318,8 +230,8 @@ describe('InviteMembersModal', () => { ); }); - it('tracks the submit for invite_members_for_task', () => { - setupComponent(); + it('tracks the submit for invite_members_for_task', async () => { + await setupComponentWithTasks(); clickInviteButton(); expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name, { @@ -352,8 +264,9 @@ describe('InviteMembersModal', () => { }); describe('when inviting members with celebration', () => { - beforeEach(() => { - createComponent({ mode: 'celebrate', inviteeType: 'members' }, { isProject: true }); + beforeEach(async () => { + createComponent({ isProject: true }); + await triggerOpenModal({ mode: 'celebrate' }); }); it('renders the modal with confetti', () => { @@ -372,34 +285,14 @@ describe('InviteMembersModal', () => { expect(membersFormGroupDescription()).toBe(MEMBERS_PLACEHOLDER); }); }); - - describe('when sharing with a group', () => { - it('includes the correct invitee, type, and formatted name', () => { - createInviteGroupToProjectWrapper(); - - expect(findIntroText()).toBe("You're inviting a group to the test name project."); - expect(membersFormGroupDescription()).toBe(''); - }); - }); }); describe('when inviting to a group', () => { - describe('when inviting members', () => { - it('includes the correct invitee, type, and formatted name', () => { - createInviteMembersToGroupWrapper(); - - expect(findIntroText()).toBe("You're inviting members to the test name group."); - expect(membersFormGroupDescription()).toBe(MEMBERS_PLACEHOLDER); - }); - }); - - describe('when sharing with a group', () => { - it('includes the correct invitee, type, and formatted name', () => { - createInviteGroupToGroupWrapper(); + it('includes the correct invitee, type, and formatted name', () => { + createInviteMembersToGroupWrapper(); - expect(findIntroText()).toBe("You're inviting a group to the test name group."); - expect(membersFormGroupDescription()).toBe(''); - }); + expect(findIntroText()).toBe("You're inviting members to the test name group."); + expect(membersFormGroupDescription()).toBe(MEMBERS_PLACEHOLDER); }); }); }); @@ -419,7 +312,7 @@ describe('InviteMembersModal', () => { describe('when inviting an existing user to group by user ID', () => { const postData = { user_id: '1,2', - access_level: defaultAccessLevel, + access_level: propsData.defaultAccessLevel, expires_at: undefined, invite_source: inviteSource, format: 'json', @@ -428,8 +321,9 @@ describe('InviteMembersModal', () => { }; describe('when member is added successfully', () => { - beforeEach(() => { - createComponent({ newUsersToInvite: [user1, user2] }); + beforeEach(async () => { + createComponent(); + await triggerMembersTokenSelect([user1, user2]); wrapper.vm.$toast = { show: jest.fn() }; jest.spyOn(Api, 'addGroupMembersByUserId').mockResolvedValue({ data: postData }); @@ -445,19 +339,17 @@ describe('InviteMembersModal', () => { }); it('calls Api addGroupMembersByUserId with the correct params', () => { - expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, postData); + expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(propsData.id, postData); }); it('displays the successful toastMessage', () => { - expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', { - onComplete: expect.any(Function), - }); + expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added'); }); }); describe('when opened from a Learn GitLab page', () => { it('emits the `showSuccessfulInvitationsAlert` event', async () => { - eventHub.$emit('openModal', { inviteeType: 'members', source: LEARN_GITLAB }); + await triggerOpenModal({ source: LEARN_GITLAB }); jest.spyOn(eventHub, '$emit').mockImplementation(); @@ -471,12 +363,10 @@ describe('InviteMembersModal', () => { }); describe('when member is not added successfully', () => { - beforeEach(() => { + beforeEach(async () => { createInviteMembersToGroupWrapper(); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ newUsersToInvite: [user1] }); + await triggerMembersTokenSelect([user1]); }); it('displays "Member already exists" api message for http status conflict', async () => { @@ -487,7 +377,6 @@ describe('InviteMembersModal', () => { await waitForPromises(); expect(membersFormGroupInvalidFeedback()).toBe('Member already exists'); - expect(findMembersFormGroup().props('state')).toBe(false); expect(findMembersSelect().props('validationState')).toBe(false); expect(findInviteButton().props('loading')).toBe(false); }); @@ -503,35 +392,31 @@ describe('InviteMembersModal', () => { it('clears the error when the list of members to invite is cleared', async () => { expect(membersFormGroupInvalidFeedback()).toBe('Member already exists'); - expect(findMembersFormGroup().props('state')).toBe(false); expect(findMembersSelect().props('validationState')).toBe(false); findMembersSelect().vm.$emit('clear'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(membersFormGroupInvalidFeedback()).toBe(''); - expect(findMembersFormGroup().props('state')).not.toBe(false); expect(findMembersSelect().props('validationState')).not.toBe(false); }); it('clears the error when the cancel button is clicked', async () => { clickCancelButton(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(membersFormGroupInvalidFeedback()).toBe(''); - expect(findMembersFormGroup().props('state')).not.toBe(false); expect(findMembersSelect().props('validationState')).not.toBe(false); }); it('clears the error when the modal is hidden', async () => { wrapper.findComponent(GlModal).vm.$emit('hide'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(membersFormGroupInvalidFeedback()).toBe(''); - expect(findMembersFormGroup().props('state')).not.toBe(false); expect(findMembersSelect().props('validationState')).not.toBe(false); }); }); @@ -544,7 +429,6 @@ describe('InviteMembersModal', () => { await waitForPromises(); expect(membersFormGroupInvalidFeedback()).toBe('Member already exists'); - expect(findMembersFormGroup().props('state')).toBe(false); expect(findMembersSelect().props('validationState')).toBe(false); expect(findInviteButton().props('loading')).toBe(false); @@ -553,8 +437,7 @@ describe('InviteMembersModal', () => { await waitForPromises(); expect(membersFormGroupInvalidFeedback()).toBe(''); - expect(findMembersFormGroup().props('state')).not.toBe(false); - expect(findMembersSelect().props('validationState')).not.toBe(false); + expect(findMembersSelect().props('validationState')).toBe(null); expect(findInviteButton().props('loading')).toBe(false); }); @@ -608,7 +491,7 @@ describe('InviteMembersModal', () => { describe('when inviting a new user by email address', () => { const postData = { - access_level: defaultAccessLevel, + access_level: propsData.defaultAccessLevel, expires_at: undefined, email: 'email@example.com', invite_source: inviteSource, @@ -618,8 +501,9 @@ describe('InviteMembersModal', () => { }; describe('when invites are sent successfully', () => { - beforeEach(() => { - createComponent({ newUsersToInvite: [user3] }); + beforeEach(async () => { + createComponent(); + await triggerMembersTokenSelect([user3]); wrapper.vm.$toast = { show: jest.fn() }; jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData }); @@ -631,24 +515,20 @@ describe('InviteMembersModal', () => { }); it('calls Api inviteGroupMembersByEmail with the correct params', () => { - expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, postData); + expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(propsData.id, postData); }); it('displays the successful toastMessage', () => { - expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', { - onComplete: expect.any(Function), - }); + expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added'); }); }); }); describe('when invites are not sent successfully', () => { - beforeEach(() => { + beforeEach(async () => { createInviteMembersToGroupWrapper(); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ newUsersToInvite: [user3] }); + await triggerMembersTokenSelect([user3]); }); it('displays the api error for invalid email syntax', async () => { @@ -683,9 +563,7 @@ describe('InviteMembersModal', () => { await waitForPromises(); - expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', { - onComplete: expect.any(Function), - }); + expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added'); expect(findMembersSelect().props('validationState')).toBe(null); }); @@ -716,9 +594,7 @@ describe('InviteMembersModal', () => { it('displays the invalid syntax error if one of the emails is invalid', async () => { createInviteMembersToGroupWrapper(); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ newUsersToInvite: [user3, user4] }); + await triggerMembersTokenSelect([user3, user4]); mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.ERROR_EMAIL_INVALID); clickInviteButton(); @@ -733,7 +609,7 @@ describe('InviteMembersModal', () => { describe('when inviting members and non-members in same click', () => { const postData = { - access_level: defaultAccessLevel, + access_level: propsData.defaultAccessLevel, expires_at: undefined, invite_source: inviteSource, format: 'json', @@ -745,8 +621,9 @@ describe('InviteMembersModal', () => { const idPostData = { ...postData, user_id: '1' }; describe('when invites are sent successfully', () => { - beforeEach(() => { - createComponent({ newUsersToInvite: [user1, user3] }); + beforeEach(async () => { + createComponent(); + await triggerMembersTokenSelect([user1, user3]); wrapper.vm.$toast = { show: jest.fn() }; jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData }); @@ -759,30 +636,28 @@ describe('InviteMembersModal', () => { }); it('calls Api inviteGroupMembersByEmail with the correct params', () => { - expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, emailPostData); + expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(propsData.id, emailPostData); }); it('calls Api addGroupMembersByUserId with the correct params', () => { - expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, idPostData); + expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(propsData.id, idPostData); }); it('displays the successful toastMessage', () => { - expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', { - onComplete: expect.any(Function), - }); + expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added'); }); }); - it('calls Apis with the invite source passed through to openModal', () => { - eventHub.$emit('openModal', { inviteeType: 'members', source: '_invite_source_' }); + it('calls Apis with the invite source passed through to openModal', async () => { + await triggerOpenModal({ source: '_invite_source_' }); clickInviteButton(); - expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, { + expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(propsData.id, { ...emailPostData, invite_source: '_invite_source_', }); - expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, { + expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(propsData.id, { ...idPostData, invite_source: '_invite_source_', }); @@ -790,12 +665,10 @@ describe('InviteMembersModal', () => { }); describe('when any invite failed for any reason', () => { - beforeEach(() => { + beforeEach(async () => { createInviteMembersToGroupWrapper(); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ newUsersToInvite: [user1, user3] }); + await triggerMembersTokenSelect([user1, user3]); mockInvitationsApi(httpStatus.BAD_REQUEST, invitationsApiResponse.EMAIL_INVALID); mockMembersApi(httpStatus.OK, '200 OK'); @@ -811,71 +684,17 @@ describe('InviteMembersModal', () => { }); }); - describe('when inviting a group to share', () => { - describe('when sharing the group is successful', () => { - const groupPostData = { - group_id: sharedGroup.id, - group_access: defaultAccessLevel, - expires_at: undefined, - format: 'json', - }; - - beforeEach(() => { - createComponent({ groupToBeSharedWith: sharedGroup }); - - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ inviteeType: 'group' }); - wrapper.vm.$toast = { show: jest.fn() }; - jest.spyOn(Api, 'groupShareWithGroup').mockResolvedValue({ data: groupPostData }); - - clickInviteButton(); - }); - - it('calls Api groupShareWithGroup with the correct params', () => { - expect(Api.groupShareWithGroup).toHaveBeenCalledWith(id, groupPostData); - }); - - it('displays the successful toastMessage', () => { - expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', { - onComplete: expect.any(Function), - }); - }); - }); - - describe('when sharing the group fails', () => { - beforeEach(() => { - createInviteGroupToGroupWrapper(); - - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ groupToBeSharedWith: sharedGroup }); - wrapper.vm.$toast = { show: jest.fn() }; - - jest - .spyOn(Api, 'groupShareWithGroup') - .mockRejectedValue({ response: { data: { success: false } } }); - - clickInviteButton(); - }); - - it('displays the generic error message', () => { - expect(membersFormGroupInvalidFeedback()).toBe('Something went wrong'); - expect(membersFormGroupDescription()).toBe(''); - }); - }); - }); - describe('tracking', () => { - beforeEach(() => { - createComponent({ newUsersToInvite: [user3] }); + beforeEach(async () => { + createComponent(); + await triggerMembersTokenSelect([user3]); wrapper.vm.$toast = { show: jest.fn() }; jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({}); }); it('tracks the view for learn_gitlab source', () => { - eventHub.$emit('openModal', { inviteeType: 'members', source: LEARN_GITLAB }); + eventHub.$emit('openModal', { source: LEARN_GITLAB }); expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name); expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(LEARN_GITLAB); |