summaryrefslogtreecommitdiff
path: root/spec/frontend/invite_members
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 08:27:35 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 08:27:35 +0000
commit7e9c479f7de77702622631cff2628a9c8dcbc627 (patch)
treec8f718a08e110ad7e1894510980d2155a6549197 /spec/frontend/invite_members
parente852b0ae16db4052c1c567d9efa4facc81146e88 (diff)
downloadgitlab-ce-7e9c479f7de77702622631cff2628a9c8dcbc627.tar.gz
Add latest changes from gitlab-org/gitlab@13-6-stable-eev13.6.0-rc42
Diffstat (limited to 'spec/frontend/invite_members')
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js87
-rw-r--r--spec/frontend/invite_members/components/members_token_select_spec.js112
2 files changed, 181 insertions, 18 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 0be0fbbde2d..4ac2a28105c 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -3,24 +3,31 @@ import { GlDropdown, GlDropdownItem, GlDatepicker, GlSprintf, GlLink } from '@gi
import Api from '~/api';
import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue';
-const groupId = '1';
-const groupName = 'testgroup';
+const id = '1';
+const name = 'testgroup';
+const isProject = false;
const accessLevels = { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 };
const defaultAccessLevel = '10';
const helpLink = 'https://example.com';
-const createComponent = () => {
+const createComponent = (data = {}) => {
return shallowMount(InviteMembersModal, {
propsData: {
- groupId,
- groupName,
+ id,
+ name,
+ isProject,
accessLevels,
defaultAccessLevel,
helpLink,
},
+ data() {
+ return data;
+ },
stubs: {
- GlSprintf,
'gl-modal': '<div><slot name="modal-footer"></slot><slot></slot></div>',
+ 'gl-dropdown': true,
+ 'gl-dropdown-item': true,
+ GlSprintf,
},
});
};
@@ -34,7 +41,7 @@ describe('InviteMembersModal', () => {
});
const findDropdown = () => wrapper.find(GlDropdown);
- const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findDropdownItems = () => findDropdown().findAll(GlDropdownItem);
const findDatepicker = () => wrapper.find(GlDatepicker);
const findLink = () => wrapper.find(GlLink);
const findCancelButton = () => wrapper.find({ ref: 'cancelButton' });
@@ -88,25 +95,69 @@ describe('InviteMembersModal', () => {
format: 'json',
};
- beforeEach(() => {
- wrapper = createComponent();
+ describe('when the invite was sent successfully', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest.spyOn(Api, 'inviteGroupMember').mockResolvedValue({ data: postData });
- jest.spyOn(Api, 'inviteGroupMember').mockResolvedValue({ data: postData });
- wrapper.vm.$toast = { show: jest.fn() };
+ wrapper.vm.submitForm(postData);
+ });
- wrapper.vm.submitForm(postData);
+ it('displays the successful toastMessage', () => {
+ const toastMessageSuccessful = 'Members were successfully added';
+
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
+ toastMessageSuccessful,
+ wrapper.vm.toastOptions,
+ );
+ });
+
+ it('calls Api inviteGroupMember with the correct params', () => {
+ expect(Api.inviteGroupMember).toHaveBeenCalledWith(id, postData);
+ });
});
- it('calls Api inviteGroupMember with the correct params', () => {
- expect(Api.inviteGroupMember).toHaveBeenCalledWith(groupId, postData);
+ describe('when sending the invite for a single member returned an api error', () => {
+ const apiErrorMessage = 'Members already exists';
+
+ beforeEach(() => {
+ wrapper = createComponent({ newUsersToInvite: '123' });
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest
+ .spyOn(Api, 'inviteGroupMember')
+ .mockRejectedValue({ response: { data: { message: apiErrorMessage } } });
+
+ findInviteButton().vm.$emit('click');
+ });
+
+ it('displays the api error message for the toastMessage', () => {
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
+ apiErrorMessage,
+ wrapper.vm.toastOptions,
+ );
+ });
});
- describe('when the invite was sent successfully', () => {
- const toastMessageSuccessful = 'Users were succesfully added';
+ describe('when sending the invite for multiple members returned any error', () => {
+ const genericErrorMessage = 'Some of the members could not be added';
- it('displays the successful toastMessage', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ newUsersToInvite: '123' });
+
+ wrapper.vm.$toast = { show: jest.fn() };
+ jest
+ .spyOn(Api, 'inviteGroupMember')
+ .mockRejectedValue({ response: { data: { success: false } } });
+
+ findInviteButton().vm.$emit('click');
+ });
+
+ it('displays the expected toastMessage', () => {
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
- toastMessageSuccessful,
+ genericErrorMessage,
wrapper.vm.toastOptions,
);
});
diff --git a/spec/frontend/invite_members/components/members_token_select_spec.js b/spec/frontend/invite_members/components/members_token_select_spec.js
new file mode 100644
index 00000000000..fb0bd6bb195
--- /dev/null
+++ b/spec/frontend/invite_members/components/members_token_select_spec.js
@@ -0,0 +1,112 @@
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { GlTokenSelector } from '@gitlab/ui';
+import waitForPromises from 'helpers/wait_for_promises';
+import Api from '~/api';
+import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
+
+const label = 'testgroup';
+const placeholder = 'Search for a member';
+const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' };
+const user2 = { id: 2, name: 'Name Two', username: 'two_2', avatar_url: '' };
+const allUsers = [user1, user2];
+
+const createComponent = () => {
+ return shallowMount(MembersTokenSelect, {
+ propsData: {
+ ariaLabelledby: label,
+ placeholder,
+ },
+ });
+};
+
+describe('MembersTokenSelect', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ jest.spyOn(Api, 'users').mockResolvedValue({ data: allUsers });
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findTokenSelector = () => wrapper.find(GlTokenSelector);
+
+ describe('rendering the token-selector component', () => {
+ it('renders with the correct props', () => {
+ const expectedProps = {
+ ariaLabelledby: label,
+ placeholder,
+ };
+
+ expect(findTokenSelector().props()).toEqual(expect.objectContaining(expectedProps));
+ });
+ });
+
+ describe('users', () => {
+ describe('when input is focused for the first time (modal auto-focus)', () => {
+ it('does not call the API', async () => {
+ findTokenSelector().vm.$emit('focus');
+
+ await waitForPromises();
+
+ expect(Api.users).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('when input is manually focused', () => {
+ it('calls the API and sets dropdown items as request result', async () => {
+ const tokenSelector = findTokenSelector();
+
+ tokenSelector.vm.$emit('focus');
+ tokenSelector.vm.$emit('blur');
+ tokenSelector.vm.$emit('focus');
+
+ await waitForPromises();
+
+ expect(tokenSelector.props('dropdownItems')).toMatchObject(allUsers);
+ expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
+ });
+ });
+
+ describe('when text input is typed in', () => {
+ it('calls the API with search parameter', async () => {
+ const searchParam = 'One';
+ const tokenSelector = findTokenSelector();
+
+ tokenSelector.vm.$emit('text-input', searchParam);
+
+ await waitForPromises();
+
+ expect(Api.users).toHaveBeenCalledWith(searchParam, wrapper.vm.$options.queryOptions);
+ expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
+ });
+ });
+
+ describe('when user is selected', () => {
+ it('emits `input` event with selected users', () => {
+ findTokenSelector().vm.$emit('input', [
+ { id: 1, name: 'John Smith' },
+ { id: 2, name: 'Jane Doe' },
+ ]);
+
+ expect(wrapper.emitted().input[0][0]).toBe('1,2');
+ });
+ });
+ });
+
+ describe('when text input is blurred', () => {
+ it('clears text input', async () => {
+ const tokenSelector = findTokenSelector();
+
+ tokenSelector.vm.$emit('blur');
+
+ await nextTick();
+
+ expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
+ });
+ });
+});