debian-mirror-gitlab/spec/frontend/members/components/table/members_table_spec.js

218 lines
7.1 KiB
JavaScript
Raw Normal View History

2021-01-03 14:25:43 +05:30
import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
import Vuex from 'vuex';
import {
getByText as getByTextHelper,
getByTestId as getByTestIdHelper,
2021-01-29 00:20:46 +05:30
within,
2021-01-03 14:25:43 +05:30
} from '@testing-library/dom';
2021-01-29 00:20:46 +05:30
import { GlBadge, GlTable } from '@gitlab/ui';
2021-02-22 17:27:13 +05:30
import MembersTable from '~/members/components/table/members_table.vue';
import MemberAvatar from '~/members/components/table/member_avatar.vue';
import MemberSource from '~/members/components/table/member_source.vue';
import ExpiresAt from '~/members/components/table/expires_at.vue';
import CreatedAt from '~/members/components/table/created_at.vue';
import RoleDropdown from '~/members/components/table/role_dropdown.vue';
import ExpirationDatepicker from '~/members/components/table/expiration_datepicker.vue';
import MemberActionButtons from '~/members/components/table/member_action_buttons.vue';
2021-01-03 14:25:43 +05:30
import * as initUserPopovers from '~/user_popovers';
2021-02-22 17:27:13 +05:30
import { member as memberMock, invite, accessRequest } from '../../mock_data';
2021-01-03 14:25:43 +05:30
const localVue = createLocalVue();
localVue.use(Vuex);
2021-02-22 17:27:13 +05:30
describe('MembersTable', () => {
2021-01-03 14:25:43 +05:30
let wrapper;
const createStore = (state = {}) => {
return new Vuex.Store({
state: {
members: [],
tableFields: [],
2021-01-29 00:20:46 +05:30
tableAttrs: {
table: { 'data-qa-selector': 'members_list' },
tr: { 'data-qa-selector': 'member_row' },
},
2021-01-03 14:25:43 +05:30
sourceId: 1,
2021-01-29 00:20:46 +05:30
currentUserId: 1,
2021-01-03 14:25:43 +05:30
...state,
},
});
};
2021-03-08 18:12:59 +05:30
const createComponent = (state) => {
2021-01-03 14:25:43 +05:30
wrapper = mount(MembersTable, {
localVue,
store: createStore(state),
stubs: [
'member-avatar',
'member-source',
'expires-at',
'created-at',
'member-action-buttons',
'role-dropdown',
'remove-group-link-modal',
2021-01-29 00:20:46 +05:30
'expiration-datepicker',
2021-01-03 14:25:43 +05:30
],
});
};
const getByText = (text, options) =>
createWrapper(getByTextHelper(wrapper.element, text, options));
const getByTestId = (id, options) =>
createWrapper(getByTestIdHelper(wrapper.element, id, options));
2021-01-29 00:20:46 +05:30
const findTable = () => wrapper.find(GlTable);
2021-03-08 18:12:59 +05:30
const findTableCellByMemberId = (tableCellLabel, memberId) =>
getByTestId(`members-table-row-${memberId}`).find(
`[data-label="${tableCellLabel}"][role="cell"]`,
);
2021-01-29 00:20:46 +05:30
2021-01-03 14:25:43 +05:30
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('fields', () => {
2021-01-29 00:20:46 +05:30
const directMember = {
2021-01-03 14:25:43 +05:30
...memberMock,
source: { ...memberMock.source, id: 1 },
};
2021-01-29 00:20:46 +05:30
const memberCanUpdate = {
...directMember,
canUpdate: true,
};
2021-01-03 14:25:43 +05:30
it.each`
field | label | member | expectedComponent
${'account'} | ${'Account'} | ${memberMock} | ${MemberAvatar}
${'source'} | ${'Source'} | ${memberMock} | ${MemberSource}
${'granted'} | ${'Access granted'} | ${memberMock} | ${CreatedAt}
${'invited'} | ${'Invited'} | ${invite} | ${CreatedAt}
${'requested'} | ${'Requested'} | ${accessRequest} | ${CreatedAt}
${'expires'} | ${'Access expires'} | ${memberMock} | ${ExpiresAt}
${'maxRole'} | ${'Max role'} | ${memberCanUpdate} | ${RoleDropdown}
2021-01-29 00:20:46 +05:30
${'expiration'} | ${'Expiration'} | ${memberMock} | ${ExpirationDatepicker}
2021-01-03 14:25:43 +05:30
`('renders the $label field', ({ field, label, member, expectedComponent }) => {
createComponent({
members: [member],
tableFields: [field],
});
expect(getByText(label, { selector: '[role="columnheader"]' }).exists()).toBe(true);
if (expectedComponent) {
expect(
2021-03-08 18:12:59 +05:30
wrapper.find(`[data-label="${label}"][role="cell"]`).find(expectedComponent).exists(),
2021-01-03 14:25:43 +05:30
).toBe(true);
}
});
2021-01-29 00:20:46 +05:30
describe('"Actions" field', () => {
it('renders "Actions" field for screen readers', () => {
createComponent({ members: [memberCanUpdate], tableFields: ['actions'] });
2021-01-03 14:25:43 +05:30
2021-01-29 00:20:46 +05:30
const actionField = getByTestId('col-actions');
2021-01-03 14:25:43 +05:30
2021-01-29 00:20:46 +05:30
expect(actionField.exists()).toBe(true);
expect(actionField.classes('gl-sr-only')).toBe(true);
expect(
2021-03-08 18:12:59 +05:30
wrapper.find(`[data-label="Actions"][role="cell"]`).find(MemberActionButtons).exists(),
2021-01-29 00:20:46 +05:30
).toBe(true);
});
describe('when user is not logged in', () => {
it('does not render the "Actions" field', () => {
createComponent({ currentUserId: null, tableFields: ['actions'] });
expect(within(wrapper.element).queryByTestId('col-actions')).toBe(null);
});
});
const memberCanRemove = {
...directMember,
canRemove: true,
};
2021-03-08 18:12:59 +05:30
const memberNoPermissions = {
...memberMock,
id: 2,
};
2021-01-29 00:20:46 +05:30
describe.each`
permission | members
2021-03-08 18:12:59 +05:30
${'canUpdate'} | ${[memberNoPermissions, memberCanUpdate]}
${'canRemove'} | ${[memberNoPermissions, memberCanRemove]}
${'canResend'} | ${[memberNoPermissions, invite]}
2021-01-29 00:20:46 +05:30
`('when one of the members has $permission permissions', ({ members }) => {
it('renders the "Actions" field', () => {
createComponent({ members, tableFields: ['actions'] });
expect(getByTestId('col-actions').exists()).toBe(true);
2021-03-08 18:12:59 +05:30
expect(findTableCellByMemberId('Actions', members[0].id).classes()).toStrictEqual([
'col-actions',
'gl-display-none!',
'gl-display-lg-table-cell!',
]);
expect(findTableCellByMemberId('Actions', members[1].id).classes()).toStrictEqual([
'col-actions',
]);
2021-01-29 00:20:46 +05:30
});
});
describe.each`
permission | members
${'canUpdate'} | ${[memberMock]}
${'canRemove'} | ${[memberMock]}
${'canResend'} | ${[{ ...invite, invite: { ...invite.invite, canResend: false } }]}
`('when none of the members have $permission permissions', ({ members }) => {
it('does not render the "Actions" field', () => {
createComponent({ members, tableFields: ['actions'] });
expect(within(wrapper.element).queryByTestId('col-actions')).toBe(null);
});
});
2021-01-03 14:25:43 +05:30
});
});
describe('when `members` is an empty array', () => {
it('displays a "No members found" message', () => {
createComponent();
expect(getByText('No members found').exists()).toBe(true);
});
});
describe('when member can not be updated', () => {
it('renders badge in "Max role" field', () => {
createComponent({ members: [memberMock], tableFields: ['maxRole'] });
2021-03-08 18:12:59 +05:30
expect(wrapper.find(`[data-label="Max role"][role="cell"]`).find(GlBadge).text()).toBe(
memberMock.accessLevel.stringValue,
);
2021-01-03 14:25:43 +05:30
});
});
it('initializes user popovers when mounted', () => {
const initUserPopoversMock = jest.spyOn(initUserPopovers, 'default');
createComponent();
expect(initUserPopoversMock).toHaveBeenCalled();
});
2021-01-29 00:20:46 +05:30
it('adds QA selector to table', () => {
createComponent();
expect(findTable().attributes('data-qa-selector')).toBe('members_list');
});
it('adds QA selector to table row', () => {
createComponent();
2021-03-08 18:12:59 +05:30
expect(findTable().find('tbody tr').attributes('data-qa-selector')).toBe('member_row');
2021-01-29 00:20:46 +05:30
});
2021-01-03 14:25:43 +05:30
});