diff --git a/app/assets/javascripts/repository/components/blob_button_group.vue b/app/assets/javascripts/repository/components/blob_button_group.vue index 6f540bf8ece4f9f4388a267df2811be8cffe07d6..857795c71b0a7ab68798f595218c66757411e65e 100644 --- a/app/assets/javascripts/repository/components/blob_button_group.vue +++ b/app/assets/javascripts/repository/components/blob_button_group.vue @@ -1,5 +1,5 @@ <script> -import { GlButtonGroup, GlButton, GlModalDirective } from '@gitlab/ui'; +import { GlButtonGroup, GlButton } from '@gitlab/ui'; import { uniqueId } from 'lodash'; import { sprintf, __ } from '~/locale'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; @@ -20,9 +20,6 @@ export default { DeleteBlobModal, LockButton: () => import('ee_component/repository/components/lock_button.vue'), }, - directives: { - GlModal: GlModalDirective, - }, mixins: [getRefMixin, glFeatureFlagMixin()], inject: { targetBranch: { @@ -73,6 +70,10 @@ export default { type: Boolean, required: true, }, + showForkSuggestion: { + type: Boolean, + required: true, + }, }, computed: { replaceModalId() { @@ -91,6 +92,16 @@ export default { return this.canLock ? 'lock_button' : 'disabled_lock_button'; }, }, + methods: { + showModal(modalId) { + if (this.showForkSuggestion) { + this.$emit('fork'); + return; + } + + this.$refs[modalId].show(); + }, + }, }; </script> @@ -107,14 +118,15 @@ export default { data-testid="lock" :data-qa-selector="lockBtnQASelector" /> - <gl-button v-gl-modal="replaceModalId" data-testid="replace"> + <gl-button data-testid="replace" @click="showModal(replaceModalId)"> {{ $options.i18n.replace }} </gl-button> - <gl-button v-gl-modal="deleteModalId" data-testid="delete"> + <gl-button data-testid="delete" @click="showModal(deleteModalId)"> {{ $options.i18n.delete }} </gl-button> </gl-button-group> <upload-blob-modal + :ref="replaceModalId" :modal-id="replaceModalId" :modal-title="replaceModalTitle" :commit-message="replaceModalTitle" @@ -126,6 +138,7 @@ export default { :primary-btn-text="$options.i18n.replacePrimaryBtnText" /> <delete-blob-modal + :ref="deleteModalId" :modal-id="deleteModalId" :modal-title="deleteModalTitle" :delete-path="deletePath" diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue index 46b4c5131091c7497aa4a5b3d921bfa4330c60a0..cb007db08cc5b223208f880716bfb401abda48f2 100644 --- a/app/assets/javascripts/repository/components/blob_content_viewer.vue +++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue @@ -280,6 +280,8 @@ export default { :project-path="projectPath" :is-locked="Boolean(pathLockedByUser)" :can-lock="canLock" + :show-fork-suggestion="showForkSuggestion" + @fork="setForkTarget('ide')" /> </template> </blob-header> diff --git a/app/assets/javascripts/repository/components/delete_blob_modal.vue b/app/assets/javascripts/repository/components/delete_blob_modal.vue index 0d3dc06c2c8ecf03a3d53e9bb2486993a1c59e56..f3c9aea36f15eed8b260d606bb30ae4842044af5 100644 --- a/app/assets/javascripts/repository/components/delete_blob_modal.vue +++ b/app/assets/javascripts/repository/components/delete_blob_modal.vue @@ -146,6 +146,9 @@ export default { /* eslint-enable dot-notation */ }, methods: { + show() { + this.$refs[this.modalId].show(); + }, submitForm(e) { e.preventDefault(); // Prevent modal from closing this.form.showValidation = true; @@ -164,6 +167,7 @@ export default { <template> <gl-modal + :ref="modalId" v-bind="$attrs" data-testid="modal-delete" :modal-id="modalId" diff --git a/app/assets/javascripts/repository/components/fork_suggestion.vue b/app/assets/javascripts/repository/components/fork_suggestion.vue index c266bea319b5557293bc54a60f617810cec9582d..471f1dad2e35c31c226d8ff6172e71111225ddac 100644 --- a/app/assets/javascripts/repository/components/fork_suggestion.vue +++ b/app/assets/javascripts/repository/components/fork_suggestion.vue @@ -32,6 +32,7 @@ export default { class="gl-mr-3" category="secondary" variant="confirm" + data-method="post" :href="forkPath" data-testid="fork" > diff --git a/app/assets/javascripts/repository/components/upload_blob_modal.vue b/app/assets/javascripts/repository/components/upload_blob_modal.vue index b56c9ce52471bd78d5fe0328d92c699e5270eb6d..7fcaf772aac6e74c7271f177a4ee81b7a81408bf 100644 --- a/app/assets/javascripts/repository/components/upload_blob_modal.vue +++ b/app/assets/javascripts/repository/components/upload_blob_modal.vue @@ -136,6 +136,9 @@ export default { }, }, methods: { + show() { + this.$refs[this.modalId].show(); + }, setFile(file) { this.file = file; @@ -206,6 +209,7 @@ export default { <template> <gl-form> <gl-modal + :ref="modalId" :modal-id="modalId" :title="modalTitle" :action-primary="primaryOptions" diff --git a/ee/spec/frontend/repository/components/blob_button_group_spec.js b/ee/spec/frontend/repository/components/blob_button_group_spec.js index 8719c5316db565f104343dce2034e993dec4a3f4..be2c937f5c81afefd2e442839b4db3e5afbf5686 100644 --- a/ee/spec/frontend/repository/components/blob_button_group_spec.js +++ b/ee/spec/frontend/repository/components/blob_button_group_spec.js @@ -13,6 +13,7 @@ const DEFAULT_PROPS = { projectPath: 'some/project/path', isLocked: false, canLock: true, + showForkSuggestion: false, }; const DEFAULT_INJECT = { diff --git a/spec/frontend/repository/components/blob_button_group_spec.js b/spec/frontend/repository/components/blob_button_group_spec.js index 9f9d574a8ed3750fa25514f6fafe60dfe5f36045..d5b882bd71595ba4f901676893c4e94b3c76e91f 100644 --- a/spec/frontend/repository/components/blob_button_group_spec.js +++ b/spec/frontend/repository/components/blob_button_group_spec.js @@ -1,6 +1,5 @@ import { GlButton } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; import BlobButtonGroup from '~/repository/components/blob_button_group.vue'; import DeleteBlobModal from '~/repository/components/delete_blob_modal.vue'; import UploadBlobModal from '~/repository/components/upload_blob_modal.vue'; @@ -16,6 +15,7 @@ const DEFAULT_PROPS = { projectPath: 'some/project/path', isLocked: false, canLock: true, + showForkSuggestion: false, }; const DEFAULT_INJECT = { @@ -27,7 +27,7 @@ describe('BlobButtonGroup component', () => { let wrapper; const createComponent = (props = {}) => { - wrapper = shallowMount(BlobButtonGroup, { + wrapper = mountExtended(BlobButtonGroup, { propsData: { ...DEFAULT_PROPS, ...props, @@ -35,9 +35,6 @@ describe('BlobButtonGroup component', () => { provide: { ...DEFAULT_INJECT, }, - directives: { - GlModal: createMockDirective(), - }, }); }; @@ -47,7 +44,8 @@ describe('BlobButtonGroup component', () => { const findDeleteBlobModal = () => wrapper.findComponent(DeleteBlobModal); const findUploadBlobModal = () => wrapper.findComponent(UploadBlobModal); - const findReplaceButton = () => wrapper.find('[data-testid="replace"]'); + const findDeleteButton = () => wrapper.findByTestId('delete'); + const findReplaceButton = () => wrapper.findByTestId('replace'); it('renders component', () => { createComponent(); @@ -63,6 +61,8 @@ describe('BlobButtonGroup component', () => { describe('buttons', () => { beforeEach(() => { createComponent(); + jest.spyOn(findUploadBlobModal().vm, 'show'); + jest.spyOn(findDeleteBlobModal().vm, 'show'); }); it('renders both the replace and delete button', () => { @@ -75,10 +75,37 @@ describe('BlobButtonGroup component', () => { }); it('triggers the UploadBlobModal from the replace button', () => { - const { value } = getBinding(findReplaceButton().element, 'gl-modal'); - const modalId = findUploadBlobModal().props('modalId'); + findReplaceButton().trigger('click'); + + expect(findUploadBlobModal().vm.show).toHaveBeenCalled(); + }); + + it('triggers the DeleteBlobModal from the delete button', () => { + findDeleteButton().trigger('click'); + + expect(findDeleteBlobModal().vm.show).toHaveBeenCalled(); + }); + + describe('showForkSuggestion set to true', () => { + beforeEach(() => { + createComponent({ showForkSuggestion: true }); + jest.spyOn(findUploadBlobModal().vm, 'show'); + jest.spyOn(findDeleteBlobModal().vm, 'show'); + }); + + it('does not trigger the UploadBlobModal from the replace button', () => { + findReplaceButton().trigger('click'); + + expect(findUploadBlobModal().vm.show).not.toHaveBeenCalled(); + expect(wrapper.emitted().fork).toBeTruthy(); + }); + + it('does not trigger the DeleteBlobModal from the delete button', () => { + findDeleteButton().trigger('click'); - expect(modalId).toEqual(value); + expect(findDeleteBlobModal().vm.show).not.toHaveBeenCalled(); + expect(wrapper.emitted().fork).toBeTruthy(); + }); }); });