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:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-22 15:10:04 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-22 15:10:04 +0300
commitcb8bd7d5946ca50a2de99645687a633a0c8105be (patch)
treea327e4da74f2a2d050a6971e0e03d41e5b0c5780 /spec/frontend/members
parent8e0dafbb6665d431f7f1b635c0f7c4a5c61bc325 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/members')
-rw-r--r--spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js2
-rw-r--r--spec/frontend/members/components/action_buttons/remove_member_button_spec.js27
-rw-r--r--spec/frontend/members/components/modals/remove_member_modal_spec.js133
-rw-r--r--spec/frontend/members/components/table/members_table_spec.js1
-rw-r--r--spec/frontend/members/mock_data.js9
-rw-r--r--spec/frontend/members/store/actions_spec.js32
-rw-r--r--spec/frontend/members/store/mutations_spec.js30
7 files changed, 218 insertions, 16 deletions
diff --git a/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js b/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js
index e7a99a96da6..79252456f67 100644
--- a/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js
+++ b/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js
@@ -37,7 +37,7 @@ describe('InviteActionButtons', () => {
});
it('sets props correctly', () => {
- expect(findRemoveMemberButton().props()).toEqual({
+ expect(findRemoveMemberButton().props()).toMatchObject({
memberId: member.id,
memberType: null,
message: `Are you sure you want to revoke the invitation for ${member.invite.email} to join "${member.source.fullName}"`,
diff --git a/spec/frontend/members/components/action_buttons/remove_member_button_spec.js b/spec/frontend/members/components/action_buttons/remove_member_button_spec.js
index 4ff12f7fa97..d8453d453e7 100644
--- a/spec/frontend/members/components/action_buttons/remove_member_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/remove_member_button_spec.js
@@ -1,6 +1,8 @@
+import { GlButton } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { modalData } from 'jest/members/mock_data';
import RemoveMemberButton from '~/members/components/action_buttons/remove_member_button.vue';
import { MEMBER_TYPES } from '~/members/constants';
@@ -10,6 +12,10 @@ localVue.use(Vuex);
describe('RemoveMemberButton', () => {
let wrapper;
+ const actions = {
+ showRemoveMemberModal: jest.fn(),
+ };
+
const createStore = (state = {}) => {
return new Vuex.Store({
modules: {
@@ -19,6 +25,7 @@ describe('RemoveMemberButton', () => {
memberPath: '/groups/foo-bar/-/group_members/:id',
...state,
},
+ actions,
},
},
});
@@ -47,20 +54,16 @@ describe('RemoveMemberButton', () => {
});
};
+ beforeEach(() => {
+ createComponent();
+ });
+
afterEach(() => {
wrapper.destroy();
});
it('sets attributes on button', () => {
- createComponent();
-
expect(wrapper.attributes()).toMatchObject({
- 'data-member-path': '/groups/foo-bar/-/group_members/1',
- 'data-member-type': 'GroupMember',
- 'data-message': 'Are you sure you want to remove John Smith?',
- 'data-is-access-request': 'true',
- 'data-is-invite': 'true',
- 'data-oncall-schedules': '{"name":"user","schedules":[]}',
'aria-label': 'Remove member',
title: 'Remove member',
icon: 'remove',
@@ -68,14 +71,12 @@ describe('RemoveMemberButton', () => {
});
it('displays `title` prop as a tooltip', () => {
- createComponent();
-
expect(getBinding(wrapper.element, 'gl-tooltip')).not.toBeUndefined();
});
- it('has CSS class used by `remove_member_modal.vue`', () => {
- createComponent();
+ it('calls Vuex action to show `remove member` modal when clicked', () => {
+ wrapper.findComponent(GlButton).vm.$emit('click');
- expect(wrapper.classes()).toContain('js-remove-member-button');
+ expect(actions.showRemoveMemberModal).toHaveBeenCalledWith(expect.any(Object), modalData);
});
});
diff --git a/spec/frontend/members/components/modals/remove_member_modal_spec.js b/spec/frontend/members/components/modals/remove_member_modal_spec.js
new file mode 100644
index 00000000000..1dc41582c12
--- /dev/null
+++ b/spec/frontend/members/components/modals/remove_member_modal_spec.js
@@ -0,0 +1,133 @@
+import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import Vuex from 'vuex';
+import RemoveMemberModal from '~/members/components/modals/remove_member_modal.vue';
+import { MEMBER_TYPES } from '~/members/constants';
+import OncallSchedulesList from '~/vue_shared/components/oncall_schedules_list.vue';
+
+Vue.use(Vuex);
+
+describe('RemoveMemberModal', () => {
+ const memberPath = '/gitlab-org/gitlab-test/-/project_members/90';
+ const mockSchedules = {
+ name: 'User1',
+ schedules: [{ id: 1, name: 'Schedule 1' }],
+ };
+ let wrapper;
+
+ const actions = {
+ hideRemoveMemberModal: jest.fn(),
+ };
+
+ const createStore = (removeMemberModalData) =>
+ new Vuex.Store({
+ modules: {
+ [MEMBER_TYPES.user]: {
+ namespaced: true,
+ state: {
+ removeMemberModalData,
+ },
+ actions,
+ },
+ },
+ });
+
+ const createComponent = (state) => {
+ wrapper = shallowMount(RemoveMemberModal, {
+ store: createStore(state),
+ provide: {
+ namespace: MEMBER_TYPES.user,
+ },
+ });
+ };
+
+ const findForm = () => wrapper.find({ ref: 'form' });
+ const findGlModal = () => wrapper.findComponent(GlModal);
+ const findOnCallSchedulesList = () => wrapper.findComponent(OncallSchedulesList);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe.each`
+ state | memberType | isAccessRequest | isInvite | actionText | removeSubMembershipsCheckboxExpected | unassignIssuablesCheckboxExpected | message | onCallSchedules
+ ${'removing a group member'} | ${'GroupMember'} | ${false} | ${false} | ${'Remove member'} | ${true} | ${true} | ${'Are you sure you want to remove Jane Doe from the Gitlab Org / Gitlab Test project?'} | ${{}}
+ ${'removing a project member'} | ${'ProjectMember'} | ${false} | ${false} | ${'Remove member'} | ${false} | ${true} | ${'Are you sure you want to remove Jane Doe from the Gitlab Org / Gitlab Test project?'} | ${mockSchedules}
+ ${'denying an access request'} | ${'ProjectMember'} | ${true} | ${false} | ${'Deny access request'} | ${false} | ${false} | ${"Are you sure you want to deny Jane Doe's request to join the Gitlab Org / Gitlab Test project?"} | ${{}}
+ ${'revoking invite'} | ${'ProjectMember'} | ${false} | ${true} | ${'Revoke invite'} | ${false} | ${false} | ${'Are you sure you want to revoke the invitation for foo@bar.com to join the Gitlab Org / Gitlab Test project?'} | ${mockSchedules}
+ `(
+ 'when $state',
+ ({
+ actionText,
+ memberType,
+ isAccessRequest,
+ isInvite,
+ message,
+ removeSubMembershipsCheckboxExpected,
+ unassignIssuablesCheckboxExpected,
+ onCallSchedules,
+ }) => {
+ beforeEach(() => {
+ createComponent({
+ isAccessRequest,
+ isInvite,
+ message,
+ memberPath,
+ memberType,
+ onCallSchedules,
+ });
+ });
+
+ const isPartOfOncallSchedules = Boolean(isAccessRequest && onCallSchedules.schedules?.length);
+
+ it(`has the title ${actionText}`, () => {
+ expect(findGlModal().attributes('title')).toBe(actionText);
+ });
+
+ it('contains a form action', () => {
+ expect(findForm().attributes('action')).toBe(memberPath);
+ });
+
+ it('displays a message to the user', () => {
+ expect(wrapper.find('p').text()).toBe(message);
+ });
+
+ it(`shows ${
+ removeSubMembershipsCheckboxExpected ? 'a' : 'no'
+ } checkbox to remove direct memberships of subgroups/projects`, () => {
+ expect(wrapper.find('[name=remove_sub_memberships]').exists()).toBe(
+ removeSubMembershipsCheckboxExpected,
+ );
+ });
+
+ it(`shows ${
+ unassignIssuablesCheckboxExpected ? 'a' : 'no'
+ } checkbox to allow removal from related issues and MRs`, () => {
+ expect(wrapper.find('[name=unassign_issuables]').exists()).toBe(
+ unassignIssuablesCheckboxExpected,
+ );
+ });
+
+ it(`shows ${isPartOfOncallSchedules ? 'all' : 'no'} related on-call schedules`, () => {
+ expect(findOnCallSchedulesList().exists()).toBe(isPartOfOncallSchedules);
+ });
+
+ it('submits the form when the modal is submitted', () => {
+ const spy = jest.spyOn(findForm().element, 'submit');
+
+ findGlModal().vm.$emit('primary');
+
+ expect(spy).toHaveBeenCalled();
+
+ spy.mockRestore();
+ });
+
+ it('calls Vuex action to hide the modal when `GlModal` emits `hide` event', () => {
+ findGlModal().vm.$emit('hide');
+
+ expect(actions.hideRemoveMemberModal).toHaveBeenCalled();
+ });
+ },
+ );
+});
diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js
index 3a17d78bd17..6e7d9bc6b6e 100644
--- a/spec/frontend/members/components/table/members_table_spec.js
+++ b/spec/frontend/members/components/table/members_table_spec.js
@@ -72,6 +72,7 @@ describe('MembersTable', () => {
'member-action-buttons',
'role-dropdown',
'remove-group-link-modal',
+ 'remove-member-modal',
'expiration-datepicker',
],
});
diff --git a/spec/frontend/members/mock_data.js b/spec/frontend/members/mock_data.js
index 4275db5fa9f..eb9f905fea2 100644
--- a/spec/frontend/members/mock_data.js
+++ b/spec/frontend/members/mock_data.js
@@ -57,6 +57,15 @@ export const group = {
validRoles: { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 },
};
+export const modalData = {
+ isAccessRequest: true,
+ isInvite: true,
+ memberPath: '/groups/foo-bar/-/group_members/1',
+ memberType: 'GroupMember',
+ message: 'Are you sure you want to remove John Smith?',
+ oncallSchedules: { name: 'user', schedules: [] },
+};
+
const { user, ...memberNoUser } = member;
export const invite = {
...memberNoUser,
diff --git a/spec/frontend/members/store/actions_spec.js b/spec/frontend/members/store/actions_spec.js
index d913c5c56df..d37e6871387 100644
--- a/spec/frontend/members/store/actions_spec.js
+++ b/spec/frontend/members/store/actions_spec.js
@@ -3,12 +3,14 @@ import MockAdapter from 'axios-mock-adapter';
import { noop } from 'lodash';
import { useFakeDate } from 'helpers/fake_date';
import testAction from 'helpers/vuex_action_helper';
-import { members, group } from 'jest/members/mock_data';
+import { members, group, modalData } from 'jest/members/mock_data';
import httpStatusCodes from '~/lib/utils/http_status';
import {
updateMemberRole,
showRemoveGroupLinkModal,
hideRemoveGroupLinkModal,
+ showRemoveMemberModal,
+ hideRemoveMemberModal,
updateMemberExpiration,
} from '~/members/store/actions';
import * as types from '~/members/store/mutation_types';
@@ -153,4 +155,32 @@ describe('Vuex members actions', () => {
});
});
});
+
+ describe('Remove member modal', () => {
+ const state = {
+ removeMemberModalVisible: false,
+ removeMemberModalData: {},
+ };
+
+ describe('showRemoveMemberModal', () => {
+ it(`commits ${types.SHOW_REMOVE_MEMBER_MODAL} mutation`, () => {
+ testAction(showRemoveMemberModal, modalData, state, [
+ {
+ type: types.SHOW_REMOVE_MEMBER_MODAL,
+ payload: modalData,
+ },
+ ]);
+ });
+ });
+
+ describe('hideRemoveMemberModal', () => {
+ it(`commits ${types.HIDE_REMOVE_MEMBER_MODAL} mutation`, () => {
+ testAction(hideRemoveMemberModal, undefined, state, [
+ {
+ type: types.HIDE_REMOVE_MEMBER_MODAL,
+ },
+ ]);
+ });
+ });
+ });
});
diff --git a/spec/frontend/members/store/mutations_spec.js b/spec/frontend/members/store/mutations_spec.js
index 7ad7034eb6d..72423c6b4d4 100644
--- a/spec/frontend/members/store/mutations_spec.js
+++ b/spec/frontend/members/store/mutations_spec.js
@@ -1,4 +1,4 @@
-import { members, group } from 'jest/members/mock_data';
+import { members, group, modalData } from 'jest/members/mock_data';
import * as types from '~/members/store/mutation_types';
import mutations from '~/members/store/mutations';
@@ -154,4 +154,32 @@ describe('Vuex members mutations', () => {
expect(state.removeGroupLinkModalVisible).toBe(false);
});
});
+
+ describe(types.SHOW_REMOVE_MEMBER_MODAL, () => {
+ it('sets `removeMemberModalVisible` and `removeMemberModalData`', () => {
+ const state = {
+ removeMemberModalVisible: false,
+ removeMemberModalData: {},
+ };
+
+ mutations[types.SHOW_REMOVE_MEMBER_MODAL](state, modalData);
+
+ expect(state).toEqual({
+ removeMemberModalVisible: true,
+ removeMemberModalData: modalData,
+ });
+ });
+ });
+
+ describe(types.HIDE_REMOVE_MEMBER_MODAL, () => {
+ it('sets `removeMemberModalVisible` to `false`', () => {
+ const state = {
+ removeMemberModalVisible: true,
+ };
+
+ mutations[types.HIDE_REMOVE_MEMBER_MODAL](state);
+
+ expect(state.removeMemberModalVisible).toBe(false);
+ });
+ });
});