gitlab-org--gitlab-foss/spec/frontend/cycle_analytics/value_stream_metrics_spec.js

186 lines
6.2 KiB
JavaScript

import { GlSkeletonLoader } from '@gitlab/ui';
import { nextTick } from 'vue';
import metricsData from 'test_fixtures/projects/analytics/value_stream_analytics/summary.json';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import ValueStreamMetrics from '~/analytics/shared/components/value_stream_metrics.vue';
import { METRIC_TYPE_SUMMARY } from '~/api/analytics_api';
import { VSA_METRICS_GROUPS, METRICS_POPOVER_CONTENT } from '~/analytics/shared/constants';
import { prepareTimeMetricsData } from '~/analytics/shared/utils';
import MetricTile from '~/analytics/shared/components/metric_tile.vue';
import { createAlert } from '~/flash';
import { group } from './mock_data';
jest.mock('~/flash');
describe('ValueStreamMetrics', () => {
let wrapper;
let mockGetValueStreamSummaryMetrics;
let mockFilterFn;
const { full_path: requestPath } = group;
const fakeReqName = 'Mock metrics';
const metricsRequestFactory = () => ({
request: mockGetValueStreamSummaryMetrics,
endpoint: METRIC_TYPE_SUMMARY,
name: fakeReqName,
});
const createComponent = (props = {}) => {
return shallowMountExtended(ValueStreamMetrics, {
propsData: {
requestPath,
requestParams: {},
requests: [metricsRequestFactory()],
...props,
},
});
};
const findMetrics = () => wrapper.findAllComponents(MetricTile);
const findMetricsGroups = () => wrapper.findAllByTestId('vsa-metrics-group');
const expectToHaveRequest = (fields) => {
expect(mockGetValueStreamSummaryMetrics).toHaveBeenCalledWith({
endpoint: METRIC_TYPE_SUMMARY,
requestPath,
...fields,
});
};
afterEach(() => {
wrapper.destroy();
});
describe('with successful requests', () => {
beforeEach(() => {
mockGetValueStreamSummaryMetrics = jest.fn().mockResolvedValue({ data: metricsData });
});
it('will display a loader with pending requests', async () => {
wrapper = createComponent();
await nextTick();
expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(true);
});
describe('with data loaded', () => {
beforeEach(async () => {
wrapper = createComponent();
await waitForPromises();
});
it('fetches data from the value stream analytics endpoint', () => {
expectToHaveRequest({ params: {} });
});
describe.each`
index | identifier | value | label
${0} | ${metricsData[0].identifier} | ${metricsData[0].value} | ${metricsData[0].title}
${1} | ${metricsData[1].identifier} | ${metricsData[1].value} | ${metricsData[1].title}
${2} | ${metricsData[2].identifier} | ${metricsData[2].value} | ${metricsData[2].title}
${3} | ${metricsData[3].identifier} | ${metricsData[3].value} | ${metricsData[3].title}
`('metric tiles', ({ identifier, index, value, label }) => {
it(`renders a metric tile component for "${label}"`, () => {
const metric = findMetrics().at(index);
expect(metric.props('metric')).toMatchObject({ identifier, value, label });
expect(metric.isVisible()).toBe(true);
});
});
it('will not display a loading icon', () => {
expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(false);
});
describe('filterFn', () => {
const transferredMetricsData = prepareTimeMetricsData(metricsData, METRICS_POPOVER_CONTENT);
it('with a filter function, will call the function with the metrics data', async () => {
const filteredData = [
{ identifier: 'issues', value: '3', title: 'New Issues', description: 'foo' },
];
mockFilterFn = jest.fn(() => filteredData);
wrapper = createComponent({
filterFn: mockFilterFn,
});
await waitForPromises();
expect(mockFilterFn).toHaveBeenCalledWith(transferredMetricsData);
expect(wrapper.vm.metrics).toEqual(filteredData);
});
it('without a filter function, it will only update the metrics', async () => {
wrapper = createComponent();
await waitForPromises();
expect(mockFilterFn).not.toHaveBeenCalled();
expect(wrapper.vm.metrics).toEqual(transferredMetricsData);
});
});
describe('with additional params', () => {
beforeEach(async () => {
wrapper = createComponent({
requestParams: {
'project_ids[]': [1],
created_after: '2020-01-01',
created_before: '2020-02-01',
},
});
await waitForPromises();
});
it('fetches data for the `getValueStreamSummaryMetrics` request', () => {
expectToHaveRequest({
params: {
'project_ids[]': [1],
created_after: '2020-01-01',
created_before: '2020-02-01',
},
});
});
});
describe('groupBy', () => {
beforeEach(async () => {
mockGetValueStreamSummaryMetrics = jest.fn().mockResolvedValue({ data: metricsData });
wrapper = createComponent({ groupBy: VSA_METRICS_GROUPS });
await waitForPromises();
});
it('renders the metrics as separate groups', () => {
const groups = findMetricsGroups();
expect(groups).toHaveLength(VSA_METRICS_GROUPS.length);
});
it('renders titles for each group', () => {
const groups = findMetricsGroups();
groups.wrappers.forEach((g, index) => {
const { title } = VSA_METRICS_GROUPS[index];
expect(g.html()).toContain(title);
});
});
});
});
});
describe('with a request failing', () => {
beforeEach(async () => {
mockGetValueStreamSummaryMetrics = jest.fn().mockRejectedValue();
wrapper = createComponent();
await waitForPromises();
});
it('should render an error message', () => {
expect(createAlert).toHaveBeenCalledWith({
message: `There was an error while fetching value stream analytics ${fakeReqName} data.`,
});
});
});
});