2021-03-08 18:12:59 +05:30
|
|
|
import { GlTabs, GlTab } from '@gitlab/ui';
|
2021-03-11 19:13:27 +05:30
|
|
|
import { merge } from 'lodash';
|
2022-04-04 11:22:00 +05:30
|
|
|
import { nextTick } from 'vue';
|
2022-01-26 12:08:38 +05:30
|
|
|
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
2021-03-11 19:13:27 +05:30
|
|
|
import setWindowLocation from 'helpers/set_window_location_helper';
|
|
|
|
import { TEST_HOST } from 'helpers/test_constants';
|
|
|
|
import { mergeUrlParams, updateHistory, getParameterValues } from '~/lib/utils/url_utility';
|
2020-03-13 15:44:24 +05:30
|
|
|
import Component from '~/projects/pipelines/charts/components/app.vue';
|
2021-03-08 18:12:59 +05:30
|
|
|
import PipelineCharts from '~/projects/pipelines/charts/components/pipeline_charts.vue';
|
2022-01-26 12:08:38 +05:30
|
|
|
import API from '~/api';
|
2023-01-13 00:05:48 +05:30
|
|
|
import { mockTracking } from 'helpers/tracking_helper';
|
|
|
|
import {
|
|
|
|
SNOWPLOW_DATA_SOURCE,
|
|
|
|
SNOWPLOW_LABEL,
|
|
|
|
SNOWPLOW_SCHEMA,
|
|
|
|
} from '~/projects/pipelines/charts/constants';
|
2021-02-22 17:27:13 +05:30
|
|
|
|
2021-03-11 19:13:27 +05:30
|
|
|
jest.mock('~/lib/utils/url_utility');
|
2020-03-13 15:44:24 +05:30
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} };
|
2021-04-29 21:17:54 +05:30
|
|
|
const LeadTimeChartsStub = { name: 'LeadTimeCharts', render: () => {} };
|
2022-07-23 23:45:48 +05:30
|
|
|
const TimeToRestoreServiceChartsStub = { name: 'TimeToRestoreServiceCharts', render: () => {} };
|
2022-08-13 15:12:31 +05:30
|
|
|
const ChangeFailureRateChartsStub = { name: 'ChangeFailureRateCharts', render: () => {} };
|
2021-12-11 22:18:48 +05:30
|
|
|
const ProjectQualitySummaryStub = { name: 'ProjectQualitySummary', render: () => {} };
|
2021-03-08 18:12:59 +05:30
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
describe('ProjectsPipelinesChartsApp', () => {
|
|
|
|
let wrapper;
|
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
function createComponent(mountOptions = {}) {
|
2022-01-26 12:08:38 +05:30
|
|
|
wrapper = shallowMountExtended(
|
2021-03-08 18:12:59 +05:30
|
|
|
Component,
|
|
|
|
merge(
|
|
|
|
{},
|
|
|
|
{
|
|
|
|
provide: {
|
2021-04-29 21:17:54 +05:30
|
|
|
shouldRenderDoraCharts: true,
|
2021-12-11 22:18:48 +05:30
|
|
|
shouldRenderQualitySummary: true,
|
2021-03-08 18:12:59 +05:30
|
|
|
},
|
|
|
|
stubs: {
|
|
|
|
DeploymentFrequencyCharts: DeploymentFrequencyChartsStub,
|
2021-04-29 21:17:54 +05:30
|
|
|
LeadTimeCharts: LeadTimeChartsStub,
|
2022-07-23 23:45:48 +05:30
|
|
|
TimeToRestoreServiceCharts: TimeToRestoreServiceChartsStub,
|
2022-08-13 15:12:31 +05:30
|
|
|
ChangeFailureRateCharts: ChangeFailureRateChartsStub,
|
2021-12-11 22:18:48 +05:30
|
|
|
ProjectQualitySummary: ProjectQualitySummaryStub,
|
2021-03-08 18:12:59 +05:30
|
|
|
},
|
|
|
|
},
|
|
|
|
mountOptions,
|
|
|
|
),
|
|
|
|
);
|
2021-02-22 17:27:13 +05:30
|
|
|
}
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
afterEach(() => {
|
|
|
|
wrapper.destroy();
|
|
|
|
});
|
|
|
|
|
2022-10-11 01:57:18 +05:30
|
|
|
const findGlTabs = () => wrapper.findComponent(GlTabs);
|
|
|
|
const findAllGlTabs = () => wrapper.findAllComponents(GlTab);
|
2021-04-29 21:17:54 +05:30
|
|
|
const findGlTabAtIndex = (index) => findAllGlTabs().at(index);
|
2022-10-11 01:57:18 +05:30
|
|
|
const findLeadTimeCharts = () => wrapper.findComponent(LeadTimeChartsStub);
|
|
|
|
const findTimeToRestoreServiceCharts = () =>
|
|
|
|
wrapper.findComponent(TimeToRestoreServiceChartsStub);
|
|
|
|
const findChangeFailureRateCharts = () => wrapper.findComponent(ChangeFailureRateChartsStub);
|
|
|
|
const findDeploymentFrequencyCharts = () => wrapper.findComponent(DeploymentFrequencyChartsStub);
|
|
|
|
const findPipelineCharts = () => wrapper.findComponent(PipelineCharts);
|
|
|
|
const findProjectQualitySummary = () => wrapper.findComponent(ProjectQualitySummaryStub);
|
2021-03-11 19:13:27 +05:30
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
describe('when all charts are available', () => {
|
2021-03-08 18:12:59 +05:30
|
|
|
beforeEach(() => {
|
2021-04-29 21:17:54 +05:30
|
|
|
createComponent();
|
2020-03-13 15:44:24 +05:30
|
|
|
});
|
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
describe.each`
|
|
|
|
title | finderFn | index
|
|
|
|
${'Pipelines'} | ${findPipelineCharts} | ${0}
|
|
|
|
${'Deployment frequency'} | ${findDeploymentFrequencyCharts} | ${1}
|
|
|
|
${'Lead time'} | ${findLeadTimeCharts} | ${2}
|
|
|
|
${'Time to restore service'} | ${findTimeToRestoreServiceCharts} | ${3}
|
|
|
|
${'Change failure rate'} | ${findChangeFailureRateCharts} | ${4}
|
|
|
|
${'Project quality'} | ${findProjectQualitySummary} | ${5}
|
|
|
|
`('Tabs', ({ title, finderFn, index }) => {
|
|
|
|
it(`renders tab with a title ${title} at index ${index}`, () => {
|
|
|
|
expect(findGlTabAtIndex(index).attributes('title')).toBe(title);
|
|
|
|
});
|
2021-04-29 21:17:54 +05:30
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
it(`renders the ${title} chart`, () => {
|
|
|
|
expect(finderFn().exists()).toBe(true);
|
|
|
|
});
|
2021-04-29 21:17:54 +05:30
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
it(`updates the current tab and url when the ${title} tab is clicked`, async () => {
|
|
|
|
let chartsPath;
|
|
|
|
const tabName = title.toLowerCase().replace(/\s/g, '-');
|
2021-04-29 21:17:54 +05:30
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`);
|
2021-03-11 19:13:27 +05:30
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
mergeUrlParams.mockImplementation(({ chart }, path) => {
|
|
|
|
expect(chart).toBe(tabName);
|
|
|
|
expect(path).toBe(window.location.pathname);
|
|
|
|
chartsPath = `${path}?chart=${chart}`;
|
|
|
|
return chartsPath;
|
|
|
|
});
|
2021-04-29 21:17:54 +05:30
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
updateHistory.mockImplementation(({ url }) => {
|
|
|
|
expect(url).toBe(chartsPath);
|
|
|
|
});
|
|
|
|
const tabs = findGlTabs();
|
2022-07-23 23:45:48 +05:30
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
expect(tabs.attributes('value')).toBe('0');
|
2021-12-11 22:18:48 +05:30
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
tabs.vm.$emit('input', index);
|
2021-03-11 19:13:27 +05:30
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
await nextTick();
|
2021-03-11 19:13:27 +05:30
|
|
|
|
2022-08-13 15:12:31 +05:30
|
|
|
expect(tabs.attributes('value')).toBe(index.toString());
|
2021-03-11 19:13:27 +05:30
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not try to push history if the tab does not change', async () => {
|
|
|
|
setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`);
|
|
|
|
|
|
|
|
mergeUrlParams.mockImplementation(({ chart }, path) => `${path}?chart=${chart}`);
|
|
|
|
|
|
|
|
const tabs = findGlTabs();
|
|
|
|
|
|
|
|
expect(tabs.attributes('value')).toBe('0');
|
|
|
|
|
|
|
|
tabs.vm.$emit('input', 0);
|
|
|
|
|
2022-04-04 11:22:00 +05:30
|
|
|
await nextTick();
|
2021-03-11 19:13:27 +05:30
|
|
|
|
|
|
|
expect(updateHistory).not.toHaveBeenCalled();
|
|
|
|
});
|
2022-01-26 12:08:38 +05:30
|
|
|
|
|
|
|
describe('event tracking', () => {
|
2023-01-13 00:05:48 +05:30
|
|
|
describe('RedisHLL events', () => {
|
|
|
|
it.each`
|
|
|
|
testId | event
|
|
|
|
${'pipelines-tab'} | ${'p_analytics_ci_cd_pipelines'}
|
|
|
|
${'deployment-frequency-tab'} | ${'p_analytics_ci_cd_deployment_frequency'}
|
|
|
|
${'lead-time-tab'} | ${'p_analytics_ci_cd_lead_time'}
|
|
|
|
${'time-to-restore-service-tab'} | ${'p_analytics_ci_cd_time_to_restore_service'}
|
|
|
|
${'change-failure-rate-tab'} | ${'p_analytics_ci_cd_change_failure_rate'}
|
|
|
|
`('tracks the $event event when clicked', ({ testId, event }) => {
|
|
|
|
const trackApiSpy = jest.spyOn(API, 'trackRedisHllUserEvent');
|
|
|
|
|
|
|
|
expect(trackApiSpy).not.toHaveBeenCalled();
|
|
|
|
|
|
|
|
wrapper.findByTestId(testId).vm.$emit('click');
|
|
|
|
|
|
|
|
expect(trackApiSpy).toHaveBeenCalledWith(event);
|
|
|
|
});
|
|
|
|
});
|
2022-01-26 12:08:38 +05:30
|
|
|
|
2023-01-13 00:05:48 +05:30
|
|
|
describe('Snowplow events', () => {
|
|
|
|
it.each`
|
|
|
|
testId | event
|
|
|
|
${'pipelines-tab'} | ${'p_analytics_ci_cd_pipelines'}
|
|
|
|
${'deployment-frequency-tab'} | ${'p_analytics_ci_cd_deployment_frequency'}
|
|
|
|
${'lead-time-tab'} | ${'p_analytics_ci_cd_lead_time'}
|
|
|
|
`('tracks the $event event when clicked', ({ testId, event }) => {
|
|
|
|
const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
|
|
|
|
|
|
|
|
wrapper.findByTestId(testId).vm.$emit('click');
|
|
|
|
|
|
|
|
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_tab', {
|
|
|
|
label: SNOWPLOW_LABEL,
|
|
|
|
context: {
|
|
|
|
schema: SNOWPLOW_SCHEMA,
|
|
|
|
data: {
|
|
|
|
event_name: event,
|
|
|
|
data_source: SNOWPLOW_DATA_SOURCE,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
2022-01-26 12:08:38 +05:30
|
|
|
|
2023-01-13 00:05:48 +05:30
|
|
|
it.each`
|
|
|
|
tab
|
|
|
|
${'time-to-restore-service-tab'}
|
|
|
|
${'change-failure-rate-tab'}
|
|
|
|
`('does not track when tab $tab is clicked', ({ tab }) => {
|
|
|
|
const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
|
2022-01-26 12:08:38 +05:30
|
|
|
|
2023-01-13 00:05:48 +05:30
|
|
|
wrapper.findByTestId(tab).vm.$emit('click');
|
|
|
|
|
|
|
|
expect(trackingSpy).not.toHaveBeenCalled();
|
|
|
|
});
|
2022-01-26 12:08:38 +05:30
|
|
|
});
|
|
|
|
});
|
2021-03-11 19:13:27 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
describe('when provided with a query param', () => {
|
|
|
|
it.each`
|
2022-07-23 23:45:48 +05:30
|
|
|
chart | tab
|
2022-08-13 15:12:31 +05:30
|
|
|
${'change-failure-rate'} | ${'4'}
|
2022-07-23 23:45:48 +05:30
|
|
|
${'time-to-restore-service'} | ${'3'}
|
|
|
|
${'lead-time'} | ${'2'}
|
|
|
|
${'deployment-frequency'} | ${'1'}
|
|
|
|
${'pipelines'} | ${'0'}
|
|
|
|
${'fake'} | ${'0'}
|
|
|
|
${''} | ${'0'}
|
2021-03-11 19:13:27 +05:30
|
|
|
`('shows the correct tab for URL parameter "$chart"', ({ chart, tab }) => {
|
|
|
|
setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts?chart=${chart}`);
|
|
|
|
getParameterValues.mockImplementation((name) => {
|
|
|
|
expect(name).toBe('chart');
|
|
|
|
return chart ? [chart] : [];
|
|
|
|
});
|
2021-04-29 21:17:54 +05:30
|
|
|
createComponent();
|
2021-03-11 19:13:27 +05:30
|
|
|
expect(findGlTabs().attributes('value')).toBe(tab);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should set the tab when the back button is clicked', async () => {
|
|
|
|
let popstateHandler;
|
|
|
|
|
|
|
|
window.addEventListener = jest.fn();
|
|
|
|
|
|
|
|
window.addEventListener.mockImplementation((event, handler) => {
|
|
|
|
if (event === 'popstate') {
|
|
|
|
popstateHandler = handler;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
getParameterValues.mockImplementation((name) => {
|
|
|
|
expect(name).toBe('chart');
|
|
|
|
return [];
|
|
|
|
});
|
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
createComponent();
|
2021-03-11 19:13:27 +05:30
|
|
|
|
|
|
|
expect(findGlTabs().attributes('value')).toBe('0');
|
|
|
|
|
|
|
|
getParameterValues.mockImplementationOnce((name) => {
|
|
|
|
expect(name).toBe('chart');
|
2021-06-08 01:23:25 +05:30
|
|
|
return ['deployment-frequency'];
|
2021-03-11 19:13:27 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
popstateHandler();
|
|
|
|
|
2022-04-04 11:22:00 +05:30
|
|
|
await nextTick();
|
2021-03-11 19:13:27 +05:30
|
|
|
|
|
|
|
expect(findGlTabs().attributes('value')).toBe('1');
|
|
|
|
});
|
2021-03-08 18:12:59 +05:30
|
|
|
});
|
2020-03-13 15:44:24 +05:30
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
describe('when the dora charts are not available and project quality summary is not available', () => {
|
2021-03-08 18:12:59 +05:30
|
|
|
beforeEach(() => {
|
2021-12-11 22:18:48 +05:30
|
|
|
createComponent({
|
|
|
|
provide: { shouldRenderDoraCharts: false, shouldRenderQualitySummary: false },
|
|
|
|
});
|
2021-03-08 18:12:59 +05:30
|
|
|
});
|
2020-03-13 15:44:24 +05:30
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
it('does not render tabs', () => {
|
2021-03-08 18:12:59 +05:30
|
|
|
expect(findGlTabs().exists()).toBe(false);
|
2021-04-29 21:17:54 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
it('renders the pipeline charts', () => {
|
|
|
|
expect(findPipelineCharts().exists()).toBe(true);
|
2020-03-13 15:44:24 +05:30
|
|
|
});
|
|
|
|
});
|
2021-12-11 22:18:48 +05:30
|
|
|
|
|
|
|
describe('when the project quality summary is not available', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
createComponent({ provide: { shouldRenderQualitySummary: false } });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('does not render the tab', () => {
|
|
|
|
expect(findProjectQualitySummary().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
2020-03-13 15:44:24 +05:30
|
|
|
});
|