Commit 7c885d0c authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '335962-add-a-locked-state-to-approval-checkbox' into 'master'

Add a locked state to approval settings checkbox

See merge request gitlab-org/gitlab!66450
parents b6eeb4a9 4be82295
<script> <script>
import { GlFormCheckbox, GlIcon, GlLink } from '@gitlab/ui'; import { GlFormCheckbox, GlIcon, GlLink, GlPopover } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper'; import { helpPagePath } from '~/helpers/help_page_helper';
import { slugify } from '~/lib/utils/text_utility';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { APPROVALS_HELP_PATH } from '../constants'; import { APPROVALS_HELP_PATH } from '../constants';
...@@ -9,6 +10,7 @@ export default { ...@@ -9,6 +10,7 @@ export default {
GlFormCheckbox, GlFormCheckbox,
GlIcon, GlIcon,
GlLink, GlLink,
GlPopover,
}, },
props: { props: {
label: { label: {
...@@ -24,11 +26,24 @@ export default { ...@@ -24,11 +26,24 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
locked: {
type: Boolean,
required: false,
default: false,
},
lockedText: {
type: String,
required: false,
default: '',
},
}, },
computed: { computed: {
href() { href() {
return helpPagePath(APPROVALS_HELP_PATH, { anchor: this.anchor }); return helpPagePath(APPROVALS_HELP_PATH, { anchor: this.anchor });
}, },
lockIconId() {
return `approval-settings-checkbox-lock-icon-${slugify(this.label)}`;
},
}, },
methods: { methods: {
input(value) { input(value) {
...@@ -37,15 +52,32 @@ export default { ...@@ -37,15 +52,32 @@ export default {
}, },
i18n: { i18n: {
helpLabel: __('Help'), helpLabel: __('Help'),
lockIconTitle: __('Setting enforced'),
}, },
}; };
</script> </script>
<template> <template>
<gl-form-checkbox :checked="value" @input="input"> <gl-form-checkbox :disabled="locked" :checked="value" @input="input">
{{ label }} {{ label }}
<template v-if="locked">
<gl-icon :id="lockIconId" data-testid="lock-icon" name="lock" />
<gl-popover
:target="lockIconId"
container="viewport"
placement="top"
:title="$options.i18n.lockIconTitle"
triggers="hover focus"
:content="lockedText"
/>
</template>
<gl-link :href="href" target="_blank"> <gl-link :href="href" target="_blank">
<gl-icon name="question-o" :aria-label="$options.i18n.helpLabel" :size="16" /> <gl-icon
data-testid="help-icon"
name="question-o"
:aria-label="$options.i18n.helpLabel"
:size="16"
/>
</gl-link> </gl-link>
</gl-form-checkbox> </gl-form-checkbox>
</template> </template>
import { GlFormCheckbox, GlIcon, GlLink } from '@gitlab/ui'; import { GlFormCheckbox, GlIcon, GlLink, GlPopover } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import ApprovalSettingsCheckbox from 'ee/approvals/components/approval_settings_checkbox.vue'; import ApprovalSettingsCheckbox from 'ee/approvals/components/approval_settings_checkbox.vue';
import { APPROVALS_HELP_PATH } from 'ee/approvals/constants'; import { APPROVALS_HELP_PATH } from 'ee/approvals/constants';
import { stubComponent } from 'helpers/stub_component'; import { stubComponent } from 'helpers/stub_component';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { slugify } from '~/lib/utils/text_utility';
describe('ApprovalSettingsCheckbox', () => { describe('ApprovalSettingsCheckbox', () => {
const label = 'Foo'; const label = 'Foo';
const anchor = 'bar-baz'; const anchor = 'bar-baz';
const lockIconId = `approval-settings-checkbox-lock-icon-${slugify(label)}`;
let wrapper; let wrapper;
const createWrapper = (props = {}) => { const createWrapper = (props = {}) => {
wrapper = shallowMount(ApprovalSettingsCheckbox, { wrapper = extendedWrapper(
propsData: { label, anchor, ...props }, shallowMount(ApprovalSettingsCheckbox, {
stubs: { propsData: { label, anchor, ...props },
GlFormCheckbox: stubComponent(GlFormCheckbox, { stubs: {
props: ['checked'], GlFormCheckbox: stubComponent(GlFormCheckbox, {
}), props: ['checked'],
GlIcon, }),
GlLink, GlIcon,
}, GlLink,
}); },
}),
);
}; };
const findCheckbox = () => wrapper.findComponent(GlFormCheckbox); const findCheckbox = () => wrapper.findComponent(GlFormCheckbox);
const findIcon = () => wrapper.findComponent(GlIcon);
const findLink = () => wrapper.findComponent(GlLink); const findLink = () => wrapper.findComponent(GlLink);
const findPopover = () => wrapper.findComponent(GlPopover);
const findLockIcon = () => wrapper.findByTestId('lock-icon');
const findHelpIcon = () => wrapper.findByTestId('help-icon');
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
...@@ -45,8 +52,8 @@ describe('ApprovalSettingsCheckbox', () => { ...@@ -45,8 +52,8 @@ describe('ApprovalSettingsCheckbox', () => {
expect(findLink().attributes('href')).toBe(`/help/${APPROVALS_HELP_PATH}#${anchor}`); expect(findLink().attributes('href')).toBe(`/help/${APPROVALS_HELP_PATH}#${anchor}`);
}); });
it('shows the icon', () => { it('shows a help icon', () => {
expect(findIcon().props('name')).toBe('question-o'); expect(findHelpIcon().props('name')).toBe('question-o');
}); });
}); });
...@@ -71,4 +78,63 @@ describe('ApprovalSettingsCheckbox', () => { ...@@ -71,4 +78,63 @@ describe('ApprovalSettingsCheckbox', () => {
expect(wrapper.emitted('input')[0]).toStrictEqual([true]); expect(wrapper.emitted('input')[0]).toStrictEqual([true]);
}); });
}); });
describe('locked', () => {
describe('when the setting is not locked', () => {
beforeEach(() => {
createWrapper();
});
it('does not render a lock icon', () => {
expect(findLockIcon().exists()).toBe(false);
});
it('does not render a popover', () => {
expect(findPopover().exists()).toBe(false);
});
it('the input is enabled', () => {
expect(findCheckbox().attributes('disabled')).toBeUndefined();
});
});
describe('when the setting is locked', () => {
beforeEach(() => {
createWrapper({ locked: true });
});
it('disables the input', () => {
expect(findCheckbox().attributes('disabled')).toBe('disabled');
});
it('shows a lock icon', () => {
expect(findLockIcon().props('name')).toBe('lock');
expect(findLockIcon().attributes('id')).toBe(lockIconId);
});
it('shows a popover for the lock icon', () => {
expect(findPopover().props('target')).toBe(lockIconId);
});
it('configures how and when the popover should show', () => {
expect(findPopover().props()).toMatchObject({
title: 'Setting enforced',
triggers: 'hover focus',
placement: 'top',
container: 'viewport',
});
});
it('when lockedText is set, then the popover content matches the lockedText', () => {
const lockedText = 'Admin';
createWrapper({ locked: true, lockedText });
expect(findPopover().attributes('content')).toBe(lockedText);
});
it('when lockedText is not set, then the popover content is empty', () => {
expect(findPopover().attributes('content')).toBe('');
});
});
});
}); });
...@@ -29969,6 +29969,9 @@ msgstr "" ...@@ -29969,6 +29969,9 @@ msgstr ""
msgid "Setting" msgid "Setting"
msgstr "" msgstr ""
msgid "Setting enforced"
msgstr ""
msgid "Setting this to 0 means using the system default timeout value." msgid "Setting this to 0 means using the system default timeout value."
msgstr "" msgstr ""
......
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