提交 2a868635 编写于 作者: F Fatih Acet

Merge branch '32178-prevent-merge-on-sha-change' into 'master'

Add "SHA mismatch" state to the MR widget

Closes #32178

See merge request !11316
export default {
name: 'MRWidgetSHAMismatch',
template: `
<div class="mr-widget-body">
<button
type="button"
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
<span class="bold">
The source branch HEAD has recently changed. Please reload the page and review the changes before merging.
</span>
</div>
`,
};
......@@ -27,6 +27,7 @@ export { default as NothingToMergeState } from './components/states/mr_widget_no
export { default as MissingBranchState } from './components/states/mr_widget_missing_branch';
export { default as NotAllowedState } from './components/states/mr_widget_not_allowed';
export { default as ReadyToMergeState } from './components/states/mr_widget_ready_to_merge';
export { default as SHAMismatchState } from './components/states/mr_widget_sha_mismatch';
export { default as UnresolvedDiscussionsState } from './components/states/mr_widget_unresolved_discussions';
export { default as PipelineBlockedState } from './components/states/mr_widget_pipeline_blocked';
export { default as PipelineFailedState } from './components/states/mr_widget_pipeline_failed';
......
......@@ -16,6 +16,7 @@ import {
MissingBranchState,
NotAllowedState,
ReadyToMergeState,
SHAMismatchState,
UnresolvedDiscussionsState,
PipelineBlockedState,
PipelineFailedState,
......@@ -203,6 +204,7 @@ export default {
'mr-widget-not-allowed': NotAllowedState,
'mr-widget-missing-branch': MissingBranchState,
'mr-widget-ready-to-merge': ReadyToMergeState,
'mr-widget-sha-mismatch': SHAMismatchState,
'mr-widget-squash-before-merge': SquashBeforeMerge,
'mr-widget-checking': CheckingState,
'mr-widget-unresolved-discussions': UnresolvedDiscussionsState,
......
......@@ -21,6 +21,8 @@ export default function deviseState(data) {
return 'unresolvedDiscussions';
} else if (this.isPipelineBlocked) {
return 'pipelineBlocked';
} else if (this.hasSHAChanged) {
return 'shaMismatch';
} else if (this.canBeMerged) {
return 'readyToMerge';
}
......
......@@ -4,6 +4,7 @@ import { getStateKey } from '../dependencies';
export default class MergeRequestStore {
constructor(data) {
this.startingSha = data.diff_head_sha;
this.setData(data);
}
......@@ -67,6 +68,7 @@ export default class MergeRequestStore {
this.canMerge = !!data.merge_path;
this.canCreateIssue = currentUser.can_create_issue || false;
this.canCancelAutomaticMerge = !!data.cancel_merge_when_pipeline_succeeds_path;
this.hasSHAChanged = this.sha !== this.startingSha;
this.canBeMerged = data.can_be_merged || false;
// Cherry-pick and Revert actions related
......
......@@ -16,6 +16,7 @@ const stateToComponentMap = {
mergeWhenPipelineSucceeds: 'mr-widget-merge-when-pipeline-succeeds',
failedToMerge: 'mr-widget-failed-to-merge',
autoMergeFailed: 'mr-widget-auto-merge-failed',
shaMismatch: 'mr-widget-sha-mismatch',
};
const statesToShowHelpWidget = [
......
---
title: Add state to MR widget that prevent merges when branch changes after page load
merge_request: 11316
author:
import Vue from 'vue';
import shaMismatchComponent from '~/vue_merge_request_widget/components/states/mr_widget_sha_mismatch';
describe('MRWidgetSHAMismatch', () => {
describe('template', () => {
const Component = Vue.extend(shaMismatchComponent);
const vm = new Component({
el: document.createElement('div'),
});
it('should have correct elements', () => {
expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
expect(vm.$el.innerText).toContain('The source branch HEAD has recently changed. Please reload the page and review the changes before merging.');
});
});
});
......@@ -25,6 +25,9 @@ describe('getStateKey', () => {
context.canBeMerged = true;
expect(bound()).toEqual('readyToMerge');
context.hasSHAChanged = true;
expect(bound()).toEqual('shaMismatch');
context.isPipelineBlocked = true;
expect(bound()).toEqual('pipelineBlocked');
......
import MergeRequestStore from '~/vue_merge_request_widget/stores/mr_widget_store';
import mockData from '../mock_data';
describe('MergeRequestStore', () => {
describe('setData', () => {
let store;
beforeEach(() => {
store = new MergeRequestStore(mockData);
});
it('should set hasSHAChanged when the diff SHA changes', () => {
store.setData({ ...mockData, diff_head_sha: 'a-different-string' });
expect(store.hasSHAChanged).toBe(true);
});
it('should not set hasSHAChanged when other data changes', () => {
store.setData({ ...mockData, work_in_progress: !mockData.work_in_progress });
expect(store.hasSHAChanged).toBe(false);
});
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册