Commit 10ac75d0 authored by Jacques Erasmus's avatar Jacques Erasmus

Merge branch '335743-delete-blob-validation' into 'master'

Add validation to delete blob modal

See merge request gitlab-org/gitlab!66585
parents 3912dd1b 3257efbd
......@@ -2,6 +2,7 @@
import { GlModal, GlFormGroup, GlFormInput, GlFormTextarea, GlToggle, GlForm } from '@gitlab/ui';
import csrf from '~/lib/utils/csrf';
import { __ } from '~/locale';
import validation from '~/vue_shared/directives/validation';
import {
SECONDARY_OPTIONS_TEXT,
COMMIT_LABEL,
......@@ -9,6 +10,13 @@ import {
TOGGLE_CREATE_MR_LABEL,
} from '../constants';
const initFormField = ({ value, required = true, skipValidation = false }) => ({
value,
required,
state: skipValidation ? true : null,
feedback: null,
});
export default {
csrf,
components: {
......@@ -26,6 +34,9 @@ export default {
TARGET_BRANCH_LABEL,
TOGGLE_CREATE_MR_LABEL,
},
directives: {
validation: validation(),
},
props: {
modalId: {
type: String,
......@@ -61,12 +72,20 @@ export default {
},
},
data() {
const form = {
state: false,
showValidation: false,
fields: {
// fields key must match case of form name for validation directive to work
commit_message: initFormField({ value: this.commitMessage }),
branch_name: initFormField({ value: this.targetBranch }),
},
};
return {
loading: false,
commit: this.commitMessage,
target: this.targetBranch,
createNewMr: true,
error: '',
form,
};
},
computed: {
......@@ -77,7 +96,7 @@ export default {
{
variant: 'danger',
loading: this.loading,
disabled: !this.formCompleted || this.loading,
disabled: this.loading || !this.form.state,
},
],
};
......@@ -92,17 +111,26 @@ export default {
],
};
},
/* eslint-disable dot-notation */
showCreateNewMrToggle() {
return this.canPushCode && this.target !== this.originalBranch;
return this.canPushCode && this.form.fields['branch_name'].value !== this.originalBranch;
},
formCompleted() {
return this.commit && this.target;
return this.form.fields['commit_message'].value && this.form.fields['branch_name'].value;
},
/* eslint-enable dot-notation */
},
methods: {
submitForm(e) {
e.preventDefault(); // Prevent modal from closing
this.form.showValidation = true;
if (!this.form.state) {
return;
}
this.loading = true;
this.form.showValidation = false;
this.$refs.form.$el.submit();
},
},
......@@ -119,7 +147,7 @@ export default {
:action-cancel="cancelOptions"
@primary="submitForm"
>
<gl-form ref="form" :action="deletePath" method="post">
<gl-form ref="form" novalidate :action="deletePath" method="post">
<input type="hidden" name="_method" value="delete" />
<input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
<template v-if="emptyRepo">
......@@ -132,15 +160,34 @@ export default {
<!-- Once "push to branch" permission is made available, will need to add to conditional
Follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/335462 -->
<input v-if="createNewMr" type="hidden" name="create_merge_request" value="1" />
<gl-form-group :label="$options.i18n.COMMIT_LABEL" label-for="commit_message">
<gl-form-textarea v-model="commit" name="commit_message" :disabled="loading" />
<gl-form-group
:label="$options.i18n.COMMIT_LABEL"
label-for="commit_message"
:invalid-feedback="form.fields['commit_message'].feedback"
>
<gl-form-textarea
v-model="form.fields['commit_message'].value"
v-validation:[form.showValidation]
name="commit_message"
:state="form.fields['commit_message'].state"
:disabled="loading"
required
/>
</gl-form-group>
<gl-form-group
v-if="canPushCode"
:label="$options.i18n.TARGET_BRANCH_LABEL"
label-for="branch_name"
:invalid-feedback="form.fields['branch_name'].feedback"
>
<gl-form-input v-model="target" :disabled="loading" name="branch_name" />
<gl-form-input
v-model="form.fields['branch_name'].value"
v-validation:[form.showValidation]
:state="form.fields['branch_name'].state"
:disabled="loading"
name="branch_name"
required
/>
</gl-form-group>
<gl-toggle
v-if="showCreateNewMrToggle"
......
......@@ -37,6 +37,8 @@ describe('DeleteBlobModal', () => {
const findModal = () => wrapper.findComponent(GlModal);
const findForm = () => findModal().findComponent(GlForm);
const findCommitTextarea = () => findForm().findComponent(GlFormTextarea);
const findTargetInput = () => findForm().findComponent(GlFormInput);
afterEach(() => {
wrapper.destroy();
......@@ -65,18 +67,6 @@ describe('DeleteBlobModal', () => {
expect(findForm().attributes('action')).toBe(initialProps.deletePath);
});
it('submits the form', async () => {
createFullComponent();
await nextTick();
const submitSpy = jest.spyOn(findForm().element, 'submit');
findModal().vm.$emit('primary', { preventDefault: () => {} });
await nextTick();
expect(submitSpy).toHaveBeenCalled();
submitSpy.mockRestore();
});
it.each`
component | defaultValue | canPushCode | targetBranch | originalBranch | exist
${GlFormTextarea} | ${initialProps.commitMessage} | ${true} | ${initialProps.targetBranch} | ${initialProps.originalBranch} | ${true}
......@@ -135,4 +125,62 @@ describe('DeleteBlobModal', () => {
},
);
});
describe('form submission', () => {
let submitSpy;
beforeEach(async () => {
createFullComponent();
await nextTick();
submitSpy = jest.spyOn(findForm().element, 'submit');
});
afterEach(() => {
submitSpy.mockRestore();
});
const fillForm = async (inputValue = {}) => {
const { targetText, commitText } = inputValue;
await findTargetInput().vm.$emit('input', targetText);
await findCommitTextarea().vm.$emit('input', commitText);
};
describe('invalid form', () => {
beforeEach(async () => {
await fillForm({ targetText: '', commitText: '' });
});
it('disables submit button', async () => {
expect(findModal().props('actionPrimary').attributes[0]).toEqual(
expect.objectContaining({ disabled: true }),
);
});
it('does not submit form', async () => {
findModal().vm.$emit('primary', { preventDefault: () => {} });
expect(submitSpy).not.toHaveBeenCalled();
});
});
describe('valid form', () => {
beforeEach(async () => {
await fillForm({
targetText: 'some valid target branch',
commitText: 'some valid commit message',
});
});
it('enables submit button', async () => {
expect(findModal().props('actionPrimary').attributes[0]).toEqual(
expect.objectContaining({ disabled: false }),
);
});
it('submits form', async () => {
findModal().vm.$emit('primary', { preventDefault: () => {} });
expect(submitSpy).toHaveBeenCalled();
});
});
});
});
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