diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos.spec.js index b17c78124..5a0dc3659 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos.spec.js @@ -34,6 +34,7 @@ describe('date_nanos', () => { }); miscUtils.visitPage('app/data-explorer/discover#/'); cy.waitForLoader(); + cy.switchDiscoverTable('new'); cy.setTopNavDate(fromTime, toTime); cy.waitForSearch(); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos_mixed.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos_mixed.spec.js index 07e48047f..b56b2ab54 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos_mixed.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos_mixed.spec.js @@ -31,6 +31,7 @@ describe('date_nanos_mixed', () => { }); miscUtils.visitPage('app/data-explorer/discover#/'); cy.waitForLoader(); + cy.switchDiscoverTable('new'); const fromTime = 'Jan 1, 2019 @ 00:00:00.000'; const toTime = 'Jan 1, 2019 @ 23:59:59.999'; diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover.spec.js index 711ed3f5c..a11258d08 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover.spec.js @@ -62,6 +62,7 @@ describe('discover app', { scrollBehavior: false }, () => { `app/data-explorer/discover#/?_g=(filters:!(),time:(from:'2015-09-19T13:31:44.000Z',to:'2015-09-24T01:31:44.000Z'))` ); cy.waitForLoader(); + cy.switchDiscoverTable('new'); cy.waitForSearch(); }); @@ -70,6 +71,9 @@ describe('discover app', { scrollBehavior: false }, () => { describe('save search', () => { const saveSearch1 = 'Save Search # 1'; const saveSearch2 = 'Modified Save Search # 1'; + beforeEach(() => { + cy.switchDiscoverTable('new'); + }); it('should show correct time range string by timepicker', function () { cy.verifyTimeConfig(DE_DEFAULT_START_TIME, DE_DEFAULT_END_TIME); @@ -146,6 +150,7 @@ describe('discover app', { scrollBehavior: false }, () => { const toTime = 'Jun 12, 1999 @ 11:21:04.000'; before(() => { + cy.switchDiscoverTable('new'); cy.setTopNavDate(fromTime, toTime); }); @@ -259,6 +264,10 @@ describe('discover app', { scrollBehavior: false }, () => { }); describe('refresh interval', function () { + beforeEach(() => { + cy.switchDiscoverTable('new'); + }); + it('should refetch when autofresh is enabled', () => { cy.getElementByTestId('openInspectorButton').click(); cy.getElementByTestId('inspectorPanel') @@ -276,12 +285,15 @@ describe('discover app', { scrollBehavior: false }, () => { .should('be.visible') .clear() .type('2'); + + cy.makeDatePickerMenuOpen(); cy.getElementByTestId('superDatePickerToggleRefreshButton').click(); // Let auto refresh run cy.wait(100); // Close the auto refresh + cy.makeDatePickerMenuOpen(); cy.getElementByTestId('superDatePickerToggleRefreshButton').click(); // Check the timestamp of the last request, it should be different than the first timestamp diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_navigation.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_navigation.spec.js index 40ad4c7d9..9901acf4e 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_navigation.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_navigation.spec.js @@ -46,6 +46,7 @@ describe('doc link in discover', () => { `app/data-explorer/discover#/?_g=(filters:!(),time:(from:'2015-09-19T13:31:44.000Z',to:'2015-09-24T01:31:44.000Z'))` ); cy.waitForLoader(); + cy.switchDiscoverTable('new'); cy.waitForSearch(); }); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_table.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_table.spec.js index e79c33fb3..8b49c671c 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_table.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_table.spec.js @@ -46,6 +46,7 @@ describe('discover doc table', () => { `app/data-explorer/discover#/?_g=(filters:!(),time:(from:'2015-09-19T13:31:44.000Z',to:'2015-09-24T01:31:44.000Z'))` ); cy.waitForLoader(); + cy.switchDiscoverTable('new'); cy.waitForSearch(); }); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/field_data.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/field_data.spec.js index 2cbf475ae..6f350710c 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/field_data.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/field_data.spec.js @@ -46,12 +46,17 @@ describe('discover tab', () => { `app/data-explorer/discover#/?_g=(filters:!(),time:(from:'2015-09-19T13:31:44.000Z',to:'2015-09-24T01:31:44.000Z'))` ); cy.waitForLoader(); + cy.switchDiscoverTable('new'); cy.waitForSearch(); }); after(() => {}); describe('field data', function () { + before(() => { + cy.switchDiscoverTable('new'); + }); + it('search php should show the correct hit count', function () { const expectedHitCount = '445'; cy.setTopNavQuery('php'); @@ -65,12 +70,18 @@ describe('discover tab', () => { }); it('search type:apache should show the correct hit count', () => { + // add this line to address flakiness in Cypress: + // ensures stable switching to the new Discover table format. + cy.switchDiscoverTable('new'); const expectedHitCount = '11,156'; cy.setTopNavQuery('type:apache'); cy.verifyHitCount(expectedHitCount); }); it('doc view should show Time and _source columns', function () { + // add this line to address flakiness in Cypress: + // ensures stable switching to the new Discover table format. + cy.switchDiscoverTable('new'); cy.getElementByTestId('dataGridHeaderCell-@timestamp').should( 'be.visible' ); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_with_encoded_id.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_with_encoded_id.spec.js index 6d99eecc5..8e4d4766f 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_with_encoded_id.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_with_encoded_id.spec.js @@ -36,6 +36,7 @@ describe('index pattern with encoded id', () => { // Go to the Discover page miscUtils.visitPage('app/data-explorer/discover#/'); + cy.switchDiscoverTable('new'); cy.setTopNavDate(DE_DEFAULT_START_TIME, DE_DEFAULT_END_TIME); cy.waitForLoader(); }); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_without_field.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_without_field.spec.js index bc09964e2..5eeb2a57e 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_without_field.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_without_field.spec.js @@ -33,6 +33,7 @@ describe('index pattern without field spec', () => { // Go to the Discover page miscUtils.visitPage('app/data-explorer/discover#/'); cy.waitForLoader(); + cy.switchDiscoverTable('new'); }); after(() => { @@ -49,6 +50,7 @@ describe('index pattern without field spec', () => { it('should display a timepicker after switching to an index pattern with timefield', () => { const indexName = 'with-timefield'; + cy.switchDiscoverTable('new'); cy.getElementByTestId('comboBoxToggleListButton') .should('be.visible') .click(); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/large_string.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/large_string.spec.js index 825bcbd60..c2a1fc1a2 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/large_string.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/large_string.spec.js @@ -44,6 +44,7 @@ describe('test large strings', () => { // Go to the Discover page miscUtils.visitPage('app/data-explorer/discover#/'); cy.waitForLoader(); + cy.switchDiscoverTable('new'); const ExpectedDoc = 'Project Gutenberg EBook of Hamlet'; @@ -56,7 +57,7 @@ describe('test large strings', () => { }); describe('test large data', function () { - it('search Newsletter should show the correct hit count', function () { + it('search Newsletter should show the correct hit count in legacy table', function () { cy.log('test Newsletter keyword is searched'); const expectedHitCount = '1'; const query = 'Newsletter'; @@ -64,6 +65,15 @@ describe('test large strings', () => { cy.verifyHitCount(expectedHitCount); }); + it('search Newsletter should show the correct hit count in datagrid table', function () { + cy.log('test Newsletter keyword is searched'); + cy.switchDiscoverTable('new'); + const expectedHitCount = '1'; + const query = 'Newsletter'; + cy.setTopNavQuery(query); + cy.verifyHitCount(expectedHitCount); + }); + // flaky when looking for the highlighted mark it.skip('the search term Newsletter should be highlighted in the field data', function () { cy.log('Newsletter appears only once'); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/saved_queries.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/saved_queries.spec.js index 8173db2cb..f6b5bf711 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/saved_queries.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/saved_queries.spec.js @@ -24,7 +24,7 @@ const indexSet = [ 'logstash-2015.09.20', ]; -describe('saved queries saved objects', () => { +describe.skip('saved queries saved objects', () => { const fromTime = 'Sep 20, 2015 @ 08:00:00.000'; const toTime = 'Sep 21, 2015 @ 08:00:00.000'; before(() => { @@ -50,6 +50,8 @@ describe('saved queries saved objects', () => { // Go to the Discover page miscUtils.visitPage('app/data-explorer/discover#/'); + cy.waitForLoader(); + cy.switchDiscoverTable('new'); // Set time filter cy.setTopNavDate(fromTime, toTime); @@ -62,6 +64,10 @@ describe('saved queries saved objects', () => { }); describe('saved query management component functionality', function () { + beforeEach(() => { + cy.switchDiscoverTable('new'); + }); + it('should show the saved query management component when there are no saved queries', () => { cy.getElementByTestId('saved-query-management-popover-button').click(); cy.getElementByTestId('saved-query-management-popover') diff --git a/cypress/integration/plugins/custom-import-map-dashboards/1_import_vector_map_tab.spec.js b/cypress/integration/plugins/custom-import-map-dashboards/1_import_vector_map_tab.spec.js index 1a6589675..0099d7960 100644 --- a/cypress/integration/plugins/custom-import-map-dashboards/1_import_vector_map_tab.spec.js +++ b/cypress/integration/plugins/custom-import-map-dashboards/1_import_vector_map_tab.spec.js @@ -7,10 +7,12 @@ import { BASE_PATH } from '../../../utils/constants'; import { MiscUtils } from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { CURRENT_TENANT } from '../../../utils/commands'; const miscUtils = new MiscUtils(cy); describe('Verify the presence of import custom map tab in region map plugin', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; cy.deleteAllIndices(); miscUtils.addSampleData(); @@ -25,7 +27,7 @@ describe('Verify the presence of import custom map tab in region map plugin', () }); it('checks import custom map tab is present', () => { - cy.wait(5000); + cy.wait(10000); // Click on "Import Vector Map" tab, which is part of customImportMap plugin cy.contains('Import Vector Map', { timeout: 120000 }) .should('be.visible') diff --git a/cypress/integration/plugins/custom-import-map-dashboards/2_opensearchMapLayer.spec.js b/cypress/integration/plugins/custom-import-map-dashboards/2_opensearchMapLayer.spec.js index 97fd52e2d..f2536f73b 100644 --- a/cypress/integration/plugins/custom-import-map-dashboards/2_opensearchMapLayer.spec.js +++ b/cypress/integration/plugins/custom-import-map-dashboards/2_opensearchMapLayer.spec.js @@ -4,13 +4,16 @@ */ import { BASE_PATH } from '../../../utils/constants'; +import { CURRENT_TENANT } from '../../../utils/commands'; describe('Default OpenSearch base map layer', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; cy.visit(`${BASE_PATH}/app/home#/tutorial_directory/sampleData`, { retryOnStatusCodeFailure: true, timeout: 60000, }); + cy.wait(5000); cy.get('div[data-test-subj="sampleDataSetCardflights"]', { timeout: 60000, }) @@ -20,8 +23,9 @@ describe('Default OpenSearch base map layer', () => { }); it('check if default OpenSearch map layer can be open', () => { - cy.visit(`${BASE_PATH}/app/maps-dashboards`); - cy.contains('Create map', { timeout: 120000 }).click(); + cy.wait(10000); + cy.visit(`${BASE_PATH}/app/maps-dashboards/create`); + cy.wait(10000); cy.get('[data-test-subj="layerControlPanel"]').should( 'contain', 'Default map' @@ -46,6 +50,7 @@ describe('Default OpenSearch base map layer', () => { after(() => { cy.visit(`${BASE_PATH}/app/home#/tutorial_directory`); + cy.wait(5000); cy.get('button[data-test-subj="removeSampleDataSetflights"]') .should('be.visible') .click(); diff --git a/cypress/integration/plugins/custom-import-map-dashboards/3_add_saved_object.spec.js b/cypress/integration/plugins/custom-import-map-dashboards/3_add_saved_object.spec.js index ff5e868e8..2d8b29495 100644 --- a/cypress/integration/plugins/custom-import-map-dashboards/3_add_saved_object.spec.js +++ b/cypress/integration/plugins/custom-import-map-dashboards/3_add_saved_object.spec.js @@ -4,13 +4,16 @@ */ import { BASE_PATH } from '../../../utils/constants'; +import { CURRENT_TENANT } from '../../../utils/commands'; describe('Add flights dataset saved object', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; cy.visit(`${BASE_PATH}/app/home#/tutorial_directory/sampleData`, { retryOnStatusCodeFailure: true, timeout: 60000, }); + cy.wait(5000); cy.get('div[data-test-subj="sampleDataSetCardflights"]', { timeout: 60000, }) @@ -21,6 +24,7 @@ describe('Add flights dataset saved object', () => { after(() => { cy.visit(`${BASE_PATH}/app/home#/tutorial_directory`); + cy.wait(5000); cy.get('button[data-test-subj="removeSampleDataSetflights"]', { timeout: 120000, }) @@ -29,7 +33,9 @@ describe('Add flights dataset saved object', () => { }); it('check if maps saved object of flights dataset can be found and open', () => { + cy.wait(10000); cy.visit(`${BASE_PATH}/app/maps-dashboards`); + cy.wait(10000); cy.contains('[Flights] Flights Status on Maps Destination Location', { timeout: 120000, }).click(); diff --git a/cypress/integration/plugins/custom-import-map-dashboards/4_documentsLayer.spec.js b/cypress/integration/plugins/custom-import-map-dashboards/4_documentsLayer.spec.js index 9659ef190..65b637d18 100644 --- a/cypress/integration/plugins/custom-import-map-dashboards/4_documentsLayer.spec.js +++ b/cypress/integration/plugins/custom-import-map-dashboards/4_documentsLayer.spec.js @@ -4,13 +4,16 @@ */ import { BASE_PATH } from '../../../utils/constants'; +import { CURRENT_TENANT } from '../../../utils/commands'; describe('Documents layer', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; cy.visit(`${BASE_PATH}/app/home#/tutorial_directory/sampleData`, { retryOnStatusCodeFailure: true, timeout: 60000, }); + cy.wait(5000); cy.get('div[data-test-subj="sampleDataSetCardflights"]', { timeout: 60000, }) @@ -22,9 +25,9 @@ describe('Documents layer', () => { const uniqueName = 'saved-map-' + Date.now().toString(); it('Add new documents layer with configuration', () => { - cy.visit(`${BASE_PATH}/app/maps-dashboards`); - cy.wait(5000); - cy.contains('Create map', { timeout: 120000 }).click(); + cy.wait(10000); + cy.visit(`${BASE_PATH}/app/maps-dashboards/create`); + cy.wait(10000); cy.get("button[data-test-subj='addLayerButton']", { timeout: 120000, }).click(); @@ -70,7 +73,9 @@ describe('Documents layer', () => { }); it('Open saved map with documents layer', () => { + cy.wait(30000); cy.visit(`${BASE_PATH}/app/maps-dashboards`); + cy.wait(10000); cy.get('[data-test-subj="mapListingPage"]', { timeout: 120000 }).should( 'contain', uniqueName @@ -84,6 +89,7 @@ describe('Documents layer', () => { after(() => { cy.visit(`${BASE_PATH}/app/home#/tutorial_directory`); + cy.wait(5000); cy.get('button[data-test-subj="removeSampleDataSetflights"]') .should('be.visible') .click(); diff --git a/cypress/integration/plugins/gantt-chart-dashboards/gantt_ui.spec.js b/cypress/integration/plugins/gantt-chart-dashboards/gantt_ui.spec.js index 29251e3c2..914ada7c3 100644 --- a/cypress/integration/plugins/gantt-chart-dashboards/gantt_ui.spec.js +++ b/cypress/integration/plugins/gantt-chart-dashboards/gantt_ui.spec.js @@ -11,7 +11,7 @@ import { BASE_PATH } from '../../../utils/constants'; dayjs.extend(customParseFormat); -const delay = 100; +const delay = 5000; const GANTT_VIS_NAME = 'A test gantt chart ' + Math.random().toString(36).substring(2); const Y_LABEL = 'A unique label for Y-axis'; @@ -57,6 +57,7 @@ describe('Dump test data', () => { describe('Save a gantt chart', () => { beforeEach(() => { cy.visit(`${BASE_PATH}/app/visualize#`); + cy.wait(delay); }); it('Creates and saves a gantt chart', () => { @@ -83,8 +84,10 @@ describe('Save a gantt chart', () => { describe('Render and configure a gantt chart', () => { beforeEach(() => { + cy.wait(delay); cy.visit(`${BASE_PATH}/app/visualize#`); cy.contains(GANTT_VIS_NAME).click({ force: true }); + cy.wait(delay); }); it('Renders no data message', () => { @@ -114,7 +117,7 @@ describe('Render and configure a gantt chart', () => { cy.wait(delay); cy.get('.traces').should('have.length', DEFAULT_SIZE); - + cy.wait(delay); cy.get('.euiButton__text').contains('Save').click({ force: true }); cy.wait(delay); cy.get('button[data-test-subj="confirmSaveSavedObjectButton"]').click({ @@ -128,6 +131,7 @@ describe('Configure panel settings', () => { cy.visit(`${BASE_PATH}/app/visualize#`); cy.contains(GANTT_VIS_NAME).click({ force: true }); cy.contains('Panel settings').click({ force: true }); + cy.wait(delay); }); it('Changes y-axis label', () => { @@ -244,7 +248,7 @@ describe('Configure panel settings', () => { describe('Add gantt chart to dashboard', () => { it('Adds gantt chart to dashboard', () => { cy.visit(`${BASE_PATH}/app/dashboards#/create`); - + cy.wait(delay); cy.contains('Add an existing').click({ force: true }); cy.wait(delay); cy.get('input[data-test-subj="savedObjectFinderSearchInput"]') diff --git a/cypress/integration/plugins/observability-dashboards/6_notebooks.spec.js b/cypress/integration/plugins/observability-dashboards/6_notebooks.spec.js index 46e54e28a..8c6ebd3d8 100644 --- a/cypress/integration/plugins/observability-dashboards/6_notebooks.spec.js +++ b/cypress/integration/plugins/observability-dashboards/6_notebooks.spec.js @@ -115,7 +115,7 @@ describe('Test reporting integration if plugin installed', () => { cy.get('button.euiContextMenuItem:nth-child(1)') .contains('Download PDF') .click(); - cy.get('#downloadInProgressLoadingModal').should('exist'); + cy.get('body').contains('Please continue report generation in the new tab'); }); it('Create in-context PNG report from notebook', () => { @@ -123,7 +123,7 @@ describe('Test reporting integration if plugin installed', () => { cy.get('button.euiContextMenuItem:nth-child(2)') .contains('Download PNG') .click(); - cy.get('#downloadInProgressLoadingModal').should('exist'); + cy.get('body').contains('Please continue report generation in the new tab'); }); it('Create on-demand report definition from context menu', () => { diff --git a/cypress/integration/plugins/query-workbench-dashboards/ui.spec.js b/cypress/integration/plugins/query-workbench-dashboards/ui.spec.js index cb3be70b4..16506a2bd 100644 --- a/cypress/integration/plugins/query-workbench-dashboards/ui.spec.js +++ b/cypress/integration/plugins/query-workbench-dashboards/ui.spec.js @@ -189,7 +189,7 @@ describe('Test and verify SQL downloads', () => { it(title, () => { cy.request({ method: 'POST', - form: false, + form: true, url: url, headers: { 'content-type': 'application/json;charset=UTF-8', @@ -200,7 +200,10 @@ describe('Test and verify SQL downloads', () => { 'select * from accounts where balance > 49500 order by account_number', }, }).then((response) => { - expect(response.body.data.resp).to.have.string(files[file]); + const data = files[file]; + for (const line of data.split('\n')) { + expect(response.body.data.resp).to.have.string(line.trim()); + } }); }); }); diff --git a/cypress/integration/plugins/reports-dashboards/04-download.spec.js b/cypress/integration/plugins/reports-dashboards/04-download.spec.js index 418255be7..3ab6bd1a3 100644 --- a/cypress/integration/plugins/reports-dashboards/04-download.spec.js +++ b/cypress/integration/plugins/reports-dashboards/04-download.spec.js @@ -73,9 +73,7 @@ describe('Cypress', () => { cy.wait(5000); // open saved search list - cy.get( - 'button.euiButtonEmpty:nth-child(3) > span:nth-child(1) > span:nth-child(1)' - ).click({ force: true }); + cy.get('[data-test-subj="discoverOpenButton"]').click({ force: true }); cy.wait(5000); // click first entry diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js index 823d2f84e..bb2244e46 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js @@ -7,6 +7,10 @@ import { NODE_API, OPENSEARCH_DASHBOARDS_URL, } from '../../../utils/plugins/security-analytics-dashboards-plugin/constants'; +import { + getLogTypeLabel, + setupIntercept, +} from '../../../utils/plugins/security-analytics-dashboards-plugin/helpers'; import sample_windows_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_windows_index_settings.json'; import sample_dns_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_dns_index_settings.json'; import dns_name_rule_data from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_dns_rule_with_name_selection.json'; @@ -18,6 +22,7 @@ const cypressIndexDns = 'cypress-index-dns'; const cypressIndexWindows = 'cypress-index-windows'; const detectorName = 'test detector'; const cypressLogTypeDns = 'dns'; +const creationFailedMessage = 'Create detector failed.'; const cypressDNSRule = dns_name_rule_data.title; @@ -39,7 +44,7 @@ const dataSourceLabel = 'Select or input source indexes or index patterns'; const getDataSourceField = () => cy.sa_getFieldByLabel(dataSourceLabel); -const logTypeLabel = 'Select a log type you would like to detect'; +const logTypeLabel = 'Log type'; const getLogTypeField = () => cy.sa_getFieldByLabel(logTypeLabel); @@ -133,25 +138,39 @@ const validatePendingFieldMappingsPanel = (mappings) => { }); }; -const fillDetailsForm = (detectorName, dataSource) => { +const fillDetailsForm = ( + detectorName, + dataSource, + isCustomDataSource = false +) => { getNameField().type(detectorName); - getDataSourceField().sa_selectComboboxItem(dataSource); + + if (isCustomDataSource) { + getDataSourceField() + .focus() + .type(dataSource + '{enter}'); + } else { + getDataSourceField().sa_selectComboboxItem(dataSource); + } + getDataSourceField().focus().blur(); - getLogTypeField().sa_selectComboboxItem(cypressLogTypeDns); + getLogTypeField().sa_selectComboboxItem(getLogTypeLabel(cypressLogTypeDns)); getLogTypeField().focus().blur(); }; const createDetector = (detectorName, dataSource, expectFailure) => { getCreateDetectorButton().click({ force: true }); - fillDetailsForm(detectorName, dataSource); + fillDetailsForm(detectorName, dataSource, expectFailure); cy.sa_getElementByText( '.euiAccordion .euiTitle', - 'Detection rules (14 selected)' + 'Selected detection rules (14)' ) .click({ force: true, timeout: 5000 }) - .then(() => cy.contains('.euiTable .euiTableRow', 'Dns')); + .then(() => + cy.contains('.euiTable .euiTableRow', getLogTypeLabel(cypressLogTypeDns)) + ); cy.sa_getElementByText('.euiAccordion .euiTitle', 'Field mapping - optional'); cy.get('[aria-controls="mappedTitleFieldsAccordion"]').then(($btn) => { @@ -168,21 +187,14 @@ const createDetector = (detectorName, dataSource, expectFailure) => { // Open the trigger details accordion cy.get('[data-test-subj="trigger-details-btn"]').click({ force: true }); cy.sa_getElementByText('.euiTitle.euiTitle--medium', 'Set up alert triggers'); - cy.sa_getInputByPlaceholder( - 'Enter a name to describe the alert condition' - ).type('test_trigger'); cy.sa_getElementByTestSubject('alert-tags-combo-box') .type(`attack.defense_evasion{enter}`) .find('input') .focus() .blur(); - cy.sa_getFieldByLabel('Specify alert severity').sa_selectComboboxItem( - '1 (Highest)' - ); - - cy.intercept('POST', NODE_API.MAPPINGS_BASE).as('createMappingsRequest'); - cy.intercept('POST', NODE_API.DETECTORS_BASE).as('createDetectorRequest'); + setupIntercept(cy, NODE_API.MAPPINGS_BASE, 'createMappingsRequest'); + setupIntercept(cy, NODE_API.DETECTORS_BASE, 'createDetectorRequest'); // create the detector cy.sa_getElementByText('button', 'Create').click({ force: true }); @@ -197,11 +209,6 @@ const createDetector = (detectorName, dataSource, expectFailure) => { cy.url() .should('contain', detectorId) .then(() => { - cy.sa_getElementByText( - '.euiCallOut', - `Detector created successfully: ${detectorName}` - ); - // Confirm detector state cy.sa_getElementByText('.euiTitle', detectorName); cy.sa_getElementByText('.euiHealth', 'Active').then(() => { @@ -217,7 +224,7 @@ const createDetector = (detectorName, dataSource, expectFailure) => { cy.wait(5000); // waiting for the page to be reloaded after pushing detector id into route cy.sa_getElementByText('button.euiTab', 'Alert triggers') .should('be.visible') - .click(); + .click({ force: true }); validateAlertPanel('Trigger 1'); }); }); @@ -265,7 +272,7 @@ describe('Detectors', () => { describe('...should validate form fields', () => { beforeEach(() => { - cy.intercept(NODE_API.SEARCH_DETECTORS).as('detectorsSearch'); + setupIntercept(cy, NODE_API.SEARCH_DETECTORS, 'detectorsSearch'); // Visit Detectors page before any test cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`); @@ -414,9 +421,7 @@ describe('Detectors', () => { describe('...validate create detector flow', () => { beforeEach(() => { - cy.intercept(NODE_API.SEARCH_DETECTORS) - .as('detectorsSearch') - .as('detectorsSearch'); + setupIntercept(cy, NODE_API.SEARCH_DETECTORS, 'detectorsSearch'); // Visit Detectors page before any test cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`); @@ -425,16 +430,16 @@ describe('Detectors', () => { it('...can fail creation', () => { createDetector(`${detectorName}_fail`, '.kibana_1', true); - cy.sa_getElementByText('.euiCallOut', 'Create detector failed.'); + cy.sa_getElementByText('.euiCallOut', creationFailedMessage); }); it('...can be created', () => { createDetector(detectorName, cypressIndexDns, false); - cy.sa_getElementByText('.euiCallOut', 'Detector created successfully'); + cy.contains(creationFailedMessage).should('not.exist'); }); it('...basic details can be edited', () => { - cy.intercept('GET', NODE_API.INDICES_BASE).as('getIndices'); + setupIntercept(cy, NODE_API.INDICES_BASE, 'getIndices', 'GET'); openDetectorDetails(detectorName); editDetectorDetails(detectorName, 'Detector details'); @@ -494,10 +499,13 @@ describe('Detectors', () => { }); xit('...should update field mappings if data source is changed', () => { - cy.intercept( - `${NODE_API.MAPPINGS_VIEW}?indexName=cypress-index-dns&ruleTopic=dns` - ).as('getMappingsView'); - cy.intercept('GET', NODE_API.INDICES_BASE).as('getIndices'); + setupIntercept( + cy, + `${NODE_API.MAPPINGS_VIEW}?indexName=cypress-index-dns&ruleTopic=dns`, + 'getMappingsView', + 'GET' + ); + setupIntercept(cy, NODE_API.INDICES_BASE, 'getIndices', 'GET'); openDetectorDetails(detectorName); editDetectorDetails(detectorName, 'Detector details'); @@ -519,9 +527,7 @@ describe('Detectors', () => { }); xit('...should show field mappings if rule selection is changed', () => { - cy.intercept( - `${NODE_API.MAPPINGS_VIEW}?indexName=cypress-index-windows&ruleTopic=dns` - ).as('getMappingsView'); + setupIntercept(cy, `${NODE_API.MAPPINGS_VIEW}`, 'getMappingsView', 'GET'); openDetectorDetails(detectorName); @@ -544,22 +550,16 @@ describe('Detectors', () => { }); it('...can be deleted', () => { - cy.intercept(`${NODE_API.RULES_BASE}/_search?prePackaged=true`).as( - 'getSigmaRules' - ); - cy.intercept(`${NODE_API.RULES_BASE}/_search?prePackaged=false`).as( - 'getCustomRules' - ); + setupIntercept(cy, `${NODE_API.RULES_BASE}/_search`, 'getSigmaRules'); openDetectorDetails(detectorName); cy.wait('@detectorsSearch'); - cy.wait('@getCustomRules'); cy.wait('@getSigmaRules'); cy.sa_getButtonByText('Actions') .click({ force: true }) .then(() => { - cy.intercept(`${NODE_API.DETECTORS_BASE}/_search`).as('detectors'); + setupIntercept(cy, `${NODE_API.DETECTORS_BASE}/_search`, 'detectors'); cy.sa_getElementByText('.euiContextMenuItem', 'Delete').click({ force: true, }); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js index 4b6fa5774..43f027a07 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js @@ -7,6 +7,10 @@ import { NODE_API, OPENSEARCH_DASHBOARDS_URL, } from '../../../utils/plugins/security-analytics-dashboards-plugin/constants'; +import { + getLogTypeLabel, + setupIntercept, +} from '../../../utils/plugins/security-analytics-dashboards-plugin/helpers'; const uniqueId = Cypress._.random(0, 1e6); const SAMPLE_RULE = { @@ -72,7 +76,7 @@ const checkRulesFlyout = () => { // Validate log type cy.get('[data-test-subj="rule_flyout_rule_log_type"]').contains( - SAMPLE_RULE.logType + getLogTypeLabel(SAMPLE_RULE.logType) ); // Validate description @@ -170,10 +174,6 @@ const getListRadioField = () => cy.get('[for="selection-map-list-0-0"]'); const getTextRadioField = () => cy.get('[for="selection-map-value-0-0"]'); const getConditionField = () => cy.get('[data-test-subj="rule_detection_field"]'); -const getConditionAddButton = () => - cy.get('[data-test-subj="condition-add-selection-btn"]'); -const getConditionRemoveButton = (index) => - cy.get(`[data-test-subj="selection-exp-field-item-remove-${index}"]`); const getRuleSubmitButton = () => cy.get('[data-test-subj="submit_rule_form_button"]'); const getTagField = (index) => @@ -196,7 +196,7 @@ const fillCreateForm = () => { getAuthorField().type(`${SAMPLE_RULE.author}`); // rule details - getLogTypeField().sa_selectComboboxItem(SAMPLE_RULE.logType); + getLogTypeField().sa_selectComboboxItem(getLogTypeLabel(SAMPLE_RULE.logType)); getRuleLevelField().sa_selectComboboxItem(SAMPLE_RULE.severity); // rule detection @@ -208,8 +208,6 @@ const fillCreateForm = () => { getMapValueField().type('FieldValue'); }); - getConditionAddButton().click({ force: true }); - // rule additional details SAMPLE_RULE.tags.forEach((tag, idx) => { getTagField(idx).type(tag); @@ -226,9 +224,7 @@ describe('Rules', () => { describe('...should validate form fields', () => { beforeEach(() => { - cy.intercept(`${NODE_API.RULES_BASE}/_search?prePackaged=true`).as( - 'rulesSearch' - ); + setupIntercept(cy, `${NODE_API.RULES_BASE}/_search`, 'rulesSearch'); // Visit Rules page cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/rules`); cy.wait('@rulesSearch').should('have.property', 'state', 'Complete'); @@ -334,7 +330,9 @@ describe('Rules', () => { getLogTypeField().focus().blur(); getLogTypeField().sa_containsError('Log type is required'); - getLogTypeField().sa_selectComboboxItem(SAMPLE_RULE.logType); + getLogTypeField().sa_selectComboboxItem( + getLogTypeLabel(SAMPLE_RULE.logType) + ); getLogTypeField().focus().blur().sa_shouldNotHaveError(); }); @@ -379,13 +377,20 @@ describe('Rules', () => { it('...should validate selection map key field', () => { getSelectionPanelByIndex(0).within(() => { getMapKeyField().should('be.empty'); - getMapKeyField().focus().blur(); + getMapKeyField() + .focus() + .blur() + .parents('.euiFormRow__fieldWrapper') + .find('.euiFormErrorText') + .should('not.exist'); + + getMapKeyField().type('hello@'); getMapKeyField() .parentsUntil('.euiFormRow__fieldWrapper') .siblings() - .contains('Key name is required'); + .contains('Invalid key name'); - getMapKeyField().type('FieldKey'); + getMapKeyField().focus().type('{selectall}').type('FieldKey'); getMapKeyField() .focus() .blur() @@ -439,15 +444,8 @@ describe('Rules', () => { getRuleSubmitButton().click({ force: true }); getConditionField() .parents('.euiFormRow__fieldWrapper') - .contains('Condition is required'); - - getConditionAddButton().click({ force: true }); - getConditionField().find('.euiFormErrorText').should('not.exist'); - - getConditionRemoveButton(0).click({ force: true }); - getConditionField() - .parents('.euiFormRow__fieldWrapper') - .contains('Condition is required'); + .contains('Condition is required') + .should('not.exist'); }); it('...should validate tag field', () => { @@ -481,7 +479,9 @@ describe('Rules', () => { // log field getLogTypeField().sa_clearCombobox(); toastShouldExist(); - getLogTypeField().sa_selectComboboxItem(SAMPLE_RULE.logType); + getLogTypeField().sa_selectComboboxItem( + getLogTypeLabel(SAMPLE_RULE.logType) + ); // severity field getRuleLevelField().sa_clearCombobox(); @@ -506,7 +506,6 @@ describe('Rules', () => { getSelectionPanelByIndex(0).within(() => getMapKeyField().type('{selectall}').type('{backspace}') ); - toastShouldExist(); getSelectionPanelByIndex(0).within(() => getMapKeyField().type('FieldKey') ); @@ -517,7 +516,7 @@ describe('Rules', () => { ); toastShouldExist(); getSelectionPanelByIndex(0).within(() => - getMapValueField().type('FieldValue') + getMapValueField().type('FieldValue', { force: true }) ); // selection map list field @@ -528,14 +527,9 @@ describe('Rules', () => { toastShouldExist(); getSelectionPanelByIndex(0).within(() => { getListRadioField().click({ force: true }); - getMapListField().type('FieldValue'); + getMapListField().type('FieldValue', { force: true }); }); - // condition field - getConditionRemoveButton(0).click({ force: true }); - toastShouldExist(); - getConditionAddButton().click({ force: true }); - // tags field getTagField(0).sa_clearValue().type('wrong.tag'); toastShouldExist(); @@ -545,9 +539,7 @@ describe('Rules', () => { describe('...should validate create rule flow', () => { beforeEach(() => { - cy.intercept(`${NODE_API.RULES_BASE}/_search?prePackaged=false`).as( - 'rulesSearch' - ); + setupIntercept(cy, `${NODE_API.RULES_BASE}/_search`, 'rulesSearch'); // Visit Rules page cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/rules`); cy.wait('@rulesSearch').should('have.property', 'state', 'Complete'); @@ -572,9 +564,7 @@ describe('Rules', () => { cy.get('[data-test-subj="rule_yaml_editor"]').contains(line) ); - cy.intercept({ - url: `${NODE_API.RULES_BASE}/_search?prePackaged=false`, - }).as('getRules'); + setupIntercept(cy, `${NODE_API.RULES_BASE}/_search`, 'getRules'); submitRule(); @@ -618,10 +608,12 @@ describe('Rules', () => { SAMPLE_RULE.logType = 'dns'; YAML_RULE_LINES[2] = `product: ${SAMPLE_RULE.logType}`; YAML_RULE_LINES[3] = `title: ${SAMPLE_RULE.name}`; - getLogTypeField().sa_selectComboboxItem(SAMPLE_RULE.logType); + getLogTypeField().sa_selectComboboxItem( + getLogTypeLabel(SAMPLE_RULE.logType) + ); getLogTypeField() .sa_containsValue(SAMPLE_RULE.logType) - .contains(SAMPLE_RULE.logType); + .contains(getLogTypeLabel(SAMPLE_RULE.logType)); SAMPLE_RULE.description += ' edited'; YAML_RULE_LINES[4] = `description: ${SAMPLE_RULE.description}`; @@ -629,9 +621,7 @@ describe('Rules', () => { getDescriptionField().type(SAMPLE_RULE.description); getDescriptionField().should('have.value', SAMPLE_RULE.description); - cy.intercept({ - url: `${NODE_API.RULES_BASE}/_search?prePackaged=false`, - }).as('getRules'); + setupIntercept(cy, `${NODE_API.RULES_BASE}/_search`, 'getRules'); submitRule(); @@ -645,13 +635,7 @@ describe('Rules', () => { }); it('...can be deleted', () => { - cy.intercept('POST', `${NODE_API.RULES_BASE}/_search?prePackaged=true`, { - delay: 5000, - }).as('getPrePackagedRules'); - - cy.intercept('POST', `${NODE_API.RULES_BASE}/_search?prePackaged=false`, { - delay: 5000, - }).as('getCustomRules'); + setupIntercept(cy, `${NODE_API.RULES_BASE}/_search`, 'getRules', 'POST'); cy.get(`input[placeholder="Search rules"]`).sa_ospSearch( SAMPLE_RULE.name @@ -677,8 +661,7 @@ describe('Rules', () => { ); cy.wait(5000); - cy.wait('@getCustomRules'); - cy.wait('@getPrePackagedRules'); + cy.wait('@getRules'); // Search for sample_detector, presumably deleted cy.wait(3000); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js index 8812d5c28..0f7de238e 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js @@ -13,6 +13,7 @@ import indexSettings from '../../../fixtures/plugins/security-analytics-dashboar import aliasMappings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_alias_mappings.json'; import indexDoc from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_document.json'; import ruleSettings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_windows_usb_rule.json'; +import { setupIntercept } from '../../../utils/plugins/security-analytics-dashboards-plugin/helpers'; const indexName = 'test-index'; const detectorName = 'test-detector'; @@ -49,7 +50,7 @@ describe('Alerts', () => { beforeEach(() => { // Visit Alerts table page - cy.intercept(`${NODE_API.DETECTORS_BASE}/_search`).as('detectorsSearch'); + setupIntercept(cy, `${NODE_API.DETECTORS_BASE}/_search`, 'detectorsSearch'); // Visit Detectors page cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/alerts`); cy.wait('@detectorsSearch').should('have.property', 'state', 'Complete'); @@ -103,6 +104,7 @@ describe('Alerts', () => { // Click the "View details" button for the first alert cy.get('[aria-label="View details"]').click({ force: true }); }); + cy.wait(3000); // Get the details flyout, and validate its content cy.get('[data-test-subj="alert-details-flyout"]').within(() => { @@ -138,14 +140,16 @@ describe('Alerts', () => { // Wait for the findings table to finish loading cy.contains('Findings (1)'); - cy.contains('Cypress USB Rule'); + cy.contains('Detection rules'); // Confirm alert findings contain expected values cy.get('tbody > tr').should(($tr) => { expect($tr, `timestamp`).to.contain(date); - expect($tr, `rule name`).to.contain('Cypress USB Rule'); + expect($tr, `detection type`).to.contain('Detection rules'); expect($tr, `detector name`).to.contain(testDetectorCfg.name); - expect($tr, `log type`).to.contain('System Activity: Windows'); + expect($tr, `log type`).to.contain( + 'System Activity: Microsoft Windows' + ); }); // Close the flyout @@ -167,9 +171,11 @@ describe('Alerts', () => { cy.get('[aria-label="View details"]').click({ force: true }); }); + cy.wait(3000); + cy.get('[data-test-subj="alert-details-flyout"]').within(() => { // Wait for findings table to finish loading - cy.contains('Cypress USB Rule'); + cy.contains('Detection rules'); // Click the details button for the first finding cy.get('tbody > tr') @@ -193,10 +199,10 @@ describe('Alerts', () => { date ); - // Confirm finding detector name + // Confirm finding detection type cy.get( - '[data-test-subj="finding-details-flyout-detector-link"]' - ).contains(testDetectorCfg.name); + '[data-test-subj="finding-details-flyout-detection-type"]' + ).contains('Detection rules'); // Confirm there's only 1 rule details accordion cy.get( @@ -429,42 +435,5 @@ describe('Alerts', () => { }); }); - it('detector name hyperlink on finding details flyout redirects to the detector details page', () => { - // Open first alert details flyout - cy.get('tbody > tr') - .first() - .within(() => { - // Click the "View details" button for the first alert - cy.get('[aria-label="View details"]').click({ force: true }); - }); - - cy.get('[data-test-subj="alert-details-flyout"]').within(() => { - // Wait for findings table to finish loading - cy.contains('Cypress USB Rule'); - - // Click the details button for the first finding - cy.get('tbody > tr') - .first() - .within(() => { - cy.get('[data-test-subj="finding-details-flyout-button"]').click({ - force: true, - }); - }); - }); - - cy.get('[data-test-subj="finding-details-flyout"]').within(() => { - // Click the detector name hyperlink - cy.get('[data-test-subj="finding-details-flyout-detector-link"]') - // Removing the "target" attribute so the link won't open a new tab. Cypress wouldn't test the new tab. - .invoke('removeAttr', 'target') - .click({ force: true }); - }); - - // Confirm the detector details page is for the expected detector - cy.get('[data-test-subj="detector-details-detector-name"]').contains( - testDetectorCfg.name - ); - }); - after(() => cy.sa_cleanUpTests()); }); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js index f692a6b52..c8d458992 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js @@ -55,7 +55,7 @@ describe('Findings', () => { cy.contains('No items found').should('not.exist'); // Check for expected findings - cy.contains('System Activity: Windows'); + cy.contains('System Activity: Microsoft Windows'); cy.contains('High'); }); diff --git a/cypress/support/assistant-dummy-llm.js b/cypress/support/assistant-dummy-llm.js index 930f6b223..f80ef3803 100644 --- a/cypress/support/assistant-dummy-llm.js +++ b/cypress/support/assistant-dummy-llm.js @@ -10,7 +10,7 @@ const suggestionJson = require('../fixtures/plugins/dashboards-assistant/suggest const MATCH_AGENT_FRAMEWORK_PROMPT = 'Assistant is designed to be able to assist with a wide range of tasks'; const MATCH_SUGGESTION_PROMPT = 'You are an AI that only speaks JSON'; -const TOOL_RESPONSE = 'TOOL RESPONSE:'; +const TOOL_RESPONSE = 'TOOL RESPONSE of '; const server = http.createServer((req, res) => { // Set the content type to JSON diff --git a/cypress/utils/dashboards/data_explorer/commands.js b/cypress/utils/dashboards/data_explorer/commands.js index 968558b89..8170089d6 100644 --- a/cypress/utils/dashboards/data_explorer/commands.js +++ b/cypress/utils/dashboards/data_explorer/commands.js @@ -133,3 +133,46 @@ Cypress.Commands.add('deleteSaveQuery', (name) => { }); cy.getElementByTestId('confirmModalConfirmButton').click(); }); + +Cypress.Commands.add('switchDiscoverTable', (name) => { + cy.getElementByTestId('datagridTableButton') + .then(($button) => { + const buttonText = $button.text(); + + if (name === 'new' && buttonText.includes('Try new Discover')) { + cy.wrap($button).click(); + } + if (name === 'legacy' && buttonText.includes('Use legacy Discover')) { + cy.wrap($button).click(); + } + cy.waitForLoader(); + }) + .then(() => { + checkForElementVisibility(); + }); +}); + +Cypress.Commands.add('makeDatePickerMenuOpen', () => { + cy.get( + '[class="euiFormControlLayout euiFormControlLayout--group euiSuperDatePicker"]' + ).then(($popover) => { + // Check if the popover does not have the 'euiPopover-isOpen' class + if (!$popover.hasClass('euiPopover-isOpen')) { + // If not open, click the button to open the quick menu + cy.getElementByTestId('superDatePickerToggleQuickMenuButton').click(); + } + }); +}); + +function checkForElementVisibility() { + cy.getElementsByTestIds('queryInput') + .should('be.visible') + .then(($element) => { + if ($element.is(':visible')) { + return; + } else { + cy.wait(500); // Wait for half a second before checking again + checkForElementVisibility(); // Recursive call + } + }); +} diff --git a/cypress/utils/dashboards/data_explorer/index.d.ts b/cypress/utils/dashboards/data_explorer/index.d.ts index ef7c5980d..bc71c6ade 100644 --- a/cypress/utils/dashboards/data_explorer/index.d.ts +++ b/cypress/utils/dashboards/data_explorer/index.d.ts @@ -15,6 +15,8 @@ declare namespace Cypress { saveQuery(name: string, description: string): Chainable; loadSaveQuery(name: string): Chainable; clearSaveQuery(): Chainable; - deleteSaveQuery(name: string):Chainable; + deleteSaveQuery(name: string): Chainable; + switchDiscoverTable(name: string): Chainable; + makeDatePickerMenuOpen(): Chainable; } } \ No newline at end of file diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js index 79c637364..b9c853fbf 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js @@ -126,3 +126,21 @@ export const createDetector = ( return detectorConfig; }; + +export const logTypeLabels = { + cloudtrail: 'AWS Cloudtrail', + dns: 'DNS', + vpcflow: 'VPC Flow', + ad_ldap: 'AD/LDAP', + apache_access: 'Apache Access', + m365: 'Microsoft 365', + okta: 'Okta', + waf: 'WAF', + s3: 'AWS S3', + github: 'Github', + gworkspace: 'Google Workspace', + windows: 'Microsoft Windows', + network: 'Network', + linux: 'Linux System Logs', + azure: 'Microsoft Azure', +}; diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/helpers.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/helpers.js new file mode 100644 index 000000000..edc7cd4af --- /dev/null +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/helpers.js @@ -0,0 +1,16 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { logTypeLabels } from './constants'; +import { startCase } from 'lodash'; + +export function getLogTypeLabel(name) { + return !name ? '-' : logTypeLabels[name.toLowerCase()] || startCase(name); +} + +export function setupIntercept(cy, url, interceptName, method = 'POST') { + const urlRegex = new RegExp(`.*${url}.*`); + cy.intercept(method, urlRegex).as(interceptName); +}