diff options
author | Eric Eastwood <contact@ericeastwood.com> | 2017-09-18 17:06:47 -0500 |
---|---|---|
committer | Eric Eastwood <contact@ericeastwood.com> | 2017-09-19 23:48:40 -0500 |
commit | f7f9847b26fd9f401039908843de2b660473e73d (patch) | |
tree | a66ffe98c8e912a426de98470205a885da7d113a | |
parent | ccdf687baa82dd0e0f809cfb24dc892db756bad7 (diff) | |
download | gitlab-ce-f7f9847b26fd9f401039908843de2b660473e73d.tar.gz |
Port fast-forward MR widget states from EE
See https://gitlab.com/gitlab-org/gitlab-ce/issues/20076
7 files changed, 157 insertions, 83 deletions
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js index 703f3a56a34..3cbcbdd52c5 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js @@ -26,6 +26,7 @@ export default { <ci-icon v-else :status="statusObj" /> <button v-if="showDisabledButton" + ref="mergeButton" type="button" class="btn btn-success btn-sm" disabled="true"> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js index f9cb79a0bc1..f2245a532f4 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.js @@ -10,27 +10,40 @@ export default { }, template: ` <div class="mr-widget-body media"> - <status-icon status="failed" showDisabledButton /> + <status-icon + ref="statusIcon" + status="failed" + showDisabledButton /> <div class="media-body space-children"> - <span class="bold"> - There are merge conflicts<span v-if="!mr.canMerge">.</span> - <span v-if="!mr.canMerge"> - Resolve these conflicts or ask someone with write access to this repository to merge it locally + <template v-if="mr.ffOnlyEnabled"> + <span class="bold"> + Fast-forward merge is not possible. + To merge this request, first rebase locally </span> - </span> - <a - v-if="mr.canMerge && mr.conflictResolutionPath" - :href="mr.conflictResolutionPath" - class="btn btn-default btn-xs js-resolve-conflicts-button"> - Resolve conflicts - </a> - <a - v-if="mr.canMerge" - class="btn btn-default btn-xs js-merge-locally-button" - data-toggle="modal" - href="#modal_merge_info"> - Merge locally - </a> + </template> + <template v-else> + <span class="bold"> + There are merge conflicts<span v-if="!mr.canMerge">.</span> + <span v-if="!mr.canMerge"> + Resolve these conflicts or ask someone with write access to this repository to merge it locally + </span> + </span> + <a + v-if="mr.canMerge && mr.conflictResolutionPath" + ref="resolveConflictsButton" + :href="mr.conflictResolutionPath" + class="btn btn-default btn-xs"> + Resolve conflicts + </a> + <a + v-if="mr.canMerge" + ref="mergeLocallyButton" + class="btn btn-default btn-xs" + data-toggle="modal" + href="#modal_merge_info"> + Merge locally + </a> + </template> </div> </div> `, diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js index ad709da51ee..e1c37add496 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js @@ -284,7 +284,14 @@ export default { :mr="mr" :is-merge-button-disabled="isMergeButtonDisabled" /> + <span + v-if="mr.ffOnlyEnabled" + ref="fastForwardMessage"> + Fast-forward merge without a merge commit + </span> <button + v-else + ref="modifyCommitMessageButton" @click="toggleCommitMessageEditor" :disabled="isMergeButtonDisabled" class="btn btn-default btn-xs" diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js index 29464662578..03969e33e97 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js @@ -57,6 +57,7 @@ export default class MergeRequestStore { this.onlyAllowMergeIfPipelineSucceeds = data.only_allow_merge_if_pipeline_succeeds || false; this.mergeWhenPipelineSucceeds = data.merge_when_pipeline_succeeds || false; this.mergePath = data.merge_path; + this.ffOnlyEnabled = data.ff_only_enabled; this.statusPath = data.status_path; this.emailPatchesPath = data.email_patches_path; this.plainDiffPath = data.plain_diff_path; diff --git a/app/serializers/merge_request_entity.rb b/app/serializers/merge_request_entity.rb index 1f5ce2ef58c..5f2700df692 100644 --- a/app/serializers/merge_request_entity.rb +++ b/app/serializers/merge_request_entity.rb @@ -17,7 +17,6 @@ class MergeRequestEntity < IssuableEntity merge_request.project.merge_requests_ff_only_enabled end - # Events expose :merge_event, using: EventEntity expose :closed_event, using: EventEntity diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js index 3b7b7d93662..d4b18703b25 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js @@ -2,17 +2,16 @@ import Vue from 'vue'; import conflictsComponent from '~/vue_merge_request_widget/components/states/mr_widget_conflicts'; const path = '/conflicts'; -const createComponent = () => { +const createComponent = (customConfig = {}) => { const Component = Vue.extend(conflictsComponent); + const config = Object.assign({ + mr: {}, + }, customConfig); + return new Component({ el: document.createElement('div'), - propsData: { - mr: { - canMerge: true, - conflictResolutionPath: path, - }, - }, + propsData: config, }); }; @@ -27,44 +26,78 @@ describe('MRWidgetConflicts', () => { }); describe('template', () => { - it('should have correct elements', () => { - const el = createComponent().$el; - const resolveButton = el.querySelector('.js-resolve-conflicts-button'); - const mergeButton = el.querySelector('.mr-widget-body .btn'); - const mergeLocallyButton = el.querySelector('.js-merge-locally-button'); - - expect(el.textContent).toContain('There are merge conflicts'); - expect(el.textContent).not.toContain('ask someone with write access'); - expect(el.querySelector('.btn-success').disabled).toBeTruthy(); - expect(resolveButton.textContent).toContain('Resolve conflicts'); - expect(resolveButton.getAttribute('href')).toEqual(path); - expect(mergeButton.textContent).toContain('Merge'); - expect(mergeLocallyButton.textContent).toContain('Merge locally'); + describe('when allowed to merge', () => { + let vm; + + beforeEach(() => { + vm = createComponent({ + mr: { + canMerge: true, + conflictResolutionPath: path, + }, + }); + }); + + it('should tell you about conflicts without bothering other people', () => { + expect(vm.$el.textContent).toContain('There are merge conflicts'); + expect(vm.$el.textContent).not.toContain('ask someone with write access'); + }); + + it('should allow you to resolve the conflicts', () => { + const resolveButton = vm.$refs.resolveConflictsButton; + + expect(resolveButton.textContent).toContain('Resolve conflicts'); + expect(resolveButton.getAttribute('href')).toEqual(path); + }); + + it('should have merge buttons', () => { + const mergeButton = vm.$refs.statusIcon.$refs.mergeButton; + const mergeLocallyButton = vm.$refs.mergeLocallyButton; + + expect(mergeButton.textContent).toContain('Merge'); + expect(mergeButton.disabled).toBeTruthy(); + expect(mergeButton.classList.contains('btn-success')).toBeTruthy(); + expect(mergeLocallyButton.textContent).toContain('Merge locally'); + }); }); describe('when user does not have permission to merge', () => { let vm; beforeEach(() => { - vm = createComponent(); - vm.mr.canMerge = false; + vm = createComponent({ + mr: { + canMerge: false, + }, + }); }); - it('should show proper message', (done) => { - Vue.nextTick(() => { - expect(vm.$el.textContent).toContain('ask someone with write access'); - done(); - }); + it('should show proper message', () => { + expect(vm.$el.textContent).toContain('ask someone with write access'); + }); + + it('should not have action buttons', () => { + expect(vm.$refs.statusIcon.$refs.mergeButton).toBeDefined(); + expect(vm.$refs.resolveConflictsButton).toBeUndefined(); + expect(vm.$refs.mergeLocallyButton).toBeUndefined(); }); + }); + + describe('when fast-forward merge enabled', () => { + let vm; - it('should not have action buttons', (done) => { - Vue.nextTick(() => { - expect(vm.$el.querySelectorAll('.btn').length).toBe(1); - expect(vm.$el.querySelector('.js-resolve-conflicts-button')).toEqual(null); - expect(vm.$el.querySelector('.js-merge-locally-button')).toEqual(null); - done(); + beforeEach(() => { + vm = createComponent({ + mr: { + ffOnlyEnabled: true, + }, }); }); + + it('should tell you to rebase locally', () => { + expect(vm.$el.textContent).toContain('Fast-forward merge is not possible.'); + expect(vm.$el.textContent).toContain('To merge this request, first rebase locally'); + }); }); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js index 03a52f1f91c..f36b74c9e94 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js @@ -182,36 +182,6 @@ describe('MRWidgetReadyToMerge', () => { expect(vm.isMergeButtonDisabled).toBeTruthy(); }); }); - - describe('Remove source branch checkbox', () => { - describe('when user can merge but cannot delete branch', () => { - it('isRemoveSourceBranchButtonDisabled should be true', () => { - expect(vm.isRemoveSourceBranchButtonDisabled).toBe(true); - }); - - it('should be disabled in the rendered output', () => { - const checkboxElement = vm.$el.querySelector('#remove-source-branch-input'); - expect(checkboxElement.getAttribute('disabled')).toBe('disabled'); - }); - }); - - describe('when user can merge and can delete branch', () => { - beforeEach(() => { - this.customVm = createComponent({ - mr: { canRemoveSourceBranch: true }, - }); - }); - - it('isRemoveSourceBranchButtonDisabled should be false', () => { - expect(this.customVm.isRemoveSourceBranchButtonDisabled).toBe(false); - }); - - it('should be enabled in rendered output', () => { - const checkboxElement = this.customVm.$el.querySelector('#remove-source-branch-input'); - expect(checkboxElement.getAttribute('disabled')).toBeNull(); - }); - }); - }); }); describe('methods', () => { @@ -467,4 +437,54 @@ describe('MRWidgetReadyToMerge', () => { }); }); }); + + describe('Remove source branch checkbox', () => { + describe('when user can merge but cannot delete branch', () => { + it('isRemoveSourceBranchButtonDisabled should be true', () => { + expect(vm.isRemoveSourceBranchButtonDisabled).toBe(true); + }); + + it('should be disabled in the rendered output', () => { + const checkboxElement = vm.$el.querySelector('#remove-source-branch-input'); + expect(checkboxElement.getAttribute('disabled')).toBe('disabled'); + }); + }); + + describe('when user can merge and can delete branch', () => { + beforeEach(() => { + this.customVm = createComponent({ + mr: { canRemoveSourceBranch: true }, + }); + }); + + it('isRemoveSourceBranchButtonDisabled should be false', () => { + expect(this.customVm.isRemoveSourceBranchButtonDisabled).toBe(false); + }); + + it('should be enabled in rendered output', () => { + const checkboxElement = this.customVm.$el.querySelector('#remove-source-branch-input'); + expect(checkboxElement.getAttribute('disabled')).toBeNull(); + }); + }); + }); + + describe('Commit message area', () => { + it('when using merge commits, should show "Modify commit message" button', () => { + const customVm = createComponent({ + mr: { ffOnlyEnabled: false }, + }); + + expect(customVm.$refs.fastForwardMessage).toBeUndefined(); + expect(customVm.$refs.modifyCommitMessageButton).toBeDefined(); + }); + + it('when fast-forward merge is enabled, only show fast-forward message', () => { + const customVm = createComponent({ + mr: { ffOnlyEnabled: true }, + }); + + expect(customVm.$refs.fastForwardMessage).toBeDefined(); + expect(customVm.$refs.modifyCommitMessageButton).toBeUndefined(); + }); + }); }); |