Commit 05a6be0c authored by Mike Greiling's avatar Mike Greiling

Merge branch 'leipert-remove-unused-modal' into 'master'

Remove unused recaptcha and deprecated modal

See merge request gitlab-org/gitlab!55527
parents a1072c4f 88baa590
<script>
/* eslint-disable vue/require-default-prop */
import { __ } from '~/locale';
export default {
name: 'DeprecatedModal', // use GlModal instead
props: {
id: {
type: String,
required: false,
},
title: {
type: String,
required: false,
},
text: {
type: String,
required: false,
},
hideFooter: {
type: Boolean,
required: false,
default: false,
},
kind: {
type: String,
required: false,
default: 'primary',
},
modalDialogClass: {
type: String,
required: false,
default: '',
},
closeKind: {
type: String,
required: false,
default: 'default',
},
closeButtonLabel: {
type: String,
required: false,
default: __('Cancel'),
},
primaryButtonLabel: {
type: String,
required: false,
default: '',
},
secondaryButtonLabel: {
type: String,
required: false,
default: '',
},
submitDisabled: {
type: Boolean,
required: false,
default: false,
},
},
computed: {
btnKindClass() {
return {
[`btn-${this.kind}`]: true,
};
},
btnCancelKindClass() {
return {
[`btn-${this.closeKind}`]: true,
};
},
},
methods: {
emitCancel(event) {
this.$emit('cancel', event);
},
emitSubmit(event) {
this.$emit('submit', event);
},
},
};
</script>
<template>
<div class="modal-open">
<div :id="id" :class="id ? '' : 'd-block'" class="modal" role="dialog" tabindex="-1">
<div :class="modalDialogClass" class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<slot name="header">
<h4 class="modal-title float-left">{{ title }}</h4>
<button
type="button"
class="close float-right"
data-dismiss="modal"
:aria-label="__('Close')"
@click="emitCancel($event)"
>
<span aria-hidden="true">&times;</span>
</button>
</slot>
</div>
<div class="modal-body">
<slot :text="text" name="body">
<p>{{ text }}</p>
</slot>
</div>
<div v-if="!hideFooter" class="modal-footer">
<button
:class="btnCancelKindClass"
type="button"
class="btn"
data-dismiss="modal"
@click="emitCancel($event)"
>
{{ closeButtonLabel }}
</button>
<slot v-if="secondaryButtonLabel" name="secondary-button">
<button v-if="secondaryButtonLabel" type="button" class="btn" data-dismiss="modal">
{{ secondaryButtonLabel }}
</button>
</slot>
<button
v-if="primaryButtonLabel"
:disabled="submitDisabled"
:class="btnKindClass"
type="button"
class="btn js-primary-button"
data-dismiss="modal"
data-qa-selector="save_changes_button"
@click="emitSubmit($event)"
>
{{ primaryButtonLabel }}
</button>
</div>
</div>
</div>
</div>
<div v-if="!id" class="modal-backdrop fade show"></div>
</div>
</template>
import createEventHub from '~/helpers/event_hub_factory';
// see recaptcha_tags in app/views/shared/_recaptcha_form.html.haml
export const callbackName = 'recaptchaDialogCallback';
export const eventHub = createEventHub();
const throwDuplicateCallbackError = () => {
throw new Error(`${callbackName} is already defined!`);
};
if (window[callbackName]) {
throwDuplicateCallbackError();
}
const callback = () => eventHub.$emit('submit');
Object.defineProperty(window, callbackName, {
get: () => callback,
set: throwDuplicateCallbackError,
});
<script>
/* eslint-disable vue/no-v-html */
import DeprecatedModal from './deprecated_modal.vue';
import { eventHub } from './recaptcha_eventhub';
export default {
name: 'RecaptchaModal',
components: {
DeprecatedModal,
},
props: {
html: {
type: String,
required: false,
default: '',
},
},
data() {
return {
script: {},
scriptSrc: 'https://www.recaptcha.net/recaptcha/api.js',
};
},
watch: {
html() {
this.appendRecaptchaScript();
},
},
mounted() {
eventHub.$on('submit', this.submit);
if (this.html) {
this.appendRecaptchaScript();
}
},
beforeDestroy() {
eventHub.$off('submit', this.submit);
},
methods: {
appendRecaptchaScript() {
this.removeRecaptchaScript();
const script = document.createElement('script');
script.src = this.scriptSrc;
script.classList.add('js-recaptcha-script');
script.async = true;
script.defer = true;
this.script = script;
document.body.appendChild(script);
},
removeRecaptchaScript() {
if (this.script instanceof Element) this.script.remove();
},
close() {
this.removeRecaptchaScript();
this.$emit('close');
},
submit() {
this.$el.querySelector('form').submit();
},
},
};
</script>
<template>
<deprecated-modal
:hide-footer="true"
:title="__('Please solve the reCAPTCHA')"
kind="warning"
class="recaptcha-modal js-recaptcha-modal"
@cancel="close"
>
<div slot="body">
<p>{{ __('We want to be sure it is you, please confirm you are not a robot.') }}</p>
<div ref="recaptcha" v-html="html"></div>
</div>
</deprecated-modal>
</template>
import recaptchaModal from '../components/recaptcha_modal.vue';
export default {
data() {
return {
showRecaptcha: false,
recaptchaHTML: '',
};
},
components: {
recaptchaModal,
},
methods: {
openRecaptcha() {
this.showRecaptcha = true;
},
closeRecaptcha() {
this.showRecaptcha = false;
},
checkForSpam(data) {
if (!data.recaptcha_html) return data;
this.recaptchaHTML = data.recaptcha_html;
const spamError = new Error(data.error_message);
spamError.name = 'SpamError';
spamError.message = 'SpamError';
throw spamError;
},
},
};
......@@ -22993,9 +22993,6 @@ msgstr ""
msgid "Please solve the captcha"
msgstr ""
msgid "Please solve the reCAPTCHA"
msgstr ""
msgid "Please try again"
msgstr ""
......
......@@ -11,6 +11,7 @@ module QA
view 'app/assets/javascripts/boards/components/board_form.vue' do
element :board_name_field
element :save_changes_button
end
view 'app/assets/javascripts/boards/components/board_list.vue' do
......@@ -23,10 +24,6 @@ module QA
element :create_new_board_button
end
view 'app/assets/javascripts/vue_shared/components/deprecated_modal.vue' do
element :save_changes_button
end
view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue' do
element :labels_dropdown_content
end
......
import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
const modalComponent = Vue.extend(DeprecatedModal);
describe('DeprecatedModal', () => {
let vm;
afterEach(() => {
vm.$destroy();
});
describe('props', () => {
describe('without primaryButtonLabel', () => {
beforeEach(() => {
vm = mountComponent(modalComponent, {
primaryButtonLabel: null,
});
});
it('does not render a primary button', () => {
expect(vm.$el.querySelector('.js-primary-button')).toBeNull();
});
});
describe('with id', () => {
describe('does not render a primary button', () => {
beforeEach(() => {
vm = mountComponent(modalComponent, {
id: 'my-modal',
});
});
it('assigns the id to the modal', () => {
expect(vm.$el.querySelector('#my-modal.modal')).not.toBeNull();
});
it('does not show the modal immediately', () => {
expect(vm.$el.querySelector('#my-modal.modal')).not.toHaveClass('show');
});
it('does not show a backdrop', () => {
expect(vm.$el.querySelector('modal-backdrop')).toBeNull();
});
});
});
it('works with data-toggle="modal"', () => {
setFixtures(`
<button id="modal-button" data-toggle="modal" data-target="#my-modal"></button>
<div id="modal-container"></div>
`);
const modalContainer = document.getElementById('modal-container');
const modalButton = document.getElementById('modal-button');
vm = mountComponent(
modalComponent,
{
id: 'my-modal',
},
modalContainer,
);
const modalElement = vm.$el.querySelector('#my-modal');
expect(modalElement).not.toHaveClass('show');
modalButton.click();
expect(modalElement).toHaveClass('show');
});
});
});
import { eventHub, callbackName } from '~/vue_shared/components/recaptcha_eventhub';
describe('reCAPTCHA event hub', () => {
// the following test case currently crashes
// see https://gitlab.com/gitlab-org/gitlab/issues/29192#note_217840035
// eslint-disable-next-line jest/no-disabled-tests
it.skip('throws an error for overriding the callback', () => {
expect(() => {
window[callbackName] = 'something';
}).toThrow();
});
it('triggering callback emits a submit event', () => {
const eventHandler = jest.fn();
eventHub.$once('submit', eventHandler);
window[callbackName]();
expect(eventHandler).toHaveBeenCalled();
});
});
import { shallowMount } from '@vue/test-utils';
import { eventHub } from '~/vue_shared/components/recaptcha_eventhub';
import RecaptchaModal from '~/vue_shared/components/recaptcha_modal.vue';
describe('RecaptchaModal', () => {
const recaptchaFormId = 'recaptcha-form';
const recaptchaHtml = `<form id="${recaptchaFormId}"></form>`;
let wrapper;
const findRecaptchaForm = () => wrapper.find(`#${recaptchaFormId}`).element;
beforeEach(() => {
wrapper = shallowMount(RecaptchaModal, {
propsData: {
html: recaptchaHtml,
},
});
});
afterEach(() => {
wrapper.destroy();
});
it('submits the form if event hub emits submit event', () => {
const form = findRecaptchaForm();
jest.spyOn(form, 'submit').mockImplementation();
eventHub.$emit('submit');
expect(form.submit).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