From d744eaec8ce40516fd0d6e81ba784e2dec5ca24f Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 21 Dec 2020 15:22:42 +0100 Subject: [PATCH 1/3] [ML] Data Frame Analytics: Scatterplot Matrix Fixes (#86357) - use ml API service from the Kibana context - adds jest tests for the Vega Lite Spec generator - fix chart layout overflow with too many fields selected --- .../scatterplot_matrix.scss | 2 + .../scatterplot_matrix/scatterplot_matrix.tsx | 6 +- .../scatterplot_matrix_vega_lite_spec.test.ts | 170 ++++++++++++++++++ .../scatterplot_matrix_vega_lite_spec.ts | 21 ++- 4 files changed, 188 insertions(+), 11 deletions(-) create mode 100644 x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix_vega_lite_spec.test.ts diff --git a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.scss b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.scss index f59c27dccc7426..6a4fbd97b3bddd 100644 --- a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.scss +++ b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.scss @@ -1,4 +1,6 @@ .mlScatterplotMatrix { + overflow-x: auto; + .vega-bind span { font-size: $euiFontSizeXS; padding: 0 $euiSizeXS; diff --git a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx index ad9f63b10ebdd2..b1ee9afb17788a 100644 --- a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx +++ b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx @@ -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'; @@ -72,6 +72,8 @@ export const ScatterplotMatrix: FC = ({ 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(false); @@ -147,7 +149,7 @@ export const ScatterplotMatrix: FC = ({ } : { match_all: {} }; - const resp: SearchResponse7 = await ml.esSearch({ + const resp: SearchResponse7 = await esSearch({ index, body: { fields: queryFields, diff --git a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix_vega_lite_spec.test.ts b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix_vega_lite_spec.test.ts new file mode 100644 index 00000000000000..dd467161ff489e --- /dev/null +++ b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix_vega_lite_spec.test.ts @@ -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' }, + ]); + }); +}); diff --git a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix_vega_lite_spec.ts b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix_vega_lite_spec.ts index ee93074d9e034c..9e0834dd8b9221 100644 --- a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix_vega_lite_spec.ts +++ b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix_vega_lite_spec.ts @@ -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, @@ -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', From 8d5dd1de63d44b42db7acb8ba6fd0080cee0eeed Mon Sep 17 00:00:00 2001 From: ymao1 Date: Mon, 21 Dec 2020 10:11:19 -0500 Subject: [PATCH 2/3] [Alerting] Updating wording on "Notify" dropdown (#86453) * Updating wording * PR fixes Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../sections/alert_form/alert_notify_when.tsx | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_notify_when.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_notify_when.tsx index da872484dda4a2..eeb8b9f77a9b89 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_notify_when.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_notify_when.tsx @@ -29,13 +29,18 @@ const DEFAULT_NOTIFY_WHEN_VALUE: AlertNotifyWhenType = 'onActionGroupChange'; const NOTIFY_WHEN_OPTIONS: Array> = [ { value: 'onActionGroupChange', - inputDisplay: 'Run only on status change', + inputDisplay: i18n.translate( + 'xpack.triggersActionsUI.sections.alertForm.alertNotifyWhen.onActionGroupChange.display', + { + defaultMessage: 'Only on status change.', + } + ), 'data-test-subj': 'onActionGroupChange', dropdownDisplay: ( @@ -52,13 +57,18 @@ const NOTIFY_WHEN_OPTIONS: Array> = [ }, { value: 'onActiveAlert', - inputDisplay: 'Run every time alert is active', + inputDisplay: i18n.translate( + 'xpack.triggersActionsUI.sections.alertForm.alertNotifyWhen.onActiveAlert.display', + { + defaultMessage: 'Every time alert is active', + } + ), 'data-test-subj': 'onActiveAlert', dropdownDisplay: ( @@ -75,13 +85,18 @@ const NOTIFY_WHEN_OPTIONS: Array> = [ }, { value: 'onThrottleInterval', - inputDisplay: 'Set a custom action interval', + inputDisplay: i18n.translate( + 'xpack.triggersActionsUI.sections.alertForm.alertNotifyWhen.onThrottleInterval.display', + { + defaultMessage: 'On a custom action interval', + } + ), 'data-test-subj': 'onThrottleInterval', dropdownDisplay: ( @@ -143,7 +158,7 @@ export const AlertNotifyWhen = ({ <> {' '} Date: Mon, 21 Dec 2020 08:18:32 -0700 Subject: [PATCH 3/3] [Security Solution] Fixing jest warnings and errors (#86532) --- .../components/case_action_bar/index.tsx | 20 ++++++------- .../event_details/event_details.test.tsx | 30 +++++++++++-------- .../events_viewer/events_viewer.test.tsx | 9 +++++- .../exceptions/builder/entry_item.test.tsx | 30 +++++++++++-------- .../components/last_updated/index.test.tsx | 14 ++++++--- .../ml/score/anomaly_score.test.tsx | 5 ++-- .../ml/score/anomaly_scores.test.tsx | 5 ++-- .../score/create_descriptions_list.test.tsx | 14 ++++----- .../properties/use_create_timeline.tsx | 4 +-- .../timeline/query_bar/index.test.tsx | 9 +++--- 10 files changed, 83 insertions(+), 57 deletions(-) diff --git a/x-pack/plugins/security_solution/public/cases/components/case_action_bar/index.tsx b/x-pack/plugins/security_solution/public/cases/components/case_action_bar/index.tsx index 3bad7b7870a537..3a65ea724d7641 100644 --- a/x-pack/plugins/security_solution/public/cases/components/case_action_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/case_action_bar/index.tsx @@ -101,17 +101,17 @@ const CaseActionBarComponent: React.FC = ({ + + + + {i18n.SYNC_ALERTS} + + + + + + - - - - {i18n.SYNC_ALERTS} - - - - - - { @@ -36,18 +37,21 @@ describe('EventDetails', () => { isAlert: true, }; - const wrapper = mount( - - - - ); - - const alertsWrapper = mount( - - - - ); - + let wrapper: ReactWrapper; + let alertsWrapper: ReactWrapper; + beforeAll(async () => { + wrapper = mount( + + + + ) as ReactWrapper; + alertsWrapper = mount( + + + + ) as ReactWrapper; + await waitFor(() => wrapper.update()); + }); describe('rendering', () => { test('should match snapshot', () => { const shallowWrap = shallow(); diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.test.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.test.tsx index 5e5bdebffa1828..423b3566e4eb5a 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.test.tsx @@ -30,6 +30,13 @@ jest.mock('../../../timelines/components/graph_overlay', () => ({ GraphOverlay: jest.fn(() =>
), })); +jest.mock('@elastic/eui', () => { + const original = jest.requireActual('@elastic/eui'); + return { + ...original, + useDataGridColumnSorting: jest.fn(), + }; +}); jest.mock('../../../timelines/containers', () => ({ useTimelineEvents: jest.fn(), })); @@ -84,7 +91,7 @@ const eventsViewerDefaultProps = { sort: [ { columnId: 'foo', - sortDirection: 'none' as SortDirection, + sortDirection: 'asc' as SortDirection, }, ], scopeId: SourcererScopeName.timeline, diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/builder/entry_item.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/builder/entry_item.test.tsx index 60b2f079c869bf..ba894e0410b04d 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/builder/entry_item.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/builder/entry_item.test.tsx @@ -25,6 +25,7 @@ import { } from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { getFoundListSchemaMock } from '../../../../../../lists/common/schemas/response/found_list_schema.mock'; import { getEmptyValue } from '../../empty_value'; +import { waitFor } from '@testing-library/dom'; // mock out lists hook const mockStart = jest.fn(); @@ -583,7 +584,7 @@ describe('BuilderEntryItem', () => { ); }); - test('it invokes "setErrorsExist" when user touches value input and leaves empty', () => { + test('it invokes "setErrorsExist" when user touches value input and leaves empty', async () => { const mockSetErrorExists = jest.fn(); wrapper = mount( { /> ); - ((wrapper.find(EuiComboBox).at(2).props() as unknown) as { - onBlur: () => void; - }).onBlur(); + await waitFor(() => { + ((wrapper.find(EuiComboBox).at(2).props() as unknown) as { + onBlur: () => void; + }).onBlur(); + }); expect(mockSetErrorExists).toHaveBeenCalledWith(true); }); - test('it invokes "setErrorsExist" when invalid value inputted for field value input', () => { + test('it invokes "setErrorsExist" when invalid value inputted for field value input', async () => { const mockSetErrorExists = jest.fn(); wrapper = mount( { setErrorsExist={mockSetErrorExists} /> ); - ((wrapper.find(EuiComboBox).at(2).props() as unknown) as { - onBlur: () => void; - }).onBlur(); - // Invalid input because field type is number - ((wrapper.find(EuiComboBox).at(2).props() as unknown) as { - onSearchChange: (arg: string) => void; - }).onSearchChange('hellooo'); + await waitFor(() => { + ((wrapper.find(EuiComboBox).at(2).props() as unknown) as { + onBlur: () => void; + }).onBlur(); + + // Invalid input because field type is number + ((wrapper.find(EuiComboBox).at(2).props() as unknown) as { + onSearchChange: (arg: string) => void; + }).onSearchChange('hellooo'); + }); expect(mockSetErrorExists).toHaveBeenCalledWith(true); }); diff --git a/x-pack/plugins/security_solution/public/common/components/last_updated/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/last_updated/index.test.tsx index db42794448c533..31ba5530f60829 100644 --- a/x-pack/plugins/security_solution/public/common/components/last_updated/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/last_updated/index.test.tsx @@ -8,12 +8,18 @@ import { mount } from 'enzyme'; import { I18nProvider } from '@kbn/i18n/react'; import { LastUpdatedAt } from './'; +jest.mock('@kbn/i18n/react', () => { + const originalModule = jest.requireActual('@kbn/i18n/react'); + const FormattedRelative = jest.fn(); + FormattedRelative.mockImplementation(() => '2 minutes ago'); + + return { + ...originalModule, + FormattedRelative, + }; +}); describe('LastUpdatedAt', () => { - beforeEach(() => { - Date.now = jest.fn().mockReturnValue(1603995369774); - }); - test('it renders correct relative time', () => { const wrapper = mount( diff --git a/x-pack/plugins/security_solution/public/common/components/ml/score/anomaly_score.test.tsx b/x-pack/plugins/security_solution/public/common/components/ml/score/anomaly_score.test.tsx index cb10c61302d3c2..745bd486524adb 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/score/anomaly_score.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/score/anomaly_score.test.tsx @@ -14,6 +14,7 @@ import { mockAnomalies } from '../mock'; import { TestProviders } from '../../../mock/test_providers'; import { useMountAppended } from '../../../utils/use_mount_appended'; import { Anomalies } from '../types'; +import { waitFor } from '@testing-library/dom'; const startDate: string = '2020-07-07T08:20:18.966Z'; const endDate: string = '3000-01-01T00:00:00.000Z'; @@ -57,7 +58,7 @@ describe('anomaly_scores', () => { expect(wrapper.find('[data-test-subj="anomaly-description-list"]').exists()).toEqual(false); }); - test('show a popover on a mouse click', () => { + test('show a popover on a mouse click', async () => { const wrapper = mount( { ); wrapper.find('[data-test-subj="anomaly-score-popover"]').first().simulate('click'); - wrapper.update(); + await waitFor(() => wrapper.update()); expect(wrapper.find('[data-test-subj="anomaly-description-list"]').exists()).toEqual(true); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/ml/score/anomaly_scores.test.tsx b/x-pack/plugins/security_solution/public/common/components/ml/score/anomaly_scores.test.tsx index 52151f217e01ad..edbb3528a098af 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/score/anomaly_scores.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/score/anomaly_scores.test.tsx @@ -15,6 +15,7 @@ import { TestProviders } from '../../../mock/test_providers'; import { getEmptyValue } from '../../empty_value'; import { Anomalies } from '../types'; import { useMountAppended } from '../../../utils/use_mount_appended'; +import { waitFor } from '@testing-library/dom'; const startDate: string = '2020-07-07T08:20:18.966Z'; const endDate: string = '3000-01-01T00:00:00.000Z'; @@ -121,7 +122,7 @@ describe('anomaly_scores', () => { expect(wrapper.find('[data-test-subj="anomaly-description-list"]').exists()).toEqual(false); }); - test('showing a popover on a mouse click', () => { + test('showing a popover on a mouse click', async () => { const wrapper = mount( { ); wrapper.find('[data-test-subj="anomaly-score-popover"]').first().simulate('click'); - wrapper.update(); + await waitFor(() => wrapper.update()); expect(wrapper.find('[data-test-subj="anomaly-description-list"]').exists()).toEqual(true); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/ml/score/create_descriptions_list.test.tsx b/x-pack/plugins/security_solution/public/common/components/ml/score/create_descriptions_list.test.tsx index e9dd5f922e26a5..695b4dd8caea45 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/score/create_descriptions_list.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/score/create_descriptions_list.test.tsx @@ -10,6 +10,7 @@ import { mockAnomalies } from '../mock'; import { createDescriptionList } from './create_description_list'; import { EuiDescriptionList } from '@elastic/eui'; import { Anomaly } from '../types'; +import { waitFor } from '@testing-library/dom'; jest.mock('../../../lib/kibana'); @@ -38,7 +39,7 @@ describe('create_description_list', () => { expect(wrapper).toMatchSnapshot(); }); - test('it calls the narrow date range function on click', () => { + test('it calls the narrow date range function on click', async () => { const wrapper = mount( { .find('[data-test-subj="anomaly-description-narrow-range-link"]') .first() .simulate('click'); - wrapper.update(); + await waitFor(() => wrapper.update()); expect(narrowDateRange.mock.calls.length).toBe(1); }); - test('it should the narrow date range with the score', () => { + test('it should the narrow date range with the score', async () => { const wrapper = mount( { .find('[data-test-subj="anomaly-description-narrow-range-link"]') .first() .simulate('click'); - wrapper.update(); + await waitFor(() => wrapper.update()); const expected: Anomaly = { detectorIndex: 0, @@ -119,7 +120,7 @@ describe('create_description_list', () => { expect(narrowDateRange.mock.calls[0][0]).toEqual(expected); }); - test('it should call the narrow date range with the interval', () => { + test('it should call the narrow date range with the interval', async () => { const wrapper = mount( { .find('[data-test-subj="anomaly-description-narrow-range-link"]') .first() .simulate('click'); - wrapper.update(); - + await waitFor(() => wrapper.update()); expect(narrowDateRange.mock.calls[0][1]).toEqual('hours'); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_create_timeline.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_create_timeline.tsx index 12845477e0f393..96187329a21c65 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_create_timeline.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/use_create_timeline.tsx @@ -123,13 +123,13 @@ export const useCreateTimelineButton = ({ timelineId, timelineType, closeGearMen }; const dataTestSubjPrefix = timelineType === TimelineType.template ? `template-timeline-new` : `timeline-new`; - + const { fill: noThanks, ...propsWithoutFill } = buttonProps; return outline ? ( {title} ) : ( - + {title} ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.test.tsx index 1226dabe485590..959504249e1270 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.test.tsx @@ -23,6 +23,7 @@ import { getDataProviderFilter, TIMELINE_FILTER_DROP_AREA, } from './index'; +import { waitFor } from '@testing-library/dom'; const mockUiSettingsForFilterManager = coreMock.createStart().uiSettings; @@ -181,7 +182,7 @@ describe('Timeline QueryBar ', () => { }); describe('#onSavedQuery', () => { - test('is only reference that changed when dataProviders props get updated', () => { + test('is only reference that changed when dataProviders props get updated', async () => { const Proxy = (props: QueryBarTimelineComponentProps) => ( @@ -213,13 +214,13 @@ describe('Timeline QueryBar ', () => { const onSavedQueryRef = queryBarProps.onSavedQuery; wrapper.setProps({ dataProviders: mockDataProviders.slice(1, 0) }); - wrapper.update(); + await waitFor(() => wrapper.update()); expect(onSavedQueryRef).not.toEqual(wrapper.find(QueryBar).props().onSavedQuery); expect(onSubmitQueryRef).toEqual(wrapper.find(QueryBar).props().onSubmitQuery); }); - test('is only reference that changed when savedQueryId props get updated', () => { + test('is only reference that changed when savedQueryId props get updated', async () => { const Proxy = (props: QueryBarTimelineComponentProps) => ( @@ -253,7 +254,7 @@ describe('Timeline QueryBar ', () => { wrapper.setProps({ savedQueryId: 'new', }); - wrapper.update(); + await waitFor(() => wrapper.update()); expect(onSavedQueryRef).not.toEqual(wrapper.find(QueryBar).props().onSavedQuery); expect(onSubmitQueryRef).toEqual(wrapper.find(QueryBar).props().onSubmitQuery);