Commit 0c033a97 authored by Vitaly Slobodin's avatar Vitaly Slobodin

Merge branch '344104-project-feature-gl-toggle-create' into 'master'

Migrate create protected branch form to GlToggle

See merge request gitlab-org/gitlab!80548
parents 0bb0b3b6 66ed251b
......@@ -5,6 +5,7 @@ import AccessorUtilities from '~/lib/utils/accessor';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import AccessDropdown from '~/projects/settings/access_dropdown';
import { initToggle } from '~/toggles';
import { ACCESS_LEVELS, LEVEL_TYPES } from './constants';
export default class ProtectedBranchCreate {
......@@ -15,25 +16,18 @@ export default class ProtectedBranchCreate {
this.isLocalStorageAvailable = AccessorUtilities.canUseLocalStorage();
this.currentProjectUserDefaults = {};
this.buildDropdowns();
this.$forcePushToggle = this.$form.find('.js-force-push-toggle');
this.$codeOwnerToggle = this.$form.find('.js-code-owner-toggle');
this.bindEvents();
}
bindEvents() {
this.$forcePushToggle.on('click', this.onForcePushToggleClick.bind(this));
this.forcePushToggle = initToggle(document.querySelector('.js-force-push-toggle'));
if (this.hasLicense) {
this.$codeOwnerToggle.on('click', this.onCodeOwnerToggleClick.bind(this));
this.codeOwnerToggle = initToggle(document.querySelector('.js-code-owner-toggle'));
}
this.$form.on('submit', this.onFormSubmit.bind(this));
}
onForcePushToggleClick() {
this.$forcePushToggle.toggleClass('is-checked');
this.bindEvents();
}
onCodeOwnerToggleClick() {
this.$codeOwnerToggle.toggleClass('is-checked');
bindEvents() {
this.$form.on('submit', this.onFormSubmit.bind(this));
}
buildDropdowns() {
......@@ -92,8 +86,8 @@ export default class ProtectedBranchCreate {
authenticity_token: this.$form.find('input[name="authenticity_token"]').val(),
protected_branch: {
name: this.$form.find('input[name="protected_branch[name]"]').val(),
allow_force_push: this.$forcePushToggle.hasClass('is-checked'),
code_owner_approval_required: this.$codeOwnerToggle.hasClass('is-checked'),
allow_force_push: this.forcePushToggle.value,
code_owner_approval_required: this.codeOwnerToggle?.value ?? false,
},
};
......
......@@ -24,8 +24,10 @@
.form-group.row
= f.label :allow_force_push, s_("ProtectedBranch|Allowed to force push:"), class: 'col-md-2 gl-text-left text-md-right'
.col-md-10
= render "shared/buttons/project_feature_toggle", class_list: "js-force-push-toggle project-feature-toggle"
.form-text.gl-text-gray-600.gl-mt-0
= render "shared/gl_toggle",
classes: 'js-force-push-toggle',
label: s_("ProtectedBranch|Allowed to force push"),
label_position: 'hidden' do
- force_push_docs_url = help_page_url('topics/git/git_rebase', anchor: 'force-push')
- force_push_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: force_push_docs_url }
= (s_("ProtectedBranch|Allow all users with push access to %{tag_start}force push%{tag_end}.") % { tag_start: force_push_link_start, tag_end: '</a>' }).html_safe
......
......@@ -2,6 +2,9 @@
.form-group.row
= f.label :code_owner_approval_required, s_("ProtectedBranch|Require approval from code owners:"), class: 'col-md-2 text-left text-md-right'
.col-md-10
= render "shared/buttons/project_feature_toggle", label: s_("ProtectedBranch|Toggle code owner approval"), class_list: "js-code-owner-toggle project-feature-toggle is-checked"
.form-text.text-muted
= s_("ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file.")
= render "shared/gl_toggle",
classes: 'js-code-owner-toggle',
label: s_("ProtectedBranch|Toggle code owner approval"),
is_checked: true,
help: s_("ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."),
label_position: 'hidden'
......@@ -21,7 +21,7 @@ RSpec.describe 'Protected Branches', :js do
describe 'protect a branch form' do
let!(:protected_branch) { create(:protected_branch, project: project) }
let(:container) { page.find('#new_protected_branch') }
let(:code_owner_toggle) { container.find('.js-code-owner-toggle') }
let(:code_owner_toggle) { container.find('.js-code-owner-toggle').find('button') }
let(:branch_input) { container.find('.js-protected-branch-select') }
let(:allowed_to_merge_input) { container.find('.js-allowed-to-merge') }
let(:allowed_to_push) { container.find('.js-allowed-to-push') }
......
import ProtectedBranchCreate from '~/protected_branches/protected_branch_create';
const FORCE_PUSH_TOGGLE_TESTID = 'force-push-toggle';
const CODE_OWNER_TOGGLE_TESTID = 'code-owner-toggle';
const IS_CHECKED_CLASS = 'is-checked';
const IS_DISABLED_CLASS = 'is-disabled';
const IS_LOADING_CLASS = 'toggle-loading';
describe('ProtectedBranchCreate', () => {
beforeEach(() => {
jest.spyOn(ProtectedBranchCreate.prototype, 'buildDropdowns').mockImplementation();
});
const findForcePushToggle = () =>
document.querySelector(`div[data-testid="${FORCE_PUSH_TOGGLE_TESTID}"] button`);
const findCodeOwnerToggle = () =>
document.querySelector(`div[data-testid="${CODE_OWNER_TOGGLE_TESTID}"] button`);
const create = ({
forcePushToggleChecked = false,
codeOwnerToggleChecked = false,
hasLicense = true,
} = {}) => {
setFixtures(`
<form class="js-new-protected-branch">
<span
class="js-force-push-toggle"
data-label="Toggle allowed to force push"
data-is-checked="${forcePushToggleChecked}"
data-testid="${FORCE_PUSH_TOGGLE_TESTID}"></span>
<span
class="js-code-owner-toggle"
data-label="Toggle code owner approval"
data-is-checked="${codeOwnerToggleChecked}"
data-testid="${CODE_OWNER_TOGGLE_TESTID}"></span>
<input type="submit" />
</form>
`);
return new ProtectedBranchCreate({ hasLicense });
};
describe('when license supports code owner approvals', () => {
it('instantiates the code owner toggle', () => {
create();
expect(findCodeOwnerToggle()).not.toBe(null);
});
});
describe('when license does not support code owner approvals', () => {
it('does not instantiate the code owner toggle', () => {
create({ hasLicense: false });
expect(findCodeOwnerToggle()).toBe(null);
});
});
describe.each`
description | checkedOption | finder
${'force push'} | ${'forcePushToggleChecked'} | ${findForcePushToggle}
${'code owner'} | ${'codeOwnerToggleChecked'} | ${findCodeOwnerToggle}
`('when unchecked $description toggle button', ({ checkedOption, finder }) => {
it('is not changed', () => {
create({ [checkedOption]: false });
const toggle = finder();
expect(toggle).not.toHaveClass(IS_CHECKED_CLASS);
expect(toggle.querySelector(`.${IS_LOADING_CLASS}`)).toBe(null);
expect(toggle).not.toHaveClass(IS_DISABLED_CLASS);
});
});
describe('form data', () => {
let protectedBranchCreate;
beforeEach(() => {
protectedBranchCreate = create({
forcePushToggleChecked: false,
codeOwnerToggleChecked: true,
});
// Mock access levels. This should probably be improved in future iterations.
protectedBranchCreate.merge_access_levels_dropdown = {
getSelectedItems: () => [],
};
protectedBranchCreate.push_access_levels_dropdown = {
getSelectedItems: () => [],
};
});
afterEach(() => {
protectedBranchCreate = null;
});
it('returns the default form data if toggles are untouched', () => {
expect(protectedBranchCreate.getFormData().protected_branch).toMatchObject({
allow_force_push: false,
code_owner_approval_required: true,
});
});
it('reflects toggles changes if any', () => {
findForcePushToggle().click();
findCodeOwnerToggle().click();
expect(protectedBranchCreate.getFormData().protected_branch).toMatchObject({
allow_force_push: true,
code_owner_approval_required: false,
});
});
});
});
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