Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/invite_members')
-rw-r--r--spec/frontend/invite_members/components/import_project_members_modal_spec.js46
-rw-r--r--spec/frontend/invite_members/components/invite_group_notification_spec.js42
-rw-r--r--spec/frontend/invite_members/components/invite_groups_modal_spec.js63
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js81
-rw-r--r--spec/frontend/invite_members/components/invite_modal_base_spec.js86
-rw-r--r--spec/frontend/invite_members/mock_data/group_modal.js2
-rw-r--r--spec/frontend/invite_members/utils/trigger_successful_invite_alert_spec.js54
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();
+ });
+});