Commit 8526a2b4 authored by Vijay Hawoldar's avatar Vijay Hawoldar Committed by Vitaly Slobodin

Change members to billable members in frontend

The seat usage member management is changing to use a
specific billable member endpoint, so the terminology should
also change to reflect this to avoid confusion between members and
billable members
parent 08c21fb6
...@@ -3,7 +3,6 @@ import { buildApiUrl } from './api_utils'; ...@@ -3,7 +3,6 @@ import { buildApiUrl } from './api_utils';
import { DEFAULT_PER_PAGE } from './constants'; import { DEFAULT_PER_PAGE } from './constants';
const GROUPS_PATH = '/api/:version/groups.json'; const GROUPS_PATH = '/api/:version/groups.json';
const GROUPS_MEMBERS_SINGLE_PATH = '/api/:version/groups/:group_id/members/:id';
export function getGroups(query, options, callback = () => {}) { export function getGroups(query, options, callback = () => {}) {
const url = buildApiUrl(GROUPS_PATH); const url = buildApiUrl(GROUPS_PATH);
...@@ -21,11 +20,3 @@ export function getGroups(query, options, callback = () => {}) { ...@@ -21,11 +20,3 @@ export function getGroups(query, options, callback = () => {}) {
return data; return data;
}); });
} }
export function removeMemberFromGroup(groupId, memberId, options) {
const url = buildApiUrl(GROUPS_MEMBERS_SINGLE_PATH)
.replace(':group_id', groupId)
.replace(':id', memberId);
return axios.delete(url, { params: { ...options } });
}
import { buildApiUrl } from '~/api/api_utils';
import axios from '~/lib/utils/axios_utils';
const GROUPS_BILLABLE_MEMBERS_SINGLE_PATH = '/api/:version/groups/:group_id/billable_members/:id';
export function removeBillableMemberFromGroup(groupId, memberId, options) {
const url = buildApiUrl(GROUPS_BILLABLE_MEMBERS_SINGLE_PATH)
.replace(':group_id', groupId)
.replace(':id', memberId);
return axios.delete(url, { params: { ...options } });
}
...@@ -8,14 +8,14 @@ import { ...@@ -8,14 +8,14 @@ import {
} from '@gitlab/ui'; } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex'; import { mapActions, mapState } from 'vuex';
import { import {
REMOVE_MEMBER_MODAL_ID, REMOVE_BILLABLE_MEMBER_MODAL_ID,
REMOVE_MEMBER_MODAL_CONTENT_TEXT_TEMPLATE, REMOVE_BILLABLE_MEMBER_MODAL_CONTENT_TEXT_TEMPLATE,
} from 'ee/billings/seat_usage/constants'; } from 'ee/billings/seat_usage/constants';
import csrf from '~/lib/utils/csrf'; import csrf from '~/lib/utils/csrf';
import { __, s__, sprintf } from '~/locale'; import { __, s__, sprintf } from '~/locale';
export default { export default {
name: 'RemoveMemberModal', name: 'RemoveBillableMemberModal',
csrf, csrf,
components: { components: {
GlFormInput, GlFormInput,
...@@ -32,17 +32,17 @@ export default { ...@@ -32,17 +32,17 @@ export default {
}; };
}, },
computed: { computed: {
...mapState(['namespaceName', 'namespaceId', 'memberToRemove']), ...mapState(['namespaceName', 'namespaceId', 'billableMemberToRemove']),
modalTitle() { modalTitle() {
return sprintf(s__('Billing|Remove user %{username} from your subscription'), { return sprintf(s__('Billing|Remove user %{username} from your subscription'), {
username: this.usernameWithAtPrepended, username: this.usernameWithAtPrepended,
}); });
}, },
canSubmit() { canSubmit() {
return this.enteredMemberUsername === this.memberToRemove.username; return this.enteredMemberUsername === this.billableMemberToRemove.username;
}, },
modalText() { modalText() {
return REMOVE_MEMBER_MODAL_CONTENT_TEXT_TEMPLATE; return REMOVE_BILLABLE_MEMBER_MODAL_CONTENT_TEXT_TEMPLATE;
}, },
actionPrimaryProps() { actionPrimaryProps() {
return { return {
...@@ -63,13 +63,13 @@ export default { ...@@ -63,13 +63,13 @@ export default {
}; };
}, },
usernameWithAtPrepended() { usernameWithAtPrepended() {
return `@${this.memberToRemove.username}`; return `@${this.billableMemberToRemove.username}`;
}, },
}, },
methods: { methods: {
...mapActions(['removeMember', 'setMemberToRemove']), ...mapActions(['removeBillableMember', 'setBillableMemberToRemove']),
}, },
modalId: REMOVE_MEMBER_MODAL_ID, modalId: REMOVE_BILLABLE_MEMBER_MODAL_ID,
i18n: { i18n: {
inputLabel: s__('Billing|Type %{username} to confirm'), inputLabel: s__('Billing|Type %{username} to confirm'),
}, },
...@@ -78,16 +78,15 @@ export default { ...@@ -78,16 +78,15 @@ export default {
<template> <template>
<gl-modal <gl-modal
v-if="memberToRemove" v-if="billableMemberToRemove"
v-bind="$attrs"
:modal-id="$options.modalId" :modal-id="$options.modalId"
:action-primary="actionPrimaryProps" :action-primary="actionPrimaryProps"
:action-cancel="actionCancelProps" :action-cancel="actionCancelProps"
:title="modalTitle" :title="modalTitle"
data-qa-selector="remove_member_modal" data-qa-selector="remove_billable_member_modal"
:ok-disabled="!canSubmit" :ok-disabled="!canSubmit"
@primary="removeMember" @primary="removeBillableMember"
@canceled="setMemberToRemove(null)" @canceled="setBillableMemberToRemove(null)"
> >
<p> <p>
<gl-sprintf :message="modalText"> <gl-sprintf :message="modalText">
...@@ -101,7 +100,7 @@ export default { ...@@ -101,7 +100,7 @@ export default {
<label id="input-label"> <label id="input-label">
<gl-sprintf :message="this.$options.i18n.inputLabel"> <gl-sprintf :message="this.$options.i18n.inputLabel">
<template #username> <template #username>
<gl-badge variant="danger">{{ memberToRemove.username }}</gl-badge> <gl-badge variant="danger">{{ billableMemberToRemove.username }}</gl-badge>
</template> </template>
</gl-sprintf> </gl-sprintf>
</label> </label>
......
...@@ -17,11 +17,11 @@ import { ...@@ -17,11 +17,11 @@ import {
FIELDS, FIELDS,
AVATAR_SIZE, AVATAR_SIZE,
SEARCH_DEBOUNCE_MS, SEARCH_DEBOUNCE_MS,
REMOVE_MEMBER_MODAL_ID, REMOVE_BILLABLE_MEMBER_MODAL_ID,
} from 'ee/billings/seat_usage/constants'; } from 'ee/billings/seat_usage/constants';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import RemoveMemberModal from './remove_member_modal.vue'; import RemoveBillableMemberModal from './remove_billable_member_modal.vue';
export default { export default {
directives: { directives: {
...@@ -37,7 +37,7 @@ export default { ...@@ -37,7 +37,7 @@ export default {
GlPagination, GlPagination,
GlSearchBoxByType, GlSearchBoxByType,
GlTable, GlTable,
RemoveMemberModal, RemoveBillableMemberModal,
TimeAgoTooltip, TimeAgoTooltip,
}, },
data() { data() {
...@@ -53,7 +53,7 @@ export default { ...@@ -53,7 +53,7 @@ export default {
'total', 'total',
'namespaceName', 'namespaceName',
'namespaceId', 'namespaceId',
'memberToRemove', 'billableMemberToRemove',
]), ]),
...mapGetters(['tableItems']), ...mapGetters(['tableItems']),
currentPage: { currentPage: {
...@@ -95,7 +95,11 @@ export default { ...@@ -95,7 +95,11 @@ export default {
this.fetchBillableMembersList(); this.fetchBillableMembersList();
}, },
methods: { methods: {
...mapActions(['fetchBillableMembersList', 'resetMembers', 'setMemberToRemove']), ...mapActions([
'fetchBillableMembersList',
'resetBillableMembers',
'setBillableMemberToRemove',
]),
onSearchEnter() { onSearchEnter() {
this.debouncedSearch.cancel(); this.debouncedSearch.cancel();
this.executeQuery(); this.executeQuery();
...@@ -107,7 +111,7 @@ export default { ...@@ -107,7 +111,7 @@ export default {
if (queryLength === 0 || queryLength >= MIN_SEARCH_LENGTH) { if (queryLength === 0 || queryLength >= MIN_SEARCH_LENGTH) {
this.debouncedSearch(); this.debouncedSearch();
} else if (queryLength < MIN_SEARCH_LENGTH) { } else if (queryLength < MIN_SEARCH_LENGTH) {
this.resetMembers(); this.resetBillableMembers();
} }
}, },
}, },
...@@ -118,7 +122,7 @@ export default { ...@@ -118,7 +122,7 @@ export default {
}, },
avatarSize: AVATAR_SIZE, avatarSize: AVATAR_SIZE,
fields: FIELDS, fields: FIELDS,
removeMemberModalId: REMOVE_MEMBER_MODAL_ID, removeBillableMemberModalId: REMOVE_BILLABLE_MEMBER_MODAL_ID,
}; };
</script> </script>
...@@ -195,8 +199,8 @@ export default { ...@@ -195,8 +199,8 @@ export default {
<template #cell(actions)="data"> <template #cell(actions)="data">
<gl-dropdown icon="ellipsis_h" right data-testid="user-actions"> <gl-dropdown icon="ellipsis_h" right data-testid="user-actions">
<gl-dropdown-item <gl-dropdown-item
v-gl-modal="$options.removeMemberModalId" v-gl-modal="$options.removeBillableMemberModalId"
@click="setMemberToRemove(data.item.user)" @click="setBillableMemberToRemove(data.item.user)"
> >
{{ __('Remove user') }} {{ __('Remove user') }}
</gl-dropdown-item> </gl-dropdown-item>
...@@ -213,6 +217,9 @@ export default { ...@@ -213,6 +217,9 @@ export default {
class="gl-mt-5" class="gl-mt-5"
/> />
<remove-member-modal v-if="memberToRemove" :modal-id="$options.removeMemberModalId" /> <remove-billable-member-modal
v-if="billableMemberToRemove"
:modal-id="$options.removeBillableMemberModalId"
/>
</section> </section>
</template> </template>
...@@ -28,8 +28,8 @@ export const FIELDS = [ ...@@ -28,8 +28,8 @@ export const FIELDS = [
}, },
]; ];
export const REMOVE_MEMBER_MODAL_ID = 'member-remove-modal'; export const REMOVE_BILLABLE_MEMBER_MODAL_ID = 'billable-member-remove-modal';
export const REMOVE_MEMBER_MODAL_CONTENT_TEXT_TEMPLATE = s__( export const REMOVE_BILLABLE_MEMBER_MODAL_CONTENT_TEXT_TEMPLATE = s__(
`Billing|You are about to remove user %{username} from your subscription. `Billing|You are about to remove user %{username} from your subscription.
If you continue, the user will be removed from the %{namespace} If you continue, the user will be removed from the %{namespace}
group and all its subgroups and projects. This action can't be undone.`, group and all its subgroups and projects. This action can't be undone.`,
......
import Api from 'ee/api'; import Api from 'ee/api';
import * as GroupsApi from '~/api/groups_api'; import * as GroupsApi from 'ee/api/groups_api';
import createFlash, { FLASH_TYPES } from '~/flash'; import createFlash, { FLASH_TYPES } from '~/flash';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import * as types from './mutation_types'; import * as types from './mutation_types';
...@@ -24,21 +24,21 @@ export const receiveBillableMembersListError = ({ commit }) => { ...@@ -24,21 +24,21 @@ export const receiveBillableMembersListError = ({ commit }) => {
commit(types.RECEIVE_BILLABLE_MEMBERS_ERROR); commit(types.RECEIVE_BILLABLE_MEMBERS_ERROR);
}; };
export const resetMembers = ({ commit }) => { export const resetBillableMembers = ({ commit }) => {
commit(types.RESET_MEMBERS); commit(types.RESET_BILLABLE_MEMBERS);
}; };
export const setMemberToRemove = ({ commit }, member) => { export const setBillableMemberToRemove = ({ commit }, member) => {
commit(types.SET_MEMBER_TO_REMOVE, member); commit(types.SET_BILLABLE_MEMBER_TO_REMOVE, member);
}; };
export const removeMember = ({ dispatch, state }) => { export const removeBillableMember = ({ dispatch, state }) => {
return GroupsApi.removeMemberFromGroup(state.namespaceId, state.memberToRemove.id) return GroupsApi.removeBillableMemberFromGroup(state.namespaceId, state.billableMemberToRemove.id)
.then(() => dispatch('removeMemberSuccess')) .then(() => dispatch('removeBillableMemberSuccess'))
.catch(() => dispatch('removeMemberError')); .catch(() => dispatch('removeBillableMemberError'));
}; };
export const removeMemberSuccess = ({ dispatch, commit }) => { export const removeBillableMemberSuccess = ({ dispatch, commit }) => {
dispatch('fetchBillableMembersList'); dispatch('fetchBillableMembersList');
createFlash({ createFlash({
...@@ -46,12 +46,12 @@ export const removeMemberSuccess = ({ dispatch, commit }) => { ...@@ -46,12 +46,12 @@ export const removeMemberSuccess = ({ dispatch, commit }) => {
type: FLASH_TYPES.SUCCESS, type: FLASH_TYPES.SUCCESS,
}); });
commit(types.REMOVE_MEMBER_SUCCESS); commit(types.REMOVE_BILLABLE_MEMBER_SUCCESS);
}; };
export const removeMemberError = ({ commit }) => { export const removeBillableMemberError = ({ commit }) => {
createFlash({ createFlash({
message: s__('Billing|An error occurred while removing a billable member'), message: s__('Billing|An error occurred while removing a billable member'),
}); });
commit(types.REMOVE_MEMBER_ERROR); commit(types.REMOVE_BILLABLE_MEMBER_ERROR);
}; };
...@@ -4,8 +4,8 @@ export const RECEIVE_BILLABLE_MEMBERS_ERROR = 'RECEIVE_BILLABLE_MEMBERS_ERROR'; ...@@ -4,8 +4,8 @@ export const RECEIVE_BILLABLE_MEMBERS_ERROR = 'RECEIVE_BILLABLE_MEMBERS_ERROR';
export const SET_SEARCH = 'SET_SEARCH'; export const SET_SEARCH = 'SET_SEARCH';
export const RESET_MEMBERS = 'RESET_MEMBERS'; export const RESET_BILLABLE_MEMBERS = 'RESET_BILLABLE_MEMBERS';
export const REMOVE_MEMBER = 'REMOVE_MEMBER'; export const REMOVE_BILLABLE_MEMBER = 'REMOVE_BILLABLE_MEMBER';
export const REMOVE_MEMBER_SUCCESS = 'REMOVE_MEMBER_SUCCESS'; export const REMOVE_BILLABLE_MEMBER_SUCCESS = 'REMOVE_BILLABLE_MEMBER_SUCCESS';
export const REMOVE_MEMBER_ERROR = 'REMOVE_MEMBER_ERROR'; export const REMOVE_BILLABLE_MEMBER_ERROR = 'REMOVE_BILLABLE_MEMBER_ERROR';
export const SET_MEMBER_TO_REMOVE = 'SET_MEMBER_TO_REMOVE'; export const SET_BILLABLE_MEMBER_TO_REMOVE = 'SET_BILLABLE_MEMBER_TO_REMOVE';
...@@ -31,7 +31,7 @@ export default { ...@@ -31,7 +31,7 @@ export default {
state.search = searchString ?? ''; state.search = searchString ?? '';
}, },
[types.RESET_MEMBERS](state) { [types.RESET_BILLABLE_MEMBERS](state) {
state.members = []; state.members = [];
state.total = null; state.total = null;
...@@ -41,28 +41,30 @@ export default { ...@@ -41,28 +41,30 @@ export default {
state.isLoading = false; state.isLoading = false;
}, },
[types.SET_MEMBER_TO_REMOVE](state, memberToRemove) { [types.SET_BILLABLE_MEMBER_TO_REMOVE](state, memberToRemove) {
if (!memberToRemove) { if (!memberToRemove) {
state.memberToRemove = null; state.billableMemberToRemove = null;
} else { } else {
state.memberToRemove = state.members.find((member) => member.id === memberToRemove.id); state.billableMemberToRemove = state.members.find(
(member) => member.id === memberToRemove.id,
);
} }
}, },
[types.REMOVE_MEMBER](state) { [types.REMOVE_BILLABLE_MEMBER](state) {
state.isLoading = true; state.isLoading = true;
state.hasError = false; state.hasError = false;
}, },
[types.REMOVE_MEMBER_SUCCESS](state) { [types.REMOVE_BILLABLE_MEMBER_SUCCESS](state) {
state.isLoading = false; state.isLoading = false;
state.hasError = false; state.hasError = false;
state.memberToRemove = null; state.billableMemberToRemove = null;
}, },
[types.REMOVE_MEMBER_ERROR](state) { [types.REMOVE_BILLABLE_MEMBER_ERROR](state) {
state.isLoading = false; state.isLoading = false;
state.hasError = true; state.hasError = true;
state.memberToRemove = null; state.billableMemberToRemove = null;
}, },
}; };
...@@ -7,5 +7,5 @@ export default ({ namespaceId = null, namespaceName = null } = {}) => ({ ...@@ -7,5 +7,5 @@ export default ({ namespaceId = null, namespaceName = null } = {}) => ({
total: null, total: null,
page: null, page: null,
perPage: null, perPage: null,
memberToRemove: null, billableMemberToRemove: null,
}); });
export * from './api/groups_api';
...@@ -48,13 +48,13 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do ...@@ -48,13 +48,13 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do
end end
it 'has disabled the remove button' do it 'has disabled the remove button' do
within '[data-qa-selector="remove_member_modal"]' do within '[data-qa-selector="remove_billable_member_modal"]' do
expect(page).to have_button('Remove user', disabled: true) expect(page).to have_button('Remove user', disabled: true)
end end
end end
it 'enables the remove button when user enters valid username' do it 'enables the remove button when user enters valid username' do
within '[data-qa-selector="remove_member_modal"]' do within '[data-qa-selector="remove_billable_member_modal"]' do
find('input').fill_in(with: maintainer.username) find('input').fill_in(with: maintainer.username)
find('input').send_keys(:tab) find('input').send_keys(:tab)
...@@ -63,7 +63,7 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do ...@@ -63,7 +63,7 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do
end end
it 'does not enable button when user enters invalid username' do it 'does not enable button when user enters invalid username' do
within '[data-qa-selector="remove_member_modal"]' do within '[data-qa-selector="remove_billable_member_modal"]' do
find('input').fill_in(with: 'invalid username') find('input').fill_in(with: 'invalid username')
find('input').send_keys(:tab) find('input').send_keys(:tab)
...@@ -81,7 +81,7 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do ...@@ -81,7 +81,7 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do
end end
it 'shows a flash message' do it 'shows a flash message' do
within '[data-qa-selector="remove_member_modal"]' do within '[data-qa-selector="remove_billable_member_modal"]' do
find('input').fill_in(with: maintainer.username) find('input').fill_in(with: maintainer.username)
find('input').send_keys(:tab) find('input').send_keys(:tab)
......
...@@ -2,18 +2,18 @@ import { GlSprintf } from '@gitlab/ui'; ...@@ -2,18 +2,18 @@ import { GlSprintf } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import RemoveMemberModal from 'ee/billings/seat_usage/components/remove_member_modal.vue'; import RemoveBillableMemberModal from 'ee/billings/seat_usage/components/remove_billable_member_modal.vue';
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(Vuex); localVue.use(Vuex);
describe('RemoveMemberModal', () => { describe('RemoveBillableMemberModal', () => {
let wrapper; let wrapper;
const defaultState = { const defaultState = {
namespaceName: 'foo', namespaceName: 'foo',
namespaceId: '1', namespaceId: '1',
memberToRemove: { billableMemberToRemove: {
id: 2, id: 2,
username: 'username', username: 'username',
name: 'First Last', name: 'First Last',
...@@ -27,7 +27,7 @@ describe('RemoveMemberModal', () => { ...@@ -27,7 +27,7 @@ describe('RemoveMemberModal', () => {
}; };
const createComponent = (mountFn = shallowMount) => { const createComponent = (mountFn = shallowMount) => {
wrapper = mountFn(RemoveMemberModal, { wrapper = mountFn(RemoveBillableMemberModal, {
store: createStore(), store: createStore(),
stubs: { stubs: {
GlSprintf, GlSprintf,
...@@ -53,13 +53,13 @@ describe('RemoveMemberModal', () => { ...@@ -53,13 +53,13 @@ describe('RemoveMemberModal', () => {
it('renders the title with username', () => { it('renders the title with username', () => {
expect(wrapper.attributes('title')).toBe( expect(wrapper.attributes('title')).toBe(
`Remove user @${defaultState.memberToRemove.username} from your subscription`, `Remove user @${defaultState.billableMemberToRemove.username} from your subscription`,
); );
}); });
it('renders the confirmation label with username', () => { it('renders the confirmation label with username', () => {
expect(wrapper.find('label').text()).toContain( expect(wrapper.find('label').text()).toContain(
defaultState.memberToRemove.username.substring(1), defaultState.billableMemberToRemove.username.substring(1),
); );
}); });
}); });
......
...@@ -17,7 +17,7 @@ localVue.use(Vuex); ...@@ -17,7 +17,7 @@ localVue.use(Vuex);
const actionSpies = { const actionSpies = {
fetchBillableMembersList: jest.fn(), fetchBillableMembersList: jest.fn(),
resetMembers: jest.fn(), resetBillableMembers: jest.fn(),
}; };
const providedFields = { const providedFields = {
...@@ -228,17 +228,17 @@ describe('Subscription Seats', () => { ...@@ -228,17 +228,17 @@ describe('Subscription Seats', () => {
expect(findTableEmptyText()).toBe(EMPTY_TEXT_NO_USERS); expect(findTableEmptyText()).toBe(EMPTY_TEXT_NO_USERS);
}); });
it('dispatches the resetMembers action when 1 or 2 characters have been typed', async () => { it('dispatches the.resetBillableMembers action when 1 or 2 characters have been typed', async () => {
expect(actionSpies.resetMembers).not.toHaveBeenCalled(); expect(actionSpies.resetBillableMembers).not.toHaveBeenCalled();
await findSearchBox().vm.$emit('input', 'a'); await findSearchBox().vm.$emit('input', 'a');
expect(actionSpies.resetMembers).toHaveBeenCalledTimes(1); expect(actionSpies.resetBillableMembers).toHaveBeenCalledTimes(1);
await findSearchBox().vm.$emit('input', 'aa'); await findSearchBox().vm.$emit('input', 'aa');
expect(actionSpies.resetMembers).toHaveBeenCalledTimes(2); expect(actionSpies.resetBillableMembers).toHaveBeenCalledTimes(2);
await findSearchBox().vm.$emit('input', 'aaa'); await findSearchBox().vm.$emit('input', 'aaa');
expect(actionSpies.resetMembers).toHaveBeenCalledTimes(2); expect(actionSpies.resetBillableMembers).toHaveBeenCalledTimes(2);
}); });
it('dispatches fetchBillableMembersList action when search box is emptied out', async () => { it('dispatches fetchBillableMembersList action when search box is emptied out', async () => {
......
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import Api from 'ee/api'; import Api from 'ee/api';
import * as GroupsApi from 'ee/api/groups_api';
import * as actions from 'ee/billings/seat_usage/store/actions'; import * as actions from 'ee/billings/seat_usage/store/actions';
import * as types from 'ee/billings/seat_usage/store/mutation_types'; import * as types from 'ee/billings/seat_usage/store/mutation_types';
import State from 'ee/billings/seat_usage/store/state'; import State from 'ee/billings/seat_usage/store/state';
import { mockDataSeats } from 'ee_jest/billings/mock_data'; import { mockDataSeats } from 'ee_jest/billings/mock_data';
import testAction from 'helpers/vuex_action_helper'; import testAction from 'helpers/vuex_action_helper';
import * as GroupsApi from '~/api/groups_api';
import createFlash, { FLASH_TYPES } from '~/flash'; import createFlash, { FLASH_TYPES } from '~/flash';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status'; import httpStatusCodes from '~/lib/utils/http_status';
...@@ -121,35 +121,35 @@ describe('seats actions', () => { ...@@ -121,35 +121,35 @@ describe('seats actions', () => {
}); });
}); });
describe('resetMembers', () => { describe('resetBillableMembers', () => {
it('should commit mutation', () => { it('should commit mutation', () => {
testAction({ testAction({
action: actions.resetMembers, action: actions.resetBillableMembers,
state, state,
expectedMutations: [{ type: types.RESET_MEMBERS }], expectedMutations: [{ type: types.RESET_BILLABLE_MEMBERS }],
}); });
}); });
}); });
describe('setMemberToRemove', () => { describe('setBillableMemberToRemove', () => {
it('should commit the set member mutation', async () => { it('should commit the set member mutation', async () => {
await testAction({ await testAction({
action: actions.setMemberToRemove, action: actions.setBillableMemberToRemove,
state, state,
expectedMutations: [{ type: types.SET_MEMBER_TO_REMOVE }], expectedMutations: [{ type: types.SET_BILLABLE_MEMBER_TO_REMOVE }],
}); });
}); });
}); });
describe('removeMember', () => { describe('removeBillableMember', () => {
let groupsApiSpy; let groupsApiSpy;
beforeEach(() => { beforeEach(() => {
groupsApiSpy = jest.spyOn(GroupsApi, 'removeMemberFromGroup'); groupsApiSpy = jest.spyOn(GroupsApi, 'removeBillableMemberFromGroup');
state = { state = {
namespaceId: 1, namespaceId: 1,
memberToRemove: { billableMemberToRemove: {
id: 2, id: 2,
}, },
}; };
...@@ -157,14 +157,14 @@ describe('seats actions', () => { ...@@ -157,14 +157,14 @@ describe('seats actions', () => {
describe('on success', () => { describe('on success', () => {
beforeEach(() => { beforeEach(() => {
mock.onDelete('/api/v4/groups/1/members/2').reply(httpStatusCodes.OK); mock.onDelete('/api/v4/groups/1/billable_members/2').reply(httpStatusCodes.OK);
}); });
it('dispatches the removeMemberSuccess action', async () => { it('dispatches the removeBillableMemberSuccess action', async () => {
await testAction({ await testAction({
action: actions.removeMember, action: actions.removeBillableMember,
state, state,
expectedActions: [{ type: 'removeMemberSuccess' }], expectedActions: [{ type: 'removeBillableMemberSuccess' }],
}); });
expect(groupsApiSpy).toHaveBeenCalled(); expect(groupsApiSpy).toHaveBeenCalled();
...@@ -173,14 +173,16 @@ describe('seats actions', () => { ...@@ -173,14 +173,16 @@ describe('seats actions', () => {
describe('on error', () => { describe('on error', () => {
beforeEach(() => { beforeEach(() => {
mock.onDelete('/api/v4/groups/1/members/2').reply(httpStatusCodes.UNPROCESSABLE_ENTITY); mock
.onDelete('/api/v4/groups/1/billable_members/2')
.reply(httpStatusCodes.UNPROCESSABLE_ENTITY);
}); });
it('dispatches the removeMemberError action', async () => { it('dispatches the removeBillableMemberError action', async () => {
await testAction({ await testAction({
action: actions.removeMember, action: actions.removeBillableMember,
state, state,
expectedActions: [{ type: 'removeMemberError' }], expectedActions: [{ type: 'removeBillableMemberError' }],
}); });
expect(groupsApiSpy).toHaveBeenCalled(); expect(groupsApiSpy).toHaveBeenCalled();
...@@ -188,13 +190,13 @@ describe('seats actions', () => { ...@@ -188,13 +190,13 @@ describe('seats actions', () => {
}); });
}); });
describe('removeMemberSuccess', () => { describe('removeBillableMemberSuccess', () => {
it('dispatches fetchBillableMembersList', async () => { it('dispatches fetchBillableMembersList', async () => {
await testAction({ await testAction({
action: actions.removeMemberSuccess, action: actions.removeBillableMemberSuccess,
state, state,
expectedActions: [{ type: 'fetchBillableMembersList' }], expectedActions: [{ type: 'fetchBillableMembersList' }],
expectedMutations: [{ type: types.REMOVE_MEMBER_SUCCESS }], expectedMutations: [{ type: types.REMOVE_BILLABLE_MEMBER_SUCCESS }],
}); });
expect(createFlash).toHaveBeenCalledWith({ expect(createFlash).toHaveBeenCalledWith({
...@@ -204,12 +206,12 @@ describe('seats actions', () => { ...@@ -204,12 +206,12 @@ describe('seats actions', () => {
}); });
}); });
describe('removeMemberError', () => { describe('removeBillableMemberError', () => {
it('commits remove member error', async () => { it('commits remove member error', async () => {
await testAction({ await testAction({
action: actions.removeMemberError, action: actions.removeBillableMemberError,
state, state,
expectedMutations: [{ type: types.REMOVE_MEMBER_ERROR }], expectedMutations: [{ type: types.REMOVE_BILLABLE_MEMBER_ERROR }],
}); });
expect(createFlash).toHaveBeenCalledWith({ expect(createFlash).toHaveBeenCalledWith({
......
...@@ -68,10 +68,10 @@ describe('EE billings seats module mutations', () => { ...@@ -68,10 +68,10 @@ describe('EE billings seats module mutations', () => {
}); });
}); });
describe(types.RESET_MEMBERS, () => { describe(types.RESET_BILLABLE_MEMBERS, () => {
beforeEach(() => { beforeEach(() => {
mutations[types.RECEIVE_BILLABLE_MEMBERS_SUCCESS](state, mockDataSeats); mutations[types.RECEIVE_BILLABLE_MEMBERS_SUCCESS](state, mockDataSeats);
mutations[types.RESET_MEMBERS](state); mutations[types.RESET_BILLABLE_MEMBERS](state);
}); });
it('resets members state', () => { it('resets members state', () => {
...@@ -96,42 +96,42 @@ describe('EE billings seats module mutations', () => { ...@@ -96,42 +96,42 @@ describe('EE billings seats module mutations', () => {
mutations[types.RECEIVE_BILLABLE_MEMBERS_SUCCESS](state, mockDataSeats); mutations[types.RECEIVE_BILLABLE_MEMBERS_SUCCESS](state, mockDataSeats);
}); });
describe(types.SET_MEMBER_TO_REMOVE, () => { describe(types.SET_BILLABLE_MEMBER_TO_REMOVE, () => {
it('sets the member to remove', () => { it('sets the member to remove', () => {
mutations[types.SET_MEMBER_TO_REMOVE](state, memberToRemove); mutations[types.SET_BILLABLE_MEMBER_TO_REMOVE](state, memberToRemove);
expect(state.memberToRemove).toMatchObject(memberToRemove); expect(state.billableMemberToRemove).toMatchObject(memberToRemove);
}); });
}); });
describe(types.REMOVE_MEMBER, () => { describe(types.REMOVE_BILLABLE_MEMBER, () => {
it('sets state to loading', () => { it('sets state to loading', () => {
mutations[types.REMOVE_MEMBER](state, memberToRemove); mutations[types.REMOVE_BILLABLE_MEMBER](state, memberToRemove);
expect(state).toMatchObject({ isLoading: true, hasError: false }); expect(state).toMatchObject({ isLoading: true, hasError: false });
}); });
}); });
describe(types.REMOVE_MEMBER_SUCCESS, () => { describe(types.REMOVE_BILLABLE_MEMBER_SUCCESS, () => {
it('sets state to successfull', () => { it('sets state to successfull', () => {
mutations[types.REMOVE_MEMBER_SUCCESS](state, memberToRemove); mutations[types.REMOVE_BILLABLE_MEMBER_SUCCESS](state, memberToRemove);
expect(state).toMatchObject({ expect(state).toMatchObject({
isLoading: false, isLoading: false,
hasError: false, hasError: false,
memberToRemove: null, billableMemberToRemove: null,
}); });
}); });
}); });
describe(types.REMOVE_MEMBER_ERROR, () => { describe(types.REMOVE_BILLABLE_MEMBER_ERROR, () => {
it('sets state to errored', () => { it('sets state to errored', () => {
mutations[types.REMOVE_MEMBER_ERROR](state, memberToRemove); mutations[types.REMOVE_BILLABLE_MEMBER_ERROR](state, memberToRemove);
expect(state).toMatchObject({ expect(state).toMatchObject({
isLoading: false, isLoading: false,
hasError: true, hasError: true,
memberToRemove: null, billableMemberToRemove: null,
}); });
}); });
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment