From 8dc22e6926af9e78ab6a2dbd43b1b8c279ce7f03 Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Fri, 10 Feb 2023 16:22:55 +0100 Subject: [PATCH 1/4] tests: hover actions + event rendered view --- .../alert_table_hover_actions.cy.ts | 176 ++++++++++++++++++ .../event_rendered_view.cy.ts | 62 ++++++ .../cypress/screens/alerts.ts | 10 + .../cypress/screens/alerts_details.ts | 2 + .../cypress/screens/common/event_renderer.ts | 10 + .../cypress/screens/search_bar.ts | 5 + .../cypress/screens/shared.ts | 18 ++ .../cypress/screens/timeline.ts | 4 +- .../security_solution/cypress/tasks/alerts.ts | 12 ++ .../common/components/data_table/index.tsx | 7 +- .../events_viewer/right_top_menu.tsx | 6 +- .../summary_view_select/index.tsx | 3 + .../timeline/body/renderers/user_name.tsx | 2 +- 13 files changed, 313 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_hover_actions.cy.ts create mode 100644 x-pack/plugins/security_solution/cypress/e2e/detection_alerts/event_rendered_view.cy.ts create mode 100644 x-pack/plugins/security_solution/cypress/screens/common/event_renderer.ts diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_hover_actions.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_hover_actions.cy.ts new file mode 100644 index 0000000000000..2fd099759471a --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_hover_actions.cy.ts @@ -0,0 +1,176 @@ +/* + * 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 { getNewRule } from '../../objects/rule'; +import { HOST_NAME, USER_NAME } from '../../screens/alerts'; +import { + ALERT_FLYOUT, + ALERT_FLYOUT_CLOSE_BTN, + CELL_EXPAND_VALUE, + CELL_EXPANSION_POPOVER, +} from '../../screens/alerts_details'; +import { + GLOBAL_SEARCH_BAR_FILTER_ITEM, + GLOBAL_SEARCH_BAR_FILTER_ITEM_DELETE, +} from '../../screens/search_bar'; +import { + ID_COLUMN_HEADER, + ID_COLUMN_NAME, + ID_COLUMN_VALUES, + TOP_N_ALERT_HISTOGRAM, + TOP_N_CONTAINER_CLOSE_BTN, +} from '../../screens/shared'; +import { HOVER_ACTIONS, TIMELINE_DATA_PROVIDERS_CONTAINER } from '../../screens/timeline'; +import { waitForAlerts, waitForTopNHistogramToLoad } from '../../tasks/alerts'; +import { createCustomRuleEnabled } from '../../tasks/api_calls/rules'; +import { cleanKibana } from '../../tasks/common'; +import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; +import { login, visit } from '../../tasks/login'; +import { addsFieldsToTimeline } from '../../tasks/rule_details'; +import { closeTimelineUsingCloseButton } from '../../tasks/security_main'; +import { openActiveTimeline } from '../../tasks/timeline'; +import { ALERTS_URL } from '../../urls/navigation'; + +describe('Alerts Table : Hover Actions', () => { + before(() => { + cleanKibana(); + login(); + createCustomRuleEnabled(getNewRule(), 'new custom rule'); + }); + + context('Id Column', { testIsolation: false }, () => { + before(() => { + visit(ALERTS_URL); + waitForAlertsToPopulate(); + addsFieldsToTimeline(ID_COLUMN_NAME, [ID_COLUMN_NAME]); + cy.get(ID_COLUMN_HEADER).should('be.visible'); + }); + beforeEach(() => { + /* + * + * Since now alert table is different from the tables being used + * in events, we have to create different set of tests for hover actions + * for alerts table. + * + * These tests will be done on `_id` column since there can be difference + * in how `_id` is supplied to the security solution by trigger actions table + * + * */ + waitForAlerts(); + cy.get(ID_COLUMN_VALUES).first().trigger('mouseover', { timeout: 5000 }); + }); + + it('Filter For', () => { + cy.get(ID_COLUMN_VALUES) + .eq(0) + .then(($el) => { + const idTextValue = $el.text(); + cy.get(HOVER_ACTIONS.FILTER_FOR).should('exist'); + cy.get(HOVER_ACTIONS.FILTER_FOR).trigger('click', { force: true }); + cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM).should('contain.text', `_id: ${idTextValue}`); + cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM_DELETE).trigger('click'); + cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM).should('not.exist'); + }); + }); + + it('Filter Out', () => { + cy.get(ID_COLUMN_VALUES) + .eq(0) + .then(($el) => { + const idTextValue = $el.text(); + cy.get(HOVER_ACTIONS.FILTER_OUT).should('exist'); + cy.get(HOVER_ACTIONS.FILTER_OUT).trigger('click', { force: true }); + cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM).should('contain.text', `NOT _id: ${idTextValue}`); + cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM_DELETE).trigger('click'); + cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM).should('not.exist'); + }); + }); + + it('Add To Timeline', () => { + cy.get(ID_COLUMN_VALUES) + .eq(0) + .then(($el) => { + const idTextValue = $el.text(); + cy.get(HOVER_ACTIONS.ADD_TO_TIMELINE).should('exist'); + cy.get(HOVER_ACTIONS.ADD_TO_TIMELINE).trigger('click', { force: true }); + openActiveTimeline(); + cy.get(TIMELINE_DATA_PROVIDERS_CONTAINER).should('be.visible'); + cy.get(TIMELINE_DATA_PROVIDERS_CONTAINER).should('contain.text', idTextValue); + closeTimelineUsingCloseButton(); + }); + }); + }); + + context('Host Column', { testIsolation: false }, () => { + before(() => { + visit(ALERTS_URL); + waitForAlerts(); + }); + beforeEach(() => { + cy.get(HOST_NAME).first().trigger('mouseover', { timeout: 5000 }); + // we want to trigger second set of hover actions on host column + // first is on _id column + cy.get(CELL_EXPAND_VALUE).first().should('exist'); + cy.get(CELL_EXPAND_VALUE).first().trigger('click', { force: true }); + cy.get(CELL_EXPANSION_POPOVER).should('be.visible'); + }); + + it('TopN', () => { + cy.get(HOVER_ACTIONS.SHOW_TOP).should('be.visible').trigger('click'); + waitForTopNHistogramToLoad(); + cy.get(TOP_N_ALERT_HISTOGRAM).should('be.visible'); + cy.get(TOP_N_CONTAINER_CLOSE_BTN).trigger('click', { force: true }); + cy.get(TOP_N_ALERT_HISTOGRAM).should('not.exist'); + // close the expanded popover + cy.get(CELL_EXPAND_VALUE).first().click({ force: true }); + }); + + it('Host Summary', () => { + cy.get(HOVER_ACTIONS.VIEW_HOST_SUMMARY).should('be.visible').trigger('click'); + cy.get(ALERT_FLYOUT).should('exist'); + /* + * + * Currently hover actions popover does not close automatically when clicked + * on an action when using cypress + * + * */ + cy.get(ALERT_FLYOUT).trigger('click'); + cy.get(ALERT_FLYOUT_CLOSE_BTN).trigger('click'); + cy.get(ALERT_FLYOUT).should('not.exist'); + }); + }); + + context('User Column', { testIsolation: false }, () => { + before(() => { + visit(ALERTS_URL); + waitForAlerts(); + }); + beforeEach(() => { + cy.get('.euiDataGrid__virtualized').scrollTo('right'); + cy.get(USER_NAME).first().trigger('mouseover', { timeout: 5000 }); + // we want to trigger second set of hover actions on host column + // first is on _id column + cy.get(CELL_EXPAND_VALUE).first().should('exist'); + cy.get(CELL_EXPAND_VALUE).first().trigger('click', { force: true }); + cy.get(CELL_EXPANSION_POPOVER).should('be.visible'); + }); + + it('User Summary', () => { + cy.get(HOVER_ACTIONS.VIEW_USER_SUMMARY).should('be.visible').trigger('click'); + cy.get(ALERT_FLYOUT).should('exist'); + /* + * + * Currently hover actions popover does not close automatically when clicked + * on an action when using cypress + * + * */ + cy.get(ALERT_FLYOUT).trigger('click'); + cy.get(ALERT_FLYOUT_CLOSE_BTN).trigger('click'); + cy.get(ALERT_FLYOUT).should('not.exist'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/event_rendered_view.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/event_rendered_view.cy.ts new file mode 100644 index 0000000000000..5258f216e8fcf --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/event_rendered_view.cy.ts @@ -0,0 +1,62 @@ +/* + * 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 { getNewRule } from '../../objects/rule'; +import { EVENT_SUMMARY_ALERT_RENDERER_CONTENT, EVENT_SUMMARY_COLUMN } from '../../screens/alerts'; +import { ALERT_RENDERER_HOST_NAME } from '../../screens/common/event_renderer'; +import { FIELDS_BROWSER_VIEW_BUTTON } from '../../screens/fields_browser'; +import { + DATA_GRID_COLUMN_ORDER_BTN, + DATA_GRID_FIELD_SORT_BTN, + TOP_N_ALERT_HISTOGRAM, + TOP_N_CONTAINER_CLOSE_BTN, +} from '../../screens/shared'; +import { HOVER_ACTIONS } from '../../screens/timeline'; +import { + switchAlertTableToEventRenderedView, + waitForAlerts, + waitForTopNHistogramToLoad, +} from '../../tasks/alerts'; +import { createCustomRuleEnabled } from '../../tasks/api_calls/rules'; +import { cleanKibana } from '../../tasks/common'; +import { login, visit } from '../../tasks/login'; +import { ALERTS_URL } from '../../urls/navigation'; + +describe('Test Event Rendered View', { testIsolation: false }, () => { + before(() => { + cleanKibana(); + login(); + createCustomRuleEnabled(getNewRule(), 'new custom rule'); + visit(ALERTS_URL); + waitForAlerts(); + switchAlertTableToEventRenderedView(); + }); + + it('Field Browser is not visible', () => { + cy.get(FIELDS_BROWSER_VIEW_BUTTON).should('not.exist'); + }); + + it('Sorting control is not visible', () => { + cy.get(DATA_GRID_FIELD_SORT_BTN).should('not.be.visible'); + }); + + it('Column Order button is not visible', () => { + cy.get(DATA_GRID_COLUMN_ORDER_BTN).should('not.exist'); + }); + + it('Event Summary Column + Hover Actions', () => { + cy.get(EVENT_SUMMARY_COLUMN).should('be.visible'); + cy.get(EVENT_SUMMARY_ALERT_RENDERER_CONTENT).should('be.visible'); + + cy.get(ALERT_RENDERER_HOST_NAME).first().trigger('mouseover'); + + cy.get(HOVER_ACTIONS.SHOW_TOP).trigger('click'); + waitForTopNHistogramToLoad(); + cy.get(TOP_N_ALERT_HISTOGRAM).should('be.visible'); + cy.get(TOP_N_CONTAINER_CLOSE_BTN).trigger('click'); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index 046962a5d9685..85bacac8e6ad7 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -134,3 +134,13 @@ export const EVENT_CONTAINER_TABLE_LOADING = '[data-test-subj="events-container- export const EVENT_CONTAINER_TABLE_NOT_LOADING = '[data-test-subj="events-container-loading-false"]'; + +export const ALERT_TABLE_SUMMARY_VIEW_SELECTABLE = '[data-test-subj="summary-view-selector"]'; + +export const ALERT_TABLE_GRID_VIEW_OPTION = '[data-test-subj="gridView"]'; + +export const EVENT_SUMMARY_COLUMN = '[data-gridcell-column-id="eventSummary"]'; + +export const EVENT_SUMMARY_ALERT_RENDERER_CONTENT = '[data-test-subj="alertRenderer"]'; + +export const ALERT_TABLE_EVENT_RENDERED_VIEW_OPTION = '[data-test-subj="eventRenderedView"]'; 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 9a1ac0b8d08f1..7bf2546c1fdea 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts @@ -7,6 +7,8 @@ export const ALERT_FLYOUT = '[data-test-subj="timeline:details-panel:flyout"]'; +export const ALERT_FLYOUT_CLOSE_BTN = `${ALERT_FLYOUT} [data-test-subj="euiFlyoutCloseButton"]`; + export const CELL_TEXT = '.euiText'; export const ENRICHMENT_COUNT_NOTIFICATION = '[data-test-subj="enrichment-count-notification"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/common/event_renderer.ts b/x-pack/plugins/security_solution/cypress/screens/common/event_renderer.ts new file mode 100644 index 0000000000000..80030224c5246 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/screens/common/event_renderer.ts @@ -0,0 +1,10 @@ +/* + * 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 const ALERT_RENDERER_CONTENT = '[data-test-subj="alertRenderer"]'; + +export const ALERT_RENDERER_HOST_NAME = '[data-test-subj="render-content-host.name"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/search_bar.ts b/x-pack/plugins/security_solution/cypress/screens/search_bar.ts index a9e69625c2da9..0c7acee520050 100644 --- a/x-pack/plugins/security_solution/cypress/screens/search_bar.ts +++ b/x-pack/plugins/security_solution/cypress/screens/search_bar.ts @@ -29,8 +29,13 @@ export const ADD_FILTER_FORM_SAVE_BUTTON = '[data-test-subj="saveFilter"]'; export const GLOBAL_SEARCH_BAR_FILTER_ITEM = '#popoverFor_filter0'; +export const GLOBAL_SEARCH_BAR_FILTER_ITEM_DELETE = '#popoverFor_filter0 button[title^="Delete"]'; + export const GLOBAL_SEARCH_BAR_FILTER_ITEM_AT = (value: number) => `#popoverFor_filter${value}`; +export const GLOBAL_SEARCH_BAR_FILTER_ITEM_DELETE_BTN_AT = (value: number) => + `#popoverFor_filter${value} button[title^="Delete"]`; + export const GLOBAL_SEARCH_BAR_PINNED_FILTER = '.globalFilterItem-isPinned'; export const GLOBAL_KQL_INPUT = diff --git a/x-pack/plugins/security_solution/cypress/screens/shared.ts b/x-pack/plugins/security_solution/cypress/screens/shared.ts index 8a7ba48b1415d..4cc5e9f729d0e 100644 --- a/x-pack/plugins/security_solution/cypress/screens/shared.ts +++ b/x-pack/plugins/security_solution/cypress/screens/shared.ts @@ -6,3 +6,21 @@ */ export const TOAST_ERROR = '.euiToast--danger'; + +export const TOP_N_ALERT_HISTOGRAM = + '[data-test-subj="topN-container"] [data-test-subj="alerts-histogram-panel"]'; + +export const TOP_N_CONTAINER = '[data-test-subj="topN-container"]'; + +export const TOP_N_CONTAINER_CLOSE_BTN = + '[data-test-subj="topN-container"] [data-test-subj="close"]'; + +export const ID_COLUMN_VALUES = '[data-test-subj="formatted-field-_id"]'; + +export const ID_COLUMN_HEADER = '[data-gridcell-column-id="_id"]'; + +export const ID_COLUMN_NAME = '_id'; + +export const DATA_GRID_FIELD_SORT_BTN = '[data-test-subj="dataGridColumnSortingButton"]'; + +export const DATA_GRID_COLUMN_ORDER_BTN = '[data-test-subj="dataGridColumnSelectorButton"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/timeline.ts b/x-pack/plugins/security_solution/cypress/screens/timeline.ts index ca938164fb2a6..f04cc44626786 100644 --- a/x-pack/plugins/security_solution/cypress/screens/timeline.ts +++ b/x-pack/plugins/security_solution/cypress/screens/timeline.ts @@ -313,5 +313,7 @@ export const HOVER_ACTIONS = { FILTER_FOR: '[data-test-subj="filter-for-value"]', FILTER_OUT: '[data-test-subj="filter-out-value"]', COPY: '[data-test-subj="clipboard"]', - SHOW_TOP: 'show-top-field', + SHOW_TOP: '[data-test-subj="show-top-field"]', + VIEW_HOST_SUMMARY: '[data-test-subj="data-grid-host-details"]', + VIEW_USER_SUMMARY: '[data-test-subj="data-grid-user-details"]', }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts index c7810db6ae21d..d463535116ced 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts @@ -32,6 +32,8 @@ import { CLOSED_ALERTS_FILTER_BTN, OPENED_ALERTS_FILTER_BTN, ACKNOWLEDGED_ALERTS_FILTER_BTN, + ALERT_TABLE_SUMMARY_VIEW_SELECTABLE, + ALERT_TABLE_EVENT_RENDERED_VIEW_OPTION, } from '../screens/alerts'; import { LOADING_INDICATOR, REFRESH_BUTTON } from '../screens/security_header'; import { @@ -326,6 +328,11 @@ export const waitForAlertsPanelToBeLoaded = () => { cy.get(ALERTS_HISTOGRAM_PANEL_LOADER).should('not.exist'); }; +export const waitForTopNHistogramToLoad = () => { + cy.get(ALERTS_HISTOGRAM_PANEL_LOADER).should('exist'); + cy.get(ALERTS_HISTOGRAM_PANEL_LOADER).should('not.exist'); +}; + export const expandAlertTableCellValue = (columnSelector: string, row = 1) => { cy.get(columnSelector).eq(1).focus().find(CELL_EXPAND_VALUE).click({ force: true }); }; @@ -372,3 +379,8 @@ export const resetFilters = () => { * * */ }; + +export const switchAlertTableToEventRenderedView = () => { + cy.get(ALERT_TABLE_SUMMARY_VIEW_SELECTABLE).should('be.visible').trigger('click'); + cy.get(ALERT_TABLE_EVENT_RENDERED_VIEW_OPTION).should('be.visible').trigger('click'); +}; diff --git a/x-pack/plugins/security_solution/public/common/components/data_table/index.tsx b/x-pack/plugins/security_solution/public/common/components/data_table/index.tsx index 85189cd221b2f..b07009223569b 100644 --- a/x-pack/plugins/security_solution/public/common/components/data_table/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/data_table/index.tsx @@ -309,6 +309,10 @@ export const DataTableComponent = React.memo( [dispatch, id] ); + const closeCellPopover = useCallback(() => { + dataGridRef.current?.closeCellPopover(); + }, []); + const columnsWithCellActions: EuiDataGridColumn[] = useMemo( () => columnHeaders.map((header) => { @@ -320,7 +324,7 @@ export const DataTableComponent = React.memo( header: columnHeaders.find((h) => h.id === header.id), pageSize: pagination.pageSize, scopeId: id, - closeCellPopover: dataGridRef.current?.closeCellPopover, + closeCellPopover, }); return { ...header, @@ -359,6 +363,7 @@ export const DataTableComponent = React.memo( dispatch, id, pagination.pageSize, + closeCellPopover, ] ); diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/right_top_menu.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/right_top_menu.tsx index 8294cc78d77ce..d990a1f3b787c 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/right_top_menu.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/right_top_menu.tsx @@ -75,7 +75,11 @@ export const RightTopMenu = ({ {tGridEventRenderedViewEnabled && [TableId.alertsOnRuleDetailsPage, TableId.alertsOnAlertsPage].includes(tableId) && ( - + )} {menuOptions} diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/summary_view_select/index.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/summary_view_select/index.tsx index cdd391900ba86..c63547bb2c340 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/summary_view_select/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/summary_view_select/index.tsx @@ -83,6 +83,7 @@ const SummaryViewSelectorComponent = ({ viewSelected, onViewChange }: SummaryVie { label: gridView, key: 'gridView', + 'data-test-subj': 'gridView', checked: (viewSelected === 'gridView' ? 'on' : undefined) as EuiSelectableOption['checked'], meta: [ { @@ -99,6 +100,7 @@ const SummaryViewSelectorComponent = ({ viewSelected, onViewChange }: SummaryVie { label: eventRenderedView, key: 'eventRenderedView', + 'data-test-subj': 'eventRenderedView', checked: (viewSelected === 'eventRenderedView' ? 'on' : undefined) as EuiSelectableOption['checked'], @@ -140,6 +142,7 @@ const SummaryViewSelectorComponent = ({ viewSelected, onViewChange }: SummaryVie return ( = ({ const openUserDetailsSidePanel = useCallback( (e) => { e.preventDefault(); - if (onClick) { + // closing popover onClick(); } if (eventContext && isInTimelineContext) { From a87f75f41c16d19d74b6d0b262537bd463c4d00f Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Mon, 13 Feb 2023 15:55:49 +0100 Subject: [PATCH 2/4] Additional Controls + Table controls --- .../alert_table_controls.cy.ts | 66 +++++++++++++++++ .../alert_table_hover_actions.cy.ts | 5 +- .../alerts_table_threat_indicator.cy.ts | 72 +++++++++++++++++++ .../cypress/screens/alerts.ts | 8 +++ .../cypress/screens/shared.ts | 42 ++++++++++- 5 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_controls.cy.ts create mode 100644 x-pack/plugins/security_solution/cypress/e2e/detection_rules/alerts_table_threat_indicator.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_controls.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_controls.cy.ts new file mode 100644 index 0000000000000..57a68cb2f04be --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_controls.cy.ts @@ -0,0 +1,66 @@ +/* + * 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 { getNewRule } from '../../objects/rule'; +import { + DATA_GRID_FIELDS, + DATA_GRID_FULL_SCREEN, + GET_DATA_GRID_HEADER, + GET_DATA_GRID_HEADER_CELL_ACTION_GROUP, +} from '../../screens/shared'; +import { createCustomRuleEnabled } from '../../tasks/api_calls/rules'; +import { cleanKibana } from '../../tasks/common'; +import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; +import { login, visit } from '../../tasks/login'; +import { ALERTS_URL } from '../../urls/navigation'; + +describe('Alert Table Contorls', { testIsolation: false }, () => { + before(() => { + cleanKibana(); + login(); + createCustomRuleEnabled(getNewRule()); + visit(ALERTS_URL); + waitForAlertsToPopulate(); + }); + + it('full screen', () => { + cy.get(DATA_GRID_FULL_SCREEN) + .should('have.attr', 'aria-label', 'Enter fullscreen') + .trigger('click') + .should('have.attr', 'aria-label', 'Exit fullscreen') + .trigger('click'); + }); + + context('Sorting', { testIsolation: false }, () => { + it('Date Column', () => { + const timestampField = DATA_GRID_FIELDS.TIMESTAMP.fieldName; + cy.get(GET_DATA_GRID_HEADER(timestampField)).trigger('click'); + cy.get(GET_DATA_GRID_HEADER_CELL_ACTION_GROUP(timestampField)) + .should('be.visible') + .should('contain.text', 'Sort Old-New'); + cy.get(GET_DATA_GRID_HEADER(timestampField)).trigger('click'); + }); + + it('Number column', () => { + const riskScoreField = DATA_GRID_FIELDS.RISK_SCORE.fieldName; + cy.get(GET_DATA_GRID_HEADER(riskScoreField)).trigger('click'); + cy.get(GET_DATA_GRID_HEADER_CELL_ACTION_GROUP(riskScoreField)) + .should('be.visible') + .should('contain.text', 'Sort Low-High'); + cy.get(GET_DATA_GRID_HEADER(riskScoreField)).trigger('click'); + }); + + it('Text Column', () => { + const ruleField = DATA_GRID_FIELDS.RULE.fieldName; + cy.get(GET_DATA_GRID_HEADER(ruleField)).trigger('click'); + cy.get(GET_DATA_GRID_HEADER_CELL_ACTION_GROUP(ruleField)) + .should('be.visible') + .should('contain.text', 'Sort A-Z'); + cy.get(GET_DATA_GRID_HEADER(ruleField)).trigger('click'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_hover_actions.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_hover_actions.cy.ts index 2fd099759471a..1e9a9dc4bf573 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_hover_actions.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_hover_actions.cy.ts @@ -18,7 +18,8 @@ import { GLOBAL_SEARCH_BAR_FILTER_ITEM_DELETE, } from '../../screens/search_bar'; import { - ID_COLUMN_HEADER, + DATA_GRID_FIELDS, + GET_DATA_GRID_HEADER, ID_COLUMN_NAME, ID_COLUMN_VALUES, TOP_N_ALERT_HISTOGRAM, @@ -47,7 +48,7 @@ describe('Alerts Table : Hover Actions', () => { visit(ALERTS_URL); waitForAlertsToPopulate(); addsFieldsToTimeline(ID_COLUMN_NAME, [ID_COLUMN_NAME]); - cy.get(ID_COLUMN_HEADER).should('be.visible'); + cy.get(GET_DATA_GRID_HEADER(DATA_GRID_FIELDS.ID.fieldName)).should('be.visible'); }); beforeEach(() => { /* diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/alerts_table_threat_indicator.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/alerts_table_threat_indicator.cy.ts new file mode 100644 index 0000000000000..6309dff3b43b8 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/alerts_table_threat_indicator.cy.ts @@ -0,0 +1,72 @@ +/* + * 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 type { CustomRule } from '../../objects/rule'; +import { getNewThreatIndicatorRule } from '../../objects/rule'; +import { + ALERTS_COUNT, + ALERT_TABLE_ADDITIONAL_CONTROLS, + ALERT_TABLE_SHOW_THREAT_INDICATOR, +} from '../../screens/alerts'; +import { goToRuleDetails } from '../../tasks/alerts_detection_rules'; +import { cleanKibana } from '../../tasks/common'; +import { + createAndEnableRule, + fillAboutRuleAndContinue, + fillDefineIndicatorMatchRuleAndContinue, + fillScheduleRuleAndContinue, + selectIndicatorMatchType, + waitForAlertsToPopulate, +} from '../../tasks/create_new_rule'; +import { esArchiverLoad, esArchiverUnload } from '../../tasks/es_archiver'; +import { login, visit, visitWithoutDateRange } from '../../tasks/login'; +import { ALERTS_URL, RULE_CREATION } from '../../urls/navigation'; + +describe('Threat Indicator', () => { + before(() => { + cleanKibana(); + esArchiverLoad('threat_indicator'); + esArchiverLoad('suspicious_source_event'); + login(); + const rule = getNewThreatIndicatorRule(); + visitWithoutDateRange(RULE_CREATION); + selectIndicatorMatchType(); + fillDefineIndicatorMatchRuleAndContinue(rule); + fillAboutRuleAndContinue({ name: rule.name, description: rule.description } as CustomRule); + fillScheduleRuleAndContinue(rule); + createAndEnableRule(); + }); + + after(() => { + esArchiverUnload('threat_indicator'); + esArchiverUnload('suspicious_source_event'); + }); + + it('Rule Details Page', () => { + goToRuleDetails(); + waitForAlertsToPopulate(); + cy.get(ALERTS_COUNT).should('have.text', '1 alert'); + cy.get(ALERT_TABLE_ADDITIONAL_CONTROLS).trigger('click'); + cy.get(ALERT_TABLE_SHOW_THREAT_INDICATOR) + .pipe(($el) => $el.trigger('click')) + .should('be.checked'); + waitForAlertsToPopulate(); + cy.get(ALERTS_COUNT).should('have.text', '1 alert'); + }); + + it('Alert Page', () => { + visit(ALERTS_URL); + waitForAlertsToPopulate(); + cy.get(ALERTS_COUNT).should('have.text', '1 alert'); + cy.get(ALERT_TABLE_ADDITIONAL_CONTROLS).trigger('click'); + cy.get(ALERT_TABLE_SHOW_THREAT_INDICATOR) + .pipe(($el) => $el.trigger('click')) + .should('be.checked'); + waitForAlertsToPopulate(); + cy.get(ALERTS_COUNT).should('have.text', '1 alert'); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index 85bacac8e6ad7..c1136dfaa9662 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -144,3 +144,11 @@ export const EVENT_SUMMARY_COLUMN = '[data-gridcell-column-id="eventSummary"]'; export const EVENT_SUMMARY_ALERT_RENDERER_CONTENT = '[data-test-subj="alertRenderer"]'; export const ALERT_TABLE_EVENT_RENDERED_VIEW_OPTION = '[data-test-subj="eventRenderedView"]'; + +export const ALERT_TABLE_ADDITIONAL_CONTROLS = '[data-test-subj="additionalFilters-popover"]'; + +export const ALERT_TABLE_SHOW_BUILDING_BLOCK_TOGGLE = + '[data-test-subj="showBuildingBlockAlertsCheckbox"]'; + +export const ALERT_TABLE_SHOW_THREAT_INDICATOR = + '[data-test-subj="showOnlyThreatIndicatorAlertsCheckbox"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/shared.ts b/x-pack/plugins/security_solution/cypress/screens/shared.ts index 4cc5e9f729d0e..4d673bb238fdd 100644 --- a/x-pack/plugins/security_solution/cypress/screens/shared.ts +++ b/x-pack/plugins/security_solution/cypress/screens/shared.ts @@ -17,10 +17,50 @@ export const TOP_N_CONTAINER_CLOSE_BTN = export const ID_COLUMN_VALUES = '[data-test-subj="formatted-field-_id"]'; -export const ID_COLUMN_HEADER = '[data-gridcell-column-id="_id"]'; +export const GET_DATA_GRID_HEADER = (fieldName: string) => { + return `[data-test-subj="dataGridHeaderCell-${fieldName}"]`; +}; + +export const DATA_GRID_FIELDS = { + TIMESTAMP: { + fieldName: '@timestamp', + label: '@timestamp', + }, + ID: { + fieldName: '_id', + label: '_id', + }, + RISK_SCORE: { + fieldName: 'kibana.alert.risk_score', + label: 'Risk Score', + }, + + RULE: { + fieldName: 'kibana.alert.rule.name', + label: 'Rule', + }, +}; + +export const GET_DATA_GRID_HEADER_CELL_ACTION_GROUP = (fieldName: string) => { + return `[data-test-subj="dataGridHeaderCellActionGroup-${fieldName}"]`; +}; + +export const DATA_GRID_FULL_SCREEN = '[data-test-subj="dataGridFullScreenButton"]'; + +export const DATA_GRID_HEADERS = { + ID: '[data-gridcell-column-id="_id"]', + TIMESTAMP: '[data-test-subj="dataGridHeaderCell-@timestamp"]', +}; export const ID_COLUMN_NAME = '_id'; export const DATA_GRID_FIELD_SORT_BTN = '[data-test-subj="dataGridColumnSortingButton"]'; export const DATA_GRID_COLUMN_ORDER_BTN = '[data-test-subj="dataGridColumnSelectorButton"]'; + +export const DATA_GRID_COLUMNS = '.euiDataGridHeaderCell__content'; + +export const COLUMN_ORDER_POPUP = { + TIMESTAMP: '[data-test-subj="dataGridColumnSelectorColumnItem-@timestamp"]', + REASON: '[data-test-subj="dataGridColumnSelectorColumnItem-kibana.alert.reason"]', +}; From d5e66327c47970f43fea214efa9c15bce2894a6a Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Mon, 13 Feb 2023 16:00:59 +0100 Subject: [PATCH 3/4] more table controls --- .../e2e/detection_alerts/alert_table_controls.cy.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_controls.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_controls.cy.ts index 57a68cb2f04be..007019c24d156 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_controls.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_controls.cy.ts @@ -6,7 +6,9 @@ */ import { getNewRule } from '../../objects/rule'; +import { FIELDS_BROWSER_BTN } from '../../screens/rule_details'; import { + DATA_GRID_COLUMN_ORDER_BTN, DATA_GRID_FIELDS, DATA_GRID_FULL_SCREEN, GET_DATA_GRID_HEADER, @@ -35,7 +37,15 @@ describe('Alert Table Contorls', { testIsolation: false }, () => { .trigger('click'); }); - context('Sorting', { testIsolation: false }, () => { + it('column sorting control exists', () => { + cy.get(DATA_GRID_COLUMN_ORDER_BTN).should('be.visible'); + }); + + it('field Browser Exists', () => { + cy.get(FIELDS_BROWSER_BTN).should('be.visible'); + }); + + context('Sorting', () => { it('Date Column', () => { const timestampField = DATA_GRID_FIELDS.TIMESTAMP.fieldName; cy.get(GET_DATA_GRID_HEADER(timestampField)).trigger('click'); From e42be916f0f2a78a01da3cb975ab2db7951bfcd6 Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Mon, 13 Feb 2023 16:34:14 +0100 Subject: [PATCH 4/4] Remove unncessary vars --- .../e2e/detection_alerts/alert_table_hover_actions.cy.ts | 4 ++-- x-pack/plugins/security_solution/cypress/screens/shared.ts | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_hover_actions.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_hover_actions.cy.ts index 1e9a9dc4bf573..0ab0d03aa4827 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_hover_actions.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_table_hover_actions.cy.ts @@ -20,7 +20,6 @@ import { import { DATA_GRID_FIELDS, GET_DATA_GRID_HEADER, - ID_COLUMN_NAME, ID_COLUMN_VALUES, TOP_N_ALERT_HISTOGRAM, TOP_N_CONTAINER_CLOSE_BTN, @@ -47,7 +46,8 @@ describe('Alerts Table : Hover Actions', () => { before(() => { visit(ALERTS_URL); waitForAlertsToPopulate(); - addsFieldsToTimeline(ID_COLUMN_NAME, [ID_COLUMN_NAME]); + const idColName = DATA_GRID_FIELDS.ID.fieldName; + addsFieldsToTimeline(idColName, [idColName]); cy.get(GET_DATA_GRID_HEADER(DATA_GRID_FIELDS.ID.fieldName)).should('be.visible'); }); beforeEach(() => { diff --git a/x-pack/plugins/security_solution/cypress/screens/shared.ts b/x-pack/plugins/security_solution/cypress/screens/shared.ts index 4d673bb238fdd..483aac42c7a85 100644 --- a/x-pack/plugins/security_solution/cypress/screens/shared.ts +++ b/x-pack/plugins/security_solution/cypress/screens/shared.ts @@ -47,13 +47,6 @@ export const GET_DATA_GRID_HEADER_CELL_ACTION_GROUP = (fieldName: string) => { export const DATA_GRID_FULL_SCREEN = '[data-test-subj="dataGridFullScreenButton"]'; -export const DATA_GRID_HEADERS = { - ID: '[data-gridcell-column-id="_id"]', - TIMESTAMP: '[data-test-subj="dataGridHeaderCell-@timestamp"]', -}; - -export const ID_COLUMN_NAME = '_id'; - export const DATA_GRID_FIELD_SORT_BTN = '[data-test-subj="dataGridColumnSortingButton"]'; export const DATA_GRID_COLUMN_ORDER_BTN = '[data-test-subj="dataGridColumnSelectorButton"]';