2021-10-27 15:23:28 +05:30
|
|
|
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
|
|
|
|
import { shallowMount } from '@vue/test-utils';
|
2022-04-04 11:22:00 +05:30
|
|
|
import { nextTick } from 'vue';
|
2021-12-11 22:18:48 +05:30
|
|
|
import metricsData from 'test_fixtures/projects/analytics/value_stream_analytics/summary.json';
|
2021-10-27 15:23:28 +05:30
|
|
|
import waitForPromises from 'helpers/wait_for_promises';
|
2022-04-04 11:22:00 +05:30
|
|
|
import ValueStreamMetrics from '~/analytics/shared/components/value_stream_metrics.vue';
|
2021-10-27 15:23:28 +05:30
|
|
|
import { METRIC_TYPE_SUMMARY } from '~/api/analytics_api';
|
2022-04-04 11:22:00 +05:30
|
|
|
import { METRICS_POPOVER_CONTENT } from '~/analytics/shared/constants';
|
|
|
|
import { prepareTimeMetricsData } from '~/analytics/shared/utils';
|
|
|
|
import MetricTile from '~/analytics/shared/components/metric_tile.vue';
|
2021-10-27 15:23:28 +05:30
|
|
|
import createFlash from '~/flash';
|
2021-12-11 22:18:48 +05:30
|
|
|
import { group } from './mock_data';
|
2021-10-27 15:23:28 +05:30
|
|
|
|
|
|
|
jest.mock('~/flash');
|
|
|
|
|
|
|
|
describe('ValueStreamMetrics', () => {
|
|
|
|
let wrapper;
|
|
|
|
let mockGetValueStreamSummaryMetrics;
|
2022-04-04 11:22:00 +05:30
|
|
|
let mockFilterFn;
|
2021-10-27 15:23:28 +05:30
|
|
|
|
|
|
|
const { full_path: requestPath } = group;
|
|
|
|
const fakeReqName = 'Mock metrics';
|
|
|
|
const metricsRequestFactory = () => ({
|
|
|
|
request: mockGetValueStreamSummaryMetrics,
|
|
|
|
endpoint: METRIC_TYPE_SUMMARY,
|
|
|
|
name: fakeReqName,
|
|
|
|
});
|
|
|
|
|
2022-04-04 11:22:00 +05:30
|
|
|
const createComponent = (props = {}) => {
|
2021-10-27 15:23:28 +05:30
|
|
|
return shallowMount(ValueStreamMetrics, {
|
|
|
|
propsData: {
|
|
|
|
requestPath,
|
2022-04-04 11:22:00 +05:30
|
|
|
requestParams: {},
|
2021-10-27 15:23:28 +05:30
|
|
|
requests: [metricsRequestFactory()],
|
2022-04-04 11:22:00 +05:30
|
|
|
...props,
|
2021-10-27 15:23:28 +05:30
|
|
|
},
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2022-04-04 11:22:00 +05:30
|
|
|
const findMetrics = () => wrapper.findAllComponents(MetricTile);
|
2021-10-27 15:23:28 +05:30
|
|
|
|
|
|
|
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 });
|
|
|
|
wrapper = createComponent();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('will display a loader with pending requests', async () => {
|
2022-04-04 11:22:00 +05:30
|
|
|
await nextTick();
|
2021-10-27 15:23:28 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
expect(wrapper.findComponent(GlSkeletonLoading).exists()).toBe(true);
|
|
|
|
});
|
|
|
|
|
2022-04-04 11:22:00 +05:30
|
|
|
it('renders hidden MetricTile components for each metric', async () => {
|
2021-12-11 22:18:48 +05:30
|
|
|
await waitForPromises();
|
|
|
|
|
2022-03-02 08:16:31 +05:30
|
|
|
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
|
|
|
|
// eslint-disable-next-line no-restricted-syntax
|
2021-12-11 22:18:48 +05:30
|
|
|
wrapper.setData({ isLoading: true });
|
|
|
|
|
2022-04-04 11:22:00 +05:30
|
|
|
await nextTick();
|
2021-12-11 22:18:48 +05:30
|
|
|
|
|
|
|
const components = findMetrics();
|
|
|
|
|
|
|
|
expect(components).toHaveLength(metricsData.length);
|
|
|
|
|
|
|
|
metricsData.forEach((metric, index) => {
|
|
|
|
expect(components.at(index).isVisible()).toBe(false);
|
|
|
|
});
|
2021-10-27 15:23:28 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
describe('with data loaded', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
await waitForPromises();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('fetches data from the value stream analytics endpoint', () => {
|
|
|
|
expectToHaveRequest({ params: {} });
|
|
|
|
});
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
describe.each`
|
2022-04-04 11:22:00 +05:30
|
|
|
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}"`, () => {
|
2021-10-27 15:23:28 +05:30
|
|
|
const metric = findMetrics().at(index);
|
2022-04-04 11:22:00 +05:30
|
|
|
expect(metric.props('metric')).toMatchObject({ identifier, value, label });
|
2021-12-11 22:18:48 +05:30
|
|
|
expect(metric.isVisible()).toBe(true);
|
|
|
|
});
|
|
|
|
});
|
2021-10-27 15:23:28 +05:30
|
|
|
|
|
|
|
it('will not display a loading icon', () => {
|
|
|
|
expect(wrapper.find(GlSkeletonLoading).exists()).toBe(false);
|
|
|
|
});
|
|
|
|
|
2022-04-04 11:22:00 +05:30
|
|
|
describe('filterFn', () => {
|
2022-05-07 20:08:51 +05:30
|
|
|
const transferredMetricsData = prepareTimeMetricsData(metricsData, METRICS_POPOVER_CONTENT);
|
2022-04-04 11:22:00 +05:30
|
|
|
|
|
|
|
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();
|
|
|
|
|
2022-05-07 20:08:51 +05:30
|
|
|
expect(mockFilterFn).toHaveBeenCalledWith(transferredMetricsData);
|
2022-04-04 11:22:00 +05:30
|
|
|
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();
|
2022-05-07 20:08:51 +05:30
|
|
|
expect(wrapper.vm.metrics).toEqual(transferredMetricsData);
|
2022-04-04 11:22:00 +05:30
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2021-10-27 15:23:28 +05:30
|
|
|
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('with a request failing', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
mockGetValueStreamSummaryMetrics = jest.fn().mockRejectedValue();
|
|
|
|
wrapper = createComponent();
|
|
|
|
|
|
|
|
await waitForPromises();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('it should render an error message', () => {
|
|
|
|
expect(createFlash).toHaveBeenCalledWith({
|
|
|
|
message: `There was an error while fetching value stream analytics ${fakeReqName} data.`,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|