debian-mirror-gitlab/spec/frontend/monitoring/components/charts/anomaly_spec.js

309 lines
9.2 KiB
JavaScript
Raw Normal View History

2020-01-01 13:55:28 +05:30
import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
2019-12-26 22:10:19 +05:30
import Anomaly from '~/monitoring/components/charts/anomaly.vue';
2021-03-11 19:13:27 +05:30
import MonitorTimeSeriesChart from '~/monitoring/components/charts/time_series.vue';
2019-12-26 22:10:19 +05:30
import { colorValues } from '~/monitoring/constants';
2020-07-28 23:09:34 +05:30
import { anomalyGraphData } from '../../graph_data';
2021-03-11 19:13:27 +05:30
import { anomalyDeploymentData, mockProjectDir } from '../../mock_data';
2019-12-26 22:10:19 +05:30
const mockProjectPath = `${TEST_HOST}${mockProjectDir}`;
2020-07-28 23:09:34 +05:30
const TEST_UPPER = 11;
const TEST_LOWER = 9;
2019-12-26 22:10:19 +05:30
describe('Anomaly chart component', () => {
let wrapper;
2021-03-08 18:12:59 +05:30
const setupAnomalyChart = (props) => {
2019-12-26 22:10:19 +05:30
wrapper = shallowMount(Anomaly, {
propsData: { ...props },
});
};
const findTimeSeries = () => wrapper.find(MonitorTimeSeriesChart);
const getTimeSeriesProps = () => findTimeSeries().props();
describe('wrapped monitor-time-series-chart component', () => {
2020-07-28 23:09:34 +05:30
const mockValues = ['10', '10', '10'];
const mockGraphData = anomalyGraphData(
{},
{
upper: mockValues.map(() => String(TEST_UPPER)),
values: mockValues,
lower: mockValues.map(() => String(TEST_LOWER)),
},
);
2019-12-26 22:10:19 +05:30
const inputThresholds = ['some threshold'];
beforeEach(() => {
setupAnomalyChart({
2020-07-28 23:09:34 +05:30
graphData: mockGraphData,
2019-12-26 22:10:19 +05:30
deploymentData: anomalyDeploymentData,
thresholds: inputThresholds,
projectPath: mockProjectPath,
});
});
2020-11-24 15:15:51 +05:30
it('renders correctly', () => {
2019-12-26 22:10:19 +05:30
expect(findTimeSeries().exists()).toBe(true);
});
describe('receives props correctly', () => {
describe('graph-data', () => {
it('receives a single "metric" series', () => {
const { graphData } = getTimeSeriesProps();
2020-01-01 13:55:28 +05:30
expect(graphData.metrics.length).toBe(1);
2019-12-26 22:10:19 +05:30
});
it('receives "metric" with all data', () => {
const { graphData } = getTimeSeriesProps();
2020-07-28 23:09:34 +05:30
const metric = graphData.metrics[0];
const expectedMetric = mockGraphData.metrics[0];
expect(metric).toEqual(expectedMetric);
2019-12-26 22:10:19 +05:30
});
it('receives the "metric" results', () => {
const { graphData } = getTimeSeriesProps();
2020-01-01 13:55:28 +05:30
const { result } = graphData.metrics[0];
2019-12-26 22:10:19 +05:30
const { values } = result[0];
2020-07-28 23:09:34 +05:30
expect(values).toEqual([
[expect.any(String), 10],
[expect.any(String), 10],
[expect.any(String), 10],
]);
2019-12-26 22:10:19 +05:30
});
});
describe('option', () => {
let option;
let series;
beforeEach(() => {
({ option } = getTimeSeriesProps());
({ series } = option);
});
it('contains a boundary band', () => {
expect(series).toEqual(expect.any(Array));
expect(series.length).toEqual(2); // 1 upper + 1 lower boundaries
expect(series[0].stack).toEqual(series[1].stack);
2021-03-08 18:12:59 +05:30
series.forEach((s) => {
2019-12-26 22:10:19 +05:30
expect(s.type).toBe('line');
expect(s.lineStyle.width).toBe(0);
expect(s.lineStyle.color).toMatch(/rgba\(.+\)/);
expect(s.lineStyle.color).toMatch(s.color);
expect(s.symbol).toEqual('none');
});
});
it('upper boundary values are stacked on top of lower boundary', () => {
const [lowerSeries, upperSeries] = series;
2020-07-28 23:09:34 +05:30
lowerSeries.data.forEach(([, y]) => {
expect(y).toBeCloseTo(TEST_LOWER);
2019-12-26 22:10:19 +05:30
});
2020-07-28 23:09:34 +05:30
upperSeries.data.forEach(([, y]) => {
expect(y).toBeCloseTo(TEST_UPPER - TEST_LOWER);
2019-12-26 22:10:19 +05:30
});
});
});
describe('series-config', () => {
let seriesConfig;
beforeEach(() => {
({ seriesConfig } = getTimeSeriesProps());
});
it('display symbols is enabled', () => {
expect(seriesConfig).toEqual(
expect.objectContaining({
type: 'line',
symbol: 'circle',
showSymbol: true,
symbolSize: expect.any(Function),
itemStyle: {
color: expect.any(Function),
},
}),
);
});
2020-07-28 23:09:34 +05:30
2019-12-26 22:10:19 +05:30
it('does not display anomalies', () => {
const { symbolSize, itemStyle } = seriesConfig;
2020-07-28 23:09:34 +05:30
mockValues.forEach((v, dataIndex) => {
2019-12-26 22:10:19 +05:30
const size = symbolSize(null, { dataIndex });
const color = itemStyle.color({ dataIndex });
// normal color and small size
expect(size).toBeCloseTo(0);
expect(color).toBe(colorValues.primaryColor);
});
});
it('can format y values (to use in tooltips)', () => {
2020-07-28 23:09:34 +05:30
mockValues.forEach((v, dataIndex) => {
const formatted = wrapper.vm.yValueFormatted(0, dataIndex);
expect(parseFloat(formatted)).toEqual(parseFloat(v));
});
2019-12-26 22:10:19 +05:30
});
});
describe('inherited properties', () => {
it('"deployment-data" keeps the same value', () => {
const { deploymentData } = getTimeSeriesProps();
expect(deploymentData).toEqual(anomalyDeploymentData);
});
it('"thresholds" keeps the same value', () => {
const { thresholds } = getTimeSeriesProps();
expect(thresholds).toEqual(inputThresholds);
});
it('"projectPath" keeps the same value', () => {
const { projectPath } = getTimeSeriesProps();
expect(projectPath).toEqual(mockProjectPath);
});
});
});
});
describe('with no boundary data', () => {
2020-07-28 23:09:34 +05:30
const noBoundaryData = anomalyGraphData(
{},
{
upper: [],
values: ['10', '10', '10'],
lower: [],
},
);
2019-12-26 22:10:19 +05:30
beforeEach(() => {
setupAnomalyChart({
2020-07-28 23:09:34 +05:30
graphData: noBoundaryData,
2019-12-26 22:10:19 +05:30
deploymentData: anomalyDeploymentData,
});
});
describe('option', () => {
let option;
let series;
beforeEach(() => {
({ option } = getTimeSeriesProps());
({ series } = option);
});
it('does not display a boundary band', () => {
expect(series).toEqual(expect.any(Array));
expect(series.length).toEqual(0); // no boundaries
});
it('can format y values (to use in tooltips)', () => {
2020-07-28 23:09:34 +05:30
expect(parseFloat(wrapper.vm.yValueFormatted(0, 0))).toEqual(10);
2019-12-26 22:10:19 +05:30
expect(wrapper.vm.yValueFormatted(1, 0)).toBe(''); // missing boundary
expect(wrapper.vm.yValueFormatted(2, 0)).toBe(''); // missing boundary
});
});
});
describe('with one anomaly', () => {
2020-07-28 23:09:34 +05:30
const mockValues = ['10', '20', '10'];
const oneAnomalyData = anomalyGraphData(
{},
{
upper: mockValues.map(() => TEST_UPPER),
values: mockValues,
lower: mockValues.map(() => TEST_LOWER),
},
);
2019-12-26 22:10:19 +05:30
beforeEach(() => {
setupAnomalyChart({
2020-07-28 23:09:34 +05:30
graphData: oneAnomalyData,
2019-12-26 22:10:19 +05:30
deploymentData: anomalyDeploymentData,
});
});
describe('series-config', () => {
it('displays one anomaly', () => {
const { seriesConfig } = getTimeSeriesProps();
const { symbolSize, itemStyle } = seriesConfig;
2020-07-28 23:09:34 +05:30
const bigDots = mockValues.filter((v, dataIndex) => {
2019-12-26 22:10:19 +05:30
const size = symbolSize(null, { dataIndex });
return size > 0.1;
});
2020-07-28 23:09:34 +05:30
const redDots = mockValues.filter((v, dataIndex) => {
2019-12-26 22:10:19 +05:30
const color = itemStyle.color({ dataIndex });
return color === colorValues.anomalySymbol;
});
expect(bigDots.length).toBe(1);
expect(redDots.length).toBe(1);
});
});
});
describe('with offset', () => {
2020-07-28 23:09:34 +05:30
const mockValues = ['10', '11', '12'];
const mockUpper = ['20', '20', '20'];
const mockLower = ['-1', '-2', '-3.70'];
const expectedOffset = 4; // Lowest point in mock data is -3.70, it gets rounded
2019-12-26 22:10:19 +05:30
beforeEach(() => {
setupAnomalyChart({
2020-07-28 23:09:34 +05:30
graphData: anomalyGraphData(
{},
{
upper: mockUpper,
values: mockValues,
lower: mockLower,
},
),
2019-12-26 22:10:19 +05:30
deploymentData: anomalyDeploymentData,
});
});
describe('receives props correctly', () => {
describe('graph-data', () => {
it('receives a single "metric" series', () => {
const { graphData } = getTimeSeriesProps();
2020-01-01 13:55:28 +05:30
expect(graphData.metrics.length).toBe(1);
2019-12-26 22:10:19 +05:30
});
it('receives "metric" results and applies the offset to them', () => {
const { graphData } = getTimeSeriesProps();
2020-01-01 13:55:28 +05:30
const { result } = graphData.metrics[0];
2019-12-26 22:10:19 +05:30
const { values } = result[0];
2020-07-28 23:09:34 +05:30
2019-12-26 22:10:19 +05:30
expect(values).toEqual(expect.any(Array));
values.forEach(([, y], index) => {
2020-07-28 23:09:34 +05:30
expect(y).toBeCloseTo(parseFloat(mockValues[index]) + expectedOffset);
2019-12-26 22:10:19 +05:30
});
});
});
});
describe('option', () => {
it('upper boundary values are stacked on top of lower boundary, plus the offset', () => {
const { option } = getTimeSeriesProps();
const { series } = option;
const [lowerSeries, upperSeries] = series;
lowerSeries.data.forEach(([, y], i) => {
2020-07-28 23:09:34 +05:30
expect(y).toBeCloseTo(parseFloat(mockLower[i]) + expectedOffset);
2019-12-26 22:10:19 +05:30
});
upperSeries.data.forEach(([, y], i) => {
2020-07-28 23:09:34 +05:30
expect(y).toBeCloseTo(parseFloat(mockUpper[i] - mockLower[i]));
2019-12-26 22:10:19 +05:30
});
});
});
});
});