2020-04-08 14:13:33 +05:30
|
|
|
import { mount } from '@vue/test-utils';
|
2020-10-24 23:57:45 +05:30
|
|
|
import { deprecatedCreateFlash as createFlash } from '~/flash';
|
2020-04-08 14:13:33 +05:30
|
|
|
import { visitUrl } from '~/lib/utils/url_utility';
|
|
|
|
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
|
|
|
|
import DeploymentActions from '~/vue_merge_request_widget/components/deployment/deployment_actions.vue';
|
|
|
|
import {
|
|
|
|
CREATED,
|
|
|
|
MANUAL_DEPLOY,
|
|
|
|
FAILED,
|
|
|
|
DEPLOYING,
|
|
|
|
REDEPLOYING,
|
|
|
|
STOPPING,
|
|
|
|
} from '~/vue_merge_request_widget/components/deployment/constants';
|
|
|
|
import {
|
|
|
|
actionButtonMocks,
|
|
|
|
deploymentMockData,
|
|
|
|
playDetails,
|
|
|
|
retryDetails,
|
|
|
|
} from './deployment_mock_data';
|
|
|
|
|
|
|
|
jest.mock('~/flash');
|
|
|
|
jest.mock('~/lib/utils/url_utility');
|
|
|
|
|
|
|
|
describe('DeploymentAction component', () => {
|
|
|
|
let wrapper;
|
|
|
|
let executeActionSpy;
|
|
|
|
|
|
|
|
const factory = (options = {}) => {
|
|
|
|
// This destroys any wrappers created before a nested call to factory reassigns it
|
|
|
|
if (wrapper && wrapper.destroy) {
|
|
|
|
wrapper.destroy();
|
|
|
|
}
|
|
|
|
|
2021-01-03 14:25:43 +05:30
|
|
|
wrapper = mount(DeploymentActions, options);
|
2020-04-08 14:13:33 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
const findStopButton = () => wrapper.find('.js-stop-env');
|
|
|
|
const findDeployButton = () => wrapper.find('.js-manual-deploy-action');
|
|
|
|
const findRedeployButton = () => wrapper.find('.js-manual-redeploy-action');
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
executeActionSpy = jest.spyOn(MRWidgetService, 'executeInlineAction');
|
|
|
|
|
|
|
|
factory({
|
|
|
|
propsData: {
|
|
|
|
computedDeploymentStatus: CREATED,
|
|
|
|
deployment: deploymentMockData,
|
|
|
|
showVisualReviewApp: false,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
wrapper.destroy();
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('actions do not appear when conditions are unmet', () => {
|
|
|
|
describe('when there is no stop_url', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
factory({
|
|
|
|
propsData: {
|
|
|
|
computedDeploymentStatus: CREATED,
|
|
|
|
deployment: {
|
|
|
|
...deploymentMockData,
|
|
|
|
stop_url: null,
|
|
|
|
},
|
|
|
|
showVisualReviewApp: false,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('the stop button does not appear', () => {
|
|
|
|
expect(findStopButton().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when there is no play_path in details', () => {
|
|
|
|
it('the manual deploy button does not appear', () => {
|
|
|
|
expect(findDeployButton().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when there is no retry_path in details', () => {
|
|
|
|
it('the manual redeploy button does not appear', () => {
|
|
|
|
expect(findRedeployButton().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when conditions are met', () => {
|
|
|
|
describe.each`
|
|
|
|
configConst | computedDeploymentStatus | displayConditionChanges | finderFn | endpoint
|
|
|
|
${STOPPING} | ${CREATED} | ${{}} | ${findStopButton} | ${deploymentMockData.stop_url}
|
|
|
|
${DEPLOYING} | ${MANUAL_DEPLOY} | ${playDetails} | ${findDeployButton} | ${playDetails.playable_build.play_path}
|
|
|
|
${REDEPLOYING} | ${FAILED} | ${retryDetails} | ${findRedeployButton} | ${retryDetails.playable_build.retry_path}
|
|
|
|
`(
|
|
|
|
'$configConst action',
|
|
|
|
({ configConst, computedDeploymentStatus, displayConditionChanges, finderFn, endpoint }) => {
|
|
|
|
describe(`${configConst} action`, () => {
|
|
|
|
const confirmAction = () => {
|
|
|
|
jest.spyOn(window, 'confirm').mockReturnValueOnce(true);
|
|
|
|
finderFn().trigger('click');
|
|
|
|
};
|
|
|
|
|
|
|
|
const rejectAction = () => {
|
|
|
|
jest.spyOn(window, 'confirm').mockReturnValueOnce(false);
|
|
|
|
finderFn().trigger('click');
|
|
|
|
};
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
factory({
|
|
|
|
propsData: {
|
|
|
|
computedDeploymentStatus,
|
|
|
|
deployment: {
|
|
|
|
...deploymentMockData,
|
|
|
|
details: displayConditionChanges,
|
|
|
|
},
|
|
|
|
showVisualReviewApp: false,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('the button is rendered', () => {
|
|
|
|
expect(finderFn().exists()).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when clicked', () => {
|
|
|
|
describe('should show a confirm dialog but not call executeInlineAction when declined', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
executeActionSpy.mockResolvedValueOnce();
|
|
|
|
rejectAction();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should show the confirm dialog', () => {
|
|
|
|
expect(window.confirm).toHaveBeenCalled();
|
|
|
|
expect(window.confirm).toHaveBeenCalledWith(
|
|
|
|
actionButtonMocks[configConst].confirmMessage,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not execute the action', () => {
|
|
|
|
expect(MRWidgetService.executeInlineAction).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('should show a confirm dialog and call executeInlineAction when accepted', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
executeActionSpy.mockResolvedValueOnce();
|
|
|
|
confirmAction();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should show the confirm dialog', () => {
|
|
|
|
expect(window.confirm).toHaveBeenCalled();
|
|
|
|
expect(window.confirm).toHaveBeenCalledWith(
|
|
|
|
actionButtonMocks[configConst].confirmMessage,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should execute the action with expected URL', () => {
|
|
|
|
expect(MRWidgetService.executeInlineAction).toHaveBeenCalled();
|
|
|
|
expect(MRWidgetService.executeInlineAction).toHaveBeenCalledWith(endpoint);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not throw an error', () => {
|
|
|
|
expect(createFlash).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('response includes redirect_url', () => {
|
|
|
|
const url = '/root/example';
|
|
|
|
beforeEach(() => {
|
|
|
|
executeActionSpy.mockResolvedValueOnce({
|
|
|
|
data: { redirect_url: url },
|
|
|
|
});
|
|
|
|
confirmAction();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('calls visit url with the redirect_url', () => {
|
|
|
|
expect(visitUrl).toHaveBeenCalled();
|
|
|
|
expect(visitUrl).toHaveBeenCalledWith(url);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('it should call the executeAction method ', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
jest.spyOn(wrapper.vm, 'executeAction').mockImplementation();
|
|
|
|
confirmAction();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('calls with the expected arguments', () => {
|
|
|
|
expect(wrapper.vm.executeAction).toHaveBeenCalled();
|
|
|
|
expect(wrapper.vm.executeAction).toHaveBeenCalledWith(
|
|
|
|
endpoint,
|
|
|
|
actionButtonMocks[configConst],
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when executeInlineAction errors', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
executeActionSpy.mockRejectedValueOnce();
|
|
|
|
confirmAction();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should call createFlash with error message', () => {
|
|
|
|
expect(createFlash).toHaveBeenCalled();
|
|
|
|
expect(createFlash).toHaveBeenCalledWith(
|
|
|
|
actionButtonMocks[configConst].errorMessage,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|