Commit 38364325 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Added missing createCustomStage action specs

Added missing updateStage action specs

Ensures we correctly handle fetch
reqeust failures in the success actions
parent a49b0d95
......@@ -24,7 +24,7 @@ const handleErrorOrRethrow = ({ action, error }) => {
const isStageNameExistsError = ({ status, errors }) => {
const ERROR_NAME_RESERVED = 'is reserved';
if (status === httpStatus.UNPROCESSABLE_ENTITY) {
if (errors.name && errors.name[0] === ERROR_NAME_RESERVED) return true;
if (errors?.name.includes(ERROR_NAME_RESERVED)) return true;
}
return false;
};
......@@ -278,14 +278,22 @@ export const receiveCreateCustomStageSuccess = ({ commit, dispatch }, { data: {
commit(types.RECEIVE_CREATE_CUSTOM_STAGE_SUCCESS);
createFlash(sprintf(__(`Your custom stage '%{title}' was created`), { title }), 'notice');
return dispatch('fetchGroupStagesAndEvents').then(() => dispatch('fetchSummaryData'));
return Promise.resolve()
.then(() => dispatch('fetchGroupStagesAndEvents'))
.then(() => dispatch('fetchSummaryData'))
.catch(() => {
createFlash(__('There was a problem refreshing the data, please try again'));
});
};
export const receiveCreateCustomStageError = ({ commit }, { status, message, errors, data }) => {
commit(types.RECEIVE_CREATE_CUSTOM_STAGE_ERROR, { status, message, errors, data });
const { name } = data;
const flashMessage = isStageNameExistsError({ status, errors })
export const receiveCreateCustomStageError = (
{ commit },
{ status = 400, errors = {}, data = {} } = {},
) => {
commit(types.RECEIVE_CREATE_CUSTOM_STAGE_ERROR, { errors });
const { name = null } = data;
const flashMessage =
name && isStageNameExistsError({ status, errors })
? sprintf(__(`'%{name}' stage already exists`), { name })
: __('There was a problem saving your custom stage, please try again');
......@@ -299,12 +307,12 @@ export const createCustomStage = ({ dispatch, state }, data) => {
dispatch('requestCreateCustomStage');
return Api.cycleAnalyticsCreateStage(fullPath, data)
.then(response => dispatch('receiveCreateCustomStageSuccess', response))
.catch(({ response }) => {
const {
data: { message, errors },
status,
} = response;
.then(response => {
const { status, data: responseData } = response;
return dispatch('receiveCreateCustomStageSuccess', { status, data: responseData });
})
.catch(({ response } = {}) => {
const { data: { message, errors } = null, status = 400 } = response;
dispatch('receiveCreateCustomStageError', { data, message, errors, status });
});
......@@ -356,8 +364,12 @@ export const receiveUpdateStageSuccess = ({ commit, dispatch }, updatedData) =>
commit(types.RECEIVE_UPDATE_STAGE_SUCCESS);
createFlash(__('Stage data updated'), 'notice');
dispatch('fetchGroupStagesAndEvents');
dispatch('setSelectedStage', updatedData);
return Promise.all([
dispatch('fetchGroupStagesAndEvents'),
dispatch('setSelectedStage', updatedData),
]).catch(() => {
createFlash(__('There was a problem refreshing the data, please try again'));
});
};
export const receiveUpdateStageError = (
......
......@@ -435,8 +435,8 @@ describe 'Group Value Stream Analytics', :js do
context 'with all required fields set' do
before do
select_dropdown_label 'custom-stage-start-event-label', 2
select_dropdown_label 'custom-stage-stop-event-label', 3
select_dropdown_label 'custom-stage-start-event-label', 1
select_dropdown_label 'custom-stage-stop-event-label', 2
end
it_behaves_like 'submits the form successfully', custom_stage_with_labels_name
......
......@@ -682,6 +682,53 @@ describe('Cycle analytics actions', () => {
done();
});
});
describe('receiveUpdateStageSuccess', () => {
beforeEach(() => {
setFixtures('<div class="flash-container"></div>');
});
const response = {
title: 'NEW - COOL',
};
it('will dispatch fetchGroupStagesAndEvents and fetchSummaryData', () =>
testAction(
actions.receiveUpdateStageSuccess,
response,
state,
[{ type: types.RECEIVE_UPDATE_STAGE_SUCCESS }],
[{ type: 'fetchGroupStagesAndEvents' }, { type: 'setSelectedStage', payload: response }],
));
it('will flash a success message', () =>
actions
.receiveUpdateStageSuccess(
{
dispatch: () => {},
commit: () => {},
},
response,
)
.then(() => {
shouldFlashAMessage('Stage data updated');
}));
describe('with an error', () => {
it('will flash an error message', () =>
actions
.receiveUpdateStageSuccess(
{
dispatch: () => Promise.reject(),
commit: () => {},
},
response,
)
.then(() => {
shouldFlashAMessage('There was a problem refreshing the data, please try again');
}));
});
});
});
describe('removeStage', () => {
......@@ -1276,4 +1323,150 @@ describe('Cycle analytics actions', () => {
);
});
});
describe('createCustomStage', () => {
describe('with valid data', () => {
const customStageData = {
startEventIdentifier: 'start_event',
endEventIdentifier: 'end_event',
name: 'cool-new-stage',
};
beforeEach(() => {
state = { ...state, selectedGroup };
mock.onPost(endpoints.baseStagesEndpointstageData).reply(201, customStageData);
});
it(`dispatches the 'receiveCreateCustomStageSuccess' action`, () =>
testAction(
actions.createCustomStage,
customStageData,
state,
[],
[
{ type: 'requestCreateCustomStage' },
{
type: 'receiveCreateCustomStageSuccess',
payload: { data: customStageData, status: 201 },
},
],
));
});
describe('with errors', () => {
const message = 'failed';
const errors = {
endEventIdentifier: ['Cant be blank'],
};
const customStageData = {
startEventIdentifier: 'start_event',
endEventIdentifier: '',
name: 'cool-new-stage',
};
beforeEach(() => {
state = { ...state, selectedGroup };
mock.onPost(endpoints.baseStagesEndpointstageData).reply(422, {
message,
errors,
});
});
it(`dispatches the 'receiveCreateCustomStageError' action`, () =>
testAction(
actions.createCustomStage,
customStageData,
state,
[],
[
{ type: 'requestCreateCustomStage' },
{
type: 'receiveCreateCustomStageError',
payload: {
data: customStageData,
errors,
message,
status: 422,
},
},
],
));
});
});
describe('receiveCreateCustomStageError', () => {
const response = {
data: { name: 'uh oh' },
};
beforeEach(() => {
setFixtures('<div class="flash-container"></div>');
});
it('will commit the RECEIVE_CREATE_CUSTOM_STAGE_ERROR mutation', () =>
testAction(actions.receiveCreateCustomStageError, response, state, [
{ type: types.RECEIVE_CREATE_CUSTOM_STAGE_ERROR, payload: { errors: {} } },
]));
it('will flash an error message', done => {
actions.receiveCreateCustomStageError(
{
commit: () => {},
},
response,
);
shouldFlashAMessage('There was a problem saving your custom stage, please try again');
done();
});
describe('with a stage name error', () => {
it('will flash an error message', done => {
actions.receiveCreateCustomStageError(
{
commit: () => {},
},
{ ...response, status: 422, errors: { name: ['is reserved'] } },
);
shouldFlashAMessage("'uh oh' stage already exists");
done();
});
});
});
describe('receiveCreateCustomStageSuccess', () => {
const response = {
data: {
title: 'COOL',
},
};
it('will dispatch fetchGroupStagesAndEvents and fetchSummaryData', () =>
testAction(
actions.receiveCreateCustomStageSuccess,
response,
state,
[{ type: types.RECEIVE_CREATE_CUSTOM_STAGE_SUCCESS }],
[{ type: 'fetchGroupStagesAndEvents' }, { type: 'fetchSummaryData' }],
));
describe('with an error', () => {
beforeEach(() => {
setFixtures('<div class="flash-container"></div>');
});
it('will flash an error message', () =>
actions
.receiveCreateCustomStageSuccess(
{
dispatch: () => Promise.reject(),
commit: () => {},
},
response,
)
.then(() => {
shouldFlashAMessage('There was a problem refreshing the data, please try again');
}));
});
});
});
......@@ -19326,6 +19326,9 @@ msgstr ""
msgid "There was a problem communicating with your device."
msgstr ""
msgid "There was a problem refreshing the data, please try again"
msgstr ""
msgid "There was a problem saving your custom stage, please try again"
msgstr ""
......
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