diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_details.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_details.cy.ts index ffc2aa727153b..68a3a9a6fbe81 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_details.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_details.cy.ts @@ -16,19 +16,41 @@ import { TABLE_ROWS, } from '../../screens/alerts_details'; import { closeAlertFlyout, expandFirstAlert } from '../../tasks/alerts'; -import { filterBy, openJsonView, openTable } from '../../tasks/alerts_details'; +import { changeAlertStatusTo, filterBy, openJsonView, openTable } from '../../tasks/alerts_details'; import { createRule } from '../../tasks/api_calls/rules'; import { cleanKibana } from '../../tasks/common'; import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; import { esArchiverLoad, esArchiverUnload } from '../../tasks/es_archiver'; import { login, visit, visitWithoutDateRange } from '../../tasks/login'; -import { getUnmappedRule } from '../../objects/rule'; +import { getNewRule, getUnmappedRule } from '../../objects/rule'; import { ALERTS_URL } from '../../urls/navigation'; import { tablePageSelector } from '../../screens/table_pagination'; +import { ALERTS_TABLE_COUNT } from '../../screens/timeline'; +import { ALERT_SUMMARY_SEVERITY_DONUT_CHART } from '../../screens/alerts'; import { getLocalstorageEntryAsObject } from '../../helpers/common'; import { goToRuleDetails } from '../../tasks/alerts_detection_rules'; describe('Alert details flyout', () => { + describe('Basic functions', () => { + before(() => { + cleanKibana(); + login(); + createRule(getNewRule()); + visitWithoutDateRange(ALERTS_URL); + waitForAlertsToPopulate(); + expandFirstAlert(); + }); + + it('should update the table when status of the alert is updated', () => { + cy.get(ALERTS_TABLE_COUNT).should('have.text', '2 alerts'); + cy.get(ALERT_SUMMARY_SEVERITY_DONUT_CHART).should('contain.text', '2alerts'); + expandFirstAlert(); + changeAlertStatusTo('acknowledged'); + cy.get(ALERTS_TABLE_COUNT).should('have.text', '1 alert'); + cy.get(ALERT_SUMMARY_SEVERITY_DONUT_CHART).should('contain.text', '1alert'); + }); + }); + describe('With unmapped fields', { testIsolation: false }, () => { before(() => { cleanKibana(); diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index 6f4ded4fef9bc..8c8d93f3444f3 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { getDataTestSubjectSelector } from '../helpers/common'; + export const ADD_EXCEPTION_BTN = '[data-test-subj="add-exception-menu-item"]'; export const ADD_ENDPOINT_EXCEPTION_BTN = '[data-test-subj="add-endpoint-exception-menu-item"]'; @@ -177,3 +179,6 @@ export const SESSION_VIEWER_BUTTON = '[data-test-subj="session-view-button"]'; export const OVERLAY_CONTAINER = '[data-test-subj="overlayContainer"]'; export const CLOSE_OVERLAY = '[data-test-subj="close-overlay"]'; + +export const ALERT_SUMMARY_SEVERITY_DONUT_CHART = + getDataTestSubjectSelector('severity-level-donut'); diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts index c3a092c63a949..b4eaaeda35e5d 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts @@ -42,6 +42,9 @@ export const OVERVIEW_SEVERITY = '[data-test-subj="eventDetails"] [data-test-sub export const OVERVIEW_STATUS = '[data-test-subj="eventDetails"] [data-test-subj="alertStatus"]'; +export const EVENT_DETAILS_ALERT_STATUS_POPOVER = + '[data-test-subj="event-details-alertStatusPopover"]'; + const SUMMARY_VIEW = '[data-test-subj="summary-view"]'; export const TABLE_CELL = '.euiTableRowCell'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts_details.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts_details.ts index b5bff14fd5492..6623f01215a66 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts_details.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts_details.ts @@ -5,12 +5,15 @@ * 2.0. */ +import { CLOSE_ALERT_BTN, MARK_ALERT_ACKNOWLEDGED_BTN, OPEN_ALERT_BTN } from '../screens/alerts'; import { ALERT_FLYOUT, ENRICHMENT_COUNT_NOTIFICATION, JSON_VIEW_TAB, TABLE_TAB, FILTER_INPUT, + OVERVIEW_STATUS, + EVENT_DETAILS_ALERT_STATUS_POPOVER, } from '../screens/alerts_details'; import { TIMELINE_TITLE, QUERY_TAB_BUTTON } from '../screens/timeline'; @@ -61,3 +64,20 @@ export const verifyInsightCount = ({ cy.get(QUERY_TAB_BUTTON).should('contain.text', actualCount); }); }; + +export const changeAlertStatusTo = (status: 'open' | 'closed' | 'acknowledged') => { + cy.get(OVERVIEW_STATUS).trigger('click'); + cy.get(EVENT_DETAILS_ALERT_STATUS_POPOVER).should('be.visible'); + + if (status === 'acknowledged') { + cy.get(MARK_ALERT_ACKNOWLEDGED_BTN).should('be.visible').trigger('click'); + return; + } + if (status === 'open') { + cy.get(OPEN_ALERT_BTN).should('be.visible').trigger('click'); + } + + if (status === 'closed') { + cy.get(CLOSE_ALERT_BTN).should('be.visible').trigger('click'); + } +}; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/overview/status_popover_button.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/overview/status_popover_button.tsx index f026138c8a779..c0da50cad6e75 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/overview/status_popover_button.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/overview/status_popover_button.tsx @@ -16,6 +16,9 @@ import { } from '../../../../detections/components/alerts_table/translations'; import { FormattedFieldValue } from '../../../../timelines/components/timeline/body/renderers/formatted_field'; import type { EnrichedFieldInfoWithValues } from '../types'; +import type { inputsModel } from '../../../store'; +import { inputsSelectors } from '../../../store'; +import { useDeepEqualSelector } from '../../../hooks/use_selector'; interface StatusPopoverButtonProps { eventId: string; @@ -36,12 +39,21 @@ export const StatusPopoverButton = React.memo( handleOnEventClosed(); }, [closePopover, handleOnEventClosed]); + const getGlobalQuerySelector = useMemo(() => inputsSelectors.globalQuery(), []); + + const globalQueries = useDeepEqualSelector(getGlobalQuerySelector); + + const refetchGlobalQuery = useCallback(() => { + globalQueries.forEach((q) => q.refetch && (q.refetch as inputsModel.Refetch)()); + }, [globalQueries]); + const { actionItems } = useAlertsActions({ closePopover: closeAfterAction, eventId, scopeId, indexName, alertStatus: enrichedFieldInfo.values[0] as Status, + refetch: refetchGlobalQuery, }); // statusPopoverVisible includes the logic for the visibility of the popover in @@ -82,7 +94,10 @@ export const StatusPopoverButton = React.memo( data-test-subj="alertStatus" > {CHANGE_ALERT_STATUS} - + ); }