Skip to content

Commit

Permalink
[Security Solution] expandable flyout - add no data message in entiti…
Browse files Browse the repository at this point in the history
…es details and entities overview components (elastic#164955)
  • Loading branch information
PhilippeOberti authored Aug 29, 2023
1 parent 299407d commit 34c7a03
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import '@testing-library/jest-dom';
import { LeftPanelContext } from '../context';
import { TestProviders } from '../../../common/mock';
import { EntitiesDetails } from './entities_details';
import { ENTITIES_DETAILS_TEST_ID, HOST_DETAILS_TEST_ID, USER_DETAILS_TEST_ID } from './test_ids';
import {
ENTITIES_DETAILS_NO_DATA_TEST_ID,
ENTITIES_DETAILS_TEST_ID,
HOST_DETAILS_TEST_ID,
USER_DETAILS_TEST_ID,
} from './test_ids';
import { mockContextValue } from '../mocks/mock_context';
import { EXPANDABLE_PANEL_CONTENT_TEST_ID } from '../../shared/components/test_ids';

Expand Down Expand Up @@ -49,8 +54,8 @@ describe('<EntitiesDetails />', () => {
expect(getByTestId(HOST_TEST_ID)).toBeInTheDocument();
});

it('does not render user and host details if user name and host name are not available', () => {
const { queryByTestId } = render(
it('should render no data message if user name and host name are not available', () => {
const { getByTestId, queryByTestId } = render(
<TestProviders>
<LeftPanelContext.Provider
value={{
Expand All @@ -63,12 +68,13 @@ describe('<EntitiesDetails />', () => {
</LeftPanelContext.Provider>
</TestProviders>
);
expect(getByTestId(ENTITIES_DETAILS_NO_DATA_TEST_ID)).toBeInTheDocument();
expect(queryByTestId(USER_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(HOST_TEST_ID)).not.toBeInTheDocument();
});

it('does not render user and host details if @timestamp is not available', () => {
const { queryByTestId } = render(
const { getByTestId, queryByTestId } = render(
<TestProviders>
<LeftPanelContext.Provider
value={{
Expand All @@ -89,6 +95,7 @@ describe('<EntitiesDetails />', () => {
</LeftPanelContext.Provider>
</TestProviders>
);
expect(getByTestId(ENTITIES_DETAILS_NO_DATA_TEST_ID)).toBeInTheDocument();
expect(queryByTestId(USER_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(HOST_TEST_ID)).not.toBeInTheDocument();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@

import React from 'react';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { ENTITIES_NO_DATA_MESSAGE } from './translations';
import { useLeftPanelContext } from '../context';
import { getField } from '../../shared/utils';
import { UserDetails } from './user_details';
import { HostDetails } from './host_details';
import { ENTITIES_DETAILS_TEST_ID } from './test_ids';
import { ENTITIES_DETAILS_NO_DATA_TEST_ID, ENTITIES_DETAILS_TEST_ID } from './test_ids';

export const ENTITIES_TAB_ID = 'entities-details';

Expand All @@ -24,19 +25,29 @@ export const EntitiesDetails: React.FC = () => {
const userName = getField(getFieldsData('user.name'));
const timestamp = getField(getFieldsData('@timestamp'));

const showDetails = timestamp && (hostName || userName);
const showUserDetails = userName && timestamp;
const showHostDetails = hostName && timestamp;

return (
<EuiFlexGroup direction="column" gutterSize="m" data-test-subj={ENTITIES_DETAILS_TEST_ID}>
{userName && timestamp && (
<EuiFlexItem>
<UserDetails userName={userName} timestamp={timestamp} scopeId={scopeId} />
</EuiFlexItem>
)}
{hostName && timestamp && (
<EuiFlexItem>
<HostDetails hostName={hostName} timestamp={timestamp} scopeId={scopeId} />
</EuiFlexItem>
<>
{showDetails ? (
<EuiFlexGroup direction="column" gutterSize="m" data-test-subj={ENTITIES_DETAILS_TEST_ID}>
{showUserDetails && (
<EuiFlexItem>
<UserDetails userName={userName} timestamp={timestamp} scopeId={scopeId} />
</EuiFlexItem>
)}
{showHostDetails && (
<EuiFlexItem>
<HostDetails hostName={hostName} timestamp={timestamp} scopeId={scopeId} />
</EuiFlexItem>
)}
</EuiFlexGroup>
) : (
<div data-test-subj={ENTITIES_DETAILS_NO_DATA_TEST_ID}>{ENTITIES_NO_DATA_MESSAGE}</div>
)}
</EuiFlexGroup>
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const PREVALENCE_DETAILS_TABLE_NO_DATA_TEST_ID =
/* Entities */

export const ENTITIES_DETAILS_TEST_ID = `${PREFIX}EntitiesDetails` as const;
export const ENTITIES_DETAILS_NO_DATA_TEST_ID = `${ENTITIES_DETAILS_TEST_ID}NoData` as const;
export const USER_DETAILS_TEST_ID = `${PREFIX}UsersDetails` as const;
export const USER_DETAILS_INFO_TEST_ID = 'user-overview';
export const USER_DETAILS_RELATED_HOSTS_TABLE_TEST_ID =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@

import { i18n } from '@kbn/i18n';

export const ENTITIES_NO_DATA_MESSAGE = i18n.translate(
'xpack.securitySolution.flyout.entitiesNoDataMessage',
{
defaultMessage: 'No user or host data available',
}
);

export const ANALYZER_ERROR_MESSAGE = i18n.translate(
'xpack.securitySolution.flyout.analyzerErrorMessage',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { RightPanelContext } from '../context';
import {
ENTITIES_HOST_OVERVIEW_TEST_ID,
ENTITIES_USER_OVERVIEW_TEST_ID,
INSIGHTS_ENTITIES_NO_DATA_TEST_ID,
INSIGHTS_ENTITIES_TEST_ID,
} from './test_ids';
import { EntitiesOverview } from './entities_overview';
Expand All @@ -28,16 +29,18 @@ const TITLE_LINK_TEST_ID = EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID(INSIGHTS_E
const TITLE_ICON_TEST_ID = EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID(INSIGHTS_ENTITIES_TEST_ID);
const TITLE_TEXT_TEST_ID = EXPANDABLE_PANEL_HEADER_TITLE_TEXT_TEST_ID(INSIGHTS_ENTITIES_TEST_ID);

const mockContextValue = {
eventId: 'event id',
indexName: 'index',
scopeId: 'scopeId',
getFieldsData: mockGetFieldsData,
} as unknown as RightPanelContext;

describe('<EntitiesOverview />', () => {
it('should render wrapper component', () => {
const contextValue = {
eventId: 'event id',
getFieldsData: mockGetFieldsData,
} as unknown as RightPanelContext;

const { getByTestId, queryByTestId } = render(
<TestProviders>
<RightPanelContext.Provider value={contextValue}>
<RightPanelContext.Provider value={mockContextValue}>
<EntitiesOverview />
</RightPanelContext.Provider>
</TestProviders>
Expand All @@ -51,14 +54,9 @@ describe('<EntitiesOverview />', () => {
});

it('should render user and host', () => {
const contextValue = {
eventId: 'event id',
getFieldsData: mockGetFieldsData,
} as unknown as RightPanelContext;

const { getByTestId } = render(
<TestProviders>
<RightPanelContext.Provider value={contextValue}>
<RightPanelContext.Provider value={mockContextValue}>
<EntitiesOverview />
</RightPanelContext.Provider>
</TestProviders>
Expand All @@ -69,7 +67,7 @@ describe('<EntitiesOverview />', () => {

it('should only render user when host name is null', () => {
const contextValue = {
eventId: 'event id',
...mockContextValue,
getFieldsData: (field: string) => (field === 'user.name' ? 'user1' : null),
} as unknown as RightPanelContext;

Expand All @@ -87,7 +85,7 @@ describe('<EntitiesOverview />', () => {

it('should only render host when user name is null', () => {
const contextValue = {
eventId: 'event id',
...mockContextValue,
getFieldsData: (field: string) => (field === 'host.name' ? 'host1' : null),
} as unknown as RightPanelContext;

Expand All @@ -103,27 +101,61 @@ describe('<EntitiesOverview />', () => {
expect(queryByTestId(ENTITIES_USER_OVERVIEW_TEST_ID)).not.toBeInTheDocument();
});

it('should not render if both host name and user name are null/blank', () => {
it('should render no data message if both host name and user name are null/blank', () => {
const contextValue = {
eventId: 'event id',
...mockContextValue,
getFieldsData: (field: string) => {},
} as unknown as RightPanelContext;

const { container } = render(
const { queryByTestId } = render(
<TestProviders>
<RightPanelContext.Provider value={contextValue}>
<EntitiesOverview />
</RightPanelContext.Provider>
</TestProviders>
);

expect(container).toBeEmptyDOMElement();
expect(queryByTestId(INSIGHTS_ENTITIES_NO_DATA_TEST_ID)).toBeInTheDocument();
});

it('should not render if eventId is null', () => {
const contextValue = {
...mockContextValue,
eventId: null,
getFieldsData: (field: string) => {},
} as unknown as RightPanelContext;

const { container } = render(
<TestProviders>
<RightPanelContext.Provider value={contextValue}>
<EntitiesOverview />
</RightPanelContext.Provider>
</TestProviders>
);

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

it('should not render if indexName is null', () => {
const contextValue = {
...mockContextValue,
indexName: null,
} as unknown as RightPanelContext;

const { container } = render(
<TestProviders>
<RightPanelContext.Provider value={contextValue}>
<EntitiesOverview />
</RightPanelContext.Provider>
</TestProviders>
);

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

it('should not render if scopeId is null', () => {
const contextValue = {
...mockContextValue,
scopeId: null,
} as unknown as RightPanelContext;

const { container } = render(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
import React, { useCallback } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import { useExpandableFlyoutContext } from '@kbn/expandable-flyout';
import { INSIGHTS_ENTITIES_NO_DATA_TEST_ID, INSIGHTS_ENTITIES_TEST_ID } from './test_ids';
import { ExpandablePanel } from '../../shared/components/expandable_panel';
import { useRightPanelContext } from '../context';
import { INSIGHTS_ENTITIES_TEST_ID } from './test_ids';
import { ENTITIES_TITLE } from './translations';
import { ENTITIES_NO_DATA_MESSAGE, ENTITIES_TITLE } from './translations';
import { getField } from '../../shared/utils';
import { HostEntityOverview } from './host_entity_overview';
import { UserEntityOverview } from './user_entity_overview';
Expand Down Expand Up @@ -42,7 +42,7 @@ export const EntitiesOverview: React.FC = () => {
});
}, [eventId, openLeftPanel, indexName, scopeId]);

if (!eventId || (!userName && !hostName)) {
if (!eventId || !indexName || !scopeId) {
return null;
}

Expand All @@ -56,19 +56,23 @@ export const EntitiesOverview: React.FC = () => {
}}
data-test-subj={INSIGHTS_ENTITIES_TEST_ID}
>
<EuiFlexGroup direction="column" gutterSize="s">
{userName && (
<EuiFlexItem>
<UserEntityOverview userName={userName} />
</EuiFlexItem>
)}
<EuiSpacer size="s" />
{hostName && (
<EuiFlexItem>
<HostEntityOverview hostName={hostName} />
</EuiFlexItem>
)}
</EuiFlexGroup>
{userName || hostName ? (
<EuiFlexGroup direction="column" gutterSize="s">
{userName && (
<EuiFlexItem>
<UserEntityOverview userName={userName} />
</EuiFlexItem>
)}
<EuiSpacer size="s" />
{hostName && (
<EuiFlexItem>
<HostEntityOverview hostName={hostName} />
</EuiFlexItem>
)}
</EuiFlexGroup>
) : (
<div data-test-subj={INSIGHTS_ENTITIES_NO_DATA_TEST_ID}>{ENTITIES_NO_DATA_MESSAGE}</div>
)}
</ExpandablePanel>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export const SUMMARY_ROW_VALUE_TEST_ID = (dataTestSubj: string) => `${dataTestSu
/* Insights Entities */

export const INSIGHTS_ENTITIES_TEST_ID = 'securitySolutionDocumentDetailsFlyoutInsightsEntities';
export const INSIGHTS_ENTITIES_NO_DATA_TEST_ID = `${INSIGHTS_ENTITIES_TEST_ID}NoData` as const;
export const ENTITIES_USER_OVERVIEW_TEST_ID =
'securitySolutionDocumentDetailsFlyoutEntitiesUserOverview';
export const ENTITIES_USER_OVERVIEW_LINK_TEST_ID = `${ENTITIES_USER_OVERVIEW_TEST_ID}Link`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ export const ENTITIES_TITLE = i18n.translate(
{ defaultMessage: 'Entities' }
);

export const ENTITIES_NO_DATA_MESSAGE = i18n.translate(
'xpack.securitySolution.flyout.documentDetails.entitiesNoDataMessage',
{
defaultMessage: 'No user or host data available',
}
);

export const THREAT_INTELLIGENCE_TITLE = i18n.translate(
'xpack.securitySolution.flyout.documentDetails.threatIntelligenceTitle',
{ defaultMessage: 'Threat Intelligence' }
Expand Down

0 comments on commit 34c7a03

Please sign in to comment.