gitlab-ce/spec/frontend/token_access/policies_selector_spec.js

188 lines
6.8 KiB
JavaScript

import { GlTableLite, GlFormRadio, GlFormRadioGroup, GlCollapsibleListbox } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import PoliciesSelector, { TABLE_FIELDS } from '~/token_access/components/policies_selector.vue';
import { stubComponent } from 'helpers/stub_component';
import { POLICIES_BY_RESOURCE, RESOURCE_JOBS, RESOURCE_RELEASES } from '~/token_access/constants';
describe('Policies selector component', () => {
let wrapper;
const createWrapper = ({
isDefaultPermissionsSelected = false,
jobTokenPolicies = [],
disabled = false,
stubs = {},
} = {}) => {
wrapper = mountExtended(PoliciesSelector, {
propsData: { isDefaultPermissionsSelected, jobTokenPolicies, disabled },
stubs,
});
return waitForPromises();
};
const findTable = () => wrapper.findComponent(GlTableLite);
const findRadioGroup = () => wrapper.findComponent(GlFormRadioGroup);
const findDefaultRadio = () => wrapper.findByTestId('default-radio');
const findFineGrainedRadio = () => wrapper.findByTestId('fine-grained-radio');
const getResourceIndex = (item) =>
POLICIES_BY_RESOURCE.map(({ resource }) => resource).indexOf(item);
const findNameForResource = (resource) =>
findTable().findAll('tbody tr').at(getResourceIndex(resource)).findAll('td').at(0);
const findPolicyDropdownForResource = (resource) =>
wrapper.findAllComponents(GlCollapsibleListbox).at(getResourceIndex(resource));
describe('permission type radio options', () => {
beforeEach(() =>
createWrapper({
stubs: {
GlFormRadioGroup: stubComponent(GlFormRadioGroup, { props: ['checked'] }),
GlFormRadio: stubComponent(GlFormRadio, {
template: '<div><slot></slot><slot name="help"></slot></div>',
props: ['value'],
}),
},
}),
);
describe('radio group', () => {
it('shows radio group', () => {
expect(findRadioGroup().exists()).toBe(true);
});
it.each`
name | isDefaultPermissionsSelected
${'default'} | ${true}
${'fine-grained'} | ${false}
`(
'selects the $name option when the isDefaultPermissionsSelected prop is $isDefaultPermissionsSelected',
async ({ isDefaultPermissionsSelected }) => {
await wrapper.setProps({ isDefaultPermissionsSelected });
expect(findRadioGroup().props('checked')).toBe(isDefaultPermissionsSelected);
},
);
it.each`
name | isDefaultPermissionsSelected
${'default'} | ${true}
${'fine-grained'} | ${false}
`(
'emits update:isDefaultPermissionsSelected event with $isDefaultPermissionsSelected when $name is selected',
({ isDefaultPermissionsSelected }) => {
findRadioGroup().vm.$emit('change', isDefaultPermissionsSelected);
expect(wrapper.emitted('update:isDefaultPermissionsSelected')[0][0]).toEqual(
isDefaultPermissionsSelected,
);
},
);
});
it.each`
name | value | findRadio | expectedText
${'default'} | ${true} | ${findDefaultRadio} | ${'Default permissions Use the standard permissions model based on user membership and roles.'}
${'fine-grained'} | ${false} | ${findFineGrainedRadio} | ${'Fine-grained permissions Apply permissions that grant access to individual resources.'}
`('shows the $name radio', ({ value, findRadio, expectedText }) => {
expect(findRadio().text()).toMatchInterpolatedText(expectedText);
expect(findRadio().props('value')).toBe(value);
});
});
describe('when Default permissions is selected', () => {
beforeEach(() => createWrapper({ isDefaultPermissionsSelected: true }));
it('does not show policies table', () => {
expect(findTable().exists()).toBe(false);
});
});
describe('when Fine-grained permissions is selected', () => {
beforeEach(() => {
createWrapper({
stubs: { GlTableLite: stubComponent(GlTableLite, { props: ['fields', 'items'] }) },
});
});
it('shows policies table', () => {
expect(findTable().props()).toMatchObject({
items: POLICIES_BY_RESOURCE,
fields: TABLE_FIELDS,
});
});
describe('policies table', () => {
beforeEach(() => createWrapper());
describe.each(POLICIES_BY_RESOURCE)(
'for resource $resource.text',
({ resource, policies }) => {
it('shows the resource name', () => {
expect(findNameForResource(resource).text()).toBe(resource.text);
});
it('shows the resource dropdown', () => {
expect(findPolicyDropdownForResource(resource).props('items')).toEqual(policies);
});
it.each(policies)(`emits $value policy when it is selected`, (policy) => {
const expected = policy.value ? [policy.value] : [];
findPolicyDropdownForResource(resource).vm.$emit('select', policy.value);
expect(wrapper.emitted('update:jobTokenPolicies')[0][0]).toEqual(expected);
});
},
);
describe('when multiple policies are selected across different resources', () => {
const jobTokenPolicies = ['READ_JOBS', 'ADMIN_PACKAGES'];
beforeEach(() => wrapper.setProps({ jobTokenPolicies }));
it('adds the policy when there is no policy set for the resource', () => {
findPolicyDropdownForResource(RESOURCE_RELEASES).vm.$emit('select', 'READ_RELEASES');
expect(wrapper.emitted('update:jobTokenPolicies')[0][0]).toEqual([
...jobTokenPolicies,
'READ_RELEASES',
]);
});
it('updates the policy when there is already a policy for the resource', () => {
findPolicyDropdownForResource(RESOURCE_JOBS).vm.$emit('select', 'ADMIN_JOBS');
expect(wrapper.emitted('update:jobTokenPolicies')[0][0]).toEqual([
'ADMIN_JOBS',
'ADMIN_PACKAGES',
]);
});
});
});
describe('disabled prop', () => {
describe.each([true, false])('when disabled prop is %s', (disabled) => {
beforeEach(() =>
createWrapper({
disabled,
stubs: { GlFormRadioGroup: stubComponent(GlFormRadioGroup, { props: ['disabled'] }) },
}),
);
it(`sets radio group disabled to ${disabled}`, () => {
expect(findRadioGroup().props('disabled')).toBe(disabled);
});
it(`sets all policy dropdowns disabled to ${disabled}`, () => {
wrapper.findAllComponents(GlCollapsibleListbox).wrappers.forEach((dropdown) => {
expect(dropdown.props('disabled')).toBe(disabled);
});
});
});
});
});
});