Skip to content
Snippets Groups Projects
Commit 57e3d49f authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 33185181
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -10810,9 +10810,6 @@ msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
msgstr ""
 
msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
msgstr ""
msgid "Metrics|Unit label"
msgstr ""
 
Loading
Loading
import { shallowMount } from '@vue/test-utils';
import { setTestTimeout } from 'helpers/timeout';
import { createStore } from '~/monitoring/stores';
import { GlLink } from '@gitlab/ui';
import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper';
import TimeSeries from '~/monitoring/components/charts/time_series.vue';
import * as types from '~/monitoring/stores/mutation_types';
import { TEST_HOST } from 'spec/test_constants';
import MonitoringMock, {
import {
deploymentData,
mockProjectPath,
} from '../../../javascripts/monitoring/mock_data';
metricsGroupsAPIResponse,
mockedQueryResultPayload,
mockProjectDir,
mockHost,
} from '../mock_data';
import * as iconUtils from '~/lib/utils/icon_utils';
 
const mockSvgPathContent = 'mockSvgPathContent';
const mockSha = 'mockSha';
const mockWidgets = 'mockWidgets';
const projectPath = `${TEST_HOST}${mockProjectPath}`;
const commitUrl = `${projectPath}/commit/${mockSha}`;
 
jest.mock('~/lib/utils/icon_utils', () => ({
getSvgIconPathContent: jest.fn().mockImplementation(
Loading
Loading
@@ -33,32 +34,44 @@ describe('Time series component', () => {
let store;
 
beforeEach(() => {
setTestTimeout(1000);
store = createStore();
store.commit(`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, MonitoringMock.data);
store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
metricsGroupsAPIResponse,
);
store.commit(`monitoringDashboard/${types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS}`, deploymentData);
[, mockGraphData] = store.state.monitoringDashboard.dashboard.panel_groups[0].metrics;
// Mock data contains 2 panels, pick the first one
store.commit(`monitoringDashboard/${types.SET_QUERY_RESULT}`, mockedQueryResultPayload);
[mockGraphData] = store.state.monitoringDashboard.dashboard.panel_groups[0].metrics;
 
makeTimeSeriesChart = (graphData, type) =>
shallowMount(TimeSeries, {
attachToDocument: true,
propsData: {
graphData: { ...graphData, type },
deploymentData: store.state.monitoringDashboard.deploymentData,
projectPath,
projectPath: `${mockHost}${mockProjectDir}`,
},
slots: {
default: mockWidgets,
},
sync: false,
store,
attachToDocument: true,
});
});
 
describe('general functions', () => {
let timeSeriesChart;
 
beforeEach(() => {
beforeEach(done => {
timeSeriesChart = makeTimeSeriesChart(mockGraphData, 'area-chart');
timeSeriesChart.vm.$nextTick(done);
});
 
it('renders chart title', () => {
Loading
Loading
@@ -83,18 +96,24 @@ describe('Time series component', () => {
 
describe('methods', () => {
describe('formatTooltipText', () => {
const mockDate = deploymentData[0].created_at;
const mockCommitUrl = deploymentData[0].commitUrl;
const generateSeriesData = type => ({
seriesData: [
{
seriesName: timeSeriesChart.vm.chartData[0].name,
componentSubType: type,
value: [mockDate, 5.55555],
dataIndex: 0,
},
],
value: mockDate,
let mockDate;
let mockCommitUrl;
let generateSeriesData;
beforeEach(() => {
mockDate = deploymentData[0].created_at;
mockCommitUrl = deploymentData[0].commitUrl;
generateSeriesData = type => ({
seriesData: [
{
seriesName: timeSeriesChart.vm.chartData[0].name,
componentSubType: type,
value: [mockDate, 5.55555],
dataIndex: 0,
},
],
value: mockDate,
});
});
 
describe('when series is of line type', () => {
Loading
Loading
@@ -104,11 +123,11 @@ describe('Time series component', () => {
});
 
it('formats tooltip title', () => {
expect(timeSeriesChart.vm.tooltip.title).toBe('31 May 2017, 9:23PM');
expect(timeSeriesChart.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM');
});
 
it('formats tooltip content', () => {
const name = 'Core Usage';
const name = 'Pod average';
const value = '5.556';
const dataIndex = 0;
const seriesLabel = timeSeriesChart.find(GlChartSeriesLabel);
Loading
Loading
@@ -129,13 +148,13 @@ describe('Time series component', () => {
});
});
 
describe('when series is of scatter type', () => {
describe('when series is of scatter type, for deployments', () => {
beforeEach(() => {
timeSeriesChart.vm.formatTooltipText(generateSeriesData('scatter'));
});
 
it('formats tooltip title', () => {
expect(timeSeriesChart.vm.tooltip.title).toBe('31 May 2017, 9:23PM');
expect(timeSeriesChart.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM');
});
 
it('formats tooltip sha', () => {
Loading
Loading
@@ -274,9 +293,9 @@ describe('Time series component', () => {
describe('scatterSeries', () => {
it('utilizes deployment data', () => {
expect(timeSeriesChart.vm.scatterSeries.data).toEqual([
['2017-05-31T21:23:37.881Z', 0],
['2017-05-30T20:08:04.629Z', 0],
['2017-05-30T17:42:38.409Z', 0],
['2019-07-16T10:14:25.589Z', 0],
['2019-07-16T11:14:25.589Z', 0],
['2019-07-16T12:14:25.589Z', 0],
]);
 
expect(timeSeriesChart.vm.scatterSeries.symbolSize).toBe(14);
Loading
Loading
@@ -285,7 +304,7 @@ describe('Time series component', () => {
 
describe('yAxisLabel', () => {
it('constructs a label for the chart y-axis', () => {
expect(timeSeriesChart.vm.yAxisLabel).toBe('CPU');
expect(timeSeriesChart.vm.yAxisLabel).toBe('Memory Used per Pod');
});
});
});
Loading
Loading
@@ -318,6 +337,10 @@ describe('Time series component', () => {
timeSeriesAreaChart.vm.$nextTick(done);
});
 
afterEach(() => {
timeSeriesAreaChart.destroy();
});
it('is a Vue instance', () => {
expect(glChart.exists()).toBe(true);
expect(glChart.isVueInstance()).toBe(true);
Loading
Loading
@@ -343,6 +366,9 @@ describe('Time series component', () => {
});
 
describe('when tooltip is showing deployment data', () => {
const mockSha = 'mockSha';
const commitUrl = `${mockProjectDir}/commit/${mockSha}`;
beforeEach(done => {
timeSeriesAreaChart.vm.tooltip.isDeployment = true;
timeSeriesAreaChart.vm.$nextTick(done);
Loading
Loading
export const mockHost = 'http://test.host';
export const mockProjectDir = '/frontend-fixtures/environments-project';
 
export const anomalyDeploymentData = [
Loading
Loading
@@ -159,3 +160,171 @@ export const anomalyMockGraphData = {
},
],
};
export const deploymentData = [
{
id: 111,
iid: 3,
sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
commitUrl:
'http://test.host/frontend-fixtures/environments-project/commit/f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
ref: {
name: 'master',
},
created_at: '2019-07-16T10:14:25.589Z',
tag: false,
tagUrl: 'http://test.host/frontend-fixtures/environments-project/tags/false',
'last?': true,
},
{
id: 110,
iid: 2,
sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
commitUrl:
'http://test.host/frontend-fixtures/environments-project/commit/f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
ref: {
name: 'master',
},
created_at: '2019-07-16T11:14:25.589Z',
tag: false,
tagUrl: 'http://test.host/frontend-fixtures/environments-project/tags/false',
'last?': false,
},
{
id: 109,
iid: 1,
sha: '6511e58faafaa7ad2228990ec57f19d66f7db7c2',
commitUrl:
'http://test.host/frontend-fixtures/environments-project/commit/6511e58faafaa7ad2228990ec57f19d66f7db7c2',
ref: {
name: 'update2-readme',
},
created_at: '2019-07-16T12:14:25.589Z',
tag: false,
tagUrl: 'http://test.host/frontend-fixtures/environments-project/tags/false',
'last?': false,
},
];
export const metricsNewGroupsAPIResponse = [
{
group: 'System metrics (Kubernetes)',
priority: 5,
panels: [
{
title: 'Memory Usage (Pod average)',
type: 'area-chart',
y_label: 'Memory Used per Pod',
weight: 2,
metrics: [
{
id: 'system_metrics_kubernetes_container_memory_average',
query_range:
'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024',
label: 'Pod average',
unit: 'MB',
metric_id: 17,
prometheus_endpoint_path:
'/root/autodevops-deploy/environments/32/prometheus/api/v1/query_range?query=avg%28sum%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+by+%28job%29%29+without+%28job%29+%2F+count%28avg%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+without+%28job%29%29+%2F1024%2F1024',
appearance: {
line: {
width: 2,
},
},
},
],
},
],
},
];
export const mockedQueryResultPayload = {
metricId: '17_system_metrics_kubernetes_container_memory_average',
result: [
{
metric: {},
values: [
[1563272065.589, '10.396484375'],
[1563272125.589, '10.333984375'],
[1563272185.589, '10.333984375'],
[1563272245.589, '10.333984375'],
[1563272305.589, '10.333984375'],
[1563272365.589, '10.333984375'],
[1563272425.589, '10.38671875'],
[1563272485.589, '10.333984375'],
[1563272545.589, '10.333984375'],
[1563272605.589, '10.333984375'],
[1563272665.589, '10.333984375'],
[1563272725.589, '10.333984375'],
[1563272785.589, '10.396484375'],
[1563272845.589, '10.333984375'],
[1563272905.589, '10.333984375'],
[1563272965.589, '10.3984375'],
[1563273025.589, '10.337890625'],
[1563273085.589, '10.34765625'],
[1563273145.589, '10.337890625'],
[1563273205.589, '10.337890625'],
[1563273265.589, '10.337890625'],
[1563273325.589, '10.337890625'],
[1563273385.589, '10.337890625'],
[1563273445.589, '10.337890625'],
[1563273505.589, '10.337890625'],
[1563273565.589, '10.337890625'],
[1563273625.589, '10.337890625'],
[1563273685.589, '10.337890625'],
[1563273745.589, '10.337890625'],
[1563273805.589, '10.337890625'],
[1563273865.589, '10.390625'],
[1563273925.589, '10.390625'],
],
},
],
};
export const metricsGroupsAPIResponse = [
{
group: 'System metrics (Kubernetes)',
priority: 5,
panels: [
{
title: 'Memory Usage (Pod average)',
type: 'area-chart',
y_label: 'Memory Used per Pod',
weight: 2,
metrics: [
{
id: 'system_metrics_kubernetes_container_memory_average',
query_range:
'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024',
label: 'Pod average',
unit: 'MB',
metric_id: 17,
prometheus_endpoint_path:
'/root/autodevops-deploy/environments/32/prometheus/api/v1/query_range?query=avg%28sum%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+by+%28job%29%29+without+%28job%29+%2F+count%28avg%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+without+%28job%29%29+%2F1024%2F1024',
appearance: {
line: {
width: 2,
},
},
},
],
},
{
title: 'Core Usage (Total)',
type: 'area-chart',
y_label: 'Total Cores',
weight: 3,
metrics: [
{
id: 'system_metrics_kubernetes_container_cores_total',
query_range:
'avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job)',
label: 'Total',
unit: 'cores',
metric_id: 13,
},
],
},
],
},
];
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import { setTestTimeout } from 'helpers/timeout';
import axios from '~/lib/utils/axios_utils';
import PanelType from '~/monitoring/components/panel_type.vue';
import EmptyChart from '~/monitoring/components/charts/empty_chart.vue';
Loading
Loading
@@ -10,15 +11,17 @@ import { anomalyMockGraphData } from '../../frontend/monitoring/mock_data';
import { createStore } from '~/monitoring/stores';
 
global.IS_EE = true;
global.URL.createObjectURL = jest.fn(() => {});
global.URL.createObjectURL = jest.fn();
 
describe('Panel Type component', () => {
let axiosMock;
let store;
let panelType;
const dashboardWidth = 100;
const exampleText = 'example_text';
 
beforeEach(() => {
setTestTimeout(1000);
axiosMock = new AxiosMockAdapter(axios);
});
 
Loading
Loading
@@ -40,6 +43,7 @@ describe('Panel Type component', () => {
graphData: graphDataNoResult,
},
sync: false,
attachToDocument: true,
});
});
 
Loading
Loading
@@ -65,14 +69,13 @@ describe('Panel Type component', () => {
});
 
describe('when Graph data is available', () => {
const exampleText = 'example_text';
const propsData = {
clipboardText: exampleText,
dashboardWidth,
graphData: graphDataPrometheusQueryRange,
};
 
beforeEach(() => {
beforeEach(done => {
store = createStore();
panelType = shallowMount(PanelType, {
propsData,
Loading
Loading
@@ -80,6 +83,11 @@ describe('Panel Type component', () => {
sync: false,
attachToDocument: true,
});
panelType.vm.$nextTick(done);
});
afterEach(() => {
panelType.destroy();
});
 
describe('Time Series Chart panel type', () => {
Loading
Loading
@@ -110,4 +118,49 @@ describe('Panel Type component', () => {
});
});
});
describe('when downloading metrics data as CSV', () => {
beforeEach(done => {
graphDataPrometheusQueryRange.y_label = 'metric';
store = createStore();
panelType = shallowMount(PanelType, {
propsData: {
clipboardText: exampleText,
dashboardWidth,
graphData: graphDataPrometheusQueryRange,
},
store,
sync: false,
attachToDocument: true,
});
panelType.vm.$nextTick(done);
});
afterEach(() => {
panelType.destroy();
});
describe('csvText', () => {
it('converts metrics data from json to csv', () => {
const header = `timestamp,${graphDataPrometheusQueryRange.y_label}`;
const data = graphDataPrometheusQueryRange.queries[0].result[0].values;
const firstRow = `${data[0][0]},${data[0][1]}`;
const secondRow = `${data[1][0]},${data[1][1]}`;
expect(panelType.vm.csvText).toBe(`${header}\r\n${firstRow}\r\n${secondRow}\r\n`);
});
});
describe('downloadCsv', () => {
it('produces a link with a Blob', () => {
expect(global.URL.createObjectURL).toHaveBeenLastCalledWith(expect.any(Blob));
expect(global.URL.createObjectURL).toHaveBeenLastCalledWith(
expect.objectContaining({
size: panelType.vm.csvText.length,
type: 'text/plain',
}),
);
});
});
});
});
Loading
Loading
@@ -7,11 +7,12 @@ import Dashboard from '~/monitoring/components/dashboard.vue';
import * as types from '~/monitoring/stores/mutation_types';
import { createStore } from '~/monitoring/stores';
import axios from '~/lib/utils/axios_utils';
import MonitoringMock, {
import {
metricsGroupsAPIResponse,
mockedQueryResultPayload,
mockedQueryResultPayloadCoresTotal,
mockApiEndpoint,
environmentData,
singleGroupResponse,
dashboardGitResponse,
} from '../mock_data';
 
Loading
Loading
@@ -44,12 +45,33 @@ const resetSpy = spy => {
 
export default propsData;
 
function setupComponentStore(component) {
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
metricsGroupsAPIResponse,
);
// Load 2 panels to the dashboard
component.$store.commit(
`monitoringDashboard/${types.SET_QUERY_RESULT}`,
mockedQueryResultPayload,
);
component.$store.commit(
`monitoringDashboard/${types.SET_QUERY_RESULT}`,
mockedQueryResultPayloadCoresTotal,
);
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
environmentData,
);
}
describe('Dashboard', () => {
let DashboardComponent;
let mock;
let store;
let component;
let mockGraphData;
 
beforeEach(() => {
setFixtures(`
Loading
Loading
@@ -123,25 +145,6 @@ describe('Dashboard', () => {
});
});
 
it('hides the legend when showLegend is false', done => {
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showLegend: false,
},
store,
});
setTimeout(() => {
expect(component.showEmptyState).toEqual(false);
expect(component.$el.querySelector('.legend-group')).toEqual(null);
expect(component.$el.querySelector('.prometheus-graph-group')).toBeTruthy();
done();
});
});
it('hides the group panels when showPanels is false', done => {
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
Loading
Loading
@@ -153,52 +156,66 @@ describe('Dashboard', () => {
store,
});
 
setTimeout(() => {
expect(component.showEmptyState).toEqual(false);
expect(component.$el.querySelector('.prometheus-panel')).toEqual(null);
expect(component.$el.querySelector('.prometheus-graph-group')).toBeTruthy();
done();
});
setupComponentStore(component);
Vue.nextTick()
.then(() => {
expect(component.showEmptyState).toEqual(false);
expect(component.$el.querySelector('.prometheus-panel')).toEqual(null);
expect(component.$el.querySelector('.prometheus-graph-group')).toBeTruthy();
done();
})
.catch(done.fail);
});
 
it('renders the environments dropdown with a number of environments', done => {
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
},
store,
describe('when all the requests have been commited by the store', () => {
beforeEach(() => {
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
},
store,
});
setupComponentStore(component);
});
 
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
environmentData,
);
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
singleGroupResponse,
);
it('renders the environments dropdown with a number of environments', done => {
Vue.nextTick()
.then(() => {
const dropdownMenuEnvironments = component.$el.querySelectorAll(
'.js-environments-dropdown .dropdown-item',
);
 
Vue.nextTick()
.then(() => {
const dropdownMenuEnvironments = component.$el.querySelectorAll(
'.js-environments-dropdown .dropdown-item',
);
expect(component.environments.length).toEqual(environmentData.length);
expect(dropdownMenuEnvironments.length).toEqual(component.environments.length);
 
expect(component.environments.length).toEqual(environmentData.length);
expect(dropdownMenuEnvironments.length).toEqual(component.environments.length);
Array.from(dropdownMenuEnvironments).forEach((value, index) => {
if (environmentData[index].metrics_path) {
expect(value).toHaveAttr('href', environmentData[index].metrics_path);
}
});
 
Array.from(dropdownMenuEnvironments).forEach((value, index) => {
if (environmentData[index].metrics_path) {
expect(value).toHaveAttr('href', environmentData[index].metrics_path);
}
});
done();
})
.catch(done.fail);
});
 
done();
})
.catch(done.fail);
it('renders the environments dropdown with a single active element', done => {
Vue.nextTick()
.then(() => {
const dropdownItems = component.$el.querySelectorAll(
'.js-environments-dropdown .dropdown-item.active',
);
expect(dropdownItems.length).toEqual(1);
done();
})
.catch(done.fail);
});
});
 
