Commit 9c39998a authored by Ezekiel Kigbo's avatar Ezekiel Kigbo Committed by Kushal Pandya

Replace summary table with recent activity card

Encapsulates the code to display recent activity
in a separate component. Removes the need to
store the activity data in the vuex store

Render recent activity using a shared
metrics component
parent 46264342
...@@ -10,11 +10,11 @@ import Scatterplot from '../../shared/components/scatterplot.vue'; ...@@ -10,11 +10,11 @@ import Scatterplot from '../../shared/components/scatterplot.vue';
import { LAST_ACTIVITY_AT, dateFormats, DATE_RANGE_LIMIT } from '../../shared/constants'; import { LAST_ACTIVITY_AT, dateFormats, DATE_RANGE_LIMIT } from '../../shared/constants';
import DateRange from '../../shared/components/daterange.vue'; import DateRange from '../../shared/components/daterange.vue';
import StageDropdownFilter from './stage_dropdown_filter.vue'; import StageDropdownFilter from './stage_dropdown_filter.vue';
import SummaryTable from './summary_table.vue';
import StageTable from './stage_table.vue'; import StageTable from './stage_table.vue';
import TasksByTypeChart from './tasks_by_type_chart.vue'; import TasksByTypeChart from './tasks_by_type_chart.vue';
import UrlSyncMixin from '../../shared/mixins/url_sync_mixin'; import UrlSyncMixin from '../../shared/mixins/url_sync_mixin';
import { toYmd } from '../../shared/utils'; import { toYmd } from '../../shared/utils';
import RecentActivityCard from './recent_activity_card.vue';
export default { export default {
name: 'CycleAnalytics', name: 'CycleAnalytics',
...@@ -24,11 +24,11 @@ export default { ...@@ -24,11 +24,11 @@ export default {
GlEmptyState, GlEmptyState,
GroupsDropdownFilter, GroupsDropdownFilter,
ProjectsDropdownFilter, ProjectsDropdownFilter,
SummaryTable,
StageTable, StageTable,
StageDropdownFilter, StageDropdownFilter,
Scatterplot, Scatterplot,
TasksByTypeChart, TasksByTypeChart,
RecentActivityCard,
}, },
mixins: [glFeatureFlagsMixin(), UrlSyncMixin], mixins: [glFeatureFlagsMixin(), UrlSyncMixin],
props: { props: {
...@@ -84,6 +84,7 @@ export default { ...@@ -84,6 +84,7 @@ export default {
'activeStages', 'activeStages',
'selectedProjectIds', 'selectedProjectIds',
'enableCustomOrdering', 'enableCustomOrdering',
'cycleAnalyticsRequestParams',
]), ]),
shouldRenderEmptyState() { shouldRenderEmptyState() {
return !this.selectedGroup; return !this.selectedGroup;
...@@ -281,11 +282,16 @@ export default { ...@@ -281,11 +282,16 @@ export default {
" "
/> />
<div v-else-if="!errorCode"> <div v-else-if="!errorCode">
<div class="js-recent-activity mt-3">
<recent-activity-card
:group-path="currentGroupPath"
:additional-params="cycleAnalyticsRequestParams"
/>
</div>
<div v-if="isLoading"> <div v-if="isLoading">
<gl-loading-icon class="mt-4" size="md" /> <gl-loading-icon class="mt-4" size="md" />
</div> </div>
<div v-else> <div v-else>
<summary-table class="js-summary-table" :items="summary" />
<stage-table <stage-table
v-if="selectedStage" v-if="selectedStage"
:key="stageCount" :key="stageCount"
......
<script>
import Api from 'ee/api';
import { __ } from '~/locale';
import createFlash from '~/flash';
import { slugify } from '~/lib/utils/text_utility';
import MetricCard from '../../shared/components/metric_card.vue';
import { removeFlash } from '../utils';
export default {
name: 'RecentActivityCard',
components: {
MetricCard,
},
props: {
groupPath: {
type: String,
required: true,
},
additionalParams: {
type: Object,
required: false,
default: null,
},
},
data() {
return {
data: [],
loading: false,
};
},
watch: {
additionalParams() {
this.fetchData();
},
},
mounted() {
this.fetchData();
},
methods: {
fetchData() {
removeFlash();
this.loading = true;
return Api.cycleAnalyticsSummaryData(
this.groupPath,
this.additionalParams ? this.additionalParams : {},
)
.then(({ data }) => {
this.data = data.map(({ title: label, value }) => ({
value: value || '-',
label,
key: slugify(label),
}));
})
.catch(() => {
createFlash(
__('There was an error while fetching value stream analytics recent activity data.'),
);
})
.finally(() => {
this.loading = false;
});
},
},
};
</script>
<template>
<metric-card :title="__('Recent Activity')" :metrics="data" :is-loading="loading" />
</template>
<script>
export default {
name: 'SummaryTable',
props: {
items: {
type: Array,
required: true,
},
},
};
</script>
<template>
<div class="wrapper mt-3">
<div class="card">
<div class="card-header font-weight-bold">{{ __('Recent Activity') }}</div>
<div class="content-block">
<div class="container-fluid">
<div class="row">
<div class="col-sm-3"></div>
<div
v-for="{ title, value } in items"
:key="title"
class="col-sm-3 col-12 column text-center"
>
<h3 class="header">{{ value }}</h3>
<p class="text">{{ title }}</p>
</div>
<div class="col-sm-3"></div>
</div>
</div>
</div>
</div>
</div>
</template>
...@@ -133,7 +133,6 @@ export const fetchCycleAnalyticsData = ({ dispatch }) => { ...@@ -133,7 +133,6 @@ export const fetchCycleAnalyticsData = ({ dispatch }) => {
return Promise.resolve() return Promise.resolve()
.then(() => dispatch('fetchGroupStagesAndEvents')) .then(() => dispatch('fetchGroupStagesAndEvents'))
.then(() => dispatch('fetchStageMedianValues')) .then(() => dispatch('fetchStageMedianValues'))
.then(() => dispatch('fetchSummaryData'))
.then(() => dispatch('receiveCycleAnalyticsDataSuccess')) .then(() => dispatch('receiveCycleAnalyticsDataSuccess'))
.catch(error => dispatch('receiveCycleAnalyticsDataError', error)); .catch(error => dispatch('receiveCycleAnalyticsDataError', error));
}; };
...@@ -170,37 +169,6 @@ export const showEditCustomStageForm = ({ commit, dispatch }, selectedStage = {} ...@@ -170,37 +169,6 @@ export const showEditCustomStageForm = ({ commit, dispatch }, selectedStage = {}
removeFlash(); removeFlash();
}; };
export const requestSummaryData = ({ commit }) => commit(types.REQUEST_SUMMARY_DATA);
export const receiveSummaryDataError = ({ commit }, error) => {
commit(types.RECEIVE_SUMMARY_DATA_ERROR, error);
createFlash(__('There was an error while fetching value stream analytics summary data.'));
};
export const receiveSummaryDataSuccess = ({ commit }, data) =>
commit(types.RECEIVE_SUMMARY_DATA_SUCCESS, data);
export const fetchSummaryData = ({ state, dispatch, getters }) => {
const {
cycleAnalyticsRequestParams: { created_after, created_before, project_ids },
} = getters;
dispatch('requestSummaryData');
const {
selectedGroup: { fullPath },
} = state;
return Api.cycleAnalyticsSummaryData(fullPath, {
created_after,
created_before,
project_ids,
})
.then(({ data }) => dispatch('receiveSummaryDataSuccess', data))
.catch(error =>
handleErrorOrRethrow({ error, action: () => dispatch('receiveSummaryDataError', error) }),
);
};
export const requestGroupStagesAndEvents = ({ commit }) => export const requestGroupStagesAndEvents = ({ commit }) =>
commit(types.REQUEST_GROUP_STAGES_AND_EVENTS); commit(types.REQUEST_GROUP_STAGES_AND_EVENTS);
...@@ -294,7 +262,6 @@ export const receiveCreateCustomStageSuccess = ({ commit, dispatch }, { data: { ...@@ -294,7 +262,6 @@ export const receiveCreateCustomStageSuccess = ({ commit, dispatch }, { data: {
return Promise.resolve() return Promise.resolve()
.then(() => dispatch('fetchGroupStagesAndEvents')) .then(() => dispatch('fetchGroupStagesAndEvents'))
.then(() => dispatch('fetchSummaryData'))
.catch(() => { .catch(() => {
createFlash(__('There was a problem refreshing the data, please try again')); createFlash(__('There was a problem refreshing the data, please try again'));
}); });
......
...@@ -28,10 +28,6 @@ export const REQUEST_TOP_RANKED_GROUP_LABELS = 'REQUEST_TOP_RANKED_GROUP_LABELS' ...@@ -28,10 +28,6 @@ export const REQUEST_TOP_RANKED_GROUP_LABELS = 'REQUEST_TOP_RANKED_GROUP_LABELS'
export const RECEIVE_TOP_RANKED_GROUP_LABELS_SUCCESS = 'RECEIVE_TOP_RANKED_GROUP_LABELS_SUCCESS'; export const RECEIVE_TOP_RANKED_GROUP_LABELS_SUCCESS = 'RECEIVE_TOP_RANKED_GROUP_LABELS_SUCCESS';
export const RECEIVE_TOP_RANKED_GROUP_LABELS_ERROR = 'RECEIVE_TOP_RANKED_GROUP_LABELS_ERROR'; export const RECEIVE_TOP_RANKED_GROUP_LABELS_ERROR = 'RECEIVE_TOP_RANKED_GROUP_LABELS_ERROR';
export const REQUEST_SUMMARY_DATA = 'REQUEST_SUMMARY_DATA';
export const RECEIVE_SUMMARY_DATA_SUCCESS = 'RECEIVE_SUMMARY_DATA_SUCCESS';
export const RECEIVE_SUMMARY_DATA_ERROR = 'RECEIVE_SUMMARY_DATA_ERROR';
export const REQUEST_GROUP_STAGES_AND_EVENTS = 'REQUEST_GROUP_STAGES_AND_EVENTS'; export const REQUEST_GROUP_STAGES_AND_EVENTS = 'REQUEST_GROUP_STAGES_AND_EVENTS';
export const RECEIVE_GROUP_STAGES_AND_EVENTS_SUCCESS = 'RECEIVE_GROUP_STAGES_AND_EVENTS_SUCCESS'; export const RECEIVE_GROUP_STAGES_AND_EVENTS_SUCCESS = 'RECEIVE_GROUP_STAGES_AND_EVENTS_SUCCESS';
export const RECEIVE_GROUP_STAGES_AND_EVENTS_ERROR = 'RECEIVE_GROUP_STAGES_AND_EVENTS_ERROR'; export const RECEIVE_GROUP_STAGES_AND_EVENTS_ERROR = 'RECEIVE_GROUP_STAGES_AND_EVENTS_ERROR';
......
...@@ -115,18 +115,6 @@ export default { ...@@ -115,18 +115,6 @@ export default {
[types.CLEAR_CUSTOM_STAGE_FORM_ERRORS](state) { [types.CLEAR_CUSTOM_STAGE_FORM_ERRORS](state) {
state.customStageFormErrors = null; state.customStageFormErrors = null;
}, },
[types.RECEIVE_SUMMARY_DATA_ERROR](state) {
state.summary = [];
},
[types.REQUEST_SUMMARY_DATA](state) {
state.summary = [];
},
[types.RECEIVE_SUMMARY_DATA_SUCCESS](state, data) {
state.summary = data.map(item => ({
...item,
value: item.value || '-',
}));
},
[types.REQUEST_GROUP_STAGES_AND_EVENTS](state) { [types.REQUEST_GROUP_STAGES_AND_EVENTS](state) {
state.stages = []; state.stages = [];
state.customStageFormEvents = []; state.customStageFormEvents = [];
......
...@@ -37,7 +37,7 @@ export default { ...@@ -37,7 +37,7 @@ export default {
v-for="metric in metrics" v-for="metric in metrics"
:key="metric.key" :key="metric.key"
ref="metricItem" ref="metricItem"
class="flex-grow text-center" class="js-metric-card-item flex-grow text-center"
> >
<h3 class="my-2"> <h3 class="my-2">
<template v-if="metric.value === null" <template v-if="metric.value === null"
......
...@@ -189,7 +189,7 @@ describe 'Group Value Stream Analytics', :js do ...@@ -189,7 +189,7 @@ describe 'Group Value Stream Analytics', :js do
shared_examples 'group value stream analytics' do shared_examples 'group value stream analytics' do
context 'summary table', :js do context 'summary table', :js do
it 'will display recent activity' do it 'will display recent activity' do
page.within(find('.js-summary-table')) do page.within(find('.js-recent-activity')) do
expect(page).to have_selector('.card-header') expect(page).to have_selector('.card-header')
expect(page).to have_content('Recent Activity') expect(page).to have_content('Recent Activity')
end end
...@@ -221,23 +221,27 @@ describe 'Group Value Stream Analytics', :js do ...@@ -221,23 +221,27 @@ describe 'Group Value Stream Analytics', :js do
end end
context 'with a group selected' do context 'with a group selected' do
card_metric_selector = ".js-recent-activity .js-metric-card-item"
before do before do
select_group select_group
expect(page).to have_css(card_metric_selector)
end end
it_behaves_like 'group value stream analytics' it_behaves_like 'group value stream analytics'
it 'displays the number of issues' do it 'displays the number of issues' do
expect(page).to have_content('New Issues') issue_count = page.all(card_metric_selector).first
issue_count = find(".card .header", match: :first) expect(issue_count).to have_content('New Issues')
expect(issue_count).to have_content('3') expect(issue_count).to have_content('3')
end end
it 'displays the number of deploys' do it 'displays the number of deploys' do
expect(page).to have_content('Deploys') deploys_count = page.all(card_metric_selector).last
deploys_count = page.all(".card .header").last expect(deploys_count).to have_content('Deploys')
expect(deploys_count).to have_content('-') expect(deploys_count).to have_content('-')
end end
end end
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`RecentActivityCard matches the snapshot 1`] = `
<div
class="card"
>
<!---->
<div
class="card-header"
>
<strong>
Recent Activity
</strong>
</div>
<div
class="card-body"
>
<!---->
<!---->
<div
class="d-flex"
>
<div
class="js-metric-card-item flex-grow text-center"
>
<h3
class="my-2"
>
3
</h3>
<p
class="text-secondary gl-font-size-small mb-2"
>
New Issues
</p>
</div>
<div
class="js-metric-card-item flex-grow text-center"
>
<h3
class="my-2"
>
-
</h3>
<p
class="text-secondary gl-font-size-small mb-2"
>
Deploys
</p>
</div>
</div>
</div>
<!---->
<!---->
</div>
`;
...@@ -8,7 +8,7 @@ import axios from 'axios'; ...@@ -8,7 +8,7 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import GroupsDropdownFilter from 'ee/analytics/shared/components/groups_dropdown_filter.vue'; import GroupsDropdownFilter from 'ee/analytics/shared/components/groups_dropdown_filter.vue';
import ProjectsDropdownFilter from 'ee/analytics/shared/components/projects_dropdown_filter.vue'; import ProjectsDropdownFilter from 'ee/analytics/shared/components/projects_dropdown_filter.vue';
import SummaryTable from 'ee/analytics/cycle_analytics/components/summary_table.vue'; import RecentActivityCard from 'ee/analytics/cycle_analytics/components/recent_activity_card.vue';
import StageTable from 'ee/analytics/cycle_analytics/components/stage_table.vue'; import StageTable from 'ee/analytics/cycle_analytics/components/stage_table.vue';
import 'bootstrap'; import 'bootstrap';
import '~/gl_dropdown'; import '~/gl_dropdown';
...@@ -34,7 +34,7 @@ const localVue = createLocalVue(); ...@@ -34,7 +34,7 @@ const localVue = createLocalVue();
localVue.use(Vuex); localVue.use(Vuex);
const defaultStubs = { const defaultStubs = {
'summary-table': true, 'recent-activity-card': true,
'stage-event-list': true, 'stage-event-list': true,
'stage-nav-item': true, 'stage-nav-item': true,
'tasks-by-type-chart': true, 'tasks-by-type-chart': true,
...@@ -119,8 +119,8 @@ describe('Cycle Analytics component', () => { ...@@ -119,8 +119,8 @@ describe('Cycle Analytics component', () => {
expect(wrapper.find(Daterange).exists()).toBe(flag); expect(wrapper.find(Daterange).exists()).toBe(flag);
}; };
const displaysSummaryTable = flag => { const displaysRecentActivityCard = flag => {
expect(wrapper.find(SummaryTable).exists()).toBe(flag); expect(wrapper.find(RecentActivityCard).exists()).toBe(flag);
}; };
const displaysStageTable = flag => { const displaysStageTable = flag => {
...@@ -176,7 +176,7 @@ describe('Cycle Analytics component', () => { ...@@ -176,7 +176,7 @@ describe('Cycle Analytics component', () => {
}); });
it('does not display the summary table', () => { it('does not display the summary table', () => {
displaysSummaryTable(false); displaysRecentActivityCard(false);
}); });
it('does not display the stage table', () => { it('does not display the stage table', () => {
...@@ -230,7 +230,7 @@ describe('Cycle Analytics component', () => { ...@@ -230,7 +230,7 @@ describe('Cycle Analytics component', () => {
}); });
it('displays the summary table', () => { it('displays the summary table', () => {
displaysSummaryTable(true); displaysRecentActivityCard(true);
}); });
it('displays the stage table', () => { it('displays the stage table', () => {
...@@ -341,7 +341,7 @@ describe('Cycle Analytics component', () => { ...@@ -341,7 +341,7 @@ describe('Cycle Analytics component', () => {
}); });
it('does not display the summary table', () => { it('does not display the summary table', () => {
displaysSummaryTable(false); displaysRecentActivityCard(false);
}); });
it('does not display the stage table', () => { it('does not display the stage table', () => {
...@@ -435,11 +435,6 @@ describe('Cycle Analytics component', () => { ...@@ -435,11 +435,6 @@ describe('Cycle Analytics component', () => {
}) => { }) => {
const defaultStatus = 200; const defaultStatus = 200;
const defaultRequests = { const defaultRequests = {
fetchSummaryData: {
status: defaultStatus,
endpoint: mockData.endpoints.summaryData,
response: [...mockData.summaryData],
},
fetchGroupStagesAndEvents: { fetchGroupStagesAndEvents: {
status: defaultStatus, status: defaultStatus,
endpoint: mockData.endpoints.baseStagesEndpoint, endpoint: mockData.endpoints.baseStagesEndpoint,
...@@ -500,24 +495,6 @@ describe('Cycle Analytics component', () => { ...@@ -500,24 +495,6 @@ describe('Cycle Analytics component', () => {
}); });
}; };
it('will display an error if the fetchSummaryData request fails', () => {
expect(findFlashError()).toBeNull();
mockRequestCycleAnalyticsData({
overrides: {
fetchSummaryData: {
status: httpStatusCodes.NOT_FOUND,
endpoint: mockData.endpoints.summaryData,
response: { response: { status: httpStatusCodes.NOT_FOUND } },
},
},
});
return selectGroupAndFindError(
'There was an error while fetching value stream analytics summary data.',
);
});
it('will display an error if the fetchGroupStagesAndEvents request fails', () => { it('will display an error if the fetchGroupStagesAndEvents request fails', () => {
expect(findFlashError()).toBeNull(); expect(findFlashError()).toBeNull();
......
import { mount } from '@vue/test-utils';
import createFlash from '~/flash';
import RecentActivityCard from 'ee/analytics/cycle_analytics/components/recent_activity_card.vue';
import { group, recentActivityData } from '../mock_data';
import Api from 'ee/api';
jest.mock('~/flash');
describe('RecentActivityCard', () => {
const { full_path: groupPath } = group;
let wrapper;
const createComponent = (additionalParams = {}) => {
return mount(RecentActivityCard, {
propsData: {
groupPath,
additionalParams,
},
});
};
beforeEach(() => {
jest.spyOn(Api, 'cycleAnalyticsSummaryData').mockResolvedValue({ data: recentActivityData });
wrapper = createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
it('fetches the recent activity data', () => {
expect(Api.cycleAnalyticsSummaryData).toHaveBeenCalledWith(groupPath, {});
});
describe('with a failing request', () => {
beforeEach(() => {
jest.spyOn(Api, 'cycleAnalyticsSummaryData').mockRejectedValue();
wrapper = createComponent();
});
it('should render an error message', () => {
expect(createFlash).toHaveBeenCalledWith(
'There was an error while fetching value stream analytics recent activity data.',
);
});
});
describe('with additional params', () => {
beforeEach(() => {
wrapper = createComponent({
'project_ids[]': [1],
created_after: '2020-01-01',
created_before: '2020-02-01',
});
});
it('sends additional parameters as query paremeters', () => {
expect(Api.cycleAnalyticsSummaryData).toHaveBeenCalledWith(groupPath, {
'project_ids[]': [1],
created_after: '2020-01-01',
created_before: '2020-02-01',
});
});
});
});
...@@ -13,13 +13,13 @@ const fixtureEndpoints = { ...@@ -13,13 +13,13 @@ const fixtureEndpoints = {
customizableCycleAnalyticsStagesAndEvents: 'analytics/value_stream_analytics/stages.json', // customizable stages and events endpoint customizableCycleAnalyticsStagesAndEvents: 'analytics/value_stream_analytics/stages.json', // customizable stages and events endpoint
stageEvents: stage => `analytics/value_stream_analytics/stages/${stage}/records.json`, stageEvents: stage => `analytics/value_stream_analytics/stages/${stage}/records.json`,
stageMedian: stage => `analytics/value_stream_analytics/stages/${stage}/median.json`, stageMedian: stage => `analytics/value_stream_analytics/stages/${stage}/median.json`,
summaryData: 'analytics/value_stream_analytics/summary.json', recentActivityData: 'analytics/value_stream_analytics/summary.json',
groupLabels: 'api/group_labels.json', groupLabels: 'api/group_labels.json',
}; };
export const endpoints = { export const endpoints = {
groupLabels: /groups\/[A-Z|a-z|\d|\-|_]+\/-\/labels.json/, groupLabels: /groups\/[A-Z|a-z|\d|\-|_]+\/-\/labels.json/,
summaryData: /analytics\/value_stream_analytics\/summary/, recentActivityData: /analytics\/value_stream_analytics\/summary/,
durationData: /analytics\/value_stream_analytics\/stages\/\d+\/duration_chart/, durationData: /analytics\/value_stream_analytics\/stages\/\d+\/duration_chart/,
stageData: /analytics\/value_stream_analytics\/stages\/\d+\/records/, stageData: /analytics\/value_stream_analytics\/stages\/\d+\/records/,
stageMedian: /analytics\/value_stream_analytics\/stages\/\d+\/median/, stageMedian: /analytics\/value_stream_analytics\/stages\/\d+\/median/,
...@@ -43,7 +43,7 @@ export const group = { ...@@ -43,7 +43,7 @@ export const group = {
const getStageByTitle = (stages, title) => const getStageByTitle = (stages, title) =>
stages.find(stage => stage.title && stage.title.toLowerCase().trim() === title) || {}; stages.find(stage => stage.title && stage.title.toLowerCase().trim() === title) || {};
export const summaryData = getJSONFixture(fixtureEndpoints.summaryData); export const recentActivityData = getJSONFixture(fixtureEndpoints.recentActivityData);
export const customizableStagesAndEvents = getJSONFixture( export const customizableStagesAndEvents = getJSONFixture(
fixtureEndpoints.customizableCycleAnalyticsStagesAndEvents, fixtureEndpoints.customizableCycleAnalyticsStagesAndEvents,
......
...@@ -12,7 +12,6 @@ import createFlash from '~/flash'; ...@@ -12,7 +12,6 @@ import createFlash from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status'; import httpStatusCodes from '~/lib/utils/http_status';
import { import {
group, group,
summaryData,
allowedStages as stages, allowedStages as stages,
groupLabels, groupLabels,
startDate, startDate,
...@@ -275,7 +274,6 @@ describe('Cycle analytics actions', () => { ...@@ -275,7 +274,6 @@ describe('Cycle analytics actions', () => {
fetchStageMedianValues: overrides.fetchStageMedianValues || jest.fn().mockResolvedValue(), fetchStageMedianValues: overrides.fetchStageMedianValues || jest.fn().mockResolvedValue(),
fetchGroupStagesAndEvents: fetchGroupStagesAndEvents:
overrides.fetchGroupStagesAndEvents || jest.fn().mockResolvedValue(), overrides.fetchGroupStagesAndEvents || jest.fn().mockResolvedValue(),
fetchSummaryData: overrides.fetchSummaryData || jest.fn().mockResolvedValue(),
receiveCycleAnalyticsDataSuccess: receiveCycleAnalyticsDataSuccess:
overrides.receiveCycleAnalyticsDataSuccess || jest.fn().mockResolvedValue(), overrides.receiveCycleAnalyticsDataSuccess || jest.fn().mockResolvedValue(),
}; };
...@@ -286,14 +284,12 @@ describe('Cycle analytics actions', () => { ...@@ -286,14 +284,12 @@ describe('Cycle analytics actions', () => {
.mockImplementationOnce(mocks.requestCycleAnalyticsData) .mockImplementationOnce(mocks.requestCycleAnalyticsData)
.mockImplementationOnce(mocks.fetchGroupStagesAndEvents) .mockImplementationOnce(mocks.fetchGroupStagesAndEvents)
.mockImplementationOnce(mocks.fetchStageMedianValues) .mockImplementationOnce(mocks.fetchStageMedianValues)
.mockImplementationOnce(mocks.fetchSummaryData)
.mockImplementationOnce(mocks.receiveCycleAnalyticsDataSuccess), .mockImplementationOnce(mocks.receiveCycleAnalyticsDataSuccess),
}; };
} }
beforeEach(() => { beforeEach(() => {
setFixtures('<div class="flash-container"></div>'); setFixtures('<div class="flash-container"></div>');
mock.onGet(endpoints.summaryData).replyOnce(200, summaryData);
state = { ...state, selectedGroup, startDate, endDate }; state = { ...state, selectedGroup, startDate, endDate };
}); });
...@@ -307,7 +303,6 @@ describe('Cycle analytics actions', () => { ...@@ -307,7 +303,6 @@ describe('Cycle analytics actions', () => {
{ type: 'requestCycleAnalyticsData' }, { type: 'requestCycleAnalyticsData' },
{ type: 'fetchGroupStagesAndEvents' }, { type: 'fetchGroupStagesAndEvents' },
{ type: 'fetchStageMedianValues' }, { type: 'fetchStageMedianValues' },
{ type: 'fetchSummaryData' },
{ type: 'receiveCycleAnalyticsDataSuccess' }, { type: 'receiveCycleAnalyticsDataSuccess' },
], ],
done, done,
...@@ -340,34 +335,6 @@ describe('Cycle analytics actions', () => { ...@@ -340,34 +335,6 @@ describe('Cycle analytics actions', () => {
.catch(done.fail); .catch(done.fail);
}); });
it(`displays an error if fetchSummaryData fails`, done => {
const { mockDispatchContext } = mockFetchCycleAnalyticsAction({
fetchSummaryData: actions.fetchSummaryData({
dispatch: jest
.fn()
.mockResolvedValueOnce()
.mockImplementation(actions.receiveSummaryDataError({ commit: () => {} })),
commit: () => {},
state: { ...state },
getters,
}),
});
actions
.fetchCycleAnalyticsData({
dispatch: mockDispatchContext,
state: {},
commit: () => {},
})
.then(() => {
shouldFlashAMessage(
'There was an error while fetching value stream analytics summary data.',
);
done();
})
.catch(done.fail);
});
it(`displays an error if fetchGroupStagesAndEvents fails`, done => { it(`displays an error if fetchGroupStagesAndEvents fails`, done => {
const { mockDispatchContext } = mockFetchCycleAnalyticsAction({ const { mockDispatchContext } = mockFetchCycleAnalyticsAction({
fetchGroupStagesAndEvents: actions.fetchGroupStagesAndEvents({ fetchGroupStagesAndEvents: actions.fetchGroupStagesAndEvents({
...@@ -684,7 +651,7 @@ describe('Cycle analytics actions', () => { ...@@ -684,7 +651,7 @@ describe('Cycle analytics actions', () => {
title: 'NEW - COOL', title: 'NEW - COOL',
}; };
it('will dispatch fetchGroupStagesAndEvents and fetchSummaryData', () => it('will dispatch fetchGroupStagesAndEvents', () =>
testAction( testAction(
actions.receiveUpdateStageSuccess, actions.receiveUpdateStageSuccess,
response, response,
...@@ -1502,13 +1469,13 @@ describe('Cycle analytics actions', () => { ...@@ -1502,13 +1469,13 @@ describe('Cycle analytics actions', () => {
}, },
}; };
it('will dispatch fetchGroupStagesAndEvents and fetchSummaryData', () => it('will dispatch fetchGroupStagesAndEvents', () =>
testAction( testAction(
actions.receiveCreateCustomStageSuccess, actions.receiveCreateCustomStageSuccess,
response, response,
state, state,
[{ type: types.RECEIVE_CREATE_CUSTOM_STAGE_SUCCESS }], [{ type: types.RECEIVE_CREATE_CUSTOM_STAGE_SUCCESS }],
[{ type: 'fetchGroupStagesAndEvents' }, { type: 'fetchSummaryData' }], [{ type: 'fetchGroupStagesAndEvents' }],
)); ));
describe('with an error', () => { describe('with an error', () => {
......
...@@ -4,7 +4,6 @@ import { TASKS_BY_TYPE_FILTERS } from 'ee/analytics/cycle_analytics/constants'; ...@@ -4,7 +4,6 @@ import { TASKS_BY_TYPE_FILTERS } from 'ee/analytics/cycle_analytics/constants';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { import {
summaryData,
rawIssueEvents, rawIssueEvents,
issueEvents as transformedEvents, issueEvents as transformedEvents,
issueStage, issueStage,
...@@ -52,8 +51,6 @@ describe('Cycle analytics mutations', () => { ...@@ -52,8 +51,6 @@ describe('Cycle analytics mutations', () => {
${types.REQUEST_CYCLE_ANALYTICS_DATA} | ${'isLoading'} | ${true} ${types.REQUEST_CYCLE_ANALYTICS_DATA} | ${'isLoading'} | ${true}
${types.REQUEST_TOP_RANKED_GROUP_LABELS} | ${'topRankedLabels'} | ${[]} ${types.REQUEST_TOP_RANKED_GROUP_LABELS} | ${'topRankedLabels'} | ${[]}
${types.RECEIVE_TOP_RANKED_GROUP_LABELS_ERROR} | ${'topRankedLabels'} | ${[]} ${types.RECEIVE_TOP_RANKED_GROUP_LABELS_ERROR} | ${'topRankedLabels'} | ${[]}
${types.RECEIVE_SUMMARY_DATA_ERROR} | ${'summary'} | ${[]}
${types.REQUEST_SUMMARY_DATA} | ${'summary'} | ${[]}
${types.RECEIVE_GROUP_STAGES_AND_EVENTS_ERROR} | ${'stages'} | ${[]} ${types.RECEIVE_GROUP_STAGES_AND_EVENTS_ERROR} | ${'stages'} | ${[]}
${types.REQUEST_GROUP_STAGES_AND_EVENTS} | ${'stages'} | ${[]} ${types.REQUEST_GROUP_STAGES_AND_EVENTS} | ${'stages'} | ${[]}
${types.RECEIVE_GROUP_STAGES_AND_EVENTS_ERROR} | ${'customStageFormEvents'} | ${[]} ${types.RECEIVE_GROUP_STAGES_AND_EVENTS_ERROR} | ${'customStageFormEvents'} | ${[]}
...@@ -149,7 +146,6 @@ describe('Cycle analytics mutations', () => { ...@@ -149,7 +146,6 @@ describe('Cycle analytics mutations', () => {
it('will set isLoading=false and errorCode=null', () => { it('will set isLoading=false and errorCode=null', () => {
mutations[types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS](state, { mutations[types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS](state, {
stats: [], stats: [],
summary: [],
stages: [], stages: [],
}); });
...@@ -175,20 +171,6 @@ describe('Cycle analytics mutations', () => { ...@@ -175,20 +171,6 @@ describe('Cycle analytics mutations', () => {
}); });
}); });
describe(`${types.RECEIVE_SUMMARY_DATA_SUCCESS}`, () => {
beforeEach(() => {
state = { stages: [{ slug: 'plan' }, { slug: 'issue' }, { slug: 'test' }] };
mutations[types.RECEIVE_SUMMARY_DATA_SUCCESS](state, summaryData);
});
it('will set each summary item with a value of 0 to "-"', () => {
expect(state.summary).toEqual([
{ value: 3, title: 'New Issues' },
{ value: '-', title: 'Deploys' },
]);
});
});
describe(`${types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR}`, () => { describe(`${types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR}`, () => {
it('sets errorCode correctly', () => { it('sets errorCode correctly', () => {
const errorCode = 403; const errorCode = 403;
......
...@@ -22,7 +22,7 @@ exports[`GroupActivity component matches the snapshot 1`] = ` ...@@ -22,7 +22,7 @@ exports[`GroupActivity component matches the snapshot 1`] = `
class="d-flex" class="d-flex"
> >
<div <div
class="flex-grow text-center" class="js-metric-card-item flex-grow text-center"
> >
<h3 <h3
class="my-2" class="my-2"
...@@ -37,7 +37,7 @@ exports[`GroupActivity component matches the snapshot 1`] = ` ...@@ -37,7 +37,7 @@ exports[`GroupActivity component matches the snapshot 1`] = `
</p> </p>
</div> </div>
<div <div
class="flex-grow text-center" class="js-metric-card-item flex-grow text-center"
> >
<h3 <h3
class="my-2" class="my-2"
...@@ -52,7 +52,7 @@ exports[`GroupActivity component matches the snapshot 1`] = ` ...@@ -52,7 +52,7 @@ exports[`GroupActivity component matches the snapshot 1`] = `
</p> </p>
</div> </div>
<div <div
class="flex-grow text-center" class="js-metric-card-item flex-grow text-center"
> >
<h3 <h3
class="my-2" class="my-2"
......
...@@ -20495,7 +20495,7 @@ msgstr "" ...@@ -20495,7 +20495,7 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration median data." msgid "There was an error while fetching value stream analytics duration median data."
msgstr "" msgstr ""
msgid "There was an error while fetching value stream analytics summary data." msgid "There was an error while fetching value stream analytics recent activity data."
msgstr "" msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again." msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
......
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