-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[security solution][Endpoint] Refactor host isolation exceptions list page to now use <ArtifactListPage/>
component
#129099
Changes from 18 commits
e7cc3b3
937877c
7ee5470
956b5f0
48398ba
0ed0abb
12ac093
24c1f00
cb56284
b696e92
36bcdff
ef65a42
84e0aff
7840222
5db499a
71854b0
7453c4a
c924f27
5812b67
53a325d
722b8d7
b688d50
b4bf73b
3ac4b84
bb375e1
2ae32df
e7518f5
ec07ea2
acc0983
3ca47ed
7529671
344b2d0
6ce6b00
f3d33f3
3ff6457
1163df0
739f5ba
176c48d
1f6ca0a
53ae8de
a2d1999
5dba32d
4d853ea
eb307c2
2d5864c
b16c443
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,9 @@ | |
* 2.0. | ||
*/ | ||
|
||
import userEvent from '@testing-library/user-event'; | ||
import { AppContextTestRender } from '../../../common/mock/endpoint'; | ||
|
||
/** | ||
* Forces the `offsetWidth` of `HTMLElement` to a given value. Needed due to the use of | ||
* `react-virtualized-auto-sizer` by the eui `Selectable` component | ||
|
@@ -42,3 +45,51 @@ export const forceHTMLElementOffsetWidth = (width: number = 100): (() => void) = | |
} | ||
}; | ||
}; | ||
|
||
/** | ||
* Clicks on a policy being displayed when `per policy` is selected. | ||
* NOTE: ensure that per-policy is selected first. This utility will | ||
* not do that. | ||
* @param renderResult | ||
* @param [atIndex=0] | ||
*/ | ||
export const clickOnEffectedPolicy = async ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI: a reusable utility for clicking on policies based on the index of the policy entry. I had noticed that in many cases we are being forced to grab the ID of the policy in order to generate the Further below there is another test utility that reports on whether a policy based on its index is selected or not. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is super helpful. Thanks 🥇 |
||
renderResult: ReturnType<AppContextTestRender['render']>, | ||
atIndex: number = 0 | ||
): Promise<Element> => { | ||
const policiesHolderElement = await renderResult.findByTestId( | ||
'effectedPolicies-select-policiesSelectable' | ||
); | ||
const policyElements = policiesHolderElement.querySelectorAll('li.euiSelectableListItem'); | ||
const item = policyElements.item(atIndex); | ||
|
||
if (item) { | ||
userEvent.click(item); | ||
} | ||
|
||
return item; | ||
}; | ||
|
||
/** | ||
* Returns true or false as to whether an effect policy at a given index in the list is selected or not | ||
* @param renderResult | ||
* @param atIndex | ||
*/ | ||
export const isEffectedPolicySelected = async ( | ||
renderResult: ReturnType<AppContextTestRender['render']>, | ||
atIndex: number = 0 | ||
): Promise<boolean> => { | ||
const policiesHolderElement = await renderResult.findByTestId( | ||
'effectedPolicies-select-policiesSelectable' | ||
); | ||
const policyElements = policiesHolderElement.querySelectorAll<HTMLLIElement>( | ||
'li.euiSelectableListItem' | ||
); | ||
const item = policyElements.item(atIndex); | ||
|
||
if (!item) { | ||
throw new Error(`No policy found in EffectedPolicySelect at index position ${atIndex}`); | ||
} | ||
|
||
return item.dataset.testSelected === 'true'; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { AppContextTestRender, createAppRootMockRenderer } from '../../../common/mock/endpoint'; | ||
import { FormattedError } from './formatted_error'; | ||
import React from 'react'; | ||
import type { HttpFetchError } from 'kibana/public'; | ||
|
||
describe('When using the `FormattedError` component', () => { | ||
let render: () => ReturnType<AppContextTestRender['render']>; | ||
let renderResult: ReturnType<AppContextTestRender['render']>; | ||
let error: Error; | ||
|
||
beforeEach(() => { | ||
const mockedContext = createAppRootMockRenderer(); | ||
|
||
render = () => | ||
(renderResult = mockedContext.render(<FormattedError error={error} data-test-subj="test" />)); | ||
error = new Error('foo'); | ||
}); | ||
|
||
it('should display the error message for normal errors', () => { | ||
render(); | ||
|
||
expect(renderResult.getByTestId('test').textContent).toEqual('foo'); | ||
}); | ||
|
||
it('should display status code, message and API response body for HttpFetchError', () => { | ||
const httpError = new Error('api foo') as HttpFetchError; | ||
Object.assign(httpError, { | ||
name: 'foo', | ||
req: {} as Request, | ||
res: {} as Response, | ||
response: { | ||
status: '400', | ||
statusText: 'some 400 error', | ||
} as unknown as Response, | ||
body: { message: 'something bad happen', at: 'some place' }, | ||
}); | ||
error = httpError; | ||
render(); | ||
|
||
expect(renderResult.getByTestId('test').textContent).toEqual( | ||
'400: some 400 errormessage: something bad happenat: some place' | ||
); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import React, { memo, useMemo } from 'react'; | ||
import { EuiText } from '@elastic/eui'; | ||
import type { HttpFetchError } from 'kibana/public'; | ||
|
||
const isHttpFetchError = (error: Error | HttpFetchError): error is HttpFetchError => { | ||
return 'body' in error && 'req' in error && 'res' in error && 'response' in error; | ||
}; | ||
|
||
export interface ObjectContentProps { | ||
data: object; | ||
} | ||
|
||
export const ObjectContent = memo<ObjectContentProps>(({ data }) => { | ||
return ( | ||
<EuiText size="s"> | ||
{Object.entries(data).map(([key, value]) => { | ||
return ( | ||
<div key={key} className="eui-textBreakAll"> | ||
<strong>{key}</strong> | ||
{': '} | ||
{value} | ||
</div> | ||
); | ||
})} | ||
</EuiText> | ||
); | ||
}); | ||
ObjectContent.displayName = 'ObjectContent'; | ||
|
||
export interface FormattedErrorProps { | ||
error: Error; | ||
'data-test-subj'?: string; | ||
} | ||
|
||
/** | ||
* A general component for formatting errors. Recognizes different types of errors and displays | ||
* their information. | ||
*/ | ||
export const FormattedError = memo<FormattedErrorProps>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We will likely improve upon this component moving forward. Example: if we ever introduce server/api provided error codes with response errors, this component could be improved to recognize those types of errors, and formatted them accordingly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔥 awesome |
||
({ error, 'data-test-subj': dataTestSubj }) => { | ||
return useMemo(() => { | ||
let content: JSX.Element = <>{error.message}</>; | ||
|
||
if (isHttpFetchError(error)) { | ||
content = ( | ||
<> | ||
<div>{`${error.response?.status}: ${error.response?.statusText}`}</div> | ||
{error.body && <ObjectContent data={error.body} />} | ||
</> | ||
); | ||
} | ||
|
||
return <EuiText data-test-subj={dataTestSubj}>{content}</EuiText>; | ||
}, [dataTestSubj, error]); | ||
} | ||
); | ||
FormattedError.displayName = 'FormattedError'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
export { FormattedError } from './formatted_error'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,6 @@ | |
* 2.0. | ||
*/ | ||
import { | ||
ExceptionListType, | ||
ExceptionListTypeEnum, | ||
CreateExceptionListSchema, | ||
} from '@kbn/securitysolution-io-ts-list-types'; | ||
|
@@ -22,13 +21,10 @@ export const SEARCHABLE_FIELDS: Readonly<string[]> = [ | |
`entries.value`, | ||
]; | ||
|
||
export const HOST_ISOLATION_EXCEPTIONS_LIST_TYPE: ExceptionListType = | ||
ExceptionListTypeEnum.ENDPOINT_HOST_ISOLATION_EXCEPTIONS; | ||
|
||
export const HOST_ISOLATION_EXCEPTIONS_LIST_DEFINITION: CreateExceptionListSchema = { | ||
name: ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_NAME, | ||
namespace_type: 'agnostic', | ||
description: ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_DESCRIPTION, | ||
list_id: ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID, | ||
type: HOST_ISOLATION_EXCEPTIONS_LIST_TYPE, | ||
type: ExceptionListTypeEnum.ENDPOINT_HOST_ISOLATION_EXCEPTIONS, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is nice! Although, I notice for some reason the trusted_apps list type is called There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, you can do that as long as it does not break anything. This custom |
||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should add a test for this change.