Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] [Security Solution][Alert details] - refactor UI on insights (#197349) #198417

Merged
merged 1 commit into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import {
CORRELATIONS_RELATED_CASES_TEST_ID,
CORRELATIONS_SUPPRESSED_ALERTS_TEST_ID,
CORRELATIONS_TEST_ID,
SUMMARY_ROW_VALUE_TEST_ID,
SUMMARY_ROW_BUTTON_TEST_ID,
SUMMARY_ROW_TEXT_TEST_ID,
} from './test_ids';
import { useShowRelatedAlertsByAncestry } from '../../shared/hooks/use_show_related_alerts_by_ancestry';
import { useShowRelatedAlertsBySameSourceEvent } from '../../shared/hooks/use_show_related_alerts_by_same_source_event';
Expand Down Expand Up @@ -58,17 +59,32 @@ const TITLE_LINK_TEST_ID = EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID(CORRELATIO
const TITLE_ICON_TEST_ID = EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID(CORRELATIONS_TEST_ID);
const TITLE_TEXT_TEST_ID = EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID(CORRELATIONS_TEST_ID);

const SUPPRESSED_ALERTS_TEST_ID = SUMMARY_ROW_VALUE_TEST_ID(CORRELATIONS_SUPPRESSED_ALERTS_TEST_ID);
const RELATED_ALERTS_BY_ANCESTRY_TEST_ID = SUMMARY_ROW_VALUE_TEST_ID(
const SUPPRESSED_ALERTS_TEXT_TEST_ID = SUMMARY_ROW_TEXT_TEST_ID(
CORRELATIONS_SUPPRESSED_ALERTS_TEST_ID
);
const SUPPRESSED_ALERTS_VALUE_TEST_ID = SUMMARY_ROW_BUTTON_TEST_ID(
CORRELATIONS_SUPPRESSED_ALERTS_TEST_ID
);
const RELATED_ALERTS_BY_ANCESTRY_TEXT_TEST_ID = SUMMARY_ROW_TEXT_TEST_ID(
CORRELATIONS_RELATED_ALERTS_BY_ANCESTRY_TEST_ID
);
const RELATED_ALERTS_BY_ANCESTRY_VALUE_TEST_ID = SUMMARY_ROW_BUTTON_TEST_ID(
CORRELATIONS_RELATED_ALERTS_BY_ANCESTRY_TEST_ID
);
const RELATED_ALERTS_BY_SAME_SOURCE_EVENT_TEST_ID = SUMMARY_ROW_VALUE_TEST_ID(
const RELATED_ALERTS_BY_SAME_SOURCE_EVENT_TEXT_TEST_ID = SUMMARY_ROW_TEXT_TEST_ID(
CORRELATIONS_RELATED_ALERTS_BY_SAME_SOURCE_EVENT_TEST_ID
);
const RELATED_ALERTS_BY_SESSION_TEST_ID = SUMMARY_ROW_VALUE_TEST_ID(
const RELATED_ALERTS_BY_SAME_SOURCE_EVENT_VALUE_TEST_ID = SUMMARY_ROW_BUTTON_TEST_ID(
CORRELATIONS_RELATED_ALERTS_BY_SAME_SOURCE_EVENT_TEST_ID
);
const RELATED_ALERTS_BY_SESSION_TEXT_TEST_ID = SUMMARY_ROW_TEXT_TEST_ID(
CORRELATIONS_RELATED_ALERTS_BY_SESSION_TEST_ID
);
const RELATED_ALERTS_BY_SESSION_VALUE_TEST_ID = SUMMARY_ROW_BUTTON_TEST_ID(
CORRELATIONS_RELATED_ALERTS_BY_SESSION_TEST_ID
);
const RELATED_CASES_TEST_ID = SUMMARY_ROW_VALUE_TEST_ID(CORRELATIONS_RELATED_CASES_TEST_ID);
const RELATED_CASES_TEXT_TEST_ID = SUMMARY_ROW_TEXT_TEST_ID(CORRELATIONS_RELATED_CASES_TEST_ID);
const RELATED_CASES_VALUE_TEST_ID = SUMMARY_ROW_BUTTON_TEST_ID(CORRELATIONS_RELATED_CASES_TEST_ID);

const panelContextValue = {
eventId: 'event id',
Expand Down Expand Up @@ -193,11 +209,16 @@ describe('<CorrelationsOverview />', () => {
});

const { getByTestId, queryByText } = render(renderCorrelationsOverview(panelContextValue));
expect(getByTestId(RELATED_ALERTS_BY_ANCESTRY_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RELATED_ALERTS_BY_SAME_SOURCE_EVENT_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RELATED_ALERTS_BY_SESSION_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RELATED_CASES_TEST_ID)).toBeInTheDocument();
expect(getByTestId(SUPPRESSED_ALERTS_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RELATED_ALERTS_BY_ANCESTRY_TEXT_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RELATED_ALERTS_BY_ANCESTRY_VALUE_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RELATED_ALERTS_BY_SAME_SOURCE_EVENT_TEXT_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RELATED_ALERTS_BY_SAME_SOURCE_EVENT_VALUE_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RELATED_ALERTS_BY_SESSION_TEXT_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RELATED_ALERTS_BY_SESSION_VALUE_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RELATED_CASES_TEXT_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RELATED_CASES_VALUE_TEST_ID)).toBeInTheDocument();
expect(getByTestId(SUPPRESSED_ALERTS_TEXT_TEST_ID)).toBeInTheDocument();
expect(getByTestId(SUPPRESSED_ALERTS_VALUE_TEST_ID)).toBeInTheDocument();
expect(queryByText(NO_DATA_MESSAGE)).not.toBeInTheDocument();
});

Expand All @@ -215,11 +236,18 @@ describe('<CorrelationsOverview />', () => {
jest.mocked(useShowSuppressedAlerts).mockReturnValue({ show: false, alertSuppressionCount: 0 });

const { getByText, queryByTestId } = render(renderCorrelationsOverview(panelContextValue));
expect(queryByTestId(RELATED_ALERTS_BY_ANCESTRY_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(RELATED_ALERTS_BY_SAME_SOURCE_EVENT_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(RELATED_ALERTS_BY_SESSION_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(RELATED_CASES_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(SUPPRESSED_ALERTS_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(RELATED_ALERTS_BY_ANCESTRY_TEXT_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(RELATED_ALERTS_BY_ANCESTRY_VALUE_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(RELATED_ALERTS_BY_SAME_SOURCE_EVENT_TEXT_TEST_ID)).not.toBeInTheDocument();
expect(
queryByTestId(RELATED_ALERTS_BY_SAME_SOURCE_EVENT_VALUE_TEST_ID)
).not.toBeInTheDocument();
expect(queryByTestId(RELATED_ALERTS_BY_SESSION_TEXT_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(RELATED_ALERTS_BY_SESSION_VALUE_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(RELATED_CASES_TEXT_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(RELATED_CASES_VALUE_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(SUPPRESSED_ALERTS_TEXT_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(SUPPRESSED_ALERTS_VALUE_TEST_ID)).not.toBeInTheDocument();
expect(getByText(NO_DATA_MESSAGE)).toBeInTheDocument();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export const CorrelationsOverview: React.FC = () => {
data-test-subj={CORRELATIONS_TEST_ID}
>
{canShowAtLeastOneInsight ? (
<EuiFlexGroup direction="column" gutterSize="none">
<EuiFlexGroup direction="column" gutterSize="s">
{showSuppressedAlerts && (
<SuppressedAlerts alertSuppressionCount={alertSuppressionCount} ruleType={ruleType} />
)}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,74 +9,147 @@ import React from 'react';
import { render } from '@testing-library/react';
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';
import { InsightsSummaryRow } from './insights_summary_row';
import { useDocumentDetailsContext } from '../../shared/context';
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
import { DocumentDetailsLeftPanelKey } from '../../shared/constants/panel_keys';
import { LeftPanelInsightsTab } from '../../left';

jest.mock('@kbn/expandable-flyout');
jest.mock('../../shared/context');

const mockOpenLeftPanel = jest.fn();
const scopeId = 'scopeId';
const eventId = 'eventId';
const indexName = 'indexName';

const testId = 'test';
const iconTestId = `${testId}Icon`;
const textTestId = `${testId}Text`;
const buttonTestId = `${testId}Button`;
const valueTestId = `${testId}Value`;
const colorTestId = `${testId}Color`;
const loadingTestId = `${testId}Loading`;

describe('<InsightsSummaryRow />', () => {
it('should render by default', () => {
beforeEach(() => {
jest.clearAllMocks();

(useDocumentDetailsContext as jest.Mock).mockReturnValue({
eventId,
indexName,
scopeId,
isPreviewMode: false,
});
(useExpandableFlyoutApi as jest.Mock).mockReturnValue({ openLeftPanel: mockOpenLeftPanel });
});

it('should render loading skeleton if loading is true', () => {
const { getByTestId } = render(
<InsightsSummaryRow
loading={true}
text={'text'}
value={<div>{'value for this'}</div>}
data-test-subj={testId}
/>
);

expect(getByTestId(loadingTestId)).toBeInTheDocument();
});

it('should only render null when error is true', () => {
const { container } = render(
<InsightsSummaryRow error={true} text={'text'} value={<div>{'value for this'}</div>} />
);

expect(container).toBeEmptyDOMElement();
});

it('should render the value component', () => {
const { getByTestId, queryByTestId } = render(
<IntlProvider locale="en">
<InsightsSummaryRow
icon={'image'}
value={1}
text={'this is a test for red'}
color={'rgb(189,39,30)'}
value={<div>{'value for this'}</div>}
data-test-subj={testId}
/>
</IntlProvider>
);

expect(getByTestId(iconTestId)).toBeInTheDocument();
expect(getByTestId(valueTestId)).toHaveTextContent('1 this is a test for red');
expect(getByTestId(colorTestId)).toBeInTheDocument();
expect(getByTestId(textTestId)).toHaveTextContent('this is a test for red');
expect(getByTestId(valueTestId)).toHaveTextContent('value for this');
expect(queryByTestId(buttonTestId)).not.toBeInTheDocument();
});

it('should render loading skeletton if loading is true', () => {
const { getByTestId } = render(
<InsightsSummaryRow loading={true} icon={'image'} text={'text'} data-test-subj={testId} />
it('should render the value as EuiBadge and EuiButtonEmpty', () => {
const { getByTestId, queryByTestId } = render(
<IntlProvider locale="en">
<InsightsSummaryRow text={'this is a test for red'} value={2} data-test-subj={testId} />
</IntlProvider>
);

expect(getByTestId(loadingTestId)).toBeInTheDocument();
expect(getByTestId(textTestId)).toHaveTextContent('this is a test for red');
expect(getByTestId(buttonTestId)).toHaveTextContent('2');
expect(queryByTestId(valueTestId)).not.toBeInTheDocument();
});

it('should only render null when error is true', () => {
const { container } = render(<InsightsSummaryRow error={true} icon={'image'} text={'text'} />);
it('should render big numbers formatted correctly', () => {
const { getByTestId } = render(
<IntlProvider locale="en">
<InsightsSummaryRow text={'this is a test for red'} value={2000} data-test-subj={testId} />
</IntlProvider>
);

expect(container).toBeEmptyDOMElement();
expect(getByTestId(buttonTestId)).toHaveTextContent('2k');
});

it('should handle big number in a compact notation', () => {
it('should open the expanded section to the correct tab when the number is clicked', () => {
const { getByTestId } = render(
<IntlProvider locale="en">
<InsightsSummaryRow
icon={'image'}
value={160000}
text={'this is a test for red'}
color={'rgb(189,39,30)'}
value={2}
expandedSubTab={'subTab'}
data-test-subj={testId}
/>
</IntlProvider>
);
getByTestId(buttonTestId).click();

expect(getByTestId(valueTestId)).toHaveTextContent('160k this is a test for red');
expect(mockOpenLeftPanel).toHaveBeenCalledWith({
id: DocumentDetailsLeftPanelKey,
path: {
tab: LeftPanelInsightsTab,
subTab: 'subTab',
},
params: {
id: eventId,
indexName,
scopeId,
},
});
});

it(`should not show the colored dot if color isn't provided`, () => {
const { queryByTestId } = render(
it('should disabled the click when in preview mode', () => {
(useDocumentDetailsContext as jest.Mock).mockReturnValue({
eventId,
indexName,
scopeId,
isPreviewMode: true,
});

const { getByTestId } = render(
<IntlProvider locale="en">
<InsightsSummaryRow
icon={'image'}
value={160000}
text={'this is a test for no color'}
text={'this is a test for red'}
value={2}
expandedSubTab={'subTab'}
data-test-subj={testId}
/>
</IntlProvider>
);
const button = getByTestId(buttonTestId);

expect(button).toHaveAttribute('disabled');

expect(queryByTestId(colorTestId)).not.toBeInTheDocument();
button.click();
expect(mockOpenLeftPanel).not.toHaveBeenCalled();
});
});
Loading