From 5bd8ff528c37aa77e099d8ecc224a1f7468412b5 Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Fri, 25 Oct 2024 19:14:49 +0200 Subject: [PATCH] [Security Solution] Unskips Timeline Cypress tests (#195721) ## Summary Fixes below Flaky tests issues : - [x] https://github.com/elastic/kibana/issues/180688 - [x] https://github.com/elastic/kibana/issues/176945 - [x] https://github.com/elastic/kibana/issues/175180 - [x] https://github.com/elastic/kibana/issues/181466 - [x] https://github.com/elastic/kibana/issues/182021 - [x] https://github.com/elastic/kibana/issues/183085 - [x] https://github.com/elastic/kibana/issues/175180 --------- Co-authored-by: Michael Olorunnisola --- .../alerts/event_rendered_view.cy.ts | 12 ++-- .../investigations/timelines/creation.cy.ts | 37 +---------- .../timelines/data_providers.cy.ts | 26 +++----- .../discover_timeline_state_integration.cy.ts | 13 ++-- .../timelines/esql/esql_state.cy.ts | 38 +++++++---- .../timelines/esql/search_filter.cy.ts | 17 +++-- .../e2e/investigations/timelines/export.cy.ts | 8 ++- .../timelines/flyout_button.cy.ts | 17 +---- .../timelines/row_renderers.cy.ts | 24 +++++-- .../timelines/timelines_table.cy.ts | 5 +- .../cypress/screens/alerts.ts | 8 +++ .../cypress/screens/discover.ts | 8 ++- .../cypress/screens/timeline.ts | 21 ++++-- .../cypress/tasks/discover.ts | 13 +++- .../cypress/tasks/timeline.ts | 65 +++++++++++-------- 15 files changed, 164 insertions(+), 148 deletions(-) diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/event_rendered_view.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/event_rendered_view.cy.ts index e1e7e07a3df15..e028b751c0bf5 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/event_rendered_view.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/event_rendered_view.cy.ts @@ -12,12 +12,12 @@ import { EVENT_SUMMARY_COLUMN, ALERT_RENDERER_HOST_NAME, SHOW_TOP_N_HEADER, + HOVER_ACTIONS, } from '../../../screens/alerts'; import { DATA_GRID_COLUMN_ORDER_BTN, DATA_GRID_FIELD_SORT_BTN, } from '../../../screens/common/data_grid'; -import { HOVER_ACTIONS } from '../../../screens/timeline'; import { showHoverActionsEventRenderedView, switchAlertTableToEventRenderedView, @@ -43,12 +43,12 @@ describe(`Event Rendered View`, { tags: ['@ess', '@serverless'] }, () => { waitForAlerts(); }); - it('Event Summary Column', () => { + it('should show Event Summary column correctly', () => { cy.get(EVENT_SUMMARY_COLUMN).should('be.visible'); cy.get(EVENT_SUMMARY_ALERT_RENDERER_CONTENT).should('be.visible'); }); - it('Hover Action TopN in event summary column', () => { + it('should show TopN in Event Summary column', () => { showHoverActionsEventRenderedView(ALERT_RENDERER_HOST_NAME); cy.get(HOVER_ACTIONS.SHOW_TOP).trigger('click'); cy.get(TOP_N_ALERT_HISTOGRAM).should('be.visible'); @@ -64,15 +64,15 @@ describe(`Event Rendered View`, { tags: ['@ess', '@serverless'] }, () => { * This test main checks if Alert Table controls are rendered properly. * * */ - it('Field Browser is not visible', () => { + it('should not show Field Browser', () => { cy.get(FIELDS_BROWSER_BTN).should('not.exist'); }); - it('Sorting control is not visible', () => { + it('should now show Sorting Control', () => { cy.get(DATA_GRID_FIELD_SORT_BTN).should('not.exist'); }); - it('Column Order button is not visible', () => { + it('should not show column order control', () => { cy.get(DATA_GRID_COLUMN_ORDER_BTN).should('not.exist'); }); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/creation.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/creation.cy.ts index 05957e885d9ea..ffc1fc187142b 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/creation.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/creation.cy.ts @@ -9,10 +9,8 @@ import { ROLES } from '@kbn/security-solution-plugin/common/test'; import { getTimeline } from '../../../objects/timeline'; import { - LOCKED_ICON, // NOTES_TEXT, - PIN_EVENT, - TIMELINE_FILTER, + TIMELINE_FLYOUT_WRAPPER, TIMELINE_QUERY, TIMELINE_PANEL, @@ -30,7 +28,6 @@ import { visit, visitWithTimeRange } from '../../../tasks/navigation'; import { openTimelineUsingToggle } from '../../../tasks/security_main'; import { selectCustomTemplates } from '../../../tasks/templates'; import { - addFilter, addNameAndDescriptionToTimeline, // addNotesToTimeline, clickingOnCreateTimelineFormTemplateBtn, @@ -38,9 +35,6 @@ import { createNewTimeline, executeTimelineKQL, expandEventAction, - goToQueryTab, - pinFirstEvent, - populateTimeline, addNameToTimelineAndSave, addNameToTimelineAndSaveAsNew, } from '../../../tasks/timeline'; @@ -50,8 +44,7 @@ import { OVERVIEW_URL, TIMELINE_TEMPLATES_URL, TIMELINES_URL } from '../../../ur const mockTimeline = getTimeline(); -// FLAKY: https://github.com/elastic/kibana/issues/180688 -describe.skip('Timelines', { tags: ['@ess', '@serverless'] }, (): void => { +describe('Timelines', { tags: ['@ess', '@serverless'] }, (): void => { beforeEach(() => { deleteTimelines(); }); @@ -92,32 +85,6 @@ describe.skip('Timelines', { tags: ['@ess', '@serverless'] }, (): void => { ); }); - it('should create a timeline by clicking untitled timeline from bottom bar', () => { - login(); - visitWithTimeRange(OVERVIEW_URL); - openTimelineUsingToggle(); - addNameAndDescriptionToTimeline(mockTimeline); - populateTimeline(); - goToQueryTab(); - - addFilter(mockTimeline.filter); - cy.get(TIMELINE_FILTER(mockTimeline.filter)).should('exist'); - - pinFirstEvent(); - cy.get(PIN_EVENT) - .should('have.attr', 'aria-label') - .and('match', /Unpin the event in row 2/); - - cy.get(LOCKED_ICON).should('be.visible'); - - // TODO: fix this - // While typing the note, cypress encounters this -> Error: ResizeObserver loop completed with undelivered notifications. - // addNotesToTimeline(mockTimeline.notes); - // cy.get(TIMELINE_TAB_CONTENT_GRAPHS_NOTES) - // .find(NOTES_TEXT) - // .should('have.text', mockTimeline.notes); - }); - it('should show the different timeline states', () => { login(); visitWithTimeRange(TIMELINES_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/data_providers.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/data_providers.cy.ts index 609dd0081f87e..c6ec496744a52 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/data_providers.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/data_providers.cy.ts @@ -9,8 +9,8 @@ import { TIMELINE_DROPPED_DATA_PROVIDERS, TIMELINE_DATA_PROVIDERS_ACTION_MENU, TIMELINE_FLYOUT_HEADER, - GET_TIMELINE_GRID_CELL, TIMELINE_DATA_PROVIDERS_CONTAINER, + GET_TIMELINE_GRID_CELL_VALUE, } from '../../../screens/timeline'; import { waitForAllHostsToBeLoaded } from '../../../tasks/hosts/all_hosts'; @@ -19,7 +19,6 @@ import { login } from '../../../tasks/login'; import { visitWithTimeRange } from '../../../tasks/navigation'; import { addDataProvider, - updateDataProviderbyDraggingField, addNameAndDescriptionToTimeline, populateTimeline, createTimelineFromBottomBar, @@ -28,12 +27,13 @@ import { } from '../../../tasks/timeline'; import { getTimeline } from '../../../objects/timeline'; import { hostsUrl } from '../../../urls/navigation'; +import { LOADING_INDICATOR } from '../../../screens/security_header'; -// FLAKY: https://github.com/elastic/kibana/issues/176945 const mockTimeline = getTimeline(); -describe.skip('Timeline data providers', { tags: ['@ess', '@serverless'] }, () => { +describe('Timeline data providers', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { login(); + cy.intercept('PATCH', '/api/timeline').as('updateTimeline'); visitWithTimeRange(hostsUrl('allHosts')); waitForAllHostsToBeLoaded(); createTimelineFromBottomBar(); @@ -53,28 +53,20 @@ describe.skip('Timeline data providers', { tags: ['@ess', '@serverless'] }, () = cy.get(TIMELINE_DATA_PROVIDERS_ACTION_MENU).should('exist'); }); - it('should persist timeline when data provider is updated by dragging a field from data grid', () => { - updateDataProviderbyDraggingField('host.name', 0); - saveTimeline(); - cy.reload(); - cy.get(`${GET_TIMELINE_GRID_CELL('host.name')}`) - .first() - .then((hostname) => { - cy.get(TIMELINE_DATA_PROVIDERS_CONTAINER).contains(`host.name: "${hostname.text()}"`); - }); - }); - it('should persist timeline when a field is added by hover action "Add To Timeline" in data provider ', () => { addDataProvider({ field: 'host.name', operator: 'exists' }); saveTimeline(); + cy.wait('@updateTimeline'); + cy.get(LOADING_INDICATOR).should('not.exist'); updateDataProviderByFieldHoverAction('host.name', 0); saveTimeline(); + cy.wait('@updateTimeline'); cy.reload(); - cy.get(`${GET_TIMELINE_GRID_CELL('host.name')}`) + cy.get(`${GET_TIMELINE_GRID_CELL_VALUE('host.name')}`) .first() .then((hostname) => { cy.get(TIMELINE_DATA_PROVIDERS_CONTAINER).should((dataProviderContainer) => { - expect(dataProviderContainer).to.contain(`host.name: "${hostname.text()}"`); + expect(dataProviderContainer).to.contain(`host.name: "${hostname.text().trim()}"`); }); }); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/esql/discover_timeline_state_integration.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/esql/discover_timeline_state_integration.cy.ts index 8e45d23d35433..c15f42e0e218e 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/esql/discover_timeline_state_integration.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/esql/discover_timeline_state_integration.cy.ts @@ -18,6 +18,7 @@ import { import { addDiscoverEsqlQuery, addFieldToTable, + assertFieldsAreLoaded, verifyDiscoverEsqlQuery, } from '../../../../tasks/discover'; import { @@ -69,8 +70,7 @@ const handleIntercepts = () => { }); }; -// Failing: See https://github.com/elastic/kibana/issues/180755 -describe.skip( +describe( 'Discover Timeline State Integration', { tags: ['@ess', '@skipInServerless'], @@ -81,6 +81,7 @@ describe.skip( visitWithTimeRange(ALERTS_URL); createTimelineFromBottomBar(); goToEsqlTab(); + addDiscoverEsqlQuery(esqlQuery); updateDateRangeInLocalDatePickers(DISCOVER_CONTAINER, INITIAL_START_DATE, INITIAL_END_DATE); handleIntercepts(); }); @@ -90,17 +91,14 @@ describe.skip( addNameToTimelineAndSave('Timerange timeline'); createNewTimeline(); goToEsqlTab(); - cy.get(GET_LOCAL_SHOW_DATES_BUTTON(DISCOVER_CONTAINER)).should( - 'contain.text', - `Last 15 minutes` - ); + cy.get(GET_LOCAL_SHOW_DATES_BUTTON(DISCOVER_CONTAINER)).should('be.disabled'); // default state }); it('should save/restore esql tab dataview/timerange/filter/query/columns when saving/resoring timeline', () => { const timelineSuffix = Date.now(); const timelineName = `DataView timeline-${timelineSuffix}`; const column1 = 'event.category'; const column2 = 'ecs.version'; - addDiscoverEsqlQuery(esqlQuery); + assertFieldsAreLoaded(); addFieldToTable(column1); addFieldToTable(column2); @@ -132,6 +130,7 @@ describe.skip( const column1 = 'event.category'; const column2 = 'ecs.version'; addDiscoverEsqlQuery(esqlQuery); + assertFieldsAreLoaded(); addFieldToTable(column1); addFieldToTable(column2); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/esql/esql_state.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/esql/esql_state.cy.ts index b8db1dacd03e1..0676d3d5dbfb8 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/esql/esql_state.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/esql/esql_state.cy.ts @@ -25,7 +25,7 @@ import { goToEsqlTab, openActiveTimeline, addNameAndDescriptionToTimeline, - saveTimeline, + addNameToTimelineAndSave, } from '../../../../tasks/timeline'; import { ALERTS_URL } from '../../../../urls/navigation'; import { getTimeline } from '../../../../objects/timeline'; @@ -35,7 +35,25 @@ const INITIAL_START_DATE = 'Jan 18, 2021 @ 20:33:29.186'; const INITIAL_END_DATE = 'Jan 19, 2024 @ 20:33:29.186'; const mockTimeline = getTimeline(); -// FAILURE introduced by the fix for 8.11.4 related to the default empty string and fix for the infinite loop on the esql tab +const esqlQuery = 'from auditbeat-* | limit 5'; + +const TIMELINE_REQ_WITH_SAVED_SEARCH = 'TIMELINE_REQ_WITH_SAVED_SEARCH'; +const TIMELINE_PATCH_REQ = 'TIMELINE_PATCH_REQ'; + +const handleIntercepts = () => { + cy.intercept('PATCH', '/api/timeline', (req) => { + if (Object.hasOwn(req.body, 'timeline') && req.body.timeline.savedSearchId === null) { + req.alias = TIMELINE_PATCH_REQ; + } + }); + cy.intercept('PATCH', '/api/timeline', (req) => { + if (Object.hasOwn(req.body, 'timeline') && req.body.timeline.savedSearchId !== null) { + req.alias = TIMELINE_REQ_WITH_SAVED_SEARCH; + } + }); +}; + +// Flaky: https://github.com/elastic/kibana/issues/180755 describe.skip( 'Timeline Discover ESQL State', { @@ -50,33 +68,29 @@ describe.skip( win.onbeforeunload = null; }); goToEsqlTab(); + addDiscoverEsqlQuery(esqlQuery); updateDateRangeInLocalDatePickers(DISCOVER_CONTAINER, INITIAL_START_DATE, INITIAL_END_DATE); + handleIntercepts(); }); it('should not allow the dataview to be changed', () => { cy.get(DISCOVER_DATA_VIEW_SWITCHER.BTN).should('not.exist'); }); - it('should remember esql query when navigating away and back to discover ', () => { - const esqlQuery = 'from auditbeat-* | limit 5'; - addDiscoverEsqlQuery(esqlQuery); + it.skip('should remember esql query when navigating away and back to discover ', () => { submitDiscoverSearchBar(); - addNameAndDescriptionToTimeline(mockTimeline); - saveTimeline(); + addNameToTimelineAndSave(mockTimeline.title); + cy.wait(`@${TIMELINE_REQ_WITH_SAVED_SEARCH}`); closeTimeline(); navigateFromHeaderTo(CSP_FINDINGS); navigateFromHeaderTo(ALERTS); openActiveTimeline(); goToEsqlTab(); - verifyDiscoverEsqlQuery(esqlQuery); }); it('should remember columns when navigating away and back to discover ', () => { - const esqlQuery = 'from auditbeat-* | limit 5'; - addDiscoverEsqlQuery(esqlQuery); submitDiscoverSearchBar(); - addNameAndDescriptionToTimeline(mockTimeline); addFieldToTable('host.name'); addFieldToTable('user.name'); - saveTimeline(); + addNameAndDescriptionToTimeline(mockTimeline); closeTimeline(); navigateFromHeaderTo(CSP_FINDINGS); navigateFromHeaderTo(ALERTS); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/esql/search_filter.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/esql/search_filter.cy.ts index 0009351852176..889f75130d197 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/esql/search_filter.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/esql/search_filter.cy.ts @@ -25,6 +25,7 @@ import { addDiscoverEsqlQuery, addFieldToTable, convertEditorNonBreakingSpaceToSpace, + waitForDiscoverFieldsToLoad, } from '../../../../tasks/discover'; import { login } from '../../../../tasks/login'; import { visitWithTimeRange } from '../../../../tasks/navigation'; @@ -38,8 +39,7 @@ const INITIAL_END_DATE = 'Jan 19, 2024 @ 20:33:29.186'; const NEW_START_DATE = 'Jan 18, 2023 @ 20:33:29.186'; const esqlQuery = 'from auditbeat-* | where ecs.version == "8.0.0"'; -// FLAKY: https://github.com/elastic/kibana/issues/175180 -describe.skip( +describe( 'Basic esql search and filter operations', { tags: ['@ess'], @@ -58,16 +58,19 @@ describe.skip( }); it('should show data according to the esql query', () => { - updateDateRangeInLocalDatePickers(DISCOVER_CONTAINER, INITIAL_START_DATE, INITIAL_END_DATE); addDiscoverEsqlQuery(`${esqlQuery} | limit 1`); + updateDateRangeInLocalDatePickers(DISCOVER_CONTAINER, INITIAL_START_DATE, INITIAL_END_DATE); cy.get(DISCOVER_RESULT_HITS).should('have.text', 1); }); it('should be able to add fields to the table', () => { - updateDateRangeInLocalDatePickers(DISCOVER_CONTAINER, INITIAL_START_DATE, INITIAL_END_DATE); addDiscoverEsqlQuery(`${esqlQuery} | limit 1`); - addFieldToTable('host.name'); - addFieldToTable('user.name'); + updateDateRangeInLocalDatePickers(DISCOVER_CONTAINER, INITIAL_START_DATE, INITIAL_END_DATE); + waitForDiscoverFieldsToLoad(); + cy.get(DISCOVER_CONTAINER).within(() => { + addFieldToTable('host.name'); + addFieldToTable('user.name'); + }); cy.get(GET_DISCOVER_DATA_GRID_CELL_HEADER('host.name')).should('be.visible'); cy.get(GET_DISCOVER_DATA_GRID_CELL_HEADER('user.name')).should('be.visible'); }); @@ -88,6 +91,8 @@ describe.skip( }); it(`should change the timerange to ${DEFAULT_DATE} when back is pressed after modifying timerange to ${NEW_START_DATE} without saving`, () => { + // The datepicker is only active when a query exists. + addDiscoverEsqlQuery(esqlQuery); cy.get(GET_LOCAL_SHOW_DATES_BUTTON(DISCOVER_CONTAINER)).click(); cy.get(GET_LOCAL_DATE_PICKER_START_DATE_POPOVER_BUTTON(DISCOVER_CONTAINER)).first().click({}); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/export.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/export.cy.ts index c28f0ed90d8c5..e1e3a5cf2de32 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/export.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/export.cy.ts @@ -22,8 +22,7 @@ import { createTimeline } from '../../../tasks/api_calls/timelines'; import { expectedExportedTimeline } from '../../../objects/timeline'; import { closeToast } from '../../../tasks/common/toast'; -// FLAKY: https://github.com/elastic/kibana/issues/187550 -describe.skip('Export timelines', { tags: ['@ess', '@serverless'] }, () => { +describe('Export timelines', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { login(); deleteTimelines(); @@ -42,6 +41,10 @@ describe.skip('Export timelines', { tags: ['@ess', '@serverless'] }, () => { visit(TIMELINES_URL); }); + /** + * TODO: Good candidate for converting to a jest Test + * https://github.com/elastic/kibana/issues/195612 + */ it('should export custom timeline(s)', function () { cy.log('Export a custom timeline via timeline actions'); @@ -60,6 +63,7 @@ describe.skip('Export timelines', { tags: ['@ess', '@serverless'] }, () => { cy.wrap(response?.statusCode).should('eql', 200); cy.wrap(response?.body).should('eql', expectedExportedTimeline(this.timelineResponse1)); }); + closeToast(); cy.log('Export all custom timelines via bulk actions'); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/flyout_button.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/flyout_button.cy.ts index 4ee0f4c58f151..fc2efa8534d47 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/flyout_button.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/flyout_button.cy.ts @@ -18,8 +18,7 @@ import { import { hostsUrl } from '../../../urls/navigation'; -// FLAKY: https://github.com/elastic/kibana/issues/183085 -describe.skip('timeline flyout button', () => { +describe('timeline flyout button', () => { beforeEach(() => { login(); visitWithTimeRange(hostsUrl('allHosts')); @@ -64,18 +63,4 @@ describe.skip('timeline flyout button', () => { cy.get(TIMELINE_BOTTOM_BAR_TOGGLE_BUTTON).should('have.focus'); } ); - - it( - 'should render the global search dropdown when the input is focused', - { tags: ['@ess'] }, - () => { - openTimelineUsingToggle(); - cy.get('[data-test-subj="nav-search-input"]').focus(); - cy.get('[data-test-subj="nav-search-input"]').should('be.focused'); - cy.get('[data-test-subj="nav-search-option"]').should('be.visible'); - cy.get('[data-test-subj="nav-search-option"]').first().realHover(); - // check that at least one item is visible in the search bar after mousing over, i.e. it's still usable. - cy.get('[data-test-subj="nav-search-option"]').its('length').should('be.gte', 1); - } - ); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/row_renderers.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/row_renderers.cy.ts index b27ea9fcc6a81..ebc3591adfe15 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/row_renderers.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/row_renderers.cy.ts @@ -23,12 +23,16 @@ import { waitForAllHostsToBeLoaded } from '../../../tasks/hosts/all_hosts'; import { login } from '../../../tasks/login'; import { visitWithTimeRange } from '../../../tasks/navigation'; import { openTimelineUsingToggle } from '../../../tasks/security_main'; -import { addNameToTimelineAndSave, populateTimeline, saveTimeline } from '../../../tasks/timeline'; +import { + addNameToTimelineAndSave, + enableAllRowRenderersWithSwitch, + populateTimeline, + saveTimeline, +} from '../../../tasks/timeline'; import { hostsUrl } from '../../../urls/navigation'; -// FLAKY: https://github.com/elastic/kibana/issues/182021 -describe.skip('Row renderers', { tags: ['@ess', '@serverless'] }, () => { +describe('Row renderers', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { deleteTimelines(); login(); @@ -42,16 +46,19 @@ describe.skip('Row renderers', { tags: ['@ess', '@serverless'] }, () => { }); openTimelineUsingToggle(); populateTimeline(); - cy.get(TIMELINE_SHOW_ROW_RENDERERS_GEAR).should('exist'); - cy.get(TIMELINE_SHOW_ROW_RENDERERS_GEAR).first().click({ force: true }); }); - it('Row renderers should be enabled by default', () => { + it('Row renderers should be disabled by default', () => { + cy.get(TIMELINE_SHOW_ROW_RENDERERS_GEAR).should('exist'); + cy.get(TIMELINE_SHOW_ROW_RENDERERS_GEAR).first().click(); cy.get(TIMELINE_ROW_RENDERERS_MODAL_ITEMS_CHECKBOX).should('exist'); - cy.get(TIMELINE_ROW_RENDERERS_MODAL_ITEMS_CHECKBOX).should('be.checked'); + cy.get(TIMELINE_ROW_RENDERERS_MODAL_ITEMS_CHECKBOX).should('not.be.checked'); }); it('Selected renderer can be disabled and enabled', () => { + enableAllRowRenderersWithSwitch(); + cy.get(TIMELINE_SHOW_ROW_RENDERERS_GEAR).should('exist'); + cy.get(TIMELINE_SHOW_ROW_RENDERERS_GEAR).first().click(); cy.get(TIMELINE_ROW_RENDERERS_SEARCHBOX).should('exist'); cy.get(TIMELINE_ROW_RENDERERS_SEARCHBOX).type('flow'); @@ -95,6 +102,9 @@ describe.skip('Row renderers', { tags: ['@ess', '@serverless'] }, () => { it('Selected renderer can be disabled with one click', () => { // Ensure these elements are visible before continuing since sometimes it takes a second for the modal to show up // and it gives the click handlers a bit of time to be initialized as well to reduce chances of flake + enableAllRowRenderersWithSwitch(); + cy.get(TIMELINE_SHOW_ROW_RENDERERS_GEAR).should('exist'); + cy.get(TIMELINE_SHOW_ROW_RENDERERS_GEAR).first().click(); cy.get(TIMELINE_ROW_RENDERERS_DISABLE_ALL_BTN).should('exist'); cy.get(TIMELINE_ROW_RENDERERS_MODAL_ITEMS_CHECKBOX).should('be.checked'); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/timelines_table.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/timelines_table.cy.ts index 6c1e7ee3f6cf4..4b8d55065d44e 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/timelines_table.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/timelines_table.cy.ts @@ -26,11 +26,10 @@ import { clearSearchBar, searchForTimeline, toggleFavoriteFilter } from '../../. const mockTimeline = getTimeline(); const mockFavoritedTimeline = getFavoritedTimeline(); -// FLAKY: https://github.com/elastic/kibana/issues/181466 -// Failing: See https://github.com/elastic/kibana/issues/181466 -describe.skip('timeline overview search', { tags: ['@ess', '@serverless'] }, () => { +describe('timeline overview search', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { deleteTimelines(); + // create timeline which is not favorited createTimeline(); login(); diff --git a/x-pack/test/security_solution_cypress/cypress/screens/alerts.ts b/x-pack/test/security_solution_cypress/cypress/screens/alerts.ts index 35c46e9f97557..75ee0d10c53ef 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/alerts.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/alerts.ts @@ -256,3 +256,11 @@ export const ALERT_DETAILS_TAKE_ACTION_BUTTON = export const USER_COLUMN = '[data-gridcell-column-id="user.name"]'; export const TOOLTIP = '[data-test-subj="message-tool-tip"]'; + +export const HOVER_ACTIONS = { + ADD_TO_TIMELINE: '[data-test-subj="actionItem-security-default-cellActions-addToTimeline"]', + FILTER_FOR: '[data-test-subj="actionItem-security-default-cellActions-filterIn"]', + FILTER_OUT: '[data-test-subj="actionItem-security-default-cellActions-filterOut"]', + COPY: '[data-test-subj="actionItem-security-default-cellActions-copyToClipboard"]', + SHOW_TOP: '[data-test-subj="actionItem-security-default-cellActions-showTopN"]', +}; diff --git a/x-pack/test/security_solution_cypress/cypress/screens/discover.ts b/x-pack/test/security_solution_cypress/cypress/screens/discover.ts index 114cb9a4db0c4..e699eb48d5f9d 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/discover.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/discover.ts @@ -79,6 +79,12 @@ export const GET_DISCOVER_COLUMN = (columnId: string) => export const GET_DISCOVER_COLUMN_TOGGLE_BTN = (columnId: string) => `${getDataTestSubjectSelector(`fieldToggle-${columnId}`)}`; -export const DISCOVER_FIELD_SEARCH = getDataTestSubjectSelector('fieldListFiltersFieldSearch'); +export const DISCOVER_FIELD_SEARCH = `${getDataTestSubjectSelector( + 'fieldList' +)} ${getDataTestSubjectSelector('fieldListFiltersFieldSearch')}`; export const DISCOVER_FIELD_LIST_LOADING = getDataTestSubjectSelector('fieldListLoading'); + +export const AVAILABLE_FIELD_COUNT = getDataTestSubjectSelector( + 'fieldListGroupedAvailableFields-count' +); diff --git a/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts b/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts index 3398345bcd1fd..a4aac97091af2 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts @@ -260,6 +260,9 @@ export const TIMELINE_ROW_RENDERERS_SURICATA_SIGNATURE_TOOLTIP = `[data-test-sub export const TIMELINE_SHOW_ROW_RENDERERS_GEAR = '[data-test-subj="show-row-renderers-gear"]'; +export const TIMELINE_ENABLE_DISABLE_ALL_ROW_RENDERER = + getDataTestSubjectSelector('row-renderer-switch'); + export const TIMELINE_TABS = '[data-test-subj="timeline"] .euiTabs'; export const TIMELINE_TAB_CONTENT_EQL = '[data-test-subj="timeline-tab-content-eql"]'; @@ -280,8 +283,13 @@ export const ALERT_TABLE_FILE_NAME_VALUES = `${ALERT_TABLE_FILE_NAME_HEADER}[dat export const ACTIVE_TIMELINE_BOTTOM_BAR = '[data-test-subj="timeline-bottom-bar-title-button"]'; +// timeline table grid cell export const GET_TIMELINE_GRID_CELL = (fieldName: string) => - `[data-test-subj="draggable-content-${fieldName}"]`; + `[data-test-subj="dataGridRowCell"][data-gridcell-column-id="${fieldName}"]`; + +// actual content within timeline table grid cell without screenreader text +export const GET_TIMELINE_GRID_CELL_VALUE = (fieldName: string) => + `[data-test-subj="dataGridRowCell"][data-gridcell-column-id="${fieldName}"] .unifiedDataTable__cellValue`; export const EMPTY_DROPPABLE_DATA_PROVIDER_GROUP = `.empty-providers-group`; @@ -292,11 +300,12 @@ export const TIMELINE_VIEW_IN_ANALYZER = '[data-test-subj="view-in-analyzer"]'; export const EMPTY_DATA_PROVIDER_AREA = `.timeline-drop-area-empty`; export const HOVER_ACTIONS = { - ADD_TO_TIMELINE: '[data-test-subj="actionItem-security-default-cellActions-addToTimeline"]', - FILTER_FOR: '[data-test-subj="actionItem-security-default-cellActions-filterIn"]', - FILTER_OUT: '[data-test-subj="actionItem-security-default-cellActions-filterOut"]', - COPY: '[data-test-subj="actionItem-security-default-cellActions-copyToClipboard"]', - SHOW_TOP: '[data-test-subj="actionItem-security-default-cellActions-showTopN"]', + ADD_TO_TIMELINE: + '[data-test-subj="dataGridColumnCellAction-security-default-cellActions-addToTimeline"]', + FILTER_FOR: '[data-test-subj="dataGridColumnCellAction-security-default-cellActions-filterIn"]', + FILTER_OUT: '[data-test-subj="dataGridColumnCellAction-security-default-cellActions-filterOut"]', + COPY: '[data-test-subj="dataGridColumnCellAction-security-default-cellActions-copyToClipboard"]', + SHOW_TOP: '[data-test-subj="dataGridColumnCellAction-security-default-cellActions-showTopN"]', }; export const TIMELINE_FILTER_BADGE_ENABLED = '[data-test-subj~="filter-enabled"]'; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/discover.ts b/x-pack/test/security_solution_cypress/cypress/tasks/discover.ts index 1034922383a40..583f42aaaf2e3 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/discover.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/discover.ts @@ -15,6 +15,7 @@ import { DISCOVER_DATA_VIEW_EDITOR_FLYOUT, DISCOVER_FIELD_LIST_LOADING, DISCOVER_ESQL_EDITABLE_INPUT, + AVAILABLE_FIELD_COUNT, } from '../screens/discover'; import { GET_LOCAL_SEARCH_BAR_SUBMIT_BUTTON } from '../screens/search_bar'; import { goToEsqlTab } from './timeline'; @@ -43,6 +44,14 @@ export const waitForDiscoverGridToLoad = () => { cy.get(DISCOVER_FIELD_LIST_LOADING).should('not.exist'); }; +export const waitForDiscoverFieldsToLoad = () => { + cy.get(AVAILABLE_FIELD_COUNT).should('be.visible'); +}; + +export const assertFieldsAreLoaded = () => { + cy.get(DISCOVER_FIELD_LIST_LOADING).should('not.exist'); +}; + export const fillEsqlQueryBar = (query: string) => { // eslint-disable-next-line cypress/no-force cy.get(DISCOVER_ESQL_EDITABLE_INPUT).type(query, { force: true }); @@ -94,11 +103,11 @@ export const openAddDiscoverFilterPopover = () => { }; export const searchForField = (fieldId: string) => { - cy.get(DISCOVER_FIELD_SEARCH).type(fieldId); + cy.get(DISCOVER_FIELD_SEARCH).should('be.visible').type(fieldId); }; export const clearFieldSearch = () => { - cy.get(DISCOVER_FIELD_SEARCH).clear(); + cy.get(DISCOVER_FIELD_SEARCH).first().clear(); }; export const addFieldToTable = (fieldId: string) => { diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts b/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts index 7d66243071d9d..5866011ec1cbf 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts @@ -65,8 +65,6 @@ import { TIMELINE_TAB_CONTENT_EQL, TIMESTAMP_HOVER_ACTION_OVERFLOW_BTN, ACTIVE_TIMELINE_BOTTOM_BAR, - EMPTY_DATA_PROVIDER_AREA, - EMPTY_DROPPABLE_DATA_PROVIDER_GROUP, GET_TIMELINE_GRID_CELL, HOVER_ACTIONS, TIMELINE_SWITCHQUERYLANGUAGE_BUTTON, @@ -91,14 +89,17 @@ import { TIMELINE_FLYOUT, TIMELINE_FULL_SCREEN_BUTTON, QUERY_EVENT_COUNT, + TIMELINE_ENABLE_DISABLE_ALL_ROW_RENDERER, TIMELINE_DISCOVER_FIELDS_BUTTON, } from '../screens/timeline'; import { REFRESH_BUTTON, TIMELINE, TIMELINES_TAB_TEMPLATE } from '../screens/timelines'; -import { drag, drop, waitForTabToBeLoaded } from './common'; +import { waitForTabToBeLoaded } from './common'; import { closeFieldsBrowser, filterFieldsBrowser } from './fields_browser'; import { TIMELINE_CONTEXT_MENU_BTN } from '../screens/alerts'; +import { LOADING_INDICATOR } from '../screens/security_header'; +import { TOASTER } from '../screens/alerts_detection_rules'; import { RUNTIME_FIELD_INPUT, SAVE_FIELD_BUTTON } from '../screens/create_runtime_field'; const hostExistsQuery = 'host.name: *'; @@ -123,6 +124,17 @@ export const addNameToTimelineAndSaveAsNew = (name: string) => { cy.get(TIMELINE_TITLE_INPUT).should('not.exist'); }; +export const openSaveTimelineModal = () => { + recurse( + () => { + cy.get(SAVE_TIMELINE_ACTION); + + return cy.get(TIMELINE_TITLE_INPUT); + }, + (sub) => sub.is(':visible') + ); +}; + export const addNameAndDescriptionToTimeline = ( timeline: Timeline, modalAlreadyOpen: boolean = false @@ -241,38 +253,17 @@ export const addDataProvider = (filter: TimelineFilter): Cypress.Chainable { - const dragTargetSelector = GET_TIMELINE_GRID_CELL(fieldName); - cy.get(dragTargetSelector) - .eq(rowNumber) - .then((currentSubject) => { - drag(currentSubject); - }); - let dropTarget: Cypress.Chainable>; - - cy.get('body').then((body) => { - if (body.find(EMPTY_DATA_PROVIDER_AREA).length > 0) { - dropTarget = cy.get(EMPTY_DATA_PROVIDER_AREA); - } else { - dropTarget = cy.get(EMPTY_DROPPABLE_DATA_PROVIDER_GROUP); - } - - dropTarget.then((currentEl) => { - drop(currentEl); - }); - }); -}; - export const updateDataProviderByFieldHoverAction = (fieldName: string, rowNumber: number) => { const fieldSelector = GET_TIMELINE_GRID_CELL(fieldName); - cy.get(fieldSelector).eq(rowNumber).trigger('mouseover'); + cy.get(fieldSelector).eq(rowNumber).should('be.visible').realHover(); cy.get(HOVER_ACTIONS.ADD_TO_TIMELINE).should('be.visible'); + recurse( () => { cy.get(HOVER_ACTIONS.ADD_TO_TIMELINE).click(); return cy.root(); }, - ($el) => $el.find(HOVER_ACTIONS.ADD_TO_TIMELINE).length === 0 + ($el) => $el.find(TOASTER).text().startsWith('Added ') ); }; @@ -314,7 +305,13 @@ export const createNewTimeline = () => { }; export const openCreateTimelineOptionsPopover = () => { - cy.get(NEW_TIMELINE_ACTION).filter(':visible').click(); + recurse( + () => { + cy.get(NEW_TIMELINE_ACTION).filter(':visible').click(); + return cy.get(CREATE_NEW_TIMELINE); + }, + (sub) => sub.is(':visible') + ); }; export const createTimelineFromBottomBar = () => { @@ -370,6 +367,8 @@ export const saveTimeline = () => { cy.get(TIMELINE_PROGRESS_BAR).should('exist'); cy.get(TIMELINE_PROGRESS_BAR).should('not.exist'); + + cy.get(LOADING_INDICATOR).should('not.exist'); }); }; @@ -546,3 +545,13 @@ export const openTimelineEventContextMenu = (rowIndex: number = 0) => { export const toggleFullScreen = () => { cy.get(TIMELINE_FULL_SCREEN_BUTTON).first().click(); }; + +export const enableAllRowRenderersWithSwitch = () => { + cy.get(TIMELINE_ENABLE_DISABLE_ALL_ROW_RENDERER).click(); + cy.get(TIMELINE_ENABLE_DISABLE_ALL_ROW_RENDERER).should('have.attr', 'aria-checked', 'true'); +}; + +export const disableAllRowRenderersWithSwitch = () => { + cy.get(TIMELINE_ENABLE_DISABLE_ALL_ROW_RENDERER).click(); + cy.get(TIMELINE_ENABLE_DISABLE_ALL_ROW_RENDERER).should('have.attr', 'aria-checked', 'false'); +};