mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Security Solution] Replace badge with health indicator in endpoint details flyout (#115901)
This commit is contained in:
parent
414a1fbf0d
commit
80bb1ad8da
3 changed files with 41 additions and 72 deletions
|
@ -62,7 +62,7 @@ export const EndpointDetailsFlyoutTabs = memo(
|
|||
const selectedTab = useMemo(() => tabs.find((tab) => tab.id === show), [tabs, show]);
|
||||
|
||||
const renderTabs = tabs.map((tab) => (
|
||||
<EndpointDetailsTab tab={tab} isSelected={tab.id === selectedTab?.id} />
|
||||
<EndpointDetailsTab key={tab.id} tab={tab} isSelected={tab.id === selectedTab?.id} />
|
||||
));
|
||||
|
||||
return (
|
||||
|
|
|
@ -13,8 +13,9 @@ import {
|
|||
EuiText,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiBadge,
|
||||
EuiSpacer,
|
||||
EuiLink,
|
||||
EuiHealth,
|
||||
} from '@elastic/eui';
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
@ -30,7 +31,6 @@ import { getEndpointDetailsPath } from '../../../../common/routing';
|
|||
import { EndpointPolicyLink } from '../components/endpoint_policy_link';
|
||||
import { OutOfDate } from '../components/out_of_date';
|
||||
import { EndpointAgentStatus } from '../components/endpoint_agent_status';
|
||||
import { useAppUrl } from '../../../../../common/lib/kibana/hooks';
|
||||
|
||||
const HostIds = styled(EuiListGroupItem)`
|
||||
margin-top: 0;
|
||||
|
@ -53,9 +53,8 @@ export const EndpointDetailsContent = memo(
|
|||
const policyStatus = useEndpointSelector(
|
||||
policyResponseStatus
|
||||
) as keyof typeof POLICY_STATUS_TO_BADGE_COLOR;
|
||||
const { getAppUrl } = useAppUrl();
|
||||
|
||||
const [policyResponseUri, policyResponseRoutePath] = useMemo(() => {
|
||||
const policyResponseRoutePath = useMemo(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const { selected_endpoint, show, ...currentUrlParams } = queryParams;
|
||||
const path = getEndpointDetailsPath({
|
||||
|
@ -63,8 +62,8 @@ export const EndpointDetailsContent = memo(
|
|||
...currentUrlParams,
|
||||
selected_endpoint: details.agent.id,
|
||||
});
|
||||
return [getAppUrl({ path }), path];
|
||||
}, [details.agent.id, getAppUrl, queryParams]);
|
||||
return path;
|
||||
}, [details.agent.id, queryParams]);
|
||||
|
||||
const policyStatusClickHandler = useNavigateByRouterEventHandler(policyResponseRoutePath);
|
||||
|
||||
|
@ -142,26 +141,20 @@ export const EndpointDetailsContent = memo(
|
|||
defaultMessage: 'Policy Status',
|
||||
}),
|
||||
description: (
|
||||
// https://github.com/elastic/eui/issues/4530
|
||||
// @ts-ignore
|
||||
<EuiBadge
|
||||
<EuiHealth
|
||||
data-test-subj={`policyStatusValue-${policyStatus}`}
|
||||
color={POLICY_STATUS_TO_BADGE_COLOR[policyStatus] || 'default'}
|
||||
data-test-subj="policyStatusValue"
|
||||
href={policyResponseUri}
|
||||
onClick={policyStatusClickHandler}
|
||||
onClickAriaLabel={i18n.translate(
|
||||
'xpack.securitySolution.endpoint.details.policyStatus',
|
||||
{ defaultMessage: 'Policy Status' }
|
||||
)}
|
||||
>
|
||||
<EuiText size="m">
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.endpoint.details.policyStatusValue"
|
||||
defaultMessage="{policyStatus, select, success {Success} warning {Warning} failure {Failed} other {Unknown}}"
|
||||
values={{ policyStatus }}
|
||||
/>
|
||||
</EuiText>
|
||||
</EuiBadge>
|
||||
<EuiLink onClick={policyStatusClickHandler} data-test-subj="policyStatusValue">
|
||||
<EuiText size="m">
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.endpoint.details.policyStatusValue"
|
||||
defaultMessage="{policyStatus, select, success {Success} warning {Warning} failure {Failed} other {Unknown}}"
|
||||
values={{ policyStatus }}
|
||||
/>
|
||||
</EuiText>
|
||||
</EuiLink>
|
||||
</EuiHealth>
|
||||
),
|
||||
},
|
||||
{
|
||||
|
@ -185,14 +178,7 @@ export const EndpointDetailsContent = memo(
|
|||
),
|
||||
},
|
||||
];
|
||||
}, [
|
||||
details,
|
||||
hostStatus,
|
||||
policyResponseUri,
|
||||
policyStatus,
|
||||
policyStatusClickHandler,
|
||||
policyInfo,
|
||||
]);
|
||||
}, [details, hostStatus, policyStatus, policyStatusClickHandler, policyInfo]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -167,7 +167,7 @@ describe('when on the endpoint list page', () => {
|
|||
|
||||
it('should NOT display timeline', async () => {
|
||||
const renderResult = render();
|
||||
const timelineFlyout = await renderResult.queryByTestId('flyoutOverlay');
|
||||
const timelineFlyout = renderResult.queryByTestId('flyoutOverlay');
|
||||
expect(timelineFlyout).toBeNull();
|
||||
});
|
||||
|
||||
|
@ -460,7 +460,7 @@ describe('when on the endpoint list page', () => {
|
|||
const outOfDates = await renderResult.findAllByTestId('rowPolicyOutOfDate');
|
||||
expect(outOfDates).toHaveLength(4);
|
||||
|
||||
outOfDates.forEach((item, index) => {
|
||||
outOfDates.forEach((item) => {
|
||||
expect(item.textContent).toEqual('Out-of-date');
|
||||
expect(item.querySelector(`[data-euiicon-type][color=warning]`)).not.toBeNull();
|
||||
});
|
||||
|
@ -512,8 +512,8 @@ describe('when on the endpoint list page', () => {
|
|||
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/75721
|
||||
describe.skip('when polling on Endpoint List', () => {
|
||||
beforeEach(async () => {
|
||||
await reactTestingLibrary.act(() => {
|
||||
beforeEach(() => {
|
||||
reactTestingLibrary.act(() => {
|
||||
const hostListData = mockEndpointResultList({ total: 4 }).hosts;
|
||||
|
||||
setEndpointListApiMockImplementation(coreStart.http, {
|
||||
|
@ -703,8 +703,8 @@ describe('when on the endpoint list page', () => {
|
|||
|
||||
it('should show the flyout and footer', async () => {
|
||||
const renderResult = await renderAndWaitForData();
|
||||
await expect(renderResult.findByTestId('endpointDetailsFlyout')).not.toBeNull();
|
||||
await expect(renderResult.queryByTestId('endpointDetailsFlyoutFooter')).not.toBeNull();
|
||||
expect(renderResult.getByTestId('endpointDetailsFlyout')).not.toBeNull();
|
||||
expect(renderResult.getByTestId('endpointDetailsFlyoutFooter')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should display policy name value as a link', async () => {
|
||||
|
@ -738,15 +738,6 @@ describe('when on the endpoint list page', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('should display policy status value as a link', async () => {
|
||||
const renderResult = await renderAndWaitForData();
|
||||
const policyStatusLink = await renderResult.findByTestId('policyStatusValue');
|
||||
expect(policyStatusLink).not.toBeNull();
|
||||
expect(policyStatusLink.getAttribute('href')).toEqual(
|
||||
`${APP_PATH}${MANAGEMENT_PATH}/endpoints?page_index=0&page_size=10&selected_endpoint=1&show=policy_response`
|
||||
);
|
||||
});
|
||||
|
||||
it('should update the URL when policy status link is clicked', async () => {
|
||||
const renderResult = await renderAndWaitForData();
|
||||
const policyStatusLink = await renderResult.findByTestId('policyStatusValue');
|
||||
|
@ -763,10 +754,8 @@ describe('when on the endpoint list page', () => {
|
|||
it('should display Success overall policy status', async () => {
|
||||
const renderResult = await renderAndWaitForData();
|
||||
const policyStatusBadge = await renderResult.findByTestId('policyStatusValue');
|
||||
expect(renderResult.getByTestId('policyStatusValue-success')).toBeTruthy();
|
||||
expect(policyStatusBadge.textContent).toEqual('Success');
|
||||
expect(policyStatusBadge.getAttribute('style')).toMatch(
|
||||
/background-color\: rgb\(109\, 204\, 177\)\;/
|
||||
);
|
||||
});
|
||||
|
||||
it('should display Warning overall policy status', async () => {
|
||||
|
@ -774,9 +763,7 @@ describe('when on the endpoint list page', () => {
|
|||
const renderResult = await renderAndWaitForData();
|
||||
const policyStatusBadge = await renderResult.findByTestId('policyStatusValue');
|
||||
expect(policyStatusBadge.textContent).toEqual('Warning');
|
||||
expect(policyStatusBadge.getAttribute('style')).toMatch(
|
||||
/background-color\: rgb\(241\, 216\, 111\)\;/
|
||||
);
|
||||
expect(renderResult.getByTestId('policyStatusValue-warning')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should display Failed overall policy status', async () => {
|
||||
|
@ -784,9 +771,7 @@ describe('when on the endpoint list page', () => {
|
|||
const renderResult = await renderAndWaitForData();
|
||||
const policyStatusBadge = await renderResult.findByTestId('policyStatusValue');
|
||||
expect(policyStatusBadge.textContent).toEqual('Failed');
|
||||
expect(policyStatusBadge.getAttribute('style')).toMatch(
|
||||
/background-color\: rgb\(255\, 126\, 98\)\;/
|
||||
);
|
||||
expect(renderResult.getByTestId('policyStatusValue-failure')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should display Unknown overall policy status', async () => {
|
||||
|
@ -794,9 +779,7 @@ describe('when on the endpoint list page', () => {
|
|||
const renderResult = await renderAndWaitForData();
|
||||
const policyStatusBadge = await renderResult.findByTestId('policyStatusValue');
|
||||
expect(policyStatusBadge.textContent).toEqual('Unknown');
|
||||
expect(policyStatusBadge.getAttribute('style')).toMatch(
|
||||
/background-color\: rgb\(211\, 218\, 230\)\;/
|
||||
);
|
||||
expect(renderResult.getByTestId('policyStatusValue-')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show the Take Action button', async () => {
|
||||
|
@ -898,7 +881,7 @@ describe('when on the endpoint list page', () => {
|
|||
await reactTestingLibrary.act(async () => {
|
||||
await middlewareSpy.waitForAction('serverReturnedEndpointList');
|
||||
});
|
||||
const hostNameLinks = await renderResult.getAllByTestId('hostnameCellLink');
|
||||
const hostNameLinks = renderResult.getAllByTestId('hostnameCellLink');
|
||||
reactTestingLibrary.fireEvent.click(hostNameLinks[0]);
|
||||
});
|
||||
|
||||
|
@ -913,7 +896,7 @@ describe('when on the endpoint list page', () => {
|
|||
reactTestingLibrary.act(() => {
|
||||
dispatchEndpointDetailsActivityLogChanged('success', getMockData());
|
||||
});
|
||||
const endpointDetailsFlyout = await renderResult.queryByTestId('endpointDetailsFlyoutBody');
|
||||
const endpointDetailsFlyout = renderResult.queryByTestId('endpointDetailsFlyoutBody');
|
||||
expect(endpointDetailsFlyout).not.toBeNull();
|
||||
});
|
||||
|
||||
|
@ -926,7 +909,7 @@ describe('when on the endpoint list page', () => {
|
|||
reactTestingLibrary.act(() => {
|
||||
dispatchEndpointDetailsActivityLogChanged('success', getMockData());
|
||||
});
|
||||
const logEntries = await renderResult.queryAllByTestId('timelineEntry');
|
||||
const logEntries = renderResult.queryAllByTestId('timelineEntry');
|
||||
expect(logEntries.length).toEqual(3);
|
||||
expect(`${logEntries[0]} .euiCommentTimeline__icon--update`).not.toBe(null);
|
||||
expect(`${logEntries[1]} .euiCommentTimeline__icon--regular`).not.toBe(null);
|
||||
|
@ -944,7 +927,7 @@ describe('when on the endpoint list page', () => {
|
|||
getMockData({ hasLogsEndpointActionResponses: true })
|
||||
);
|
||||
});
|
||||
const logEntries = await renderResult.queryAllByTestId('timelineEntry');
|
||||
const logEntries = renderResult.queryAllByTestId('timelineEntry');
|
||||
expect(logEntries.length).toEqual(4);
|
||||
expect(`${logEntries[0]} .euiCommentTimeline__icon--update`).not.toBe(null);
|
||||
expect(`${logEntries[1]} .euiCommentTimeline__icon--update`).not.toBe(null);
|
||||
|
@ -960,7 +943,7 @@ describe('when on the endpoint list page', () => {
|
|||
reactTestingLibrary.act(() => {
|
||||
dispatchEndpointDetailsActivityLogChanged('failed', getMockData());
|
||||
});
|
||||
const emptyState = await renderResult.queryByTestId('activityLogEmpty');
|
||||
const emptyState = renderResult.queryByTestId('activityLogEmpty');
|
||||
expect(emptyState).not.toBe(null);
|
||||
});
|
||||
|
||||
|
@ -980,10 +963,10 @@ describe('when on the endpoint list page', () => {
|
|||
});
|
||||
});
|
||||
|
||||
const emptyState = await renderResult.queryByTestId('activityLogEmpty');
|
||||
const emptyState = renderResult.queryByTestId('activityLogEmpty');
|
||||
expect(emptyState).toBe(null);
|
||||
|
||||
const superDatePicker = await renderResult.queryByTestId('activityLogSuperDatePicker');
|
||||
const superDatePicker = renderResult.queryByTestId('activityLogSuperDatePicker');
|
||||
expect(superDatePicker).not.toBe(null);
|
||||
});
|
||||
|
||||
|
@ -1002,7 +985,7 @@ describe('when on the endpoint list page', () => {
|
|||
reactTestingLibrary.act(() => {
|
||||
dispatchEndpointDetailsActivityLogChanged('success', getMockData());
|
||||
});
|
||||
const logEntries = await renderResult.queryAllByTestId('timelineEntry');
|
||||
const logEntries = renderResult.queryAllByTestId('timelineEntry');
|
||||
expect(logEntries.length).toEqual(3);
|
||||
});
|
||||
|
||||
|
@ -1047,7 +1030,7 @@ describe('when on the endpoint list page', () => {
|
|||
reactTestingLibrary.act(() => {
|
||||
dispatchEndpointDetailsActivityLogChanged('success', getMockData());
|
||||
});
|
||||
const commentTexts = await renderResult.queryAllByTestId('activityLogCommentText');
|
||||
const commentTexts = renderResult.queryAllByTestId('activityLogCommentText');
|
||||
expect(commentTexts.length).toEqual(1);
|
||||
expect(commentTexts[0].textContent).toEqual('some comment');
|
||||
expect(commentTexts[0].parentElement?.parentElement?.className).toContain(
|
||||
|
@ -1081,7 +1064,7 @@ describe('when on the endpoint list page', () => {
|
|||
afterEach(reactTestingLibrary.cleanup);
|
||||
|
||||
it('should hide the host details panel', async () => {
|
||||
const endpointDetailsFlyout = await renderResult.queryByTestId('endpointDetailsFlyoutBody');
|
||||
const endpointDetailsFlyout = renderResult.queryByTestId('endpointDetailsFlyoutBody');
|
||||
expect(endpointDetailsFlyout).toBeNull();
|
||||
});
|
||||
|
||||
|
@ -1328,8 +1311,8 @@ describe('when on the endpoint list page', () => {
|
|||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should NOT show the flyout footer', async () => {
|
||||
await expect(renderResult.queryByTestId('endpointDetailsFlyoutFooter')).toBeNull();
|
||||
it('should NOT show the flyout footer', () => {
|
||||
expect(renderResult.queryByTestId('endpointDetailsFlyoutFooter')).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue