diff options
Diffstat (limited to 'spec/frontend/invite_members')
7 files changed, 333 insertions, 41 deletions
diff --git a/spec/frontend/invite_members/components/import_project_members_modal_spec.js b/spec/frontend/invite_members/components/import_project_members_modal_spec.js index 8b2d13be309..d839cde163c 100644 --- a/spec/frontend/invite_members/components/import_project_members_modal_spec.js +++ b/spec/frontend/invite_members/components/import_project_members_modal_spec.js @@ -8,6 +8,12 @@ import * as ProjectsApi from '~/api/projects_api'; import ImportProjectMembersModal from '~/invite_members/components/import_project_members_modal.vue'; import ProjectSelect from '~/invite_members/components/project_select.vue'; import axios from '~/lib/utils/axios_utils'; +import { + displaySuccessfulInvitationAlert, + reloadOnInvitationSuccess, +} from '~/invite_members/utils/trigger_successful_invite_alert'; + +jest.mock('~/invite_members/utils/trigger_successful_invite_alert'); let wrapper; let mock; @@ -19,11 +25,12 @@ const $toast = { show: jest.fn(), }; -const createComponent = () => { +const createComponent = ({ props = {} } = {}) => { wrapper = shallowMountExtended(ImportProjectMembersModal, { propsData: { projectId, projectName, + ...props, }, stubs: { GlModal: stubComponent(GlModal, { @@ -101,6 +108,35 @@ describe('ImportProjectMembersModal', () => { }); describe('submitting the import', () => { + describe('when the import is successful with reloadPageOnSubmit', () => { + beforeEach(() => { + createComponent({ + props: { reloadPageOnSubmit: true }, + }); + + findProjectSelect().vm.$emit('input', projectToBeImported); + + jest.spyOn(ProjectsApi, 'importProjectMembers').mockResolvedValue(); + + clickImportButton(); + }); + + it('calls displaySuccessfulInvitationAlert on mount', () => { + expect(displaySuccessfulInvitationAlert).toHaveBeenCalled(); + }); + + it('calls reloadOnInvitationSuccess', () => { + expect(reloadOnInvitationSuccess).toHaveBeenCalled(); + }); + + it('does not display the successful toastMessage', () => { + expect($toast.show).not.toHaveBeenCalledWith( + 'Successfully imported', + wrapper.vm.$options.toastOptions, + ); + }); + }); + describe('when the import is successful', () => { beforeEach(() => { createComponent(); @@ -126,6 +162,14 @@ describe('ImportProjectMembersModal', () => { ); }); + it('does not call displaySuccessfulInvitationAlert on mount', () => { + expect(displaySuccessfulInvitationAlert).not.toHaveBeenCalled(); + }); + + it('does not call reloadOnInvitationSuccess', () => { + expect(reloadOnInvitationSuccess).not.toHaveBeenCalled(); + }); + it('sets isLoading to false after success', () => { expect(findGlModal().props('actionPrimary').attributes.loading).toBe(false); }); diff --git a/spec/frontend/invite_members/components/invite_group_notification_spec.js b/spec/frontend/invite_members/components/invite_group_notification_spec.js new file mode 100644 index 00000000000..3e6ba6da9f4 --- /dev/null +++ b/spec/frontend/invite_members/components/invite_group_notification_spec.js @@ -0,0 +1,42 @@ +import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import { sprintf } from '~/locale'; +import InviteGroupNotification from '~/invite_members/components/invite_group_notification.vue'; +import { GROUP_MODAL_ALERT_BODY } from '~/invite_members/constants'; + +describe('InviteGroupNotification', () => { + let wrapper; + + const findAlert = () => wrapper.findComponent(GlAlert); + const findLink = () => wrapper.findComponent(GlLink); + + const createComponent = () => { + wrapper = shallowMountExtended(InviteGroupNotification, { + provide: { freeUsersLimit: 5 }, + propsData: { name: 'name' }, + stubs: { GlSprintf }, + }); + }; + + describe('when rendering', () => { + beforeEach(() => { + createComponent(); + }); + + it('passes the correct props', () => { + expect(findAlert().props()).toMatchObject({ variant: 'warning', dismissible: false }); + }); + + it('shows the correct message', () => { + const message = sprintf(GROUP_MODAL_ALERT_BODY, { count: 5 }); + + expect(findAlert().text()).toMatchInterpolatedText(message); + }); + + it('has a help link', () => { + expect(findLink().attributes('href')).toEqual( + 'https://docs.gitlab.com/ee/user/group/manage.html#share-a-group-with-another-group', + ); + }); + }); +}); diff --git a/spec/frontend/invite_members/components/invite_groups_modal_spec.js b/spec/frontend/invite_members/components/invite_groups_modal_spec.js index f9cb4a149f2..c2a55517405 100644 --- a/spec/frontend/invite_members/components/invite_groups_modal_spec.js +++ b/spec/frontend/invite_members/components/invite_groups_modal_spec.js @@ -6,9 +6,16 @@ import InviteGroupsModal from '~/invite_members/components/invite_groups_modal.v import InviteModalBase from '~/invite_members/components/invite_modal_base.vue'; import ContentTransition from '~/vue_shared/components/content_transition.vue'; import GroupSelect from '~/invite_members/components/group_select.vue'; +import InviteGroupNotification from '~/invite_members/components/invite_group_notification.vue'; import { stubComponent } from 'helpers/stub_component'; +import { + displaySuccessfulInvitationAlert, + reloadOnInvitationSuccess, +} from '~/invite_members/utils/trigger_successful_invite_alert'; import { propsData, sharedGroup } from '../mock_data/group_modal'; +jest.mock('~/invite_members/utils/trigger_successful_invite_alert'); + describe('InviteGroupsModal', () => { let wrapper; @@ -44,6 +51,7 @@ describe('InviteGroupsModal', () => { const findModal = () => wrapper.findComponent(GlModal); const findGroupSelect = () => wrapper.findComponent(GroupSelect); + const findInviteGroupAlert = () => wrapper.findComponent(InviteGroupNotification); const findIntroText = () => wrapper.findByTestId('modal-base-intro-text').text(); const findMembersFormGroup = () => wrapper.findByTestId('members-form-group'); const membersFormGroupInvalidFeedback = () => @@ -74,6 +82,20 @@ describe('InviteGroupsModal', () => { }); }); + describe('rendering the invite group notification', () => { + it('shows the user limit notification alert when free user cap is enabled', () => { + createComponent({ freeUserCapEnabled: true }); + + expect(findInviteGroupAlert().exists()).toBe(true); + }); + + it('does not show the user limit notification alert', () => { + createComponent(); + + expect(findInviteGroupAlert().exists()).toBe(false); + }); + }); + describe('submitting the invite form', () => { let apiResolve; let apiReject; @@ -126,6 +148,14 @@ describe('InviteGroupsModal', () => { onComplete: expect.any(Function), }); }); + + it('does not call displaySuccessfulInvitationAlert on mount', () => { + expect(displaySuccessfulInvitationAlert).not.toHaveBeenCalled(); + }); + + it('does not call reloadOnInvitationSuccess', () => { + expect(reloadOnInvitationSuccess).not.toHaveBeenCalled(); + }); }); describe('when fails', () => { @@ -156,4 +186,37 @@ describe('InviteGroupsModal', () => { }); }); }); + + describe('submitting the invite form with reloadPageOnSubmit set true', () => { + const groupPostData = { + group_id: sharedGroup.id, + group_access: propsData.defaultAccessLevel, + expires_at: undefined, + format: 'json', + }; + + beforeEach(() => { + createComponent({ reloadPageOnSubmit: true }); + triggerGroupSelect(sharedGroup); + + wrapper.vm.$toast = { show: jest.fn() }; + jest.spyOn(Api, 'groupShareWithGroup').mockResolvedValue({ data: groupPostData }); + + clickInviteButton(); + }); + + describe('when succeeds', () => { + it('calls displaySuccessfulInvitationAlert on mount', () => { + expect(displaySuccessfulInvitationAlert).toHaveBeenCalled(); + }); + + it('calls reloadOnInvitationSuccess', () => { + expect(reloadOnInvitationSuccess).toHaveBeenCalled(); + }); + + it('does not show the toast message on failure', () => { + expect(wrapper.vm.$toast.show).not.toHaveBeenCalled(); + }); + }); + }); }); 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 47be1933ed7..22fcedb2eaf 100644 --- a/spec/frontend/invite_members/components/invite_members_modal_spec.js +++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js @@ -19,13 +19,17 @@ import { MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT, LEARN_GITLAB, EXPANDED_ERRORS, - EMPTY_INVITES_ERROR_TEXT, + EMPTY_INVITES_ALERT_TEXT, } from '~/invite_members/constants'; import eventHub from '~/invite_members/event_hub'; import ContentTransition from '~/vue_shared/components/content_transition.vue'; import axios from '~/lib/utils/axios_utils'; -import httpStatus from '~/lib/utils/http_status'; +import httpStatus, { HTTP_STATUS_CREATED } from '~/lib/utils/http_status'; import { getParameterValues } from '~/lib/utils/url_utility'; +import { + displaySuccessfulInvitationAlert, + reloadOnInvitationSuccess, +} from '~/invite_members/utils/trigger_successful_invite_alert'; import { GROUPS_INVITATIONS_PATH, invitationsApiResponse } from '../mock_data/api_responses'; import { propsData, @@ -40,6 +44,7 @@ import { GlEmoji, } from '../mock_data/member_modal'; +jest.mock('~/invite_members/utils/trigger_successful_invite_alert'); jest.mock('~/experimentation/experiment_tracking'); jest.mock('~/lib/utils/url_utility', () => ({ ...jest.requireActual('~/lib/utils/url_utility'), @@ -57,6 +62,7 @@ describe('InviteMembersModal', () => { }, propsData: { usersLimitDataset: {}, + fullPath: 'project', ...propsData, ...props, }, @@ -95,6 +101,7 @@ describe('InviteMembersModal', () => { const findModal = () => wrapper.findComponent(GlModal); const findBase = () => wrapper.findComponent(InviteModalBase); const findIntroText = () => wrapper.findByTestId('modal-base-intro-text').text(); + const findEmptyInvitesAlert = () => wrapper.findByTestId('empty-invites-alert'); const findMemberErrorAlert = () => wrapper.findByTestId('alert-member-error'); const findMoreInviteErrorsButton = () => wrapper.findByTestId('accordion-button'); const findUserLimitAlert = () => wrapper.findComponent(UserLimitNotification); @@ -397,7 +404,8 @@ describe('InviteMembersModal', () => { await waitForPromises(); - expect(membersFormGroupInvalidFeedback()).toBe(EMPTY_INVITES_ERROR_TEXT); + expect(findEmptyInvitesAlert().text()).toBe(EMPTY_INVITES_ALERT_TEXT); + expect(membersFormGroupInvalidFeedback()).toBe(MEMBERS_PLACEHOLDER); expect(findMembersSelect().props('exceptionState')).toBe(false); await triggerMembersTokenSelect([user1]); @@ -417,6 +425,29 @@ describe('InviteMembersModal', () => { tasks_project_id: '', }; + describe('when reloadOnSubmit is true', () => { + beforeEach(async () => { + createComponent({ reloadPageOnSubmit: true }); + await triggerMembersTokenSelect([user1, user2]); + + wrapper.vm.$toast = { show: jest.fn() }; + jest.spyOn(Api, 'inviteGroupMembers').mockResolvedValue({ data: postData }); + clickInviteButton(); + }); + + it('calls displaySuccessfulInvitationAlert on mount', () => { + expect(displaySuccessfulInvitationAlert).toHaveBeenCalled(); + }); + + it('calls reloadOnInvitationSuccess', () => { + expect(reloadOnInvitationSuccess).toHaveBeenCalled(); + }); + + it('does not show the toast message', () => { + expect(wrapper.vm.$toast.show).not.toHaveBeenCalled(); + }); + }); + describe('when member is added successfully', () => { beforeEach(async () => { createComponent(); @@ -438,6 +469,14 @@ describe('InviteMembersModal', () => { it('displays the successful toastMessage', () => { expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added'); }); + + it('does not call displaySuccessfulInvitationAlert on mount', () => { + expect(displaySuccessfulInvitationAlert).not.toHaveBeenCalled(); + }); + + it('does not call reloadOnInvitationSuccess', () => { + expect(reloadOnInvitationSuccess).not.toHaveBeenCalled(); + }); }); describe('when opened from a Learn GitLab page', () => { @@ -464,7 +503,7 @@ describe('InviteMembersModal', () => { describe('clearing the invalid state and message', () => { beforeEach(async () => { - mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.EMAIL_TAKEN); + mockInvitationsApi(HTTP_STATUS_CREATED, invitationsApiResponse.EMAIL_TAKEN); clickInviteButton(); @@ -523,7 +562,7 @@ describe('InviteMembersModal', () => { }); it('displays the restricted user api message for response with bad request', async () => { - mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.EMAIL_RESTRICTED); + mockInvitationsApi(HTTP_STATUS_CREATED, invitationsApiResponse.EMAIL_RESTRICTED); clickInviteButton(); @@ -536,7 +575,7 @@ describe('InviteMembersModal', () => { }); it('displays all errors when there are multiple existing users that are restricted by email', async () => { - mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.MULTIPLE_RESTRICTED); + mockInvitationsApi(HTTP_STATUS_CREATED, invitationsApiResponse.MULTIPLE_RESTRICTED); clickInviteButton(); @@ -590,6 +629,14 @@ describe('InviteMembersModal', () => { it('displays the successful toastMessage', () => { expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added'); }); + + it('does not call displaySuccessfulInvitationAlert on mount', () => { + expect(displaySuccessfulInvitationAlert).not.toHaveBeenCalled(); + }); + + it('does not call reloadOnInvitationSuccess', () => { + expect(reloadOnInvitationSuccess).not.toHaveBeenCalled(); + }); }); }); @@ -633,7 +680,7 @@ describe('InviteMembersModal', () => { }); it('displays the restricted email error when restricted email is invited', async () => { - mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.EMAIL_RESTRICTED); + mockInvitationsApi(HTTP_STATUS_CREATED, invitationsApiResponse.EMAIL_RESTRICTED); clickInviteButton(); @@ -647,7 +694,7 @@ describe('InviteMembersModal', () => { }); it('displays all errors when there are multiple emails that return a restricted error message', async () => { - mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.MULTIPLE_RESTRICTED); + mockInvitationsApi(HTTP_STATUS_CREATED, invitationsApiResponse.MULTIPLE_RESTRICTED); clickInviteButton(); @@ -677,6 +724,14 @@ describe('InviteMembersModal', () => { expect(membersFormGroupInvalidFeedback()).toBe(expectedSyntaxError); expect(findMembersSelect().props('exceptionState')).toBe(false); }); + + it('does not call displaySuccessfulInvitationAlert on mount', () => { + expect(displaySuccessfulInvitationAlert).not.toHaveBeenCalled(); + }); + + it('does not call reloadOnInvitationSuccess', () => { + expect(reloadOnInvitationSuccess).not.toHaveBeenCalled(); + }); }); describe('when multiple emails are invited at the same time', () => { @@ -698,7 +753,7 @@ describe('InviteMembersModal', () => { createInviteMembersToGroupWrapper(); await triggerMembersTokenSelect([user3, user4, user5, user6]); - mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.EXPANDED_RESTRICTED); + mockInvitationsApi(HTTP_STATUS_CREATED, invitationsApiResponse.EXPANDED_RESTRICTED); clickInviteButton(); @@ -791,6 +846,14 @@ describe('InviteMembersModal', () => { it('displays the successful toastMessage', () => { expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added'); }); + + it('does not call displaySuccessfulInvitationAlert on mount', () => { + expect(displaySuccessfulInvitationAlert).not.toHaveBeenCalled(); + }); + + it('does not call reloadOnInvitationSuccess', () => { + expect(reloadOnInvitationSuccess).not.toHaveBeenCalled(); + }); }); it('calls Apis with the invite source passed through to openModal', async () => { diff --git a/spec/frontend/invite_members/components/invite_modal_base_spec.js b/spec/frontend/invite_members/components/invite_modal_base_spec.js index aeead8809fd..db2afbbd141 100644 --- a/spec/frontend/invite_members/components/invite_modal_base_spec.js +++ b/spec/frontend/invite_members/components/invite_modal_base_spec.js @@ -1,16 +1,15 @@ import { - GlDropdown, - GlDropdownItem, + GlFormSelect, GlDatepicker, GlFormGroup, - GlSprintf, GlLink, + GlSprintf, GlModal, GlIcon, } from '@gitlab/ui'; import { stubComponent } from 'helpers/stub_component'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; -import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import InviteModalBase from '~/invite_members/components/invite_modal_base.vue'; import ContentTransition from '~/vue_shared/components/content_transition.vue'; @@ -26,24 +25,30 @@ import { propsData, membersPath, purchasePath } from '../mock_data/modal_base'; describe('InviteModalBase', () => { let wrapper; - const createComponent = (props = {}, stubs = {}) => { - wrapper = shallowMountExtended(InviteModalBase, { + const createComponent = ({ props = {}, stubs = {}, mountFn = shallowMountExtended } = {}) => { + const requiredStubs = + mountFn === mountExtended + ? {} + : { + ContentTransition, + GlFormSelect: true, + GlSprintf, + GlFormGroup: stubComponent(GlFormGroup, { + props: ['state', 'invalidFeedback'], + }), + }; + + wrapper = mountFn(InviteModalBase, { propsData: { ...propsData, ...props, }, stubs: { - ContentTransition, GlModal: stubComponent(GlModal, { template: '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-footer"></slot></div>', }), - GlDropdown: true, - GlDropdownItem: true, - GlSprintf, - GlFormGroup: stubComponent(GlFormGroup, { - props: ['state', 'invalidFeedback'], - }), + ...requiredStubs, ...stubs, }, }); @@ -51,11 +56,10 @@ describe('InviteModalBase', () => { afterEach(() => { wrapper.destroy(); - wrapper = null; }); - const findDropdown = () => wrapper.findComponent(GlDropdown); - const findDropdownItems = () => findDropdown().findAllComponents(GlDropdownItem); + const findFormSelect = () => wrapper.findComponent(GlFormSelect); + const findFormSelectOptions = () => findFormSelect().findAllComponents('option'); const findDatepicker = () => wrapper.findComponent(GlDatepicker); const findLink = () => wrapper.findComponent(GlLink); const findIcon = () => wrapper.findComponent(GlIcon); @@ -97,16 +101,29 @@ describe('InviteModalBase', () => { }); describe('rendering the access levels dropdown', () => { + beforeEach(() => { + createComponent({ + mountFn: mountExtended, + }); + }); + it('sets the default dropdown text to the default access level name', () => { - expect(findDropdown().attributes('text')).toBe('Guest'); + expect(findFormSelect().exists()).toBe(true); + expect(findFormSelect().element.value).toBe('10'); }); it('renders dropdown items for each accessLevel', () => { - expect(findDropdownItems()).toHaveLength(5); + expect(findFormSelectOptions()).toHaveLength(5); }); }); describe('rendering the help link', () => { + beforeEach(() => { + createComponent({ + mountFn: mountExtended, + }); + }); + it('renders the correct link', () => { expect(findLink().attributes('href')).toBe(propsData.helpLink); }); @@ -126,7 +143,7 @@ describe('InviteModalBase', () => { }); it('renders description', () => { - createComponent({}, { GlFormGroup }); + createComponent({ stubs: { GlFormGroup } }); expect(findMembersFormGroup().attributes('description')).toContain( propsData.formGroupDescription, @@ -144,13 +161,16 @@ describe('InviteModalBase', () => { beforeEach(() => { createComponent( - { usersLimitDataset: { membersPath, purchasePath, reachedLimit: true } }, - { GlModal, GlFormGroup }, + { props: { usersLimitDataset: { membersPath, purchasePath, reachedLimit: true } } }, + { stubs: { GlModal, GlFormGroup } }, ); }); it('tracks actions', () => { - createComponent({ usersLimitDataset: { reachedLimit: true } }, { GlFormGroup, GlModal }); + createComponent({ + props: { usersLimitDataset: { reachedLimit: true } }, + stubs: { GlFormGroup, GlModal }, + }); trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); const modal = wrapper.findComponent(GlModal); @@ -164,8 +184,8 @@ describe('InviteModalBase', () => { describe('when user limit is close on a personal namespace', () => { beforeEach(() => { - createComponent( - { + createComponent({ + props: { usersLimitDataset: { membersPath, userNamespace: true, @@ -173,8 +193,8 @@ describe('InviteModalBase', () => { reachedLimit: false, }, }, - { GlModal, GlFormGroup }, - ); + stubs: { GlModal, GlFormGroup }, + }); }); it('renders correct buttons', () => { @@ -190,16 +210,16 @@ describe('InviteModalBase', () => { }); describe('when users limit is not reached', () => { - const textRegex = /Select a role.+Read more about role permissions Access expiration date \(optional\)/; + const textRegex = /Select a role\s*Read more about role permissions\s*Access expiration date \(optional\)/; beforeEach(() => { - createComponent({ reachedLimit: false }, { GlModal, GlFormGroup }); + createComponent({ props: { reachedLimit: false }, stubs: { GlModal, GlFormGroup } }); }); it('renders correct blocks', () => { expect(findIcon().exists()).toBe(false); expect(findDisabledInput().exists()).toBe(false); - expect(findDropdown().exists()).toBe(true); + expect(findFormSelect().exists()).toBe(true); expect(findDatepicker().exists()).toBe(true); expect(wrapper.findComponent(GlModal).text()).toMatch(textRegex); }); @@ -213,7 +233,9 @@ describe('InviteModalBase', () => { it('with isLoading, shows loading for invite button', () => { createComponent({ - isLoading: true, + props: { + isLoading: true, + }, }); expect(wrapper.findComponent(GlModal).props('actionPrimary').attributes.loading).toBe(true); @@ -221,7 +243,9 @@ describe('InviteModalBase', () => { it('with invalidFeedbackMessage, set members form group exception state', () => { createComponent({ - invalidFeedbackMessage: 'invalid message!', + props: { + invalidFeedbackMessage: 'invalid message!', + }, }); expect(findMembersFormGroup().props()).toEqual({ diff --git a/spec/frontend/invite_members/mock_data/group_modal.js b/spec/frontend/invite_members/mock_data/group_modal.js index c8588683885..65e8b025dd9 100644 --- a/spec/frontend/invite_members/mock_data/group_modal.js +++ b/spec/frontend/invite_members/mock_data/group_modal.js @@ -7,6 +7,8 @@ export const propsData = { accessLevels: { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 }, defaultAccessLevel: 10, helpLink: 'https://example.com', + fullPath: 'project', + freeUserCapEnabled: false, }; export const sharedGroup = { id: '981' }; diff --git a/spec/frontend/invite_members/utils/trigger_successful_invite_alert_spec.js b/spec/frontend/invite_members/utils/trigger_successful_invite_alert_spec.js new file mode 100644 index 00000000000..38b16dd0c2c --- /dev/null +++ b/spec/frontend/invite_members/utils/trigger_successful_invite_alert_spec.js @@ -0,0 +1,54 @@ +import { + displaySuccessfulInvitationAlert, + reloadOnInvitationSuccess, +} from '~/invite_members/utils/trigger_successful_invite_alert'; +import { + TOAST_MESSAGE_LOCALSTORAGE_KEY, + TOAST_MESSAGE_SUCCESSFUL, +} from '~/invite_members/constants'; +import { createAlert } from '~/flash'; +import { useLocalStorageSpy } from 'helpers/local_storage_helper'; + +jest.mock('~/flash'); +useLocalStorageSpy(); + +describe('Display Successful Invitation Alert', () => { + it('does not show alert if localStorage key not present', () => { + localStorage.removeItem(TOAST_MESSAGE_LOCALSTORAGE_KEY); + + displaySuccessfulInvitationAlert(); + + expect(createAlert).not.toHaveBeenCalled(); + }); + + it('shows alert when localStorage key is present', () => { + localStorage.setItem(TOAST_MESSAGE_LOCALSTORAGE_KEY, 'true'); + + displaySuccessfulInvitationAlert(); + + expect(createAlert).toHaveBeenCalledWith({ + message: TOAST_MESSAGE_SUCCESSFUL, + variant: 'info', + }); + }); +}); + +describe('Reload On Invitation Success', () => { + const { location } = window; + + beforeAll(() => { + delete window.location; + window.location = { reload: jest.fn() }; + }); + + afterAll(() => { + window.location = location; + }); + + it('sets localStorage value and calls window.location.reload', () => { + reloadOnInvitationSuccess(); + + expect(localStorage.setItem).toHaveBeenCalledWith(TOAST_MESSAGE_LOCALSTORAGE_KEY, 'true'); + expect(window.location.reload).toHaveBeenCalled(); + }); +}); |