Commit f57e8d2b authored by Fatih Acet's avatar Fatih Acet

Merge branch '35206-follow-up-consolidate-cycle-analytics-urls' into 'master'

Follow up: consolidate cycle analytics URLs

Closes #35206

See merge request gitlab-org/gitlab!20192
parents b0182221 3894edef
...@@ -92,8 +92,6 @@ export default { ...@@ -92,8 +92,6 @@ export default {
'fetchCycleAnalyticsData', 'fetchCycleAnalyticsData',
'fetchStageData', 'fetchStageData',
'fetchGroupStagesAndEvents', 'fetchGroupStagesAndEvents',
'setCycleAnalyticsDataEndpoint',
'setStageDataEndpoint',
'setSelectedGroup', 'setSelectedGroup',
'setSelectedProjects', 'setSelectedProjects',
'setSelectedTimeframe', 'setSelectedTimeframe',
...@@ -106,7 +104,6 @@ export default { ...@@ -106,7 +104,6 @@ export default {
'fetchTasksByTypeData', 'fetchTasksByTypeData',
]), ]),
onGroupSelect(group) { onGroupSelect(group) {
this.setCycleAnalyticsDataEndpoint(group.full_path);
this.setSelectedGroup(group); this.setSelectedGroup(group);
this.fetchCycleAnalyticsData(); this.fetchCycleAnalyticsData();
}, },
...@@ -118,8 +115,7 @@ export default { ...@@ -118,8 +115,7 @@ export default {
onStageSelect(stage) { onStageSelect(stage) {
this.hideCustomStageForm(); this.hideCustomStageForm();
this.setSelectedStageId(stage.id); this.setSelectedStageId(stage.id);
this.setStageDataEndpoint(this.currentStage.slug); this.fetchStageData(this.currentStage.slug);
this.fetchStageData(this.currentStage.name);
}, },
onShowAddStageForm() { onShowAddStageForm() {
this.showCustomStageForm(); this.showCustomStageForm();
......
import axios from '~/lib/utils/axios_utils';
import createFlash, { hideFlash } from '~/flash'; import createFlash, { hideFlash } from '~/flash';
import { __ } from '~/locale'; import { __ } from '~/locale';
import Api from 'ee/api'; import Api from 'ee/api';
...@@ -13,11 +12,6 @@ const removeError = () => { ...@@ -13,11 +12,6 @@ const removeError = () => {
} }
}; };
export const setCycleAnalyticsDataEndpoint = ({ commit }, groupPath) =>
commit(types.SET_CYCLE_ANALYTICS_DATA_ENDPOINT, groupPath);
export const setStageDataEndpoint = ({ commit }, stageSlug) =>
commit(types.SET_STAGE_DATA_ENDPOINT, stageSlug);
export const setSelectedGroup = ({ commit }, group) => commit(types.SET_SELECTED_GROUP, group); export const setSelectedGroup = ({ commit }, group) => commit(types.SET_SELECTED_GROUP, group);
export const setSelectedProjects = ({ commit }, projectIds) => export const setSelectedProjects = ({ commit }, projectIds) =>
commit(types.SET_SELECTED_PROJECTS, projectIds); commit(types.SET_SELECTED_PROJECTS, projectIds);
...@@ -44,14 +38,19 @@ export const receiveStageDataError = ({ commit }) => { ...@@ -44,14 +38,19 @@ export const receiveStageDataError = ({ commit }) => {
createFlash(__('There was an error fetching data for the selected stage')); createFlash(__('There was an error fetching data for the selected stage'));
}; };
export const fetchStageData = ({ state, dispatch, getters }) => { export const fetchStageData = ({ state, dispatch, getters }, slug) => {
const { cycleAnalyticsRequestParams = {} } = getters; const { cycleAnalyticsRequestParams = {} } = getters;
dispatch('requestStageData'); dispatch('requestStageData');
axios const {
.get(state.endpoints.stageData, { selectedGroup: { fullPath },
params: nestQueryStringKeys(cycleAnalyticsRequestParams, 'cycle_analytics'), } = state;
})
return Api.cycleAnalyticsStageEvents(
fullPath,
slug,
nestQueryStringKeys(cycleAnalyticsRequestParams, 'cycle_analytics'),
)
.then(({ data }) => dispatch('receiveStageDataSuccess', data)) .then(({ data }) => dispatch('receiveStageDataSuccess', data))
.catch(error => dispatch('receiveStageDataError', error)); .catch(error => dispatch('receiveStageDataError', error));
}; };
...@@ -94,10 +93,14 @@ export const fetchSummaryData = ({ state, dispatch, getters }) => { ...@@ -94,10 +93,14 @@ export const fetchSummaryData = ({ state, dispatch, getters }) => {
const { cycleAnalyticsRequestParams = {} } = getters; const { cycleAnalyticsRequestParams = {} } = getters;
dispatch('requestSummaryData'); dispatch('requestSummaryData');
return axios const {
.get(state.endpoints.cycleAnalyticsData, { selectedGroup: { fullPath },
params: nestQueryStringKeys(cycleAnalyticsRequestParams, 'cycle_analytics'), } = state;
})
return Api.cycleAnalyticsSummaryData(
fullPath,
nestQueryStringKeys(cycleAnalyticsRequestParams, 'cycle_analytics'),
)
.then(({ data }) => dispatch('receiveSummaryDataSuccess', data)) .then(({ data }) => dispatch('receiveSummaryDataSuccess', data))
.catch(error => dispatch('receiveSummaryDataError', error)); .catch(error => dispatch('receiveSummaryDataError', error));
}; };
...@@ -139,23 +142,26 @@ export const receiveGroupStagesAndEventsSuccess = ({ state, commit, dispatch }, ...@@ -139,23 +142,26 @@ export const receiveGroupStagesAndEventsSuccess = ({ state, commit, dispatch },
const { stages = [] } = state; const { stages = [] } = state;
if (stages && stages.length) { if (stages && stages.length) {
const { slug } = stages[0]; const { slug } = stages[0];
dispatch('setStageDataEndpoint', slug); dispatch('fetchStageData', slug);
dispatch('fetchStageData');
} else { } else {
createFlash(__('There was an error while fetching cycle analytics data.')); createFlash(__('There was an error while fetching cycle analytics data.'));
} }
}; };
export const fetchGroupStagesAndEvents = ({ state, dispatch, getters }) => { export const fetchGroupStagesAndEvents = ({ state, dispatch, getters }) => {
const {
selectedGroup: { fullPath },
} = state;
const { const {
cycleAnalyticsRequestParams: { created_after, project_ids }, cycleAnalyticsRequestParams: { created_after, project_ids },
} = getters; } = getters;
dispatch('requestGroupStagesAndEvents'); dispatch('requestGroupStagesAndEvents');
return axios return Api.cycleAnalyticsGroupStagesAndEvents(
.get(state.endpoints.cycleAnalyticsStagesAndEvents, { fullPath,
params: nestQueryStringKeys({ start_date: created_after, project_ids }, 'cycle_analytics'), nestQueryStringKeys({ start_date: created_after, project_ids }, 'cycle_analytics'),
}) )
.then(({ data }) => dispatch('receiveGroupStagesAndEventsSuccess', data)) .then(({ data }) => dispatch('receiveGroupStagesAndEventsSuccess', data))
.catch(error => dispatch('receiveGroupStagesAndEventsError', error)); .catch(error => dispatch('receiveGroupStagesAndEventsError', error));
}; };
...@@ -173,6 +179,8 @@ export const receiveCreateCustomStageError = ({ commit }, { error, data }) => { ...@@ -173,6 +179,8 @@ export const receiveCreateCustomStageError = ({ commit }, { error, data }) => {
const { name } = data; const { name } = data;
const { status } = error; const { status } = error;
// TODO: check for 403, 422 etc
// Follow up issue to investigate https://gitlab.com/gitlab-org/gitlab/issues/36685
const message = const message =
status !== httpStatus.UNPROCESSABLE_ENTITY status !== httpStatus.UNPROCESSABLE_ENTITY
? __(`'${name}' stage already exists'`) ? __(`'${name}' stage already exists'`)
...@@ -186,11 +194,9 @@ export const createCustomStage = ({ dispatch, state }, data) => { ...@@ -186,11 +194,9 @@ export const createCustomStage = ({ dispatch, state }, data) => {
selectedGroup: { fullPath }, selectedGroup: { fullPath },
} = state; } = state;
const endpoint = `/-/analytics/cycle_analytics/stages?group_id=${fullPath}`;
dispatch('requestCreateCustomStage'); dispatch('requestCreateCustomStage');
axios return Api.cycleAnalyticsCreateStage(fullPath, data)
.post(endpoint, data)
.then(response => dispatch('receiveCreateCustomStageSuccess', response)) .then(response => dispatch('receiveCreateCustomStageSuccess', response))
.catch(error => dispatch('receiveCreateCustomStageError', { error, data })); .catch(error => dispatch('receiveCreateCustomStageError', { error, data }));
}; };
......
export const SET_CYCLE_ANALYTICS_DATA_ENDPOINT = 'SET_CYCLE_ANALYTICS_DATA_ENDPOINT';
export const SET_STAGE_DATA_ENDPOINT = 'SET_STAGE_DATA_ENDPOINT';
export const SET_SELECTED_GROUP = 'SET_SELECTED_GROUP'; export const SET_SELECTED_GROUP = 'SET_SELECTED_GROUP';
export const SET_SELECTED_PROJECTS = 'SET_SELECTED_PROJECTS'; export const SET_SELECTED_PROJECTS = 'SET_SELECTED_PROJECTS';
export const SET_SELECTED_STAGE_ID = 'SET_SELECTED_STAGE_ID'; export const SET_SELECTED_STAGE_ID = 'SET_SELECTED_STAGE_ID';
......
...@@ -3,18 +3,6 @@ import * as types from './mutation_types'; ...@@ -3,18 +3,6 @@ import * as types from './mutation_types';
import { transformRawStages } from '../utils'; import { transformRawStages } from '../utils';
export default { export default {
[types.SET_CYCLE_ANALYTICS_DATA_ENDPOINT](state, groupPath) {
// TODO: this endpoint will be removed when the /-/analytics endpoints are ready
// https://gitlab.com/gitlab-org/gitlab/issues/34751
state.endpoints.cycleAnalyticsData = `/groups/${groupPath}/-/cycle_analytics`;
state.endpoints.cycleAnalyticsStagesAndEvents = `/-/analytics/cycle_analytics/stages?group_id=${groupPath}`;
},
[types.SET_STAGE_DATA_ENDPOINT](state, stageSlug) {
// TODO: this endpoint will be replaced with a /-/analytics... endpoint when backend is ready
// https://gitlab.com/gitlab-org/gitlab/issues/34751
const { fullPath } = state.selectedGroup;
state.endpoints.stageData = `/groups/${fullPath}/-/cycle_analytics/events/${stageSlug}.json`;
},
[types.SET_SELECTED_GROUP](state, group) { [types.SET_SELECTED_GROUP](state, group) {
state.selectedGroup = convertObjectPropsToCamelCase(group, { deep: true }); state.selectedGroup = convertObjectPropsToCamelCase(group, { deep: true });
state.selectedProjectIds = []; state.selectedProjectIds = [];
......
import { TASKS_BY_TYPE_SUBJECT_ISSUE } from '../constants'; import { TASKS_BY_TYPE_SUBJECT_ISSUE } from '../constants';
export default () => ({ export default () => ({
endpoints: {
cycleAnalyticsData: null,
stageData: null,
cycleAnalyticsStagesAndEvents: null,
summaryData: null,
},
startDate: null, startDate: null,
endDate: null, endDate: null,
......
...@@ -19,6 +19,9 @@ export default { ...@@ -19,6 +19,9 @@ export default {
projectPackagesPath: '/api/:version/projects/:id/packages', projectPackagesPath: '/api/:version/projects/:id/packages',
projectPackagePath: '/api/:version/projects/:id/packages/:package_id', projectPackagePath: '/api/:version/projects/:id/packages/:package_id',
cycleAnalyticsTasksByTypePath: '/-/analytics/type_of_work/tasks_by_type', cycleAnalyticsTasksByTypePath: '/-/analytics/type_of_work/tasks_by_type',
cycleAnalyticsSummaryDataPath: '/groups/:group_id/-/cycle_analytics',
cycleAnalyticsGroupStagesAndEventsPath: '/-/analytics/cycle_analytics/stages',
cycleAnalyticsStageEventsPath: '/groups/:group_id/-/cycle_analytics/events/:stage_id.json',
userSubscription(namespaceId) { userSubscription(namespaceId) {
const url = Api.buildUrl(this.subscriptionPath).replace(':id', encodeURIComponent(namespaceId)); const url = Api.buildUrl(this.subscriptionPath).replace(':id', encodeURIComponent(namespaceId));
...@@ -141,4 +144,33 @@ export default { ...@@ -141,4 +144,33 @@ export default {
const url = Api.buildUrl(this.cycleAnalyticsTasksByTypePath); const url = Api.buildUrl(this.cycleAnalyticsTasksByTypePath);
return axios.get(url, { params }); return axios.get(url, { params });
}, },
cycleAnalyticsSummaryData(groupId, params = {}) {
const url = Api.buildUrl(this.cycleAnalyticsSummaryDataPath).replace(':group_id', groupId);
return axios.get(url, { params });
},
cycleAnalyticsGroupStagesAndEvents(groupId, params = {}) {
const url = Api.buildUrl(this.cycleAnalyticsGroupStagesAndEventsPath);
return axios.get(url, {
params: { group_id: groupId, ...params },
});
},
cycleAnalyticsStageEvents(groupId, stageId, params = {}) {
const url = Api.buildUrl(this.cycleAnalyticsStageEventsPath)
.replace(':group_id', groupId)
.replace(':stage_id', stageId);
return axios.get(url, { params });
},
cycleAnalyticsCreateStage(groupId, data) {
const url = Api.buildUrl(this.cycleAnalyticsGroupStagesAndEventsPath);
return axios.post(url, data, {
params: { group_id: groupId },
});
},
}; };
...@@ -309,7 +309,7 @@ describe('Cycle Analytics component', () => { ...@@ -309,7 +309,7 @@ describe('Cycle Analytics component', () => {
}, },
fetchGroupStagesAndEvents: { fetchGroupStagesAndEvents: {
status: defaultStatus, status: defaultStatus,
endpoint: `/-/analytics/cycle_analytics/stages?group_id=${groupId}`, endpoint: `/-/analytics/cycle_analytics/stages`,
response: { ...mockData.customizableStagesAndEvents }, response: { ...mockData.customizableStagesAndEvents },
}, },
fetchGroupLabels: { fetchGroupLabels: {
......
import axios from 'axios'; import axios from 'axios';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper'; import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'helpers/test_constants';
import createFlash from '~/flash'; import createFlash from '~/flash';
import * as getters from 'ee/analytics/cycle_analytics/store/getters'; import * as getters from 'ee/analytics/cycle_analytics/store/getters';
import * as actions from 'ee/analytics/cycle_analytics/store/actions'; import * as actions from 'ee/analytics/cycle_analytics/store/actions';
...@@ -18,10 +17,14 @@ import { ...@@ -18,10 +17,14 @@ import {
const stageData = { events: [] }; const stageData = { events: [] };
const error = new Error('Request failed with status code 404'); const error = new Error('Request failed with status code 404');
const groupPath = 'cool-group';
const groupLabelsEndpoint = `/groups/${groupPath}/-/labels`;
const flashErrorMessage = 'There was an error while fetching cycle analytics data.'; const flashErrorMessage = 'There was an error while fetching cycle analytics data.';
const selectedGroup = { fullPath: groupPath }; const selectedGroup = { fullPath: group.path };
const [{ id: selectedStageSlug }] = stages;
const endpoints = {
groupLabels: `/groups/${group.path}/-/labels`,
cycleAnalyticsData: `/groups/${group.path}/-/cycle_analytics`,
stageData: `/groups/${group.path}/-/cycle_analytics/events/${selectedStageSlug}.json`,
};
describe('Cycle analytics actions', () => { describe('Cycle analytics actions', () => {
let state; let state;
...@@ -33,10 +36,6 @@ describe('Cycle analytics actions', () => { ...@@ -33,10 +36,6 @@ describe('Cycle analytics actions', () => {
beforeEach(() => { beforeEach(() => {
state = { state = {
endpoints: {
cycleAnalyticsData: `${TEST_HOST}/groups/${group.path}/-/cycle_analytics`,
stageData: `${TEST_HOST}/groups/${group.path}/-/cycle_analytics/events/${cycleAnalyticsData.stats[0].name}.json`,
},
stages: [], stages: [],
getters, getters,
}; };
...@@ -49,12 +48,10 @@ describe('Cycle analytics actions', () => { ...@@ -49,12 +48,10 @@ describe('Cycle analytics actions', () => {
}); });
it.each` it.each`
action | type | stateKey | payload action | type | stateKey | payload
${'setCycleAnalyticsDataEndpoint'} | ${'SET_CYCLE_ANALYTICS_DATA_ENDPOINT'} | ${'endpoints.cycleAnalyticsData'} | ${'coolGroupName'} ${'setSelectedGroup'} | ${'SET_SELECTED_GROUP'} | ${'selectedGroup'} | ${'someNewGroup'}
${'setStageDataEndpoint'} | ${'SET_STAGE_DATA_ENDPOINT'} | ${'endpoints.stageData'} | ${'new_stage_name'} ${'setSelectedProjects'} | ${'SET_SELECTED_PROJECTS'} | ${'selectedProjectIds'} | ${[10, 20, 30, 40]}
${'setSelectedGroup'} | ${'SET_SELECTED_GROUP'} | ${'selectedGroup'} | ${'someNewGroup'} ${'setSelectedStageId'} | ${'SET_SELECTED_STAGE_ID'} | ${'selectedStageId'} | ${'someNewGroup'}
${'setSelectedProjects'} | ${'SET_SELECTED_PROJECTS'} | ${'selectedProjectIds'} | ${[10, 20, 30, 40]}
${'setSelectedStageId'} | ${'SET_SELECTED_STAGE_ID'} | ${'selectedStageId'} | ${'someNewGroup'}
`('$action should set $stateKey with $payload and type $type', ({ action, type, payload }) => { `('$action should set $stateKey with $payload and type $type', ({ action, type, payload }) => {
testAction( testAction(
actions[action], actions[action],
...@@ -87,13 +84,14 @@ describe('Cycle analytics actions', () => { ...@@ -87,13 +84,14 @@ describe('Cycle analytics actions', () => {
describe('fetchStageData', () => { describe('fetchStageData', () => {
beforeEach(() => { beforeEach(() => {
mock.onGet(state.endpoints.stageData).replyOnce(200, { events: [] }); state = { ...state, selectedGroup };
mock.onGet(endpoints.stageData).replyOnce(200, { events: [] });
}); });
it('dispatches receiveStageDataSuccess with received data on success', done => { it('dispatches receiveStageDataSuccess with received data on success', done => {
testAction( testAction(
actions.fetchStageData, actions.fetchStageData,
null, selectedStageSlug,
state, state,
[], [],
[ [
...@@ -108,17 +106,10 @@ describe('Cycle analytics actions', () => { ...@@ -108,17 +106,10 @@ describe('Cycle analytics actions', () => {
}); });
it('dispatches receiveStageDataError on error', done => { it('dispatches receiveStageDataError on error', done => {
const brokenState = {
...state,
endpoints: {
stageData: 'this will break',
},
};
testAction( testAction(
actions.fetchStageData, actions.fetchStageData,
null, null,
brokenState, state,
[], [],
[ [
{ type: 'requestStageData' }, { type: 'requestStageData' },
...@@ -176,7 +167,7 @@ describe('Cycle analytics actions', () => { ...@@ -176,7 +167,7 @@ describe('Cycle analytics actions', () => {
describe('fetchGroupLabels', () => { describe('fetchGroupLabels', () => {
beforeEach(() => { beforeEach(() => {
state = { ...state, selectedGroup }; state = { ...state, selectedGroup };
mock.onGet(groupLabelsEndpoint).replyOnce(200, groupLabels); mock.onGet(endpoints.groupLabels).replyOnce(200, groupLabels);
}); });
it('dispatches receiveGroupLabels if the request succeeds', done => { it('dispatches receiveGroupLabels if the request succeeds', done => {
...@@ -251,7 +242,7 @@ describe('Cycle analytics actions', () => { ...@@ -251,7 +242,7 @@ describe('Cycle analytics actions', () => {
beforeEach(() => { beforeEach(() => {
setFixtures('<div class="flash-container"></div>'); setFixtures('<div class="flash-container"></div>');
mock.onGet(state.endpoints.cycleAnalyticsData).replyOnce(200, cycleAnalyticsData); mock.onGet(endpoints.cycleAnalyticsData).replyOnce(200, cycleAnalyticsData);
state = { ...state, selectedGroup, startDate, endDate }; state = { ...state, selectedGroup, startDate, endDate };
}); });
...@@ -354,8 +345,7 @@ describe('Cycle analytics actions', () => { ...@@ -354,8 +345,7 @@ describe('Cycle analytics actions', () => {
}); });
}); });
it("dispatches the 'setStageDataEndpoint' and 'fetchStageData' actions", done => { it("dispatches the 'fetchStageData' action", done => {
const { id } = stages[0];
const stateWithStages = { const stateWithStages = {
...state, ...state,
stages, stages,
...@@ -371,7 +361,7 @@ describe('Cycle analytics actions', () => { ...@@ -371,7 +361,7 @@ describe('Cycle analytics actions', () => {
payload: { ...customizableStagesAndEvents }, payload: { ...customizableStagesAndEvents },
}, },
], ],
[{ type: 'setStageDataEndpoint', payload: id }, { type: 'fetchStageData' }], [{ type: 'fetchStageData', payload: selectedStageSlug }],
done, done,
); );
}); });
...@@ -463,8 +453,7 @@ describe('Cycle analytics actions', () => { ...@@ -463,8 +453,7 @@ describe('Cycle analytics actions', () => {
); );
}); });
it("dispatches the 'setStageDataEndpoint' and 'fetchStageData' actions", done => { it("dispatches the 'fetchStageData' actions", done => {
const { id } = stages[0];
const stateWithStages = { const stateWithStages = {
...state, ...state,
stages, stages,
...@@ -480,7 +469,7 @@ describe('Cycle analytics actions', () => { ...@@ -480,7 +469,7 @@ describe('Cycle analytics actions', () => {
payload: { ...customizableStagesAndEvents }, payload: { ...customizableStagesAndEvents },
}, },
], ],
[{ type: 'setStageDataEndpoint', payload: id }, { type: 'fetchStageData' }], [{ type: 'fetchStageData', payload: selectedStageSlug }],
done, done,
); );
}); });
......
...@@ -57,13 +57,11 @@ describe('Cycle analytics mutations', () => { ...@@ -57,13 +57,11 @@ describe('Cycle analytics mutations', () => {
}); });
it.each` it.each`
mutation | payload | expectedState mutation | payload | expectedState
${types.SET_CYCLE_ANALYTICS_DATA_ENDPOINT} | ${'cool-beans'} | ${{ endpoints: { cycleAnalyticsStagesAndEvents: '/-/analytics/cycle_analytics/stages?group_id=cool-beans' } }} ${types.SET_SELECTED_GROUP} | ${{ fullPath: 'cool-beans' }} | ${{ selectedGroup: { fullPath: 'cool-beans' }, selectedProjectIds: [] }}
${types.SET_STAGE_DATA_ENDPOINT} | ${'rad-stage'} | ${{ endpoints: { stageData: '/groups/rad-stage/-/cycle_analytics/events/rad-stage.json' } }} ${types.SET_SELECTED_PROJECTS} | ${[606, 707, 808, 909]} | ${{ selectedProjectIds: [606, 707, 808, 909] }}
${types.SET_SELECTED_GROUP} | ${{ fullPath: 'cool-beans' }} | ${{ selectedGroup: { fullPath: 'cool-beans' }, selectedProjectIds: [] }} ${types.SET_DATE_RANGE} | ${{ startDate, endDate }} | ${{ startDate, endDate }}
${types.SET_SELECTED_PROJECTS} | ${[606, 707, 808, 909]} | ${{ selectedProjectIds: [606, 707, 808, 909] }} ${types.SET_SELECTED_STAGE_ID} | ${'first-stage'} | ${{ selectedStageId: 'first-stage' }}
${types.SET_DATE_RANGE} | ${{ startDate, endDate }} | ${{ startDate, endDate }}
${types.SET_SELECTED_STAGE_ID} | ${'first-stage'} | ${{ selectedStageId: 'first-stage' }}
`( `(
'$mutation with payload $payload will update state with $expectedState', '$mutation with payload $payload will update state with $expectedState',
({ mutation, payload, expectedState }) => { ({ mutation, payload, expectedState }) => {
......
...@@ -289,6 +289,17 @@ describe('Api', () => { ...@@ -289,6 +289,17 @@ describe('Api', () => {
const groupId = 'counting-54321'; const groupId = 'counting-54321';
const createdBefore = '2019-11-18'; const createdBefore = '2019-11-18';
const createdAfter = '2019-08-18'; const createdAfter = '2019-08-18';
const stageId = 'thursday';
const expectRequestWithCorrectParameters = (responseObj, { params, expectedUrl, response }) => {
const {
data,
config: { params: reqParams, url },
} = responseObj;
expect(data).toEqual(response);
expect(reqParams).toEqual(params);
expect(url).toEqual(expectedUrl);
};
describe('cycleAnalyticsTasksByType', () => { describe('cycleAnalyticsTasksByType', () => {
it('fetches tasks by type data', done => { it('fetches tasks by type data', done => {
...@@ -330,5 +341,101 @@ describe('Api', () => { ...@@ -330,5 +341,101 @@ describe('Api', () => {
.catch(done.fail); .catch(done.fail);
}); });
}); });
describe('cycleAnalyticsSummaryData', () => {
it('fetches cycle analytics summary, stage stats and permissions data', done => {
const response = { summary: [], stats: [], permissions: {} };
const params = {
'cycle_analytics[created_after]': createdAfter,
'cycle_analytics[created_before]': createdBefore,
};
const expectedUrl = `${dummyUrlRoot}/groups/${groupId}/-/cycle_analytics`;
mock.onGet(expectedUrl).reply(200, response);
Api.cycleAnalyticsSummaryData(groupId, params)
.then(responseObj =>
expectRequestWithCorrectParameters(responseObj, {
response,
params,
expectedUrl,
}),
)
.then(done)
.catch(done.fail);
});
});
describe('cycleAnalyticsGroupStagesAndEvents', () => {
it('fetches custom stage events and all stages', done => {
const response = { events: [], stages: [] };
const params = {
group_id: groupId,
'cycle_analytics[created_after]': createdAfter,
'cycle_analytics[created_before]': createdBefore,
};
const expectedUrl = `${dummyUrlRoot}/-/analytics/cycle_analytics/stages`;
mock.onGet(expectedUrl).reply(200, response);
Api.cycleAnalyticsGroupStagesAndEvents(groupId, params)
.then(responseObj =>
expectRequestWithCorrectParameters(responseObj, {
response,
params,
expectedUrl,
}),
)
.then(done)
.catch(done.fail);
});
});
describe('cycleAnalyticsStageEvents', () => {
it('fetches stage events', done => {
const response = { events: [] };
const params = {
'cycle_analytics[group_id]': groupId,
'cycle_analytics[created_after]': createdAfter,
'cycle_analytics[created_before]': createdBefore,
};
const expectedUrl = `${dummyUrlRoot}/groups/${groupId}/-/cycle_analytics/events/${stageId}.json`;
mock.onGet(expectedUrl).reply(200, response);
Api.cycleAnalyticsStageEvents(groupId, stageId, params)
.then(responseObj =>
expectRequestWithCorrectParameters(responseObj, {
response,
params,
expectedUrl,
}),
)
.then(done)
.catch(done.fail);
});
});
describe('cycleAnalyticsCreateStage', () => {
it('submit the custom stage data', done => {
const response = {};
const customStage = {
name: 'cool-stage',
start_event_identifier: 'issue_created',
start_event_label_id: null,
end_event_identifier: 'issue_closed',
end_event_label_id: null,
};
const expectedUrl = `${dummyUrlRoot}/-/analytics/cycle_analytics/stages`;
mock.onPost(expectedUrl).reply(200, response);
Api.cycleAnalyticsCreateStage(groupId, customStage)
.then(({ data, config: { params: reqParams, data: reqData, url } }) => {
expect(data).toEqual(response);
expect(reqParams).toEqual({ group_id: groupId });
expect(JSON.parse(reqData)).toMatchObject(customStage);
expect(url).toEqual(expectedUrl);
})
.then(done)
.catch(done.fail);
});
});
}); });
}); });
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