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/components/invite_members_modal_spec.js')
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js210
1 files changed, 202 insertions, 8 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 8c3c549a5eb..5be79004640 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -15,17 +15,34 @@ 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 ModalConfetti from '~/invite_members/components/confetti.vue';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
-import { INVITE_MEMBERS_IN_COMMENT, MEMBER_AREAS_OF_FOCUS } from '~/invite_members/constants';
+import {
+ INVITE_MEMBERS_IN_COMMENT,
+ MEMBER_AREAS_OF_FOCUS,
+ 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,
+} from '~/invite_members/constants';
import eventHub from '~/invite_members/event_hub';
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;
jest.mock('~/experimentation/experiment_tracking');
+jest.mock('~/lib/utils/url_utility', () => ({
+ ...jest.requireActual('~/lib/utils/url_utility'),
+ getParameterValues: jest.fn(() => []),
+}));
const id = '1';
const name = 'test name';
@@ -40,6 +57,15 @@ const areasOfFocusOptions = [
{ text: 'area1', value: 'area1' },
{ text: 'area2', value: 'area2' },
];
+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: '' };
@@ -56,9 +82,13 @@ const user4 = {
avatar_url: '',
};
const sharedGroup = { id: '981' };
+const GlEmoji = { template: '<img/>' };
const createComponent = (data = {}, props = {}) => {
wrapper = shallowMountExtended(InviteMembersModal, {
+ provide: {
+ newProjectPath,
+ },
propsData: {
id,
name,
@@ -68,6 +98,8 @@ const createComponent = (data = {}, props = {}) => {
areasOfFocusOptions,
defaultAccessLevel,
noSelectionAreasOfFocus,
+ tasksToBeDoneOptions,
+ projects,
helpLink,
...props,
},
@@ -81,6 +113,7 @@ const createComponent = (data = {}, props = {}) => {
}),
GlDropdown: true,
GlDropdownItem: true,
+ GlEmoji,
GlSprintf,
GlFormGroup: stubComponent(GlFormGroup, {
props: ['state', 'invalidFeedback', 'description'],
@@ -131,6 +164,11 @@ describe('InviteMembersModal', () => {
const membersFormGroupDescription = () => findMembersFormGroup().props('description');
const findMembersSelect = () => wrapper.findComponent(MembersTokenSelect);
const findAreaofFocusCheckBoxGroup = () => wrapper.findComponent(GlFormCheckboxGroup);
+ 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(() => {
@@ -138,15 +176,15 @@ describe('InviteMembersModal', () => {
});
it('renders the modal with the correct title', () => {
- expect(wrapper.findComponent(GlModal).props('title')).toBe('Invite members');
+ expect(wrapper.findComponent(GlModal).props('title')).toBe(MEMBERS_MODAL_DEFAULT_TITLE);
});
it('renders the Cancel button text correctly', () => {
- expect(findCancelButton().text()).toBe('Cancel');
+ expect(findCancelButton().text()).toBe(CANCEL_BUTTON_TEXT);
});
it('renders the Invite button text correctly', () => {
- expect(findInviteButton().text()).toBe('Invite');
+ expect(findInviteButton().text()).toBe(INVITE_BUTTON_TEXT);
});
it('renders the Invite button modal without isLoading', () => {
@@ -171,7 +209,7 @@ describe('InviteMembersModal', () => {
describe('rendering the access expiration date field', () => {
it('renders the datepicker', () => {
- expect(findDatepicker()).toExist();
+ expect(findDatepicker().exists()).toBe(true);
});
});
});
@@ -191,14 +229,164 @@ describe('InviteMembersModal', () => {
});
});
+ describe('rendering the tasks to be done', () => {
+ const setupComponent = (
+ extraData = {},
+ props = {},
+ urlParameter = ['invite_members_for_task'],
+ ) => {
+ const data = {
+ selectedAccessLevel: 30,
+ selectedTasksToBeDone: ['ci', 'code'],
+ ...extraData,
+ };
+ getParameterValues.mockImplementation(() => urlParameter);
+ createComponent(data, props);
+ };
+
+ afterAll(() => {
+ getParameterValues.mockImplementation(() => []);
+ });
+
+ it('renders the tasks to be done', () => {
+ 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 });
+
+ 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({}, {}, []);
+
+ expect(findTasksToBeDone().exists()).toBe(false);
+ });
+ });
+
+ describe('rendering the tasks', () => {
+ it('renders the tasks', () => {
+ setupComponent();
+
+ expect(findTasks().exists()).toBe(true);
+ });
+
+ it('does not render an alert', () => {
+ setupComponent();
+
+ expect(findNoProjectsAlert().exists()).toBe(false);
+ });
+
+ describe('when there are no projects passed in the data', () => {
+ it('does not render the tasks', () => {
+ setupComponent({}, { projects: [] });
+
+ expect(findTasks().exists()).toBe(false);
+ });
+
+ it('renders an alert with a link to the new projects path', () => {
+ setupComponent({}, { projects: [] });
+
+ expect(findNoProjectsAlert().exists()).toBe(true);
+ expect(findNoProjectsAlert().findComponent(GlLink).attributes('href')).toBe(
+ newProjectPath,
+ );
+ });
+ });
+ });
+
+ describe('rendering the project dropdown', () => {
+ it('renders the project select', () => {
+ setupComponent();
+
+ expect(findProjectSelect().exists()).toBe(true);
+ });
+
+ describe('when the modal is shown for a project', () => {
+ it('does not render the project select', () => {
+ setupComponent({}, { isProject: true });
+
+ expect(findProjectSelect().exists()).toBe(false);
+ });
+ });
+
+ describe('when no tasks are selected', () => {
+ it('does not render the project select', () => {
+ setupComponent({ selectedTasksToBeDone: [] });
+
+ expect(findProjectSelect().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('tracking events', () => {
+ it('tracks the view for invite_members_for_task', () => {
+ setupComponent();
+
+ expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name);
+ expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(
+ INVITE_MEMBERS_FOR_TASK.view,
+ );
+ });
+
+ it('tracks the submit for invite_members_for_task', () => {
+ setupComponent();
+ clickInviteButton();
+
+ expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name, {
+ label: 'selected_tasks_to_be_done',
+ property: 'ci,code',
+ });
+ expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(
+ INVITE_MEMBERS_FOR_TASK.submit,
+ );
+ });
+ });
+ });
+
describe('displaying the correct introText and form group description', () => {
describe('when inviting to a project', () => {
describe('when inviting members', () => {
- it('includes the correct invitee, type, and formatted name', () => {
+ beforeEach(() => {
createInviteMembersToProjectWrapper();
+ });
+ it('renders the modal without confetti', () => {
+ expect(wrapper.findComponent(ModalConfetti).exists()).toBe(false);
+ });
+
+ it('includes the correct invitee, type, and formatted name', () => {
expect(findIntroText()).toBe("You're inviting members to the test name project.");
- expect(membersFormGroupDescription()).toBe('Select members or type email addresses');
+ expect(findCelebrationEmoji().exists()).toBe(false);
+ expect(membersFormGroupDescription()).toBe(MEMBERS_PLACEHOLDER);
+ });
+ });
+
+ describe('when inviting members with celebration', () => {
+ beforeEach(() => {
+ createComponent({ mode: 'celebrate', inviteeType: 'members' }, { isProject: true });
+ });
+
+ it('renders the modal with confetti', () => {
+ expect(wrapper.findComponent(ModalConfetti).exists()).toBe(true);
+ });
+
+ it('renders the modal with the correct title', () => {
+ expect(wrapper.findComponent(GlModal).props('title')).toBe(MEMBERS_MODAL_CELEBRATE_TITLE);
+ });
+
+ it('includes the correct celebration text and emoji', () => {
+ expect(findIntroText()).toBe(
+ `${MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT} ${MEMBERS_MODAL_CELEBRATE_INTRO}`,
+ );
+ expect(findCelebrationEmoji().exists()).toBe(true);
+ expect(membersFormGroupDescription()).toBe(MEMBERS_PLACEHOLDER);
});
});
@@ -218,7 +406,7 @@ describe('InviteMembersModal', () => {
createInviteMembersToGroupWrapper();
expect(findIntroText()).toBe("You're inviting members to the test name group.");
- expect(membersFormGroupDescription()).toBe('Select members or type email addresses');
+ expect(membersFormGroupDescription()).toBe(MEMBERS_PLACEHOLDER);
});
});
@@ -267,6 +455,8 @@ describe('InviteMembersModal', () => {
invite_source: inviteSource,
format: 'json',
areas_of_focus: noSelectionAreasOfFocus,
+ tasks_to_be_done: [],
+ tasks_project_id: '',
};
describe('when member is added successfully', () => {
@@ -448,6 +638,8 @@ describe('InviteMembersModal', () => {
email: 'email@example.com',
invite_source: inviteSource,
areas_of_focus: noSelectionAreasOfFocus,
+ tasks_to_be_done: [],
+ tasks_project_id: '',
format: 'json',
};
@@ -576,6 +768,8 @@ describe('InviteMembersModal', () => {
invite_source: inviteSource,
areas_of_focus: noSelectionAreasOfFocus,
format: 'json',
+ tasks_to_be_done: [],
+ tasks_project_id: '',
};
const emailPostData = { ...postData, email: 'email@example.com' };