Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into lens/reference-ui
Browse files Browse the repository at this point in the history
  • Loading branch information
wylieconlon committed Dec 21, 2020
2 parents 025a714 + 513138b commit 0850115
Show file tree
Hide file tree
Showing 15 changed files with 293 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.mlScatterplotMatrix {
overflow-x: auto;

.vega-bind span {
font-size: $euiFontSizeXS;
padding: 0 $euiSizeXS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { i18n } from '@kbn/i18n';

import type { SearchResponse7 } from '../../../../common/types/es_client';

import { ml } from '../../services/ml_api_service';
import { useMlApiContext } from '../../contexts/kibana';

import { getProcessedFields } from '../data_grid';
import { useCurrentEuiTheme } from '../color_range_legend';
Expand Down Expand Up @@ -72,6 +72,8 @@ export const ScatterplotMatrix: FC<ScatterplotMatrixProps> = ({
color,
legendType,
}) => {
const { esSearch } = useMlApiContext();

// dynamicSize is optionally used for outlier charts where the scatterplot marks
// are sized according to outlier_score
const [dynamicSize, setDynamicSize] = useState<boolean>(false);
Expand Down Expand Up @@ -147,7 +149,7 @@ export const ScatterplotMatrix: FC<ScatterplotMatrixProps> = ({
}
: { match_all: {} };

const resp: SearchResponse7 = await ml.esSearch({
const resp: SearchResponse7 = await esSearch({
index,
body: {
fields: queryFields,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

// @ts-ignore
import { compile } from 'vega-lite/build-es5/vega-lite';

import euiThemeLight from '@elastic/eui/dist/eui_theme_light.json';

import {
getColorSpec,
getScatterplotMatrixVegaLiteSpec,
COLOR_OUTLIER,
COLOR_RANGE_NOMINAL,
DEFAULT_COLOR,
LEGEND_TYPES,
} from './scatterplot_matrix_vega_lite_spec';

describe('getColorSpec()', () => {
it('should return the default color for non-outlier specs', () => {
const colorSpec = getColorSpec(euiThemeLight, false);

expect(colorSpec).toEqual({ value: DEFAULT_COLOR });
});

it('should return a conditional spec for outliers', () => {
const colorSpec = getColorSpec(euiThemeLight, true);

expect(colorSpec).toEqual({
condition: {
test: "(datum['outlier_score'] >= mlOutlierScoreThreshold.cutoff)",
value: COLOR_OUTLIER,
},
value: euiThemeLight.euiColorMediumShade,
});
});

it('should return a field based spec for non-outlier specs with legendType supplied', () => {
const colorName = 'the-color-field';

const colorSpec = getColorSpec(euiThemeLight, false, colorName, LEGEND_TYPES.NOMINAL);

expect(colorSpec).toEqual({
field: colorName,
scale: {
range: COLOR_RANGE_NOMINAL,
},
type: 'nominal',
});
});
});

describe('getScatterplotMatrixVegaLiteSpec()', () => {
it('should return the default spec for non-outliers without a legend', () => {
const data = [{ x: 1, y: 1 }];

const vegaLiteSpec = getScatterplotMatrixVegaLiteSpec(data, ['x', 'y'], euiThemeLight);

// A valid Vega Lite spec shouldn't throw an error when compiled.
expect(() => compile(vegaLiteSpec)).not.toThrow();

expect(vegaLiteSpec.repeat).toEqual({
column: ['x', 'y'],
row: ['y', 'x'],
});
expect(vegaLiteSpec.spec.transform).toEqual([
{ as: 'x', calculate: "datum['x']" },
{ as: 'y', calculate: "datum['y']" },
]);
expect(vegaLiteSpec.spec.data.values).toEqual(data);
expect(vegaLiteSpec.spec.mark).toEqual({
opacity: 0.75,
size: 8,
type: 'circle',
});
expect(vegaLiteSpec.spec.encoding.color).toEqual({ value: DEFAULT_COLOR });
expect(vegaLiteSpec.spec.encoding.tooltip).toEqual([
{ field: 'x', type: 'quantitative' },
{ field: 'y', type: 'quantitative' },
]);
});

it('should return the spec for outliers', () => {
const data = [{ x: 1, y: 1 }];

const vegaLiteSpec = getScatterplotMatrixVegaLiteSpec(data, ['x', 'y'], euiThemeLight, 'ml');

// A valid Vega Lite spec shouldn't throw an error when compiled.
expect(() => compile(vegaLiteSpec)).not.toThrow();

expect(vegaLiteSpec.repeat).toEqual({
column: ['x', 'y'],
row: ['y', 'x'],
});
expect(vegaLiteSpec.spec.transform).toEqual([
{ as: 'x', calculate: "datum['x']" },
{ as: 'y', calculate: "datum['y']" },
{
as: 'outlier_score',
calculate: "datum['ml.outlier_score']",
},
]);
expect(vegaLiteSpec.spec.data.values).toEqual(data);
expect(vegaLiteSpec.spec.mark).toEqual({
opacity: 0.75,
size: 8,
type: 'circle',
});
expect(vegaLiteSpec.spec.encoding.color).toEqual({
condition: {
test: "(datum['outlier_score'] >= mlOutlierScoreThreshold.cutoff)",
value: COLOR_OUTLIER,
},
value: euiThemeLight.euiColorMediumShade,
});
expect(vegaLiteSpec.spec.encoding.tooltip).toEqual([
{ field: 'x', type: 'quantitative' },
{ field: 'y', type: 'quantitative' },
{
field: 'outlier_score',
format: '.3f',
type: 'quantitative',
},
]);
});

it('should return the spec for classification', () => {
const data = [{ x: 1, y: 1 }];

const vegaLiteSpec = getScatterplotMatrixVegaLiteSpec(
data,
['x', 'y'],
euiThemeLight,
undefined,
'the-color-field',
LEGEND_TYPES.NOMINAL
);

// A valid Vega Lite spec shouldn't throw an error when compiled.
expect(() => compile(vegaLiteSpec)).not.toThrow();

expect(vegaLiteSpec.repeat).toEqual({
column: ['x', 'y'],
row: ['y', 'x'],
});
expect(vegaLiteSpec.spec.transform).toEqual([
{ as: 'x', calculate: "datum['x']" },
{ as: 'y', calculate: "datum['y']" },
]);
expect(vegaLiteSpec.spec.data.values).toEqual(data);
expect(vegaLiteSpec.spec.mark).toEqual({
opacity: 0.75,
size: 8,
type: 'circle',
});
expect(vegaLiteSpec.spec.encoding.color).toEqual({
field: 'the-color-field',
scale: {
range: COLOR_RANGE_NOMINAL,
},
type: 'nominal',
});
expect(vegaLiteSpec.spec.encoding.tooltip).toEqual([
{ field: 'x', type: 'quantitative' },
{ field: 'y', type: 'quantitative' },
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ export const OUTLIER_SCORE_FIELD = 'outlier_score';

const SCATTERPLOT_SIZE = 125;

const DEFAULT_COLOR = euiPaletteColorBlind()[0];
const COLOR_OUTLIER = euiPaletteNegative(2)[1];
const COLOR_RANGE_NOMINAL = euiPaletteColorBlind({ rotations: 2 });
const COLOR_RANGE_QUANTITATIVE = euiPalettePositive(5);
export const DEFAULT_COLOR = euiPaletteColorBlind()[0];
export const COLOR_OUTLIER = euiPaletteNegative(2)[1];
export const COLOR_RANGE_NOMINAL = euiPaletteColorBlind({ rotations: 2 });
export const COLOR_RANGE_QUANTITATIVE = euiPalettePositive(5);

const getColorSpec = (
export const getColorSpec = (
euiTheme: typeof euiThemeLight,
outliers = true,
color?: string,
Expand Down Expand Up @@ -72,10 +72,13 @@ export const getScatterplotMatrixVegaLiteSpec = (
calculate: `datum['${column}']`,
as: column,
}));
transform.push({
calculate: `datum['${resultsField}.${OUTLIER_SCORE_FIELD}']`,
as: OUTLIER_SCORE_FIELD,
});

if (resultsField !== undefined) {
transform.push({
calculate: `datum['${resultsField}.${OUTLIER_SCORE_FIELD}']`,
as: OUTLIER_SCORE_FIELD,
});
}

return {
$schema: 'https://vega.github.io/schema/vega-lite/v4.17.0.json',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,17 @@ const CaseActionBarComponent: React.FC<CaseActionBarProps> = ({
<EuiDescriptionList compressed>
<EuiFlexGroup gutterSize="l" alignItems="center">
<EuiFlexItem>
<EuiDescriptionListTitle>
<EuiFlexGroup component="span" alignItems="center" gutterSize="xs">
<EuiFlexItem grow={false}>
<span>{i18n.SYNC_ALERTS}</span>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiIconTip content={i18n.SYNC_ALERTS_HELP} />
</EuiFlexItem>
</EuiFlexGroup>
</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
<EuiDescriptionListTitle>
<EuiFlexGroup component="span" alignItems="center" gutterSize="xs">
<EuiFlexItem grow={false}>
<span>{i18n.SYNC_ALERTS}</span>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiIconTip content={i18n.SYNC_ALERTS_HELP} />
</EuiFlexItem>
</EuiFlexGroup>
</EuiDescriptionListTitle>
<SyncAlertsSwitch
disabled={disabled || isLoading}
isSynced={caseData.settings.syncAlerts}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { shallow } from 'enzyme';
import { ReactWrapper, shallow } from 'enzyme';
import React from 'react';

import '../../mock/match_media';
Expand All @@ -16,6 +16,7 @@ import { mockBrowserFields } from '../../containers/source/mock';
import { useMountAppended } from '../../utils/use_mount_appended';
import { mockAlertDetailsData } from './__mocks__';
import { TimelineEventsDetailsItem } from '../../../../common/search_strategy';
import { waitFor } from '@testing-library/dom';

jest.mock('../link_to');
describe('EventDetails', () => {
Expand All @@ -36,18 +37,21 @@ describe('EventDetails', () => {
isAlert: true,
};

const wrapper = mount(
<TestProviders>
<EventDetails {...defaultProps} />
</TestProviders>
);

const alertsWrapper = mount(
<TestProviders>
<EventDetails {...alertsProps} />
</TestProviders>
);

let wrapper: ReactWrapper;
let alertsWrapper: ReactWrapper;
beforeAll(async () => {
wrapper = mount(
<TestProviders>
<EventDetails {...defaultProps} />
</TestProviders>
) as ReactWrapper;
alertsWrapper = mount(
<TestProviders>
<EventDetails {...alertsProps} />
</TestProviders>
) as ReactWrapper;
await waitFor(() => wrapper.update());
});
describe('rendering', () => {
test('should match snapshot', () => {
const shallowWrap = shallow(<EventDetails {...defaultProps} />);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ jest.mock('../../../timelines/components/graph_overlay', () => ({
GraphOverlay: jest.fn(() => <div />),
}));

jest.mock('@elastic/eui', () => {
const original = jest.requireActual('@elastic/eui');
return {
...original,
useDataGridColumnSorting: jest.fn(),
};
});
jest.mock('../../../timelines/containers', () => ({
useTimelineEvents: jest.fn(),
}));
Expand Down Expand Up @@ -84,7 +91,7 @@ const eventsViewerDefaultProps = {
sort: [
{
columnId: 'foo',
sortDirection: 'none' as SortDirection,
sortDirection: 'asc' as SortDirection,
},
],
scopeId: SourcererScopeName.timeline,
Expand Down
Loading

0 comments on commit 0850115

Please sign in to comment.