[Security Solution] Replace badge with health indicator in endpoint details flyout (#115901)

This commit is contained in:
Esteban Beltran 2021-10-25 17:48:36 +02:00 committed by GitHub
parent 414a1fbf0d
commit 80bb1ad8da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 72 deletions

View file

@ -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 (

View file

@ -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 (
<>

View file

@ -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();
});
});
});