Commit a1c68dae authored by Paul Slaughter's avatar Paul Slaughter

Clean mr_widget_options_spec from zombies

- Also installs mock timer globally since the component
kicks off polls on every mount
parent 7b369783
import Vue from 'vue'; import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
import waitForPromises from 'spec/helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import mrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue'; import mrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
import eventHub from '~/vue_merge_request_widget/event_hub'; import eventHub from '~/vue_merge_request_widget/event_hub';
...@@ -25,6 +26,7 @@ describe('mrWidgetOptions', () => { ...@@ -25,6 +26,7 @@ describe('mrWidgetOptions', () => {
const COLLABORATION_MESSAGE = 'Allows commits from members who can merge to the target branch'; const COLLABORATION_MESSAGE = 'Allows commits from members who can merge to the target branch';
beforeEach(() => { beforeEach(() => {
jasmine.clock().install();
// Prevent component mounting // Prevent component mounting
delete mrWidgetOptions.el; delete mrWidgetOptions.el;
...@@ -36,729 +38,591 @@ describe('mrWidgetOptions', () => { ...@@ -36,729 +38,591 @@ describe('mrWidgetOptions', () => {
mock.onGet(mockData.merge_request_cached_widget_path).reply(() => [200, { ...mockData }]); mock.onGet(mockData.merge_request_cached_widget_path).reply(() => [200, { ...mockData }]);
MrWidgetOptions = Vue.extend(mrWidgetOptions); MrWidgetOptions = Vue.extend(mrWidgetOptions);
vm = mountComponent(MrWidgetOptions, {
mrData: { ...mockData },
});
}); });
afterEach(() => { afterEach(() => {
vm.$destroy(); jasmine.clock().uninstall();
mock.restore(); mock.restore();
vm.$destroy();
vm = null;
gl.mrWidgetData = {}; gl.mrWidgetData = {};
gon.features = {}; gon.features = {};
}); });
describe('data', () => { const createComponent = () => {
it('should instantiate Store and Service', () => { if (vm) {
expect(vm.mr).toBeDefined(); vm.$destroy();
expect(vm.service).toBeDefined(); }
});
});
describe('computed', () => { vm = mountComponent(MrWidgetOptions, {
describe('componentName', () => { mrData: { ...mockData },
it('should return merged component', () => { });
expect(vm.componentName).toEqual('mr-widget-merged'); };
});
it('should return conflicts component', () => { describe('default', () => {
vm.mr.state = 'conflicts'; beforeEach(() => {
createComponent();
});
expect(vm.componentName).toEqual('mr-widget-conflicts'); describe('data', () => {
it('should instantiate Store and Service', () => {
expect(vm.mr).toBeDefined();
expect(vm.service).toBeDefined();
}); });
}); });
describe('shouldRenderMergeHelp', () => { describe('computed', () => {
it('should return false for the initial merged state', () => { describe('componentName', () => {
expect(vm.shouldRenderMergeHelp).toBeFalsy(); it('should return merged component', () => {
}); expect(vm.componentName).toEqual('mr-widget-merged');
});
it('should return true for a state which requires help widget', () => { it('should return conflicts component', () => {
vm.mr.state = 'conflicts'; vm.mr.state = 'conflicts';
expect(vm.shouldRenderMergeHelp).toBeTruthy(); expect(vm.componentName).toEqual('mr-widget-conflicts');
});
}); });
});
describe('shouldRenderPipelines', () => {
it('should return true when hasCI is true', () => {
vm.mr.hasCI = true;
expect(vm.shouldRenderPipelines).toBeTruthy(); describe('shouldRenderMergeHelp', () => {
}); it('should return false for the initial merged state', () => {
expect(vm.shouldRenderMergeHelp).toBeFalsy();
});
it('should return false when hasCI is false', () => { it('should return true for a state which requires help widget', () => {
vm.mr.hasCI = false; vm.mr.state = 'conflicts';
expect(vm.shouldRenderPipelines).toBeFalsy(); expect(vm.shouldRenderMergeHelp).toBeTruthy();
});
}); });
});
describe('shouldSuggestPipelines', () => { describe('shouldRenderPipelines', () => {
describe('given suggestPipeline feature flag is enabled', () => { it('should return true when hasCI is true', () => {
beforeEach(() => { vm.mr.hasCI = true;
gon.features = { suggestPipeline: true };
vm = mountComponent(MrWidgetOptions, {
mrData: { ...mockData },
});
});
afterEach(() => { expect(vm.shouldRenderPipelines).toBeTruthy();
gon.features = {};
}); });
it('should suggest pipelines when none exist', () => { it('should return false when hasCI is false', () => {
vm.mr.mergeRequestAddCiConfigPath = 'some/path';
vm.mr.hasCI = false; vm.mr.hasCI = false;
expect(vm.shouldSuggestPipelines).toBeTruthy(); expect(vm.shouldRenderPipelines).toBeFalsy();
}); });
});
it('should not suggest pipelines when they exist', () => { describe('shouldRenderRelatedLinks', () => {
vm.mr.mergeRequestAddCiConfigPath = null; it('should return false for the initial data', () => {
vm.mr.hasCI = false; expect(vm.shouldRenderRelatedLinks).toBeFalsy();
expect(vm.shouldSuggestPipelines).toBeFalsy();
}); });
it('should not suggest pipelines hasCI is true', () => { it('should return true if there is relatedLinks in MR', () => {
vm.mr.mergeRequestAddCiConfigPath = 'some/path'; Vue.set(vm.mr, 'relatedLinks', {});
vm.mr.hasCI = true;
expect(vm.shouldSuggestPipelines).toBeFalsy(); expect(vm.shouldRenderRelatedLinks).toBeTruthy();
}); });
}); });
describe('given suggestPipeline feature flag is not enabled', () => { describe('shouldRenderSourceBranchRemovalStatus', () => {
beforeEach(() => { beforeEach(() => {
gon.features = { suggestPipeline: false }; vm.mr.state = 'readyToMerge';
vm = mountComponent(MrWidgetOptions, {
mrData: { ...mockData },
});
}); });
afterEach(() => { it('should return true when cannot remove source branch and branch will be removed', () => {
gon.features = {}; vm.mr.canRemoveSourceBranch = false;
vm.mr.shouldRemoveSourceBranch = true;
expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(true);
}); });
it('should not suggest pipelines', () => { it('should return false when can remove source branch and branch will be removed', () => {
vm.mr.mergeRequestAddCiConfigPath = null; vm.mr.canRemoveSourceBranch = true;
vm.mr.shouldRemoveSourceBranch = true;
expect(vm.shouldSuggestPipelines).toBeFalsy(); expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
}); });
});
});
describe('shouldRenderRelatedLinks', () => { it('should return false when cannot remove source branch and branch will not be removed', () => {
it('should return false for the initial data', () => { vm.mr.canRemoveSourceBranch = false;
expect(vm.shouldRenderRelatedLinks).toBeFalsy(); vm.mr.shouldRemoveSourceBranch = false;
});
it('should return true if there is relatedLinks in MR', () => { expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
Vue.set(vm.mr, 'relatedLinks', {}); });
expect(vm.shouldRenderRelatedLinks).toBeTruthy(); it('should return false when in merged state', () => {
}); vm.mr.canRemoveSourceBranch = false;
}); vm.mr.shouldRemoveSourceBranch = true;
vm.mr.state = 'merged';
describe('shouldRenderSourceBranchRemovalStatus', () => { expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
beforeEach(() => { });
vm.mr.state = 'readyToMerge';
});
it('should return true when cannot remove source branch and branch will be removed', () => { it('should return false when in nothing to merge state', () => {
vm.mr.canRemoveSourceBranch = false; vm.mr.canRemoveSourceBranch = false;
vm.mr.shouldRemoveSourceBranch = true; vm.mr.shouldRemoveSourceBranch = true;
vm.mr.state = 'nothingToMerge';
expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(true); expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
});
}); });
it('should return false when can remove source branch and branch will be removed', () => { describe('shouldRenderCollaborationStatus', () => {
vm.mr.canRemoveSourceBranch = true; describe('when collaboration is allowed', () => {
vm.mr.shouldRemoveSourceBranch = true; beforeEach(() => {
vm.mr.allowCollaboration = true;
expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false); });
});
it('should return false when cannot remove source branch and branch will not be removed', () => { describe('when merge request is opened', () => {
vm.mr.canRemoveSourceBranch = false; beforeEach(done => {
vm.mr.shouldRemoveSourceBranch = false; vm.mr.isOpen = true;
vm.$nextTick(done);
});
expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false); it('should render collaboration status', () => {
}); expect(vm.$el.textContent).toContain(COLLABORATION_MESSAGE);
});
});
it('should return false when in merged state', () => { describe('when merge request is not opened', () => {
vm.mr.canRemoveSourceBranch = false; beforeEach(done => {
vm.mr.shouldRemoveSourceBranch = true; vm.mr.isOpen = false;
vm.mr.state = 'merged'; vm.$nextTick(done);
});
expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false); it('should not render collaboration status', () => {
}); expect(vm.$el.textContent).not.toContain(COLLABORATION_MESSAGE);
});
});
});
it('should return false when in nothing to merge state', () => { describe('when collaboration is not allowed', () => {
vm.mr.canRemoveSourceBranch = false; beforeEach(() => {
vm.mr.shouldRemoveSourceBranch = true; vm.mr.allowCollaboration = false;
vm.mr.state = 'nothingToMerge'; });
expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false); describe('when merge request is opened', () => {
}); beforeEach(done => {
}); vm.mr.isOpen = true;
vm.$nextTick(done);
});
describe('shouldRenderCollaborationStatus', () => { it('should not render collaboration status', () => {
describe('when collaboration is allowed', () => { expect(vm.$el.textContent).not.toContain(COLLABORATION_MESSAGE);
beforeEach(() => { });
vm.mr.allowCollaboration = true; });
}); });
});
describe('when merge request is opened', () => { describe('showMergePipelineForkWarning', () => {
describe('when the source project and target project are the same', () => {
beforeEach(done => { beforeEach(done => {
vm.mr.isOpen = true; Vue.set(vm.mr, 'mergePipelinesEnabled', true);
Vue.set(vm.mr, 'sourceProjectId', 1);
Vue.set(vm.mr, 'targetProjectId', 1);
vm.$nextTick(done); vm.$nextTick(done);
}); });
it('should render collaboration status', () => { it('should be false', () => {
expect(vm.$el.textContent).toContain(COLLABORATION_MESSAGE); expect(vm.showMergePipelineForkWarning).toEqual(false);
}); });
}); });
describe('when merge request is not opened', () => { describe('when merge pipelines are not enabled', () => {
beforeEach(done => { beforeEach(done => {
vm.mr.isOpen = false; Vue.set(vm.mr, 'mergePipelinesEnabled', false);
Vue.set(vm.mr, 'sourceProjectId', 1);
Vue.set(vm.mr, 'targetProjectId', 2);
vm.$nextTick(done); vm.$nextTick(done);
}); });
it('should not render collaboration status', () => { it('should be false', () => {
expect(vm.$el.textContent).not.toContain(COLLABORATION_MESSAGE); expect(vm.showMergePipelineForkWarning).toEqual(false);
}); });
}); });
});
describe('when collaboration is not allowed', () => { describe('when merge pipelines are enabled _and_ the source project and target project are different', () => {
beforeEach(() => {
vm.mr.allowCollaboration = false;
});
describe('when merge request is opened', () => {
beforeEach(done => { beforeEach(done => {
vm.mr.isOpen = true; Vue.set(vm.mr, 'mergePipelinesEnabled', true);
Vue.set(vm.mr, 'sourceProjectId', 1);
Vue.set(vm.mr, 'targetProjectId', 2);
vm.$nextTick(done); vm.$nextTick(done);
}); });
it('should not render collaboration status', () => { it('should be true', () => {
expect(vm.$el.textContent).not.toContain(COLLABORATION_MESSAGE); expect(vm.showMergePipelineForkWarning).toEqual(true);
}); });
}); });
}); });
}); });
describe('showMergePipelineForkWarning', () => { describe('methods', () => {
describe('when the source project and target project are the same', () => { describe('checkStatus', () => {
beforeEach(done => { it('should tell service to check status', () => {
Vue.set(vm.mr, 'mergePipelinesEnabled', true); spyOn(vm.service, 'checkStatus').and.returnValue(returnPromise(mockData));
Vue.set(vm.mr, 'sourceProjectId', 1); spyOn(vm.mr, 'setData');
Vue.set(vm.mr, 'targetProjectId', 1); spyOn(vm, 'handleNotification');
vm.$nextTick(done);
});
it('should be false', () => { let isCbExecuted = false;
expect(vm.showMergePipelineForkWarning).toEqual(false); const cb = () => {
}); isCbExecuted = true;
}); };
describe('when merge pipelines are not enabled', () => {
beforeEach(done => {
Vue.set(vm.mr, 'mergePipelinesEnabled', false);
Vue.set(vm.mr, 'sourceProjectId', 1);
Vue.set(vm.mr, 'targetProjectId', 2);
vm.$nextTick(done);
});
it('should be false', () => {
expect(vm.showMergePipelineForkWarning).toEqual(false);
});
});
describe('when merge pipelines are enabled _and_ the source project and target project are different', () => { vm.checkStatus(cb);
beforeEach(done => {
Vue.set(vm.mr, 'mergePipelinesEnabled', true);
Vue.set(vm.mr, 'sourceProjectId', 1);
Vue.set(vm.mr, 'targetProjectId', 2);
vm.$nextTick(done);
});
it('should be true', () => { return vm.$nextTick().then(() => {
expect(vm.showMergePipelineForkWarning).toEqual(true); expect(vm.service.checkStatus).toHaveBeenCalled();
expect(vm.mr.setData).toHaveBeenCalled();
expect(vm.handleNotification).toHaveBeenCalledWith(mockData);
expect(isCbExecuted).toBeTruthy();
});
}); });
}); });
});
});
describe('methods', () => {
describe('checkStatus', () => {
it('should tell service to check status', done => {
spyOn(vm.service, 'checkStatus').and.returnValue(returnPromise(mockData));
spyOn(vm.mr, 'setData');
spyOn(vm, 'handleNotification');
let isCbExecuted = false;
const cb = () => {
isCbExecuted = true;
};
vm.checkStatus(cb);
setTimeout(() => {
expect(vm.service.checkStatus).toHaveBeenCalled();
expect(vm.mr.setData).toHaveBeenCalled();
expect(vm.handleNotification).toHaveBeenCalledWith(mockData);
expect(isCbExecuted).toBeTruthy();
done();
}, 333);
});
});
describe('initPolling', () => { describe('initPolling', () => {
it('should call SmartInterval', () => { it('should call SmartInterval', () => {
spyOn(vm, 'checkStatus').and.returnValue(Promise.resolve()); spyOn(vm, 'checkStatus').and.returnValue(Promise.resolve());
jasmine.clock().install(); vm.initPolling();
vm.initPolling();
expect(vm.checkStatus).not.toHaveBeenCalled(); expect(vm.checkStatus).not.toHaveBeenCalled();
jasmine.clock().tick(10000); jasmine.clock().tick(10000);
expect(vm.pollingInterval).toBeDefined(); expect(vm.pollingInterval).toBeDefined();
expect(vm.checkStatus).toHaveBeenCalled(); expect(vm.checkStatus).toHaveBeenCalled();
});
jasmine.clock().uninstall();
}); });
});
describe('initDeploymentsPolling', () => { describe('initDeploymentsPolling', () => {
it('should call SmartInterval', () => { it('should call SmartInterval', () => {
spyOn(vm, 'fetchDeployments').and.returnValue(Promise.resolve()); spyOn(vm, 'fetchDeployments').and.returnValue(Promise.resolve());
vm.initDeploymentsPolling(); vm.initDeploymentsPolling();
expect(vm.deploymentsInterval).toBeDefined(); expect(vm.deploymentsInterval).toBeDefined();
expect(vm.fetchDeployments).toHaveBeenCalled(); expect(vm.fetchDeployments).toHaveBeenCalled();
});
}); });
});
describe('fetchDeployments', () => { describe('fetchDeployments', () => {
it('should fetch deployments', done => { it('should fetch deployments', () => {
spyOn(vm.service, 'fetchDeployments').and.returnValue( spyOn(vm.service, 'fetchDeployments').and.returnValue(
returnPromise([{ id: 1, status: SUCCESS }]), returnPromise([{ id: 1, status: SUCCESS }]),
); );
vm.fetchPreMergeDeployments(); vm.fetchPreMergeDeployments();
setTimeout(() => { return vm.$nextTick().then(() => {
expect(vm.service.fetchDeployments).toHaveBeenCalled(); expect(vm.service.fetchDeployments).toHaveBeenCalled();
expect(vm.mr.deployments.length).toEqual(1); expect(vm.mr.deployments.length).toEqual(1);
expect(vm.mr.deployments[0].id).toBe(1); expect(vm.mr.deployments[0].id).toBe(1);
done(); });
}); });
}); });
});
describe('fetchActionsContent', () => { describe('fetchActionsContent', () => {
it('should fetch content of Cherry Pick and Revert modals', done => { it('should fetch content of Cherry Pick and Revert modals', () => {
spyOn(vm.service, 'fetchMergeActionsContent').and.returnValue(returnPromise('hello world')); spyOn(vm.service, 'fetchMergeActionsContent').and.returnValue(
returnPromise('hello world'),
);
vm.fetchActionsContent(); vm.fetchActionsContent();
setTimeout(() => { return vm.$nextTick().then(() => {
expect(vm.service.fetchMergeActionsContent).toHaveBeenCalled(); expect(vm.service.fetchMergeActionsContent).toHaveBeenCalled();
expect(document.body.textContent).toContain('hello world'); expect(document.body.textContent).toContain('hello world');
done(); });
}, 333); });
}); });
});
describe('bindEventHubListeners', () => { describe('bindEventHubListeners', () => {
it('should bind eventHub listeners', done => { it('should bind eventHub listeners', () => {
spyOn(vm, 'checkStatus').and.returnValue(() => {}); spyOn(vm, 'checkStatus').and.returnValue(() => {});
spyOn(vm.service, 'checkStatus').and.returnValue(returnPromise(mockData)); spyOn(vm.service, 'checkStatus').and.returnValue(returnPromise(mockData));
spyOn(vm, 'fetchActionsContent'); spyOn(vm, 'fetchActionsContent');
spyOn(vm.mr, 'setData'); spyOn(vm.mr, 'setData');
spyOn(vm, 'resumePolling'); spyOn(vm, 'resumePolling');
spyOn(vm, 'stopPolling'); spyOn(vm, 'stopPolling');
spyOn(eventHub, '$on').and.callThrough(); spyOn(eventHub, '$on').and.callThrough();
setTimeout(() => { return waitForPromises().then(() => {
eventHub.$emit('SetBranchRemoveFlag', ['flag']); eventHub.$emit('SetBranchRemoveFlag', ['flag']);
expect(vm.mr.isRemovingSourceBranch).toEqual('flag'); expect(vm.mr.isRemovingSourceBranch).toEqual('flag');
eventHub.$emit('FailedToMerge'); eventHub.$emit('FailedToMerge');
expect(vm.mr.state).toEqual('failedToMerge'); expect(vm.mr.state).toEqual('failedToMerge');
eventHub.$emit('UpdateWidgetData', mockData); eventHub.$emit('UpdateWidgetData', mockData);
expect(vm.mr.setData).toHaveBeenCalledWith(mockData); expect(vm.mr.setData).toHaveBeenCalledWith(mockData);
eventHub.$emit('EnablePolling'); eventHub.$emit('EnablePolling');
expect(vm.resumePolling).toHaveBeenCalled(); expect(vm.resumePolling).toHaveBeenCalled();
eventHub.$emit('DisablePolling'); eventHub.$emit('DisablePolling');
expect(vm.stopPolling).toHaveBeenCalled(); expect(vm.stopPolling).toHaveBeenCalled();
const listenersWithServiceRequest = {
MRWidgetUpdateRequested: true,
FetchActionsContent: true,
};
const allArgs = eventHub.$on.calls.allArgs(); const listenersWithServiceRequest = {
allArgs.forEach(params => { MRWidgetUpdateRequested: true,
const eventName = params[0]; FetchActionsContent: true,
const callback = params[1]; };
if (listenersWithServiceRequest[eventName]) { const allArgs = eventHub.$on.calls.allArgs();
listenersWithServiceRequest[eventName] = callback; allArgs.forEach(params => {
} const eventName = params[0];
}); const callback = params[1];
listenersWithServiceRequest.MRWidgetUpdateRequested(); if (listenersWithServiceRequest[eventName]) {
listenersWithServiceRequest[eventName] = callback;
}
});
expect(vm.checkStatus).toHaveBeenCalled(); listenersWithServiceRequest.MRWidgetUpdateRequested();
listenersWithServiceRequest.FetchActionsContent(); expect(vm.checkStatus).toHaveBeenCalled();
expect(vm.fetchActionsContent).toHaveBeenCalled(); listenersWithServiceRequest.FetchActionsContent();
done(); expect(vm.fetchActionsContent).toHaveBeenCalled();
});
}); });
}); });
});
describe('setFavicon', () => { describe('setFavicon', () => {
let faviconElement; let faviconElement;
beforeEach(() => { beforeEach(() => {
const favicon = document.createElement('link'); const favicon = document.createElement('link');
favicon.setAttribute('id', 'favicon'); favicon.setAttribute('id', 'favicon');
favicon.setAttribute('data-original-href', faviconDataUrl); favicon.setAttribute('data-original-href', faviconDataUrl);
document.body.appendChild(favicon); document.body.appendChild(favicon);
faviconElement = document.getElementById('favicon'); faviconElement = document.getElementById('favicon');
}); });
afterEach(() => { afterEach(() => {
document.body.removeChild(document.getElementById('favicon')); document.body.removeChild(document.getElementById('favicon'));
}); });
it('should call setFavicon method', done => { it('should call setFavicon method', done => {
vm.mr.ciStatusFaviconPath = overlayDataUrl; vm.mr.ciStatusFaviconPath = overlayDataUrl;
vm.setFaviconHelper() vm.setFaviconHelper()
.then(() => { .then(() => {
/* /*
It would be better if we'd could mock commonUtils.setFaviconURL It would be better if we'd could mock commonUtils.setFaviconURL
with a spy and test that it was called. We are doing the following with a spy and test that it was called. We are doing the following
tests as a proxy to show that the function has been called tests as a proxy to show that the function has been called
*/ */
expect(faviconElement.getAttribute('href')).not.toEqual(null); expect(faviconElement.getAttribute('href')).not.toEqual(null);
expect(faviconElement.getAttribute('href')).not.toEqual(overlayDataUrl); expect(faviconElement.getAttribute('href')).not.toEqual(overlayDataUrl);
expect(faviconElement.getAttribute('href')).not.toEqual(faviconDataUrl); expect(faviconElement.getAttribute('href')).not.toEqual(faviconDataUrl);
done(); done();
}) })
.catch(done.fail); .catch(done.fail);
}); });
it('should not call setFavicon when there is no ciStatusFaviconPath', done => { it('should not call setFavicon when there is no ciStatusFaviconPath', done => {
vm.mr.ciStatusFaviconPath = null; vm.mr.ciStatusFaviconPath = null;
vm.setFaviconHelper() vm.setFaviconHelper()
.then(() => { .then(() => {
expect(faviconElement.getAttribute('href')).toEqual(null); expect(faviconElement.getAttribute('href')).toEqual(null);
done(); done();
}) })
.catch(done.fail); .catch(done.fail);
});
}); });
});
describe('handleNotification', () => { describe('handleNotification', () => {
const data = { const data = {
ci_status: 'running', ci_status: 'running',
title: 'title', title: 'title',
pipeline: { details: { status: { label: 'running-label' } } }, pipeline: { details: { status: { label: 'running-label' } } },
}; };
beforeEach(() => { beforeEach(() => {
spyOn(notify, 'notifyMe'); spyOn(notify, 'notifyMe');
vm.mr.ciStatus = 'failed'; vm.mr.ciStatus = 'failed';
vm.mr.gitlabLogo = 'logo.png'; vm.mr.gitlabLogo = 'logo.png';
}); });
it('should call notifyMe', () => { it('should call notifyMe', () => {
vm.handleNotification(data); vm.handleNotification(data);
expect(notify.notifyMe).toHaveBeenCalledWith( expect(notify.notifyMe).toHaveBeenCalledWith(
'Pipeline running-label', 'Pipeline running-label',
'Pipeline running-label for "title"', 'Pipeline running-label for "title"',
'logo.png', 'logo.png',
); );
}); });
it('should not call notifyMe if the status has not changed', () => {
vm.mr.ciStatus = data.ci_status;
vm.handleNotification(data); it('should not call notifyMe if the status has not changed', () => {
vm.mr.ciStatus = data.ci_status;
expect(notify.notifyMe).not.toHaveBeenCalled(); vm.handleNotification(data);
});
it('should not notify if no pipeline provided', () => { expect(notify.notifyMe).not.toHaveBeenCalled();
vm.handleNotification({
...data,
pipeline: undefined,
}); });
expect(notify.notifyMe).not.toHaveBeenCalled(); it('should not notify if no pipeline provided', () => {
}); vm.handleNotification({
}); ...data,
pipeline: undefined,
});
describe('resumePolling', () => { expect(notify.notifyMe).not.toHaveBeenCalled();
it('should call stopTimer on pollingInterval', done => { });
setTimeout(() => { });
spyOn(vm.pollingInterval, 'resume');
vm.resumePolling(); describe('resumePolling', () => {
it('should call stopTimer on pollingInterval', () =>
waitForPromises().then(() => {
spyOn(vm.pollingInterval, 'resume');
expect(vm.pollingInterval.resume).toHaveBeenCalled(); vm.resumePolling();
done(); expect(vm.pollingInterval.resume).toHaveBeenCalled();
}); }));
}); });
});
describe('stopPolling', () => { describe('stopPolling', () => {
it('should call stopTimer on pollingInterval', done => { it('should call stopTimer on pollingInterval', () =>
setTimeout(() => { waitForPromises().then(() => {
spyOn(vm.pollingInterval, 'stopTimer'); spyOn(vm.pollingInterval, 'stopTimer');
vm.stopPolling(); vm.stopPolling();
expect(vm.pollingInterval.stopTimer).toHaveBeenCalled(); expect(vm.pollingInterval.stopTimer).toHaveBeenCalled();
}));
done();
});
}); });
}); });
});
describe('rendering relatedLinks', () => { describe('rendering relatedLinks', () => {
beforeEach(done => { beforeEach(done => {
vm.mr.relatedLinks = { vm.mr.relatedLinks = {
assignToMe: null, assignToMe: null,
closing: ` closing: `
<a class="close-related-link" href="#"> <a class="close-related-link" href="#">
Close Close
</a> </a>
`, `,
mentioned: '', mentioned: '',
}; };
Vue.nextTick(done); Vue.nextTick(done);
}); });
it('renders if there are relatedLinks', () => { it('renders if there are relatedLinks', () => {
expect(vm.$el.querySelector('.close-related-link')).toBeDefined(); expect(vm.$el.querySelector('.close-related-link')).toBeDefined();
}); });
it('does not render if state is nothingToMerge', done => { it('does not render if state is nothingToMerge', done => {
vm.mr.state = stateKey.nothingToMerge; vm.mr.state = stateKey.nothingToMerge;
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$el.querySelector('.close-related-link')).toBeNull(); expect(vm.$el.querySelector('.close-related-link')).toBeNull();
done(); done();
});
}); });
}); });
});
describe('rendering source branch removal status', () => { describe('rendering source branch removal status', () => {
it('renders when user cannot remove branch and branch should be removed', done => { it('renders when user cannot remove branch and branch should be removed', done => {
vm.mr.canRemoveSourceBranch = false; vm.mr.canRemoveSourceBranch = false;
vm.mr.shouldRemoveSourceBranch = true; vm.mr.shouldRemoveSourceBranch = true;
vm.mr.state = 'readyToMerge'; vm.mr.state = 'readyToMerge';
vm.$nextTick(() => { vm.$nextTick(() => {
const tooltip = vm.$el.querySelector('.fa-question-circle'); const tooltip = vm.$el.querySelector('.fa-question-circle');
expect(vm.$el.textContent).toContain('Deletes source branch'); expect(vm.$el.textContent).toContain('Deletes source branch');
expect(tooltip.getAttribute('data-original-title')).toBe( expect(tooltip.getAttribute('data-original-title')).toBe(
'A user with write access to the source branch selected this option', 'A user with write access to the source branch selected this option',
); );
done(); done();
});
}); });
});
it('does not render in merged state', done => { it('does not render in merged state', done => {
vm.mr.canRemoveSourceBranch = false; vm.mr.canRemoveSourceBranch = false;
vm.mr.shouldRemoveSourceBranch = true; vm.mr.shouldRemoveSourceBranch = true;
vm.mr.state = 'merged'; vm.mr.state = 'merged';
vm.$nextTick(() => { vm.$nextTick(() => {
expect(vm.$el.textContent).toContain('The source branch has been deleted'); expect(vm.$el.textContent).toContain('The source branch has been deleted');
expect(vm.$el.textContent).not.toContain('Deletes source branch'); expect(vm.$el.textContent).not.toContain('Deletes source branch');
done(); done();
});
}); });
}); });
});
describe('rendering deployments', () => { describe('rendering deployments', () => {
const changes = [ const changes = [
{ {
path: 'index.html', path: 'index.html',
external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/index.html', external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/index.html',
}, },
{
path: 'imgs/gallery.html',
external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
},
{
path: 'about/',
external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/about/',
},
];
const deploymentMockData = {
id: 15,
name: 'review/diplo',
url: '/root/acets-review-apps/environments/15',
stop_url: '/root/acets-review-apps/environments/15/stop',
metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
external_url: 'http://diplo.',
external_url_formatted: 'diplo.',
deployed_at: '2017-03-22T22:44:42.258Z',
deployed_at_formatted: 'Mar 22, 2017 10:44pm',
changes,
status: SUCCESS,
};
beforeEach(done => {
vm.mr.deployments.push(
{ {
...deploymentMockData, path: 'imgs/gallery.html',
external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
}, },
{ {
...deploymentMockData, path: 'about/',
id: deploymentMockData.id + 1, external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/about/',
}, },
); ];
const deploymentMockData = {
id: 15,
name: 'review/diplo',
url: '/root/acets-review-apps/environments/15',
stop_url: '/root/acets-review-apps/environments/15/stop',
metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
external_url: 'http://diplo.',
external_url_formatted: 'diplo.',
deployed_at: '2017-03-22T22:44:42.258Z',
deployed_at_formatted: 'Mar 22, 2017 10:44pm',
changes,
status: SUCCESS,
};
vm.$nextTick(done); beforeEach(done => {
}); vm.mr.deployments.push(
{
...deploymentMockData,
},
{
...deploymentMockData,
id: deploymentMockData.id + 1,
},
);
it('renders multiple deployments', () => { vm.$nextTick(done);
expect(vm.$el.querySelectorAll('.deploy-heading').length).toBe(2); });
});
it('renders multiple deployments', () => {
expect(vm.$el.querySelectorAll('.deploy-heading').length).toBe(2);
});
it('renders dropdpown with multiple file changes', () => { it('renders dropdpown with multiple file changes', () => {
expect( expect(
vm.$el vm.$el
.querySelector('.js-mr-wigdet-deployment-dropdown') .querySelector('.js-mr-wigdet-deployment-dropdown')
.querySelectorAll('.js-filtered-dropdown-result').length, .querySelectorAll('.js-filtered-dropdown-result').length,
).toEqual(changes.length); ).toEqual(changes.length);
});
}); });
});
describe('pipeline for target branch after merge', () => { describe('pipeline for target branch after merge', () => {
describe('with information for target branch pipeline', () => { describe('with information for target branch pipeline', () => {
beforeEach(done => { beforeEach(done => {
vm.mr.state = 'merged'; vm.mr.state = 'merged';
vm.mr.mergePipeline = { vm.mr.mergePipeline = {
id: 127, id: 127,
user: { user: {
id: 1,
name: 'Administrator',
username: 'root',
state: 'active',
avatar_url: null,
web_url: 'http://localhost:3000/root',
status_tooltip_html: null,
path: '/root',
},
active: true,
coverage: null,
source: 'push',
created_at: '2018-10-22T11:41:35.186Z',
updated_at: '2018-10-22T11:41:35.433Z',
path: '/root/ci-web-terminal/pipelines/127',
flags: {
latest: true,
stuck: true,
auto_devops: false,
yaml_errors: false,
retryable: false,
cancelable: true,
failure_reason: false,
},
details: {
status: {
icon: 'status_pending',
text: 'pending',
label: 'pending',
group: 'pending',
tooltip: 'pending',
has_details: true,
details_path: '/root/ci-web-terminal/pipelines/127',
illustration: null,
favicon:
'/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
},
duration: null,
finished_at: null,
stages: [
{
name: 'test',
title: 'test: pending',
status: {
icon: 'status_pending',
text: 'pending',
label: 'pending',
group: 'pending',
tooltip: 'pending',
has_details: true,
details_path: '/root/ci-web-terminal/pipelines/127#test',
illustration: null,
favicon:
'/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
},
path: '/root/ci-web-terminal/pipelines/127#test',
dropdown_path: '/root/ci-web-terminal/pipelines/127/stage.json?stage=test',
},
],
artifacts: [],
manual_actions: [],
scheduled_actions: [],
},
ref: {
name: 'master',
path: '/root/ci-web-terminal/commits/master',
tag: false,
branch: true,
},
commit: {
id: 'aa1939133d373c94879becb79d91828a892ee319',
short_id: 'aa193913',
title: "Merge branch 'master-test' into 'master'",
created_at: '2018-10-22T11:41:33.000Z',
parent_ids: [
'4622f4dd792468993003caf2e3be978798cbe096',
'76598df914cdfe87132d0c3c40f80db9fa9396a4',
],
message:
"Merge branch 'master-test' into 'master'\n\nUpdate .gitlab-ci.yml\n\nSee merge request root/ci-web-terminal!1",
author_name: 'Administrator',
author_email: 'admin@example.com',
authored_date: '2018-10-22T11:41:33.000Z',
committer_name: 'Administrator',
committer_email: 'admin@example.com',
committed_date: '2018-10-22T11:41:33.000Z',
author: {
id: 1, id: 1,
name: 'Administrator', name: 'Administrator',
username: 'root', username: 'root',
...@@ -768,88 +632,211 @@ describe('mrWidgetOptions', () => { ...@@ -768,88 +632,211 @@ describe('mrWidgetOptions', () => {
status_tooltip_html: null, status_tooltip_html: null,
path: '/root', path: '/root',
}, },
author_gravatar_url: null, active: true,
commit_url: coverage: null,
'http://localhost:3000/root/ci-web-terminal/commit/aa1939133d373c94879becb79d91828a892ee319', source: 'push',
commit_path: '/root/ci-web-terminal/commit/aa1939133d373c94879becb79d91828a892ee319', created_at: '2018-10-22T11:41:35.186Z',
}, updated_at: '2018-10-22T11:41:35.433Z',
cancel_path: '/root/ci-web-terminal/pipelines/127/cancel', path: '/root/ci-web-terminal/pipelines/127',
}; flags: {
vm.$nextTick(done); latest: true,
stuck: true,
auto_devops: false,
yaml_errors: false,
retryable: false,
cancelable: true,
failure_reason: false,
},
details: {
status: {
icon: 'status_pending',
text: 'pending',
label: 'pending',
group: 'pending',
tooltip: 'pending',
has_details: true,
details_path: '/root/ci-web-terminal/pipelines/127',
illustration: null,
favicon:
'/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
},
duration: null,
finished_at: null,
stages: [
{
name: 'test',
title: 'test: pending',
status: {
icon: 'status_pending',
text: 'pending',
label: 'pending',
group: 'pending',
tooltip: 'pending',
has_details: true,
details_path: '/root/ci-web-terminal/pipelines/127#test',
illustration: null,
favicon:
'/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
},
path: '/root/ci-web-terminal/pipelines/127#test',
dropdown_path: '/root/ci-web-terminal/pipelines/127/stage.json?stage=test',
},
],
artifacts: [],
manual_actions: [],
scheduled_actions: [],
},
ref: {
name: 'master',
path: '/root/ci-web-terminal/commits/master',
tag: false,
branch: true,
},
commit: {
id: 'aa1939133d373c94879becb79d91828a892ee319',
short_id: 'aa193913',
title: "Merge branch 'master-test' into 'master'",
created_at: '2018-10-22T11:41:33.000Z',
parent_ids: [
'4622f4dd792468993003caf2e3be978798cbe096',
'76598df914cdfe87132d0c3c40f80db9fa9396a4',
],
message:
"Merge branch 'master-test' into 'master'\n\nUpdate .gitlab-ci.yml\n\nSee merge request root/ci-web-terminal!1",
author_name: 'Administrator',
author_email: 'admin@example.com',
authored_date: '2018-10-22T11:41:33.000Z',
committer_name: 'Administrator',
committer_email: 'admin@example.com',
committed_date: '2018-10-22T11:41:33.000Z',
author: {
id: 1,
name: 'Administrator',
username: 'root',
state: 'active',
avatar_url: null,
web_url: 'http://localhost:3000/root',
status_tooltip_html: null,
path: '/root',
},
author_gravatar_url: null,
commit_url:
'http://localhost:3000/root/ci-web-terminal/commit/aa1939133d373c94879becb79d91828a892ee319',
commit_path: '/root/ci-web-terminal/commit/aa1939133d373c94879becb79d91828a892ee319',
},
cancel_path: '/root/ci-web-terminal/pipelines/127/cancel',
};
vm.$nextTick(done);
});
it('renders pipeline block', () => {
expect(vm.$el.querySelector('.js-post-merge-pipeline')).not.toBeNull();
});
describe('with post merge deployments', () => {
beforeEach(done => {
vm.mr.postMergeDeployments = [
{
id: 15,
name: 'review/diplo',
url: '/root/acets-review-apps/environments/15',
stop_url: '/root/acets-review-apps/environments/15/stop',
metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
external_url: 'http://diplo.',
external_url_formatted: 'diplo.',
deployed_at: '2017-03-22T22:44:42.258Z',
deployed_at_formatted: 'Mar 22, 2017 10:44pm',
changes: [
{
path: 'index.html',
external_url:
'http://root-master-patch-91341.volatile-watch.surge.sh/index.html',
},
{
path: 'imgs/gallery.html',
external_url:
'http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
},
{
path: 'about/',
external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/about/',
},
],
status: 'success',
},
];
vm.$nextTick(done);
});
it('renders post deployment information', () => {
expect(vm.$el.querySelector('.js-post-deployment')).not.toBeNull();
});
});
}); });
it('renders pipeline block', () => { describe('without information for target branch pipeline', () => {
expect(vm.$el.querySelector('.js-post-merge-pipeline')).not.toBeNull(); beforeEach(done => {
vm.mr.state = 'merged';
vm.$nextTick(done);
});
it('does not render pipeline block', () => {
expect(vm.$el.querySelector('.js-post-merge-pipeline')).toBeNull();
});
}); });
describe('with post merge deployments', () => { describe('when state is not merged', () => {
beforeEach(done => { beforeEach(done => {
vm.mr.postMergeDeployments = [ vm.mr.state = 'archived';
{
id: 15,
name: 'review/diplo',
url: '/root/acets-review-apps/environments/15',
stop_url: '/root/acets-review-apps/environments/15/stop',
metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
external_url: 'http://diplo.',
external_url_formatted: 'diplo.',
deployed_at: '2017-03-22T22:44:42.258Z',
deployed_at_formatted: 'Mar 22, 2017 10:44pm',
changes: [
{
path: 'index.html',
external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/index.html',
},
{
path: 'imgs/gallery.html',
external_url:
'http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
},
{
path: 'about/',
external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/about/',
},
],
status: 'success',
},
];
vm.$nextTick(done); vm.$nextTick(done);
}); });
it('renders post deployment information', () => { it('does not render pipeline block', () => {
expect(vm.$el.querySelector('.js-post-deployment')).not.toBeNull(); expect(vm.$el.querySelector('.js-post-merge-pipeline')).toBeNull();
});
it('does not render post deployment information', () => {
expect(vm.$el.querySelector('.js-post-deployment')).toBeNull();
}); });
}); });
}); });
describe('without information for target branch pipeline', () => { it('should not suggest pipelines', () => {
beforeEach(done => { vm.mr.mergeRequestAddCiConfigPath = null;
vm.mr.state = 'merged';
vm.$nextTick(done); expect(vm.shouldSuggestPipelines).toBeFalsy();
}); });
});
it('does not render pipeline block', () => { describe('given suggestPipeline feature flag is enabled', () => {
expect(vm.$el.querySelector('.js-post-merge-pipeline')).toBeNull(); beforeEach(() => {
}); gon.features = { suggestPipeline: true };
createComponent();
}); });
describe('when state is not merged', () => { it('should suggest pipelines when none exist', () => {
beforeEach(done => { vm.mr.mergeRequestAddCiConfigPath = 'some/path';
vm.mr.state = 'archived'; vm.mr.hasCI = false;
vm.$nextTick(done); expect(vm.shouldSuggestPipelines).toBeTruthy();
}); });
it('does not render pipeline block', () => { it('should not suggest pipelines when they exist', () => {
expect(vm.$el.querySelector('.js-post-merge-pipeline')).toBeNull(); vm.mr.mergeRequestAddCiConfigPath = null;
}); vm.mr.hasCI = false;
it('does not render post deployment information', () => { expect(vm.shouldSuggestPipelines).toBeFalsy();
expect(vm.$el.querySelector('.js-post-deployment')).toBeNull(); });
});
it('should not suggest pipelines hasCI is true', () => {
vm.mr.mergeRequestAddCiConfigPath = 'some/path';
vm.mr.hasCI = true;
expect(vm.shouldSuggestPipelines).toBeFalsy();
}); });
}); });
}); });
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