Commit 948e03df authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch 'cngo-migrate-project-settings-to-use-gl-toggle' into 'master'

Migrate project settings to use GlToggle

See merge request gitlab-org/gitlab!52729
parents fd226bfa 348f987b
<script> <script>
import { GlIcon } from '@gitlab/ui'; import { GlIcon, GlToggle } from '@gitlab/ui';
import projectFeatureToggle from '~/vue_shared/components/toggle_button.vue';
import { featureAccessLevelNone } from '../constants'; import { featureAccessLevelNone } from '../constants';
export default { export default {
components: { components: {
GlIcon, GlIcon,
projectFeatureToggle, GlToggle,
}, },
model: { model: {
prop: 'value', prop: 'value',
...@@ -78,11 +77,11 @@ export default { ...@@ -78,11 +77,11 @@ export default {
class="project-feature-controls gl-display-flex gl-align-items-center gl-my-3 gl-mx-0" class="project-feature-controls gl-display-flex gl-align-items-center gl-my-3 gl-mx-0"
> >
<input v-if="name" :name="name" :value="value" type="hidden" /> <input v-if="name" :name="name" :value="value" type="hidden" />
<project-feature-toggle <gl-toggle
v-if="showToggle" v-if="showToggle"
class="gl-flex-grow-0 gl-mr-3" class="gl-mr-3"
:value="featureEnabled" :value="featureEnabled"
:disabled-input="disabledInput" :disabled="disabledInput"
@change="toggleFeature" @change="toggleFeature"
/> />
<div class="select-wrapper gl-flex-fill-1"> <div class="select-wrapper gl-flex-fill-1">
......
<script> <script>
import { GlIcon, GlSprintf, GlLink, GlFormCheckbox } from '@gitlab/ui'; import { GlIcon, GlSprintf, GlLink, GlFormCheckbox, GlToggle } from '@gitlab/ui';
import settingsMixin from 'ee_else_ce/pages/projects/shared/permissions/mixins/settings_pannel_mixin'; import settingsMixin from 'ee_else_ce/pages/projects/shared/permissions/mixins/settings_pannel_mixin';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import projectFeatureToggle from '~/vue_shared/components/toggle_button.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { import {
visibilityOptions, visibilityOptions,
...@@ -22,12 +21,12 @@ const PAGE_FEATURE_ACCESS_LEVEL = s__('ProjectSettings|Everyone'); ...@@ -22,12 +21,12 @@ const PAGE_FEATURE_ACCESS_LEVEL = s__('ProjectSettings|Everyone');
export default { export default {
components: { components: {
projectFeatureSetting, projectFeatureSetting,
projectFeatureToggle,
projectSettingRow, projectSettingRow,
GlIcon, GlIcon,
GlSprintf, GlSprintf,
GlLink, GlLink,
GlFormCheckbox, GlFormCheckbox,
GlToggle,
}, },
mixins: [settingsMixin, glFeatureFlagsMixin()], mixins: [settingsMixin, glFeatureFlagsMixin()],
...@@ -483,9 +482,10 @@ export default { ...@@ -483,9 +482,10 @@ export default {
) )
}} }}
</div> </div>
<project-feature-toggle <gl-toggle
v-model="containerRegistryEnabled" v-model="containerRegistryEnabled"
:disabled-input="!repositoryEnabled" class="gl-my-2"
:disabled="!repositoryEnabled"
name="project[container_registry_enabled]" name="project[container_registry_enabled]"
/> />
</project-setting-row> </project-setting-row>
...@@ -498,9 +498,10 @@ export default { ...@@ -498,9 +498,10 @@ export default {
s__('ProjectSettings|Manages large files such as audio, video, and graphics files.') s__('ProjectSettings|Manages large files such as audio, video, and graphics files.')
" "
> >
<project-feature-toggle <gl-toggle
v-model="lfsEnabled" v-model="lfsEnabled"
:disabled-input="!repositoryEnabled" class="gl-my-2"
:disabled="!repositoryEnabled"
name="project[lfs_enabled]" name="project[lfs_enabled]"
/> />
<p v-if="!lfsEnabled && lfsObjectsExist"> <p v-if="!lfsEnabled && lfsObjectsExist">
...@@ -530,9 +531,10 @@ export default { ...@@ -530,9 +531,10 @@ export default {
s__('ProjectSettings|Every project can have its own space to store its packages.') s__('ProjectSettings|Every project can have its own space to store its packages.')
" "
> >
<project-feature-toggle <gl-toggle
v-model="packagesEnabled" v-model="packagesEnabled"
:disabled-input="!repositoryEnabled" class="gl-my-2"
:disabled="!repositoryEnabled"
name="project[packages_enabled]" name="project[packages_enabled]"
/> />
</project-setting-row> </project-setting-row>
......
---
title: Migrate project settings to use GlToggle
merge_request: 52729
author:
type: changed
...@@ -22,7 +22,7 @@ RSpec.describe 'Project settings > Issues', :js do ...@@ -22,7 +22,7 @@ RSpec.describe 'Project settings > Issues', :js do
expect(page).to have_content('Set a default description template to be used for new issues.') expect(page).to have_content('Set a default description template to be used for new issues.')
within('.sharing-permissions-form') do within('.sharing-permissions-form') do
find('.project-feature-controls[data-for="project[project_feature_attributes][issues_access_level]"] .project-feature-toggle').click find('.project-feature-controls[data-for="project[project_feature_attributes][issues_access_level]"] .gl-toggle').click
click_on('Save changes') click_on('Save changes')
end end
...@@ -41,7 +41,7 @@ RSpec.describe 'Project settings > Issues', :js do ...@@ -41,7 +41,7 @@ RSpec.describe 'Project settings > Issues', :js do
expect(page).not_to have_content('Set a default description template to be used for new issues.') expect(page).not_to have_content('Set a default description template to be used for new issues.')
within('.sharing-permissions-form') do within('.sharing-permissions-form') do
find('.project-feature-controls[data-for="project[project_feature_attributes][issues_access_level]"] .project-feature-toggle').click find('.project-feature-controls[data-for="project[project_feature_attributes][issues_access_level]"] .gl-toggle').click
click_on('Save changes') click_on('Save changes')
end end
......
...@@ -187,7 +187,7 @@ RSpec.describe 'Edit Project Settings' do ...@@ -187,7 +187,7 @@ RSpec.describe 'Edit Project Settings' do
click_button "Save changes" click_button "Save changes"
end end
expect(find(".sharing-permissions")).to have_selector(".project-feature-toggle.is-disabled", count: 4) expect(find(".sharing-permissions")).to have_selector(".gl-toggle.is-disabled", minimum: 4)
end end
it "shows empty features project homepage" do it "shows empty features project homepage" do
...@@ -282,10 +282,10 @@ RSpec.describe 'Edit Project Settings' do ...@@ -282,10 +282,10 @@ RSpec.describe 'Edit Project Settings' do
end end
def toggle_feature_off(feature_name) def toggle_feature_off(feature_name)
find(".project-feature-controls[data-for=\"#{feature_name}\"] .project-feature-toggle.is-checked").click find(".project-feature-controls[data-for=\"#{feature_name}\"] .gl-toggle.is-checked").click
end end
def toggle_feature_on(feature_name) def toggle_feature_on(feature_name)
find(".project-feature-controls[data-for=\"#{feature_name}\"] .project-feature-toggle:not(.is-checked)").click find(".project-feature-controls[data-for=\"#{feature_name}\"] .gl-toggle:not(.is-checked)").click
end end
end end
...@@ -39,7 +39,7 @@ RSpec.describe 'Projects settings' do ...@@ -39,7 +39,7 @@ RSpec.describe 'Projects settings' do
visit edit_project_path(project) visit edit_project_path(project)
forking_enabled_input = find('input[name="project[project_feature_attributes][forking_access_level]"]', visible: :hidden) forking_enabled_input = find('input[name="project[project_feature_attributes][forking_access_level]"]', visible: :hidden)
forking_enabled_button = find('input[name="project[project_feature_attributes][forking_access_level]"] + label > button') forking_enabled_button = find('[data-for="project[project_feature_attributes][forking_access_level]"] .gl-toggle')
expect(forking_enabled_input.value).to eq('20') expect(forking_enabled_input.value).to eq('20')
......
...@@ -51,7 +51,7 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do ...@@ -51,7 +51,7 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do
expect(page).to have_content 'All discussions must be resolved' expect(page).to have_content 'All discussions must be resolved'
within('.sharing-permissions-form') do within('.sharing-permissions-form') do
find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .gl-toggle').click
find('input[value="Save changes"]').send_keys(:return) find('input[value="Save changes"]').send_keys(:return)
end end
...@@ -71,7 +71,7 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do ...@@ -71,7 +71,7 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do
expect(page).to have_content 'All discussions must be resolved' expect(page).to have_content 'All discussions must be resolved'
within('.sharing-permissions-form') do within('.sharing-permissions-form') do
find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .project-feature-toggle').click find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .gl-toggle').click
find('input[value="Save changes"]').send_keys(:return) find('input[value="Save changes"]').send_keys(:return)
end end
...@@ -92,7 +92,7 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do ...@@ -92,7 +92,7 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do
expect(page).not_to have_content 'All discussions must be resolved' expect(page).not_to have_content 'All discussions must be resolved'
within('.sharing-permissions-form') do within('.sharing-permissions-form') do
find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .gl-toggle').click
find('input[value="Save changes"]').send_keys(:return) find('input[value="Save changes"]').send_keys(:return)
end end
......
...@@ -30,7 +30,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do ...@@ -30,7 +30,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do
context 'merge requests select' do context 'merge requests select' do
it 'hides merge requests section' do it 'hides merge requests section' do
find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .gl-toggle').click
expect(page).to have_selector('.merge-requests-feature', visible: false) expect(page).to have_selector('.merge-requests-feature', visible: false)
end end
...@@ -46,7 +46,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do ...@@ -46,7 +46,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do
context 'builds select' do context 'builds select' do
it 'hides builds select section' do it 'hides builds select section' do
find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .project-feature-toggle').click find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .gl-toggle').click
expect(page).to have_selector('.builds-feature', visible: false) expect(page).to have_selector('.builds-feature', visible: false)
end end
......
import { mount, shallowMount } from '@vue/test-utils'; import { GlToggle } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import projectFeatureSetting from '~/pages/projects/shared/permissions/components/project_feature_setting.vue'; import ProjectFeatureSetting from '~/pages/projects/shared/permissions/components/project_feature_setting.vue';
import projectFeatureToggle from '~/vue_shared/components/toggle_button.vue';
describe('Project Feature Settings', () => { describe('Project Feature Settings', () => {
const defaultProps = { const defaultProps = {
...@@ -19,81 +18,76 @@ describe('Project Feature Settings', () => { ...@@ -19,81 +18,76 @@ describe('Project Feature Settings', () => {
}; };
let wrapper; let wrapper;
const mountComponent = (customProps) => { const findHiddenInput = () => wrapper.find(`input[name=${defaultProps.name}]`);
const propsData = { ...defaultProps, ...customProps }; const findToggle = () => wrapper.findComponent(GlToggle);
return shallowMount(projectFeatureSetting, { propsData });
};
beforeEach(() => { const mountComponent = (customProps = {}) =>
wrapper = mountComponent(); shallowMount(ProjectFeatureSetting, {
}); propsData: {
...defaultProps,
...customProps,
},
});
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null;
}); });
describe('Hidden name input', () => { describe('Hidden name input', () => {
it('should set the hidden name input if the name exists', () => { it('should set the hidden name input if the name exists', () => {
expect(wrapper.find(`input[name=${defaultProps.name}]`).attributes().value).toBe('1'); wrapper = mountComponent();
expect(findHiddenInput().attributes('value')).toBe('1');
}); });
it('should not set the hidden name input if the name does not exist', () => { it('should not set the hidden name input if the name does not exist', () => {
wrapper.setProps({ name: null }); wrapper = mountComponent({ name: null });
return wrapper.vm.$nextTick(() => { expect(findHiddenInput().exists()).toBe(false);
expect(wrapper.find(`input[name=${defaultProps.name}]`).exists()).toBe(false);
});
}); });
}); });
describe('Feature toggle', () => { describe('Feature toggle', () => {
it('should be hidden if "showToggle" is passed false', async () => { it('should be hidden if "showToggle" is passed false', () => {
wrapper.setProps({ showToggle: false }); wrapper = mountComponent({ showToggle: false });
await wrapper.vm.$nextTick();
expect(wrapper.find(projectFeatureToggle).element).toBeUndefined(); expect(findToggle().exists()).toBe(false);
}); });
it('should enable the feature toggle if the value is not 0', () => { it('should enable the feature toggle if the value is not 0', () => {
expect(wrapper.find(projectFeatureToggle).props().value).toBe(true); wrapper = mountComponent();
expect(findToggle().props('value')).toBe(true);
}); });
it('should enable the feature toggle if the value is less than 0', () => { it('should enable the feature toggle if the value is less than 0', () => {
wrapper.setProps({ value: -1 }); wrapper = mountComponent({ value: -1 });
return wrapper.vm.$nextTick(() => { expect(findToggle().props('value')).toBe(true);
expect(wrapper.find(projectFeatureToggle).props().value).toBe(true);
});
}); });
it('should disable the feature toggle if the value is 0', () => { it('should disable the feature toggle if the value is 0', () => {
wrapper.setProps({ value: 0 }); wrapper = mountComponent({ value: 0 });
return wrapper.vm.$nextTick(() => { expect(findToggle().props('value')).toBe(false);
expect(wrapper.find(projectFeatureToggle).props().value).toBe(false);
});
}); });
it('should disable the feature toggle if disabledInput is set', () => { it('should disable the feature toggle if disabledInput is set', () => {
wrapper.setProps({ disabledInput: true }); wrapper = mountComponent({ disabledInput: true });
return wrapper.vm.$nextTick(() => { expect(findToggle().props('disabled')).toBe(true);
expect(wrapper.find(projectFeatureToggle).props().disabledInput).toBe(true);
});
}); });
it('should emit a change event when the feature toggle changes', () => { it('should emit a change event when the feature toggle changes', () => {
// Needs to be fully mounted to be able to trigger the click event on the internal button wrapper = mountComponent({ propsData: defaultProps });
wrapper = mount(projectFeatureSetting, { propsData: defaultProps });
expect(wrapper.emitted('change')).toBeUndefined();
expect(wrapper.emitted().change).toBeUndefined(); findToggle().vm.$emit('change', false);
wrapper.find(projectFeatureToggle).find('button').trigger('click');
return wrapper.vm.$nextTick().then(() => { expect(wrapper.emitted('change')).toHaveLength(1);
expect(wrapper.emitted().change.length).toBe(1); expect(wrapper.emitted('change')[0]).toEqual([0]);
expect(wrapper.emitted().change[0]).toEqual([0]);
});
}); });
}); });
...@@ -108,26 +102,23 @@ describe('Project Feature Settings', () => { ...@@ -108,26 +102,23 @@ describe('Project Feature Settings', () => {
`( `(
'should set disabled to $isDisabled when disabledInput is $disabledInput, the value is $value and options are $options', 'should set disabled to $isDisabled when disabledInput is $disabledInput, the value is $value and options are $options',
({ disabledInput, value, options, isDisabled }) => { ({ disabledInput, value, options, isDisabled }) => {
wrapper.setProps({ disabledInput, value, options }); wrapper = mountComponent({ disabledInput, value, options });
return wrapper.vm.$nextTick(() => { const expected = isDisabled ? 'disabled' : undefined;
if (isDisabled) {
expect(wrapper.find('select').attributes().disabled).toEqual('disabled'); expect(wrapper.find('select').attributes('disabled')).toBe(expected);
} else {
expect(wrapper.find('select').attributes().disabled).toBeUndefined();
}
});
}, },
); );
it('should emit the change when a new option is selected', () => { it('should emit the change when a new option is selected', () => {
expect(wrapper.emitted().change).toBeUndefined(); wrapper = mountComponent();
expect(wrapper.emitted('change')).toBeUndefined();
wrapper.findAll('option').at(1).trigger('change'); wrapper.findAll('option').at(1).trigger('change');
return wrapper.vm.$nextTick().then(() => { expect(wrapper.emitted('change')).toHaveLength(1);
expect(wrapper.emitted().change.length).toBe(1); expect(wrapper.emitted('change')[0]).toEqual([2]);
expect(wrapper.emitted().change[0]).toEqual([2]);
});
}); });
}); });
}); });
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