it('hides the environments dropdown list when there is no environments', done => {
Loading
Loading
@@ -207,15 +224,17 @@ describe('Dashboard', () => {
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
},
store,
});
 
component.$store.commit(`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, []);
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
singleGroupResponse,
metricsGroupsAPIResponse,
);
component.$store.commit(
`monitoringDashboard/${types.SET_QUERY_RESULT}`,
mockedQueryResultPayload,
);
 
Vue.nextTick()
Loading
Loading
@@ -230,7 +249,7 @@ describe('Dashboard', () => {
.catch(done.fail);
});
 
it('renders the environments dropdown with a single active element', done => {
it('renders the datetimepicker dropdown', done => {
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
Loading
Loading
@@ -241,64 +260,16 @@ describe('Dashboard', () => {
store,
});
 
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
environmentData,
);
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
singleGroupResponse,
);
setupComponentStore(component);
 
Vue.nextTick()
.then(() => {
const dropdownItems = component.$el.querySelectorAll(
'.js-environments-dropdown .dropdown-item.active',
);
expect(dropdownItems.length).toEqual(1);
expect(component.$el.querySelector('.js-time-window-dropdown')).not.toBeNull();
done();
})
.catch(done.fail);
});
 
it('hides the dropdown', done => {
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
environmentsEndpoint: '',
},
store,
});
Vue.nextTick(() => {
const dropdownIsActiveElement = component.$el.querySelectorAll('.environments');
expect(dropdownIsActiveElement.length).toEqual(0);
done();
});
});
it('renders the datetimepicker dropdown', done => {
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
},
store,
});
setTimeout(() => {
expect(component.$el.querySelector('.js-time-window-dropdown')).not.toBeNull();
done();
});
});
it('fetches the metrics data with proper time window', done => {
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
Loading
Loading
@@ -347,14 +318,21 @@ describe('Dashboard', () => {
el: document.querySelector('.prometheus-graphs'),
propsData: { ...propsData, hasMetrics: true },
store,
sync: false,
});
 
setTimeout(() => {
const selectedTimeWindow = component.$el.querySelector('.js-time-window-dropdown .active');
setupComponentStore(component);
 
expect(selectedTimeWindow.textContent.trim()).toEqual('30 minutes');
done();
});
Vue.nextTick()
.then(() => {
const selectedTimeWindow = component.$el.querySelector(
'.js-time-window-dropdown .active',
);
expect(selectedTimeWindow.textContent.trim()).toEqual('30 minutes');
done();
})
.catch(done.fail);
});
 
it('shows an error message if invalid url parameters are passed', done => {
Loading
Loading
@@ -381,29 +359,36 @@ describe('Dashboard', () => {
describe('drag and drop function', () => {
let wrapper;
let expectedPanelCount; // also called metrics, naming to be improved: https://gitlab.com/gitlab-org/gitlab/issues/31565
const findDraggables = () => wrapper.findAll(VueDraggable);
const findEnabledDraggables = () => findDraggables().filter(f => !f.attributes('disabled'));
const findDraggablePanels = () => wrapper.findAll('.js-draggable-panel');
const findRearrangeButton = () => wrapper.find('.js-rearrange-button');
 
beforeEach(done => {
beforeEach(() => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
expectedPanelCount = metricsGroupsAPIResponse.data.reduce(
(acc, d) => d.metrics.length + acc,
expectedPanelCount = metricsGroupsAPIResponse.reduce(
(acc, group) => group.panels.length + acc,
0,
);
store.dispatch('monitoringDashboard/setFeatureFlags', { additionalPanelTypesEnabled: true });
});
 
beforeEach(done => {
wrapper = shallowMount(DashboardComponent, {
localVue,
sync: false,
propsData: { ...propsData, hasMetrics: true },
store,
attachToDocument: true,
});
 
// not using $nextTicket becuase we must wait for the dashboard
// to be populated with the mock data results.
setTimeout(done);
setupComponentStore(wrapper.vm);
wrapper.vm.$nextTick(done);
});
afterEach(() => {
wrapper.destroy();
});
 
it('wraps vuedraggable', () => {
Loading
Loading
@@ -444,7 +429,7 @@ describe('Dashboard', () => {
 
it('metrics can be swapped', done => {
const firstDraggable = findDraggables().at(0);
const mockMetrics = [...metricsGroupsAPIResponse.data[0].metrics];
const mockMetrics = [...metricsGroupsAPIResponse[0].panels];
const value = () => firstDraggable.props('value');
 
expect(value().length).toBe(mockMetrics.length);
Loading
Loading
@@ -486,10 +471,6 @@ describe('Dashboard', () => {
});
});
});
afterEach(() => {
wrapper.destroy();
});
});
 
// https://gitlab.com/gitlab-org/gitlab-ce/issues/66922
Loading
Loading
@@ -577,24 +558,7 @@ describe('Dashboard', () => {
store,
});
 
component.$store.dispatch('monitoringDashboard/setFeatureFlags', {
prometheusEndpoint: false,
});
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
environmentData,
);
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
singleGroupResponse,
);
component.$store.commit(
`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`,
dashboardGitResponse,
);
setupComponentStore(component);
 
return Vue.nextTick().then(() => {
promPanel = component.$el.querySelector('.prometheus-panel');
Loading
Loading
@@ -707,20 +671,6 @@ describe('Dashboard', () => {
store,
});
 
component.$store.dispatch('monitoringDashboard/setFeatureFlags', {
prometheusEndpoint: false,
});
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
environmentData,
);
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
singleGroupResponse,
);
component.$store.commit(
`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`,
dashboardGitResponse,
Loading
Loading
@@ -736,38 +686,4 @@ describe('Dashboard', () => {
});
});
});
describe('when downloading metrics data as CSV', () => {
beforeEach(() => {
component = new DashboardComponent({
propsData: {
...propsData,
},
store,
});
store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
MonitoringMock.data,
);
[
mockGraphData,
] = component.$store.state.monitoringDashboard.dashboard.panel_groups[0].metrics;
});
describe('csvText', () => {
it('converts metrics data from json to csv', () => {
const header = `timestamp,${mockGraphData.y_label}`;
const data = mockGraphData.queries[0].result[0].values;
const firstRow = `${data[0][0]},${data[0][1]}`;
expect(component.csvText(mockGraphData)).toMatch(`^${header}\r\n${firstRow}`);
});
});
describe('downloadCsv', () => {
it('produces a link with a Blob', () => {
expect(component.downloadCsv(mockGraphData)).toContain(`blob:`);
});
});
});
});
This diff is collapsed.
Loading
Loading
@@ -317,7 +317,7 @@ describe('Monitoring store actions', () => {
const metric = metricsDashboardResponse.dashboard.panel_groups[0].panels[0].metrics[0];
const state = storeState();
 
const data = metricsGroupsAPIResponse.data[0].metrics[0].queries[0];
const data = metricsGroupsAPIResponse[0].panels[0].metrics[0];
const response = { data };
mock.onGet('http://test').reply(200, response);
 
Loading
Loading
Loading
Loading
@@ -21,79 +21,46 @@ describe('Monitoring mutations', () => {
 
beforeEach(() => {
stateCopy.dashboard.panel_groups = [];
groups = metricsGroupsAPIResponse.data;
groups = metricsGroupsAPIResponse;
});
 
it('adds a key to the group', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
 
expect(stateCopy.dashboard.panel_groups[0].key).toBe('kubernetes-0');
expect(stateCopy.dashboard.panel_groups[1].key).toBe('nginx-1');
expect(stateCopy.dashboard.panel_groups[0].key).toBe('system-metrics-kubernetes--0');
});
 
it('normalizes values', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
 
const expectedTimestamp = '2017-05-25T08:22:34.925Z';
const expectedValue = 8.0390625;
const [
timestamp,
value,
] = stateCopy.dashboard.panel_groups[0].metrics[0].queries[0].result[0].values[0];
const expectedLabel = 'Pod average';
const { label, query_range } = stateCopy.dashboard.panel_groups[0].metrics[0].metrics[0];
 
expect(timestamp).toEqual(expectedTimestamp);
expect(value).toEqual(expectedValue);
expect(label).toEqual(expectedLabel);
expect(query_range.length).toBeGreaterThan(0);
});
 
it('contains two groups that contains, one of which has two queries sorted by priority', () => {
it('contains one group, which it has two panels and one metrics property', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
 
expect(stateCopy.dashboard.panel_groups).toBeDefined();
expect(stateCopy.dashboard.panel_groups.length).toEqual(2);
expect(stateCopy.dashboard.panel_groups[0].metrics.length).toEqual(2);
expect(stateCopy.dashboard.panel_groups.length).toEqual(1);
expect(stateCopy.dashboard.panel_groups[0].panels.length).toEqual(2);
expect(stateCopy.dashboard.panel_groups[0].panels[0].metrics.length).toEqual(1);
expect(stateCopy.dashboard.panel_groups[0].panels[1].metrics.length).toEqual(1);
});
 
it('assigns queries a metric id', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
 
expect(stateCopy.dashboard.panel_groups[1].metrics[0].queries[0].metricId).toEqual('100');
expect(stateCopy.dashboard.panel_groups[0].metrics[0].queries[0].metricId).toEqual(
'17_system_metrics_kubernetes_container_memory_average',
);
});
 
it('removes the data if all the values from a query are not defined', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
expect(stateCopy.dashboard.panel_groups[1].metrics[0].queries[0].result.length).toEqual(0);
});
it('assigns metric id of null if metric has no id', () => {
stateCopy.dashboard.panel_groups = [];
const noId = groups.map(group => ({
...group,
...{
metrics: group.metrics.map(metric => {
const { id, ...metricWithoutId } = metric;
return metricWithoutId;
}),
},
}));
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, noId);
stateCopy.dashboard.panel_groups.forEach(group => {
group.metrics.forEach(metric => {
expect(metric.queries.every(query => query.metricId === null)).toBe(true);
});
});
});
describe('dashboard endpoint enabled', () => {
describe('dashboard endpoint', () => {
const dashboardGroups = metricsDashboardResponse.dashboard.panel_groups;
 
beforeEach(() => {
stateCopy.useDashboardEndpoint = true;
});
it('aliases group panels to metrics for backwards compatibility', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, dashboardGroups);
 
Loading
Loading
@@ -143,7 +110,6 @@ describe('Monitoring mutations', () => {
const result = [{ values: [[0, 1], [1, 1], [1, 3]] }];
 
beforeEach(() => {
stateCopy.useDashboardEndpoint = true;
const dashboardGroups = metricsDashboardResponse.dashboard.panel_groups;
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, dashboardGroups);
});
Loading
Loading
Loading
Loading
@@ -48,6 +48,10 @@ describe Gitlab::UsageData do
create(:clusters_applications_knative, :installed, cluster: gcp_cluster)
create(:clusters_applications_elastic_stack, :installed, cluster: gcp_cluster)
 
create(:grafana_integration, project: projects[0], enabled: true)
create(:grafana_integration, project: projects[1], enabled: true)
create(:grafana_integration, project: projects[2], enabled: false)
ProjectFeature.first.update_attribute('repository_access_level', 0)
end
 
Loading
Loading
@@ -140,6 +144,7 @@ describe Gitlab::UsageData do
clusters_applications_knative
clusters_applications_elastic_stack
in_review_folder
grafana_integrated_projects
groups
issues
issues_with_associated_zoom_link
Loading
Loading
@@ -221,6 +226,7 @@ describe Gitlab::UsageData do
expect(count_data[:clusters_applications_runner]).to eq(1)
expect(count_data[:clusters_applications_knative]).to eq(1)
expect(count_data[:clusters_applications_elastic_stack]).to eq(1)
expect(count_data[:grafana_integrated_projects]).to eq(2)
end
 
it 'works when queries time out' do
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment