Commit fa65c340 authored by Winnie Hellmann's avatar Winnie Hellmann Committed by Clement Ho

Display reCAPTCHA modal when making issue public

parent 287d0eaf
......@@ -5,6 +5,7 @@ import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '~/sidebar/event_hub';
import editForm from './edit_form.vue';
import recaptchaModalImplementor from '~/vue_shared/mixins/recaptcha_modal_implementor';
export default {
components: {
......@@ -14,6 +15,7 @@ export default {
directives: {
tooltip,
},
mixins: [recaptchaModalImplementor],
props: {
isConfidential: {
required: true,
......@@ -54,9 +56,14 @@ export default {
updateConfidentialAttribute(confidential) {
this.service
.update('issue', { confidential })
.then(({ data }) => this.checkForSpam(data))
.then(() => window.location.reload())
.catch(() => {
Flash(__('Something went wrong trying to change the confidentiality of this issue'));
.catch(error => {
if (error.name === 'SpamError') {
this.openRecaptcha();
} else {
Flash(__('Something went wrong trying to change the confidentiality of this issue'));
}
});
},
},
......@@ -112,5 +119,7 @@ export default {
{{ __('This issue is confidential') }}
</div>
</div>
<recaptcha-modal v-if="showRecaptcha" :html="recaptchaHTML" @close="closeRecaptcha" />
</div>
</template>
......@@ -32,6 +32,10 @@ export default {
mounted() {
eventHub.$on('submit', this.submit);
if (this.html) {
this.appendRecaptchaScript();
}
},
beforeDestroy() {
......
---
title: Display reCAPTCHA modal when making issue public
merge_request: 17553
author:
type: fixed
......@@ -49,6 +49,8 @@ exports[`Confidential Issue Sidebar Block renders for isConfidential = false and
</div>
</div>
<!---->
</div>
`;
......@@ -111,6 +113,8 @@ exports[`Confidential Issue Sidebar Block renders for isConfidential = false and
</div>
</div>
<!---->
</div>
`;
......@@ -163,6 +167,8 @@ exports[`Confidential Issue Sidebar Block renders for isConfidential = true and
</div>
</div>
<!---->
</div>
`;
......@@ -225,5 +231,7 @@ exports[`Confidential Issue Sidebar Block renders for isConfidential = true and
</div>
</div>
<!---->
</div>
`;
......@@ -2,15 +2,36 @@ import { shallowMount } from '@vue/test-utils';
import ConfidentialIssueSidebar from '~/sidebar/components/confidential/confidential_issue_sidebar.vue';
import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
import EditForm from '~/sidebar/components/confidential/edit_form.vue';
import SidebarService from '~/sidebar/services/sidebar_service';
import createFlash from '~/flash';
import RecaptchaModal from '~/vue_shared/components/recaptcha_modal';
jest.mock('~/flash');
jest.mock('~/sidebar/services/sidebar_service');
describe('Confidential Issue Sidebar Block', () => {
let wrapper;
const createComponent = propsData => {
const service = {
update: () => Promise.resolve(true),
};
const findRecaptchaModal = () => wrapper.find(RecaptchaModal);
const triggerUpdateConfidentialAttribute = () => {
wrapper.setData({ edit: true });
return (
// wait for edit form to become visible
wrapper.vm
.$nextTick()
.then(() => {
const editForm = wrapper.find(EditForm);
const { updateConfidentialAttribute } = editForm.props();
updateConfidentialAttribute();
})
// wait for reCAPTCHA modal to render
.then(() => wrapper.vm.$nextTick())
);
};
const createComponent = propsData => {
const service = new SidebarService();
wrapper = shallowMount(ConfidentialIssueSidebar, {
propsData: {
service,
......@@ -20,6 +41,15 @@ describe('Confidential Issue Sidebar Block', () => {
});
};
beforeEach(() => {
jest.clearAllMocks();
jest.spyOn(window.location, 'reload').mockImplementation();
});
afterEach(() => {
wrapper.destroy();
});
it.each`
isConfidential | isEditable
${false} | ${false}
......@@ -38,10 +68,6 @@ describe('Confidential Issue Sidebar Block', () => {
},
);
afterEach(() => {
wrapper.destroy();
});
describe('if editable', () => {
beforeEach(() => {
createComponent({
......@@ -81,5 +107,61 @@ describe('Confidential Issue Sidebar Block', () => {
property: 'confidentiality',
});
});
describe('for successful update', () => {
beforeEach(() => {
SidebarService.prototype.update.mockResolvedValue({ data: 'irrelevant' });
});
it('reloads the page', () =>
triggerUpdateConfidentialAttribute().then(() => {
expect(window.location.reload).toHaveBeenCalled();
}));
it('does not show an error message', () =>
triggerUpdateConfidentialAttribute().then(() => {
expect(createFlash).not.toHaveBeenCalled();
}));
});
describe('for update error', () => {
beforeEach(() => {
SidebarService.prototype.update.mockRejectedValue(new Error('updating failed!'));
});
it('does not reload the page', () =>
triggerUpdateConfidentialAttribute().then(() => {
expect(window.location.reload).not.toHaveBeenCalled();
}));
it('shows an error message', () =>
triggerUpdateConfidentialAttribute().then(() => {
expect(createFlash).toHaveBeenCalled();
}));
});
describe('for spam error', () => {
beforeEach(() => {
SidebarService.prototype.update.mockRejectedValue({ name: 'SpamError' });
});
it('does not reload the page', () =>
triggerUpdateConfidentialAttribute().then(() => {
expect(window.location.reload).not.toHaveBeenCalled();
}));
it('does not show an error message', () =>
triggerUpdateConfidentialAttribute().then(() => {
expect(createFlash).not.toHaveBeenCalled();
}));
it('shows a reCAPTCHA modal', () => {
expect(findRecaptchaModal().exists()).toBe(false);
return triggerUpdateConfidentialAttribute().then(() => {
expect(findRecaptchaModal().exists()).toBe(true);
});
});
});
});
});
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