From 31d773843ee7fede2d82ebf7bb22431aff15e6b5 Mon Sep 17 00:00:00 2001 From: Philippe Oberti Date: Wed, 6 Nov 2024 16:59:31 -0600 Subject: [PATCH] [8.x] [Security Solution][Notes] - disable note buttons in the right panel header when in preview mode (#199189) (#199232) # Backport This will backport the following commits from `main` to `8.x`: - [[Security Solution][Notes] - disable note buttons in the right panel header when in preview mode (#199189)](https://github.com/elastic/kibana/pull/199189) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) --- .../right/components/notes.test.tsx | 89 +++++++++++++++++++ .../right/components/notes.tsx | 70 +++++++++------ 2 files changed, 130 insertions(+), 29 deletions(-) diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/notes.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/notes.test.tsx index f70cd2aae3e8d..023b0202ecb63 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/notes.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/notes.test.tsx @@ -23,6 +23,7 @@ import type { Note } from '../../../../../common/api/timeline'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import { DocumentDetailsLeftPanelKey } from '../../shared/constants/panel_keys'; import { LeftPanelNotesTab } from '../../left'; +import { getEmptyValue } from '../../../../common/components/empty_value'; jest.mock('@kbn/expandable-flyout'); @@ -43,6 +44,10 @@ jest.mock('react-redux', () => { }); describe('', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + it('should render loading spinner', () => { (useExpandableFlyoutApi as jest.Mock).mockReturnValue({ openLeftPanel: jest.fn() }); @@ -99,6 +104,34 @@ describe('', () => { }); }); + it('should disabled the Add note button if in preview mode', () => { + const contextValue = { + ...mockContextValue, + isPreviewMode: true, + }; + + const mockOpenLeftPanel = jest.fn(); + (useExpandableFlyoutApi as jest.Mock).mockReturnValue({ openLeftPanel: mockOpenLeftPanel }); + + const { getByTestId } = render( + + + + + + ); + + expect(mockDispatch).not.toHaveBeenCalled(); + + const button = getByTestId(NOTES_ADD_NOTE_BUTTON_TEST_ID); + expect(button).toBeInTheDocument(); + expect(button).toBeDisabled(); + + button.click(); + + expect(mockOpenLeftPanel).not.toHaveBeenCalled(); + }); + it('should render number of notes and plus button', () => { const mockOpenLeftPanel = jest.fn(); (useExpandableFlyoutApi as jest.Mock).mockReturnValue({ openLeftPanel: mockOpenLeftPanel }); @@ -135,6 +168,38 @@ describe('', () => { }); }); + it('should disable the plus button if in preview mode', () => { + const mockOpenLeftPanel = jest.fn(); + (useExpandableFlyoutApi as jest.Mock).mockReturnValue({ openLeftPanel: mockOpenLeftPanel }); + + const contextValue = { + ...mockContextValue, + eventId: '1', + isPreviewMode: true, + }; + + const { getByTestId } = render( + + + + + + ); + + expect(getByTestId(NOTES_COUNT_TEST_ID)).toBeInTheDocument(); + expect(getByTestId(NOTES_COUNT_TEST_ID)).toHaveTextContent('1'); + + expect(mockDispatch).not.toHaveBeenCalled(); + + const button = getByTestId(NOTES_ADD_NOTE_ICON_BUTTON_TEST_ID); + + expect(button).toBeInTheDocument(); + button.click(); + expect(button).toBeDisabled(); + + expect(mockOpenLeftPanel).not.toHaveBeenCalled(); + }); + it('should render number of notes in scientific notation for big numbers', () => { const createMockNote = (noteId: string): Note => ({ eventId: '1', // should be a valid id based on mockTimelineData @@ -180,6 +245,30 @@ describe('', () => { expect(getByTestId(NOTES_COUNT_TEST_ID)).toHaveTextContent('1k'); }); + it('should show a - when in rule creation workflow', () => { + const contextValue = { + ...mockContextValue, + isPreview: true, + }; + + (useExpandableFlyoutApi as jest.Mock).mockReturnValue({ openLeftPanel: jest.fn() }); + + const { getByText, queryByTestId } = render( + + + + + + ); + + expect(mockDispatch).not.toHaveBeenCalled(); + + expect(queryByTestId(NOTES_ADD_NOTE_ICON_BUTTON_TEST_ID)).not.toBeInTheDocument(); + expect(queryByTestId(NOTES_ADD_NOTE_BUTTON_TEST_ID)).not.toBeInTheDocument(); + expect(queryByTestId(NOTES_COUNT_TEST_ID)).not.toBeInTheDocument(); + expect(getByText(getEmptyValue())).toBeInTheDocument(); + }); + it('should render toast error', () => { const store = createMockStore({ ...mockGlobalState, diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/notes.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/notes.tsx index a981a16117a68..b0e2008c04103 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/notes.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/notes.tsx @@ -19,6 +19,7 @@ import { } from '@elastic/eui'; import { css } from '@emotion/react'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { getEmptyTagValue } from '../../../../common/components/empty_value'; import { DocumentDetailsLeftPanelKey } from '../../shared/constants/panel_keys'; import { FormattedCount } from '../../../../common/components/formatted_number'; import { useDocumentDetailsContext } from '../../shared/context'; @@ -61,7 +62,7 @@ export const ADD_NOTE_BUTTON = i18n.translate( export const Notes = memo(() => { const { euiTheme } = useEuiTheme(); const dispatch = useDispatch(); - const { eventId, indexName, scopeId } = useDocumentDetailsContext(); + const { eventId, indexName, scopeId, isPreview, isPreviewMode } = useDocumentDetailsContext(); const { addError: addErrorToast } = useAppToasts(); const { openLeftPanel } = useExpandableFlyoutApi(); @@ -80,8 +81,11 @@ export const Notes = memo(() => { ); useEffect(() => { - dispatch(fetchNotesByDocumentIds({ documentIds: [eventId] })); - }, [dispatch, eventId]); + // only fetch notes if we are not in a preview panel, or not in a rule preview workflow + if (!isPreviewMode && !isPreview) { + dispatch(fetchNotesByDocumentIds({ documentIds: [eventId] })); + } + }, [dispatch, eventId, isPreview, isPreviewMode]); const fetchStatus = useSelector((state: State) => selectFetchNotesByDocumentIdsStatus(state)); const fetchError = useSelector((state: State) => selectFetchNotesByDocumentIdsError(state)); @@ -107,37 +111,45 @@ export const Notes = memo(() => { } data-test-subj={NOTES_TITLE_TEST_ID} > - {fetchStatus === ReqStatus.Loading ? ( - + {isPreview ? ( + getEmptyTagValue() ) : ( <> - {notes.length === 0 ? ( - - {ADD_NOTE_BUTTON} - + {fetchStatus === ReqStatus.Loading ? ( + ) : ( - - - - - - + {notes.length === 0 ? ( + - - + data-test-subj={NOTES_ADD_NOTE_BUTTON_TEST_ID} + > + {ADD_NOTE_BUTTON} + + ) : ( + + + + + + + + + )} + )} )}