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>
import { GlButton, GlModalDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import axios from 'axios';
import * as Sentry from '@sentry/browser';
import { mapState, mapActions, mapGetters } from 'vuex';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
......@@ -10,6 +11,7 @@ import {
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
integrationLevels,
} from '~/integrations/constants';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
import { testIntegrationSettings } from '../api';
import ActiveCheckbox from './active_checkbox.vue';
......@@ -55,11 +57,12 @@ export default {
integrationActive: false,
isTesting: false,
isSaving: false,
isResetting: false,
};
},
computed: {
...mapGetters(['currentKey', 'propsSource']),
...mapState(['defaultState', 'customState', 'override', 'isResetting']),
...mapState(['defaultState', 'customState', 'override']),
isEditable() {
return this.propsSource.editable;
},
......@@ -126,7 +129,20 @@ export default {
});
},
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() {
this.requestJiraIssueTypes(this.getFormData());
......@@ -208,6 +224,7 @@ export default {
variant="confirm"
:loading="isSaving"
:disabled="disableButtons"
data-testid="save-button-instance-group"
data-qa-selector="save_changes_button"
>
{{ __('Save changes') }}
......
......@@ -11,7 +11,7 @@ export default {
primaryProps() {
return {
text: __('Reset'),
attributes: [{ variant: 'warning' }, { category: 'primary' }],
attributes: [{ variant: 'danger' }, { category: 'primary' }],
};
},
cancelProps() {
......
import axios from 'axios';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import {
VALIDATE_INTEGRATION_FORM_EVENT,
I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
......@@ -10,27 +8,6 @@ import eventHub from '../event_hub';
import * as types from './mutation_types';
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) => {
commit(types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE, '');
......
......@@ -4,15 +4,6 @@ export default {
[types.SET_OVERRIDE](state, 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) {
state.jiraIssueTypes = jiraIssueTypes;
},
......
......@@ -5,8 +5,6 @@ export default ({ defaultState = null, customState = {} } = {}) => {
override,
defaultState,
customState,
isSaving: false,
isResetting: false,
isLoadingJiraIssueTypes: false,
loadingJiraIssueTypesErrorMessage: '',
jiraIssueTypes: [],
......
......@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import * as Sentry from '@sentry/browser';
import { setHTMLFixture } from 'helpers/fixtures';
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 ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
......@@ -13,7 +13,6 @@ import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_field
import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
import ResetConfirmationModal from '~/integrations/edit/components/reset_confirmation_modal.vue';
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
import waitForPromises from 'helpers/wait_for_promises';
import {
integrationLevels,
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
......@@ -23,9 +22,12 @@ import {
import { createStore } from '~/integrations/edit/store';
import eventHub from '~/integrations/edit/event_hub';
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('@sentry/browser');
jest.mock('~/lib/utils/url_utility');
describe('IntegrationForm', () => {
const mockToastShow = jest.fn();
......@@ -80,7 +82,8 @@ describe('IntegrationForm', () => {
const findConfirmationModal = () => wrapper.findComponent(ConfirmationModal);
const findResetConfirmationModal = () => wrapper.findComponent(ResetConfirmationModal);
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 findJiraTriggerFields = () => wrapper.findComponent(JiraTriggerFields);
const findJiraIssuesFields = () => wrapper.findComponent(JiraIssuesFields);
......@@ -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`', () => {
expect(findSaveButton().props('loading')).toBe(true);
expect(findProjectSaveButton().props('loading')).toBe(true);
});
it('sets test button `disabled` prop to `true`', () => {
......@@ -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', () => {
......@@ -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', () => {
......@@ -453,7 +456,7 @@ describe('IntegrationForm', () => {
});
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`', () => {
......@@ -507,7 +510,7 @@ describe('IntegrationForm', () => {
});
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', () => {
});
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`, () => {
......@@ -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';
import { I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE } from '~/integrations/constants';
import {
setOverride,
setIsResetting,
requestResetIntegration,
receiveResetIntegrationSuccess,
receiveResetIntegrationError,
requestJiraIssueTypes,
receiveJiraIssueTypesSuccess,
receiveJiraIssueTypesError,
} from '~/integrations/edit/store/actions';
import * as types from '~/integrations/edit/store/mutation_types';
import createState from '~/integrations/edit/store/state';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { mockJiraIssueTypes } from '../mock_data';
jest.mock('~/lib/utils/url_utility');
......@@ -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.each`
scenario | responseCode | response | action
......
......@@ -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}`, () => {
it('sets jiraIssueTypes', () => {
const jiraIssueTypes = ['issue', 'epic'];
......
......@@ -5,8 +5,6 @@ describe('Integration form state factory', () => {
expect(createState()).toEqual({
defaultState: null,
customState: {},
isSaving: false,
isResetting: false,
override: false,
isLoadingJiraIssueTypes: false,
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