diff --git a/packages/kbn-babel-preset/styled_components_files.js b/packages/kbn-babel-preset/styled_components_files.js index 2cd85bf9e3657..d885470c919fd 100644 --- a/packages/kbn-babel-preset/styled_components_files.js +++ b/packages/kbn-babel-preset/styled_components_files.js @@ -176,7 +176,6 @@ module.exports = { /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]and_or_badge[\/\\]rounded_badge_antenna.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]auto_download[\/\\]auto_download.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]conditions_table[\/\\]index.stories.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]drag_and_drop[\/\\]draggable_wrapper.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]drag_and_drop[\/\\]droppable_wrapper.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]drag_and_drop[\/\\]provider_container.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]empty_value[\/\\]empty_value.test.tsx/, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/__snapshots__/cell_actions_renderer.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/__snapshots__/cell_actions_renderer.test.tsx.snap new file mode 100644 index 0000000000000..d933bda4164e5 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/__snapshots__/cell_actions_renderer.test.tsx.snap @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`cell actions renderer rendering it renders theCellActionsRenderer 1`] = ` +
+
+ + + + A child of this + + + +
+
+`; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/cell_actions_renderer.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/cell_actions_renderer.test.tsx new file mode 100644 index 0000000000000..3df8ba94fa906 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/cell_actions_renderer.test.tsx @@ -0,0 +1,268 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { render } from '@testing-library/react'; +import React from 'react'; +import { TableId } from '@kbn/securitysolution-data-table'; +import { TestProviders } from '../../mock'; +import { TimelineId } from '../../../../common/types'; +import { ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID } from '../../../timelines/components/row_renderers_browser/constants'; + +import { CellActionsRenderer } from './cell_actions_renderer'; + +jest.mock('../../lib/kibana'); + +const MockSecurityCellActions = jest.fn(({ children }: { children: React.ReactNode }) => ( +
{children}
+)); +jest.mock('.', () => ({ + ...jest.requireActual('.'), + SecurityCellActions: (params: { children: React.ReactNode }) => MockSecurityCellActions(params), +})); + +const mockSourcererScopeId = 'testSourcererScopeId'; +jest.mock('../../../helpers', () => ({ + getSourcererScopeId: jest.fn(() => mockSourcererScopeId), +})); + +describe('cell actions renderer', () => { + describe('rendering', () => { + test('it renders theCellActionsRenderer', () => { + const { container } = render( + + {'A child of this'} + + ); + expect(container.firstChild).toMatchSnapshot(); + }); + }); + + describe('CellActionsRenderer', () => { + test('it works with just an id, field, and value and is some value', () => { + const field = 'some-field'; + const value = 'some value'; + const { getByText } = render( + + + + ); + expect(getByText(value)).toBeInTheDocument(); + }); + + test('it returns null if value is undefined', () => { + const { container } = render(); + expect(container.firstChild).toBeNull(); + }); + + test('it returns null if value is null', () => { + const { container } = render(); + expect(container.firstChild).toBeNull(); + }); + + test('it renders content with tooltip when tooltip is not explicitly provided', () => { + const { getByText } = render( + + + + ); + + expect(getByText('a field value')).toBeInTheDocument(); + }); + + test('it renders content with custom tooltip when string is provided', () => { + const { getByText } = render( + + + + ); + + expect(getByText('a field value')).toBeInTheDocument(); + }); + + test('it renders content with custom tooltip when element is provided', () => { + const { getByText } = render( + + {'tooltip'}} + value="a field value" + /> + + ); + + expect(getByText('a field value')).toBeInTheDocument(); + }); + + test('it does NOT render a tooltip when tooltipContent is null', () => { + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId('source.bytes-tooltip')).not.toBeInTheDocument(); + }); + }); + + describe('CellActionsRenderer functionality', () => { + const field = 'host.name'; + const value = '12345'; + const data = { field, value }; + + const scopeIdsWithHoverActions = [ + undefined, + TimelineId.active, + TableId.alternateTest, + TimelineId.casePage, + TableId.alertsOnAlertsPage, + TableId.alertsOnRuleDetailsPage, + TableId.hostsPageEvents, + TableId.hostsPageSessions, + TableId.kubernetesPageSessions, + TableId.networkPageEvents, + TimelineId.test, + TableId.usersPageEvents, + ]; + + const scopeIdsNoHoverActions = [TableId.rulePreview, ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID]; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render cell actions with the content', () => { + const result = render( + + {'test children'} + + ); + expect(result.queryByTestId('mockSecurityCellActions')).toBeInTheDocument(); + expect(result.queryByText('test children')).toBeInTheDocument(); + }); + + it('should call cell actions with the default props', () => { + render( + + {'test children'} + + ); + expect(MockSecurityCellActions).toHaveBeenCalledWith( + expect.objectContaining({ + data, + mode: 'hover-down', + sourcererScopeId: mockSourcererScopeId, + disabledActionTypes: [], + metadata: { scopeId: TimelineId.active }, + }) + ); + }); + + describe('when value is empty', () => { + it('should set an empty array value to the SecurityCellActions component', () => { + render( + + {'test children'} + + ); + expect(MockSecurityCellActions).toHaveBeenCalledWith( + expect.objectContaining({ data: { ...data, value: [] } }) + ); + }); + }); + + describe('when queryValue is provided', () => { + it('should set value to queryValue', () => { + render( + + {'test children'} + + ); + expect(MockSecurityCellActions).toHaveBeenCalledWith( + expect.objectContaining({ data: { ...data, value: 'testQueryValue' } }) + ); + }); + }); + + describe('when scopeId is defined', () => { + it('should set the scopeId to the SecurityCellActions component metadata', () => { + render( + + {'test children'} + + ); + expect(MockSecurityCellActions).toHaveBeenCalledWith( + expect.objectContaining({ metadata: { scopeId: 'testScopeId' } }) + ); + }); + }); + + describe('when hideTopN is true', () => { + it('should set the disabledActionTypes to the SecurityCellActions component', () => { + render( + + {'test children'} + + ); + expect(MockSecurityCellActions).toHaveBeenCalledWith( + expect.objectContaining({ disabledActionTypes: ['security-cellAction-type-showTopN'] }) + ); + }); + }); + + scopeIdsWithHoverActions.forEach((scopeId) => { + test(`it renders hover actions (by default) when scopeId is '${scopeId}'`, async () => { + const { getByTestId } = render( + + {'test children'} + + ); + expect(getByTestId('mockSecurityCellActions')).toBeInTheDocument(); + }); + }); + + scopeIdsNoHoverActions.forEach((scopeId) => { + test(`it does NOT render hover actions when scopeId is '${scopeId}'`, async () => { + const { queryByTestId } = render( + + {'test children'} + + ); + expect(queryByTestId('mockSecurityCellActions')).not.toBeInTheDocument(); + }); + }); + + describe('text truncation styling', () => { + test('it applies text truncation styling when truncate IS specified', () => { + const { getByTestId } = render( + + + {'test children'} + + + ); + + expect(getByTestId('render-truncatable-content')).toBeInTheDocument(); + }); + + test('it does NOT apply text truncation styling when truncate is NOT specified', () => { + const { queryByTestId } = render( + + + {'test children'} + + + ); + + expect(queryByTestId('render-truncatable-content')).not.toBeInTheDocument(); + }); + }); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/cell_actions_renderer.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/cell_actions_renderer.tsx new file mode 100644 index 0000000000000..b953ad22dbead --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/cell_actions_renderer.tsx @@ -0,0 +1,177 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ToolTipPositions } from '@elastic/eui'; +import { EuiToolTip } from '@elastic/eui'; +import React, { useContext, useMemo } from 'react'; +import styled from '@emotion/styled'; +import { TimelineId } from '../../../../common/types'; +import type { SecurityCellActionsData } from '.'; +import { + CellActionsMode, + SecurityCellActions, + SecurityCellActionsTrigger, + SecurityCellActionType, +} from '.'; +import { getSourcererScopeId } from '../../../helpers'; +import { TimelineContext } from '../../../timelines/components/timeline/context'; +import { TruncatableText } from '../truncatable_text'; +import { TableContext } from '../events_viewer/shared'; +import { + disableHoverActions, + tooltipContentIsExplicitlyNull, + getDefaultWhenTooltipIsUnspecified, +} from './utils'; + +export const ProviderContentWrapper = styled.span` + > span.euiToolTipAnchor { + display: block; /* allow EuiTooltip content to be truncatable */ + } + + > span.euiToolTipAnchor.eui-textTruncate { + display: inline-block; /* do not override display when a tooltip is truncated via eui-textTruncate */ + } +`; + +export interface CellActionsRendererProps { + hideTopN?: boolean; + field: string; + value?: string | number | null; + queryValue?: string | null; + children?: React.ReactNode; + scopeId?: string; + tooltipContent?: React.ReactNode; + tooltipPosition?: ToolTipPositions; + truncate?: boolean; +} + +/** + * Renders the content of the cell actions, wrapped in a tooltip + */ +export const Content = React.memo<{ + children?: React.ReactNode; + field: string; + tooltipContent?: React.ReactNode; + tooltipPosition?: ToolTipPositions; + value?: string | number | null; +}>(({ children, field, tooltipContent, tooltipPosition, value }) => + !tooltipContentIsExplicitlyNull(tooltipContent) ? ( + + <>{children ? children : value} + + ) : ( + <>{children ? children : value} + ) +); + +Content.displayName = 'Content'; + +/** + * Renders cell actions content (or an arbitrary visualization specified by `children`) + * that's only displayed when the specified value is non-`null`. + * @param field - the name of the field, e.g. `network.transport` + * @param value - value of the field e.g. `tcp` + * @param children - defaults to displaying `value`, this allows an arbitrary visualization to be displayed in lieu of the default behavior + * @param tooltipContent - defaults to displaying `field`, pass `null` to + * prevent a tooltip from being displayed, or pass arbitrary content + * @param tooltipPosition - defaults to eui's default tooltip position + * @param queryValue - defaults to `value`, this query overrides the `queryMatch.value` used by the `DataProvider` that represents the data + * @param hideTopN - defaults to `false`, when true, the option to aggregate this field will be hidden + * @param scopeId - the id of the scope, e.g. `timelineId` or `tableId` + * @param truncate - defaults to `false`, when true, the content will be truncated + */ +export const CellActionsRenderer = React.memo( + ({ + hideTopN = false, + field, + value, + children, + scopeId = TimelineId.active, + tooltipContent, + tooltipPosition, + queryValue, + truncate = false, + }) => { + const { timelineId: timelineIdFind } = useContext(TimelineContext); + const { tableId: tableIdFind } = useContext(TableContext); + + const sourcererScopeId = useMemo( + () => getSourcererScopeId(scopeId ?? timelineIdFind ?? tableIdFind), + [scopeId, tableIdFind, timelineIdFind] + ); + + const data = useMemo(() => { + if (queryValue) { + return { value: queryValue, field }; + } + return { value: value || [], field }; + }, [value, field, queryValue]); + + const disabledActionTypes = useMemo( + () => (hideTopN ? [SecurityCellActionType.SHOW_TOP_N] : []), + [hideTopN] + ); + + const content = useMemo( + () => ( +
+ {truncate ? ( + + + {children} + + + ) : ( + + + {children} + + + )} +
+ ), + [children, field, truncate, tooltipContent, tooltipPosition, value] + ); + + if (value == null) return null; + + if (disableHoverActions(scopeId)) { + return <>{content}; + } + + return ( + + {content} + + ); + } +); + +CellActionsRenderer.displayName = 'CellActionsRenderer'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/utils.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/utils.test.tsx new file mode 100644 index 0000000000000..f18b974482e2f --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/utils.test.tsx @@ -0,0 +1,92 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { TableId } from '@kbn/securitysolution-data-table'; +import { TimelineId } from '../../../../common/types'; +import { ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID } from '../../../timelines/components/row_renderers_browser/constants'; +import { + disableHoverActions, + tooltipContentIsExplicitlyNull, + getDefaultWhenTooltipIsUnspecified, +} from './utils'; + +const scopeIdsWithHoverActions = [ + undefined, + TimelineId.active, + TableId.alternateTest, + TimelineId.casePage, + TableId.alertsOnAlertsPage, + TableId.alertsOnRuleDetailsPage, + TableId.hostsPageEvents, + TableId.hostsPageSessions, + TableId.kubernetesPageSessions, + TableId.networkPageEvents, + TimelineId.test, + TableId.usersPageEvents, +]; + +const scopeIdsNoHoverActions = [TableId.rulePreview, ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID]; + +describe('disableHoverActions', () => { + scopeIdsNoHoverActions.forEach((scopeId) => + test(`it returns true when timelineId is ${scopeId}`, () => { + expect(disableHoverActions(scopeId)).toBe(true); + }) + ); + + scopeIdsWithHoverActions.forEach((scopeId) => + test(`it returns false when timelineId is ${scopeId}`, () => { + expect(disableHoverActions(scopeId)).toBe(false); + }) + ); +}); + +describe('tooltipContentIsExplicitlyNull', () => { + test('returns false if a string is provided for the tooltip', () => { + expect(tooltipContentIsExplicitlyNull('bob')).toBe(false); + }); + + test('returns false if the tooltip is undefined', () => { + expect(tooltipContentIsExplicitlyNull(undefined)).toBe(false); + }); + + test('returns false if the tooltip is a ReactNode', () => { + expect(tooltipContentIsExplicitlyNull({'be a good node'})).toBe(false); + }); + + test('returns true if the tooltip is null', () => { + expect(tooltipContentIsExplicitlyNull(null)).toBe(true); + }); +}); + +describe('getDefaultWhenTooltipIsUnspecified', () => { + test('it returns the field (as as string) when the tooltipContent is undefined', () => { + expect(getDefaultWhenTooltipIsUnspecified({ field: 'source.bytes' })).toEqual('source.bytes'); + }); + + test('it returns the field (as as string) when the tooltipContent is null', () => { + expect( + getDefaultWhenTooltipIsUnspecified({ field: 'source.bytes', tooltipContent: null }) + ).toEqual('source.bytes'); + }); + + test('it returns the tooltipContent when a string is provided as content', () => { + expect( + getDefaultWhenTooltipIsUnspecified({ field: 'source.bytes', tooltipContent: 'a string' }) + ).toEqual('a string'); + }); + + test('it returns the tooltipContent when an element is provided as content', () => { + expect( + getDefaultWhenTooltipIsUnspecified({ + field: 'source.bytes', + tooltipContent: {'the universe'}, + }) + ).toEqual({'the universe'}); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/utils.ts b/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/utils.ts new file mode 100644 index 0000000000000..a69a66ed07bd4 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/utils.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type React from 'react'; +import { TableId } from '@kbn/securitysolution-data-table'; +import { ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID } from '../../../timelines/components/row_renderers_browser/constants'; + +/** + * Determines if hover actions should be disabled for a given timeline ID + * @param timelineId - The timeline ID to check + * @returns true if hover actions should be disabled, false otherwise + */ +export const disableHoverActions = (timelineId: string | undefined): boolean => + [TableId.rulePreview, ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID].includes(timelineId ?? ''); + +/** + * Only returns true if the specified tooltipContent is exactly `null`. + * Example input / output: + * `bob -> false` + * `undefined -> false` + * `thing -> false` + * `null -> true` + */ +export const tooltipContentIsExplicitlyNull = (tooltipContent?: React.ReactNode): boolean => + tooltipContent === null; // an explicit / exact null check + +/** + * Derives the tooltip content from the field name if no tooltip was specified + */ +export const getDefaultWhenTooltipIsUnspecified = ({ + field, + tooltipContent, +}: { + field: string; + tooltipContent?: React.ReactNode; +}): React.ReactNode => (tooltipContent != null ? tooltipContent : field); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/barchart.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/barchart.test.tsx index 645d3cd01c075..7ef04360e6bba 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/barchart.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/barchart.test.tsx @@ -10,8 +10,6 @@ import { BarSeries, Axis, ScaleType } from '@elastic/charts'; import type { RenderResult } from '@testing-library/react'; import { screen, render } from '@testing-library/react'; import React from 'react'; - -import { escapeDataProviderId } from '../drag_and_drop/helpers'; import { TestProviders } from '../../mock'; import '../../mock/react_beautiful_dnd'; @@ -377,14 +375,10 @@ describe('BarChart with stackByField', () => { expect(screen.getByTestId('draggable-legend')).toBeInTheDocument(); }); - test.each(data)('it renders the expected draggable legend text for datum $key', ({ key }) => { - const dataProviderId = `draggableId.content.draggable-legend-item-uuid_v4()-${escapeDataProviderId( - stackByField - )}-${escapeDataProviderId(key)}`; - - expect( - wrapper.container.querySelector(`div[data-provider-id="${dataProviderId}"]`) - ).toHaveTextContent(key); + data.forEach((datum, idx) => { + test(`it renders the expected draggable legend text for datum ${datum.key}`, () => { + expect(wrapper.getByTestId(`legend-item-${idx}`)).toHaveTextContent(datum.key); + }); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/barchart.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/barchart.tsx index 42a98a0b743db..3d0ad7c9765dd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/barchart.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/barchart.tsx @@ -12,11 +12,9 @@ import type { SettingsProps } from '@elastic/charts'; import { Chart, BarSeries, Axis, Position, ScaleType, Settings } from '@elastic/charts'; import { getOr, get, isNumber } from 'lodash/fp'; import deepmerge from 'deepmerge'; -import { v4 as uuidv4 } from 'uuid'; import styled from '@emotion/styled'; import deepEqual from 'fast-deep-equal'; -import { escapeDataProviderId } from '../drag_and_drop/helpers'; import { useTimeZone } from '../../lib/kibana'; import { useThrottledResizeObserver } from '../utils'; import { hasValueToDisplay } from '../../utils/validators'; @@ -193,9 +191,6 @@ export const BarChartComponent: React.FC = ({ barChart != null && stackByField != null ? barChart.map((d) => ({ color: d.color, - dataProviderId: escapeDataProviderId( - `draggable-legend-item-${uuidv4()}-${stackByField}-${d.key}` - ), scopeId, field: stackByField, value: d.key, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/donutchart.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/donutchart.test.tsx index e29b72fbc0004..ac7e6b7a1ecc0 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/donutchart.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/donutchart.test.tsx @@ -14,8 +14,6 @@ import type { DonutChartProps } from './donutchart'; import { DonutChart } from './donutchart'; import { DraggableLegend } from './draggable_legend'; import { ChartLabel } from '../../../overview/components/detection_response/alerts_by_status/chart_label'; -import { escapeDataProviderId } from '../drag_and_drop/helpers'; -import { v4 as uuidv4 } from 'uuid'; jest.mock('@elastic/charts', () => { const actual = jest.requireActual('@elastic/charts'); @@ -73,8 +71,7 @@ describe('DonutChart', () => { totalCount: parsedMockAlertsData?.open?.total, legendItems: (['critical', 'high', 'medium', 'low'] as Severity[]).map((d) => ({ color: testColors[d], - dataProviderId: escapeDataProviderId(`draggable-legend-item-${uuidv4()}-${d}`), - timelineId: undefined, + scopeId: undefined, field: 'kibana.alert.severity', value: d, })), @@ -133,30 +130,26 @@ describe('DonutChart', () => { expect((DraggableLegend as unknown as jest.Mock).mock.calls[0][0].legendItems).toEqual([ { color: '#EF6550', - dataProviderId: 'draggable-legend-item-test-uuid-critical', field: 'kibana.alert.severity', - timelineId: undefined, + scopeId: undefined, value: 'critical', }, { color: '#EE9266', - dataProviderId: 'draggable-legend-item-test-uuid-high', field: 'kibana.alert.severity', - timelineId: undefined, + scopeId: undefined, value: 'high', }, { color: '#F3B689', - dataProviderId: 'draggable-legend-item-test-uuid-medium', field: 'kibana.alert.severity', - timelineId: undefined, + scopeId: undefined, value: 'medium', }, { color: '#F8D9B2', - dataProviderId: 'draggable-legend-item-test-uuid-low', field: 'kibana.alert.severity', - timelineId: undefined, + scopeId: undefined, value: 'low', }, ]); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.test.tsx index 02efc7784b271..496920ec33cb1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.test.tsx @@ -27,31 +27,24 @@ jest.mock('@elastic/eui', () => { const legendItems: LegendItem[] = [ { color: '#1EA593', - dataProviderId: 'draggable-legend-item-3207fda7-d008-402a-86a0-8ad632081bad-event_dataset-flow', field: 'event.dataset', value: 'flow', scopeId: 'test', }, { color: '#2B70F7', - dataProviderId: - 'draggable-legend-item-83f6c824-811d-4ec8-b373-eba2b0de6398-event_dataset-suricata_eve', field: 'event.dataset', value: 'suricata.eve', scopeId: 'test', }, { color: '#CE0060', - dataProviderId: - 'draggable-legend-item-ec57bb8f-82cd-4e07-bd38-1d11b3f0ee5f-event_dataset-traefik_access', field: 'event.dataset', value: 'traefik.access', scopeId: 'test', }, { color: '#38007E', - dataProviderId: - 'draggable-legend-item-25d5fcd6-87ba-46b5-893e-c655d7d504e3-event_dataset-esensor', field: 'event.dataset', value: 'esensor', scopeId: 'test', @@ -104,16 +97,14 @@ describe('DraggableLegend', () => { }); it('renders the legend items', () => { - const { container } = render( + const { getByTestId } = render( ); - legendItems.forEach((item) => - expect( - container.querySelector(`[data-provider-id="draggableId.content.${item.dataProviderId}"]`) - ).toHaveTextContent(item.value.toString()) + legendItems.forEach((item, idx) => + expect(getByTestId(`legend-item-${idx}`)).toHaveTextContent(item.value.toString()) ); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.tsx index b1716773a0e3b..75ab9a406c370 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.tsx @@ -78,8 +78,8 @@ const DraggableLegendComponent: React.FC<{ > - {legendItems.map((item) => ( - + {legendItems.map((item, idx) => ( + diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend_item.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend_item.test.tsx index a799d467eb23f..f8e5c662e89ca 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend_item.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend_item.test.tsx @@ -35,7 +35,6 @@ jest.mock('../cell_actions', () => ({ describe('DraggableLegendItem', () => { const legendItem: LegendItem = { color: '#1EA593', - dataProviderId: 'draggable-legend-item-3207fda7-d008-402a-86a0-8ad632081bad-event_dataset-flow', field: 'event.dataset', value: 'flow', scopeId: 'test', @@ -74,16 +73,13 @@ describe('DraggableLegendItem', () => { }); it('renders draggable legend item text', () => { - const { container } = render( + const { getByTestId } = render( ); - const legendItemElement = container.querySelector( - `[data-provider-id="draggableId.content.${legendItem.dataProviderId}"]` - ); - expect(legendItemElement).toHaveTextContent(String(legendItem.value)); + expect(getByTestId('legend-item')).toHaveTextContent('flow'); }); it('renders a custom legend item via the `render` prop when provided', () => { @@ -122,12 +118,7 @@ describe('DraggableLegendItem', () => { ); - expect(screen.getByTestId('mockSecurityCellActions')).toBeInTheDocument(); - expect(MockSecurityCellActions).toHaveBeenCalledWith( - expect.objectContaining({ - disabledActionTypes: ['security-cellAction-type-showTopN'], - }) - ); + expect(screen.getByTestId('legend-item')).toBeInTheDocument(); }); it('renders the empty value label when the value is empty', () => { @@ -156,7 +147,7 @@ describe('DraggableLegendItem', () => { ); - expect(queryByTestId(`legend-item-${legendItem.dataProviderId}`)).not.toBeInTheDocument(); + expect(queryByTestId(`render-content-${legendItem.field}`)).not.toBeInTheDocument(); expect(getByTestId('legendItemInlineActions')).toBeInTheDocument(); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend_item.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend_item.tsx index 812f7be182926..4ccd7ec31e6ad 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend_item.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend_item.tsx @@ -11,7 +11,7 @@ import React, { useMemo } from 'react'; import styled from '@emotion/styled'; import { DEFAULT_NUMBER_FORMAT } from '../../../../common/constants'; -import { DefaultDraggable } from '../draggables'; +import { CellActionsRenderer } from '../cell_actions/cell_actions_renderer'; import { useUiSetting$ } from '../../lib/kibana'; import { EMPTY_VALUE_LABEL } from './translation'; import { hasValueToDisplay } from '../../utils/validators'; @@ -29,7 +29,6 @@ const CountFlexItem = styled(EuiFlexItem)` export interface LegendItem { color?: string; - dataProviderId: string; render?: (fieldValuePair?: { field: string; value: string | number }) => React.ReactNode; field: string; scopeId?: string; @@ -55,7 +54,7 @@ const DraggableLegendItemComponent: React.FC<{ isInlineActions?: boolean; }> = ({ legendItem, isInlineActions = false }) => { const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); - const { color, count, dataProviderId, field, scopeId, value } = legendItem; + const { color, count, field, scopeId, value } = legendItem; const sourcererScopeId = getSourcererScopeId(scopeId ?? ''); const content = useMemo(() => { @@ -82,19 +81,13 @@ const DraggableLegendItemComponent: React.FC<{ gutterSize="none" responsive={false} > - + {isInlineActions ? ( content ) : ( - + {content} - +
)} diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/__snapshots__/draggable_wrapper.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/__snapshots__/draggable_wrapper.test.tsx.snap deleted file mode 100644 index aa8214938c2b0..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/__snapshots__/draggable_wrapper.test.tsx.snap +++ /dev/null @@ -1,22 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DraggableWrapper rendering it renders against the snapshot 1`] = ` - -`; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.test.tsx deleted file mode 100644 index 8f438bb9289c4..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.test.tsx +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { render } from '@testing-library/react'; -import { CellActionsWrapper } from './cell_actions_wrapper'; -import { CellActionsMode, SecurityCellActionType } from '../cell_actions'; -import { TimelineId, type DataProvider } from '../../../../common/types'; - -const MockSecurityCellActions = jest.fn(({ children }: { children: React.ReactNode }) => ( -
{children}
-)); -jest.mock('../cell_actions', () => ({ - ...jest.requireActual('../cell_actions'), - SecurityCellActions: (params: { children: React.ReactNode }) => MockSecurityCellActions(params), -})); - -const mockSourcererScopeId = 'testSourcererScopeId'; -jest.mock('../../../helpers', () => ({ - getSourcererScopeId: jest.fn(() => mockSourcererScopeId), -})); - -const dataProvider = { queryMatch: { field: 'host.name', value: '12345' } } as DataProvider; -const data = { ...dataProvider.queryMatch }; - -describe('CellActionsWrapper', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('should render cell actions with the content', () => { - const result = render( - {'test children'} - ); - expect(result.queryByTestId('mockSecurityCellActions')).toBeInTheDocument(); - expect(result.queryByText('test children')).toBeInTheDocument(); - }); - - it('should call cell actions with the default props', () => { - render({'test children'}); - expect(MockSecurityCellActions).toHaveBeenCalledWith( - expect.objectContaining({ - data, - mode: CellActionsMode.HOVER_DOWN, - sourcererScopeId: mockSourcererScopeId, - disabledActionTypes: [], - metadata: { scopeId: TimelineId.active }, - }) - ); - }); - - describe('when dataProvider value is empty', () => { - it('should set an empty array value to the SecurityCellActions component', () => { - const emptyValueDataProvider = { - queryMatch: { field: 'host.name', value: '' }, - } as DataProvider; - render( - - {'test children'} - - ); - expect(MockSecurityCellActions).toHaveBeenCalledWith( - expect.objectContaining({ data: { ...data, value: [] } }) - ); - }); - }); - - describe('when scopeId is defined', () => { - it('should set the scopeId to the SecurityCellActions component metadata', () => { - render( - - {'test children'} - - ); - expect(MockSecurityCellActions).toHaveBeenCalledWith( - expect.objectContaining({ metadata: { scopeId: 'testScopeId' } }) - ); - }); - }); - - describe('when hideTopN is true', () => { - it('should set the disabledActionTypes to the SecurityCellActions component', () => { - render( - - {'test children'} - - ); - expect(MockSecurityCellActions).toHaveBeenCalledWith( - expect.objectContaining({ disabledActionTypes: [SecurityCellActionType.SHOW_TOP_N] }) - ); - }); - }); -}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.tsx deleted file mode 100644 index 7d20a645abc35..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.tsx +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { PropsWithChildren } from 'react'; -import React, { useContext, useMemo } from 'react'; -import { TimelineId, type DataProvider } from '../../../../common/types'; -import type { SecurityCellActionsData } from '../cell_actions'; -import { - CellActionsMode, - SecurityCellActions, - SecurityCellActionsTrigger, - SecurityCellActionType, -} from '../cell_actions'; -import { getSourcererScopeId } from '../../../helpers'; -import { TimelineContext } from '../../../timelines/components/timeline/context'; - -import { TableContext } from '../events_viewer/shared'; - -type CellActionsWrapperProps = PropsWithChildren<{ - /** - * The `dataProvider` is used to retrieve the `field` and `value` for the cell actions execution. - * */ - dataProvider: DataProvider; - /** - * The `hideTopN` is used hide the show top N action. Defaults to `false`. - * */ - hideTopN?: boolean; - /** - * The `scopeId` is used to determine the context of the cell actions execution. - * If not provided this component will try to retrieve the timeline id or the table id from the context, in that order. - * */ - scopeId?: string; -}>; - -export const CellActionsWrapper = React.memo>( - ({ dataProvider, scopeId = TimelineId.active, children, hideTopN = false }) => { - const { timelineId: timelineIdFind } = useContext(TimelineContext); - const { tableId: tableIdFind } = useContext(TableContext); - - const sourcererScopeId = useMemo( - () => getSourcererScopeId(scopeId ?? timelineIdFind ?? tableIdFind), - [scopeId, tableIdFind, timelineIdFind] - ); - - const data = useMemo(() => { - const { value, field } = dataProvider.queryMatch; - return { value: value || [], field }; - }, [dataProvider.queryMatch]); - - const disabledActionTypes = useMemo( - () => (hideTopN ? [SecurityCellActionType.SHOW_TOP_N] : []), - [hideTopN] - ); - - return ( - - {children} - - ); - } -); - -CellActionsWrapper.displayName = 'CellActionsWrapper'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.test.tsx deleted file mode 100644 index 6cc769debbfa9..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.test.tsx +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { render } from '@testing-library/react'; -import { shallow } from 'enzyme'; -import React from 'react'; -import type { DraggableStateSnapshot, DraggingStyle } from '@hello-pangea/dnd'; - -import { mockBrowserFields } from '../../containers/source/mock'; -import { TestProviders } from '../../mock'; -import { mockDataProviders } from '../../../timelines/components/timeline/data_providers/mock/mock_data_providers'; -import { ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID } from '../../../timelines/components/row_renderers_browser/constants'; -import { DragDropContextWrapper } from './drag_drop_context_wrapper'; -import { disableHoverActions, DraggableWrapper, getStyle } from './draggable_wrapper'; -import { useMountAppended } from '../../utils/use_mount_appended'; -import { TimelineId } from '../../../../common/types'; -import { TableId } from '@kbn/securitysolution-data-table'; - -jest.mock('../../lib/kibana'); - -jest.mock('@elastic/eui', () => { - const original = jest.requireActual('@elastic/eui'); - return { - ...original, - EuiScreenReaderOnly: () => <>, - }; -}); - -const MockSecurityCellActions = jest.fn(({ children }: { children: React.ReactNode }) => ( -
{children}
-)); -jest.mock('../cell_actions', () => ({ - ...jest.requireActual('../cell_actions'), - SecurityCellActions: (props: { children: React.ReactNode }) => MockSecurityCellActions(props), -})); - -const scopeIdsWithHoverActions = [ - undefined, - TimelineId.active, - TableId.alternateTest, - TimelineId.casePage, - TableId.alertsOnAlertsPage, - TableId.alertsOnRuleDetailsPage, - TableId.hostsPageEvents, - TableId.hostsPageSessions, - TableId.kubernetesPageSessions, - TableId.networkPageEvents, - TimelineId.test, - TableId.usersPageEvents, -]; - -const scopeIdsNoHoverActions = [TableId.rulePreview, ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID]; - -describe('DraggableWrapper', () => { - const dataProvider = mockDataProviders[0]; - const message = 'draggable wrapper content'; - const mount = useMountAppended(); - - beforeEach(() => { - jest.useFakeTimers({ legacyFakeTimers: true }); - }); - - afterEach(() => { - const portal = document.querySelector('[data-euiportal="true"]'); - if (portal != null) { - portal.innerHTML = ''; - } - }); - - afterAll(() => { - jest.useRealTimers(); - }); - - describe('rendering', () => { - test('it renders against the snapshot', () => { - const wrapper = shallow( - - - message} /> - - - ); - - expect(wrapper.find('DraggableWrapper')).toMatchSnapshot(); - }); - - test('it renders the children passed to the render prop', () => { - const wrapper = mount( - - - message} /> - - - ); - - expect(wrapper.text()).toEqual(message); - }); - - scopeIdsWithHoverActions.forEach((scopeId) => { - test(`it renders hover actions (by default) when 'isDraggable' is false and timelineId is '${scopeId}'`, async () => { - const { queryByTestId } = render( - - - message} - scopeId={scopeId} - /> - - - ); - - expect(queryByTestId('cell-actions-mock')).toBeInTheDocument(); - }); - }); - - scopeIdsNoHoverActions.forEach((scopeId) => { - test(`it does NOT render hover actions when 'isDraggable' is false and timelineId is '${scopeId}'`, async () => { - const { queryByTestId } = render( - - - message} - scopeId={scopeId} - /> - - - ); - - expect(queryByTestId('cell-actions-mock')).not.toBeInTheDocument(); - }); - }); - }); - - describe('text truncation styling', () => { - test('it applies text truncation styling when truncate IS specified (implicit: and the user is not dragging)', () => { - const wrapper = mount( - - - message} truncate /> - - - ); - - expect(wrapper.find('[data-test-subj="render-truncatable-content"]').exists()).toEqual(true); - }); - - test('it does NOT apply text truncation styling when truncate is NOT specified', () => { - const wrapper = mount( - - - message} /> - - - ); - - expect(wrapper.find('[data-test-subj="draggable-truncatable-content"]').exists()).toEqual( - false - ); - }); - }); -}); - -describe('ConditionalPortal', () => { - describe('getStyle', () => { - const style: DraggingStyle = { - boxSizing: 'border-box', - height: 10, - left: 1, - pointerEvents: 'none', - position: 'fixed', - transition: 'none', - top: 123, - width: 50, - zIndex: 9999, - }; - - it('returns a style with no transitionDuration when the snapshot is not drop animating', () => { - const snapshot: DraggableStateSnapshot = { - isDragging: true, - isDropAnimating: false, // <-- NOT drop animating - isClone: false, - dropAnimation: null, - draggingOver: null, - combineWith: null, - combineTargetFor: null, - mode: null, - }; - - expect(getStyle(style, snapshot)).not.toHaveProperty('transitionDuration'); - }); - - it('returns a style with a transitionDuration when the snapshot is drop animating', () => { - const snapshot: DraggableStateSnapshot = { - isDragging: true, - isDropAnimating: true, // <-- it is drop animating - isClone: false, - dropAnimation: null, - draggingOver: null, - combineWith: null, - combineTargetFor: null, - mode: null, - }; - - expect(getStyle(style, snapshot)).toHaveProperty('transitionDuration', '0.00000001s'); - }); - }); - - describe('disableHoverActions', () => { - scopeIdsNoHoverActions.forEach((scopeId) => - test(`it returns true when timelineId is ${scopeId}`, () => { - expect(disableHoverActions(scopeId)).toBe(true); - }) - ); - - scopeIdsWithHoverActions.forEach((scopeId) => - test(`it returns false when timelineId is ${scopeId}`, () => { - expect(disableHoverActions(scopeId)).toBe(false); - }) - ); - }); -}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx deleted file mode 100644 index 04db0f329c33c..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useMemo } from 'react'; -import type { - DraggableProvided, - DraggableStateSnapshot, - DraggingStyle, - NotDraggingStyle, -} from '@hello-pangea/dnd'; -import styled from 'styled-components'; -import { TableId } from '@kbn/securitysolution-data-table'; -import type { DataProvider } from '../../../timelines/components/timeline/data_providers/data_provider'; -import { ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID } from '../../../timelines/components/row_renderers_browser/constants'; -import { TruncatableText } from '../truncatable_text'; -import { CellActionsWrapper } from './cell_actions_wrapper'; -import { getDraggableId } from './helpers'; - -export const ProviderContentWrapper = styled.span` - > span.euiToolTipAnchor { - display: block; /* allow EuiTooltip content to be truncatable */ - } - - > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; /* do not override display when a tooltip is truncated via eui-textTruncate */ - } -`; - -export type RenderFunctionProp = ( - props: DataProvider, - provided: DraggableProvided | null, - state: DraggableStateSnapshot -) => React.ReactNode; - -export interface DraggableWrapperProps { - dataProvider: DataProvider; - fieldType?: string; - isAggregatable?: boolean; - hideTopN?: boolean; - render: RenderFunctionProp; - scopeId?: string; - truncate?: boolean; -} - -export const disableHoverActions = (timelineId: string | undefined): boolean => - [TableId.rulePreview, ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID].includes(timelineId ?? ''); - -/** - * Wraps a draggable component to handle registration / unregistration of the - * data provider associated with the item being dropped - */ - -export const getStyle = ( - style: DraggingStyle | NotDraggingStyle | undefined, - snapshot: DraggableStateSnapshot -) => { - if (!snapshot.isDropAnimating) { - return style; - } - - return { - ...style, - transitionDuration: '0.00000001s', // cannot be 0, but can be a very short duration - }; -}; - -export const DraggableWrapper: React.FC = React.memo( - ({ dataProvider, render, scopeId, truncate, hideTopN }) => { - const content = useMemo( - () => ( -
- {truncate ? ( - - {render(dataProvider, null, { - isDragging: false, - isDropAnimating: false, - isClone: false, - dropAnimation: null, - draggingOver: null, - combineWith: null, - combineTargetFor: null, - mode: null, - })} - - ) : ( - - {render(dataProvider, null, { - isDragging: false, - isDropAnimating: false, - isClone: false, - dropAnimation: null, - draggingOver: null, - combineWith: null, - combineTargetFor: null, - mode: null, - })} - - )} -
- ), - [dataProvider, render, truncate] - ); - - if (disableHoverActions(scopeId)) { - return <>{content}; - } - return ( - - {content} - - ); - } -); -DraggableWrapper.displayName = 'DraggableWrapper'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/draggables/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/draggables/__snapshots__/index.test.tsx.snap index 33639b851c324..782be3a0cdd09 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/draggables/__snapshots__/index.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/draggables/__snapshots__/index.test.tsx.snap @@ -1,9 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`draggables rendering it renders the default Badge 1`] = ` - @@ -16,29 +15,5 @@ exports[`draggables rendering it renders the default Badge 1`] = ` A child of this - -`; - -exports[`draggables rendering it renders the default DefaultDraggable 1`] = ` - +
`; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/draggables/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/draggables/index.test.tsx index 2613714d5d9d1..765ffce045e40 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/draggables/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/draggables/index.test.tsx @@ -12,12 +12,7 @@ import { TestProviders } from '../../mock'; import { getEmptyString } from '../empty_value'; import { useMountAppended } from '../../utils/use_mount_appended'; -import { - DefaultDraggable, - DraggableBadge, - getDefaultWhenTooltipIsUnspecified, - tooltipContentIsExplicitlyNull, -} from '.'; +import { DraggableBadge } from '.'; jest.mock('../../lib/kibana'); @@ -25,20 +20,6 @@ describe('draggables', () => { const mount = useMountAppended(); describe('rendering', () => { - test('it renders the default DefaultDraggable', () => { - const wrapper = shallow( - - {'A child of this'} - - ); - expect(wrapper).toMatchSnapshot(); - }); - test('it renders the default Badge', () => { const wrapper = shallow( { }); }); - describe('#tooltipContentIsExplicitlyNull', () => { - test('returns false if a string is provided for the tooltip', () => { - expect(tooltipContentIsExplicitlyNull('bob')).toBe(false); - }); - - test('returns false if the tooltip is undefined', () => { - expect(tooltipContentIsExplicitlyNull(undefined)).toBe(false); - }); - - test('returns false if the tooltip is a ReactNode', () => { - expect(tooltipContentIsExplicitlyNull({'be a good node'})).toBe(false); - }); - - test('returns true if the tooltip is null', () => { - expect(tooltipContentIsExplicitlyNull(null)).toBe(true); - }); - }); - - describe('#getDefaultWhenTooltipIsUnspecified', () => { - test('it returns the field (as as string) when the tooltipContent is undefined', () => { - expect(getDefaultWhenTooltipIsUnspecified({ field: 'source.bytes' })).toEqual('source.bytes'); - }); - - test('it returns the field (as as string) when the tooltipContent is null', () => { - expect( - getDefaultWhenTooltipIsUnspecified({ field: 'source.bytes', tooltipContent: null }) - ).toEqual('source.bytes'); - }); - - test('it returns the tooltipContent when a string is provided as content', () => { - expect( - getDefaultWhenTooltipIsUnspecified({ field: 'source.bytes', tooltipContent: 'a string' }) - ).toEqual('a string'); - }); - - test('it returns the tooltipContent when an element is provided as content', () => { - expect( - getDefaultWhenTooltipIsUnspecified({ - field: 'source.bytes', - tooltipContent: {'the universe'}, - }) - ).toEqual({'the universe'}); - }); - }); - - describe('DefaultDraggable', () => { - test('it works with just an id, field, and value and is some value', () => { - const field = 'some-field'; - const value = 'some value'; - const wrapper = mount( - - - - ); - expect(wrapper.text()).toEqual(value); - }); - - test('it returns null if value is undefined', () => { - const wrapper = shallow( - - ); - expect(wrapper.isEmptyRender()).toBeTruthy(); - }); - - test('it returns null if value is null', () => { - const wrapper = shallow( - - ); - expect(wrapper.isEmptyRender()).toBeTruthy(); - }); - - test('it renders a tooltip with the field name if a tooltip is not explicitly provided', () => { - const wrapper = mount( - - - - ); - - expect( - wrapper.find('[data-test-subj="source.bytes-tooltip"]').first().props().content - ).toEqual('source.bytes'); - }); - - test('it renders the tooltipContent when a string is provided as content', () => { - const wrapper = mount( - - - - ); - - expect( - wrapper.find('[data-test-subj="source.bytes-tooltip"]').first().props().content - ).toEqual('default draggable string tooltip'); - }); - - test('it renders the tooltipContent when an element is provided as content', () => { - const wrapper = mount( - - {'default draggable tooltip'}} - value="a default draggable" - /> - - ); - - expect( - wrapper.find('[data-test-subj="source.bytes-tooltip"]').first().props().content - ).toEqual({'default draggable tooltip'}); - }); - - test('it does NOT render a tooltip when tooltipContent is null', () => { - const wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="source.bytes-tooltip"]').first().exists()).toBe(false); - }); - }); - describe('DraggableBadge', () => { test('it works with just an id, field, and value and is the default', () => { const wrapper = mount( diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/draggables/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/draggables/index.tsx index 625fbff36568e..8934e01382cdc 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/draggables/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/draggables/index.tsx @@ -5,160 +5,13 @@ * 2.0. */ -import type { IconType, ToolTipPositions } from '@elastic/eui'; -import { EuiBadge, EuiToolTip } from '@elastic/eui'; -import React, { useCallback, useMemo } from 'react'; +import type { IconType } from '@elastic/eui'; +import { EuiBadge } from '@elastic/eui'; +import React from 'react'; import styled from '@emotion/styled'; - -import type { DraggableWrapperProps } from '../drag_and_drop/draggable_wrapper'; -import { DraggableWrapper } from '../drag_and_drop/draggable_wrapper'; -import { escapeDataProviderId } from '../drag_and_drop/helpers'; +import type { CellActionsRendererProps } from '../cell_actions/cell_actions_renderer'; +import { CellActionsRenderer } from '../cell_actions/cell_actions_renderer'; import { getEmptyStringTag } from '../empty_value'; -import type { DataProvider } from '../../../timelines/components/timeline/data_providers/data_provider'; -import { IS_OPERATOR } from '../../../timelines/components/timeline/data_providers/data_provider'; - -export interface DefaultDraggableType { - hideTopN?: boolean; - id: string; - fieldType?: string; - isAggregatable?: boolean; - field: string; - value?: string | number | null; - name?: string | null; - queryValue?: string | null; - children?: React.ReactNode; - scopeId?: string; - tooltipContent?: React.ReactNode; - tooltipPosition?: ToolTipPositions; - truncate?: boolean; -} - -/** - * Only returns true if the specified tooltipContent is exactly `null`. - * Example input / output: - * `bob -> false` - * `undefined -> false` - * `thing -> false` - * `null -> true` - */ -export const tooltipContentIsExplicitlyNull = (tooltipContent?: React.ReactNode): boolean => - tooltipContent === null; // an explicit / exact null check - -/** - * Derives the tooltip content from the field name if no tooltip was specified - */ -export const getDefaultWhenTooltipIsUnspecified = ({ - field, - tooltipContent, -}: { - field: string; - tooltipContent?: React.ReactNode; -}): React.ReactNode => (tooltipContent != null ? tooltipContent : field); - -/** - * Renders the content of the draggable, wrapped in a tooltip - */ -export const Content = React.memo<{ - children?: React.ReactNode; - field: string; - tooltipContent?: React.ReactNode; - tooltipPosition?: ToolTipPositions; - value?: string | number | null; -}>(({ children, field, tooltipContent, tooltipPosition, value }) => - !tooltipContentIsExplicitlyNull(tooltipContent) ? ( - - <>{children ? children : value} - - ) : ( - <>{children ? children : value} - ) -); - -Content.displayName = 'Content'; - -/** - * Draggable text (or an arbitrary visualization specified by `children`) - * that's only displayed when the specified value is non-`null`. - * - * @param id - a unique draggable id, which typically follows the format `${contextId}-${eventId}-${field}-${value}` - * @param field - the name of the field, e.g. `network.transport` - * @param value - value of the field e.g. `tcp` - * @param name - defaulting to `field`, this optional human readable name is used by the `DataProvider` that represents the data - * @param children - defaults to displaying `value`, this allows an arbitrary visualization to be displayed in lieu of the default behavior - * @param tooltipContent - defaults to displaying `field`, pass `null` to - * prevent a tooltip from being displayed, or pass arbitrary content - * @param tooltipPosition - defaults to eui's default tooltip position - * @param queryValue - defaults to `value`, this query overrides the `queryMatch.value` used by the `DataProvider` that represents the data - * @param hideTopN - defaults to `false`, when true, the option to aggregate this field will be hidden - */ -export const DefaultDraggable = React.memo( - ({ - hideTopN = false, - id, - field, - fieldType = '', - isAggregatable = false, - value, - name, - children, - scopeId, - tooltipContent, - tooltipPosition, - queryValue, - truncate, - }) => { - const dataProviderProp: DataProvider = useMemo( - () => ({ - and: [], - enabled: true, - id: escapeDataProviderId(id), - name: name ? name : value?.toString() ?? '', - excluded: false, - kqlQuery: '', - queryMatch: { - field, - value: queryValue ? queryValue : value ?? '', - operator: IS_OPERATOR, - }, - }), - [field, id, name, queryValue, value] - ); - - const renderCallback = useCallback( - () => ( - - {children} - - ), - [children, field, tooltipContent, tooltipPosition, value] - ); - - if (value == null) return null; - - return ( - - ); - } -); - -DefaultDraggable.displayName = 'DefaultDraggable'; export const Badge = styled(EuiBadge)` vertical-align: top; @@ -166,17 +19,21 @@ export const Badge = styled(EuiBadge)` Badge.displayName = 'Badge'; -export type BadgeDraggableType = Omit & { - contextId: string; - eventId: string; +export type BadgeType = CellActionsRendererProps & { iconType?: IconType; + // Teporary workaround accept these unused props + // TODO: remove these props in all DraggableBadge components + id?: string; + contextId?: string; + eventId?: string; + isAggregatable?: boolean; + fieldType?: string; + name?: string; }; /** * A draggable badge that's only displayed when the specified value is non-`null`. * - * @param contextId - used as part of the formula to derive a unique draggable id, this describes the context e.g. `event-fields-browser` in which the badge is displayed - * @param eventId - uniquely identifies an event, as specified in the `_id` field of the document * @param field - the name of the field, e.g. `network.transport` * @param value - value of the field e.g. `tcp` * @param iconType -the (optional) type of icon e.g. `snowflake` to display on the badge @@ -186,27 +43,18 @@ export type BadgeDraggableType = Omit & { * prevent a tooltip from being displayed, or pass arbitrary content * @param queryValue - defaults to `value`, this query overrides the `queryMatch.value` used by the `DataProvider` that represents the data */ -const DraggableBadgeComponent: React.FC = ({ - contextId, - eventId, +const DraggableBadgeComponent: React.FC = ({ field, value, iconType, - isAggregatable, - fieldType, - name, children, scopeId, tooltipContent, queryValue, }) => value != null ? ( - = ({ {children ? children : value !== '' ? value : getEmptyStringTag()} - + ) : null; DraggableBadgeComponent.displayName = 'DraggableBadgeComponent'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.test.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.test.ts index d7f0276afab6f..a6b4cf1896bbc 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.test.ts @@ -75,18 +75,6 @@ describe('legend', () => { ).toEqual(34); }); - it('returns the expected dataProviderId', () => { - expect( - getLegendItemFromRawBucket({ - bucket: bucketsWithStackByField1[0], - colorPalette, - maxRiskSubAggregations, - showColor: true, - stackByField0: 'kibana.alert.rule.name', - }).dataProviderId - ).toContain('draggable-legend-item-treemap-kibana_alert_rule_name-matches everything-'); - }); - it('renders the expected label', () => { const item = getLegendItemFromRawBucket({ bucket: bucketsWithStackByField1[0], @@ -189,20 +177,6 @@ describe('legend', () => { expect(legendItem.render != null && legendItem.render()).toEqual('Host-k8iyfzraq9'); }); - - it('returns the expected dataProviderId', () => { - const legendItem = getLegendItemFromFlattenedBucket({ - colorPalette, - flattenedBucket, - maxRiskSubAggregations, - stackByField0: 'kibana.alert.rule.name', - stackByField1: 'host.name', - }); - - expect(legendItem.dataProviderId).toContain( - 'draggable-legend-item-treemap-matches everything-Host-k8iyfzraq9-' - ); - }); }); describe('getFirstGroupLegendItems', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.ts index b35fb012a7eb1..79bfa4520fb69 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.ts @@ -5,13 +5,10 @@ * 2.0. */ -import { v4 as uuidv4 } from 'uuid'; - import { TableId } from '@kbn/securitysolution-data-table'; import { firstNonNullValue } from '../../../../../../../../common/endpoint/models/ecs_safety_helpers'; import type { LegendItem } from '../../../../../../../common/components/charts/draggable_legend_item'; import { getFillColor } from '../chart_palette'; -import { escapeDataProviderId } from '../../../../../../../common/components/drag_and_drop/helpers'; import { getLabel } from '../labels'; import type { FlattenedBucket, RawBucket } from '../../types'; @@ -35,9 +32,6 @@ export const getLegendItemFromRawBucket = ({ }) : undefined, count: bucket.doc_count, - dataProviderId: escapeDataProviderId( - `draggable-legend-item-treemap-${stackByField0}-${bucket.key}-${uuidv4()}` - ), render: () => getLabel({ baseLabel: bucket.key_as_string ?? firstNonNullValue(bucket.key) ?? '', // prefer key_as_string when available, because it contains a formatted date @@ -66,9 +60,6 @@ export const getLegendItemFromFlattenedBucket = ({ colorPalette, }), count: stackByField1DocCount, - dataProviderId: escapeDataProviderId( - `draggable-legend-item-treemap-${key}-${stackByField1Key}-${uuidv4()}` - ), render: () => `${stackByField1Key}`, field: `${stackByField1}`, value: `${stackByField1Key}`, diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/__snapshots__/index.test.tsx.snap index 5ad1e9553d4bf..d0f3c156f78ba 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/__snapshots__/index.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/__snapshots__/index.test.tsx.snap @@ -34,14 +34,6 @@ exports[`IP Overview Component rendering it renders the default IP Overview 1`] opacity: 1; } -.c1 > span.euiToolTipAnchor { - display: block; -} - -.c1 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} -
span.euiToolTipAnchor { - display: block; -} - -.c1 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} -
( description: locationRenderer( [`${flowTarget}.geo.city_name`, `${flowTarget}.geo.region_name`], data, - contextID + scopeId ), }, { title: i18n.AUTONOMOUS_SYSTEM, description: typeData - ? autonomousSystemRenderer(typeData.autonomousSystem, flowTarget, contextID) + ? autonomousSystemRenderer(typeData.autonomousSystem, flowTarget, scopeId) : getEmptyTagValue(), }, ]; @@ -165,7 +165,6 @@ export const IpOverview = React.memo( scopeId, host: data.host, ipFilter: ip, - contextID, isFlyoutOpen, }) : getEmptyTagValue(), diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/__snapshots__/point_tool_tip_content.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/__snapshots__/point_tool_tip_content.test.tsx.snap index 741e186b28212..31f47946b10e6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/__snapshots__/point_tool_tip_content.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/__snapshots__/point_tool_tip_content.test.tsx.snap @@ -1,14 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`PointToolTipContent renders correctly against snapshot 1`] = ` -.c0 > span.euiToolTipAnchor { - display: block; -} - -.c0 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} -
- .c0 > span.euiToolTipAnchor { - display: block; -} - -.c0 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} - -
- .c0 > span.euiToolTipAnchor { - display: block; -} - -.c0 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} - - @@ -113,11 +95,10 @@ exports[`Field Renderers #hostIdRenderer it renders correctly against snapshot 1 >
- .c0 > span.euiToolTipAnchor { - display: block; -} - -.c0 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} - -
@@ -170,11 +143,10 @@ exports[`Field Renderers #hostNameRenderer it renders correctly against snapshot >
- .c0 > span.euiToolTipAnchor { - display: block; -} - -.c0 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} - -
{ describe('#locationRenderer', () => { test('it renders correctly against snapshot', () => { const { asFragment } = render( - locationRenderer(['source.geo.city_name', 'source.geo.region_name'], mockData.complete), + locationRenderer( + ['source.geo.city_name', 'source.geo.region_name'], + mockData.complete, + scopeId + ), { wrapper: TestProviders } ); @@ -51,14 +55,14 @@ describe('Field Renderers', () => { }); test('it renders emptyTagValue when no fields provided', () => { - render({locationRenderer([], mockData.complete)}); + render({locationRenderer([], mockData.complete, scopeId)}); expect(screen.getByText(getEmptyValue())).toBeInTheDocument(); }); test('it renders emptyTagValue when invalid fields provided', () => { render( - {locationRenderer(['source.geo.my_house'], mockData.complete)} + {locationRenderer(['source.geo.my_house'], mockData.complete, scopeId)} ); expect(screen.getByText(getEmptyValue())).toBeInTheDocument(); @@ -71,7 +75,11 @@ describe('Field Renderers', () => { test('it renders correctly against snapshot', () => { const { asFragment } = render( - autonomousSystemRenderer(mockData.complete.source!.autonomousSystem!, FlowTarget.source), + autonomousSystemRenderer( + mockData.complete.source!.autonomousSystem!, + FlowTarget.source, + scopeId + ), { wrapper: TestProviders } ); @@ -80,14 +88,18 @@ describe('Field Renderers', () => { test('it renders emptyTagValue when non-string field provided', () => { render( - {autonomousSystemRenderer(halfEmptyMock, FlowTarget.source)} + + {autonomousSystemRenderer(halfEmptyMock, FlowTarget.source, scopeId)} + ); expect(screen.getByText(getEmptyValue())).toBeInTheDocument(); }); test('it renders emptyTagValue when invalid field provided', () => { render( - {autonomousSystemRenderer(emptyMock, FlowTarget.source)} + + {autonomousSystemRenderer(emptyMock, FlowTarget.source, scopeId)} + ); expect(screen.getByText(getEmptyValue())).toBeInTheDocument(); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/field_renderers/field_renderers.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/field_renderers/field_renderers.tsx index 2397a7f3bd13e..3bef8aa5bcdb8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/field_renderers/field_renderers.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/field_renderers/field_renderers.tsx @@ -16,7 +16,7 @@ import type { FlowTargetSourceDest, NetworkDetailsStrategyResponse, } from '../../../../../common/search_strategy'; -import { DefaultDraggable } from '../../../../common/components/draggables'; +import { CellActionsRenderer } from '../../../../common/components/cell_actions/cell_actions_renderer'; import { getEmptyTagValue } from '../../../../common/components/empty_value'; import { ReputationLink, WhoIsLink } from '../../../../common/components/links'; import * as i18n from '../details/translations'; @@ -28,7 +28,7 @@ export const IpOverviewId = 'ip-overview'; export const locationRenderer = ( fieldNames: string[], data: NetworkDetailsStrategyResponse['networkDetails'], - contextID?: string + scopeId: string ): React.ReactElement => fieldNames.length > 0 && fieldNames.every((fieldName) => getOr(null, fieldName, data)) ? ( @@ -38,15 +38,7 @@ export const locationRenderer = ( {index ? ',\u00A0' : ''} - + ); @@ -59,29 +51,23 @@ export const locationRenderer = ( export const autonomousSystemRenderer = ( as: AutonomousSystem, flowTarget: FlowTarget | FlowTargetSourceDest, - contextID?: string + scopeId: string ): React.ReactElement => as && as.organization && as.organization.name && as.number ? ( - {'/'} - @@ -143,34 +129,23 @@ interface HostNameRendererTypes { scopeId: SourcererScopeName; host: HostEcs; ipFilter?: string; - contextID?: string; isFlyoutOpen: boolean; } export const hostNameRenderer = ({ scopeId, host, ipFilter, - contextID, isFlyoutOpen, }: HostNameRendererTypes): React.ReactElement => host.name && host.name[0] && host.ip && (!(ipFilter != null) || host.ip.includes(ipFilter)) ? ( - + - + ) : ( getEmptyTagValue() ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/geo_fields.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/geo_fields.tsx index 9cd456e1d2cd6..cf6a241c991d0 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/geo_fields.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/geo_fields.tsx @@ -10,7 +10,7 @@ import { get, uniq } from 'lodash/fp'; import React from 'react'; import styled from '@emotion/styled'; -import { DefaultDraggable } from '../../../../common/components/draggables'; +import { CellActionsRenderer } from '../../../../common/components/cell_actions/cell_actions_renderer'; import { CountryFlag } from './country_flag'; import type { GeoFieldsProps, SourceDestinationType } from './types'; @@ -89,11 +89,9 @@ const GeoFieldValues = React.memo<{ ) : null} - diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/index.test.tsx index 19beb68192637..6c9bd4d76c3cd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/index.test.tsx @@ -45,16 +45,24 @@ import { NETWORK_PROTOCOL_FIELD_NAME, NETWORK_TRANSPORT_FIELD_NAME, } from './field_names'; -import { CellActionsWrapper } from '../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { SecurityCellActions } from '../../../../common/components/cell_actions'; -jest.mock('../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../common/components/cell_actions', () => { return { - CellActionsWrapper: jest.fn(), + SecurityCellActions: jest.fn(), + CellActionsMode: { + HOVER_DOWN: 'hover-down', + HOVER_RIGHT: 'hover-right', + INLINE: 'inline', + }, + SecurityCellActionsTrigger: { + DEFAULT: 'default', + }, }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedSecurityCellActions = jest.fn(({ children }) => { + return
{children}
; }); jest.mock('../../../../common/lib/kibana'); @@ -131,7 +139,7 @@ jest.mock('react-router-dom', () => { describe('SourceDestination', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (SecurityCellActions as unknown as jest.Mock).mockImplementation(MockedSecurityCellActions); }); test('renders correctly against snapshot', () => { @@ -337,9 +345,11 @@ describe('SourceDestination', () => { test('should passing correct scopeId to cell actions', () => { render({getSourceDestinationInstance()}); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedSecurityCellActions).toHaveBeenCalledWith( expect.objectContaining({ - scopeId: 'some_scope', + metadata: expect.objectContaining({ + scopeId: 'some_scope', + }), }), {} ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/network.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/network.tsx index 441438912feb2..c976b80be70ec 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/network.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/network.tsx @@ -11,7 +11,8 @@ import React from 'react'; import styled from '@emotion/styled'; import { DirectionBadge } from '../direction'; -import { DefaultDraggable, DraggableBadge } from '../../../../common/components/draggables'; +import { CellActionsRenderer } from '../../../../common/components/cell_actions/cell_actions_renderer'; +import { DraggableBadge } from '../../../../common/components/draggables'; import * as i18n from './translations'; import { @@ -95,18 +96,13 @@ export const Network = React.memo<{ ? uniq(bytes).map((b) => !isNaN(Number(b)) ? ( - + - + ) : null ) @@ -115,16 +111,11 @@ export const Network = React.memo<{ {packets != null ? uniq(packets).map((p) => ( - + {`${p} ${i18n.PACKETS}`} - + )) : null} diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/source_destination_arrows.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/source_destination_arrows.tsx index f4839dec9ba12..c72f62a53ce14 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/source_destination_arrows.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/source_destination/source_destination_arrows.tsx @@ -17,7 +17,7 @@ import { getPercent, hasOneValue, } from '../arrows/helpers'; -import { DefaultDraggable } from '../../../../common/components/draggables'; +import { CellActionsRenderer } from '../../../../common/components/cell_actions/cell_actions_renderer'; import { PreferenceFormattedBytes } from '../../../../common/components/formatted_bytes'; import * as i18n from './translations'; @@ -74,10 +74,9 @@ const SourceArrow = React.memo<{ {sourceBytes != null && !isNaN(Number(sourceBytes)) ? ( - @@ -88,7 +87,7 @@ const SourceArrow = React.memo<{
- + ) : null} @@ -98,16 +97,15 @@ const SourceArrow = React.memo<{ {sourcePackets != null && !isNaN(Number(sourcePackets)) ? ( - {`${sourcePackets} ${i18n.PACKETS}`} - + ) : null} @@ -161,10 +159,9 @@ const DestinationArrow = React.memo<{ {destinationBytes != null && !isNaN(Number(destinationBytes)) ? ( - @@ -175,7 +172,7 @@ const DestinationArrow = React.memo<{
- + ) : null} @@ -185,16 +182,15 @@ const DestinationArrow = React.memo<{ {destinationPackets != null && !isNaN(Number(destinationPackets)) ? ( - {`${numeral(destinationPackets).format('0,0')} ${i18n.PACKETS}`} - + ) : null} diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/host_overview/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/overview/components/host_overview/__snapshots__/index.test.tsx.snap index 44f1a76b79e76..a2c0e42a798f1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/host_overview/__snapshots__/index.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/host_overview/__snapshots__/index.test.tsx.snap @@ -34,14 +34,6 @@ exports[`Host Summary Component it renders the default Host Summary 1`] = ` opacity: 1; } -.c1 > span.euiToolTipAnchor { - display: block; -} - -.c1 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} -
span.euiToolTipAnchor { - display: block; -} - -.c1 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} -
span.euiToolTipAnchor { - display: block; -} - -.c1 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} -
span.euiToolTipAnchor { - display: block; -} - -.c1 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} -
)} {typeof rowItem === 'string' && ( - + {render ? render(rowItem) : rowItem} - + )} ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/formatted_ip/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/formatted_ip/index.test.tsx index 791917e9da60f..b81f28bcc478a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/formatted_ip/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/formatted_ip/index.test.tsx @@ -37,14 +37,6 @@ jest.mock('../../../common/lib/kibana/kibana_react', () => { }; }); -jest.mock('../../../common/components/drag_and_drop/draggable_wrapper', () => { - const original = jest.requireActual('../../../common/components/drag_and_drop/draggable_wrapper'); - return { - ...original, - DraggableWrapper: () =>
, - }; -}); - jest.mock('../../store'); const mockOpenFlyout = jest.fn(); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap index 8b1fe8d554b4d..7168d972a3523 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap @@ -2,23 +2,15 @@ exports[`Netflow renders correctly against snapshot 1`] = ` - .c1 > span.euiToolTipAnchor { - display: block; -} - -.c1 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} - -.c4 { + .c3 { margin-right: 5px; } -.c3 { +.c2 { margin-right: 5px; } -.c2 { +.c1 { margin-right: 3px; position: relative; top: -1px; @@ -50,14 +42,13 @@ exports[`Netflow renders correctly against snapshot 1`] = ` class="euiFlexItem emotion-euiFlexItem-growZero" >
ja3 @@ -1310,14 +1276,13 @@ exports[`Netflow renders correctly against snapshot 1`] = ` class="euiFlexItem emotion-euiFlexItem-growZero" >
client cert @@ -1374,14 +1339,13 @@ exports[`Netflow renders correctly against snapshot 1`] = ` class="euiFlexItem emotion-euiFlexItem-growZero" >
server cert diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/index.test.tsx index 01e2a1313628b..d123552884910 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/index.test.tsx @@ -61,7 +61,25 @@ import { NETWORK_TRANSPORT_FIELD_NAME, } from '../../../explore/network/components/source_destination/field_names'; import { getMockNetflowData } from '../../../common/mock/netflow'; -import { CellActionsWrapper } from '../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { SecurityCellActions } from '../../../common/components/cell_actions'; + +jest.mock('../../../common/components/cell_actions', () => { + return { + SecurityCellActions: jest.fn(), + CellActionsMode: { + HOVER_DOWN: 'hover-down', + HOVER_RIGHT: 'hover-right', + INLINE: 'inline', + }, + SecurityCellActionsTrigger: { + DEFAULT: 'default', + }, + }; +}); + +const MockedSecurityCellActions = jest.fn(({ children }) => { + return
{children}
; +}); jest.mock('../../../common/lib/kibana'); @@ -73,16 +91,6 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../common/components/drag_and_drop/cell_actions_wrapper', () => { - return { - CellActionsWrapper: jest.fn(), - }; -}); - -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; -}); - const getNetflowInstance = () => ( { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + jest.clearAllMocks(); + (SecurityCellActions as unknown as jest.Mock).mockImplementation(MockedSecurityCellActions); }); test('renders correctly against snapshot', () => { @@ -390,9 +399,11 @@ describe('Netflow', () => { test('should passing correct scopeId to cell actions', () => { render({getNetflowInstance()}); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedSecurityCellActions).toHaveBeenCalledWith( expect.objectContaining({ - scopeId: 'some_scope', + metadata: expect.objectContaining({ + scopeId: 'some_scope', + }), }), {} ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/netflow_columns/duration_event_start_end.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/netflow_columns/duration_event_start_end.tsx index bf96d20e8f724..547ce8032e4d5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/netflow_columns/duration_event_start_end.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/netflow_columns/duration_event_start_end.tsx @@ -10,7 +10,7 @@ import { uniq } from 'lodash/fp'; import React from 'react'; import styled from 'styled-components'; -import { DefaultDraggable } from '../../../../common/components/draggables'; +import { CellActionsRenderer } from '../../../../common/components/cell_actions/cell_actions_renderer'; import { EVENT_DURATION_FIELD_NAME } from '../../duration'; import { FormattedDate } from '../../../../common/components/formatted_date'; import { FormattedDuration } from '../../formatted_duration'; @@ -33,13 +33,11 @@ TimeIcon.displayName = 'TimeIcon'; * - `event.end` */ export const DurationEventStartEnd = React.memo<{ - contextId: string; eventDuration?: string[] | null; - eventId: string; eventEnd?: string[] | null; eventStart?: string[] | null; scopeId: string; -}>(({ contextId, eventDuration, eventId, eventEnd, eventStart, scopeId }) => ( +}>(({ eventDuration, eventEnd, eventStart, scopeId }) => ( ( - @@ -66,17 +61,16 @@ export const DurationEventStartEnd = React.memo<{ tooltipTitle={EVENT_DURATION_FIELD_NAME} /> - + )) : null} {eventStart != null ? uniq(eventStart).map((start) => ( - @@ -84,17 +78,16 @@ export const DurationEventStartEnd = React.memo<{ - + )) : null} {eventEnd != null ? uniq(eventEnd).map((end) => ( - @@ -102,7 +95,7 @@ export const DurationEventStartEnd = React.memo<{ - + )) : null} diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/netflow_columns/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/netflow_columns/index.tsx index a397ffd442a38..34567c8d1876d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/netflow_columns/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/netflow_columns/index.tsx @@ -83,9 +83,7 @@ export const NetflowColumns = React.memo( diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/args.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/args.test.tsx index 34b0e78e8cb20..5ee025c8a6a3f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/args.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/args.test.tsx @@ -11,7 +11,7 @@ import React from 'react'; import { useMountAppended } from '../../../../../common/utils/use_mount_appended'; import { TestProviders } from '../../../../../common/mock'; import { ArgsComponent } from './args'; -import { CellActionsWrapper } from '../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../common/components/cell_actions/cell_actions_renderer'; jest.mock('../../../../../common/lib/kibana'); @@ -23,21 +23,21 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('Args', () => { const mount = useMountAppended(); beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); describe('rendering', () => { @@ -159,7 +159,7 @@ describe('Args', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/dns/dns_request_event_details_line.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/dns/dns_request_event_details_line.test.tsx index 888bccda14d85..652dc7eed3edd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/dns/dns_request_event_details_line.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/dns/dns_request_event_details_line.test.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { TestProviders } from '../../../../../../common/mock'; import { DnsRequestEventDetailsLine } from './dns_request_event_details_line'; import { useMountAppended } from '../../../../../../common/utils/use_mount_appended'; -import { CellActionsWrapper } from '../../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../../common/components/cell_actions/cell_actions_renderer'; jest.mock('../../../../../../common/lib/kibana'); @@ -22,19 +22,19 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('DnsRequestEventDetailsLine', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); const mount = useMountAppended(); @@ -439,7 +439,7 @@ describe('DnsRequestEventDetailsLine', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.test.tsx index a8c4642600a76..52788a3ae1857 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.test.tsx @@ -11,7 +11,7 @@ import { TestProviders } from '../../../../../../common/mock'; import { EndgameSecurityEventDetailsLine } from './endgame_security_event_details_line'; import { useMountAppended } from '../../../../../../common/utils/use_mount_appended'; -import { CellActionsWrapper } from '../../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../../common/components/cell_actions/cell_actions_renderer'; jest.mock('../../../../../../common/lib/kibana'); @@ -23,19 +23,19 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('EndgameSecurityEventDetailsLine', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); const mount = useMountAppended(); @@ -675,7 +675,7 @@ describe('EndgameSecurityEventDetailsLine', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.test.tsx index 160334f40466c..f821b7ad91e48 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { TestProviders } from '../../../../../common/mock'; import { useMountAppended } from '../../../../../common/utils/use_mount_appended'; -import { CellActionsWrapper } from '../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../common/components/cell_actions/cell_actions_renderer'; import { ExitCodeDraggable } from './exit_code_draggable'; @@ -23,19 +23,19 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('ExitCodeDraggable', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); const mount = useMountAppended(); @@ -213,7 +213,7 @@ describe('ExitCodeDraggable', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_draggable.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_draggable.test.tsx index b205fe2c1e4c3..c2db657917f51 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_draggable.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_draggable.test.tsx @@ -11,7 +11,7 @@ import { TestProviders } from '../../../../../common/mock'; import { FileDraggable } from './file_draggable'; import { useMountAppended } from '../../../../../common/utils/use_mount_appended'; -import { CellActionsWrapper } from '../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../common/components/cell_actions/cell_actions_renderer'; jest.mock('../../../../../common/lib/kibana'); @@ -23,19 +23,19 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('FileDraggable', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); const mount = useMountAppended(); @@ -165,7 +165,7 @@ describe('FileDraggable', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_hash.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_hash.test.tsx index 38a784b138259..203f54a5b56c3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_hash.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_hash.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { TestProviders } from '../../../../../common/mock'; import { useMountAppended } from '../../../../../common/utils/use_mount_appended'; -import { CellActionsWrapper } from '../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../common/components/cell_actions/cell_actions_renderer'; import { FileHash } from './file_hash'; @@ -23,19 +23,19 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('FileHash', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); const mount = useMountAppended(); @@ -79,7 +79,7 @@ describe('FileHash', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_working_dir.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_working_dir.test.tsx index 1b45ec9fb6640..5599e6354f59f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_working_dir.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_working_dir.test.tsx @@ -11,7 +11,7 @@ import React from 'react'; import { mockTimelineData, TestProviders } from '../../../../../common/mock'; import { useMountAppended } from '../../../../../common/utils/use_mount_appended'; import { HostWorkingDir } from './host_working_dir'; -import { CellActionsWrapper } from '../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../common/components/cell_actions/cell_actions_renderer'; jest.mock('../../../../../common/lib/kibana'); @@ -23,19 +23,19 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('HostWorkingDir', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); const mount = useMountAppended(); @@ -139,7 +139,7 @@ describe('HostWorkingDir', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap index 2a528d01c71a2..8f1daa0f0e7a6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap @@ -16,23 +16,15 @@ exports[`netflowRowRenderer renders correctly against snapshot 1`] = ` border-radius: 4px; } -.c3 > span.euiToolTipAnchor { - display: block; -} - -.c3 > span.euiToolTipAnchor.eui-textTruncate { - display: inline-block; -} - -.c6 { +.c5 { margin-right: 5px; } -.c5 { +.c4 { margin-right: 5px; } -.c4 { +.c3 { margin-right: 3px; position: relative; top: -1px; @@ -82,11 +74,10 @@ exports[`netflowRowRenderer renders correctly against snapshot 1`] = ` >
ja3 @@ -1290,11 +1256,10 @@ exports[`netflowRowRenderer renders correctly against snapshot 1`] = ` class="euiFlexItem emotion-euiFlexItem-growZero" >
client cert @@ -1350,11 +1315,10 @@ exports[`netflowRowRenderer renders correctly against snapshot 1`] = ` class="euiFlexItem emotion-euiFlexItem-growZero" >
server cert diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.test.tsx index c36136b1e8ece..c6951f2a89168 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.test.tsx @@ -11,7 +11,7 @@ import { TestProviders } from '../../../../../common/mock'; import { ParentProcessDraggable } from './parent_process_draggable'; import { useMountAppended } from '../../../../../common/utils/use_mount_appended'; -import { CellActionsWrapper } from '../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../common/components/cell_actions/cell_actions_renderer'; jest.mock('../../../../../common/lib/kibana'); @@ -23,19 +23,19 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('ParentProcessDraggable', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); const mount = useMountAppended(); @@ -165,7 +165,7 @@ describe('ParentProcessDraggable', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_draggable.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_draggable.test.tsx index 4d37e5b68c171..41d6923a2f875 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_draggable.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_draggable.test.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { TestProviders } from '../../../../../common/mock'; import { ProcessDraggable, ProcessDraggableWithNonExistentProcess } from './process_draggable'; -import { CellActionsWrapper } from '../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../common/components/cell_actions/cell_actions_renderer'; import { useMountAppended } from '../../../../../common/utils/use_mount_appended'; jest.mock('../../../../../common/lib/kibana'); @@ -23,19 +23,19 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('ProcessDraggable', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); const mount = useMountAppended(); @@ -465,7 +465,7 @@ describe('ProcessDraggable', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), @@ -619,7 +619,7 @@ describe('ProcessDraggableWithNonExistentProcess', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_hash.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_hash.test.tsx index b8a7a25d5849d..c438b9688690e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_hash.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_hash.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { TestProviders } from '../../../../../common/mock'; import { useMountAppended } from '../../../../../common/utils/use_mount_appended'; -import { CellActionsWrapper } from '../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../common/components/cell_actions/cell_actions_renderer'; import { ProcessHash } from './process_hash'; @@ -30,19 +30,19 @@ const allProps = { processHashSha256: undefined, }; -jest.mock('../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('ProcessHash', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); const mount = useMountAppended(); @@ -80,7 +80,7 @@ describe('ProcessHash', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/registry/registry_event_details_line.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/registry/registry_event_details_line.test.tsx index 6747bc6781117..040d9290f0980 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/registry/registry_event_details_line.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/registry/registry_event_details_line.test.tsx @@ -11,7 +11,7 @@ import { TestProviders } from '../../../../../../common/mock'; import { useMountAppended } from '../../../../../../common/utils/use_mount_appended'; import { RegistryEventDetailsLine } from './registry_event_details_line'; import { MODIFIED_REGISTRY_KEY } from '../system/translations'; -import { CellActionsWrapper } from '../../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../../common/components/cell_actions/cell_actions_renderer'; jest.mock('../../../../../../common/lib/kibana'); @@ -23,19 +23,19 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('DnsRequestEventDetailsLine', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); const mount = useMountAppended(); @@ -155,7 +155,7 @@ describe('DnsRequestEventDetailsLine', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/__snapshots__/suricata_details.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/__snapshots__/suricata_details.test.tsx.snap index e79b1e254fea3..e69e3cea64a64 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/__snapshots__/suricata_details.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/__snapshots__/suricata_details.test.tsx.snap @@ -3,8 +3,8 @@ exports[`SuricataDetails rendering it renders the default SuricataDetails 1`] = `
diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/__snapshots__/suricata_row_renderer.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/__snapshots__/suricata_row_renderer.test.tsx.snap index 8066a40af2d30..5f8384c31dca2 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/__snapshots__/suricata_row_renderer.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/__snapshots__/suricata_row_renderer.test.tsx.snap @@ -70,7 +70,7 @@ exports[`suricata_row_renderer renders correctly against snapshot 1`] = ` }, } } - timelineId="timeline-test" + scopeId="timeline-test" /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/__snapshots__/suricata_signature.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/__snapshots__/suricata_signature.test.tsx.snap index c9f04ca2313a3..76561820d349f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/__snapshots__/suricata_signature.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/__snapshots__/suricata_signature.test.tsx.snap @@ -6,8 +6,8 @@ exports[`SuricataSignature rendering it renders the default SuricataSignature 1` justifyContent="center" wrap={true} > - - @@ -36,7 +36,7 @@ exports[`SuricataSignature rendering it renders the default SuricataSignature 1` Hello
- + `; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_details.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_details.test.tsx index 7a7408925cc07..db56fa42de6dd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_details.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_details.test.tsx @@ -37,14 +37,14 @@ describe('SuricataDetails', () => { }; describe('rendering', () => { test('it renders the default SuricataDetails', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); test('it returns text if the data does contain suricata data', async () => { const wrapper = await getWrapper( - + ); const removeEuiIconText = removeExternalLinkText(wrapper.text()).replaceAll( @@ -57,7 +57,7 @@ describe('SuricataDetails', () => { }); test('it returns null for text if the data contains no suricata data', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.isEmptyRender()).toBeTruthy(); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_details.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_details.tsx index 69aca83f6857d..3d5bfb58c0aae 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_details.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_details.tsx @@ -24,8 +24,8 @@ Details.displayName = 'Details'; export const SuricataDetails = React.memo<{ data: Ecs; - timelineId: string; -}>(({ data, timelineId }) => { + scopeId: string; +}>(({ data, scopeId }) => { const signature: string | null | undefined = get('suricata.eve.alert.signature[0]', data); const signatureId: number | null | undefined = get('suricata.eve.alert.signature_id[0]', data); @@ -33,14 +33,14 @@ export const SuricataDetails = React.memo<{ return (
- +
); } else { diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.tsx index 9fe1a6085407c..31a6f31226a27 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.tsx @@ -22,7 +22,7 @@ export const suricataRowRenderer: RowRenderer = { }, renderRow: ({ data, scopeId }) => ( - + ), }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.test.tsx index 8f69bf0eb7271..92531b6d4b53b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.test.tsx @@ -13,7 +13,7 @@ import { useMountAppended } from '../../../../../../common/utils/use_mount_appen import { SuricataSignature, Tokens, - DraggableSignatureId, + SignatureId, SURICATA_SIGNATURE_ID_FIELD_NAME, } from './suricata_signature'; @@ -34,7 +34,7 @@ describe('SuricataSignature', () => { test('it renders the default SuricataSignature', () => { const wrapper = shallow( { }); }); - describe('DraggableSignatureId', () => { + describe('SignatureId', () => { test('it renders the default SuricataSignature', () => { const wrapper = mount( - + ); expect(wrapper.text()).toEqual('123'); @@ -82,12 +82,13 @@ describe('SuricataSignature', () => { test('it renders a tooltip for the signature field', () => { const wrapper = mount( - + ); expect( - wrapper.find('[data-test-subj="signature-id-tooltip"]').first().props().content + wrapper.find('[data-test-subj="suricata.eve.alert.signature_id-tooltip"]').first().props() + .content ).toEqual(SURICATA_SIGNATURE_ID_FIELD_NAME); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.tsx index 83acb4e7a8f83..14bd05a6428c8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.tsx @@ -5,20 +5,13 @@ * 2.0. */ -import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; -import React, { useCallback, useMemo } from 'react'; +import { EuiBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import React from 'react'; import styled from 'styled-components'; - -import type { DraggableWrapperProps } from '../../../../../../common/components/drag_and_drop/draggable_wrapper'; -import { DraggableWrapper } from '../../../../../../common/components/drag_and_drop/draggable_wrapper'; -import { escapeDataProviderId } from '../../../../../../common/components/drag_and_drop/helpers'; import { GoogleLink } from '../../../../../../common/components/links'; - +import { CellActionsRenderer } from '../../../../../../common/components/cell_actions/cell_actions_renderer'; import { TokensFlexItem } from '../helpers'; import { getBeginningTokens } from './suricata_links'; -import { DefaultDraggable } from '../../../../../../common/components/draggables'; -import type { QueryOperator } from '../../../data_providers/data_provider'; -import { IS_OPERATOR } from '../../../data_providers/data_provider'; export const SURICATA_SIGNATURE_FIELD_NAME = 'suricata.eve.alert.signature'; export const SURICATA_SIGNATURE_ID_FIELD_NAME = 'suricata.eve.alert.signature_id'; @@ -55,80 +48,52 @@ export const Tokens = React.memo<{ tokens: string[] }>(({ tokens }) => ( Tokens.displayName = 'Tokens'; -export const DraggableSignatureId = React.memo<{ - id: string; +export const SignatureId = React.memo<{ + scopeId: string; signatureId: number; -}>(({ id, signatureId }) => { - const dataProviderProp = useMemo( - () => ({ - and: [], - enabled: true, - id: escapeDataProviderId(`suricata-draggable-signature-id-${id}-sig-${signatureId}`), - name: String(signatureId), - excluded: false, - kqlQuery: '', - queryMatch: { - field: SURICATA_SIGNATURE_ID_FIELD_NAME, - value: signatureId, - operator: IS_OPERATOR as QueryOperator, - }, - }), - [id, signatureId] - ); - - const render: DraggableWrapperProps['render'] = useCallback( - () => ( - +}>(({ scopeId, signatureId }) => { + return ( + + {signatureId} - - ), - [signatureId] - ); - - return ( - - + ); }); -DraggableSignatureId.displayName = 'DraggableSignatureId'; +SignatureId.displayName = 'SignatureId'; export const SuricataSignature = React.memo<{ - contextId: string; + scopeId: string; id: string; signature: string; signatureId: number; -}>(({ contextId, id, signature, signatureId }) => { +}>(({ scopeId, id, signature, signatureId }) => { const tokens = getBeginningTokens(signature); return ( - + -
{signature.split(' ').splice(tokens.length).join(' ')}
-
+
); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/auth_ssh.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/auth_ssh.test.tsx index f33d8a95ee452..b5b7e39ab868d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/auth_ssh.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/auth_ssh.test.tsx @@ -9,21 +9,21 @@ import { shallow, mount } from 'enzyme'; import React from 'react'; import { AuthSsh } from './auth_ssh'; -import { CellActionsWrapper } from '../../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../../common/components/cell_actions/cell_actions_renderer'; -jest.mock('../../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('AuthSsh', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); describe('rendering', () => { test('it renders against shallow snapshot', () => { @@ -128,7 +128,7 @@ describe('AuthSsh', () => { /> ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.test.tsx index 5522f21ebd388..6443403977011 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.test.tsx @@ -12,7 +12,7 @@ import { mockTimelineData, TestProviders } from '../../../../../../common/mock'; import { mockEndgameCreationEvent } from '../../../../../../common/mock/mock_endgame_ecs_data'; import { SystemGenericFileDetails, SystemGenericFileLine } from './generic_file_details'; import { useMountAppended } from '../../../../../../common/utils/use_mount_appended'; -import { CellActionsWrapper } from '../../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../../common/components/cell_actions/cell_actions_renderer'; jest.mock('../../../../../../common/lib/kibana'); @@ -36,19 +36,19 @@ jest.mock('react-router-dom', () => { }; }); -jest.mock('../../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('SystemGenericFileDetails', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); const mount = useMountAppended(); @@ -110,7 +110,7 @@ describe('SystemGenericFileDetails', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), @@ -1893,7 +1893,7 @@ describe('SystemGenericFileDetails', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/package.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/package.test.tsx index 1ab7b57eacb25..1b06f9aab5e2d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/package.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/package.test.tsx @@ -11,7 +11,7 @@ import React from 'react'; import { TestProviders } from '../../../../../../common/mock'; import { useMountAppended } from '../../../../../../common/utils/use_mount_appended'; import { Package } from './package'; -import { CellActionsWrapper } from '../../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { CellActionsRenderer } from '../../../../../../common/components/cell_actions/cell_actions_renderer'; jest.mock('../../../../../../common/lib/kibana'); @@ -23,19 +23,19 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../../common/components/cell_actions/cell_actions_renderer', () => { return { - CellActionsWrapper: jest.fn(), + CellActionsRenderer: jest.fn(), }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedCellActionsRenderer = jest.fn(({ children }) => { + return
{children}
; }); describe('Package', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (CellActionsRenderer as unknown as jest.Mock).mockImplementation(MockedCellActionsRenderer); }); const mount = useMountAppended(); @@ -154,7 +154,7 @@ describe('Package', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedCellActionsRenderer).toHaveBeenCalledWith( expect.objectContaining({ scopeId: 'some_scope', }), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_host_working_dir.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_host_working_dir.test.tsx index 1c946daa6bff3..d4f20bfe55319 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_host_working_dir.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_host_working_dir.test.tsx @@ -11,7 +11,7 @@ import React from 'react'; import { TestProviders } from '../../../../../common/mock'; import { UserHostWorkingDir } from './user_host_working_dir'; import { useMountAppended } from '../../../../../common/utils/use_mount_appended'; -import { CellActionsWrapper } from '../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { SecurityCellActions } from '../../../../../common/components/cell_actions'; jest.mock('../../../../../common/lib/kibana'); @@ -23,19 +23,27 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../common/components/cell_actions', () => { return { - CellActionsWrapper: jest.fn(), + SecurityCellActions: jest.fn(), + CellActionsMode: { + HOVER_DOWN: 'hover-down', + HOVER_RIGHT: 'hover-right', + INLINE: 'inline', + }, + SecurityCellActionsTrigger: { + DEFAULT: 'default', + }, }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedSecurityCellActions = jest.fn(({ children }) => { + return
{children}
; }); describe('UserHostWorkingDir', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (SecurityCellActions as unknown as jest.Mock).mockImplementation(MockedSecurityCellActions); }); const mount = useMountAppended(); @@ -259,7 +267,7 @@ describe('UserHostWorkingDir', () => { expect(wrapper.text()).toEqual('[user-name-123]custom separator[host-name-123]'); }); - test('it renders a draggable `user.domain` field (by default) when userDomain is provided, and userDomainField is NOT specified as a prop', () => { + test('it renders `user.domain` field (by default) when userDomain is provided, and userDomainField is NOT specified as a prop', () => { const wrapper = mount(
@@ -276,10 +284,10 @@ describe('UserHostWorkingDir', () => { ); - expect(wrapper.find('[data-test-subj="render-content-user.domain"]').exists()).toBe(true); + expect(wrapper.find('[data-test-subj="user.domain-tooltip"]').exists()).toBe(true); }); - test('it renders a draggable with an overridden field name when userDomain is provided, and userDomainField is also specified as a prop', () => { + test('it renders with an overridden field name when userDomain is provided, and userDomainField is also specified as a prop', () => { const wrapper = mount(
@@ -297,12 +305,10 @@ describe('UserHostWorkingDir', () => { ); - expect(wrapper.find('[data-test-subj="render-content-overridden.field.name"]').exists()).toBe( - true - ); + expect(wrapper.find('[data-test-subj="overridden.field.name-tooltip"]').exists()).toBe(true); }); - test('it renders a draggable `user.name` field (by default) when userName is provided, and userNameField is NOT specified as a prop', () => { + test('it renders a `user.name` field (by default) when userName is provided, and userNameField is NOT specified as a prop', () => { const wrapper = mount(
@@ -319,10 +325,10 @@ describe('UserHostWorkingDir', () => { ); - expect(wrapper.find('[data-test-subj="render-content-user.name"]').exists()).toBe(true); + expect(wrapper.find('[data-test-subj="user.name-tooltip"]').exists()).toBe(true); }); - test('it renders a draggable with an overridden field name when userName is provided, and userNameField is also specified as a prop', () => { + test('it renders with an overridden field name when userName is provided, and userNameField is also specified as a prop', () => { const wrapper = mount(
@@ -363,9 +369,11 @@ describe('UserHostWorkingDir', () => { ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedSecurityCellActions).toHaveBeenCalledWith( expect.objectContaining({ - scopeId: 'some_scope', + metadata: expect.objectContaining({ + scopeId: 'some_scope', + }), }), {} ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap index dab754c0fcc14..949587a4b9db3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/__snapshots__/zeek_details.test.tsx.snap @@ -83,6 +83,6 @@ exports[`ZeekDetails rendering it renders the default ZeekDetails 1`] = ` }, } } - timelineId="test" + scopeId="test" /> `; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/__snapshots__/zeek_row_renderer.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/__snapshots__/zeek_row_renderer.test.tsx.snap index 59f903a17baae..0c8233e3d27d1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/__snapshots__/zeek_row_renderer.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/__snapshots__/zeek_row_renderer.test.tsx.snap @@ -70,7 +70,7 @@ exports[`zeek_row_renderer renders correctly against snapshot 1`] = ` }, } } - timelineId="timeline-test" + scopeId="timeline-test" /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/__snapshots__/zeek_signature.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/__snapshots__/zeek_signature.test.tsx.snap index fc8d1b1bc84d1..db0a2d97b606b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/__snapshots__/zeek_signature.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/__snapshots__/zeek_signature.test.tsx.snap @@ -7,83 +7,69 @@ exports[`ZeekSignature rendering it renders the default Zeek 1`] = ` justifyContent="center" wrap={true} > - - - - - - - - - - - - - - diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_details.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_details.test.tsx index f44d0a9401793..485d44b62d25c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_details.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_details.test.tsx @@ -37,7 +37,7 @@ describe('ZeekDetails', () => { test('it renders the default ZeekDetails', () => { const wrapper = mount( - + ); expect(wrapper.find('ZeekDetails')).toMatchSnapshot(); @@ -46,7 +46,7 @@ describe('ZeekDetails', () => { test('it returns zeek.connection if the data does contain zeek.connection data', () => { const wrapper = mount( - + ); expect(extractEuiIconText(removeExternalLinkText(wrapper.text()))).toEqual( @@ -57,7 +57,7 @@ describe('ZeekDetails', () => { test('it returns zeek.dns if the data does contain zeek.dns data', () => { const wrapper = mount( - + ); expect(extractEuiIconText(removeExternalLinkText(wrapper.text()))).toEqual( @@ -68,7 +68,7 @@ describe('ZeekDetails', () => { test('it returns zeek.http if the data does contain zeek.http data', () => { const wrapper = mount( - + ); expect(extractEuiIconText(removeExternalLinkText(wrapper.text()))).toEqual( @@ -79,7 +79,7 @@ describe('ZeekDetails', () => { test('it returns zeek.notice if the data does contain zeek.notice data', () => { const wrapper = mount( - + ); expect(extractEuiIconText(removeExternalLinkText(wrapper.text()))).toEqual( @@ -90,7 +90,7 @@ describe('ZeekDetails', () => { test('it returns zeek.ssl if the data does contain zeek.ssl data', () => { const wrapper = mount( - + ); expect(extractEuiIconText(removeExternalLinkText(wrapper.text()))).toEqual( @@ -101,7 +101,7 @@ describe('ZeekDetails', () => { test('it returns zeek.files if the data does contain zeek.files data', () => { const wrapper = mount( - + ); expect(wrapper.text()).toEqual('Cu0n232QMyvNtzb75jfilessha1: fa5195a...md5: f7653f1...'); @@ -110,7 +110,7 @@ describe('ZeekDetails', () => { test('it returns null for text if the data contains no zeek data', () => { const wrapper = mount( - + ); expect(wrapper.find('ZeekDetails').children().exists()).toBeFalsy(); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_details.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_details.tsx index 050f05523c510..69d2f4f6c6cf8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_details.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_details.tsx @@ -22,15 +22,15 @@ Details.displayName = 'Details'; interface ZeekDetailsProps { data: Ecs; - timelineId: string; + scopeId: string; } -export const ZeekDetails = React.memo(({ data, timelineId }) => +export const ZeekDetails = React.memo(({ data, scopeId }) => data.zeek != null ? (
- + - +
) : null ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_row_renderer.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_row_renderer.tsx index ac09011b9bcc1..03056e946fdef 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_row_renderer.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_row_renderer.tsx @@ -22,7 +22,7 @@ export const zeekRowRenderer: RowRenderer = { }, renderRow: ({ data, scopeId }) => ( - + ), }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.test.tsx index 995dcb7215942..9558fb6c5a34c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.test.tsx @@ -19,25 +19,33 @@ import { constructDroppedValue, TotalVirusLinkSha, Link, - DraggableZeekElement, + ZeekElement, sha1StringRenderer, md5StringRenderer, droppedStringRenderer, moduleStringRenderer, defaultStringRenderer, } from './zeek_signature'; -import { CellActionsWrapper } from '../../../../../../common/components/drag_and_drop/cell_actions_wrapper'; +import { SecurityCellActions } from '../../../../../../common/components/cell_actions'; jest.mock('../../../../../../common/lib/kibana'); -jest.mock('../../../../../../common/components/drag_and_drop/cell_actions_wrapper', () => { +jest.mock('../../../../../../common/components/cell_actions', () => { return { - CellActionsWrapper: jest.fn(), + SecurityCellActions: jest.fn(), + CellActionsMode: { + HOVER_DOWN: 'hover-down', + HOVER_RIGHT: 'hover-right', + INLINE: 'inline', + }, + SecurityCellActionsTrigger: { + DEFAULT: 'default', + }, }; }); -const MockedCellActionsWrapper = jest.fn(({ children }) => { - return
{children}
; +const MockedSecurityCellActions = jest.fn(({ children }) => { + return
{children}
; }); jest.mock('@elastic/eui', () => { @@ -58,7 +66,7 @@ describe('ZeekSignature', () => { describe('rendering', () => { test('it renders the default Zeek', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); }); @@ -126,29 +134,24 @@ describe('ZeekSignature', () => { }); }); - describe('DraggableZeekElement', () => { + describe('ZeekElement', () => { beforeEach(() => { - (CellActionsWrapper as unknown as jest.Mock).mockImplementation(MockedCellActionsWrapper); + (SecurityCellActions as unknown as jest.Mock).mockImplementation(MockedSecurityCellActions); }); test('it returns null if value is null', () => { const wrapper = mount( - + ); - expect(wrapper.find('DraggableZeekElement').children().exists()).toBeFalsy(); + expect(wrapper.find('ZeekElement').children().exists()).toBeFalsy(); }); test('it renders the default ZeekSignature', () => { const wrapper = mount( - + ); expect(wrapper.text()).toEqual('mynote'); @@ -157,9 +160,8 @@ describe('ZeekSignature', () => { test('it renders with a custom string renderer', () => { const wrapper = mount( - `->${value}<-`} @@ -172,19 +174,15 @@ describe('ZeekSignature', () => { test('should passing correct scopeId to cell actions', () => { mount( - `->${value}<-`} - /> + ); - expect(MockedCellActionsWrapper).toHaveBeenCalledWith( + expect(MockedSecurityCellActions).toHaveBeenCalledWith( expect.objectContaining({ - scopeId: 'some_scope', + metadata: expect.objectContaining({ + scopeId: 'some_scope', + }), }), {} ); @@ -195,18 +193,13 @@ describe('ZeekSignature', () => { const field = 'zeek.notice'; const wrapper = mount( - + ); - expect(wrapper.find('[data-test-subj="badge-tooltip"]').first().props().content).toEqual( - field - ); + expect( + wrapper.find('[data-test-subj="zeek.notice-tooltip"]').first().props().content + ).toEqual(field); }); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.tsx index da22a164a815a..94962d26de18a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.tsx @@ -5,19 +5,13 @@ * 2.0. */ -import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; +import { EuiBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { get } from 'lodash/fp'; -import React, { useCallback, useMemo } from 'react'; +import React from 'react'; import styled from 'styled-components'; - import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; -import type { DraggableWrapperProps } from '../../../../../../common/components/drag_and_drop/draggable_wrapper'; -import { DraggableWrapper } from '../../../../../../common/components/drag_and_drop/draggable_wrapper'; -import { escapeDataProviderId } from '../../../../../../common/components/drag_and_drop/helpers'; +import { CellActionsRenderer } from '../../../../../../common/components/cell_actions/cell_actions_renderer'; import { GoogleLink, ReputationLink } from '../../../../../../common/components/links'; -import type { QueryOperator } from '../../../data_providers/data_provider'; -import { IS_OPERATOR } from '../../../data_providers/data_provider'; - import * as i18n from './translations'; const Badge = styled(EuiBadge)` @@ -62,55 +56,24 @@ export const md5StringRenderer: StringRenderer = (value: string) => `md5: ${valu export const sha1StringRenderer: StringRenderer = (value: string) => `sha1: ${value.substr(0, 7)}...`; -export const DraggableZeekElement = React.memo<{ - id: string; +export const ZeekElement = React.memo<{ field: string; value: string | null | undefined; - stringRenderer?: StringRenderer; scopeId: string; -}>(({ id, field, value, stringRenderer = defaultStringRenderer, scopeId }) => { - const dataProviderProp = useMemo( - () => ({ - and: [], - enabled: true, - id: escapeDataProviderId(`draggable-zeek-element-draggable-wrapper-${id}-${field}-${value}`), - name: String(value), - excluded: false, - kqlQuery: '', - queryMatch: { - field, - value: String(value), - operator: IS_OPERATOR as QueryOperator, - }, - }), - [field, id, value] - ); - - const render: DraggableWrapperProps['render'] = useCallback( - () => ( - + stringRenderer?: StringRenderer; +}>(({ field, value, scopeId, stringRenderer = defaultStringRenderer }) => + value != null ? ( + + {stringRenderer(String(value))} - - ), - [field, stringRenderer, value] - ); - - return value != null ? ( - - + - ) : null; -}); + ) : null +); -DraggableZeekElement.displayName = 'DraggableZeekElement'; +ZeekElement.displayName = 'ZeekElement'; interface LinkProps { value: string | null | undefined; @@ -203,11 +166,10 @@ export const constructDroppedValue = (dropped: boolean | null | undefined): stri interface ZeekSignatureProps { data: Ecs; - timelineId: string; + scopeId: string; } -export const ZeekSignature = React.memo(({ data, timelineId }) => { - const id = `zeek-signature-draggable-zeek-element-${timelineId}-${data._id}`; +export const ZeekSignature = React.memo(({ data, scopeId }) => { const sessionId: string | null | undefined = get('zeek.session_id[0]', data); const dataSet: string | null | undefined = get('event.dataset[0]', data); const sslVersion: string | null | undefined = get('zeek.ssl.version[0]', data); @@ -234,81 +196,41 @@ export const ZeekSignature = React.memo(({ data, timelineId return ( <> - - + - - - - - - - - - - - - + + + + + + + +