diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.test.tsx
index d02f84207ecde..eb56069bb7646 100644
--- a/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.test.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.test.tsx
@@ -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';
@@ -49,8 +54,8 @@ describe('', () => {
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(
', () => {
);
+ 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(
', () => {
);
+ expect(getByTestId(ENTITIES_DETAILS_NO_DATA_TEST_ID)).toBeInTheDocument();
expect(queryByTestId(USER_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(HOST_TEST_ID)).not.toBeInTheDocument();
});
diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.tsx b/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.tsx
index 29e748dd70eae..ff3678a06e428 100644
--- a/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/left/components/entities_details.tsx
@@ -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';
@@ -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 (
-
- {userName && timestamp && (
-
-
-
- )}
- {hostName && timestamp && (
-
-
-
+ <>
+ {showDetails ? (
+
+ {showUserDetails && (
+
+
+
+ )}
+ {showHostDetails && (
+
+
+
+ )}
+
+ ) : (
+ {ENTITIES_NO_DATA_MESSAGE}
)}
-
+ >
);
};
diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/left/components/test_ids.ts
index 6c736770544bd..03b768607c20c 100644
--- a/x-pack/plugins/security_solution/public/flyout/left/components/test_ids.ts
+++ b/x-pack/plugins/security_solution/public/flyout/left/components/test_ids.ts
@@ -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 =
diff --git a/x-pack/plugins/security_solution/public/flyout/left/components/translations.ts b/x-pack/plugins/security_solution/public/flyout/left/components/translations.ts
index dbd0cd21e129c..9e7cf56db7c05 100644
--- a/x-pack/plugins/security_solution/public/flyout/left/components/translations.ts
+++ b/x-pack/plugins/security_solution/public/flyout/left/components/translations.ts
@@ -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',
{
diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.test.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.test.tsx
index d26a93262fa31..528b839bb218c 100644
--- a/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.test.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.test.tsx
@@ -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';
@@ -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('', () => {
it('should render wrapper component', () => {
- const contextValue = {
- eventId: 'event id',
- getFieldsData: mockGetFieldsData,
- } as unknown as RightPanelContext;
-
const { getByTestId, queryByTestId } = render(
-
+
@@ -51,14 +54,9 @@ describe('', () => {
});
it('should render user and host', () => {
- const contextValue = {
- eventId: 'event id',
- getFieldsData: mockGetFieldsData,
- } as unknown as RightPanelContext;
-
const { getByTestId } = render(
-
+
@@ -69,7 +67,7 @@ describe('', () => {
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;
@@ -87,7 +85,7 @@ describe('', () => {
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;
@@ -103,13 +101,13 @@ describe('', () => {
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(
@@ -117,13 +115,47 @@ describe('', () => {
);
- 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(
+
+
+
+
+
+ );
+
+ expect(container).toBeEmptyDOMElement();
+ });
+
+ it('should not render if indexName is null', () => {
+ const contextValue = {
+ ...mockContextValue,
+ indexName: null,
+ } as unknown as RightPanelContext;
+
+ const { container } = render(
+
+
+
+
+
+ );
+
+ expect(container).toBeEmptyDOMElement();
+ });
+
+ it('should not render if scopeId is null', () => {
+ const contextValue = {
+ ...mockContextValue,
+ scopeId: null,
} as unknown as RightPanelContext;
const { container } = render(
diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.tsx b/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.tsx
index d74fd844ea4a9..efab7fa9f6d03 100644
--- a/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/right/components/entities_overview.tsx
@@ -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';
@@ -42,7 +42,7 @@ export const EntitiesOverview: React.FC = () => {
});
}, [eventId, openLeftPanel, indexName, scopeId]);
- if (!eventId || (!userName && !hostName)) {
+ if (!eventId || !indexName || !scopeId) {
return null;
}
@@ -56,19 +56,23 @@ export const EntitiesOverview: React.FC = () => {
}}
data-test-subj={INSIGHTS_ENTITIES_TEST_ID}
>
-
- {userName && (
-
-
-
- )}
-
- {hostName && (
-
-
-
- )}
-
+ {userName || hostName ? (
+
+ {userName && (
+
+
+
+ )}
+
+ {hostName && (
+
+
+
+ )}
+
+ ) : (
+
{ENTITIES_NO_DATA_MESSAGE}
+ )}
>
);
diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/right/components/test_ids.ts
index c4eb67f5ddba9..9c810f7bfc696 100644
--- a/x-pack/plugins/security_solution/public/flyout/right/components/test_ids.ts
+++ b/x-pack/plugins/security_solution/public/flyout/right/components/test_ids.ts
@@ -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`;
diff --git a/x-pack/plugins/security_solution/public/flyout/right/components/translations.ts b/x-pack/plugins/security_solution/public/flyout/right/components/translations.ts
index 3a04a68ac0ebf..4d1390701ad10 100644
--- a/x-pack/plugins/security_solution/public/flyout/right/components/translations.ts
+++ b/x-pack/plugins/security_solution/public/flyout/right/components/translations.ts
@@ -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' }