Commit acd459de authored by Phil Hughes's avatar Phil Hughes

Merge branch '347507-reset-integration-logic-from-vuex-to-vue' into 'master'

Move integration reset code from Vuex to Vue component

See merge request gitlab-org/gitlab!77555
parents 015c466b 1d50c904
<script> <script>
import { GlButton, GlModalDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui'; import { GlButton, GlModalDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import axios from 'axios';
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import { mapState, mapActions, mapGetters } from 'vuex'; import { mapState, mapActions, mapGetters } from 'vuex';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
...@@ -10,6 +11,7 @@ import { ...@@ -10,6 +11,7 @@ import {
I18N_SUCCESSFUL_CONNECTION_MESSAGE, I18N_SUCCESSFUL_CONNECTION_MESSAGE,
integrationLevels, integrationLevels,
} from '~/integrations/constants'; } from '~/integrations/constants';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
import { testIntegrationSettings } from '../api'; import { testIntegrationSettings } from '../api';
import ActiveCheckbox from './active_checkbox.vue'; import ActiveCheckbox from './active_checkbox.vue';
...@@ -55,11 +57,12 @@ export default { ...@@ -55,11 +57,12 @@ export default {
integrationActive: false, integrationActive: false,
isTesting: false, isTesting: false,
isSaving: false, isSaving: false,
isResetting: false,
}; };
}, },
computed: { computed: {
...mapGetters(['currentKey', 'propsSource']), ...mapGetters(['currentKey', 'propsSource']),
...mapState(['defaultState', 'customState', 'override', 'isResetting']), ...mapState(['defaultState', 'customState', 'override']),
isEditable() { isEditable() {
return this.propsSource.editable; return this.propsSource.editable;
}, },
...@@ -126,7 +129,20 @@ export default { ...@@ -126,7 +129,20 @@ export default {
}); });
}, },
onResetClick() { onResetClick() {
this.fetchResetIntegration(); this.isResetting = true;
return axios
.post(this.propsSource.resetPath)
.then(() => {
refreshCurrentPage();
})
.catch((error) => {
this.$toast.show(I18N_DEFAULT_ERROR_MESSAGE);
Sentry.captureException(error);
})
.finally(() => {
this.isResetting = false;
});
}, },
onRequestJiraIssueTypes() { onRequestJiraIssueTypes() {
this.requestJiraIssueTypes(this.getFormData()); this.requestJiraIssueTypes(this.getFormData());
...@@ -208,6 +224,7 @@ export default { ...@@ -208,6 +224,7 @@ export default {
variant="confirm" variant="confirm"
:loading="isSaving" :loading="isSaving"
:disabled="disableButtons" :disabled="disableButtons"
data-testid="save-button-instance-group"
data-qa-selector="save_changes_button" data-qa-selector="save_changes_button"
> >
{{ __('Save changes') }} {{ __('Save changes') }}
......
...@@ -11,7 +11,7 @@ export default { ...@@ -11,7 +11,7 @@ export default {
primaryProps() { primaryProps() {
return { return {
text: __('Reset'), text: __('Reset'),
attributes: [{ variant: 'warning' }, { category: 'primary' }], attributes: [{ variant: 'danger' }, { category: 'primary' }],
}; };
}, },
cancelProps() { cancelProps() {
......
import axios from 'axios';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { import {
VALIDATE_INTEGRATION_FORM_EVENT, VALIDATE_INTEGRATION_FORM_EVENT,
I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE, I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
...@@ -10,27 +8,6 @@ import eventHub from '../event_hub'; ...@@ -10,27 +8,6 @@ import eventHub from '../event_hub';
import * as types from './mutation_types'; import * as types from './mutation_types';
export const setOverride = ({ commit }, override) => commit(types.SET_OVERRIDE, override); export const setOverride = ({ commit }, override) => commit(types.SET_OVERRIDE, override);
export const setIsResetting = ({ commit }, isResetting) =>
commit(types.SET_IS_RESETTING, isResetting);
export const requestResetIntegration = ({ commit }) => {
commit(types.REQUEST_RESET_INTEGRATION);
};
export const receiveResetIntegrationSuccess = () => {
refreshCurrentPage();
};
export const receiveResetIntegrationError = ({ commit }) => {
commit(types.RECEIVE_RESET_INTEGRATION_ERROR);
};
export const fetchResetIntegration = ({ dispatch, getters }) => {
dispatch('requestResetIntegration');
return axios
.post(getters.propsSource.resetPath, { params: { format: 'json' } })
.then(() => dispatch('receiveResetIntegrationSuccess'))
.catch(() => dispatch('receiveResetIntegrationError'));
};
export const requestJiraIssueTypes = ({ commit, dispatch, getters }, formData) => { export const requestJiraIssueTypes = ({ commit, dispatch, getters }, formData) => {
commit(types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE, ''); commit(types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE, '');
......
...@@ -4,15 +4,6 @@ export default { ...@@ -4,15 +4,6 @@ export default {
[types.SET_OVERRIDE](state, override) { [types.SET_OVERRIDE](state, override) {
state.override = override; state.override = override;
}, },
[types.SET_IS_RESETTING](state, isResetting) {
state.isResetting = isResetting;
},
[types.REQUEST_RESET_INTEGRATION](state) {
state.isResetting = true;
},
[types.RECEIVE_RESET_INTEGRATION_ERROR](state) {
state.isResetting = false;
},
[types.SET_JIRA_ISSUE_TYPES](state, jiraIssueTypes) { [types.SET_JIRA_ISSUE_TYPES](state, jiraIssueTypes) {
state.jiraIssueTypes = jiraIssueTypes; state.jiraIssueTypes = jiraIssueTypes;
}, },
......
...@@ -5,8 +5,6 @@ export default ({ defaultState = null, customState = {} } = {}) => { ...@@ -5,8 +5,6 @@ export default ({ defaultState = null, customState = {} } = {}) => {
override, override,
defaultState, defaultState,
customState, customState,
isSaving: false,
isResetting: false,
isLoadingJiraIssueTypes: false, isLoadingJiraIssueTypes: false,
loadingJiraIssueTypesErrorMessage: '', loadingJiraIssueTypesErrorMessage: '',
jiraIssueTypes: [], jiraIssueTypes: [],
......
...@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter'; ...@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import { setHTMLFixture } from 'helpers/fixtures'; import { setHTMLFixture } from 'helpers/fixtures';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { mockIntegrationProps } from 'jest/integrations/edit/mock_data'; import waitForPromises from 'helpers/wait_for_promises';
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue'; import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue'; import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
import DynamicField from '~/integrations/edit/components/dynamic_field.vue'; import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
...@@ -13,7 +13,6 @@ import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_field ...@@ -13,7 +13,6 @@ import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_field
import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue'; import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
import ResetConfirmationModal from '~/integrations/edit/components/reset_confirmation_modal.vue'; import ResetConfirmationModal from '~/integrations/edit/components/reset_confirmation_modal.vue';
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue'; import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
import waitForPromises from 'helpers/wait_for_promises';
import { import {
integrationLevels, integrationLevels,
I18N_SUCCESSFUL_CONNECTION_MESSAGE, I18N_SUCCESSFUL_CONNECTION_MESSAGE,
...@@ -23,9 +22,12 @@ import { ...@@ -23,9 +22,12 @@ import {
import { createStore } from '~/integrations/edit/store'; import { createStore } from '~/integrations/edit/store';
import eventHub from '~/integrations/edit/event_hub'; import eventHub from '~/integrations/edit/event_hub';
import httpStatus from '~/lib/utils/http_status'; import httpStatus from '~/lib/utils/http_status';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { mockIntegrationProps } from '../mock_data';
jest.mock('~/integrations/edit/event_hub'); jest.mock('~/integrations/edit/event_hub');
jest.mock('@sentry/browser'); jest.mock('@sentry/browser');
jest.mock('~/lib/utils/url_utility');
describe('IntegrationForm', () => { describe('IntegrationForm', () => {
const mockToastShow = jest.fn(); const mockToastShow = jest.fn();
...@@ -80,7 +82,8 @@ describe('IntegrationForm', () => { ...@@ -80,7 +82,8 @@ describe('IntegrationForm', () => {
const findConfirmationModal = () => wrapper.findComponent(ConfirmationModal); const findConfirmationModal = () => wrapper.findComponent(ConfirmationModal);
const findResetConfirmationModal = () => wrapper.findComponent(ResetConfirmationModal); const findResetConfirmationModal = () => wrapper.findComponent(ResetConfirmationModal);
const findResetButton = () => wrapper.findByTestId('reset-button'); const findResetButton = () => wrapper.findByTestId('reset-button');
const findSaveButton = () => wrapper.findByTestId('save-button'); const findProjectSaveButton = () => wrapper.findByTestId('save-button');
const findInstanceOrGroupSaveButton = () => wrapper.findByTestId('save-button-instance-group');
const findTestButton = () => wrapper.findByTestId('test-button'); const findTestButton = () => wrapper.findByTestId('test-button');
const findJiraTriggerFields = () => wrapper.findComponent(JiraTriggerFields); const findJiraTriggerFields = () => wrapper.findComponent(JiraTriggerFields);
const findJiraIssuesFields = () => wrapper.findComponent(JiraIssuesFields); const findJiraIssuesFields = () => wrapper.findComponent(JiraIssuesFields);
...@@ -395,11 +398,11 @@ describe('IntegrationForm', () => { ...@@ -395,11 +398,11 @@ describe('IntegrationForm', () => {
}, },
}); });
await findSaveButton().vm.$emit('click', new Event('click')); await findProjectSaveButton().vm.$emit('click', new Event('click'));
}); });
it('sets save button `loading` prop to `true`', () => { it('sets save button `loading` prop to `true`', () => {
expect(findSaveButton().props('loading')).toBe(true); expect(findProjectSaveButton().props('loading')).toBe(true);
}); });
it('sets test button `disabled` prop to `true`', () => { it('sets test button `disabled` prop to `true`', () => {
...@@ -425,7 +428,7 @@ describe('IntegrationForm', () => { ...@@ -425,7 +428,7 @@ describe('IntegrationForm', () => {
}, },
}); });
await findSaveButton().vm.$emit('click', new Event('click')); await findProjectSaveButton().vm.$emit('click', new Event('click'));
}); });
it('submit form', () => { it('submit form', () => {
...@@ -445,7 +448,7 @@ describe('IntegrationForm', () => { ...@@ -445,7 +448,7 @@ describe('IntegrationForm', () => {
}, },
}); });
await findSaveButton().vm.$emit('click', new Event('click')); await findProjectSaveButton().vm.$emit('click', new Event('click'));
}); });
it('does not submit form', () => { it('does not submit form', () => {
...@@ -453,7 +456,7 @@ describe('IntegrationForm', () => { ...@@ -453,7 +456,7 @@ describe('IntegrationForm', () => {
}); });
it('sets save button `loading` prop to `false`', () => { it('sets save button `loading` prop to `false`', () => {
expect(findSaveButton().props('loading')).toBe(false); expect(findProjectSaveButton().props('loading')).toBe(false);
}); });
it('sets test button `disabled` prop to `false`', () => { it('sets test button `disabled` prop to `false`', () => {
...@@ -507,7 +510,7 @@ describe('IntegrationForm', () => { ...@@ -507,7 +510,7 @@ describe('IntegrationForm', () => {
}); });
it('sets save button `disabled` prop to `true`', () => { it('sets save button `disabled` prop to `true`', () => {
expect(findSaveButton().props('disabled')).toBe(true); expect(findProjectSaveButton().props('disabled')).toBe(true);
}); });
}); });
...@@ -536,7 +539,7 @@ describe('IntegrationForm', () => { ...@@ -536,7 +539,7 @@ describe('IntegrationForm', () => {
}); });
it('sets save button `disabled` prop to `false`', () => { it('sets save button `disabled` prop to `false`', () => {
expect(findSaveButton().props('disabled')).toBe(false); expect(findProjectSaveButton().props('disabled')).toBe(false);
}); });
it(`${expectSentry ? 'does' : 'does not'} capture exception in Sentry`, () => { it(`${expectSentry ? 'does' : 'does not'} capture exception in Sentry`, () => {
...@@ -545,4 +548,83 @@ describe('IntegrationForm', () => { ...@@ -545,4 +548,83 @@ describe('IntegrationForm', () => {
}); });
}); });
}); });
describe('when `reset-confirmation-modal` emits `reset` event', () => {
const mockResetPath = '/reset';
describe('buttons', () => {
beforeEach(async () => {
createComponent({
customStateProps: {
integrationLevel: integrationLevels.GROUP,
canTest: true,
resetPath: mockResetPath,
},
});
await findResetConfirmationModal().vm.$emit('reset');
});
it('sets reset button `loading` prop to `true`', () => {
expect(findResetButton().props('loading')).toBe(true);
});
it('sets other button `disabled` props to `true`', () => {
expect(findInstanceOrGroupSaveButton().props('disabled')).toBe(true);
expect(findTestButton().props('disabled')).toBe(true);
});
});
describe('when "reset settings" request fails', () => {
beforeEach(async () => {
mockAxios.onPost(mockResetPath).replyOnce(httpStatus.INTERNAL_SERVER_ERROR);
createComponent({
customStateProps: {
integrationLevel: integrationLevels.GROUP,
canTest: true,
resetPath: mockResetPath,
},
});
await findResetConfirmationModal().vm.$emit('reset');
await waitForPromises();
});
it('displays a toast', () => {
expect(mockToastShow).toHaveBeenCalledWith(I18N_DEFAULT_ERROR_MESSAGE);
});
it('captures exception in Sentry', () => {
expect(Sentry.captureException).toHaveBeenCalledTimes(1);
});
it('sets reset button `loading` prop to `false`', () => {
expect(findResetButton().props('loading')).toBe(false);
});
it('sets button `disabled` props to `false`', () => {
expect(findInstanceOrGroupSaveButton().props('disabled')).toBe(false);
expect(findTestButton().props('disabled')).toBe(false);
});
});
describe('when "reset settings" succeeds', () => {
beforeEach(async () => {
mockAxios.onPost(mockResetPath).replyOnce(httpStatus.OK);
createComponent({
customStateProps: {
integrationLevel: integrationLevels.GROUP,
resetPath: mockResetPath,
},
});
await findResetConfirmationModal().vm.$emit('reset');
await waitForPromises();
});
it('calls `refreshCurrentPage`', () => {
expect(refreshCurrentPage).toHaveBeenCalledTimes(1);
});
});
});
}); });
...@@ -4,17 +4,12 @@ import testAction from 'helpers/vuex_action_helper'; ...@@ -4,17 +4,12 @@ import testAction from 'helpers/vuex_action_helper';
import { I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE } from '~/integrations/constants'; import { I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE } from '~/integrations/constants';
import { import {
setOverride, setOverride,
setIsResetting,
requestResetIntegration,
receiveResetIntegrationSuccess,
receiveResetIntegrationError,
requestJiraIssueTypes, requestJiraIssueTypes,
receiveJiraIssueTypesSuccess, receiveJiraIssueTypesSuccess,
receiveJiraIssueTypesError, receiveJiraIssueTypesError,
} from '~/integrations/edit/store/actions'; } from '~/integrations/edit/store/actions';
import * as types from '~/integrations/edit/store/mutation_types'; import * as types from '~/integrations/edit/store/mutation_types';
import createState from '~/integrations/edit/store/state'; import createState from '~/integrations/edit/store/state';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { mockJiraIssueTypes } from '../mock_data'; import { mockJiraIssueTypes } from '../mock_data';
jest.mock('~/lib/utils/url_utility'); jest.mock('~/lib/utils/url_utility');
...@@ -38,38 +33,6 @@ describe('Integration form store actions', () => { ...@@ -38,38 +33,6 @@ describe('Integration form store actions', () => {
}); });
}); });
describe('setIsResetting', () => {
it('should commit isResetting mutation', () => {
return testAction(setIsResetting, true, state, [
{ type: types.SET_IS_RESETTING, payload: true },
]);
});
});
describe('requestResetIntegration', () => {
it('should commit REQUEST_RESET_INTEGRATION mutation', () => {
return testAction(requestResetIntegration, null, state, [
{ type: types.REQUEST_RESET_INTEGRATION },
]);
});
});
describe('receiveResetIntegrationSuccess', () => {
it('should call refreshCurrentPage()', () => {
return testAction(receiveResetIntegrationSuccess, null, state, [], [], () => {
expect(refreshCurrentPage).toHaveBeenCalled();
});
});
});
describe('receiveResetIntegrationError', () => {
it('should commit RECEIVE_RESET_INTEGRATION_ERROR mutation', () => {
return testAction(receiveResetIntegrationError, null, state, [
{ type: types.RECEIVE_RESET_INTEGRATION_ERROR },
]);
});
});
describe('requestJiraIssueTypes', () => { describe('requestJiraIssueTypes', () => {
describe.each` describe.each`
scenario | responseCode | response | action scenario | responseCode | response | action
......
...@@ -17,30 +17,6 @@ describe('Integration form store mutations', () => { ...@@ -17,30 +17,6 @@ describe('Integration form store mutations', () => {
}); });
}); });
describe(`${types.SET_IS_RESETTING}`, () => {
it('sets isResetting', () => {
mutations[types.SET_IS_RESETTING](state, true);
expect(state.isResetting).toBe(true);
});
});
describe(`${types.REQUEST_RESET_INTEGRATION}`, () => {
it('sets isResetting', () => {
mutations[types.REQUEST_RESET_INTEGRATION](state);
expect(state.isResetting).toBe(true);
});
});
describe(`${types.RECEIVE_RESET_INTEGRATION_ERROR}`, () => {
it('sets isResetting', () => {
mutations[types.RECEIVE_RESET_INTEGRATION_ERROR](state);
expect(state.isResetting).toBe(false);
});
});
describe(`${types.SET_JIRA_ISSUE_TYPES}`, () => { describe(`${types.SET_JIRA_ISSUE_TYPES}`, () => {
it('sets jiraIssueTypes', () => { it('sets jiraIssueTypes', () => {
const jiraIssueTypes = ['issue', 'epic']; const jiraIssueTypes = ['issue', 'epic'];
......
...@@ -5,8 +5,6 @@ describe('Integration form state factory', () => { ...@@ -5,8 +5,6 @@ describe('Integration form state factory', () => {
expect(createState()).toEqual({ expect(createState()).toEqual({
defaultState: null, defaultState: null,
customState: {}, customState: {},
isSaving: false,
isResetting: false,
override: false, override: false,
isLoadingJiraIssueTypes: false, isLoadingJiraIssueTypes: false,
jiraIssueTypes: [], jiraIssueTypes: [],
......
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