Commit f0befa3c authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'ph/readyToMergeVueTestUtils' into 'master'

Refactor ready to merge widget tests to Vue test utils

See merge request gitlab-org/gitlab!61699
parents a1441526 ecd34366
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ReadyToMerge with a mismatched SHA warns the user to refresh to review 1`] = `"<gl-sprintf-stub message=\\"New changes were added. %{linkStart}Reload the page to review them%{linkEnd}\\"></gl-sprintf-stub>"`;
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue'; import Vue from 'vue';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import simplePoll from '~/lib/utils/simple_poll'; import simplePoll from '~/lib/utils/simple_poll';
import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit.vue'; import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit.vue';
import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue'; import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue';
import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue'; import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
import ReadyToMerge from '~/vue_merge_request_widget/components/states/ready_to_merge.vue'; import ReadyToMerge from '~/vue_merge_request_widget/components/states/ready_to_merge.vue';
import SquashBeforeMerge from '~/vue_merge_request_widget/components/states/squash_before_merge.vue'; import SquashBeforeMerge from '~/vue_merge_request_widget/components/states/squash_before_merge.vue';
import { MWPS_MERGE_STRATEGY, MTWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants'; import { MWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
import eventHub from '~/vue_merge_request_widget/event_hub'; import eventHub from '~/vue_merge_request_widget/event_hub';
jest.mock('~/lib/utils/simple_poll', () => jest.mock('~/lib/utils/simple_poll', () =>
...@@ -58,11 +58,9 @@ const createTestService = () => ({ ...@@ -58,11 +58,9 @@ const createTestService = () => ({
poll: jest.fn().mockResolvedValue(), poll: jest.fn().mockResolvedValue(),
}); });
let wrapper;
const createComponent = (customConfig = {}) => { const createComponent = (customConfig = {}) => {
const Component = Vue.extend(ReadyToMerge); wrapper = shallowMount(ReadyToMerge, {
return new Component({
el: document.createElement('div'),
propsData: { propsData: {
mr: createTestMr(customConfig), mr: createTestMr(customConfig),
service: createTestService(), service: createTestService(),
...@@ -71,277 +69,207 @@ const createComponent = (customConfig = {}) => { ...@@ -71,277 +69,207 @@ const createComponent = (customConfig = {}) => {
}; };
describe('ReadyToMerge', () => { describe('ReadyToMerge', () => {
let vm;
beforeEach(() => {
vm = createComponent();
});
afterEach(() => { afterEach(() => {
vm.$destroy(); wrapper.destroy();
});
describe('props', () => {
it('should have props', () => {
const { mr, service } = ReadyToMerge.props;
expect(mr.type instanceof Object).toBeTruthy();
expect(mr.required).toBeTruthy();
expect(service.type instanceof Object).toBeTruthy();
expect(service.required).toBeTruthy();
});
});
describe('data', () => {
it('should have default data', () => {
expect(vm.mergeWhenBuildSucceeds).toBeFalsy();
expect(vm.useCommitMessageWithDescription).toBeFalsy();
expect(vm.showCommitMessageEditor).toBeFalsy();
expect(vm.isMakingRequest).toBeFalsy();
expect(vm.isMergingImmediately).toBeFalsy();
expect(vm.commitMessage).toBe(vm.mr.commitMessage);
});
}); });
describe('computed', () => { describe('computed', () => {
describe('isAutoMergeAvailable', () => { describe('isAutoMergeAvailable', () => {
it('should return true when at least one merge strategy is available', () => { it('should return true when at least one merge strategy is available', () => {
vm.mr.availableAutoMergeStrategies = [MWPS_MERGE_STRATEGY]; createComponent();
expect(vm.isAutoMergeAvailable).toBe(true); expect(wrapper.vm.isAutoMergeAvailable).toBe(true);
}); });
it('should return false when no merge strategies are available', () => { it('should return false when no merge strategies are available', () => {
vm.mr.availableAutoMergeStrategies = []; createComponent({ mr: { availableAutoMergeStrategies: [] } });
expect(vm.isAutoMergeAvailable).toBe(false); expect(wrapper.vm.isAutoMergeAvailable).toBe(false);
}); });
}); });
describe('status', () => { describe('status', () => {
it('defaults to success', () => { it('defaults to success', () => {
Vue.set(vm.mr, 'pipeline', true); createComponent({ mr: { pipeline: true, availableAutoMergeStrategies: [] } });
Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
expect(vm.status).toEqual('success'); expect(wrapper.vm.status).toEqual('success');
}); });
it('returns failed when MR has CI but also has an unknown status', () => { it('returns failed when MR has CI but also has an unknown status', () => {
Vue.set(vm.mr, 'hasCI', true); createComponent({ mr: { hasCI: true } });
expect(vm.status).toEqual('failed'); expect(wrapper.vm.status).toEqual('failed');
}); });
it('returns default when MR has no pipeline', () => { it('returns default when MR has no pipeline', () => {
Vue.set(vm.mr, 'availableAutoMergeStrategies', []); createComponent({ mr: { availableAutoMergeStrategies: [] } });
expect(vm.status).toEqual('success'); expect(wrapper.vm.status).toEqual('success');
}); });
it('returns pending when pipeline is active', () => { it('returns pending when pipeline is active', () => {
Vue.set(vm.mr, 'pipeline', {}); createComponent({ mr: { pipeline: {}, isPipelineActive: true } });
Vue.set(vm.mr, 'isPipelineActive', true);
expect(vm.status).toEqual('pending'); expect(wrapper.vm.status).toEqual('pending');
}); });
it('returns failed when pipeline is failed', () => { it('returns failed when pipeline is failed', () => {
Vue.set(vm.mr, 'pipeline', {}); createComponent({
Vue.set(vm.mr, 'isPipelineFailed', true); mr: { pipeline: {}, isPipelineFailed: true, availableAutoMergeStrategies: [] },
Vue.set(vm.mr, 'availableAutoMergeStrategies', []); });
expect(vm.status).toEqual('failed'); expect(wrapper.vm.status).toEqual('failed');
}); });
}); });
describe('mergeButtonVariant', () => { describe('mergeButtonVariant', () => {
it('defaults to success class', () => { it('defaults to success class', () => {
Vue.set(vm.mr, 'availableAutoMergeStrategies', []); createComponent({
mr: { availableAutoMergeStrategies: [] },
});
expect(vm.mergeButtonVariant).toEqual('success'); expect(wrapper.vm.mergeButtonVariant).toEqual('success');
}); });
it('returns success class for success status', () => { it('returns success class for success status', () => {
Vue.set(vm.mr, 'availableAutoMergeStrategies', []); createComponent({
Vue.set(vm.mr, 'pipeline', true); mr: { availableAutoMergeStrategies: [], pipeline: true },
});
expect(vm.mergeButtonVariant).toEqual('success'); expect(wrapper.vm.mergeButtonVariant).toEqual('success');
}); });
it('returns info class for pending status', () => { it('returns info class for pending status', () => {
Vue.set(vm.mr, 'availableAutoMergeStrategies', [MTWPS_MERGE_STRATEGY]); createComponent();
expect(vm.mergeButtonVariant).toEqual('info'); expect(wrapper.vm.mergeButtonVariant).toEqual('info');
}); });
it('returns danger class for failed status', () => { it('returns danger class for failed status', () => {
vm.mr.hasCI = true; createComponent({ mr: { hasCI: true } });
expect(vm.mergeButtonVariant).toEqual('danger'); expect(wrapper.vm.mergeButtonVariant).toEqual('danger');
}); });
}); });
describe('status icon', () => { describe('status icon', () => {
it('defaults to tick icon', () => { it('defaults to tick icon', () => {
expect(vm.iconClass).toEqual('success'); createComponent();
expect(wrapper.vm.iconClass).toEqual('success');
}); });
it('shows tick for success status', () => { it('shows tick for success status', () => {
vm.mr.pipeline = true; createComponent({ mr: { pipeline: true } });
expect(vm.iconClass).toEqual('success'); expect(wrapper.vm.iconClass).toEqual('success');
}); });
it('shows tick for pending status', () => { it('shows tick for pending status', () => {
vm.mr.pipeline = {}; createComponent({ mr: { pipeline: {}, isPipelineActive: true } });
vm.mr.isPipelineActive = true;
expect(vm.iconClass).toEqual('success'); expect(wrapper.vm.iconClass).toEqual('success');
});
it('shows warning icon for failed status', () => {
vm.mr.hasCI = true;
expect(vm.iconClass).toEqual('warning');
});
it('shows warning icon for merge not allowed', () => {
vm.mr.hasCI = true;
expect(vm.iconClass).toEqual('warning');
}); });
}); });
describe('mergeButtonText', () => { describe('mergeButtonText', () => {
it('should return "Merge" when no auto merge strategies are available', () => { it('should return "Merge" when no auto merge strategies are available', () => {
Vue.set(vm.mr, 'availableAutoMergeStrategies', []); createComponent({ mr: { availableAutoMergeStrategies: [] } });
expect(vm.mergeButtonText).toEqual('Merge'); expect(wrapper.vm.mergeButtonText).toEqual('Merge');
}); });
it('should return "Merge in progress"', () => { it('should return "Merge in progress"', async () => {
Vue.set(vm, 'isMergingImmediately', true); createComponent();
wrapper.setData({ isMergingImmediately: true });
await Vue.nextTick();
expect(vm.mergeButtonText).toEqual('Merge in progress'); expect(wrapper.vm.mergeButtonText).toEqual('Merge in progress');
}); });
it('should return "Merge when pipeline succeeds" when the MWPS auto merge strategy is available', () => { it('should return "Merge when pipeline succeeds" when the MWPS auto merge strategy is available', () => {
Vue.set(vm, 'isMergingImmediately', false); createComponent({
Vue.set(vm.mr, 'preferredAutoMergeStrategy', MWPS_MERGE_STRATEGY); mr: { isMergingImmediately: false, preferredAutoMergeStrategy: MWPS_MERGE_STRATEGY },
});
expect(vm.mergeButtonText).toEqual('Merge when pipeline succeeds'); expect(wrapper.vm.mergeButtonText).toEqual('Merge when pipeline succeeds');
}); });
}); });
describe('autoMergeText', () => { describe('autoMergeText', () => {
it('should return Merge when pipeline succeeds', () => { it('should return Merge when pipeline succeeds', () => {
Vue.set(vm.mr, 'preferredAutoMergeStrategy', MWPS_MERGE_STRATEGY); createComponent({ mr: { preferredAutoMergeStrategy: MWPS_MERGE_STRATEGY } });
expect(vm.autoMergeText).toEqual('Merge when pipeline succeeds'); expect(wrapper.vm.autoMergeText).toEqual('Merge when pipeline succeeds');
}); });
}); });
describe('shouldShowMergeImmediatelyDropdown', () => { describe('shouldShowMergeImmediatelyDropdown', () => {
it('should return false if no pipeline is active', () => { it('should return false if no pipeline is active', () => {
Vue.set(vm.mr, 'isPipelineActive', false); createComponent({
Vue.set(vm.mr, 'onlyAllowMergeIfPipelineSucceeds', false); mr: { isPipelineActive: false, onlyAllowMergeIfPipelineSucceeds: false },
});
expect(vm.shouldShowMergeImmediatelyDropdown).toBe(false); expect(wrapper.vm.shouldShowMergeImmediatelyDropdown).toBe(false);
}); });
it('should return false if "Pipelines must succeed" is enabled for the current project', () => { it('should return false if "Pipelines must succeed" is enabled for the current project', () => {
Vue.set(vm.mr, 'isPipelineActive', true); createComponent({ mr: { isPipelineActive: true, onlyAllowMergeIfPipelineSucceeds: true } });
Vue.set(vm.mr, 'onlyAllowMergeIfPipelineSucceeds', true);
expect(vm.shouldShowMergeImmediatelyDropdown).toBe(false); expect(wrapper.vm.shouldShowMergeImmediatelyDropdown).toBe(false);
});
it('should return true if the MR\'s pipeline is active and "Pipelines must succeed" is not enabled for the current project', () => {
Vue.set(vm.mr, 'isPipelineActive', true);
Vue.set(vm.mr, 'onlyAllowMergeIfPipelineSucceeds', false);
expect(vm.shouldShowMergeImmediatelyDropdown).toBe(true);
}); });
}); });
describe('isMergeButtonDisabled', () => { describe('isMergeButtonDisabled', () => {
it('should return false with initial data', () => { it('should return false with initial data', () => {
Vue.set(vm.mr, 'isMergeAllowed', true); createComponent({ mr: { isMergeAllowed: true } });
expect(vm.isMergeButtonDisabled).toBe(false); expect(wrapper.vm.isMergeButtonDisabled).toBe(false);
}); });
it('should return true when there is no commit message', () => { it('should return true when there is no commit message', () => {
Vue.set(vm.mr, 'isMergeAllowed', true); createComponent({ mr: { isMergeAllowed: true, commitMessage: '' } });
Vue.set(vm, 'commitMessage', '');
expect(vm.isMergeButtonDisabled).toBe(true); expect(wrapper.vm.isMergeButtonDisabled).toBe(true);
}); });
it('should return true if merge is not allowed', () => { it('should return true if merge is not allowed', () => {
Vue.set(vm.mr, 'isMergeAllowed', false); createComponent({
Vue.set(vm.mr, 'availableAutoMergeStrategies', []); mr: {
Vue.set(vm.mr, 'onlyAllowMergeIfPipelineSucceeds', true); isMergeAllowed: false,
availableAutoMergeStrategies: [],
onlyAllowMergeIfPipelineSucceeds: true,
},
});
expect(vm.isMergeButtonDisabled).toBe(true); expect(wrapper.vm.isMergeButtonDisabled).toBe(true);
}); });
it('should return true when the vm instance is making request', () => { it('should return true when the vm instance is making request', async () => {
Vue.set(vm.mr, 'isMergeAllowed', true); createComponent({ mr: { isMergeAllowed: true } });
Vue.set(vm, 'isMakingRequest', true);
expect(vm.isMergeButtonDisabled).toBe(true); wrapper.setData({ isMakingRequest: true });
});
});
describe('isMergeImmediatelyDangerous', () => { await Vue.nextTick();
it('should always return false in CE', () => {
expect(vm.isMergeImmediatelyDangerous).toBe(false); expect(wrapper.vm.isMergeButtonDisabled).toBe(true);
}); });
}); });
}); });
describe('methods', () => { describe('methods', () => {
describe('shouldShowMergeControls', () => {
it('should return false when an external pipeline is running and required to succeed', () => {
Vue.set(vm.mr, 'isMergeAllowed', false);
Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
expect(vm.shouldShowMergeControls).toBe(false);
});
it('should return true when the build succeeded or build not required to succeed', () => {
Vue.set(vm.mr, 'isMergeAllowed', true);
Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
expect(vm.shouldShowMergeControls).toBe(true);
});
it('should return true when showing the MWPS button and a pipeline is running that needs to be successful', () => {
Vue.set(vm.mr, 'isMergeAllowed', false);
Vue.set(vm.mr, 'availableAutoMergeStrategies', [MWPS_MERGE_STRATEGY]);
expect(vm.shouldShowMergeControls).toBe(true);
});
it('should return true when showing the MWPS button but not required for the pipeline to succeed', () => {
Vue.set(vm.mr, 'isMergeAllowed', true);
Vue.set(vm.mr, 'availableAutoMergeStrategies', [MWPS_MERGE_STRATEGY]);
expect(vm.shouldShowMergeControls).toBe(true);
});
});
describe('updateMergeCommitMessage', () => { describe('updateMergeCommitMessage', () => {
it('should revert flag and change commitMessage', () => { it('should revert flag and change commitMessage', () => {
expect(vm.commitMessage).toEqual(commitMessage); createComponent();
vm.updateMergeCommitMessage(true);
wrapper.vm.updateMergeCommitMessage(true);
expect(vm.commitMessage).toEqual(commitMessageWithDescription); expect(wrapper.vm.commitMessage).toEqual(commitMessageWithDescription);
vm.updateMergeCommitMessage(false); wrapper.vm.updateMergeCommitMessage(false);
expect(vm.commitMessage).toEqual(commitMessage); expect(wrapper.vm.commitMessage).toEqual(commitMessage);
}); });
}); });
...@@ -356,23 +284,26 @@ describe('ReadyToMerge', () => { ...@@ -356,23 +284,26 @@ describe('ReadyToMerge', () => {
}); });
it('should handle merge when pipeline succeeds', (done) => { it('should handle merge when pipeline succeeds', (done) => {
createComponent();
jest.spyOn(eventHub, '$emit').mockImplementation(() => {}); jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
jest jest
.spyOn(vm.service, 'merge') .spyOn(wrapper.vm.service, 'merge')
.mockReturnValue(returnPromise('merge_when_pipeline_succeeds')); .mockReturnValue(returnPromise('merge_when_pipeline_succeeds'));
vm.removeSourceBranch = false; wrapper.setData({ removeSourceBranch: false });
vm.handleMergeButtonClick(true);
wrapper.vm.handleMergeButtonClick(true);
setImmediate(() => { setImmediate(() => {
expect(vm.isMakingRequest).toBeTruthy(); expect(wrapper.vm.isMakingRequest).toBeTruthy();
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested'); expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
const params = vm.service.merge.mock.calls[0][0]; const params = wrapper.vm.service.merge.mock.calls[0][0];
expect(params).toEqual( expect(params).toEqual(
expect.objectContaining({ expect.objectContaining({
sha: vm.mr.sha, sha: wrapper.vm.mr.sha,
commit_message: vm.mr.commitMessage, commit_message: wrapper.vm.mr.commitMessage,
should_remove_source_branch: false, should_remove_source_branch: false,
auto_merge_strategy: 'merge_when_pipeline_succeeds', auto_merge_strategy: 'merge_when_pipeline_succeeds',
}), }),
...@@ -382,15 +313,17 @@ describe('ReadyToMerge', () => { ...@@ -382,15 +313,17 @@ describe('ReadyToMerge', () => {
}); });
it('should handle merge failed', (done) => { it('should handle merge failed', (done) => {
createComponent();
jest.spyOn(eventHub, '$emit').mockImplementation(() => {}); jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
jest.spyOn(vm.service, 'merge').mockReturnValue(returnPromise('failed')); jest.spyOn(wrapper.vm.service, 'merge').mockReturnValue(returnPromise('failed'));
vm.handleMergeButtonClick(false, true); wrapper.vm.handleMergeButtonClick(false, true);
setImmediate(() => { setImmediate(() => {
expect(vm.isMakingRequest).toBeTruthy(); expect(wrapper.vm.isMakingRequest).toBeTruthy();
expect(eventHub.$emit).toHaveBeenCalledWith('FailedToMerge', undefined); expect(eventHub.$emit).toHaveBeenCalledWith('FailedToMerge', undefined);
const params = vm.service.merge.mock.calls[0][0]; const params = wrapper.vm.service.merge.mock.calls[0][0];
expect(params.should_remove_source_branch).toBeTruthy(); expect(params.should_remove_source_branch).toBeTruthy();
expect(params.auto_merge_strategy).toBeUndefined(); expect(params.auto_merge_strategy).toBeUndefined();
...@@ -399,15 +332,17 @@ describe('ReadyToMerge', () => { ...@@ -399,15 +332,17 @@ describe('ReadyToMerge', () => {
}); });
it('should handle merge action accepted case', (done) => { it('should handle merge action accepted case', (done) => {
jest.spyOn(vm.service, 'merge').mockReturnValue(returnPromise('success')); createComponent();
jest.spyOn(vm, 'initiateMergePolling').mockImplementation(() => {});
vm.handleMergeButtonClick(); jest.spyOn(wrapper.vm.service, 'merge').mockReturnValue(returnPromise('success'));
jest.spyOn(wrapper.vm, 'initiateMergePolling').mockImplementation(() => {});
wrapper.vm.handleMergeButtonClick();
setImmediate(() => { setImmediate(() => {
expect(vm.isMakingRequest).toBeTruthy(); expect(wrapper.vm.isMakingRequest).toBeTruthy();
expect(vm.initiateMergePolling).toHaveBeenCalled(); expect(wrapper.vm.initiateMergePolling).toHaveBeenCalled();
const params = vm.service.merge.mock.calls[0][0]; const params = wrapper.vm.service.merge.mock.calls[0][0];
expect(params.should_remove_source_branch).toBeTruthy(); expect(params.should_remove_source_branch).toBeTruthy();
expect(params.auto_merge_strategy).toBeUndefined(); expect(params.auto_merge_strategy).toBeUndefined();
...@@ -418,128 +353,31 @@ describe('ReadyToMerge', () => { ...@@ -418,128 +353,31 @@ describe('ReadyToMerge', () => {
describe('initiateMergePolling', () => { describe('initiateMergePolling', () => {
it('should call simplePoll', () => { it('should call simplePoll', () => {
vm.initiateMergePolling(); createComponent();
wrapper.vm.initiateMergePolling();
expect(simplePoll).toHaveBeenCalledWith(expect.any(Function), { timeout: 0 }); expect(simplePoll).toHaveBeenCalledWith(expect.any(Function), { timeout: 0 });
}); });
it('should call handleMergePolling', () => { it('should call handleMergePolling', () => {
jest.spyOn(vm, 'handleMergePolling').mockImplementation(() => {}); createComponent();
vm.initiateMergePolling();
expect(vm.handleMergePolling).toHaveBeenCalled();
});
});
describe('handleMergePolling', () => {
const returnPromise = (state) =>
new Promise((resolve) => {
resolve({
data: {
state,
source_branch_exists: true,
},
});
});
beforeEach(() => {
loadFixtures('merge_requests/merge_request_of_current_user.html');
});
it('should call start and stop polling when MR merged', (done) => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
jest.spyOn(vm.service, 'poll').mockReturnValue(returnPromise('merged'));
jest.spyOn(vm, 'initiateRemoveSourceBranchPolling').mockImplementation(() => {});
let cpc = false; // continuePollingCalled
let spc = false; // stopPollingCalled
vm.handleMergePolling(
() => {
cpc = true;
},
() => {
spc = true;
},
);
setImmediate(() => {
expect(vm.service.poll).toHaveBeenCalled();
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
expect(eventHub.$emit).toHaveBeenCalledWith('FetchActionsContent');
expect(vm.initiateRemoveSourceBranchPolling).toHaveBeenCalled();
expect(refreshUserMergeRequestCounts).toHaveBeenCalled();
expect(cpc).toBeFalsy();
expect(spc).toBeTruthy();
done(); jest.spyOn(wrapper.vm, 'handleMergePolling').mockImplementation(() => {});
});
});
it('updates status box', (done) => {
jest.spyOn(vm.service, 'poll').mockReturnValue(returnPromise('merged'));
jest.spyOn(vm, 'initiateRemoveSourceBranchPolling').mockImplementation(() => {});
vm.handleMergePolling(
() => {},
() => {},
);
setImmediate(() => {
const statusBox = document.querySelector('.status-box');
expect(statusBox.classList.contains('status-box-mr-merged')).toBeTruthy();
expect(statusBox.textContent).toContain('Merged');
done();
});
});
it('updates merge request count badge', (done) => {
jest.spyOn(vm.service, 'poll').mockReturnValue(returnPromise('merged'));
jest.spyOn(vm, 'initiateRemoveSourceBranchPolling').mockImplementation(() => {});
vm.handleMergePolling(
() => {},
() => {},
);
setImmediate(() => { wrapper.vm.initiateMergePolling();
expect(document.querySelector('.js-merge-counter').textContent).toBe('0');
done();
});
});
it('should continue polling until MR is merged', (done) => {
jest.spyOn(vm.service, 'poll').mockReturnValue(returnPromise('some_other_state'));
jest.spyOn(vm, 'initiateRemoveSourceBranchPolling').mockImplementation(() => {});
let cpc = false; // continuePollingCalled
let spc = false; // stopPollingCalled
vm.handleMergePolling(
() => {
cpc = true;
},
() => {
spc = true;
},
);
setImmediate(() => {
expect(cpc).toBeTruthy();
expect(spc).toBeFalsy();
done(); expect(wrapper.vm.handleMergePolling).toHaveBeenCalled();
});
}); });
}); });
describe('initiateRemoveSourceBranchPolling', () => { describe('initiateRemoveSourceBranchPolling', () => {
it('should emit event and call simplePoll', () => { it('should emit event and call simplePoll', () => {
createComponent();
jest.spyOn(eventHub, '$emit').mockImplementation(() => {}); jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
vm.initiateRemoveSourceBranchPolling(); wrapper.vm.initiateRemoveSourceBranchPolling();
expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [true]); expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [true]);
expect(simplePoll).toHaveBeenCalled(); expect(simplePoll).toHaveBeenCalled();
...@@ -557,13 +395,15 @@ describe('ReadyToMerge', () => { ...@@ -557,13 +395,15 @@ describe('ReadyToMerge', () => {
}); });
it('should call start and stop polling when MR merged', (done) => { it('should call start and stop polling when MR merged', (done) => {
createComponent();
jest.spyOn(eventHub, '$emit').mockImplementation(() => {}); jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
jest.spyOn(vm.service, 'poll').mockReturnValue(returnPromise(false)); jest.spyOn(wrapper.vm.service, 'poll').mockReturnValue(returnPromise(false));
let cpc = false; // continuePollingCalled let cpc = false; // continuePollingCalled
let spc = false; // stopPollingCalled let spc = false; // stopPollingCalled
vm.handleRemoveBranchPolling( wrapper.vm.handleRemoveBranchPolling(
() => { () => {
cpc = true; cpc = true;
}, },
...@@ -572,7 +412,7 @@ describe('ReadyToMerge', () => { ...@@ -572,7 +412,7 @@ describe('ReadyToMerge', () => {
}, },
); );
setImmediate(() => { setImmediate(() => {
expect(vm.service.poll).toHaveBeenCalled(); expect(wrapper.vm.service.poll).toHaveBeenCalled();
const args = eventHub.$emit.mock.calls[0]; const args = eventHub.$emit.mock.calls[0];
...@@ -590,12 +430,14 @@ describe('ReadyToMerge', () => { ...@@ -590,12 +430,14 @@ describe('ReadyToMerge', () => {
}); });
it('should continue polling until MR is merged', (done) => { it('should continue polling until MR is merged', (done) => {
jest.spyOn(vm.service, 'poll').mockReturnValue(returnPromise(true)); createComponent();
jest.spyOn(wrapper.vm.service, 'poll').mockReturnValue(returnPromise(true));
let cpc = false; // continuePollingCalled let cpc = false; // continuePollingCalled
let spc = false; // stopPollingCalled let spc = false; // stopPollingCalled
vm.handleRemoveBranchPolling( wrapper.vm.handleRemoveBranchPolling(
() => { () => {
cpc = true; cpc = true;
}, },
...@@ -616,49 +458,26 @@ describe('ReadyToMerge', () => { ...@@ -616,49 +458,26 @@ describe('ReadyToMerge', () => {
describe('Remove source branch checkbox', () => { describe('Remove source branch checkbox', () => {
describe('when user can merge but cannot delete branch', () => { describe('when user can merge but cannot delete branch', () => {
it('should be disabled in the rendered output', () => { it('should be disabled in the rendered output', () => {
const checkboxElement = vm.$el.querySelector('#remove-source-branch-input'); createComponent();
expect(checkboxElement).toBeNull(); expect(wrapper.find('#remove-source-branch-input').exists()).toBe(false);
}); });
}); });
describe('when user can merge and can delete branch', () => { describe('when user can merge and can delete branch', () => {
beforeEach(() => { beforeEach(() => {
vm = createComponent({ createComponent({
mr: { canRemoveSourceBranch: true }, mr: { canRemoveSourceBranch: true },
}); });
}); });
it('isRemoveSourceBranchButtonDisabled should be false', () => { it('isRemoveSourceBranchButtonDisabled should be false', () => {
expect(vm.isRemoveSourceBranchButtonDisabled).toBe(false); expect(wrapper.find('#remove-source-branch-input').props('disabled')).toBe(undefined);
});
it('removed source branch should be enabled in rendered output', () => {
const checkboxElement = vm.$el.querySelector('#remove-source-branch-input');
expect(checkboxElement).not.toBeNull();
}); });
}); });
}); });
describe('render children components', () => { describe('render children components', () => {
let wrapper;
const localVue = createLocalVue();
const createLocalComponent = (customConfig = {}) => {
wrapper = shallowMount(localVue.extend(ReadyToMerge), {
localVue,
propsData: {
mr: createTestMr(customConfig),
service: createTestService(),
},
});
};
afterEach(() => {
wrapper.destroy();
});
const findCheckboxElement = () => wrapper.find(SquashBeforeMerge); const findCheckboxElement = () => wrapper.find(SquashBeforeMerge);
const findCommitsHeaderElement = () => wrapper.find(CommitsHeader); const findCommitsHeaderElement = () => wrapper.find(CommitsHeader);
const findCommitEditElements = () => wrapper.findAll(CommitEdit); const findCommitEditElements = () => wrapper.findAll(CommitEdit);
...@@ -667,7 +486,7 @@ describe('ReadyToMerge', () => { ...@@ -667,7 +486,7 @@ describe('ReadyToMerge', () => {
describe('squash checkbox', () => { describe('squash checkbox', () => {
it('should be rendered when squash before merge is enabled and there is more than 1 commit', () => { it('should be rendered when squash before merge is enabled and there is more than 1 commit', () => {
createLocalComponent({ createComponent({
mr: { commitsCount: 2, enableSquashBeforeMerge: true }, mr: { commitsCount: 2, enableSquashBeforeMerge: true },
}); });
...@@ -675,13 +494,13 @@ describe('ReadyToMerge', () => { ...@@ -675,13 +494,13 @@ describe('ReadyToMerge', () => {
}); });
it('should not be rendered when squash before merge is disabled', () => { it('should not be rendered when squash before merge is disabled', () => {
createLocalComponent({ mr: { commitsCount: 2, enableSquashBeforeMerge: false } }); createComponent({ mr: { commitsCount: 2, enableSquashBeforeMerge: false } });
expect(findCheckboxElement().exists()).toBeFalsy(); expect(findCheckboxElement().exists()).toBeFalsy();
}); });
it('should not be rendered when there is only 1 commit', () => { it('should not be rendered when there is only 1 commit', () => {
createLocalComponent({ mr: { commitsCount: 1, enableSquashBeforeMerge: true } }); createComponent({ mr: { commitsCount: 1, enableSquashBeforeMerge: true } });
expect(findCheckboxElement().exists()).toBeFalsy(); expect(findCheckboxElement().exists()).toBeFalsy();
}); });
...@@ -695,7 +514,7 @@ describe('ReadyToMerge', () => { ...@@ -695,7 +514,7 @@ describe('ReadyToMerge', () => {
`( `(
'is $state when squashIsReadonly returns $expectation ', 'is $state when squashIsReadonly returns $expectation ',
({ squashState, prop, expectation }) => { ({ squashState, prop, expectation }) => {
createLocalComponent({ createComponent({
mr: { commitsCount: 2, enableSquashBeforeMerge: true, [squashState]: expectation }, mr: { commitsCount: 2, enableSquashBeforeMerge: true, [squashState]: expectation },
}); });
...@@ -704,7 +523,7 @@ describe('ReadyToMerge', () => { ...@@ -704,7 +523,7 @@ describe('ReadyToMerge', () => {
); );
it('is not rendered for "Do not allow" option', () => { it('is not rendered for "Do not allow" option', () => {
createLocalComponent({ createComponent({
mr: { mr: {
commitsCount: 2, commitsCount: 2,
enableSquashBeforeMerge: true, enableSquashBeforeMerge: true,
...@@ -720,14 +539,14 @@ describe('ReadyToMerge', () => { ...@@ -720,14 +539,14 @@ describe('ReadyToMerge', () => {
describe('commits count collapsible header', () => { describe('commits count collapsible header', () => {
it('should be rendered when fast-forward is disabled', () => { it('should be rendered when fast-forward is disabled', () => {
createLocalComponent(); createComponent();
expect(findCommitsHeaderElement().exists()).toBeTruthy(); expect(findCommitsHeaderElement().exists()).toBeTruthy();
}); });
describe('when fast-forward is enabled', () => { describe('when fast-forward is enabled', () => {
it('should be rendered if squash and squash before are enabled and there is more than 1 commit', () => { it('should be rendered if squash and squash before are enabled and there is more than 1 commit', () => {
createLocalComponent({ createComponent({
mr: { mr: {
ffOnlyEnabled: true, ffOnlyEnabled: true,
enableSquashBeforeMerge: true, enableSquashBeforeMerge: true,
...@@ -740,7 +559,7 @@ describe('ReadyToMerge', () => { ...@@ -740,7 +559,7 @@ describe('ReadyToMerge', () => {
}); });
it('should not be rendered if squash before merge is disabled', () => { it('should not be rendered if squash before merge is disabled', () => {
createLocalComponent({ createComponent({
mr: { mr: {
ffOnlyEnabled: true, ffOnlyEnabled: true,
enableSquashBeforeMerge: false, enableSquashBeforeMerge: false,
...@@ -753,7 +572,7 @@ describe('ReadyToMerge', () => { ...@@ -753,7 +572,7 @@ describe('ReadyToMerge', () => {
}); });
it('should not be rendered if squash is disabled', () => { it('should not be rendered if squash is disabled', () => {
createLocalComponent({ createComponent({
mr: { mr: {
ffOnlyEnabled: true, ffOnlyEnabled: true,
squash: false, squash: false,
...@@ -766,7 +585,7 @@ describe('ReadyToMerge', () => { ...@@ -766,7 +585,7 @@ describe('ReadyToMerge', () => {
}); });
it('should not be rendered if commits count is 1', () => { it('should not be rendered if commits count is 1', () => {
createLocalComponent({ createComponent({
mr: { mr: {
ffOnlyEnabled: true, ffOnlyEnabled: true,
squash: true, squash: true,
...@@ -783,7 +602,7 @@ describe('ReadyToMerge', () => { ...@@ -783,7 +602,7 @@ describe('ReadyToMerge', () => {
describe('commits edit components', () => { describe('commits edit components', () => {
describe('when fast-forward merge is enabled', () => { describe('when fast-forward merge is enabled', () => {
it('should not be rendered if squash is disabled', () => { it('should not be rendered if squash is disabled', () => {
createLocalComponent({ createComponent({
mr: { mr: {
ffOnlyEnabled: true, ffOnlyEnabled: true,
squash: false, squash: false,
...@@ -796,7 +615,7 @@ describe('ReadyToMerge', () => { ...@@ -796,7 +615,7 @@ describe('ReadyToMerge', () => {
}); });
it('should not be rendered if squash before merge is disabled', () => { it('should not be rendered if squash before merge is disabled', () => {
createLocalComponent({ createComponent({
mr: { mr: {
ffOnlyEnabled: true, ffOnlyEnabled: true,
squash: true, squash: true,
...@@ -809,7 +628,7 @@ describe('ReadyToMerge', () => { ...@@ -809,7 +628,7 @@ describe('ReadyToMerge', () => {
}); });
it('should not be rendered if there is only one commit', () => { it('should not be rendered if there is only one commit', () => {
createLocalComponent({ createComponent({
mr: { mr: {
ffOnlyEnabled: true, ffOnlyEnabled: true,
squash: true, squash: true,
...@@ -822,7 +641,7 @@ describe('ReadyToMerge', () => { ...@@ -822,7 +641,7 @@ describe('ReadyToMerge', () => {
}); });
it('should have one edit component if squash is enabled and there is more than 1 commit', () => { it('should have one edit component if squash is enabled and there is more than 1 commit', () => {
createLocalComponent({ createComponent({
mr: { mr: {
ffOnlyEnabled: true, ffOnlyEnabled: true,
squashIsSelected: true, squashIsSelected: true,
...@@ -837,13 +656,13 @@ describe('ReadyToMerge', () => { ...@@ -837,13 +656,13 @@ describe('ReadyToMerge', () => {
}); });
it('should have one edit component when squash is disabled', () => { it('should have one edit component when squash is disabled', () => {
createLocalComponent(); createComponent();
expect(findCommitEditElements().length).toBe(1); expect(findCommitEditElements().length).toBe(1);
}); });
it('should have two edit components when squash is enabled and there is more than 1 commit', () => { it('should have two edit components when squash is enabled and there is more than 1 commit', () => {
createLocalComponent({ createComponent({
mr: { mr: {
commitsCount: 2, commitsCount: 2,
squashIsSelected: true, squashIsSelected: true,
...@@ -855,7 +674,7 @@ describe('ReadyToMerge', () => { ...@@ -855,7 +674,7 @@ describe('ReadyToMerge', () => {
}); });
it('should have one edit components when squash is enabled and there is 1 commit only', () => { it('should have one edit components when squash is enabled and there is 1 commit only', () => {
createLocalComponent({ createComponent({
mr: { mr: {
commitsCount: 1, commitsCount: 1,
squash: true, squash: true,
...@@ -867,13 +686,13 @@ describe('ReadyToMerge', () => { ...@@ -867,13 +686,13 @@ describe('ReadyToMerge', () => {
}); });
it('should have correct edit merge commit label', () => { it('should have correct edit merge commit label', () => {
createLocalComponent(); createComponent();
expect(findFirstCommitEditLabel()).toBe('Merge commit message'); expect(findFirstCommitEditLabel()).toBe('Merge commit message');
}); });
it('should have correct edit squash commit label', () => { it('should have correct edit squash commit label', () => {
createLocalComponent({ createComponent({
mr: { mr: {
commitsCount: 2, commitsCount: 2,
squashIsSelected: true, squashIsSelected: true,
...@@ -887,13 +706,13 @@ describe('ReadyToMerge', () => { ...@@ -887,13 +706,13 @@ describe('ReadyToMerge', () => {
describe('commits dropdown', () => { describe('commits dropdown', () => {
it('should not be rendered if squash is disabled', () => { it('should not be rendered if squash is disabled', () => {
createLocalComponent(); createComponent();
expect(findCommitDropdownElement().exists()).toBeFalsy(); expect(findCommitDropdownElement().exists()).toBeFalsy();
}); });
it('should be rendered if squash is enabled and there is more than 1 commit', () => { it('should be rendered if squash is enabled and there is more than 1 commit', () => {
createLocalComponent({ createComponent({
mr: { enableSquashBeforeMerge: true, squashIsSelected: true, commitsCount: 2 }, mr: { enableSquashBeforeMerge: true, squashIsSelected: true, commitsCount: 2 },
}); });
...@@ -902,83 +721,38 @@ describe('ReadyToMerge', () => { ...@@ -902,83 +721,38 @@ describe('ReadyToMerge', () => {
}); });
}); });
describe('Merge controls', () => {
describe('when allowed to merge', () => {
beforeEach(() => {
vm = createComponent({
mr: { isMergeAllowed: true, canRemoveSourceBranch: true },
});
});
it('shows remove source branch checkbox', () => {
expect(vm.$el.querySelector('.js-remove-source-branch-checkbox')).not.toBeNull();
});
it('shows modify commit message button', () => {
expect(vm.$el.querySelector('.js-modify-commit-message-button')).toBeDefined();
});
it('does not show message about needing to resolve items', () => {
expect(vm.$el.querySelector('.js-resolve-mr-widget-items-message')).toBeNull();
});
});
describe('when not allowed to merge', () => {
beforeEach(() => {
vm = createComponent({
mr: { isMergeAllowed: false },
});
});
it('does not show remove source branch checkbox', () => {
expect(vm.$el.querySelector('.js-remove-source-branch-checkbox')).toBeNull();
});
it('shows message to resolve all items before being allowed to merge', () => {
expect(vm.$el.querySelector('.js-resolve-mr-widget-items-message')).toBeDefined();
});
});
});
describe('Merge request project settings', () => { describe('Merge request project settings', () => {
describe('when the merge commit merge method is enabled', () => { describe('when the merge commit merge method is enabled', () => {
beforeEach(() => { beforeEach(() => {
vm = createComponent({ createComponent({
mr: { ffOnlyEnabled: false }, mr: { ffOnlyEnabled: false },
}); });
}); });
it('should not show fast forward message', () => { it('should not show fast forward message', () => {
expect(vm.$el.querySelector('.mr-fast-forward-message')).toBeNull(); expect(wrapper.find('.mr-fast-forward-message').exists()).toBe(false);
});
it('should show "Modify commit message" button', () => {
expect(vm.$el.querySelector('.js-modify-commit-message-button')).toBeDefined();
}); });
}); });
describe('when the fast-forward merge method is enabled', () => { describe('when the fast-forward merge method is enabled', () => {
beforeEach(() => { beforeEach(() => {
vm = createComponent({ createComponent({
mr: { ffOnlyEnabled: true }, mr: { ffOnlyEnabled: true },
}); });
}); });
it('should show fast forward message', () => { it('should show fast forward message', () => {
expect(vm.$el.querySelector('.mr-fast-forward-message')).toBeDefined(); expect(wrapper.find('.mr-fast-forward-message').exists()).toBe(true);
});
it('should not show "Modify commit message" button', () => {
expect(vm.$el.querySelector('.js-modify-commit-message-button')).toBeNull();
}); });
}); });
}); });
describe('with a mismatched SHA', () => { describe('with a mismatched SHA', () => {
const findMismatchShaBlock = () => vm.$el.querySelector('.js-sha-mismatch'); const findMismatchShaBlock = () => wrapper.find('.js-sha-mismatch');
const findMismatchShaTextBlock = () => findMismatchShaBlock().find(GlSprintf);
beforeEach(() => { beforeEach(() => {
vm = createComponent({ createComponent({
mr: { mr: {
isSHAMismatch: true, isSHAMismatch: true,
mergeRequestDiffsPath: '/merge_requests/1/diffs', mergeRequestDiffsPath: '/merge_requests/1/diffs',
...@@ -987,17 +761,11 @@ describe('ReadyToMerge', () => { ...@@ -987,17 +761,11 @@ describe('ReadyToMerge', () => {
}); });
it('displays a warning message', () => { it('displays a warning message', () => {
expect(findMismatchShaBlock()).toExist(); expect(findMismatchShaBlock().exists()).toBe(true);
}); });
it('warns the user to refresh to review', () => { it('warns the user to refresh to review', () => {
expect(findMismatchShaBlock().textContent.trim()).toBe( expect(findMismatchShaTextBlock().element.outerHTML).toMatchSnapshot();
'New changes were added. Reload the page to review them',
);
});
it('displays link to the diffs tab', () => {
expect(findMismatchShaBlock().querySelector('a').href).toContain(vm.mr.mergeRequestDiffsPath);
}); });
}); });
}); });
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