diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-24 21:09:05 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-24 21:09:05 +0300 |
commit | c2367afbf57ebc65d5b78a743b5d6a91f0aece9f (patch) | |
tree | 165c2c54bf72ab3a3a9417d97f63ece5c9eba9f5 /spec/frontend/monitoring | |
parent | 51a9512965d86e3094968fa514e4ae8a96d38cf3 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/monitoring')
-rw-r--r-- | spec/frontend/monitoring/components/charts/time_series_spec.js | 813 | ||||
-rw-r--r-- | spec/frontend/monitoring/components/dashboard_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/monitoring/mock_data.js | 42 | ||||
-rw-r--r-- | spec/frontend/monitoring/store/mutations_spec.js | 3 |
4 files changed, 483 insertions, 377 deletions
diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js index 49f2a70a8b2..4dd376faac0 100644 --- a/spec/frontend/monitoring/components/charts/time_series_spec.js +++ b/spec/frontend/monitoring/components/charts/time_series_spec.js @@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils'; import { setTestTimeout } from 'helpers/timeout'; import { GlLink } from '@gitlab/ui'; import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts'; +import { cloneDeep } from 'lodash'; import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper'; import { chartColorValues } from '~/monitoring/constants'; import { createStore } from '~/monitoring/stores'; @@ -32,501 +33,563 @@ jest.mock('~/lib/utils/icon_utils', () => ({ describe('Time series component', () => { let mockGraphData; - let makeTimeSeriesChart; let store; - beforeEach(() => { - setTestTimeout(1000); - - store = createStore(); - - store.commit( - `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, - metricsDashboardPayload, - ); - - store.commit(`monitoringDashboard/${types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS}`, deploymentData); + const makeTimeSeriesChart = (graphData, type) => + shallowMount(TimeSeries, { + propsData: { + graphData: { ...graphData, type }, + deploymentData: store.state.monitoringDashboard.deploymentData, + projectPath: `${mockHost}${mockProjectDir}`, + }, + store, + }); - // Mock data contains 2 panel groups, with 1 and 2 panels respectively - store.commit( - `monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`, - mockedQueryResultPayload, - ); + describe('With a single time series', () => { + beforeEach(() => { + setTestTimeout(1000); - // Pick the second panel group and the first panel in it - [mockGraphData] = store.state.monitoringDashboard.dashboard.panel_groups[1].panels; + store = createStore(); - makeTimeSeriesChart = (graphData, type) => - shallowMount(TimeSeries, { - propsData: { - graphData: { ...graphData, type }, - deploymentData: store.state.monitoringDashboard.deploymentData, - projectPath: `${mockHost}${mockProjectDir}`, - }, - store, - }); - }); + store.commit( + `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, + metricsDashboardPayload, + ); - describe('general functions', () => { - let timeSeriesChart; + store.commit(`monitoringDashboard/${types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS}`, deploymentData); - const findChart = () => timeSeriesChart.find({ ref: 'chart' }); + // Mock data contains 2 panel groups, with 1 and 2 panels respectively + store.commit( + `monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`, + mockedQueryResultPayload, + ); - beforeEach(done => { - timeSeriesChart = makeTimeSeriesChart(mockGraphData, 'area-chart'); - timeSeriesChart.vm.$nextTick(done); + // Pick the second panel group and the first panel in it + [mockGraphData] = store.state.monitoringDashboard.dashboard.panel_groups[1].panels; }); - it('allows user to override max value label text using prop', () => { - timeSeriesChart.setProps({ legendMaxText: 'legendMaxText' }); - - return timeSeriesChart.vm.$nextTick().then(() => { - expect(timeSeriesChart.props().legendMaxText).toBe('legendMaxText'); - }); - }); + describe('general functions', () => { + let timeSeriesChart; - it('allows user to override average value label text using prop', () => { - timeSeriesChart.setProps({ legendAverageText: 'averageText' }); + const findChart = () => timeSeriesChart.find({ ref: 'chart' }); - return timeSeriesChart.vm.$nextTick().then(() => { - expect(timeSeriesChart.props().legendAverageText).toBe('averageText'); + beforeEach(done => { + timeSeriesChart = makeTimeSeriesChart(mockGraphData, 'area-chart'); + timeSeriesChart.vm.$nextTick(done); }); - }); - describe('events', () => { - describe('datazoom', () => { - let eChartMock; - let startValue; - let endValue; - - beforeEach(done => { - eChartMock = { - handlers: {}, - getOption: () => ({ - dataZoom: [ - { - startValue, - endValue, - }, - ], - }), - off: jest.fn(eChartEvent => { - delete eChartMock.handlers[eChartEvent]; - }), - on: jest.fn((eChartEvent, fn) => { - eChartMock.handlers[eChartEvent] = fn; - }), - }; - - timeSeriesChart = makeTimeSeriesChart(mockGraphData); - timeSeriesChart.vm.$nextTick(() => { - findChart().vm.$emit('created', eChartMock); - done(); - }); - }); + it('allows user to override max value label text using prop', () => { + timeSeriesChart.setProps({ legendMaxText: 'legendMaxText' }); - it('handles datazoom event from chart', () => { - startValue = 1577836800000; // 2020-01-01T00:00:00.000Z - endValue = 1577840400000; // 2020-01-01T01:00:00.000Z - eChartMock.handlers.datazoom(); - - expect(timeSeriesChart.emitted('datazoom')).toHaveLength(1); - expect(timeSeriesChart.emitted('datazoom')[0]).toEqual([ - { - start: new Date(startValue).toISOString(), - end: new Date(endValue).toISOString(), - }, - ]); + return timeSeriesChart.vm.$nextTick().then(() => { + expect(timeSeriesChart.props().legendMaxText).toBe('legendMaxText'); }); }); - }); - describe('methods', () => { - describe('formatTooltipText', () => { - let mockDate; - let mockCommitUrl; - let generateSeriesData; + it('allows user to override average value label text using prop', () => { + timeSeriesChart.setProps({ legendAverageText: 'averageText' }); - 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, - }); + return timeSeriesChart.vm.$nextTick().then(() => { + expect(timeSeriesChart.props().legendAverageText).toBe('averageText'); }); + }); - it('does not throw error if data point is outside the zoom range', () => { - const seriesDataWithoutValue = generateSeriesData('line'); - expect( - timeSeriesChart.vm.formatTooltipText({ - ...seriesDataWithoutValue, - seriesData: seriesDataWithoutValue.seriesData.map(data => ({ - ...data, - value: undefined, - })), - }), - ).toBeUndefined(); - }); + describe('events', () => { + describe('datazoom', () => { + let eChartMock; + let startValue; + let endValue; - describe('when series is of line type', () => { beforeEach(done => { - timeSeriesChart.vm.formatTooltipText(generateSeriesData('line')); - timeSeriesChart.vm.$nextTick(done); - }); + eChartMock = { + handlers: {}, + getOption: () => ({ + dataZoom: [ + { + startValue, + endValue, + }, + ], + }), + off: jest.fn(eChartEvent => { + delete eChartMock.handlers[eChartEvent]; + }), + on: jest.fn((eChartEvent, fn) => { + eChartMock.handlers[eChartEvent] = fn; + }), + }; - it('formats tooltip title', () => { - expect(timeSeriesChart.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM'); + timeSeriesChart = makeTimeSeriesChart(mockGraphData); + timeSeriesChart.vm.$nextTick(() => { + findChart().vm.$emit('created', eChartMock); + done(); + }); }); - it('formats tooltip content', () => { - const name = 'Pod average'; - const value = '5.556'; - const dataIndex = 0; - const seriesLabel = timeSeriesChart.find(GlChartSeriesLabel); + it('handles datazoom event from chart', () => { + startValue = 1577836800000; // 2020-01-01T00:00:00.000Z + endValue = 1577840400000; // 2020-01-01T01:00:00.000Z + eChartMock.handlers.datazoom(); - expect(seriesLabel.vm.color).toBe(''); - expect(shallowWrapperContainsSlotText(seriesLabel, 'default', name)).toBe(true); - expect(timeSeriesChart.vm.tooltip.content).toEqual([ - { name, value, dataIndex, color: undefined }, + expect(timeSeriesChart.emitted('datazoom')).toHaveLength(1); + expect(timeSeriesChart.emitted('datazoom')[0]).toEqual([ + { + start: new Date(startValue).toISOString(), + end: new Date(endValue).toISOString(), + }, ]); - - expect( - shallowWrapperContainsSlotText( - timeSeriesChart.find(GlAreaChart), - 'tooltipContent', - value, - ), - ).toBe(true); }); }); + }); + + describe('methods', () => { + describe('formatTooltipText', () => { + let mockDate; + let mockCommitUrl; + let generateSeriesData; - describe('when series is of scatter type, for deployments', () => { beforeEach(() => { - timeSeriesChart.vm.formatTooltipText(generateSeriesData('scatter')); + 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, + }); }); - it('formats tooltip title', () => { - expect(timeSeriesChart.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM'); + it('does not throw error if data point is outside the zoom range', () => { + const seriesDataWithoutValue = generateSeriesData('line'); + expect( + timeSeriesChart.vm.formatTooltipText({ + ...seriesDataWithoutValue, + seriesData: seriesDataWithoutValue.seriesData.map(data => ({ + ...data, + value: undefined, + })), + }), + ).toBeUndefined(); }); - it('formats tooltip sha', () => { - expect(timeSeriesChart.vm.tooltip.sha).toBe('f5bcd1d9'); + describe('when series is of line type', () => { + beforeEach(done => { + timeSeriesChart.vm.formatTooltipText(generateSeriesData('line')); + timeSeriesChart.vm.$nextTick(done); + }); + + it('formats tooltip title', () => { + expect(timeSeriesChart.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM'); + }); + + it('formats tooltip content', () => { + const name = 'Pod average'; + const value = '5.556'; + const dataIndex = 0; + const seriesLabel = timeSeriesChart.find(GlChartSeriesLabel); + + expect(seriesLabel.vm.color).toBe(''); + expect(shallowWrapperContainsSlotText(seriesLabel, 'default', name)).toBe(true); + expect(timeSeriesChart.vm.tooltip.content).toEqual([ + { name, value, dataIndex, color: undefined }, + ]); + + expect( + shallowWrapperContainsSlotText( + timeSeriesChart.find(GlAreaChart), + 'tooltipContent', + value, + ), + ).toBe(true); + }); }); - it('formats tooltip commit url', () => { - expect(timeSeriesChart.vm.tooltip.commitUrl).toBe(mockCommitUrl); + 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('16 Jul 2019, 10:14AM'); + }); + + it('formats tooltip sha', () => { + expect(timeSeriesChart.vm.tooltip.sha).toBe('f5bcd1d9'); + }); + + it('formats tooltip commit url', () => { + expect(timeSeriesChart.vm.tooltip.commitUrl).toBe(mockCommitUrl); + }); }); }); - }); - describe('setSvg', () => { - const mockSvgName = 'mockSvgName'; + describe('setSvg', () => { + const mockSvgName = 'mockSvgName'; - beforeEach(done => { - timeSeriesChart.vm.setSvg(mockSvgName); - timeSeriesChart.vm.$nextTick(done); - }); + beforeEach(done => { + timeSeriesChart.vm.setSvg(mockSvgName); + timeSeriesChart.vm.$nextTick(done); + }); - it('gets svg path content', () => { - expect(iconUtils.getSvgIconPathContent).toHaveBeenCalledWith(mockSvgName); - }); + it('gets svg path content', () => { + expect(iconUtils.getSvgIconPathContent).toHaveBeenCalledWith(mockSvgName); + }); - it('sets svg path content', () => { - timeSeriesChart.vm.$nextTick(() => { - expect(timeSeriesChart.vm.svgs[mockSvgName]).toBe(`path://${mockSvgPathContent}`); + it('sets svg path content', () => { + timeSeriesChart.vm.$nextTick(() => { + expect(timeSeriesChart.vm.svgs[mockSvgName]).toBe(`path://${mockSvgPathContent}`); + }); }); - }); - it('contains an svg object within an array to properly render icon', () => { - timeSeriesChart.vm.$nextTick(() => { - expect(timeSeriesChart.vm.chartOptions.dataZoom).toEqual([ - { - handleIcon: `path://${mockSvgPathContent}`, - }, - ]); + it('contains an svg object within an array to properly render icon', () => { + timeSeriesChart.vm.$nextTick(() => { + expect(timeSeriesChart.vm.chartOptions.dataZoom).toEqual([ + { + handleIcon: `path://${mockSvgPathContent}`, + }, + ]); + }); }); }); - }); - describe('onResize', () => { - const mockWidth = 233; + describe('onResize', () => { + const mockWidth = 233; - beforeEach(() => { - jest.spyOn(Element.prototype, 'getBoundingClientRect').mockImplementation(() => ({ - width: mockWidth, - })); - timeSeriesChart.vm.onResize(); - }); + beforeEach(() => { + jest.spyOn(Element.prototype, 'getBoundingClientRect').mockImplementation(() => ({ + width: mockWidth, + })); + timeSeriesChart.vm.onResize(); + }); - it('sets area chart width', () => { - expect(timeSeriesChart.vm.width).toBe(mockWidth); + it('sets area chart width', () => { + expect(timeSeriesChart.vm.width).toBe(mockWidth); + }); }); }); - }); - describe('computed', () => { - const getChartOptions = () => findChart().props('option'); + describe('computed', () => { + const getChartOptions = () => findChart().props('option'); - describe('chartData', () => { - let chartData; - const seriesData = () => chartData[0]; + describe('chartData', () => { + let chartData; + const seriesData = () => chartData[0]; - beforeEach(() => { - ({ chartData } = timeSeriesChart.vm); - }); + beforeEach(() => { + ({ chartData } = timeSeriesChart.vm); + }); - it('utilizes all data points', () => { - const { values } = mockGraphData.metrics[0].result[0]; + it('utilizes all data points', () => { + const { values } = mockGraphData.metrics[0].result[0]; - expect(chartData.length).toBe(1); - expect(seriesData().data.length).toBe(values.length); - }); + expect(chartData.length).toBe(1); + expect(seriesData().data.length).toBe(values.length); + }); - it('creates valid data', () => { - const { data } = seriesData(); + it('creates valid data', () => { + const { data } = seriesData(); - expect( - data.filter( - ([time, value]) => new Date(time).getTime() > 0 && typeof value === 'number', - ).length, - ).toBe(data.length); - }); + expect( + data.filter( + ([time, value]) => new Date(time).getTime() > 0 && typeof value === 'number', + ).length, + ).toBe(data.length); + }); - it('formats line width correctly', () => { - expect(chartData[0].lineStyle.width).toBe(2); - }); + it('formats line width correctly', () => { + expect(chartData[0].lineStyle.width).toBe(2); + }); - it('formats line color correctly', () => { - expect(chartData[0].lineStyle.color).toBe(chartColorValues[0]); + it('formats line color correctly', () => { + expect(chartData[0].lineStyle.color).toBe(chartColorValues[0]); + }); }); - }); - describe('chartOptions', () => { - describe('are extended by `option`', () => { - const mockSeriesName = 'Extra series 1'; - const mockOption = { - option1: 'option1', - option2: 'option2', - }; - - it('arbitrary options', () => { - timeSeriesChart.setProps({ - option: mockOption, - }); + describe('chartOptions', () => { + describe('are extended by `option`', () => { + const mockSeriesName = 'Extra series 1'; + const mockOption = { + option1: 'option1', + option2: 'option2', + }; - return timeSeriesChart.vm.$nextTick().then(() => { - expect(getChartOptions()).toEqual(expect.objectContaining(mockOption)); - }); - }); + it('arbitrary options', () => { + timeSeriesChart.setProps({ + option: mockOption, + }); - it('additional series', () => { - timeSeriesChart.setProps({ - option: { - series: [ - { - name: mockSeriesName, - }, - ], - }, + return timeSeriesChart.vm.$nextTick().then(() => { + expect(getChartOptions()).toEqual(expect.objectContaining(mockOption)); + }); }); - return timeSeriesChart.vm.$nextTick().then(() => { - const optionSeries = getChartOptions().series; + it('additional series', () => { + timeSeriesChart.setProps({ + option: { + series: [ + { + name: mockSeriesName, + }, + ], + }, + }); + + return timeSeriesChart.vm.$nextTick().then(() => { + const optionSeries = getChartOptions().series; - expect(optionSeries.length).toEqual(2); - expect(optionSeries[0].name).toEqual(mockSeriesName); + expect(optionSeries.length).toEqual(2); + expect(optionSeries[0].name).toEqual(mockSeriesName); + }); }); - }); - it('additional y axis data', () => { - const mockCustomYAxisOption = { - name: 'Custom y axis label', - axisLabel: { - formatter: jest.fn(), - }, - }; + it('additional y axis data', () => { + const mockCustomYAxisOption = { + name: 'Custom y axis label', + axisLabel: { + formatter: jest.fn(), + }, + }; - timeSeriesChart.setProps({ - option: { - yAxis: mockCustomYAxisOption, - }, + timeSeriesChart.setProps({ + option: { + yAxis: mockCustomYAxisOption, + }, + }); + + return timeSeriesChart.vm.$nextTick().then(() => { + const { yAxis } = getChartOptions(); + + expect(yAxis[0]).toMatchObject(mockCustomYAxisOption); + }); }); - return timeSeriesChart.vm.$nextTick().then(() => { - const { yAxis } = getChartOptions(); + it('additional x axis data', () => { + const mockCustomXAxisOption = { + name: 'Custom x axis label', + }; + + timeSeriesChart.setProps({ + option: { + xAxis: mockCustomXAxisOption, + }, + }); + + return timeSeriesChart.vm.$nextTick().then(() => { + const { xAxis } = getChartOptions(); - expect(yAxis[0]).toMatchObject(mockCustomYAxisOption); + expect(xAxis).toMatchObject(mockCustomXAxisOption); + }); }); }); - it('additional x axis data', () => { - const mockCustomXAxisOption = { - name: 'Custom x axis label', - }; + describe('yAxis formatter', () => { + let dataFormatter; + let deploymentFormatter; - timeSeriesChart.setProps({ - option: { - xAxis: mockCustomXAxisOption, - }, + beforeEach(() => { + dataFormatter = getChartOptions().yAxis[0].axisLabel.formatter; + deploymentFormatter = getChartOptions().yAxis[1].axisLabel.formatter; }); - return timeSeriesChart.vm.$nextTick().then(() => { - const { xAxis } = getChartOptions(); + it('rounds to 3 decimal places', () => { + expect(dataFormatter(0.88888)).toBe('0.889'); + }); - expect(xAxis).toMatchObject(mockCustomXAxisOption); + it('deployment formatter is set as is required to display a tooltip', () => { + expect(deploymentFormatter).toEqual(expect.any(Function)); }); }); }); - describe('yAxis formatter', () => { - let dataFormatter; - let deploymentFormatter; + describe('deploymentSeries', () => { + it('utilizes deployment data', () => { + expect(timeSeriesChart.vm.deploymentSeries.yAxisIndex).toBe(1); // same as deployment y axis + expect(timeSeriesChart.vm.deploymentSeries.data).toEqual([ + ['2019-07-16T10:14:25.589Z', expect.any(Number)], + ['2019-07-16T11:14:25.589Z', expect.any(Number)], + ['2019-07-16T12:14:25.589Z', expect.any(Number)], + ]); - beforeEach(() => { - dataFormatter = getChartOptions().yAxis[0].axisLabel.formatter; - deploymentFormatter = getChartOptions().yAxis[1].axisLabel.formatter; + expect(timeSeriesChart.vm.deploymentSeries.symbolSize).toBe(14); }); + }); - it('rounds to 3 decimal places', () => { - expect(dataFormatter(0.88888)).toBe('0.889'); + describe('yAxisLabel', () => { + it('y axis is configured correctly', () => { + const { yAxis } = getChartOptions(); + + expect(yAxis).toHaveLength(2); + + const [dataAxis, deploymentAxis] = yAxis; + + expect(dataAxis.boundaryGap).toHaveLength(2); + expect(dataAxis.scale).toBe(true); + + expect(deploymentAxis.show).toBe(false); + expect(deploymentAxis.min).toEqual(expect.any(Number)); + expect(deploymentAxis.max).toEqual(expect.any(Number)); + expect(deploymentAxis.min).toBeLessThan(deploymentAxis.max); }); - it('deployment formatter is set as is required to display a tooltip', () => { - expect(deploymentFormatter).toEqual(expect.any(Function)); + it('constructs a label for the chart y-axis', () => { + const { yAxis } = getChartOptions(); + + expect(yAxis[0].name).toBe('Memory Used per Pod'); }); }); }); - describe('deploymentSeries', () => { - it('utilizes deployment data', () => { - expect(timeSeriesChart.vm.deploymentSeries.yAxisIndex).toBe(1); // same as deployment y axis - expect(timeSeriesChart.vm.deploymentSeries.data).toEqual([ - ['2019-07-16T10:14:25.589Z', expect.any(Number)], - ['2019-07-16T11:14:25.589Z', expect.any(Number)], - ['2019-07-16T12:14:25.589Z', expect.any(Number)], - ]); - - expect(timeSeriesChart.vm.deploymentSeries.symbolSize).toBe(14); - }); + afterEach(() => { + timeSeriesChart.destroy(); }); + }); - describe('yAxisLabel', () => { - it('y axis is configured correctly', () => { - const { yAxis } = getChartOptions(); + describe('wrapped components', () => { + const glChartComponents = [ + { + chartType: 'area-chart', + component: GlAreaChart, + }, + { + chartType: 'line-chart', + component: GlLineChart, + }, + ]; - expect(yAxis).toHaveLength(2); + glChartComponents.forEach(dynamicComponent => { + describe(`GitLab UI: ${dynamicComponent.chartType}`, () => { + let timeSeriesAreaChart; + const findChartComponent = () => timeSeriesAreaChart.find(dynamicComponent.component); - const [dataAxis, deploymentAxis] = yAxis; + beforeEach(done => { + timeSeriesAreaChart = makeTimeSeriesChart(mockGraphData, dynamicComponent.chartType); + timeSeriesAreaChart.vm.$nextTick(done); + }); - expect(dataAxis.boundaryGap).toHaveLength(2); - expect(dataAxis.scale).toBe(true); + afterEach(() => { + timeSeriesAreaChart.destroy(); + }); - expect(deploymentAxis.show).toBe(false); - expect(deploymentAxis.min).toEqual(expect.any(Number)); - expect(deploymentAxis.max).toEqual(expect.any(Number)); - expect(deploymentAxis.min).toBeLessThan(deploymentAxis.max); - }); + it('is a Vue instance', () => { + expect(findChartComponent().exists()).toBe(true); + expect(findChartComponent().isVueInstance()).toBe(true); + }); - it('constructs a label for the chart y-axis', () => { - const { yAxis } = getChartOptions(); + it('receives data properties needed for proper chart render', () => { + const props = findChartComponent().props(); - expect(yAxis[0].name).toBe('Memory Used per Pod'); - }); - }); - }); + expect(props.data).toBe(timeSeriesAreaChart.vm.chartData); + expect(props.option).toBe(timeSeriesAreaChart.vm.chartOptions); + expect(props.formatTooltipText).toBe(timeSeriesAreaChart.vm.formatTooltipText); + expect(props.thresholds).toBe(timeSeriesAreaChart.vm.thresholds); + }); - afterEach(() => { - timeSeriesChart.destroy(); - }); - }); + it('recieves a tooltip title', done => { + const mockTitle = 'mockTitle'; + timeSeriesAreaChart.vm.tooltip.title = mockTitle; - describe('wrapped components', () => { - const glChartComponents = [ - { - chartType: 'area-chart', - component: GlAreaChart, - }, - { - chartType: 'line-chart', - component: GlLineChart, - }, - ]; + timeSeriesAreaChart.vm.$nextTick(() => { + expect( + shallowWrapperContainsSlotText(findChartComponent(), 'tooltipTitle', mockTitle), + ).toBe(true); + done(); + }); + }); - glChartComponents.forEach(dynamicComponent => { - describe(`GitLab UI: ${dynamicComponent.chartType}`, () => { - let timeSeriesAreaChart; - const findChartComponent = () => timeSeriesAreaChart.find(dynamicComponent.component); + describe('when tooltip is showing deployment data', () => { + const mockSha = 'mockSha'; + const commitUrl = `${mockProjectDir}/-/commit/${mockSha}`; - beforeEach(done => { - timeSeriesAreaChart = makeTimeSeriesChart(mockGraphData, dynamicComponent.chartType); - timeSeriesAreaChart.vm.$nextTick(done); - }); + beforeEach(done => { + timeSeriesAreaChart.vm.tooltip.isDeployment = true; + timeSeriesAreaChart.vm.$nextTick(done); + }); - afterEach(() => { - timeSeriesAreaChart.destroy(); - }); + it('uses deployment title', () => { + expect( + shallowWrapperContainsSlotText(findChartComponent(), 'tooltipTitle', 'Deployed'), + ).toBe(true); + }); - it('is a Vue instance', () => { - expect(findChartComponent().exists()).toBe(true); - expect(findChartComponent().isVueInstance()).toBe(true); - }); + it('renders clickable commit sha in tooltip content', done => { + timeSeriesAreaChart.vm.tooltip.sha = mockSha; + timeSeriesAreaChart.vm.tooltip.commitUrl = commitUrl; - it('receives data properties needed for proper chart render', () => { - const props = findChartComponent().props(); + timeSeriesAreaChart.vm.$nextTick(() => { + const commitLink = timeSeriesAreaChart.find(GlLink); - expect(props.data).toBe(timeSeriesAreaChart.vm.chartData); - expect(props.option).toBe(timeSeriesAreaChart.vm.chartOptions); - expect(props.formatTooltipText).toBe(timeSeriesAreaChart.vm.formatTooltipText); - expect(props.thresholds).toBe(timeSeriesAreaChart.vm.thresholds); + expect(shallowWrapperContainsSlotText(commitLink, 'default', mockSha)).toBe(true); + expect(commitLink.attributes('href')).toEqual(commitUrl); + done(); + }); + }); + }); }); + }); + }); + }); - it('recieves a tooltip title', done => { - const mockTitle = 'mockTitle'; - timeSeriesAreaChart.vm.tooltip.title = mockTitle; + describe('with multiple time series', () => { + const mockedResultMultipleSeries = []; + const [, , panelData] = metricsDashboardPayload.panel_groups[1].panels; - timeSeriesAreaChart.vm.$nextTick(() => { - expect( - shallowWrapperContainsSlotText(findChartComponent(), 'tooltipTitle', mockTitle), - ).toBe(true); - done(); - }); - }); + for (let i = 0; i < panelData.metrics.length; i += 1) { + mockedResultMultipleSeries.push(cloneDeep(mockedQueryResultPayload)); + mockedResultMultipleSeries[ + i + ].metricId = `${panelData.metrics[i].metric_id}_${panelData.metrics[i].id}`; + } - describe('when tooltip is showing deployment data', () => { - const mockSha = 'mockSha'; - const commitUrl = `${mockProjectDir}/-/commit/${mockSha}`; + beforeEach(() => { + setTestTimeout(1000); - beforeEach(done => { - timeSeriesAreaChart.vm.tooltip.isDeployment = true; - timeSeriesAreaChart.vm.$nextTick(done); - }); + store = createStore(); - it('uses deployment title', () => { - expect( - shallowWrapperContainsSlotText(findChartComponent(), 'tooltipTitle', 'Deployed'), - ).toBe(true); - }); + store.commit( + `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, + metricsDashboardPayload, + ); - it('renders clickable commit sha in tooltip content', done => { - timeSeriesAreaChart.vm.tooltip.sha = mockSha; - timeSeriesAreaChart.vm.tooltip.commitUrl = commitUrl; + store.commit(`monitoringDashboard/${types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS}`, deploymentData); - timeSeriesAreaChart.vm.$nextTick(() => { - const commitLink = timeSeriesAreaChart.find(GlLink); + // Mock data contains the metric_id for a multiple time series panel + for (let i = 0; i < panelData.metrics.length; i += 1) { + store.commit( + `monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`, + mockedResultMultipleSeries[i], + ); + } - expect(shallowWrapperContainsSlotText(commitLink, 'default', mockSha)).toBe(true); - expect(commitLink.attributes('href')).toEqual(commitUrl); - done(); - }); - }); + // Pick the second panel group and the second panel in it + [, , mockGraphData] = store.state.monitoringDashboard.dashboard.panel_groups[1].panels; + }); + + describe('General functions', () => { + let timeSeriesChart; + + beforeEach(done => { + timeSeriesChart = makeTimeSeriesChart(mockGraphData, 'area-chart'); + timeSeriesChart.vm.$nextTick(done); + }); + + describe('computed', () => { + let chartData; + + beforeEach(() => { + ({ chartData } = timeSeriesChart.vm); + }); + + it('should contain different colors for each time series', () => { + expect(chartData[0].lineStyle.color).toBe('#1f78d1'); + expect(chartData[1].lineStyle.color).toBe('#1aaa55'); + expect(chartData[2].lineStyle.color).toBe('#fc9403'); + expect(chartData[3].lineStyle.color).toBe('#6d49cb'); + expect(chartData[4].lineStyle.color).toBe('#1f78d1'); }); }); }); diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js index 15c82242262..fcf70a1af63 100644 --- a/spec/frontend/monitoring/components/dashboard_spec.js +++ b/spec/frontend/monitoring/components/dashboard_spec.js @@ -22,7 +22,7 @@ import { } from '../mock_data'; const localVue = createLocalVue(); -const expectedPanelCount = 2; +const expectedPanelCount = 3; describe('Dashboard', () => { let store; diff --git a/spec/frontend/monitoring/mock_data.js b/spec/frontend/monitoring/mock_data.js index 4d83933f2b8..bad3962dd8f 100644 --- a/spec/frontend/monitoring/mock_data.js +++ b/spec/frontend/monitoring/mock_data.js @@ -513,6 +513,48 @@ export const metricsDashboardPayload = { }, ], }, + { + title: 'memories', + type: 'area-chart', + y_label: 'memories', + metrics: [ + { + id: 'metric_of_ages_1000', + label: 'memory_1000', + unit: 'count', + prometheus_endpoint_path: '/root', + metric_id: 20, + }, + { + id: 'metric_of_ages_1001', + label: 'memory_1000', + unit: 'count', + prometheus_endpoint_path: '/root', + metric_id: 21, + }, + { + id: 'metric_of_ages_1002', + label: 'memory_1000', + unit: 'count', + prometheus_endpoint_path: '/root', + metric_id: 22, + }, + { + id: 'metric_of_ages_1003', + label: 'memory_1000', + unit: 'count', + prometheus_endpoint_path: '/root', + metric_id: 23, + }, + { + id: 'metric_of_ages_1004', + label: 'memory_1004', + unit: 'count', + prometheus_endpoint_path: '/root', + metric_id: 24, + }, + ], + }, ], }, ], diff --git a/spec/frontend/monitoring/store/mutations_spec.js b/spec/frontend/monitoring/store/mutations_spec.js index d9aebafb9ec..3fb7b84fae5 100644 --- a/spec/frontend/monitoring/store/mutations_spec.js +++ b/spec/frontend/monitoring/store/mutations_spec.js @@ -50,9 +50,10 @@ describe('Monitoring mutations', () => { expect(groups[0].panels).toHaveLength(1); expect(groups[0].panels[0].metrics).toHaveLength(1); - expect(groups[1].panels).toHaveLength(2); + expect(groups[1].panels).toHaveLength(3); expect(groups[1].panels[0].metrics).toHaveLength(1); expect(groups[1].panels[1].metrics).toHaveLength(1); + expect(groups[1].panels[2].metrics).toHaveLength(5); }); it('assigns metrics a metric id', () => { mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, payload); |