mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
* change Scale types for charts * update mock data * add unit test for rendering charts with configs * add timezone and formatter for charts * update mock implementation for ui/chrome * update snapshot
This commit is contained in:
parent
da706ab1df
commit
7c1ed64c03
24 changed files with 1229 additions and 958 deletions
5
x-pack/plugins/siem/public/components/charts/__snapshots__/areachart.test.tsx.snap
generated
Normal file
5
x-pack/plugins/siem/public/components/charts/__snapshots__/areachart.test.tsx.snap
generated
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AreaChartBaseComponent render with customized configs should 2 render AreaSeries 1`] = `[Function]`;
|
||||
|
||||
exports[`AreaChartBaseComponent render with default configs if no customized configs given should 2 render AreaSeries 1`] = `[Function]`;
|
5
x-pack/plugins/siem/public/components/charts/__snapshots__/barchart.test.tsx.snap
generated
Normal file
5
x-pack/plugins/siem/public/components/charts/__snapshots__/barchart.test.tsx.snap
generated
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`BarChartBaseComponent render with customized configs should 2 render BarSeries 1`] = `[Function]`;
|
||||
|
||||
exports[`BarChartBaseComponent render with default configs if no customized configs given should 2 render BarSeries 1`] = `[Function]`;
|
|
@ -4,30 +4,33 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { mount, ReactWrapper } from 'enzyme';
|
||||
import { ShallowWrapper, shallow } from 'enzyme';
|
||||
import * as React from 'react';
|
||||
|
||||
import { AreaChartBaseComponent, AreaChartWithCustomPrompt } from './areachart';
|
||||
import { ChartConfigsData } from './common';
|
||||
import { ChartConfigsData, ChartHolder } from './common';
|
||||
import { ScaleType, AreaSeries, Axis } from '@elastic/charts';
|
||||
|
||||
jest.mock('@elastic/charts');
|
||||
|
||||
describe('AreaChartBaseComponent', () => {
|
||||
let wrapper: ReactWrapper;
|
||||
let shallowWrapper: ShallowWrapper;
|
||||
const mockAreaChartData: ChartConfigsData[] = [
|
||||
{
|
||||
key: 'uniqueSourceIpsHistogram',
|
||||
value: [
|
||||
{ x: 1556686800000, y: 580213 },
|
||||
{ x: 1556730000000, y: 1096175 },
|
||||
{ x: 1556773200000, y: 12382 },
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf(), y: 580213 },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf(), y: 1096175 },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf(), y: 12382 },
|
||||
],
|
||||
color: '#DB1374',
|
||||
},
|
||||
{
|
||||
key: 'uniqueDestinationIpsHistogram',
|
||||
value: [
|
||||
{ x: 1556686800000, y: 565975 },
|
||||
{ x: 1556730000000, y: 1084366 },
|
||||
{ x: 1556773200000, y: 12280 },
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf(), y: 565975 },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf(), y: 1084366 },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf(), y: 12280 },
|
||||
],
|
||||
color: '#490092',
|
||||
},
|
||||
|
@ -35,47 +38,165 @@ describe('AreaChartBaseComponent', () => {
|
|||
|
||||
describe('render', () => {
|
||||
beforeAll(() => {
|
||||
wrapper = mount(<AreaChartBaseComponent height={100} width={120} data={mockAreaChartData} />);
|
||||
shallowWrapper = shallow(
|
||||
<AreaChartBaseComponent height={100} width={120} data={mockAreaChartData} />
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Chart', () => {
|
||||
expect(wrapper.find('Chart')).toHaveLength(1);
|
||||
expect(shallowWrapper.find('Chart')).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('render with customized configs', () => {
|
||||
const mockTimeFormatter = jest.fn();
|
||||
const mockNumberFormatter = jest.fn();
|
||||
const configs = {
|
||||
series: {
|
||||
xScaleType: ScaleType.Time,
|
||||
yScaleType: ScaleType.Linear,
|
||||
},
|
||||
axis: {
|
||||
xTickFormatter: mockTimeFormatter,
|
||||
yTickFormatter: mockNumberFormatter,
|
||||
},
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
shallowWrapper = shallow(
|
||||
<AreaChartBaseComponent
|
||||
height={100}
|
||||
width={120}
|
||||
data={mockAreaChartData}
|
||||
configs={configs}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it(`should ${mockAreaChartData.length} render AreaSeries`, () => {
|
||||
expect(shallow).toMatchSnapshot();
|
||||
expect(shallowWrapper.find(AreaSeries)).toHaveLength(mockAreaChartData.length);
|
||||
});
|
||||
|
||||
it('should render AreaSeries with given xScaleType', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(AreaSeries)
|
||||
.first()
|
||||
.prop('xScaleType')
|
||||
).toEqual(configs.series.xScaleType);
|
||||
});
|
||||
|
||||
it('should render AreaSeries with given yScaleType', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(AreaSeries)
|
||||
.first()
|
||||
.prop('yScaleType')
|
||||
).toEqual(configs.series.yScaleType);
|
||||
});
|
||||
|
||||
it('should render xAxis with given tick formatter', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(Axis)
|
||||
.first()
|
||||
.prop('tickFormat')
|
||||
).toEqual(mockTimeFormatter);
|
||||
});
|
||||
|
||||
it('should render yAxis with given tick formatter', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(Axis)
|
||||
.last()
|
||||
.prop('tickFormat')
|
||||
).toEqual(mockNumberFormatter);
|
||||
});
|
||||
});
|
||||
|
||||
describe('render with default configs if no customized configs given', () => {
|
||||
beforeAll(() => {
|
||||
shallowWrapper = shallow(
|
||||
<AreaChartBaseComponent height={100} width={120} data={mockAreaChartData} />
|
||||
);
|
||||
});
|
||||
|
||||
it(`should ${mockAreaChartData.length} render AreaSeries`, () => {
|
||||
expect(shallow).toMatchSnapshot();
|
||||
expect(shallowWrapper.find(AreaSeries)).toHaveLength(mockAreaChartData.length);
|
||||
});
|
||||
|
||||
it('should render AreaSeries with default xScaleType: Linear', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(AreaSeries)
|
||||
.first()
|
||||
.prop('xScaleType')
|
||||
).toEqual(ScaleType.Linear);
|
||||
});
|
||||
|
||||
it('should render AreaSeries with default yScaleType: Linear', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(AreaSeries)
|
||||
.first()
|
||||
.prop('yScaleType')
|
||||
).toEqual(ScaleType.Linear);
|
||||
});
|
||||
|
||||
it('should not format xTicks value', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(Axis)
|
||||
.last()
|
||||
.prop('tickFormat')
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not format yTicks value', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(Axis)
|
||||
.last()
|
||||
.prop('tickFormat')
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('no render', () => {
|
||||
beforeAll(() => {
|
||||
wrapper = mount(
|
||||
shallowWrapper = shallow(
|
||||
<AreaChartBaseComponent height={null} width={null} data={mockAreaChartData} />
|
||||
);
|
||||
});
|
||||
|
||||
it('should not render without height and width', () => {
|
||||
expect(wrapper.find('Chart')).toHaveLength(0);
|
||||
expect(shallowWrapper.find('Chart')).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('AreaChartWithCustomPrompt', () => {
|
||||
let wrapper: ReactWrapper;
|
||||
let shallowWrapper: ShallowWrapper;
|
||||
describe.each([
|
||||
[
|
||||
[
|
||||
{
|
||||
key: 'uniqueSourceIpsHistogram',
|
||||
value: [
|
||||
{ x: 1556686800000, y: 580213 },
|
||||
{ x: 1556730000000, y: 1096175 },
|
||||
{ x: 1556773200000, y: 12382 },
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf(), y: 580213 },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf(), y: 1096175 },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf(), y: 12382 },
|
||||
],
|
||||
color: '#DB1374',
|
||||
},
|
||||
{
|
||||
key: 'uniqueDestinationIpsHistogram',
|
||||
value: [
|
||||
{ x: 1556686800000, y: 565975 },
|
||||
{ x: 1556730000000, y: 1084366 },
|
||||
{ x: 1556773200000, y: 12280 },
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf(), y: 565975 },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf(), y: 1084366 },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf(), y: 12280 },
|
||||
],
|
||||
color: '#490092',
|
||||
},
|
||||
|
@ -90,9 +211,9 @@ describe('AreaChartWithCustomPrompt', () => {
|
|||
{
|
||||
key: 'uniqueDestinationIpsHistogram',
|
||||
value: [
|
||||
{ x: 1556686800000, y: 565975 },
|
||||
{ x: 1556730000000, y: 1084366 },
|
||||
{ x: 1556773200000, y: 12280 },
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf(), y: 565975 },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf(), y: 1084366 },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf(), y: 12280 },
|
||||
],
|
||||
color: '#490092',
|
||||
},
|
||||
|
@ -101,12 +222,12 @@ describe('AreaChartWithCustomPrompt', () => {
|
|||
],
|
||||
])('renders areachart', (data: ChartConfigsData[] | [] | null | undefined) => {
|
||||
beforeAll(() => {
|
||||
wrapper = mount(<AreaChartWithCustomPrompt height={100} width={120} data={data} />);
|
||||
shallowWrapper = shallow(<AreaChartWithCustomPrompt height={100} width={120} data={data} />);
|
||||
});
|
||||
|
||||
it('render AreaChartBaseComponent', () => {
|
||||
expect(wrapper.find('Chart')).toHaveLength(1);
|
||||
expect(wrapper.find('ChartHolder')).toHaveLength(0);
|
||||
expect(shallowWrapper.find(AreaChartBaseComponent)).toHaveLength(1);
|
||||
expect(shallowWrapper.find(ChartHolder)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -128,12 +249,20 @@ describe('AreaChartWithCustomPrompt', () => {
|
|||
[
|
||||
{
|
||||
key: 'uniqueSourceIpsHistogram',
|
||||
value: [{ x: 1556686800000 }, { x: 1556730000000 }, { x: 1556773200000 }],
|
||||
value: [
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf() },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf() },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf() },
|
||||
],
|
||||
color: '#DB1374',
|
||||
},
|
||||
{
|
||||
key: 'uniqueDestinationIpsHistogram',
|
||||
value: [{ x: 1556686800000 }, { x: 1556730000000 }, { x: 1556773200000 }],
|
||||
value: [
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf() },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf() },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf() },
|
||||
],
|
||||
color: '#490092',
|
||||
},
|
||||
],
|
||||
|
@ -142,18 +271,18 @@ describe('AreaChartWithCustomPrompt', () => {
|
|||
{
|
||||
key: 'uniqueSourceIpsHistogram',
|
||||
value: [
|
||||
{ x: 1556686800000, y: 580213 },
|
||||
{ x: 1556730000000, y: null },
|
||||
{ x: 1556773200000, y: 12382 },
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf(), y: 580213 },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf(), y: null },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf(), y: 12382 },
|
||||
],
|
||||
color: '#DB1374',
|
||||
},
|
||||
{
|
||||
key: 'uniqueDestinationIpsHistogram',
|
||||
value: [
|
||||
{ x: 1556686800000, y: 565975 },
|
||||
{ x: 1556730000000, y: 1084366 },
|
||||
{ x: 1556773200000, y: 12280 },
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf(), y: 565975 },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf(), y: 1084366 },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf(), y: 12280 },
|
||||
],
|
||||
color: '#490092',
|
||||
},
|
||||
|
@ -164,18 +293,18 @@ describe('AreaChartWithCustomPrompt', () => {
|
|||
{
|
||||
key: 'uniqueSourceIpsHistogram',
|
||||
value: [
|
||||
{ x: 1556686800000, y: 580213 },
|
||||
{ x: 1556730000000, y: {} },
|
||||
{ x: 1556773200000, y: 12382 },
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf(), y: 580213 },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf(), y: {} },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf(), y: 12382 },
|
||||
],
|
||||
color: '#DB1374',
|
||||
},
|
||||
{
|
||||
key: 'uniqueDestinationIpsHistogram',
|
||||
value: [
|
||||
{ x: 1556686800000, y: 565975 },
|
||||
{ x: 1556730000000, y: 1084366 },
|
||||
{ x: 1556773200000, y: 12280 },
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf(), y: 565975 },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf(), y: 1084366 },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf(), y: 12280 },
|
||||
],
|
||||
color: '#490092',
|
||||
},
|
||||
|
@ -183,12 +312,12 @@ describe('AreaChartWithCustomPrompt', () => {
|
|||
],
|
||||
])('renders prompt', (data: ChartConfigsData[] | [] | null | undefined) => {
|
||||
beforeAll(() => {
|
||||
wrapper = mount(<AreaChartWithCustomPrompt height={100} width={120} data={data} />);
|
||||
shallowWrapper = shallow(<AreaChartWithCustomPrompt height={100} width={120} data={data} />);
|
||||
});
|
||||
|
||||
it('render Chart Holder', () => {
|
||||
expect(wrapper.find('Chart')).toHaveLength(0);
|
||||
expect(wrapper.find('ChartHolder')).toHaveLength(1);
|
||||
expect(shallowWrapper.find(AreaChartBaseComponent)).toHaveLength(0);
|
||||
expect(shallowWrapper.find(ChartHolder)).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -15,20 +15,18 @@ import {
|
|||
ScaleType,
|
||||
Settings,
|
||||
} from '@elastic/charts';
|
||||
import { getOr, get } from 'lodash/fp';
|
||||
import {
|
||||
ChartConfigsData,
|
||||
ChartHolder,
|
||||
getSeriesStyle,
|
||||
numberFormatter,
|
||||
WrappedByAutoSizer,
|
||||
getTheme,
|
||||
ChartSeriesConfigs,
|
||||
browserTimezone,
|
||||
} from './common';
|
||||
import { AutoSizer } from '../auto_sizer';
|
||||
|
||||
const dateFormatter = (d: string) => {
|
||||
return d.toLocaleString().split('T')[0];
|
||||
};
|
||||
|
||||
// custom series styles: https://ela.st/areachart-styling
|
||||
const getSeriesLineStyle = (color: string | undefined) => {
|
||||
return color
|
||||
|
@ -64,7 +62,13 @@ export const AreaChartBaseComponent = React.memo<{
|
|||
data: ChartConfigsData[];
|
||||
width: number | null | undefined;
|
||||
height: number | null | undefined;
|
||||
configs?: ChartSeriesConfigs | undefined;
|
||||
}>(({ data, ...chartConfigs }) => {
|
||||
const xTickFormatter = get('configs.axis.xTickFormatter', chartConfigs);
|
||||
const yTickFormatter = get('configs.axis.yTickFormatter', chartConfigs);
|
||||
const xAxisId = getAxisId(`group-${data[0].key}-x`);
|
||||
const yAxisId = getAxisId(`group-${data[0].key}-y`);
|
||||
|
||||
return chartConfigs.width && chartConfigs.height ? (
|
||||
<div style={{ height: chartConfigs.height, width: chartConfigs.width, position: 'relative' }}>
|
||||
<Chart>
|
||||
|
@ -78,8 +82,9 @@ export const AreaChartBaseComponent = React.memo<{
|
|||
key={seriesKey}
|
||||
name={series.key.replace('Histogram', '')}
|
||||
data={series.value}
|
||||
xScaleType={ScaleType.Ordinal}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xScaleType={getOr(ScaleType.Linear, 'configs.series.xScaleType', chartConfigs)}
|
||||
yScaleType={getOr(ScaleType.Linear, 'configs.series.yScaleType', chartConfigs)}
|
||||
timeZone={browserTimezone}
|
||||
xAccessor="x"
|
||||
yAccessors={['y']}
|
||||
areaSeriesStyle={getSeriesLineStyle(series.color)}
|
||||
|
@ -88,19 +93,23 @@ export const AreaChartBaseComponent = React.memo<{
|
|||
) : null;
|
||||
})}
|
||||
|
||||
<Axis
|
||||
id={getAxisId(`group-${data[0].key}-x`)}
|
||||
position={Position.Bottom}
|
||||
showOverlappingTicks={false}
|
||||
tickFormat={dateFormatter}
|
||||
tickSize={0}
|
||||
/>
|
||||
<Axis
|
||||
id={getAxisId(`group-${data[0].key}-y`)}
|
||||
position={Position.Left}
|
||||
tickSize={0}
|
||||
tickFormat={numberFormatter}
|
||||
/>
|
||||
{xTickFormatter ? (
|
||||
<Axis
|
||||
id={xAxisId}
|
||||
position={Position.Bottom}
|
||||
showOverlappingTicks={false}
|
||||
tickFormat={xTickFormatter}
|
||||
tickSize={0}
|
||||
/>
|
||||
) : (
|
||||
<Axis id={xAxisId} position={Position.Bottom} showOverlappingTicks={false} tickSize={0} />
|
||||
)}
|
||||
|
||||
{yTickFormatter ? (
|
||||
<Axis id={yAxisId} position={Position.Left} tickSize={0} tickFormat={yTickFormatter} />
|
||||
) : (
|
||||
<Axis id={yAxisId} position={Position.Left} tickSize={0} />
|
||||
)}
|
||||
</Chart>
|
||||
</div>
|
||||
) : null;
|
||||
|
@ -110,7 +119,8 @@ export const AreaChartWithCustomPrompt = React.memo<{
|
|||
data: ChartConfigsData[] | null | undefined;
|
||||
height: number | null | undefined;
|
||||
width: number | null | undefined;
|
||||
}>(({ data, height, width }) => {
|
||||
configs?: ChartSeriesConfigs | undefined;
|
||||
}>(({ data, height, width, configs }) => {
|
||||
return data != null &&
|
||||
data.length &&
|
||||
data.every(
|
||||
|
@ -119,20 +129,26 @@ export const AreaChartWithCustomPrompt = React.memo<{
|
|||
value.length > 0 &&
|
||||
value.every(chart => chart.x != null && chart.y != null)
|
||||
) ? (
|
||||
<AreaChartBaseComponent height={height} width={width} data={data} />
|
||||
<AreaChartBaseComponent height={height} width={width} data={data} configs={configs} />
|
||||
) : (
|
||||
<ChartHolder />
|
||||
);
|
||||
});
|
||||
|
||||
export const AreaChart = React.memo<{ areaChart: ChartConfigsData[] | null | undefined }>(
|
||||
({ areaChart }) => (
|
||||
<AutoSizer detectAnyWindowResize={false} content>
|
||||
{({ measureRef, content: { height, width } }) => (
|
||||
<WrappedByAutoSizer innerRef={measureRef}>
|
||||
<AreaChartWithCustomPrompt data={areaChart} height={height} width={width} />
|
||||
</WrappedByAutoSizer>
|
||||
)}
|
||||
</AutoSizer>
|
||||
)
|
||||
);
|
||||
export const AreaChart = React.memo<{
|
||||
areaChart: ChartConfigsData[] | null | undefined;
|
||||
configs?: ChartSeriesConfigs | undefined;
|
||||
}>(({ areaChart, configs }) => (
|
||||
<AutoSizer detectAnyWindowResize={false} content>
|
||||
{({ measureRef, content: { height, width } }) => (
|
||||
<WrappedByAutoSizer innerRef={measureRef}>
|
||||
<AreaChartWithCustomPrompt
|
||||
data={areaChart}
|
||||
height={height}
|
||||
width={width}
|
||||
configs={configs}
|
||||
/>
|
||||
</WrappedByAutoSizer>
|
||||
)}
|
||||
</AutoSizer>
|
||||
));
|
||||
|
|
|
@ -4,14 +4,17 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { mount, ReactWrapper } from 'enzyme';
|
||||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import * as React from 'react';
|
||||
|
||||
import { BarChartBaseComponent, BarChartWithCustomPrompt } from './barchart';
|
||||
import { ChartConfigsData } from './common';
|
||||
import { ChartConfigsData, ChartHolder } from './common';
|
||||
import { BarSeries, ScaleType, Axis } from '@elastic/charts';
|
||||
|
||||
jest.mock('@elastic/charts');
|
||||
|
||||
describe('BarChartBaseComponent', () => {
|
||||
let wrapper: ReactWrapper;
|
||||
let shallowWrapper: ShallowWrapper;
|
||||
const mockBarChartData: ChartConfigsData[] = [
|
||||
{
|
||||
key: 'uniqueSourceIps',
|
||||
|
@ -27,21 +30,134 @@ describe('BarChartBaseComponent', () => {
|
|||
|
||||
describe('render', () => {
|
||||
beforeAll(() => {
|
||||
wrapper = mount(<BarChartBaseComponent height={100} width={120} data={mockBarChartData} />);
|
||||
shallowWrapper = shallow(
|
||||
<BarChartBaseComponent height={100} width={120} data={mockBarChartData} />
|
||||
);
|
||||
});
|
||||
|
||||
it('should render two bar series', () => {
|
||||
expect(wrapper.find('Chart')).toHaveLength(1);
|
||||
expect(shallowWrapper.find('Chart')).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('render with customized configs', () => {
|
||||
const mockNumberFormatter = jest.fn();
|
||||
const configs = {
|
||||
series: {
|
||||
xScaleType: ScaleType.Ordinal,
|
||||
yScaleType: ScaleType.Linear,
|
||||
},
|
||||
axis: {
|
||||
yTickFormatter: mockNumberFormatter,
|
||||
},
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
shallowWrapper = shallow(
|
||||
<BarChartBaseComponent height={100} width={120} data={mockBarChartData} configs={configs} />
|
||||
);
|
||||
});
|
||||
|
||||
it(`should ${mockBarChartData.length} render BarSeries`, () => {
|
||||
expect(shallow).toMatchSnapshot();
|
||||
expect(shallowWrapper.find(BarSeries)).toHaveLength(mockBarChartData.length);
|
||||
});
|
||||
|
||||
it('should render BarSeries with given xScaleType', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(BarSeries)
|
||||
.first()
|
||||
.prop('xScaleType')
|
||||
).toEqual(configs.series.xScaleType);
|
||||
});
|
||||
|
||||
it('should render BarSeries with given yScaleType', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(BarSeries)
|
||||
.first()
|
||||
.prop('yScaleType')
|
||||
).toEqual(configs.series.yScaleType);
|
||||
});
|
||||
|
||||
it('should render xAxis with given tick formatter', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(Axis)
|
||||
.first()
|
||||
.prop('tickFormat')
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should render yAxis with given tick formatter', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(Axis)
|
||||
.last()
|
||||
.prop('tickFormat')
|
||||
).toEqual(mockNumberFormatter);
|
||||
});
|
||||
});
|
||||
|
||||
describe('render with default configs if no customized configs given', () => {
|
||||
beforeAll(() => {
|
||||
shallowWrapper = shallow(
|
||||
<BarChartBaseComponent height={100} width={120} data={mockBarChartData} />
|
||||
);
|
||||
});
|
||||
|
||||
it(`should ${mockBarChartData.length} render BarSeries`, () => {
|
||||
expect(shallow).toMatchSnapshot();
|
||||
expect(shallowWrapper.find(BarSeries)).toHaveLength(mockBarChartData.length);
|
||||
});
|
||||
|
||||
it('should render BarSeries with default xScaleType: Linear', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(BarSeries)
|
||||
.first()
|
||||
.prop('xScaleType')
|
||||
).toEqual(ScaleType.Linear);
|
||||
});
|
||||
|
||||
it('should render BarSeries with default yScaleType: Linear', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(BarSeries)
|
||||
.first()
|
||||
.prop('yScaleType')
|
||||
).toEqual(ScaleType.Linear);
|
||||
});
|
||||
|
||||
it('should not format xTicks value', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(Axis)
|
||||
.last()
|
||||
.prop('tickFormat')
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not format yTicks value', () => {
|
||||
expect(
|
||||
shallowWrapper
|
||||
.find(Axis)
|
||||
.last()
|
||||
.prop('tickFormat')
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('no render', () => {
|
||||
beforeAll(() => {
|
||||
wrapper = mount(<BarChartBaseComponent height={null} width={null} data={mockBarChartData} />);
|
||||
shallowWrapper = shallow(
|
||||
<BarChartBaseComponent height={null} width={null} data={mockBarChartData} />
|
||||
);
|
||||
});
|
||||
|
||||
it('should not render without height and width', () => {
|
||||
expect(wrapper.find('Chart')).toHaveLength(0);
|
||||
expect(shallowWrapper.find('Chart')).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -78,17 +194,17 @@ describe.each([
|
|||
],
|
||||
],
|
||||
])('BarChartWithCustomPrompt', mockBarChartData => {
|
||||
let wrapper: ReactWrapper;
|
||||
let shallowWrapper: ShallowWrapper;
|
||||
describe('renders barchart', () => {
|
||||
beforeAll(() => {
|
||||
wrapper = mount(
|
||||
shallowWrapper = shallow(
|
||||
<BarChartWithCustomPrompt height={100} width={120} data={mockBarChartData} />
|
||||
);
|
||||
});
|
||||
|
||||
it('render BarChartBaseComponent', () => {
|
||||
expect(wrapper.find('Chart')).toHaveLength(1);
|
||||
expect(wrapper.find('ChartHolder')).toHaveLength(0);
|
||||
expect(shallowWrapper.find(BarChartBaseComponent)).toHaveLength(1);
|
||||
expect(shallowWrapper.find(ChartHolder)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -156,13 +272,13 @@ describe.each([
|
|||
],
|
||||
],
|
||||
])('renders prompt', (data: ChartConfigsData[] | [] | null | undefined) => {
|
||||
let wrapper: ReactWrapper;
|
||||
let shallowWrapper: ShallowWrapper;
|
||||
beforeAll(() => {
|
||||
wrapper = mount(<BarChartWithCustomPrompt height={100} width={120} data={data} />);
|
||||
shallowWrapper = shallow(<BarChartWithCustomPrompt height={100} width={120} data={data} />);
|
||||
});
|
||||
|
||||
it('render Chart Holder', () => {
|
||||
expect(wrapper.find('Chart')).toHaveLength(0);
|
||||
expect(wrapper.find('ChartHolder')).toHaveLength(1);
|
||||
expect(shallowWrapper.find(BarChartBaseComponent)).toHaveLength(0);
|
||||
expect(shallowWrapper.find(ChartHolder)).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,14 +8,16 @@ import React from 'react';
|
|||
|
||||
import { Chart, BarSeries, Axis, Position, getSpecId, ScaleType, Settings } from '@elastic/charts';
|
||||
import { getAxisId } from '@elastic/charts';
|
||||
import { getOr, get } from 'lodash/fp';
|
||||
import {
|
||||
ChartConfigsData,
|
||||
WrappedByAutoSizer,
|
||||
ChartHolder,
|
||||
numberFormatter,
|
||||
SeriesType,
|
||||
getSeriesStyle,
|
||||
getTheme,
|
||||
ChartSeriesConfigs,
|
||||
browserTimezone,
|
||||
} from './common';
|
||||
import { AutoSizer } from '../auto_sizer';
|
||||
|
||||
|
@ -24,7 +26,13 @@ export const BarChartBaseComponent = React.memo<{
|
|||
data: ChartConfigsData[];
|
||||
width: number | null | undefined;
|
||||
height: number | null | undefined;
|
||||
configs?: ChartSeriesConfigs | undefined;
|
||||
}>(({ data, ...chartConfigs }) => {
|
||||
const xTickFormatter = get('configs.axis.xTickFormatter', chartConfigs);
|
||||
const yTickFormatter = get('configs.axis.yTickFormatter', chartConfigs);
|
||||
const xAxisId = getAxisId(`stat-items-barchart-${data[0].key}-x`);
|
||||
const yAxisId = getAxisId(`stat-items-barchart-${data[0].key}-y`);
|
||||
|
||||
return chartConfigs.width && chartConfigs.height ? (
|
||||
<Chart>
|
||||
<Settings rotation={90} theme={getTheme()} />
|
||||
|
@ -37,10 +45,11 @@ export const BarChartBaseComponent = React.memo<{
|
|||
id={barSeriesSpecId}
|
||||
key={barSeriesKey}
|
||||
name={series.key}
|
||||
xScaleType={ScaleType.Ordinal}
|
||||
yScaleType={ScaleType.Linear}
|
||||
xScaleType={getOr(ScaleType.Linear, 'configs.series.xScaleType', chartConfigs)}
|
||||
yScaleType={getOr(ScaleType.Linear, 'configs.series.yScaleType', chartConfigs)}
|
||||
xAccessor="x"
|
||||
yAccessors={['y']}
|
||||
timeZone={browserTimezone}
|
||||
splitSeriesAccessors={['g']}
|
||||
data={series.value!}
|
||||
stackAccessors={['y']}
|
||||
|
@ -49,17 +58,23 @@ export const BarChartBaseComponent = React.memo<{
|
|||
);
|
||||
})}
|
||||
|
||||
<Axis
|
||||
id={getAxisId(`stat-items-barchart-${data[0].key}-x`)}
|
||||
position={Position.Bottom}
|
||||
tickSize={0}
|
||||
tickFormat={numberFormatter}
|
||||
/>
|
||||
<Axis
|
||||
id={getAxisId(`stat-items-barchart-${data[0].key}-y`)}
|
||||
position={Position.Left}
|
||||
tickSize={0}
|
||||
/>
|
||||
{xTickFormatter ? (
|
||||
<Axis
|
||||
id={xAxisId}
|
||||
position={Position.Bottom}
|
||||
showOverlappingTicks={false}
|
||||
tickSize={0}
|
||||
tickFormat={xTickFormatter}
|
||||
/>
|
||||
) : (
|
||||
<Axis id={xAxisId} position={Position.Bottom} showOverlappingTicks={false} tickSize={0} />
|
||||
)}
|
||||
|
||||
{yTickFormatter ? (
|
||||
<Axis id={yAxisId} position={Position.Left} tickSize={0} tickFormat={yTickFormatter} />
|
||||
) : (
|
||||
<Axis id={yAxisId} position={Position.Left} tickSize={0} />
|
||||
)}
|
||||
</Chart>
|
||||
) : null;
|
||||
});
|
||||
|
@ -68,27 +83,29 @@ export const BarChartWithCustomPrompt = React.memo<{
|
|||
data: ChartConfigsData[] | null | undefined;
|
||||
height: number | null | undefined;
|
||||
width: number | null | undefined;
|
||||
}>(({ data, height, width }) => {
|
||||
configs?: ChartSeriesConfigs | undefined;
|
||||
}>(({ data, height, width, configs }) => {
|
||||
return data &&
|
||||
data.length &&
|
||||
data.some(
|
||||
({ value }) =>
|
||||
value != null && value.length > 0 && value.every(chart => chart.y != null && chart.y > 0)
|
||||
) ? (
|
||||
<BarChartBaseComponent height={height} width={width} data={data} />
|
||||
<BarChartBaseComponent height={height} width={width} data={data} configs={configs} />
|
||||
) : (
|
||||
<ChartHolder />
|
||||
);
|
||||
});
|
||||
|
||||
export const BarChart = React.memo<{ barChart: ChartConfigsData[] | null | undefined }>(
|
||||
({ barChart }) => (
|
||||
<AutoSizer detectAnyWindowResize={false} content>
|
||||
{({ measureRef, content: { height, width } }) => (
|
||||
<WrappedByAutoSizer innerRef={measureRef}>
|
||||
<BarChartWithCustomPrompt height={height} width={width} data={barChart} />
|
||||
</WrappedByAutoSizer>
|
||||
)}
|
||||
</AutoSizer>
|
||||
)
|
||||
);
|
||||
export const BarChart = React.memo<{
|
||||
barChart: ChartConfigsData[] | null | undefined;
|
||||
configs?: ChartSeriesConfigs | undefined;
|
||||
}>(({ barChart, configs }) => (
|
||||
<AutoSizer detectAnyWindowResize={false} content>
|
||||
{({ measureRef, content: { height, width } }) => (
|
||||
<WrappedByAutoSizer innerRef={measureRef}>
|
||||
<BarChartWithCustomPrompt height={height} width={width} data={barChart} configs={configs} />
|
||||
</WrappedByAutoSizer>
|
||||
)}
|
||||
</AutoSizer>
|
||||
));
|
||||
|
|
|
@ -14,9 +14,12 @@ import {
|
|||
PartialTheme,
|
||||
LIGHT_THEME,
|
||||
DARK_THEME,
|
||||
ScaleType,
|
||||
} from '@elastic/charts';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { TickFormatter } from '@elastic/charts/dist/lib/series/specs';
|
||||
import chrome from 'ui/chrome';
|
||||
import moment from 'moment-timezone';
|
||||
|
||||
const chartHeight = 74;
|
||||
const FlexGroup = styled(EuiFlexGroup)`
|
||||
|
@ -42,10 +45,23 @@ export interface ChartData {
|
|||
g?: number | string;
|
||||
}
|
||||
|
||||
export interface ChartSeriesConfigs {
|
||||
series?: {
|
||||
xScaleType?: ScaleType | undefined;
|
||||
yScaleType?: ScaleType | undefined;
|
||||
};
|
||||
axis?: {
|
||||
xTickFormatter?: TickFormatter | undefined;
|
||||
yTickFormatter?: TickFormatter | undefined;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ChartConfigsData {
|
||||
key: string;
|
||||
value: ChartData[] | [] | null;
|
||||
color?: string | undefined;
|
||||
areachartConfigs?: ChartSeriesConfigs | undefined;
|
||||
barchartConfigs?: ChartSeriesConfigs | undefined;
|
||||
}
|
||||
|
||||
export const WrappedByAutoSizer = styled.div`
|
||||
|
@ -57,10 +73,6 @@ export const WrappedByAutoSizer = styled.div`
|
|||
}
|
||||
`;
|
||||
|
||||
export const numberFormatter = (value: string | number) => {
|
||||
return value.toLocaleString && value.toLocaleString();
|
||||
};
|
||||
|
||||
export enum SeriesType {
|
||||
BAR = 'bar',
|
||||
AREA = 'area',
|
||||
|
@ -109,3 +121,6 @@ export const getTheme = () => {
|
|||
const defaultTheme = isDarkMode ? DARK_THEME : LIGHT_THEME;
|
||||
return mergeWithDefaultTheme(theme, defaultTheme);
|
||||
};
|
||||
|
||||
const kibanaTimezone = chrome.getUiSettingsClient().get('dateFormat:tz');
|
||||
export const browserTimezone = kibanaTimezone === 'Browser' ? moment.tz.guess() : kibanaTimezone;
|
||||
|
|
|
@ -10,11 +10,11 @@ exports[`KpiNetwork Component rendering it renders loading icons 1`] = `
|
|||
"uniqueDestinationPrivateIps": 18,
|
||||
"uniqueDestinationPrivateIpsHistogram": Array [
|
||||
Object {
|
||||
"x": "2019-02-09T16:00:00.000Z",
|
||||
"x": 1549728000000,
|
||||
"y": 8,
|
||||
},
|
||||
Object {
|
||||
"x": "2019-02-09T19:00:00.000Z",
|
||||
"x": 1549738800000,
|
||||
"y": 0,
|
||||
},
|
||||
],
|
||||
|
@ -22,11 +22,11 @@ exports[`KpiNetwork Component rendering it renders loading icons 1`] = `
|
|||
"uniqueSourcePrivateIps": 383,
|
||||
"uniqueSourcePrivateIpsHistogram": Array [
|
||||
Object {
|
||||
"x": "2019-02-09T16:00:00.000Z",
|
||||
"x": 1549728000000,
|
||||
"y": 8,
|
||||
},
|
||||
Object {
|
||||
"x": "2019-02-09T19:00:00.000Z",
|
||||
"x": 1549738800000,
|
||||
"y": 0,
|
||||
},
|
||||
],
|
||||
|
@ -46,11 +46,11 @@ exports[`KpiNetwork Component rendering it renders the default widget 1`] = `
|
|||
"uniqueDestinationPrivateIps": 18,
|
||||
"uniqueDestinationPrivateIpsHistogram": Array [
|
||||
Object {
|
||||
"x": "2019-02-09T16:00:00.000Z",
|
||||
"x": 1549728000000,
|
||||
"y": 8,
|
||||
},
|
||||
Object {
|
||||
"x": "2019-02-09T19:00:00.000Z",
|
||||
"x": 1549738800000,
|
||||
"y": 0,
|
||||
},
|
||||
],
|
||||
|
@ -58,11 +58,11 @@ exports[`KpiNetwork Component rendering it renders the default widget 1`] = `
|
|||
"uniqueSourcePrivateIps": 383,
|
||||
"uniqueSourcePrivateIpsHistogram": Array [
|
||||
Object {
|
||||
"x": "2019-02-09T16:00:00.000Z",
|
||||
"x": 1549728000000,
|
||||
"y": 8,
|
||||
},
|
||||
Object {
|
||||
"x": "2019-02-09T19:00:00.000Z",
|
||||
"x": 1549738800000,
|
||||
"y": 0,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -14,22 +14,22 @@ export const mockData: { KpiNetwork: KpiNetworkData } = {
|
|||
uniqueSourcePrivateIps: 383,
|
||||
uniqueSourcePrivateIpsHistogram: [
|
||||
{
|
||||
x: '2019-02-09T16:00:00.000Z',
|
||||
x: new Date('2019-02-09T16:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
},
|
||||
],
|
||||
uniqueDestinationPrivateIps: 18,
|
||||
uniqueDestinationPrivateIpsHistogram: [
|
||||
{
|
||||
x: '2019-02-09T16:00:00.000Z',
|
||||
x: new Date('2019-02-09T16:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
},
|
||||
],
|
||||
|
@ -176,9 +176,9 @@ export const mockEnableChartsData = {
|
|||
{
|
||||
key: 'uniqueSourcePrivateIpsHistogram',
|
||||
value: [
|
||||
{ x: '2019-02-09T16:00:00.000Z', y: 8 },
|
||||
{ x: new Date('2019-02-09T16:00:00.000Z').valueOf(), y: 8 },
|
||||
{
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
},
|
||||
],
|
||||
|
@ -189,7 +189,10 @@ export const mockEnableChartsData = {
|
|||
},
|
||||
{
|
||||
key: 'uniqueDestinationPrivateIpsHistogram',
|
||||
value: [{ x: '2019-02-09T16:00:00.000Z', y: 8 }, { x: '2019-02-09T19:00:00.000Z', y: 0 }],
|
||||
value: [
|
||||
{ x: new Date('2019-02-09T16:00:00.000Z').valueOf(), y: 8 },
|
||||
{ x: new Date('2019-02-09T19:00:00.000Z').valueOf(), y: 0 },
|
||||
],
|
||||
name: 'Dist.',
|
||||
description: 'Destination',
|
||||
color: '#490092',
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,39 +14,53 @@ import {
|
|||
addValueToFields,
|
||||
addValueToAreaChart,
|
||||
addValueToBarChart,
|
||||
useKpiMatrixStatus,
|
||||
StatItems,
|
||||
} from '.';
|
||||
import { BarChart } from '../charts/barchart';
|
||||
import { AreaChart } from '../charts/areachart';
|
||||
import { EuiHorizontalRule } from '@elastic/eui';
|
||||
import { fieldTitleChartMapping, KpiNetworkBaseComponent } from '../page/network/kpi_network';
|
||||
import { fieldTitleChartMapping } from '../page/network/kpi_network';
|
||||
import {
|
||||
mockData,
|
||||
mockNoChartMappings,
|
||||
mockDisableChartsInitialData,
|
||||
mockEnableChartsData,
|
||||
mockEnableChartsInitialData,
|
||||
mockNoChartMappings,
|
||||
} from '../page/network/kpi_network/mock';
|
||||
import { mockGlobalState, apolloClientObservable } from '../../mock';
|
||||
import { State, createStore } from '../../store';
|
||||
import { Provider as ReduxStoreProvider } from 'react-redux';
|
||||
import { KpiNetworkData, KpiHostsData } from '../../graphql/types';
|
||||
jest.mock('../charts/barchart');
|
||||
jest.mock('../charts/areachart');
|
||||
|
||||
describe('Stat Items Component', () => {
|
||||
const state: State = mockGlobalState;
|
||||
|
||||
const store = createStore(state, apolloClientObservable);
|
||||
|
||||
describe.each([
|
||||
[
|
||||
mount(
|
||||
<StatItemsComponent
|
||||
fields={[{ key: 'hosts', value: null, color: '#3185FC', icon: 'cross' }]}
|
||||
description="HOSTS"
|
||||
key="mock-keys"
|
||||
/>
|
||||
<ReduxStoreProvider store={store}>
|
||||
<StatItemsComponent
|
||||
fields={[{ key: 'hosts', value: null, color: '#3185FC', icon: 'cross' }]}
|
||||
description="HOSTS"
|
||||
key="mock-keys"
|
||||
/>
|
||||
</ReduxStoreProvider>
|
||||
),
|
||||
],
|
||||
[
|
||||
mount(
|
||||
<StatItemsComponent
|
||||
fields={[{ key: 'hosts', value: null, color: '#3185FC', icon: 'cross' }]}
|
||||
description="HOSTS"
|
||||
areaChart={[]}
|
||||
barChart={[]}
|
||||
key="mock-keys"
|
||||
/>
|
||||
<ReduxStoreProvider store={store}>
|
||||
<StatItemsComponent
|
||||
fields={[{ key: 'hosts', value: null, color: '#3185FC', icon: 'cross' }]}
|
||||
description="HOSTS"
|
||||
areaChart={[]}
|
||||
barChart={[]}
|
||||
key="mock-keys"
|
||||
/>
|
||||
</ReduxStoreProvider>
|
||||
),
|
||||
],
|
||||
])('disable charts', wrapper => {
|
||||
|
@ -99,18 +113,18 @@ describe('Stat Items Component', () => {
|
|||
{
|
||||
key: 'uniqueSourceIpsHistogram',
|
||||
value: [
|
||||
{ x: 1556686800000, y: 580213 },
|
||||
{ x: 1556730000000, y: 1096175 },
|
||||
{ x: 1556773200000, y: 12382 },
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf(), y: 565975 },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf(), y: 1084366 },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf(), y: 12280 },
|
||||
],
|
||||
color: '#DB1374',
|
||||
},
|
||||
{
|
||||
key: 'uniqueDestinationIpsHistogram',
|
||||
value: [
|
||||
{ x: 1556686800000, y: 565975 },
|
||||
{ x: 1556730000000, y: 1084366 },
|
||||
{ x: 1556773200000, y: 12280 },
|
||||
{ x: new Date('2019-05-03T13:00:00.000Z').valueOf(), y: 565975 },
|
||||
{ x: new Date('2019-05-04T01:00:00.000Z').valueOf(), y: 1084366 },
|
||||
{ x: new Date('2019-05-04T13:00:00.000Z').valueOf(), y: 12280 },
|
||||
],
|
||||
color: '#490092',
|
||||
},
|
||||
|
@ -128,7 +142,11 @@ describe('Stat Items Component', () => {
|
|||
};
|
||||
let wrapper: ReactWrapper;
|
||||
beforeAll(() => {
|
||||
wrapper = mount(<StatItemsComponent {...mockStatItemsData} />);
|
||||
wrapper = mount(
|
||||
<ReduxStoreProvider store={store}>
|
||||
<StatItemsComponent {...mockStatItemsData} />
|
||||
</ReduxStoreProvider>
|
||||
);
|
||||
});
|
||||
test('it renders the default widget', () => {
|
||||
expect(toJson(wrapper)).toMatchSnapshot();
|
||||
|
@ -186,41 +204,52 @@ describe('addValueToBarChart', () => {
|
|||
describe('useKpiMatrixStatus', () => {
|
||||
const mockNetworkMappings = fieldTitleChartMapping;
|
||||
const mockKpiNetworkData = mockData.KpiNetwork;
|
||||
const MockChildComponent = (mappedStatItemProps: StatItemsProps) => <span />;
|
||||
const MockHookWrapperComponent = ({
|
||||
fieldsMapping,
|
||||
data,
|
||||
}: {
|
||||
fieldsMapping: Readonly<StatItems[]>;
|
||||
data: KpiNetworkData | KpiHostsData;
|
||||
}) => {
|
||||
const statItemsProps: StatItemsProps[] = useKpiMatrixStatus(fieldsMapping, data);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{statItemsProps.map(mappedStatItemProps => {
|
||||
return <MockChildComponent {...mappedStatItemProps} />;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
test('it updates status correctly', () => {
|
||||
const wrapper = mount(
|
||||
<KpiNetworkBaseComponent fieldsMapping={mockNetworkMappings} data={{}} />
|
||||
<>
|
||||
<MockHookWrapperComponent fieldsMapping={mockNetworkMappings} data={mockKpiNetworkData} />
|
||||
</>
|
||||
);
|
||||
expect(wrapper.find(StatItemsComponent).get(0).props).toEqual(mockEnableChartsInitialData);
|
||||
wrapper.setProps({ data: mockKpiNetworkData });
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find(StatItemsComponent).get(0).props).toEqual(mockEnableChartsData);
|
||||
expect(wrapper.find('MockChildComponent').get(0).props).toEqual(mockEnableChartsData);
|
||||
});
|
||||
|
||||
test('it should not append areaChart if enableAreaChart is off', () => {
|
||||
const mockNetworkMappingsNoAreaChart = mockNoChartMappings;
|
||||
|
||||
const wrapper = mount(
|
||||
<KpiNetworkBaseComponent fieldsMapping={mockNetworkMappingsNoAreaChart} data={{}} />
|
||||
<>
|
||||
<MockHookWrapperComponent fieldsMapping={mockNoChartMappings} data={mockKpiNetworkData} />
|
||||
</>
|
||||
);
|
||||
expect(wrapper.find(StatItemsComponent).get(0).props).toEqual(mockDisableChartsInitialData);
|
||||
wrapper.setProps({ data: mockKpiNetworkData });
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find(StatItemsComponent).get(0).props.areaChart).toBeUndefined();
|
||||
expect(wrapper.find('MockChildComponent').get(0).props.areaChart).toBeUndefined();
|
||||
});
|
||||
|
||||
test('it should not append barChart if enableBarChart is off', () => {
|
||||
const mockNetworkMappingsNoAreaChart = mockNoChartMappings;
|
||||
|
||||
const wrapper = mount(
|
||||
<KpiNetworkBaseComponent fieldsMapping={mockNetworkMappingsNoAreaChart} data={{}} />
|
||||
<>
|
||||
<MockHookWrapperComponent fieldsMapping={mockNoChartMappings} data={mockKpiNetworkData} />
|
||||
</>
|
||||
);
|
||||
expect(wrapper.find(StatItemsComponent).get(0).props).toEqual(mockDisableChartsInitialData);
|
||||
wrapper.setProps({ data: mockKpiNetworkData });
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find(StatItemsComponent).get(0).props.barChart).toBeUndefined();
|
||||
expect(wrapper.find('MockChildComponent').get(0).props.barChart).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,11 +17,13 @@ import React, { useState, useEffect } from 'react';
|
|||
import styled from 'styled-components';
|
||||
|
||||
import { get, getOr } from 'lodash/fp';
|
||||
import { ScaleType, niceTimeFormatter } from '@elastic/charts';
|
||||
import { BarChart } from '../charts/barchart';
|
||||
import { AreaChart } from '../charts/areachart';
|
||||
import { getEmptyTagValue } from '../empty_value';
|
||||
import { ChartConfigsData, ChartData } from '../charts/common';
|
||||
import { ChartConfigsData, ChartData, ChartSeriesConfigs } from '../charts/common';
|
||||
import { KpiHostsData, KpiNetworkData } from '../../graphql/types';
|
||||
import { GlobalTime } from '../../containers/global_time';
|
||||
|
||||
const FlexItem = styled(EuiFlexItem)`
|
||||
min-width: 0;
|
||||
|
@ -49,6 +51,8 @@ export interface StatItems {
|
|||
enableAreaChart?: boolean;
|
||||
enableBarChart?: boolean;
|
||||
grow?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | true | false | null;
|
||||
areachartConfigs?: ChartSeriesConfigs;
|
||||
barchartConfigs?: ChartSeriesConfigs;
|
||||
}
|
||||
|
||||
export interface StatItemsProps extends StatItems {
|
||||
|
@ -56,6 +60,27 @@ export interface StatItemsProps extends StatItems {
|
|||
barChart?: ChartConfigsData[];
|
||||
}
|
||||
|
||||
export const numberFormatter = (value: string | number): string => value.toLocaleString();
|
||||
export const areachartConfigs = (from: number, to: number) => ({
|
||||
series: {
|
||||
xScaleType: ScaleType.Time,
|
||||
yScaleType: ScaleType.Linear,
|
||||
},
|
||||
axis: {
|
||||
xTickFormatter: niceTimeFormatter([from, to]),
|
||||
yTickFormatter: numberFormatter,
|
||||
},
|
||||
});
|
||||
export const barchartConfigs = {
|
||||
series: {
|
||||
xScaleType: ScaleType.Ordinal,
|
||||
yScaleType: ScaleType.Linear,
|
||||
},
|
||||
axis: {
|
||||
xTickFormatter: numberFormatter,
|
||||
},
|
||||
};
|
||||
|
||||
export const addValueToFields = (
|
||||
fields: StatItem[],
|
||||
data: KpiHostsData | KpiNetworkData
|
||||
|
@ -129,7 +154,7 @@ export const useKpiMatrixStatus = (
|
|||
|
||||
export const StatItemsComponent = React.memo<StatItemsProps>(
|
||||
({ fields, description, grow, barChart, areaChart, enableAreaChart, enableBarChart }) => {
|
||||
const isBarChartDataAbailable =
|
||||
const isBarChartDataAvailable =
|
||||
barChart &&
|
||||
barChart.length &&
|
||||
barChart.every(item => item.value != null && item.value.length > 0);
|
||||
|
@ -148,7 +173,7 @@ export const StatItemsComponent = React.memo<StatItemsProps>(
|
|||
{fields.map(field => (
|
||||
<FlexItem key={`stat-items-field-${field.key}`}>
|
||||
<EuiFlexGroup alignItems="center" gutterSize="m" responsive={false}>
|
||||
{(isAreaChartDataAvailable || isBarChartDataAbailable) && field.icon && (
|
||||
{(isAreaChartDataAvailable || isBarChartDataAvailable) && field.icon && (
|
||||
<FlexItem grow={false}>
|
||||
<EuiIcon
|
||||
type={field.icon}
|
||||
|
@ -177,13 +202,17 @@ export const StatItemsComponent = React.memo<StatItemsProps>(
|
|||
<EuiFlexGroup>
|
||||
{enableBarChart && (
|
||||
<FlexItem>
|
||||
<BarChart barChart={barChart!} />
|
||||
<BarChart barChart={barChart} configs={barchartConfigs} />
|
||||
</FlexItem>
|
||||
)}
|
||||
|
||||
{enableAreaChart && (
|
||||
<FlexItem>
|
||||
<AreaChart areaChart={areaChart!} />
|
||||
<GlobalTime>
|
||||
{({ from, to }) => (
|
||||
<AreaChart areaChart={areaChart} configs={areachartConfigs(from, to)} />
|
||||
)}
|
||||
</GlobalTime>
|
||||
</FlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -6932,7 +6932,7 @@
|
|||
"name": "x",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
|
||||
"type": { "kind": "SCALAR", "name": "Float", "ofType": null },
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
|
@ -7090,7 +7090,7 @@
|
|||
"name": "x",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
|
||||
"type": { "kind": "SCALAR", "name": "Float", "ofType": null },
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
|
|
|
@ -1068,7 +1068,7 @@ export interface KpiNetworkData {
|
|||
}
|
||||
|
||||
export interface KpiNetworkHistogramData {
|
||||
x?: string | null;
|
||||
x?: number | null;
|
||||
|
||||
y?: number | null;
|
||||
}
|
||||
|
@ -1096,7 +1096,7 @@ export interface KpiHostsData {
|
|||
}
|
||||
|
||||
export interface KpiHostHistogramData {
|
||||
x?: string | null;
|
||||
x?: number | null;
|
||||
|
||||
y?: number | null;
|
||||
}
|
||||
|
@ -5041,7 +5041,7 @@ export namespace KpiHostChartFields {
|
|||
export type Fragment = {
|
||||
__typename?: 'KpiHostHistogramData';
|
||||
|
||||
x?: string | null;
|
||||
x?: number | null;
|
||||
|
||||
y?: number | null;
|
||||
};
|
||||
|
@ -5051,7 +5051,7 @@ export namespace KpiNetworkChartFields {
|
|||
export type Fragment = {
|
||||
__typename?: 'KpiNetworkHistogramData';
|
||||
|
||||
x?: string | null;
|
||||
x?: number | null;
|
||||
|
||||
y?: number | null;
|
||||
};
|
||||
|
|
|
@ -14,6 +14,8 @@ chrome.getUiSettingsClient().get.mockImplementation((key: string) => {
|
|||
return { pause: false, value: 0 };
|
||||
case 'siem:defaultIndex':
|
||||
return ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'];
|
||||
case 'dateFormat:tz':
|
||||
return 'Asia/Taipei';
|
||||
case 'theme:darkMode':
|
||||
return false;
|
||||
default:
|
||||
|
|
|
@ -8,7 +8,7 @@ import gql from 'graphql-tag';
|
|||
|
||||
export const kpiHostsSchema = gql`
|
||||
type KpiHostHistogramData {
|
||||
x: String
|
||||
x: Float
|
||||
y: Float
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import gql from 'graphql-tag';
|
|||
|
||||
export const kpiNetworkSchema = gql`
|
||||
type KpiNetworkHistogramData {
|
||||
x: String
|
||||
x: Float
|
||||
y: Float
|
||||
}
|
||||
|
||||
|
|
|
@ -1097,7 +1097,7 @@ export interface KpiNetworkData {
|
|||
}
|
||||
|
||||
export interface KpiNetworkHistogramData {
|
||||
x?: string | null;
|
||||
x?: number | null;
|
||||
|
||||
y?: number | null;
|
||||
}
|
||||
|
@ -1125,7 +1125,7 @@ export interface KpiHostsData {
|
|||
}
|
||||
|
||||
export interface KpiHostHistogramData {
|
||||
x?: string | null;
|
||||
x?: number | null;
|
||||
|
||||
y?: number | null;
|
||||
}
|
||||
|
@ -5874,13 +5874,13 @@ export namespace KpiNetworkDataResolvers {
|
|||
|
||||
export namespace KpiNetworkHistogramDataResolvers {
|
||||
export interface Resolvers<Context = SiemContext, TypeParent = KpiNetworkHistogramData> {
|
||||
x?: XResolver<string | null, TypeParent, Context>;
|
||||
x?: XResolver<number | null, TypeParent, Context>;
|
||||
|
||||
y?: YResolver<number | null, TypeParent, Context>;
|
||||
}
|
||||
|
||||
export type XResolver<
|
||||
R = string | null,
|
||||
R = number | null,
|
||||
Parent = KpiNetworkHistogramData,
|
||||
Context = SiemContext
|
||||
> = Resolver<R, Parent, Context>;
|
||||
|
@ -5984,13 +5984,13 @@ export namespace KpiHostsDataResolvers {
|
|||
|
||||
export namespace KpiHostHistogramDataResolvers {
|
||||
export interface Resolvers<Context = SiemContext, TypeParent = KpiHostHistogramData> {
|
||||
x?: XResolver<string | null, TypeParent, Context>;
|
||||
x?: XResolver<number | null, TypeParent, Context>;
|
||||
|
||||
y?: YResolver<number | null, TypeParent, Context>;
|
||||
}
|
||||
|
||||
export type XResolver<
|
||||
R = string | null,
|
||||
R = number | null,
|
||||
Parent = KpiHostHistogramData,
|
||||
Context = SiemContext
|
||||
> = Resolver<R, Parent, Context>;
|
||||
|
|
|
@ -27,8 +27,8 @@ const formatGeneralHistogramData = (
|
|||
data: Array<KpiHostHistogram<KpiHostGeneralHistogramCount>>
|
||||
): KpiHostHistogramData[] | null => {
|
||||
return data && data.length > 0
|
||||
? data.map<KpiHostHistogramData>(({ key_as_string, count }) => ({
|
||||
x: key_as_string,
|
||||
? data.map<KpiHostHistogramData>(({ key, count }) => ({
|
||||
x: key,
|
||||
y: count.value,
|
||||
}))
|
||||
: null;
|
||||
|
@ -38,8 +38,8 @@ const formatAuthHistogramData = (
|
|||
data: Array<KpiHostHistogram<KpiHostAuthHistogramCount>>
|
||||
): KpiHostHistogramData[] | null => {
|
||||
return data && data.length > 0
|
||||
? data.map<KpiHostHistogramData>(({ key_as_string, count }) => ({
|
||||
x: key_as_string,
|
||||
? data.map<KpiHostHistogramData>(({ key, count }) => ({
|
||||
x: key,
|
||||
y: count.doc_count,
|
||||
}))
|
||||
: null;
|
||||
|
|
|
@ -32,7 +32,7 @@ export const mockRequest = {
|
|||
filterQuery: '',
|
||||
},
|
||||
query:
|
||||
'fragment ChartFields on KpiHostHistogramData {\n x: key\n y: count {\n value\n doc_count\n __typename\n }\n __typename\n}\n\nquery GetKpiHostsQuery($sourceId: ID!, $timerange: TimerangeInput!, $filterQuery: String) {\n source(id: $sourceId) {\n id\n KpiHosts(timerange: $timerange, filterQuery: $filterQuery) {\n hosts\n hostsHistogram {\n ...ChartFields\n __typename\n }\n authSuccess\n authSuccessHistogram {\n ...ChartFields\n __typename\n }\n authFailure\n authFailureHistogram {\n ...ChartFields\n __typename\n }\n uniqueSourceIps\n uniqueSourceIpsHistogram {\n ...ChartFields\n __typename\n }\n uniqueDestinationIps\n uniqueDestinationIpsHistogram {\n ...ChartFields\n __typename\n }\n __typename\n }\n __typename\n }\n}\n',
|
||||
'fragment KpiHostChartFields on KpiHostHistogramData {\n x\n y\n __typename\n}\n\nquery GetKpiHostsQuery($sourceId: ID!, $timerange: TimerangeInput!, $filterQuery: String, $defaultIndex: [String!]!) {\n source(id: $sourceId) {\n id\n KpiHosts(timerange: $timerange, filterQuery: $filterQuery, defaultIndex: $defaultIndex) {\n hosts\n hostsHistogram {\n ...KpiHostChartFields\n __typename\n }\n authSuccess\n authSuccessHistogram {\n ...KpiHostChartFields\n __typename\n }\n authFailure\n authFailureHistogram {\n ...KpiHostChartFields\n __typename\n }\n uniqueSourceIps\n uniqueSourceIpsHistogram {\n ...KpiHostChartFields\n __typename\n }\n uniqueDestinationIps\n uniqueDestinationIpsHistogram {\n ...KpiHostChartFields\n __typename\n }\n __typename\n }\n __typename\n }\n}\n',
|
||||
},
|
||||
query: {},
|
||||
};
|
||||
|
@ -241,75 +241,75 @@ export const mockResult = {
|
|||
hosts: 986,
|
||||
hostsHistogram: [
|
||||
{
|
||||
x: '2019-05-03T13:00:00.000Z',
|
||||
x: new Date('2019-05-03T13:00:00.000Z').valueOf(),
|
||||
y: 919,
|
||||
},
|
||||
{
|
||||
x: '2019-05-04T01:00:00.000Z',
|
||||
x: new Date('2019-05-04T01:00:00.000Z').valueOf(),
|
||||
y: 82,
|
||||
},
|
||||
{
|
||||
x: '2019-05-04T13:00:00.000Z',
|
||||
x: new Date('2019-05-04T13:00:00.000Z').valueOf(),
|
||||
y: 4,
|
||||
},
|
||||
],
|
||||
authSuccess: 61,
|
||||
authSuccessHistogram: [
|
||||
{
|
||||
x: '2019-05-03T13:00:00.000Z',
|
||||
x: new Date('2019-05-03T13:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
},
|
||||
{
|
||||
x: '2019-05-04T01:00:00.000Z',
|
||||
x: new Date('2019-05-04T01:00:00.000Z').valueOf(),
|
||||
y: 52,
|
||||
},
|
||||
{
|
||||
x: '2019-05-04T13:00:00.000Z',
|
||||
x: new Date('2019-05-04T13:00:00.000Z').valueOf(),
|
||||
y: 1,
|
||||
},
|
||||
],
|
||||
authFailure: 15722,
|
||||
authFailureHistogram: [
|
||||
{
|
||||
x: '2019-05-03T13:00:00.000Z',
|
||||
x: new Date('2019-05-03T13:00:00.000Z').valueOf(),
|
||||
y: 11731,
|
||||
},
|
||||
{
|
||||
x: '2019-05-04T01:00:00.000Z',
|
||||
x: new Date('2019-05-04T01:00:00.000Z').valueOf(),
|
||||
y: 3979,
|
||||
},
|
||||
{
|
||||
x: '2019-05-04T13:00:00.000Z',
|
||||
x: new Date('2019-05-04T13:00:00.000Z').valueOf(),
|
||||
y: 12,
|
||||
},
|
||||
],
|
||||
uniqueSourceIps: 1407,
|
||||
uniqueSourceIpsHistogram: [
|
||||
{
|
||||
x: '2019-05-03T13:00:00.000Z',
|
||||
x: new Date('2019-05-03T13:00:00.000Z').valueOf(),
|
||||
y: 1182,
|
||||
},
|
||||
{
|
||||
x: '2019-05-04T01:00:00.000Z',
|
||||
x: new Date('2019-05-04T01:00:00.000Z').valueOf(),
|
||||
y: 364,
|
||||
},
|
||||
{
|
||||
x: '2019-05-04T13:00:00.000Z',
|
||||
x: new Date('2019-05-04T13:00:00.000Z').valueOf(),
|
||||
y: 63,
|
||||
},
|
||||
],
|
||||
uniqueDestinationIps: 1954,
|
||||
uniqueDestinationIpsHistogram: [
|
||||
{
|
||||
x: '2019-05-03T13:00:00.000Z',
|
||||
x: new Date('2019-05-03T13:00:00.000Z').valueOf(),
|
||||
y: 1809,
|
||||
},
|
||||
{
|
||||
x: '2019-05-04T01:00:00.000Z',
|
||||
x: new Date('2019-05-04T01:00:00.000Z').valueOf(),
|
||||
y: 407,
|
||||
},
|
||||
{
|
||||
x: '2019-05-04T13:00:00.000Z',
|
||||
x: new Date('2019-05-04T13:00:00.000Z').valueOf(),
|
||||
y: 64,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -23,12 +23,12 @@ import { TermAggregation } from '../types';
|
|||
import { KpiNetworkHistogramData, KpiNetworkData } from '../../graphql/types';
|
||||
|
||||
const formatHistogramData = (
|
||||
data: Array<{ key_as_string: string; count: { value: number } }>
|
||||
data: Array<{ key: number; count: { value: number } }>
|
||||
): KpiNetworkHistogramData[] | null => {
|
||||
return data && data.length > 0
|
||||
? data.map<KpiNetworkHistogramData>(({ key_as_string, count }) => {
|
||||
? data.map<KpiNetworkHistogramData>(({ key, count }) => {
|
||||
return {
|
||||
x: key_as_string,
|
||||
x: key,
|
||||
y: getOr(null, 'value', count),
|
||||
};
|
||||
})
|
||||
|
|
|
@ -36,7 +36,7 @@ export const mockRequest = {
|
|||
filterQuery: '',
|
||||
},
|
||||
query:
|
||||
'fragment ChartFields on KpiNetworkHistogramData {\n key_as_string\n doc_count\n count {\n value\n __typename\n }\n __typename\n}\n\nquery GetKpiNetworkQuery($sourceId: ID!, $timerange: TimerangeInput!, $filterQuery: String) {\n source(id: $sourceId) {\n id\n KpiNetwork(timerange: $timerange, filterQuery: $filterQuery) {\n networkEvents\n networkEventsHistogram {\n ...ChartFields\n __typename\n }\n uniqueFlowId\n activeAgents\n uniqueSourcePrivateIps\n uniqueSourcePrivateIpsHistogram {\n ...ChartFields\n __typename\n }\n uniqueDestinationPrivateIps\n uniqueDestinationPrivateIpsHistogram {\n ...ChartFields\n __typename\n }\n dnsQueries\n tlsHandshakes\n __typename\n }\n __typename\n }\n}\n',
|
||||
'fragment KpiNetworkChartFields on KpiNetworkHistogramData {\n x\n y\n __typename\n}\n\nquery GetKpiNetworkQuery($sourceId: ID!, $timerange: TimerangeInput!, $filterQuery: String, $defaultIndex: [String!]!) {\n source(id: $sourceId) {\n id\n KpiNetwork(timerange: $timerange, filterQuery: $filterQuery, defaultIndex: $defaultIndex) {\n networkEvents\n uniqueFlowId\n uniqueSourcePrivateIps\n uniqueSourcePrivateIpsHistogram {\n ...KpiNetworkChartFields\n __typename\n }\n uniqueDestinationPrivateIps\n uniqueDestinationPrivateIpsHistogram {\n ...KpiNetworkChartFields\n __typename\n }\n dnsQueries\n tlsHandshakes\n __typename\n }\n __typename\n }\n}\n',
|
||||
},
|
||||
query: {},
|
||||
};
|
||||
|
@ -221,15 +221,15 @@ export const mockResult = {
|
|||
uniqueDestinationPrivateIps: 878,
|
||||
uniqueDestinationPrivateIpsHistogram: [
|
||||
{
|
||||
x: '2019-05-09T23:00:00.000Z',
|
||||
x: new Date('2019-05-09T23:00:00.000Z').valueOf(),
|
||||
y: 11,
|
||||
},
|
||||
{
|
||||
x: '2019-05-10T11:00:00.000Z',
|
||||
x: new Date('2019-05-10T11:00:00.000Z').valueOf(),
|
||||
y: 877,
|
||||
},
|
||||
{
|
||||
x: '2019-05-10T23:00:00.000Z',
|
||||
x: new Date('2019-05-10T23:00:00.000Z').valueOf(),
|
||||
y: 7,
|
||||
},
|
||||
],
|
||||
|
@ -237,15 +237,15 @@ export const mockResult = {
|
|||
uniqueSourcePrivateIps: 387,
|
||||
uniqueSourcePrivateIpsHistogram: [
|
||||
{
|
||||
x: '2019-05-09T23:00:00.000Z',
|
||||
x: new Date('2019-05-09T23:00:00.000Z').valueOf(),
|
||||
y: 14,
|
||||
},
|
||||
{
|
||||
x: '2019-05-10T11:00:00.000Z',
|
||||
x: new Date('2019-05-10T11:00:00.000Z').valueOf(),
|
||||
y: 385,
|
||||
},
|
||||
{
|
||||
x: '2019-05-10T23:00:00.000Z',
|
||||
x: new Date('2019-05-10T23:00:00.000Z').valueOf(),
|
||||
y: 7,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -24,22 +24,22 @@ const kpiHostsTests: KbnTestProvider = ({ getService }) => {
|
|||
hosts: 1,
|
||||
hostsHistogram: [
|
||||
{
|
||||
x: '2019-02-09T16:00:00.000Z',
|
||||
x: new Date('2019-02-09T16:00:00.000Z').valueOf(),
|
||||
y: 1,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T22:00:00.000Z',
|
||||
x: new Date('2019-02-09T22:00:00.000Z').valueOf(),
|
||||
y: 1,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-10T01:00:00.000Z',
|
||||
x: new Date('2019-02-10T01:00:00.000Z').valueOf(),
|
||||
y: 1,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
|
@ -51,22 +51,22 @@ const kpiHostsTests: KbnTestProvider = ({ getService }) => {
|
|||
uniqueSourceIps: 121,
|
||||
uniqueSourceIpsHistogram: [
|
||||
{
|
||||
x: '2019-02-09T16:00:00.000Z',
|
||||
x: new Date('2019-02-09T16:00:00.000Z').valueOf(),
|
||||
y: 52,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T22:00:00.000Z',
|
||||
x: new Date('2019-02-09T22:00:00.000Z').valueOf(),
|
||||
y: 31,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-10T01:00:00.000Z',
|
||||
x: new Date('2019-02-10T01:00:00.000Z').valueOf(),
|
||||
y: 88,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
|
@ -74,22 +74,22 @@ const kpiHostsTests: KbnTestProvider = ({ getService }) => {
|
|||
uniqueDestinationIps: 154,
|
||||
uniqueDestinationIpsHistogram: [
|
||||
{
|
||||
x: '2019-02-09T16:00:00.000Z',
|
||||
x: new Date('2019-02-09T16:00:00.000Z').valueOf(),
|
||||
y: 61,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T22:00:00.000Z',
|
||||
x: new Date('2019-02-09T22:00:00.000Z').valueOf(),
|
||||
y: 45,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-10T01:00:00.000Z',
|
||||
x: new Date('2019-02-10T01:00:00.000Z').valueOf(),
|
||||
y: 114,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
|
@ -128,22 +128,22 @@ const kpiHostsTests: KbnTestProvider = ({ getService }) => {
|
|||
hosts: 1,
|
||||
hostsHistogram: [
|
||||
{
|
||||
x: '2019-02-09T16:00:00.000Z',
|
||||
x: new Date('2019-02-09T16:00:00.000Z').valueOf(),
|
||||
y: 1,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T22:00:00.000Z',
|
||||
x: new Date('2019-02-09T22:00:00.000Z').valueOf(),
|
||||
y: 1,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-10T01:00:00.000Z',
|
||||
x: new Date('2019-02-10T01:00:00.000Z').valueOf(),
|
||||
y: 1,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
|
@ -155,22 +155,22 @@ const kpiHostsTests: KbnTestProvider = ({ getService }) => {
|
|||
uniqueSourceIps: 121,
|
||||
uniqueSourceIpsHistogram: [
|
||||
{
|
||||
x: '2019-02-09T16:00:00.000Z',
|
||||
x: new Date('2019-02-09T16:00:00.000Z').valueOf(),
|
||||
y: 52,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T22:00:00.000Z',
|
||||
x: new Date('2019-02-09T22:00:00.000Z').valueOf(),
|
||||
y: 31,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-10T01:00:00.000Z',
|
||||
x: new Date('2019-02-10T01:00:00.000Z').valueOf(),
|
||||
y: 88,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
|
@ -178,22 +178,22 @@ const kpiHostsTests: KbnTestProvider = ({ getService }) => {
|
|||
uniqueDestinationIps: 154,
|
||||
uniqueDestinationIpsHistogram: [
|
||||
{
|
||||
x: '2019-02-09T16:00:00.000Z',
|
||||
x: new Date('2019-02-09T16:00:00.000Z').valueOf(),
|
||||
y: 61,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T22:00:00.000Z',
|
||||
x: new Date('2019-02-09T22:00:00.000Z').valueOf(),
|
||||
y: 45,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-10T01:00:00.000Z',
|
||||
x: new Date('2019-02-10T01:00:00.000Z').valueOf(),
|
||||
y: 114,
|
||||
__typename: 'KpiHostHistogramData',
|
||||
},
|
||||
|
|
|
@ -26,22 +26,22 @@ const kpiNetworkTests: KbnTestProvider = ({ getService }) => {
|
|||
uniqueSourcePrivateIps: 8,
|
||||
uniqueSourcePrivateIpsHistogram: [
|
||||
{
|
||||
x: '2019-02-09T16:00:00.000Z',
|
||||
x: new Date('2019-02-09T16:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T22:00:00.000Z',
|
||||
x: new Date('2019-02-09T22:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-10T01:00:00.000Z',
|
||||
x: new Date('2019-02-10T01:00:00.000Z').valueOf(),
|
||||
y: 7,
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
},
|
||||
|
@ -50,22 +50,22 @@ const kpiNetworkTests: KbnTestProvider = ({ getService }) => {
|
|||
uniqueDestinationPrivateIpsHistogram: [
|
||||
{
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
x: '2019-02-09T16:00:00.000Z',
|
||||
x: new Date('2019-02-09T16:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
},
|
||||
{
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
},
|
||||
{
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
x: '2019-02-09T22:00:00.000Z',
|
||||
x: new Date('2019-02-09T22:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
},
|
||||
{
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
x: '2019-02-10T01:00:00.000Z',
|
||||
x: new Date('2019-02-10T01:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
},
|
||||
],
|
||||
|
@ -107,22 +107,22 @@ const kpiNetworkTests: KbnTestProvider = ({ getService }) => {
|
|||
uniqueSourcePrivateIps: 8,
|
||||
uniqueSourcePrivateIpsHistogram: [
|
||||
{
|
||||
x: '2019-02-09T16:00:00.000Z',
|
||||
x: new Date('2019-02-09T16:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-09T22:00:00.000Z',
|
||||
x: new Date('2019-02-09T22:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
},
|
||||
{
|
||||
x: '2019-02-10T01:00:00.000Z',
|
||||
x: new Date('2019-02-10T01:00:00.000Z').valueOf(),
|
||||
y: 7,
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
},
|
||||
|
@ -131,22 +131,22 @@ const kpiNetworkTests: KbnTestProvider = ({ getService }) => {
|
|||
uniqueDestinationPrivateIpsHistogram: [
|
||||
{
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
x: '2019-02-09T16:00:00.000Z',
|
||||
x: new Date('2019-02-09T16:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
},
|
||||
{
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
x: '2019-02-09T19:00:00.000Z',
|
||||
x: new Date('2019-02-09T19:00:00.000Z').valueOf(),
|
||||
y: 0,
|
||||
},
|
||||
{
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
x: '2019-02-09T22:00:00.000Z',
|
||||
x: new Date('2019-02-09T22:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
},
|
||||
{
|
||||
__typename: 'KpiNetworkHistogramData',
|
||||
x: '2019-02-10T01:00:00.000Z',
|
||||
x: new Date('2019-02-10T01:00:00.000Z').valueOf(),
|
||||
y: 8,
|
||||
},
|
||||
],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue