debian-mirror-gitlab/spec/frontend/members/components/table/role_dropdown_spec.js
2021-03-08 18:12:59 +05:30

151 lines
4.3 KiB
JavaScript

import { mount, createWrapper, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { nextTick } from 'vue';
import { within } from '@testing-library/dom';
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import waitForPromises from 'helpers/wait_for_promises';
import RoleDropdown from '~/members/components/table/role_dropdown.vue';
import { member } from '../../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('RoleDropdown', () => {
let wrapper;
let actions;
const $toast = {
show: jest.fn(),
};
const createStore = () => {
actions = {
updateMemberRole: jest.fn(() => Promise.resolve()),
};
return new Vuex.Store({ actions });
};
const createComponent = (propsData = {}) => {
wrapper = mount(RoleDropdown, {
propsData: {
member,
permissions: {},
...propsData,
},
localVue,
store: createStore(),
mocks: {
$toast,
},
});
};
const getDropdownMenu = () => within(wrapper.element).getByRole('menu');
const getByTextInDropdownMenu = (text, options = {}) =>
createWrapper(within(getDropdownMenu()).getByText(text, options));
const getDropdownItemByText = (text) =>
createWrapper(
within(getDropdownMenu())
.getByText(text, { selector: '[role="menuitem"] p' })
.closest('[role="menuitem"]'),
);
const getCheckedDropdownItem = () =>
wrapper
.findAll(GlDropdownItem)
.wrappers.find((dropdownItemWrapper) => dropdownItemWrapper.props('isChecked'));
const findDropdownToggle = () => wrapper.find('button[aria-haspopup="true"]');
const findDropdown = () => wrapper.find(GlDropdown);
afterEach(() => {
wrapper.destroy();
});
describe('when dropdown is open', () => {
beforeEach((done) => {
createComponent();
findDropdownToggle().trigger('click');
wrapper.vm.$root.$on('bv::dropdown::shown', () => {
done();
});
});
it('renders all valid roles', () => {
Object.keys(member.validRoles).forEach((role) => {
expect(getDropdownItemByText(role).exists()).toBe(true);
});
});
it('renders dropdown header', () => {
expect(getByTextInDropdownMenu('Change permissions').exists()).toBe(true);
});
it('sets dropdown toggle and checks selected role', () => {
expect(findDropdownToggle().text()).toBe('Owner');
expect(getCheckedDropdownItem().text()).toBe('Owner');
});
describe('when dropdown item is selected', () => {
it('does nothing if the item selected was already selected', () => {
getDropdownItemByText('Owner').trigger('click');
expect(actions.updateMemberRole).not.toHaveBeenCalled();
});
it('calls `updateMemberRole` Vuex action', () => {
getDropdownItemByText('Developer').trigger('click');
expect(actions.updateMemberRole).toHaveBeenCalledWith(expect.any(Object), {
memberId: member.id,
accessLevel: { integerValue: 30, stringValue: 'Developer' },
});
});
it('displays toast when successful', async () => {
getDropdownItemByText('Developer').trigger('click');
await waitForPromises();
expect($toast.show).toHaveBeenCalledWith('Role updated successfully.');
});
it('disables dropdown while waiting for `updateMemberRole` to resolve', async () => {
getDropdownItemByText('Developer').trigger('click');
await nextTick();
expect(findDropdown().props('disabled')).toBe(true);
await waitForPromises();
expect(findDropdown().props('disabled')).toBe(false);
});
});
});
it("sets initial dropdown toggle value to member's role", () => {
createComponent();
expect(findDropdownToggle().text()).toBe('Owner');
});
it('sets the dropdown alignment to right on mobile', async () => {
jest.spyOn(bp, 'isDesktop').mockReturnValue(false);
createComponent();
await nextTick();
expect(findDropdown().props('right')).toBe(true);
});
it('sets the dropdown alignment to left on desktop', async () => {
jest.spyOn(bp, 'isDesktop').mockReturnValue(true);
createComponent();
await nextTick();
expect(findDropdown().props('right')).toBe(false);
});
});