diff --git a/app/assets/javascripts/analytics/cycle_analytics/mixins/filter_mixins.js b/app/assets/javascripts/analytics/cycle_analytics/mixins/filter_mixins.js
deleted file mode 100644
index ff8b4c56321a3362fc00224b01800f62466f9a1f..0000000000000000000000000000000000000000
--- a/app/assets/javascripts/analytics/cycle_analytics/mixins/filter_mixins.js
+++ /dev/null
@@ -1 +0,0 @@
-export default {};
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
index f609ca5f22d9330cb43f718eb0a66f6fd5e8d281..4b35b7d360c9a35f8c24a55f3669f0717649077c 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
@@ -2,7 +2,6 @@ import $ from 'jquery';
 import Vue from 'vue';
 import Cookies from 'js-cookie';
 import { GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
-import filterMixins from 'ee_else_ce/analytics/cycle_analytics/mixins/filter_mixins';
 import Flash from '../flash';
 import { __ } from '~/locale';
 import Translate from '../vue_shared/translate';
@@ -45,7 +44,6 @@ export default () => {
         import('ee_component/analytics/shared/components/date_range_dropdown.vue'),
       'stage-nav-item': stageNavItem,
     },
-    mixins: [filterMixins],
     data() {
       return {
         store: CycleAnalyticsStore,
diff --git a/ee/app/assets/javascripts/analytics/cycle_analytics/components/base.vue b/ee/app/assets/javascripts/analytics/cycle_analytics/components/base.vue
index 4e862c5294645c6796fc091524eaa22500f71cdd..92fe1dadb8891f6abcb6dd7a0a54a9f057c7e2bd 100644
--- a/ee/app/assets/javascripts/analytics/cycle_analytics/components/base.vue
+++ b/ee/app/assets/javascripts/analytics/cycle_analytics/components/base.vue
@@ -2,7 +2,7 @@
 import { GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
 import { mapActions, mapState, mapGetters } from 'vuex';
 import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
-import { PROJECTS_PER_PAGE, STAGE_ACTIONS } from '../constants';
+import { PROJECTS_PER_PAGE } from '../constants';
 import GroupsDropdownFilter from '../../shared/components/groups_dropdown_filter.vue';
 import ProjectsDropdownFilter from '../../shared/components/projects_dropdown_filter.vue';
 import { SIMILARITY_ORDER, LAST_ACTIVITY_AT, DATE_RANGE_LIMIT } from '../../shared/constants';
@@ -12,14 +12,12 @@ import DurationChart from './duration_chart.vue';
 import TypeOfWorkCharts from './type_of_work_charts.vue';
 import UrlSync from '~/vue_shared/components/url_sync.vue';
 import { toYmd } from '../../shared/utils';
-import RecentActivityCard from './recent_activity_card.vue';
-import TimeMetricsCard from './time_metrics_card.vue';
 import StageTableNav from './stage_table_nav.vue';
 import CustomStageForm from './custom_stage_form.vue';
 import PathNavigation from './path_navigation.vue';
-import MetricCard from '../../shared/components/metric_card.vue';
 import FilterBar from './filter_bar.vue';
 import ValueStreamSelect from './value_stream_select.vue';
+import Metrics from './metrics.vue';
 
 export default {
   name: 'CycleAnalytics',
@@ -32,15 +30,13 @@ export default {
     ProjectsDropdownFilter,
     StageTable,
     TypeOfWorkCharts,
-    RecentActivityCard,
-    TimeMetricsCard,
     CustomStageForm,
     StageTableNav,
     PathNavigation,
-    MetricCard,
     FilterBar,
     ValueStreamSelect,
     UrlSync,
+    Metrics,
   },
   props: {
     emptyStateSvgPath: {
@@ -215,7 +211,6 @@ export default {
     min_access_level: featureAccessLevel.EVERYONE,
   },
   maxDateRange: DATE_RANGE_LIMIT,
-  STAGE_ACTIONS,
 };
 </script>
 <template>
@@ -304,23 +299,7 @@ export default {
         "
       />
       <div v-else-if="!errorCode">
-        <div class="js-recent-activity gl-mt-3 gl-display-flex">
-          <div class="gl-flex-fill-1 gl-pr-2">
-            <time-metrics-card
-              #default="{ metrics, loading }"
-              :group-path="currentGroupPath"
-              :additional-params="cycleAnalyticsRequestParams"
-            >
-              <metric-card :title="__('Time')" :metrics="metrics" :is-loading="loading" />
-            </time-metrics-card>
-          </div>
-          <div class="gl-flex-fill-1 gl-pl-2">
-            <recent-activity-card
-              :group-path="currentGroupPath"
-              :additional-params="cycleAnalyticsRequestParams"
-            />
-          </div>
-        </div>
+        <metrics :group-path="currentGroupPath" :request-params="cycleAnalyticsRequestParams" />
         <div v-if="isLoading">
           <gl-loading-icon class="mt-4" size="md" />
         </div>
@@ -356,7 +335,7 @@ export default {
                 :events="formEvents"
                 @createStage="onCreateCustomStage"
                 @updateStage="onUpdateCustomStage"
-                @clearErrors="$emit('clearFormErrors')"
+                @clearErrors="$emit('clear-form-errors')"
               />
             </template>
           </stage-table>
diff --git a/ee/app/assets/javascripts/analytics/cycle_analytics/components/metrics.vue b/ee/app/assets/javascripts/analytics/cycle_analytics/components/metrics.vue
new file mode 100644
index 0000000000000000000000000000000000000000..3cc3b5f03d99c30d63dd703708ec362210d99a17
--- /dev/null
+++ b/ee/app/assets/javascripts/analytics/cycle_analytics/components/metrics.vue
@@ -0,0 +1,48 @@
+<script>
+import { OVERVIEW_METRICS } from '../constants';
+import TimeMetricsCard from './time_metrics_card.vue';
+import MetricCard from '../../shared/components/metric_card.vue';
+
+export default {
+  name: 'OverviewActivity',
+  components: {
+    TimeMetricsCard,
+    MetricCard,
+  },
+  props: {
+    groupPath: {
+      type: String,
+      required: true,
+    },
+    requestParams: {
+      type: Object,
+      required: true,
+    },
+  },
+  overviewMetrics: OVERVIEW_METRICS,
+};
+</script>
+<template>
+  <div class="js-recent-activity gl-mt-3 gl-display-flex">
+    <div class="gl-flex-fill-1 gl-pr-2">
+      <time-metrics-card
+        #default="{ metrics, loading }"
+        :group-path="groupPath"
+        :additional-params="requestParams"
+        :request-type="$options.overviewMetrics.TIME_SUMMARY"
+      >
+        <metric-card :title="__('Time')" :metrics="metrics" :is-loading="loading" />
+      </time-metrics-card>
+    </div>
+    <div class="gl-flex-fill-1 gl-pl-2">
+      <time-metrics-card
+        #default="{ metrics, loading }"
+        :group-path="groupPath"
+        :additional-params="requestParams"
+        :request-type="$options.overviewMetrics.RECENT_ACTIVITY"
+      >
+        <metric-card :title="__('Recent Activity')" :metrics="metrics" :is-loading="loading" />
+      </time-metrics-card>
+    </div>
+  </div>
+</template>
diff --git a/ee/app/assets/javascripts/analytics/cycle_analytics/components/recent_activity_card.vue b/ee/app/assets/javascripts/analytics/cycle_analytics/components/recent_activity_card.vue
deleted file mode 100644
index 95564456f7508f41af56553a3b425148c570d9f2..0000000000000000000000000000000000000000
--- a/ee/app/assets/javascripts/analytics/cycle_analytics/components/recent_activity_card.vue
+++ /dev/null
@@ -1,63 +0,0 @@
-<script>
-import Api from 'ee/api';
-import { __ } from '~/locale';
-import createFlash from '~/flash';
-import MetricCard from '../../shared/components/metric_card.vue';
-import { removeFlash, prepareTimeMetricsData } 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 = prepareTimeMetricsData(data);
-        })
-        .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>
diff --git a/ee/app/assets/javascripts/analytics/cycle_analytics/components/time_metrics_card.vue b/ee/app/assets/javascripts/analytics/cycle_analytics/components/time_metrics_card.vue
index 34895b91baf65cf57ffd02028f9bba6f64c0e28c..f6df5bbd0fedabac9b2f0ad9859191cab2eb55e6 100644
--- a/ee/app/assets/javascripts/analytics/cycle_analytics/components/time_metrics_card.vue
+++ b/ee/app/assets/javascripts/analytics/cycle_analytics/components/time_metrics_card.vue
@@ -1,15 +1,22 @@
 <script>
 import Api from 'ee/api';
-import { __, s__ } from '~/locale';
+import { sprintf, __, s__ } from '~/locale';
 import createFlash from '~/flash';
 import MetricCard from '../../shared/components/metric_card.vue';
 import { removeFlash, prepareTimeMetricsData } from '../utils';
+import { OVERVIEW_METRICS } from '../constants';
 
 const I18N_TEXT = {
   'lead-time': s__('ValueStreamAnalytics|Median time from issue created to issue closed.'),
   'cycle-time': s__('ValueStreamAnalytics|Median time from first commit to issue closed.'),
 };
 
+const requestData = ({ requestType, groupPath, additionalParams }) => {
+  return requestType === OVERVIEW_METRICS.TIME_SUMMARY
+    ? Api.cycleAnalyticsTimeSummaryData(groupPath, additionalParams)
+    : Api.cycleAnalyticsSummaryData(groupPath, additionalParams);
+};
+
 export default {
   name: 'TimeMetricsCard',
   components: {
@@ -25,6 +32,11 @@ export default {
       required: false,
       default: () => ({}),
     },
+    requestType: {
+      type: String,
+      required: true,
+      validator: t => OVERVIEW_METRICS[t],
+    },
   },
   data() {
     return {
@@ -44,13 +56,22 @@ export default {
     fetchData() {
       removeFlash();
       this.loading = true;
-      return Api.cycleAnalyticsTimeSummaryData(this.groupPath, this.additionalParams)
+      return requestData(this)
         .then(({ data }) => {
           this.data = prepareTimeMetricsData(data, I18N_TEXT);
         })
         .catch(() => {
+          const requestTypeName =
+            this.requestType === OVERVIEW_METRICS.TIME_SUMMARY
+              ? __('time summary')
+              : __('recent activity');
           createFlash(
-            __('There was an error while fetching value stream analytics time summary data.'),
+            sprintf(
+              s__(
+                'There was an error while fetching value stream analytics %{requestTypeName} data.',
+              ),
+              { requestTypeName },
+            ),
           );
         })
         .finally(() => {
diff --git a/ee/app/assets/javascripts/analytics/cycle_analytics/constants.js b/ee/app/assets/javascripts/analytics/cycle_analytics/constants.js
index e969462917ac72413f50f53f2f9596d86443a098..eb17d5ae14882923f7201bb0b439cc6466d85776 100644
--- a/ee/app/assets/javascripts/analytics/cycle_analytics/constants.js
+++ b/ee/app/assets/javascripts/analytics/cycle_analytics/constants.js
@@ -78,3 +78,8 @@ export const CAPITALIZED_STAGE_NAME = Object.keys(STAGE_NAME).reduce((acc, stage
 export const PATH_HOME_ICON = 'home';
 
 export const DEFAULT_VALUE_STREAM_ID = 'default';
+
+export const OVERVIEW_METRICS = {
+  TIME_SUMMARY: 'TIME_SUMMARY',
+  RECENT_ACTIVITY: 'RECENT_ACTIVITY',
+};
diff --git a/ee/app/assets/javascripts/analytics/cycle_analytics/mixins/filter_mixins.js b/ee/app/assets/javascripts/analytics/cycle_analytics/mixins/filter_mixins.js
deleted file mode 100644
index 0d509d449220024cb43587e86981b8edfcff1eec..0000000000000000000000000000000000000000
--- a/ee/app/assets/javascripts/analytics/cycle_analytics/mixins/filter_mixins.js
+++ /dev/null
@@ -1,36 +0,0 @@
-export default {
-  data() {
-    return {
-      dateOptions: [7, 30, 90],
-      selectedGroup: null,
-      selectedProjectIds: [],
-      multiProjectSelect: true,
-    };
-  },
-  methods: {
-    renderSelectedGroup(selectedItemURL) {
-      this.service = this.createCycleAnalyticsService(selectedItemURL);
-      this.loadAnalyticsData();
-    },
-    setSelectedGroup(selectedGroup) {
-      this.selectedGroup = selectedGroup;
-      this.renderSelectedGroup(`/groups/${selectedGroup.path}/-/value_stream_analytics`);
-    },
-    setSelectedProjects(selectedProjects) {
-      this.selectedProjectIds = selectedProjects.map(value => value.id);
-      this.loadAnalyticsData();
-    },
-    setSelectedDate(days) {
-      if (this.startDate !== days) {
-        this.startDate = days;
-        this.loadAnalyticsData();
-      }
-    },
-    loadAnalyticsData() {
-      this.fetchCycleAnalyticsData({
-        startDate: this.startDate,
-        projectIds: this.selectedProjectIds,
-      });
-    },
-  },
-};
diff --git a/ee/spec/frontend/analytics/cycle_analytics/components/__snapshots__/metrics_spec.js.snap b/ee/spec/frontend/analytics/cycle_analytics/components/__snapshots__/metrics_spec.js.snap
new file mode 100644
index 0000000000000000000000000000000000000000..7a38186bb0845066db5ccdcde15fe68dfb2f0d38
--- /dev/null
+++ b/ee/spec/frontend/analytics/cycle_analytics/components/__snapshots__/metrics_spec.js.snap
@@ -0,0 +1,5 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Metrics renders the recent activity 1`] = `"<time-metrics-card-stub grouppath=\\"foo\\" additionalparams=\\"[object Object]\\" requesttype=\\"RECENT_ACTIVITY\\"></time-metrics-card-stub>"`;
+
+exports[`Metrics renders the time summary 1`] = `"<time-metrics-card-stub grouppath=\\"foo\\" additionalparams=\\"[object Object]\\" requesttype=\\"TIME_SUMMARY\\"></time-metrics-card-stub>"`;
diff --git a/ee/spec/frontend/analytics/cycle_analytics/components/__snapshots__/recent_activity_card_spec.js.snap b/ee/spec/frontend/analytics/cycle_analytics/components/__snapshots__/recent_activity_card_spec.js.snap
deleted file mode 100644
index 739151a6d40476e17e0bb7e225f927ac2ef16cf7..0000000000000000000000000000000000000000
--- a/ee/spec/frontend/analytics/cycle_analytics/components/__snapshots__/recent_activity_card_spec.js.snap
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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="gl-display-flex"
-    >
-      <div
-        class="js-metric-card-item gl-flex-grow-1 gl-text-center"
-      >
-        <h3
-          class="gl-my-2"
-        >
-          4
-        </h3>
-         
-        <p
-          class="text-secondary gl-font-sm gl-mb-2"
-        >
-          
-          New Issues
-          
-          <!---->
-        </p>
-      </div>
-      <div
-        class="js-metric-card-item gl-flex-grow-1 gl-text-center"
-      >
-        <h3
-          class="gl-my-2"
-        >
-          -
-        </h3>
-         
-        <p
-          class="text-secondary gl-font-sm gl-mb-2"
-        >
-          
-          Deploys
-          
-          <!---->
-        </p>
-      </div>
-      <div
-        class="js-metric-card-item gl-flex-grow-1 gl-text-center"
-      >
-        <h3
-          class="gl-my-2"
-        >
-          -
-        </h3>
-         
-        <p
-          class="text-secondary gl-font-sm gl-mb-2"
-        >
-          
-          Deployment Frequency
-          
-          <!---->
-        </p>
-      </div>
-    </div>
-     
-  </div>
-  <!---->
-  <!---->
-</div>
-`;
diff --git a/ee/spec/frontend/analytics/cycle_analytics/components/__snapshots__/time_metrics_card_spec.js.snap b/ee/spec/frontend/analytics/cycle_analytics/components/__snapshots__/time_metrics_card_spec.js.snap
new file mode 100644
index 0000000000000000000000000000000000000000..a6c0834cf193584cefd9f5ccb382df3e032e8271
--- /dev/null
+++ b/ee/spec/frontend/analytics/cycle_analytics/components/__snapshots__/time_metrics_card_spec.js.snap
@@ -0,0 +1,5 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`TimeMetricsCard Recent activity renders the Recent activity metric 1`] = `"<div><span>4 </span><span>- </span><span>- per day</span></div>"`;
+
+exports[`TimeMetricsCard Time summary renders the Time summary metric 1`] = `"<div><span>4.5 days</span><span>3.0 days</span></div>"`;
diff --git a/ee/spec/frontend/analytics/cycle_analytics/components/base_spec.js b/ee/spec/frontend/analytics/cycle_analytics/components/base_spec.js
index 6390e775d57a50a3c8f312316a8ce5b21ee0ac78..4d4c7afceead3b337a0a5943475354fe80a965be 100644
--- a/ee/spec/frontend/analytics/cycle_analytics/components/base_spec.js
+++ b/ee/spec/frontend/analytics/cycle_analytics/components/base_spec.js
@@ -7,8 +7,7 @@ import axios from 'axios';
 import MockAdapter from 'axios-mock-adapter';
 import GroupsDropdownFilter from 'ee/analytics/shared/components/groups_dropdown_filter.vue';
 import ProjectsDropdownFilter from 'ee/analytics/shared/components/projects_dropdown_filter.vue';
-import RecentActivityCard from 'ee/analytics/cycle_analytics/components/recent_activity_card.vue';
-import TimeMetricsCard from 'ee/analytics/cycle_analytics/components/time_metrics_card.vue';
+import Metrics from 'ee/analytics/cycle_analytics/components/metrics.vue';
 import PathNavigation from 'ee/analytics/cycle_analytics/components/path_navigation.vue';
 import StageTable from 'ee/analytics/cycle_analytics/components/stage_table.vue';
 import StageTableNav from 'ee/analytics/cycle_analytics/components/stage_table_nav.vue';
@@ -38,7 +37,6 @@ const localVue = createLocalVue();
 localVue.use(Vuex);
 
 const defaultStubs = {
-  'recent-activity-card': true,
   'stage-event-list': true,
   'stage-nav-item': true,
   'tasks-by-type-chart': true,
@@ -46,6 +44,7 @@ const defaultStubs = {
   DurationChart: true,
   GroupsDropdownFilter: true,
   ValueStreamSelect: true,
+  Metrics: true,
 };
 
 const defaultFeatureFlags = {
@@ -150,12 +149,8 @@ describe('Cycle Analytics component', () => {
     expect(wrapper.find(Daterange).exists()).toBe(flag);
   };
 
-  const displaysRecentActivityCard = flag => {
-    expect(wrapper.find(RecentActivityCard).exists()).toBe(flag);
-  };
-
-  const displaysTimeMetricsCard = flag => {
-    expect(wrapper.find(TimeMetricsCard).exists()).toBe(flag);
+  const displaysMetrics = flag => {
+    expect(wrapper.contains(Metrics)).toBe(flag);
   };
 
   const displaysStageTable = flag => {
@@ -225,12 +220,8 @@ describe('Cycle Analytics component', () => {
         displaysDateRangePicker(false);
       });
 
-      it('does not display the recent activity card', () => {
-        displaysRecentActivityCard(false);
-      });
-
-      it('does not display the time metrics card', () => {
-        displaysTimeMetricsCard(false);
+      it('does not display the metrics cards', () => {
+        displaysMetrics(false);
       });
 
       it('does not display the stage table', () => {
@@ -335,12 +326,8 @@ describe('Cycle Analytics component', () => {
           displaysDateRangePicker(true);
         });
 
-        it('displays the recent activity card', () => {
-          displaysRecentActivityCard(true);
-        });
-
-        it('displays the time metrics card', () => {
-          displaysTimeMetricsCard(true);
+        it('displays the metrics', () => {
+          displaysMetrics(true);
         });
 
         it('displays the stage table', () => {
@@ -473,12 +460,8 @@ describe('Cycle Analytics component', () => {
           displaysDateRangePicker(false);
         });
 
-        it('does not display the recent activity card', () => {
-          displaysRecentActivityCard(false);
-        });
-
-        it('does not display the time metrics card', () => {
-          displaysTimeMetricsCard(false);
+        it('does not display the metrics', () => {
+          displaysMetrics(false);
         });
 
         it('does not display the stage table', () => {
diff --git a/ee/spec/frontend/analytics/cycle_analytics/components/metrics_spec.js b/ee/spec/frontend/analytics/cycle_analytics/components/metrics_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..4b58a849f4a1521b3a1e7bb64c4894fb35377d76
--- /dev/null
+++ b/ee/spec/frontend/analytics/cycle_analytics/components/metrics_spec.js
@@ -0,0 +1,39 @@
+import { shallowMount } from '@vue/test-utils';
+import Metrics from 'ee/analytics/cycle_analytics/components/metrics.vue';
+import TimeMetricsCard from 'ee/analytics/cycle_analytics/components/time_metrics_card.vue';
+import { OVERVIEW_METRICS } from 'ee/analytics/cycle_analytics/constants';
+import { group } from '../mock_data';
+
+describe('Metrics', () => {
+  const { full_path: groupPath } = group;
+  let wrapper;
+
+  const createComponent = ({ requestParams = {} } = {}) => {
+    return shallowMount(Metrics, {
+      propsData: {
+        groupPath,
+        requestParams,
+      },
+    });
+  };
+
+  beforeEach(() => {
+    wrapper = createComponent();
+  });
+
+  afterEach(() => {
+    wrapper.destroy();
+  });
+
+  const findTimeMetricsAtIndex = index => wrapper.findAll(TimeMetricsCard).at(index);
+
+  it.each`
+    metric               | index | requestType
+    ${'time summary'}    | ${0}  | ${OVERVIEW_METRICS.TIME_SUMMARY}
+    ${'recent activity'} | ${1}  | ${OVERVIEW_METRICS.RECENT_ACTIVITY}
+  `('renders the $metric', ({ index, requestType }) => {
+    const card = findTimeMetricsAtIndex(index);
+    expect(card.props('requestType')).toBe(requestType);
+    expect(card.html()).toMatchSnapshot();
+  });
+});
diff --git a/ee/spec/frontend/analytics/cycle_analytics/components/recent_activity_card_spec.js b/ee/spec/frontend/analytics/cycle_analytics/components/recent_activity_card_spec.js
deleted file mode 100644
index a0dd5d8b253860673e6fc0c3e9fd10244ed69b4e..0000000000000000000000000000000000000000
--- a/ee/spec/frontend/analytics/cycle_analytics/components/recent_activity_card_spec.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import { mount } from '@vue/test-utils';
-import RecentActivityCard from 'ee/analytics/cycle_analytics/components/recent_activity_card.vue';
-import Api from 'ee/api';
-import createFlash from '~/flash';
-import { group, recentActivityData } from '../mock_data';
-
-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',
-      });
-    });
-  });
-});
diff --git a/ee/spec/frontend/analytics/cycle_analytics/components/time_metrics_card_spec.js b/ee/spec/frontend/analytics/cycle_analytics/components/time_metrics_card_spec.js
index b83e4960487b0d206f5c84e6f4b9e43b2cf9f774..221a7333aa8ebf337e3ca067a84620f5d67ebe2c 100644
--- a/ee/spec/frontend/analytics/cycle_analytics/components/time_metrics_card_spec.js
+++ b/ee/spec/frontend/analytics/cycle_analytics/components/time_metrics_card_spec.js
@@ -1,8 +1,9 @@
 import { shallowMount } from '@vue/test-utils';
 import TimeMetricsCard from 'ee/analytics/cycle_analytics/components/time_metrics_card.vue';
+import { OVERVIEW_METRICS } from 'ee/analytics/cycle_analytics/constants';
 import Api from 'ee/api';
+import { group, timeMetricsData, recentActivityData } from '../mock_data';
 import createFlash from '~/flash';
-import { group, timeMetricsData } from '../mock_data';
 
 jest.mock('~/flash');
 
@@ -10,62 +11,78 @@ describe('TimeMetricsCard', () => {
   const { full_path: groupPath } = group;
   let wrapper;
 
-  const createComponent = ({ additionalParams = {} } = {}) => {
+  const template = `
+    <div slot-scope="{ metrics }">
+      <span v-for="metric in metrics">{{metric.value}} {{metric.unit}}</span>
+    </div>`;
+
+  const createComponent = ({ additionalParams = {}, requestType } = {}) => {
     return shallowMount(TimeMetricsCard, {
       propsData: {
         groupPath,
         additionalParams,
+        requestType,
       },
-      slots: {
-        default: 'mockMetricCard',
+      scopedSlots: {
+        default: template,
       },
     });
   };
 
-  beforeEach(() => {
-    jest.spyOn(Api, 'cycleAnalyticsTimeSummaryData').mockResolvedValue({ data: timeMetricsData });
-
-    wrapper = createComponent();
-  });
+  describe.each`
+    metric               | requestType                         | request                            | data
+    ${'Recent activity'} | ${OVERVIEW_METRICS.RECENT_ACTIVITY} | ${'cycleAnalyticsSummaryData'}     | ${recentActivityData}
+    ${'Time summary'}    | ${OVERVIEW_METRICS.TIME_SUMMARY}    | ${'cycleAnalyticsTimeSummaryData'} | ${timeMetricsData}
+  `('$metric', ({ requestType, request, data, metric }) => {
+    beforeEach(() => {
+      jest.spyOn(Api, request).mockResolvedValue({ data });
+      wrapper = createComponent({ requestType });
+    });
 
-  afterEach(() => {
-    wrapper.destroy();
-    wrapper = null;
-  });
-  it('fetches the time metrics data', () => {
-    expect(Api.cycleAnalyticsTimeSummaryData).toHaveBeenCalledWith(groupPath, {});
-  });
+    afterEach(() => {
+      wrapper.destroy();
+      wrapper = null;
+    });
 
-  describe('with a failing request', () => {
-    beforeEach(() => {
-      jest.spyOn(Api, 'cycleAnalyticsTimeSummaryData').mockRejectedValue();
+    it(`renders the ${metric} metric`, () => {
+      expect(wrapper.html()).toMatchSnapshot();
+    });
 
-      wrapper = createComponent();
+    it('fetches the metric data', () => {
+      expect(Api[request]).toHaveBeenCalledWith(groupPath, {});
     });
 
-    it('should render an error message', () => {
-      expect(createFlash).toHaveBeenCalledWith(
-        'There was an error while fetching value stream analytics time summary data.',
-      );
+    describe('with a failing request', () => {
+      beforeEach(() => {
+        jest.spyOn(Api, request).mockRejectedValue();
+        wrapper = createComponent({ requestType });
+      });
+
+      it('should render an error message', () => {
+        expect(createFlash).toHaveBeenCalledWith(
+          `There was an error while fetching value stream analytics ${metric.toLowerCase()} data.`,
+        );
+      });
     });
-  });
 
-  describe('with additional params', () => {
-    beforeEach(() => {
-      wrapper = createComponent({
-        additionalParams: {
+    describe('with additional params', () => {
+      beforeEach(() => {
+        wrapper = createComponent({
+          requestType,
+          additionalParams: {
+            'project_ids[]': [1],
+            created_after: '2020-01-01',
+            created_before: '2020-02-01',
+          },
+        });
+      });
+
+      it('sends additional parameters as query paremeters', () => {
+        expect(Api[request]).toHaveBeenCalledWith(groupPath, {
           'project_ids[]': [1],
           created_after: '2020-01-01',
           created_before: '2020-02-01',
-        },
-      });
-    });
-
-    it('sends additional parameters as query paremeters', () => {
-      expect(Api.cycleAnalyticsTimeSummaryData).toHaveBeenCalledWith(groupPath, {
-        'project_ids[]': [1],
-        created_after: '2020-01-01',
-        created_before: '2020-02-01',
+        });
       });
     });
   });
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 497757c72d0680e787baeabe9b5173f8bb2f58f8..f06e59d18e6afc3724909459070117b172cc8be0 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -24830,6 +24830,9 @@ msgstr ""
 msgid "There was an error while fetching the table data."
 msgstr ""
 
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
+msgstr ""
+
 msgid "There was an error while fetching value stream analytics data."
 msgstr ""
 
@@ -24839,12 +24842,6 @@ msgstr ""
 msgid "There was an error while fetching value stream analytics duration median data."
 msgstr ""
 
-msgid "There was an error while fetching value stream analytics recent activity data."
-msgstr ""
-
-msgid "There was an error while fetching value stream analytics time summary data."
-msgstr ""
-
 msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
 msgstr ""
 
@@ -29728,6 +29725,9 @@ msgstr ""
 msgid "quick actions"
 msgstr ""
 
+msgid "recent activity"
+msgstr ""
+
 msgid "register"
 msgstr ""
 
@@ -29892,6 +29892,9 @@ msgstr ""
 msgid "this document"
 msgstr ""
 
+msgid "time summary"
+msgstr ""
+
 msgid "to help your contributors communicate effectively!"
 msgstr ""