From 02bb7d4a880a99505879d6d892b0ca8964a880b7 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Wed, 8 Jan 2025 21:09:18 -0800 Subject: [PATCH 01/36] add spec for old ui Signed-off-by: Argus Li --- .../field_display_filtering.spec.js | 2 +- .../saved_queries_old_ui.spec.js | 104 +++++++++ .../query_enhancements/utils/saved_queries.js | 207 ++++++++++++++++++ cypress/utils/apps/data_explorer/commands.js | 19 +- .../utils/apps/query_enhancements/commands.js | 12 +- 5 files changed, 337 insertions(+), 7 deletions(-) create mode 100644 cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js create mode 100644 cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/saved_queries.js diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/field_display_filtering.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/field_display_filtering.spec.js index 1069f2077db0..726cb3d4fd4a 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/field_display_filtering.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/field_display_filtering.spec.js @@ -223,7 +223,7 @@ describe('filter for value spec', () => { }); after(() => { - cy.deleteWorkspaceByName(`${WORKSPACE_NAME}`); + cy.deleteWorkspaceByName(`${workspace}`); cy.deleteDataSourceByName(`${DATASOURCE_NAME}`); // TODO: Modify deleteIndex to handle an array of index and remove hard code cy.deleteIndex(INDEX_PATTERN_NAME); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js new file mode 100644 index 000000000000..98ddf0a54925 --- /dev/null +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js @@ -0,0 +1,104 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + INDEX_PATTERN_WITH_TIME, + INDEX_WITH_TIME_1, + INDEX_WITH_TIME_2, + SECONDARY_ENGINE, +} from '../../../../../utils/constants'; + +import { + workspaceName, + datasourceName, + setSearchConfigurations, + setDatePickerDatesAndSearchIfRelevant, + verifyDiscoverPageState, +} from './utils/saved_search'; + +import { generateAllTestConfigurations } from './utils/saved_queries'; + +// This spec assumes data.savedQueriesNewUI.enabled is false. + +export const runSavedQueriesOldUITests = () => { + describe('saved queries old UI', () => { + before(() => { + // Load test data + cy.setupTestData( + SECONDARY_ENGINE.url, + [ + `cypress/fixtures/query_enhancements/data-logs-1/${INDEX_WITH_TIME_1}.mapping.json`, + `cypress/fixtures/query_enhancements/data-logs-2/${INDEX_WITH_TIME_2}.mapping.json`, + ], + [ + `cypress/fixtures/query_enhancements/data-logs-1/${INDEX_WITH_TIME_1}.data.ndjson`, + `cypress/fixtures/query_enhancements/data-logs-2/${INDEX_WITH_TIME_2}.data.ndjson`, + ] + ); + // Add data source + cy.addDataSource({ + name: datasourceName, + url: 'http://opensearch-node:9200', + authType: 'no_auth', + }); + + // Create workspace + cy.deleteWorkspaceByName(workspaceName); + cy.visit('/app/home'); + cy.createInitialWorkspaceWithDataSource(datasourceName, workspaceName); + cy.createWorkspaceIndexPatterns({ + workspaceName: workspaceName, + indexPattern: INDEX_PATTERN_WITH_TIME.replace('*', ''), + timefieldName: 'timestamp', + dataSource: datasourceName, + isEnhancement: true, + }); + }); + + after(() => { + cy.deleteWorkspaceByName(workspaceName); + // // TODO: Modify deleteIndex to handle an array of index and remove hard code + cy.deleteDataSourceByName(datasourceName); + cy.deleteIndex(INDEX_WITH_TIME_1); + cy.deleteIndex(INDEX_WITH_TIME_2); + }); + + const testConfigurations = generateAllTestConfigurations(); + testConfigurations.forEach((config) => { + it(`should successfully create a saved query for ${config.testName}`, () => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + cy.setDataset(config.dataset, datasourceName, config.datasetType); + + cy.setQueryLanguage(config.language); + setDatePickerDatesAndSearchIfRelevant(config.language); + + setSearchConfigurations(config); + verifyDiscoverPageState(config); + cy.saveQueryOldUI(config.saveName); + }); + }); + it('should see all saved queries', () => { + cy.getElementByTestId('saved-query-management-popover-button').click({ + force: true, + }); + + //Wait for queries to load + cy.wait(2000); + + testConfigurations.forEach((config) => { + cy.getElementByTestId('saved-query-management-popover') + .contains(config.saveName) + .should('exist'); + }); + }); + }); +}; + +runSavedQueriesOldUITests(); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/saved_queries.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/saved_queries.js new file mode 100644 index 000000000000..a31a3783f8d5 --- /dev/null +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/saved_queries.js @@ -0,0 +1,207 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + DatasetTypes, + DATASOURCE_NAME, + INDEX_PATTERN_WITH_TIME, + INDEX_WITH_TIME_1, + QueryLanguages, + WORKSPACE_NAME, +} from '../../../../../../utils/apps/query_enhancements/constants'; + +const randomString = Math.random().toString(36); + +/** + * randomized workspace name + * @constant + * @type {string} + * @default + */ +export const workspaceName = `${WORKSPACE_NAME}-${randomString.substring(7)}`; + +/** + * randomized datasource name + * @constant + * @type {string} + * @default + */ +export const datasourceName = `${DATASOURCE_NAME}-${randomString.substring(0, 18)}`; + +/** + * Returns the query string to use for a given dataset+language + * @param {string} dataset - the dataset name to use + * @param {QueryEnhancementLanguage} language - the name of query language + * @returns {string} + */ +const getQueryString = (dataset, language) => { + switch (language) { + case QueryLanguages.DQL.name: + return 'bytes_transferred > 9950'; + case QueryLanguages.Lucene.name: + return 'bytes_transferred: {9950 TO *}'; + case QueryLanguages.SQL.name: + return `SELECT * FROM ${dataset} WHERE bytes_transferred > 9950`; + case QueryLanguages.PPL.name: + return `source = ${dataset} | where bytes_transferred > 9950`; + default: + throw new Error(`getQueryString encountered unsupported language: ${language}`); + } +}; + +/** + * Returns the expected hit count, if relevant, for the provided datasetType + language + * @param {QueryEnhancementDataset} datasetType - the type of the dataset + * @param {QueryEnhancementLanguage} language - the query language name + * @returns {number|undefined} + */ +const getExpectedHitCount = (datasetType, language) => { + switch (datasetType) { + case DatasetTypes.INDEX_PATTERN.name: + switch (language) { + case QueryLanguages.DQL.name: + return 28; + case QueryLanguages.Lucene.name: + return 28; + case QueryLanguages.SQL.name: + return undefined; + case QueryLanguages.PPL.name: + // TODO: Update this to 101 once Histogram is supported on 2.17 + return undefined; + default: + throw new Error( + `getExpectedHitCount encountered unsupported language for ${datasetType}: ${language}` + ); + } + case DatasetTypes.INDEXES.name: + switch (language) { + case QueryLanguages.SQL.name: + return undefined; + case QueryLanguages.PPL.name: + // TODO: Update this to 50 once Histogram is supported on 2.17 + return undefined; + default: + throw new Error( + `getExpectedHitCount encountered unsupported language for ${datasetType}: ${language}` + ); + } + default: + throw new Error(`getExpectedHitCount encountered unsupported datasetType: ${datasetType}`); + } +}; + +/** + * returns an array of data present in the results table to check against. This is used to ensure that sorting is working as expected + * @param {QueryEnhancementDataset} datasetType - the type of the dataset + * @param {QueryEnhancementLanguage} language - the query language name + * @returns {[[number,string]]|*[]} An array of table data. For each element, 0th index is the index of the table cell, and 1st index is the value in that table cell + */ +const getSampleTableData = (datasetType, language) => { + switch (datasetType) { + case DatasetTypes.INDEX_PATTERN.name: + switch (language) { + case QueryLanguages.DQL.name: + return [ + [1, '9,998'], + [2, 'Phyllis Dach'], + ]; + case QueryLanguages.Lucene.name: + return [ + [1, '9,998'], + [2, 'Phyllis Dach'], + ]; + case QueryLanguages.SQL.name: + return []; + case QueryLanguages.PPL.name: + return []; + default: + throw new Error( + `getSampleTableData encountered unsupported language for ${datasetType}: ${language}` + ); + } + case DatasetTypes.INDEXES.name: + switch (language) { + case QueryLanguages.SQL.name: + return []; + case QueryLanguages.PPL.name: + return []; + default: + throw new Error( + `getSampleTableData encountered unsupported language for ${datasetType}: ${language}` + ); + } + default: + throw new Error(`getSampleTableData encountered unsupported datasetType: ${datasetType}`); + } +}; + +/** + * The configurations needed for saved search tests + * @typedef {Object} SavedSearchTestConfig + * @property {string} dataset - the dataset name to use + * @property {QueryEnhancementDataset} datasetType - the type of dataset + * @property {QueryEnhancementLanguage} language - the name of query language as it appears in the dashboard app + * @property {string} apiLanguage - the name of query language as recognized by OpenSearch API + * @property {string} saveName - the name to use when saving the saved search + * @property {string} testName - the phrase to add to the test case's title + * @property {boolean} filters - whether the language supports filtering + * @property {boolean} histogram - whether the language supports histogram + * @property {boolean} selectFields - whether the language supports selecting fields to view data + * @property {boolean} sort - whether the language supports sorting by fields + * @property {string} queryString - the query to use for saved search associated with the language + * @property {number|undefined} hitCount - the hitCount of the applied search config, if relevant + * @property {[[number,string]]|*[]} sampleTableData - an array of some table data to test against to ensure that sorting is working as expected + */ + +/** + * Returns the SavedSearchTestConfig for the provided dataset, datasetType, and language + * @param {string} dataset - the dataset name + * @param {QueryEnhancementDataset} datasetType - the type of the dataset + * @param {QueryEnhancementLanguageData} language - the relevant data for the query language to use + * @returns {SavedSearchTestConfig} + */ +const generateTestConfiguration = (dataset, datasetType, language) => { + const baseConfig = { + dataset, + datasetType, + language: language.name, + apiLanguage: language.apiName, + saveName: `${language.name}-${datasetType}`, + testName: `${language.name}-${datasetType}`, + ...language.supports, + }; + + return { + ...baseConfig, + queryString: getQueryString(dataset, language.name), + hitCount: getExpectedHitCount(datasetType, language.name), + sampleTableData: getSampleTableData(datasetType, language.name), + }; +}; + +/** + * Returns an array of test configurations for every query language + dataset permutation + * @returns {SavedSearchTestConfig[]} + */ +export const generateAllTestConfigurations = () => { + return Object.values(DatasetTypes).flatMap((dataset) => + dataset.supportedLanguages.map((language) => { + let datasetToUse; + switch (dataset.name) { + case DatasetTypes.INDEX_PATTERN.name: + datasetToUse = INDEX_PATTERN_WITH_TIME; + break; + case DatasetTypes.INDEXES.name: + datasetToUse = INDEX_WITH_TIME_1; + break; + default: + throw new Error( + `generateAllTestConfigurations encountered unsupported dataset: ${dataset.name}` + ); + } + return generateTestConfiguration(datasetToUse, dataset.name, language); + }) + ); +}; diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index 4e7395692030..1cd410c74d45 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -125,6 +125,19 @@ Cypress.Commands.add( } ); +Cypress.Commands.add('saveQueryOldUI', (name, description = ' ') => { + cy.whenTestIdNotFound('saved-query-management-popover', () => { + cy.getElementByTestId('saved-query-management-popover-button').click(); + }); + cy.getElementByTestId('saved-query-management-save-button').click(); + + cy.getElementByTestId('saveQueryFormTitle').type(name); + cy.getElementByTestId('saveQueryFormDescription').type(description); + + cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); + cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); +}); + Cypress.Commands.add('saveQuery', (name, description) => { cy.whenTestIdNotFound('saved-query-management-popover', () => { cy.getElementByTestId('saved-query-management-popover-button').click(); @@ -135,7 +148,7 @@ Cypress.Commands.add('saveQuery', (name, description) => { cy.getElementByTestId('saveQueryFormDescription').type(description); }); -Cypress.Commands.add('loadSaveQuery', (name) => { +Cypress.Commands.add('loadSaveQueryOldUI', (name) => { cy.getElementByTestId('saved-query-management-popover-button').click({ force: true, }); @@ -143,7 +156,7 @@ Cypress.Commands.add('loadSaveQuery', (name) => { cy.get(`[data-test-subj~="load-saved-query-${name}-button"]`).should('be.visible').click(); }); -Cypress.Commands.add('clearSaveQuery', () => { +Cypress.Commands.add('clearSaveQueryOldUI', () => { cy.whenTestIdNotFound('saved-query-management-popover', () => { cy.getElementByTestId('saved-query-management-popover-button').click(); }); @@ -151,7 +164,7 @@ Cypress.Commands.add('clearSaveQuery', () => { cy.getElementByTestId('saved-query-management-clear-button').click(); }); -Cypress.Commands.add('deleteSaveQuery', (name) => { +Cypress.Commands.add('deleteSaveQueryOldUI', (name) => { cy.getElementByTestId('saved-query-management-popover-button').click(); cy.get(`[data-test-subj~="delete-saved-query-${name}-button"]`).click({ diff --git a/cypress/utils/apps/query_enhancements/commands.js b/cypress/utils/apps/query_enhancements/commands.js index 35bc746f8929..255c24ee4fa0 100644 --- a/cypress/utils/apps/query_enhancements/commands.js +++ b/cypress/utils/apps/query_enhancements/commands.js @@ -100,12 +100,18 @@ Cypress.Commands.add('deleteDataSourceByName', (dataSourceName) => { // Navigate to the dataSource Management page cy.visit('app/dataSources'); + // Wait til the page is loaded (waitForLoader and just getting an element doesn't work) + cy.wait(2000); + // Find the anchor text corresponding to specified dataSource - cy.get('a').contains(dataSourceName).click(); + cy.get('a').contains(dataSourceName).click({ force: true }); + + // Wait til the page is loaded (waitForLoader and just getting an element doesn't work) + cy.wait(2000); // Delete the dataSource connection - cy.getElementByTestId('editDatasourceDeleteIcon').click(); - cy.getElementByTestId('confirmModalConfirmButton').click(); + cy.getElementByTestId('editDatasourceDeleteIcon').click({ force: true }); + cy.getElementByTestId('confirmModalConfirmButton').click({ force: true }); }); // Deletes all data sources. This command should only be used for convenience during development From af1352dbf1ba6fbdcf9a628fc5b18182ffedc400 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Wed, 8 Jan 2025 21:40:09 -0800 Subject: [PATCH 02/36] Add comment about cleaning up saved queries Signed-off-by: Argus Li --- .../apps/query_enhancements/saved_queries_old_ui.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js index 98ddf0a54925..071d6ade59d7 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js @@ -58,6 +58,7 @@ export const runSavedQueriesOldUITests = () => { }); after(() => { + // No need to explicitly delete all saved queries as deleting the workspace will delete associated saved queries cy.deleteWorkspaceByName(workspaceName); // // TODO: Modify deleteIndex to handle an array of index and remove hard code cy.deleteDataSourceByName(datasourceName); From d6a713b52c18e73a2736d1bf010af1858950d3be Mon Sep 17 00:00:00 2001 From: Argus Li Date: Wed, 8 Jan 2025 21:40:36 -0800 Subject: [PATCH 03/36] Add data-test-subj for save query new ui Signed-off-by: Argus Li --- .../saved_query_management/saved_query_management_component.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx b/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx index dadc2854712e..5932a96e122f 100644 --- a/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx +++ b/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx @@ -225,6 +225,7 @@ export function SavedQueryManagementComponent({ label={i18n.translate('data.saved_query_management.save_query_item_label', { defaultMessage: 'Save query', })} + data-test-subj="saved-query-management-save-button" iconType="save" onClick={() => { closeMenuPopover(); From d6e0785474622e1d52618a39cd1e3c67438c3284 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Thu, 9 Jan 2025 09:11:34 -0800 Subject: [PATCH 04/36] Add data-test-subj for save query button for new ui Signed-off-by: Argus Li --- src/plugins/data/public/ui/saved_query_form/helpers.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/plugins/data/public/ui/saved_query_form/helpers.tsx b/src/plugins/data/public/ui/saved_query_form/helpers.tsx index ad3de3acde3f..f057326d3f1b 100644 --- a/src/plugins/data/public/ui/saved_query_form/helpers.tsx +++ b/src/plugins/data/public/ui/saved_query_form/helpers.tsx @@ -280,7 +280,12 @@ export function useSaveQueryFormContent({ - + {i18n.translate('data.search.searchBar.savedQueryFlyoutFormSaveButtonText', { defaultMessage: '{saveText}', values: { saveText: savedQuery ? 'Save changes' : 'Save' }, From a15bba2c9f461a024c409f911806fc9102892f70 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Thu, 9 Jan 2025 10:03:06 -0800 Subject: [PATCH 05/36] Add data-test-subj for open query button in query management popover Signed-off-by: Argus Li --- .../saved_query_management/saved_query_management_component.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx b/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx index 5932a96e122f..824e8d045e38 100644 --- a/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx +++ b/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx @@ -247,6 +247,7 @@ export function SavedQueryManagementComponent({ label={i18n.translate('data.saved_query_management.open_query_item_label', { defaultMessage: 'Open query', })} + data-test-subj="saved-query-management-open-button" iconType="folderOpen" onClick={() => { closeMenuPopover(); From 47fe9a7e28478808301454a2065959315af05bf1 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Thu, 9 Jan 2025 10:11:13 -0800 Subject: [PATCH 06/36] Add new ui spec to test list saved queries Signed-off-by: Argus Li --- .../query_enhancements/saved_queries.spec.js | 108 ++++++++++++++++++ cypress/utils/apps/data_explorer/commands.js | 5 +- 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js new file mode 100644 index 000000000000..737b799474e9 --- /dev/null +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js @@ -0,0 +1,108 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + INDEX_PATTERN_WITH_TIME, + INDEX_WITH_TIME_1, + INDEX_WITH_TIME_2, + SECONDARY_ENGINE, +} from '../../../../../utils/constants'; + +import { + workspaceName, + datasourceName, + setSearchConfigurations, + setDatePickerDatesAndSearchIfRelevant, + verifyDiscoverPageState, +} from './utils/saved_search'; + +import { generateAllTestConfigurations } from './utils/saved_queries'; + +// This spec assumes data.savedQueriesNewUI.enabled is true. + +export const runSavedQueriesNewUITests = () => { + describe('saved queries new UI', () => { + before(() => { + // Load test data + cy.setupTestData( + SECONDARY_ENGINE.url, + [ + `cypress/fixtures/query_enhancements/data-logs-1/${INDEX_WITH_TIME_1}.mapping.json`, + `cypress/fixtures/query_enhancements/data-logs-2/${INDEX_WITH_TIME_2}.mapping.json`, + ], + [ + `cypress/fixtures/query_enhancements/data-logs-1/${INDEX_WITH_TIME_1}.data.ndjson`, + `cypress/fixtures/query_enhancements/data-logs-2/${INDEX_WITH_TIME_2}.data.ndjson`, + ] + ); + // Add data source + cy.addDataSource({ + name: datasourceName, + url: 'http://opensearch-node:9200', + authType: 'no_auth', + }); + + // Create workspace + cy.deleteWorkspaceByName(workspaceName); + cy.visit('/app/home'); + cy.createInitialWorkspaceWithDataSource(datasourceName, workspaceName); + cy.createWorkspaceIndexPatterns({ + workspaceName: workspaceName, + indexPattern: INDEX_PATTERN_WITH_TIME.replace('*', ''), + timefieldName: 'timestamp', + dataSource: datasourceName, + isEnhancement: true, + }); + }); + + after(() => { + // No need to explicitly delete all saved queries as deleting the workspace will delete associated saved queries + cy.deleteWorkspaceByName(workspaceName); + // // TODO: Modify deleteIndex to handle an array of index and remove hard code + cy.deleteDataSourceByName(datasourceName); + cy.deleteIndex(INDEX_WITH_TIME_1); + cy.deleteIndex(INDEX_WITH_TIME_2); + }); + + const testConfigurations = generateAllTestConfigurations(); + testConfigurations.forEach((config) => { + it(`should successfully create a saved query for ${config.testName}`, () => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + cy.setDataset(config.dataset, datasourceName, config.datasetType); + + cy.setQueryLanguage(config.language); + setDatePickerDatesAndSearchIfRelevant(config.language); + + setSearchConfigurations(config); + verifyDiscoverPageState(config); + cy.saveQuery(config.saveName); + }); + }); + it('should see all saved queries', () => { + cy.getElementByTestId('saved-query-management-popover-button').click({ + force: true, + }); + + cy.getElementByTestId('saved-query-management-open-button').click(); + + //Wait for queries to load + cy.wait(2000); + + testConfigurations.forEach((config) => { + cy.getElementByTestId('euiFlyoutCloseButton') + .parent() + .contains(config.saveName) + .should('exist'); + }); + }); + }); +}; + +runSavedQueriesNewUITests(); diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index 1cd410c74d45..5c9cc62a36ad 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -138,7 +138,7 @@ Cypress.Commands.add('saveQueryOldUI', (name, description = ' ') => { cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); }); -Cypress.Commands.add('saveQuery', (name, description) => { +Cypress.Commands.add('saveQuery', (name, description = ' ') => { cy.whenTestIdNotFound('saved-query-management-popover', () => { cy.getElementByTestId('saved-query-management-popover-button').click(); }); @@ -146,6 +146,9 @@ Cypress.Commands.add('saveQuery', (name, description) => { cy.getElementByTestId('saveQueryFormTitle').type(name); cy.getElementByTestId('saveQueryFormDescription').type(description); + + cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); + cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); }); Cypress.Commands.add('loadSaveQueryOldUI', (name) => { From 49a9352a35702bcbfb55fa0f626783dce1804a25 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Thu, 9 Jan 2025 10:17:04 -0800 Subject: [PATCH 07/36] Fix DataSource url Signed-off-by: Argus Li --- .../apps/query_enhancements/saved_queries.spec.js | 2 +- .../apps/query_enhancements/saved_queries_old_ui.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js index 737b799474e9..5dc4696f59b9 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js @@ -40,7 +40,7 @@ export const runSavedQueriesNewUITests = () => { // Add data source cy.addDataSource({ name: datasourceName, - url: 'http://opensearch-node:9200', + url: SECONDARY_ENGINE.url, authType: 'no_auth', }); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js index 071d6ade59d7..519a29583bb1 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js @@ -40,7 +40,7 @@ export const runSavedQueriesOldUITests = () => { // Add data source cy.addDataSource({ name: datasourceName, - url: 'http://opensearch-node:9200', + url: SECONDARY_ENGINE.url, authType: 'no_auth', }); From 00b3f60dad640e3031da6134416a7229acdff9dd Mon Sep 17 00:00:00 2001 From: "opensearch-changeset-bot[bot]" <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com> Date: Thu, 9 Jan 2025 18:18:25 +0000 Subject: [PATCH 08/36] Changeset file for PR #9166 created/updated --- changelogs/fragments/9166.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/fragments/9166.yml diff --git a/changelogs/fragments/9166.yml b/changelogs/fragments/9166.yml new file mode 100644 index 000000000000..26d9ddf7d3cd --- /dev/null +++ b/changelogs/fragments/9166.yml @@ -0,0 +1,2 @@ +test: +- Add cypress integration test for the old and new UI view saved queries. ([#9166](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/9166)) \ No newline at end of file From edb8f9f45d3ba7dda9be26ddbda87e02bba062fb Mon Sep 17 00:00:00 2001 From: Argus Li Date: Fri, 10 Jan 2025 12:46:40 -0800 Subject: [PATCH 09/36] Address Justin's comments. Signed-off-by: Argus Li --- .../apps/query_enhancements/saved_queries.spec.js | 8 ++------ .../query_enhancements/saved_queries_old_ui.spec.js | 8 ++------ cypress/utils/apps/data_explorer/commands.js | 4 ++-- cypress/utils/apps/query_enhancements/commands.js | 10 ++-------- 4 files changed, 8 insertions(+), 22 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js index 5dc4696f59b9..ccd4125ccd7c 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js @@ -85,16 +85,12 @@ export const runSavedQueriesNewUITests = () => { cy.saveQuery(config.saveName); }); }); + it('should see all saved queries', () => { - cy.getElementByTestId('saved-query-management-popover-button').click({ - force: true, - }); + cy.getElementByTestId('saved-query-management-popover-button').click(); cy.getElementByTestId('saved-query-management-open-button').click(); - //Wait for queries to load - cy.wait(2000); - testConfigurations.forEach((config) => { cy.getElementByTestId('euiFlyoutCloseButton') .parent() diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js index 519a29583bb1..f4ac07ddcf6e 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js @@ -85,13 +85,9 @@ export const runSavedQueriesOldUITests = () => { cy.saveQueryOldUI(config.saveName); }); }); - it('should see all saved queries', () => { - cy.getElementByTestId('saved-query-management-popover-button').click({ - force: true, - }); - //Wait for queries to load - cy.wait(2000); + it('should see all saved queries', () => { + cy.getElementByTestId('saved-query-management-popover-button').click(); testConfigurations.forEach((config) => { cy.getElementByTestId('saved-query-management-popover') diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index 5c9cc62a36ad..32f6f005ca93 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -134,7 +134,7 @@ Cypress.Commands.add('saveQueryOldUI', (name, description = ' ') => { cy.getElementByTestId('saveQueryFormTitle').type(name); cy.getElementByTestId('saveQueryFormDescription').type(description); - cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); + cy.getElementByTestId('savedQueryFormSaveButton').click(); cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); }); @@ -147,7 +147,7 @@ Cypress.Commands.add('saveQuery', (name, description = ' ') => { cy.getElementByTestId('saveQueryFormTitle').type(name); cy.getElementByTestId('saveQueryFormDescription').type(description); - cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); + cy.getElementByTestId('savedQueryFormSaveButton').click(); cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); }); diff --git a/cypress/utils/apps/query_enhancements/commands.js b/cypress/utils/apps/query_enhancements/commands.js index 255c24ee4fa0..977fbaa44ef1 100644 --- a/cypress/utils/apps/query_enhancements/commands.js +++ b/cypress/utils/apps/query_enhancements/commands.js @@ -100,18 +100,12 @@ Cypress.Commands.add('deleteDataSourceByName', (dataSourceName) => { // Navigate to the dataSource Management page cy.visit('app/dataSources'); - // Wait til the page is loaded (waitForLoader and just getting an element doesn't work) - cy.wait(2000); - // Find the anchor text corresponding to specified dataSource cy.get('a').contains(dataSourceName).click({ force: true }); - // Wait til the page is loaded (waitForLoader and just getting an element doesn't work) - cy.wait(2000); - // Delete the dataSource connection - cy.getElementByTestId('editDatasourceDeleteIcon').click({ force: true }); - cy.getElementByTestId('confirmModalConfirmButton').click({ force: true }); + cy.getElementByTestId('editDatasourceDeleteIcon').click(); + cy.getElementByTestId('confirmModalConfirmButton').click(); }); // Deletes all data sources. This command should only be used for convenience during development From 4ae05a42f9d303513d1fbd3c23f1f57903054b4f Mon Sep 17 00:00:00 2001 From: Argus Li Date: Fri, 10 Jan 2025 13:20:20 -0800 Subject: [PATCH 10/36] Remove final force. Signed-off-by: Argus Li --- cypress/utils/apps/query_enhancements/commands.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cypress/utils/apps/query_enhancements/commands.js b/cypress/utils/apps/query_enhancements/commands.js index 977fbaa44ef1..b2c3aaf57eb6 100644 --- a/cypress/utils/apps/query_enhancements/commands.js +++ b/cypress/utils/apps/query_enhancements/commands.js @@ -127,10 +127,7 @@ Cypress.Commands.add('deleteAllDataSources', () => { cy.log('No data sources to delete'); } else if (hasDataSources) { cy.log('Need to clean out data sources'); - cy.getElementByTestId('checkboxSelectAll') - .should('exist') - .should('not.be.disabled') - .check({ force: true }); + cy.getElementByTestId('checkboxSelectAll').should('exist').should('not.be.disabled').check(); cy.getElementByTestId('deleteDataSourceConnections').should('be.visible').click(); From b411dd0026309904eaf10da10a190a462e48ee4c Mon Sep 17 00:00:00 2001 From: Argus Li Date: Fri, 10 Jan 2025 19:52:43 -0800 Subject: [PATCH 11/36] Fix final force. Signed-off-by: Argus Li --- cypress/utils/apps/query_enhancements/commands.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cypress/utils/apps/query_enhancements/commands.js b/cypress/utils/apps/query_enhancements/commands.js index b2c3aaf57eb6..35bc746f8929 100644 --- a/cypress/utils/apps/query_enhancements/commands.js +++ b/cypress/utils/apps/query_enhancements/commands.js @@ -101,7 +101,7 @@ Cypress.Commands.add('deleteDataSourceByName', (dataSourceName) => { cy.visit('app/dataSources'); // Find the anchor text corresponding to specified dataSource - cy.get('a').contains(dataSourceName).click({ force: true }); + cy.get('a').contains(dataSourceName).click(); // Delete the dataSource connection cy.getElementByTestId('editDatasourceDeleteIcon').click(); @@ -127,7 +127,10 @@ Cypress.Commands.add('deleteAllDataSources', () => { cy.log('No data sources to delete'); } else if (hasDataSources) { cy.log('Need to clean out data sources'); - cy.getElementByTestId('checkboxSelectAll').should('exist').should('not.be.disabled').check(); + cy.getElementByTestId('checkboxSelectAll') + .should('exist') + .should('not.be.disabled') + .check({ force: true }); cy.getElementByTestId('deleteDataSourceConnections').should('be.visible').click(); From eeb0c630416faa7b68aa3ef3e396c159458613f0 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Mon, 13 Jan 2025 09:17:33 -0800 Subject: [PATCH 12/36] Move utils to Suchit's suggested location, fix comments Signed-off-by: Argus Li --- .../query_enhancements/field_display_filtering.spec.js | 2 +- .../apps/query_enhancements/saved_queries.spec.js | 4 ++-- .../query_enhancements/saved_queries_old_ui.spec.js | 4 ++-- .../apps/query_enhancements/saved_search.spec.js | 2 +- .../query_enhancements}/field_display_filtering.js | 0 .../apps/query_enhancements}/saved_queries.js | 10 +++++----- .../apps/query_enhancements}/saved_search.js | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) rename cypress/{integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils => utils/apps/query_enhancements}/field_display_filtering.js (100%) rename cypress/{integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils => utils/apps/query_enhancements}/saved_queries.js (96%) rename cypress/{integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils => utils/apps/query_enhancements}/saved_search.js (99%) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/field_display_filtering.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/field_display_filtering.spec.js index 726cb3d4fd4a..37e31917664a 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/field_display_filtering.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/field_display_filtering.spec.js @@ -12,7 +12,7 @@ import { END_TIME, DATASET_CONFIGS, } from '../../../../../utils/apps/constants'; -import * as dataExplorer from '../../../../../integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/field_display_filtering.js'; +import * as dataExplorer from '../../../../../utils/apps/query_enhancements/field_display_filtering.js'; import { SECONDARY_ENGINE, BASE_PATH } from '../../../../../utils/constants'; import { NEW_SEARCH_BUTTON } from '../../../../../utils/dashboards/data_explorer/elements.js'; diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js index ccd4125ccd7c..8af02914d157 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js @@ -16,9 +16,9 @@ import { setSearchConfigurations, setDatePickerDatesAndSearchIfRelevant, verifyDiscoverPageState, -} from './utils/saved_search'; +} from '../../../../../utils/apps/query_enhancements/saved_search'; -import { generateAllTestConfigurations } from './utils/saved_queries'; +import { generateAllTestConfigurations } from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is true. diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js index f4ac07ddcf6e..c163b144f8df 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js @@ -16,9 +16,9 @@ import { setSearchConfigurations, setDatePickerDatesAndSearchIfRelevant, verifyDiscoverPageState, -} from './utils/saved_search'; +} from '../../../../../utils/apps/query_enhancements/saved_search'; -import { generateAllTestConfigurations } from './utils/saved_queries'; +import { generateAllTestConfigurations } from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is false. diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_search.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_search.spec.js index f4cbdb228850..f2320148b98f 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_search.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_search.spec.js @@ -19,7 +19,7 @@ import { verifyDiscoverPageState, verifySavedSearchInAssetsPage, postRequestSaveSearch, -} from './utils/saved_search'; +} from '../../../../../utils/apps/query_enhancements/saved_search'; export const runSavedSearchTests = () => { describe('saved search', () => { diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/field_display_filtering.js b/cypress/utils/apps/query_enhancements/field_display_filtering.js similarity index 100% rename from cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/field_display_filtering.js rename to cypress/utils/apps/query_enhancements/field_display_filtering.js diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/saved_queries.js b/cypress/utils/apps/query_enhancements/saved_queries.js similarity index 96% rename from cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/saved_queries.js rename to cypress/utils/apps/query_enhancements/saved_queries.js index a31a3783f8d5..38e95211474f 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/saved_queries.js +++ b/cypress/utils/apps/query_enhancements/saved_queries.js @@ -10,7 +10,7 @@ import { INDEX_WITH_TIME_1, QueryLanguages, WORKSPACE_NAME, -} from '../../../../../../utils/apps/query_enhancements/constants'; +} from './constants'; const randomString = Math.random().toString(36); @@ -138,20 +138,20 @@ const getSampleTableData = (datasetType, language) => { }; /** - * The configurations needed for saved search tests + * The configurations needed for saved queries tests * @typedef {Object} SavedSearchTestConfig * @property {string} dataset - the dataset name to use * @property {QueryEnhancementDataset} datasetType - the type of dataset * @property {QueryEnhancementLanguage} language - the name of query language as it appears in the dashboard app * @property {string} apiLanguage - the name of query language as recognized by OpenSearch API - * @property {string} saveName - the name to use when saving the saved search + * @property {string} saveName - the name to use when saving the saved query * @property {string} testName - the phrase to add to the test case's title * @property {boolean} filters - whether the language supports filtering * @property {boolean} histogram - whether the language supports histogram * @property {boolean} selectFields - whether the language supports selecting fields to view data * @property {boolean} sort - whether the language supports sorting by fields - * @property {string} queryString - the query to use for saved search associated with the language - * @property {number|undefined} hitCount - the hitCount of the applied search config, if relevant + * @property {string} queryString - the query to use for saved query associated with the language + * @property {number|undefined} hitCount - the hitCount of the applied query config, if relevant * @property {[[number,string]]|*[]} sampleTableData - an array of some table data to test against to ensure that sorting is working as expected */ diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/saved_search.js b/cypress/utils/apps/query_enhancements/saved_search.js similarity index 99% rename from cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/saved_search.js rename to cypress/utils/apps/query_enhancements/saved_search.js index d95db5ef526e..47d84ad4a1e3 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/utils/saved_search.js +++ b/cypress/utils/apps/query_enhancements/saved_search.js @@ -12,7 +12,7 @@ import { QueryLanguages, START_TIME, WORKSPACE_NAME, -} from '../../../../../../utils/apps/query_enhancements/constants'; +} from './constants'; const randomString = Math.random().toString(36); From 3c2b2eca11474bb61dd4f1924cb80755220e52d5 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Mon, 13 Jan 2025 12:09:05 -0800 Subject: [PATCH 13/36] Rename specs, change cypress workflow to use new save query ui, merge old ui and new ui commands Signed-off-by: Argus Li --- .github/workflows/cypress_workflow.yml | 2 +- ...s.spec.js => saved_queries_flyout.spec.js} | 6 ++--- ....spec.js => saved_queries_popover.spec.js} | 9 ++++---- cypress/utils/apps/data_explorer/commands.js | 22 +++++-------------- 4 files changed, 14 insertions(+), 25 deletions(-) rename cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/{saved_queries.spec.js => saved_queries_flyout.spec.js} (96%) rename cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/{saved_queries_old_ui.spec.js => saved_queries_popover.spec.js} (89%) diff --git a/.github/workflows/cypress_workflow.yml b/.github/workflows/cypress_workflow.yml index 58e1dbfe9388..083373c4048b 100644 --- a/.github/workflows/cypress_workflow.yml +++ b/.github/workflows/cypress_workflow.yml @@ -90,7 +90,7 @@ jobs: options: --user 1001 env: START_CMD: ${{ matrix.config == 'query_enhanced' && - 'node scripts/opensearch_dashboards --dev --no-base-path --no-watch --savedObjects.maxImportPayloadBytes=10485760 --server.maxPayloadBytes=1759977 --logging.json=false --data.search.aggs.shardDelay.enabled=true --csp.warnLegacyBrowsers=false --uiSettings.overrides["query:enhancements:enabled"]=true --uiSettings.overrides[''home:useNewHomePage'']=true --data_source.enabled=true --workspace.enabled=true --opensearch.ignoreVersionMismatch=true' || + 'node scripts/opensearch_dashboards --dev --no-base-path --no-watch --savedObjects.maxImportPayloadBytes=10485760 --server.maxPayloadBytes=1759977 --logging.json=false --data.search.aggs.shardDelay.enabled=true --csp.warnLegacyBrowsers=false --uiSettings.overrides["query:enhancements:enabled"]=true --uiSettings.overrides[''home:useNewHomePage'']=true --data_source.enabled=true --workspace.enabled=true --opensearch.ignoreVersionMismatch=true --data.savedQueriesNewUI.enabled=true' || matrix.config == 'dashboard' && 'node scripts/opensearch_dashboards --dev --no-base-path --no-watch --savedObjects.maxImportPayloadBytes=10485760 --server.maxPayloadBytes=1759977 --logging.json=false --data.search.aggs.shardDelay.enabled=true' || 'node ../scripts/opensearch_dashboards --dev --no-base-path --no-watch --savedObjects.maxImportPayloadBytes=10485760 --server.maxPayloadBytes=1759977 --logging.json=false --data.search.aggs.shardDelay.enabled=true --csp.warnLegacyBrowsers=false --uiSettings.overrides["query:enhancements:enabled"]=false' }} diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js similarity index 96% rename from cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js rename to cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js index 8af02914d157..f9357ba4f9fe 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js @@ -22,8 +22,8 @@ import { generateAllTestConfigurations } from '../../../../../utils/apps/query_e // This spec assumes data.savedQueriesNewUI.enabled is true. -export const runSavedQueriesNewUITests = () => { - describe('saved queries new UI', () => { +export const runSavedQueriesFlyoutUITests = () => { + describe('saved queries flyout UI', () => { before(() => { // Load test data cy.setupTestData( @@ -101,4 +101,4 @@ export const runSavedQueriesNewUITests = () => { }); }; -runSavedQueriesNewUITests(); +runSavedQueriesFlyoutUITests(); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js similarity index 89% rename from cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js rename to cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js index c163b144f8df..9e717edc0b29 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_old_ui.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js @@ -21,9 +21,10 @@ import { import { generateAllTestConfigurations } from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is false. +// These tests will not be run until the older legacy tests are migrated https://github.com/opensearch-project/OpenSearch-Dashboards/pull/9166#discussion_r1913687440 -export const runSavedQueriesOldUITests = () => { - describe('saved queries old UI', () => { +export const runSavedQueriesPopoverUITests = () => { + describe.skip('saved queries popover UI', () => { before(() => { // Load test data cy.setupTestData( @@ -82,7 +83,7 @@ export const runSavedQueriesOldUITests = () => { setSearchConfigurations(config); verifyDiscoverPageState(config); - cy.saveQueryOldUI(config.saveName); + cy.saveQuery(config.saveName, ' ', false); }); }); @@ -98,4 +99,4 @@ export const runSavedQueriesOldUITests = () => { }); }; -runSavedQueriesOldUITests(); +runSavedQueriesPopoverUITests(); diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index 32f6f005ca93..3c58ba56629b 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -125,7 +125,8 @@ Cypress.Commands.add( } ); -Cypress.Commands.add('saveQueryOldUI', (name, description = ' ') => { +// eslint-disable-next-line no-unused-vars +Cypress.Commands.add('saveQuery', (name, description = ' ', savedQueriesNewUIEnabled = true) => { cy.whenTestIdNotFound('saved-query-management-popover', () => { cy.getElementByTestId('saved-query-management-popover-button').click(); }); @@ -138,20 +139,7 @@ Cypress.Commands.add('saveQueryOldUI', (name, description = ' ') => { cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); }); -Cypress.Commands.add('saveQuery', (name, description = ' ') => { - cy.whenTestIdNotFound('saved-query-management-popover', () => { - cy.getElementByTestId('saved-query-management-popover-button').click(); - }); - cy.getElementByTestId('saved-query-management-save-button').click(); - - cy.getElementByTestId('saveQueryFormTitle').type(name); - cy.getElementByTestId('saveQueryFormDescription').type(description); - - cy.getElementByTestId('savedQueryFormSaveButton').click(); - cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); -}); - -Cypress.Commands.add('loadSaveQueryOldUI', (name) => { +Cypress.Commands.add('loadSaveQuery', (name) => { cy.getElementByTestId('saved-query-management-popover-button').click({ force: true, }); @@ -159,7 +147,7 @@ Cypress.Commands.add('loadSaveQueryOldUI', (name) => { cy.get(`[data-test-subj~="load-saved-query-${name}-button"]`).should('be.visible').click(); }); -Cypress.Commands.add('clearSaveQueryOldUI', () => { +Cypress.Commands.add('clearSaveQuery', () => { cy.whenTestIdNotFound('saved-query-management-popover', () => { cy.getElementByTestId('saved-query-management-popover-button').click(); }); @@ -167,7 +155,7 @@ Cypress.Commands.add('clearSaveQueryOldUI', () => { cy.getElementByTestId('saved-query-management-clear-button').click(); }); -Cypress.Commands.add('deleteSaveQueryOldUI', (name) => { +Cypress.Commands.add('deleteSaveQuery', (name) => { cy.getElementByTestId('saved-query-management-popover-button').click(); cy.get(`[data-test-subj~="delete-saved-query-${name}-button"]`).click({ From 6297366d78d8ed328480de42fc30f35b2ca43d12 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Mon, 13 Jan 2025 16:12:25 -0800 Subject: [PATCH 14/36] fix import Signed-off-by: Argus Li --- .../apps/query_enhancements/saved_search.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_search.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_search.spec.js index 956561d00a0f..006fd737bc7f 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_search.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_search.spec.js @@ -19,6 +19,7 @@ import { verifyDiscoverPageState, verifySavedSearchInAssetsPage, postRequestSaveSearch, + updateSavedSearchAndSaveAndVerify, } from '../../../../../utils/apps/query_enhancements/saved_search'; export const runSavedSearchTests = () => { From bef2e77d1df7c292787e2c8c7da3b9b2839dc70b Mon Sep 17 00:00:00 2001 From: Argus Li Date: Thu, 16 Jan 2025 07:50:11 -0800 Subject: [PATCH 15/36] Load query Signed-off-by: Argus Li --- .../saved_queries_flyout.spec.js | 34 ++++++++++++----- cypress/utils/apps/data_explorer/commands.js | 37 ++++++++++++++----- .../apps/query_enhancements/saved_queries.js | 10 +++++ .../open_saved_query_flyout.tsx | 1 + 4 files changed, 63 insertions(+), 19 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js index f9357ba4f9fe..c8a237ae325d 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js @@ -8,17 +8,21 @@ import { INDEX_WITH_TIME_1, INDEX_WITH_TIME_2, SECONDARY_ENGINE, + START_TIME, + END_TIME, } from '../../../../../utils/constants'; import { workspaceName, datasourceName, setSearchConfigurations, - setDatePickerDatesAndSearchIfRelevant, verifyDiscoverPageState, } from '../../../../../utils/apps/query_enhancements/saved_search'; -import { generateAllTestConfigurations } from '../../../../../utils/apps/query_enhancements/saved_queries'; +import { + generateAllTestConfigurations, + setDatePickerDatesAndSearchIfRelevant, +} from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is true. @@ -40,7 +44,7 @@ export const runSavedQueriesFlyoutUITests = () => { // Add data source cy.addDataSource({ name: datasourceName, - url: SECONDARY_ENGINE.url, + url: 'http://opensearch-node:9200/', authType: 'no_auth', }); @@ -78,24 +82,36 @@ export const runSavedQueriesFlyoutUITests = () => { cy.setDataset(config.dataset, datasourceName, config.datasetType); cy.setQueryLanguage(config.language); - setDatePickerDatesAndSearchIfRelevant(config.language); + setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); setSearchConfigurations(config); verifyDiscoverPageState(config); - cy.saveQuery(config.saveName); + cy.saveQuery(config.saveName, ' ', true, true, true); }); }); it('should see all saved queries', () => { - cy.getElementByTestId('saved-query-management-popover-button').click(); + testConfigurations.forEach((config) => { + cy.getElementByTestId('discoverNewButton').click(); + setDatePickerDatesAndSearchIfRelevant( + config.language, + 'Aug 29, 2020 @ 00:00:00.000', + 'Aug 30, 2020 @ 00:00:00.000' + ); - cy.getElementByTestId('saved-query-management-open-button').click(); + cy.getElementByTestId('saved-query-management-popover-button').click(); + + cy.getElementByTestId('saved-query-management-open-button').click(); - testConfigurations.forEach((config) => { cy.getElementByTestId('euiFlyoutCloseButton') .parent() .contains(config.saveName) - .should('exist'); + .should('exist') + .click(); + + cy.getElementByTestId('open-query-action-button').click(); + + verifyDiscoverPageState(config); }); }); }); diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index 3c58ba56629b..b3fa281af861 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -126,18 +126,35 @@ Cypress.Commands.add( ); // eslint-disable-next-line no-unused-vars -Cypress.Commands.add('saveQuery', (name, description = ' ', savedQueriesNewUIEnabled = true) => { - cy.whenTestIdNotFound('saved-query-management-popover', () => { - cy.getElementByTestId('saved-query-management-popover-button').click(); - }); - cy.getElementByTestId('saved-query-management-save-button').click(); +Cypress.Commands.add( + 'saveQuery', + ( + name, + description = ' ', + savedQueriesNewUIEnabled = true, // eslint-disable-line no-unused-vars + includeFilters = true, + includeTimeFilter = false + ) => { + cy.whenTestIdNotFound('saved-query-management-popover', () => { + cy.getElementByTestId('saved-query-management-popover-button').click(); + }); + cy.getElementByTestId('saved-query-management-save-button').click(); - cy.getElementByTestId('saveQueryFormTitle').type(name); - cy.getElementByTestId('saveQueryFormDescription').type(description); + cy.getElementByTestId('saveQueryFormTitle').type(name); + cy.getElementByTestId('saveQueryFormDescription').type(description); - cy.getElementByTestId('savedQueryFormSaveButton').click(); - cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); -}); + if (includeFilters !== true) { + cy.getElementByTestId('saveQueryFormIncludeFiltersOption').click(); + } + + if (includeTimeFilter !== false) { + cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); + } + + cy.getElementByTestId('savedQueryFormSaveButton').click(); + cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); + } +); Cypress.Commands.add('loadSaveQuery', (name) => { cy.getElementByTestId('saved-query-management-popover-button').click({ diff --git a/cypress/utils/apps/query_enhancements/saved_queries.js b/cypress/utils/apps/query_enhancements/saved_queries.js index 38e95211474f..ec65eca7b4ce 100644 --- a/cypress/utils/apps/query_enhancements/saved_queries.js +++ b/cypress/utils/apps/query_enhancements/saved_queries.js @@ -12,6 +12,16 @@ import { WORKSPACE_NAME, } from './constants'; +/** + * Sets the top nav date if it is relevant for the passed language + * @param {QueryEnhancementLanguage} language - query language + */ +export const setDatePickerDatesAndSearchIfRelevant = (language, startTime, endTime) => { + if (language !== QueryLanguages.SQL.name) { + cy.setTopNavDate(startTime, endTime); + } +}; + const randomString = Math.random().toString(36); /** diff --git a/src/plugins/data/public/ui/saved_query_flyouts/open_saved_query_flyout.tsx b/src/plugins/data/public/ui/saved_query_flyouts/open_saved_query_flyout.tsx index d9c2941adc8d..b55afd023eac 100644 --- a/src/plugins/data/public/ui/saved_query_flyouts/open_saved_query_flyout.tsx +++ b/src/plugins/data/public/ui/saved_query_flyouts/open_saved_query_flyout.tsx @@ -348,6 +348,7 @@ export function OpenSavedQueryFlyout({ fill onClick={onQueryAction} data-testid="open-query-action-button" + data-test-subj="open-query-action-button" > {selectedTabId === OPEN_QUERY_TAB_ID.SAVED_QUERIES ? 'Open' : 'Copy'} query From 2cff1df47c5a8b1b8f3013eab525614b1530e622 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Thu, 16 Jan 2025 15:43:00 -0800 Subject: [PATCH 16/36] Complete load query popover and flyout Signed-off-by: Argus Li --- .../saved_queries_flyout.spec.js | 6 ++- .../saved_queries_popover.spec.js | 38 ++++++++++------ cypress/utils/apps/data_explorer/commands.js | 3 +- .../apps/query_enhancements/saved_queries.js | 43 +++++++++++++++++++ 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js index c8a237ae325d..5fbee134f484 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js @@ -16,12 +16,12 @@ import { workspaceName, datasourceName, setSearchConfigurations, - verifyDiscoverPageState, } from '../../../../../utils/apps/query_enhancements/saved_search'; import { generateAllTestConfigurations, setDatePickerDatesAndSearchIfRelevant, + verifyDiscoverPageState, } from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is true. @@ -90,7 +90,7 @@ export const runSavedQueriesFlyoutUITests = () => { }); }); - it('should see all saved queries', () => { + it('should see and load all saved queries', () => { testConfigurations.forEach((config) => { cy.getElementByTestId('discoverNewButton').click(); setDatePickerDatesAndSearchIfRelevant( @@ -111,6 +111,8 @@ export const runSavedQueriesFlyoutUITests = () => { cy.getElementByTestId('open-query-action-button').click(); + // wait for saved queries to load. + cy.wait(2000); verifyDiscoverPageState(config); }); }); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js index 9e717edc0b29..b98430739078 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js @@ -8,23 +8,27 @@ import { INDEX_WITH_TIME_1, INDEX_WITH_TIME_2, SECONDARY_ENGINE, + START_TIME, + END_TIME, } from '../../../../../utils/constants'; import { workspaceName, datasourceName, setSearchConfigurations, - setDatePickerDatesAndSearchIfRelevant, - verifyDiscoverPageState, } from '../../../../../utils/apps/query_enhancements/saved_search'; -import { generateAllTestConfigurations } from '../../../../../utils/apps/query_enhancements/saved_queries'; +import { + generateAllTestConfigurations, + setDatePickerDatesAndSearchIfRelevant, + verifyDiscoverPageState, +} from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is false. // These tests will not be run until the older legacy tests are migrated https://github.com/opensearch-project/OpenSearch-Dashboards/pull/9166#discussion_r1913687440 export const runSavedQueriesPopoverUITests = () => { - describe.skip('saved queries popover UI', () => { + describe('saved queries popover UI', () => { before(() => { // Load test data cy.setupTestData( @@ -41,7 +45,7 @@ export const runSavedQueriesPopoverUITests = () => { // Add data source cy.addDataSource({ name: datasourceName, - url: SECONDARY_ENGINE.url, + url: 'http://opensearch-node:9200/', authType: 'no_auth', }); @@ -79,21 +83,29 @@ export const runSavedQueriesPopoverUITests = () => { cy.setDataset(config.dataset, datasourceName, config.datasetType); cy.setQueryLanguage(config.language); - setDatePickerDatesAndSearchIfRelevant(config.language); + setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); setSearchConfigurations(config); verifyDiscoverPageState(config); - cy.saveQuery(config.saveName, ' ', false); + cy.saveQuery(config.saveName, ' ', false, true, true); }); }); - it('should see all saved queries', () => { - cy.getElementByTestId('saved-query-management-popover-button').click(); - + it('should see and load all saved queries', () => { testConfigurations.forEach((config) => { - cy.getElementByTestId('saved-query-management-popover') - .contains(config.saveName) - .should('exist'); + cy.getElementByTestId('discoverNewButton').click(); + setDatePickerDatesAndSearchIfRelevant( + config.language, + 'Aug 29, 2020 @ 00:00:00.000', + 'Aug 30, 2020 @ 00:00:00.000' + ); + + cy.getElementByTestId('saved-query-management-popover-button').click(); + cy.getElementByTestId('save-query-panel').contains(config.saveName).should('exist').click(); + + // wait for saved queries to load. + cy.wait(2000); + verifyDiscoverPageState(config); }); }); }); diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index b3fa281af861..91fa9a334c24 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -151,7 +151,8 @@ Cypress.Commands.add( cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); } - cy.getElementByTestId('savedQueryFormSaveButton').click(); + // The force is necessary as there is occasionally a popover that covers the button + cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); } ); diff --git a/cypress/utils/apps/query_enhancements/saved_queries.js b/cypress/utils/apps/query_enhancements/saved_queries.js index ec65eca7b4ce..c5c675fdc3c4 100644 --- a/cypress/utils/apps/query_enhancements/saved_queries.js +++ b/cypress/utils/apps/query_enhancements/saved_queries.js @@ -10,8 +10,12 @@ import { INDEX_WITH_TIME_1, QueryLanguages, WORKSPACE_NAME, + START_TIME, + END_TIME, } from './constants'; +import { APPLIED_FILTERS } from './saved_search'; + /** * Sets the top nav date if it is relevant for the passed language * @param {QueryEnhancementLanguage} language - query language @@ -215,3 +219,42 @@ export const generateAllTestConfigurations = () => { }) ); }; + +/** + * Verify that the discover page is in the correct state after loading a saved query have been run + * @param {SavedSearchTestConfig} testConfig - the relevant config for the test case + */ +export const verifyDiscoverPageState = ({ + queryString, + language, + hitCount, + filters, + histogram, +}) => { + if ([QueryLanguages.SQL.name, QueryLanguages.PPL.name].includes(language)) { + cy.getElementByTestId('osdQueryEditor__multiLine').contains(queryString); + } else { + cy.getElementByTestId('osdQueryEditor__singleLine').contains(queryString); + } + cy.getElementByTestId('queryEditorLanguageSelector').contains(language); + + if (filters) { + cy.getElementByTestId( + `filter filter-enabled filter-key-${APPLIED_FILTERS.field} filter-value-${APPLIED_FILTERS.value} filter-unpinned ` + ).should('exist'); + } + if (hitCount) { + cy.verifyHitCount(hitCount); + } + + if (histogram) { + // TODO: Uncomment this once bug is fixed, currently the interval is not saving + // https://github.com/opensearch-project/OpenSearch-Dashboards/issues/9077 + // cy.getElementByTestId('discoverIntervalSelect').should('have.value', 'w'); + } + + if (language !== QueryLanguages.SQL.name) { + cy.getElementByTestId('osdQueryEditorUpdateButton').contains(START_TIME).should('exist'); + cy.getElementByTestId('osdQueryEditorUpdateButton').contains(END_TIME).should('exist'); + } +}; From 2abb5de22ab8b76dc295f45b720f9f6a81559a51 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Thu, 16 Jan 2025 16:13:47 -0800 Subject: [PATCH 17/36] Modularize view and load query popover and flyout Signed-off-by: Argus Li --- .../saved_queries_flyout.spec.js | 17 ++---------- .../saved_queries_popover.spec.js | 9 +++---- .../apps/query_enhancements/saved_queries.js | 26 +++++++++++++++++++ 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js index 5fbee134f484..0ab6149c8434 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js @@ -22,6 +22,7 @@ import { generateAllTestConfigurations, setDatePickerDatesAndSearchIfRelevant, verifyDiscoverPageState, + verifySavedQueryExistsAndHasCorrectStateWhenLoaded, } from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is true. @@ -99,21 +100,7 @@ export const runSavedQueriesFlyoutUITests = () => { 'Aug 30, 2020 @ 00:00:00.000' ); - cy.getElementByTestId('saved-query-management-popover-button').click(); - - cy.getElementByTestId('saved-query-management-open-button').click(); - - cy.getElementByTestId('euiFlyoutCloseButton') - .parent() - .contains(config.saveName) - .should('exist') - .click(); - - cy.getElementByTestId('open-query-action-button').click(); - - // wait for saved queries to load. - cy.wait(2000); - verifyDiscoverPageState(config); + verifySavedQueryExistsAndHasCorrectStateWhenLoaded(config, true); }); }); }); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js index b98430739078..27ce910a149e 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js @@ -21,6 +21,7 @@ import { import { generateAllTestConfigurations, setDatePickerDatesAndSearchIfRelevant, + verifySavedQueryExistsAndHasCorrectStateWhenLoaded, verifyDiscoverPageState, } from '../../../../../utils/apps/query_enhancements/saved_queries'; @@ -93,6 +94,7 @@ export const runSavedQueriesPopoverUITests = () => { it('should see and load all saved queries', () => { testConfigurations.forEach((config) => { + // Dates are cached for each dataset. This ensures the dates must be set by the saved query to display the expected results. cy.getElementByTestId('discoverNewButton').click(); setDatePickerDatesAndSearchIfRelevant( config.language, @@ -100,12 +102,7 @@ export const runSavedQueriesPopoverUITests = () => { 'Aug 30, 2020 @ 00:00:00.000' ); - cy.getElementByTestId('saved-query-management-popover-button').click(); - cy.getElementByTestId('save-query-panel').contains(config.saveName).should('exist').click(); - - // wait for saved queries to load. - cy.wait(2000); - verifyDiscoverPageState(config); + verifySavedQueryExistsAndHasCorrectStateWhenLoaded(config, false); }); }); }); diff --git a/cypress/utils/apps/query_enhancements/saved_queries.js b/cypress/utils/apps/query_enhancements/saved_queries.js index c5c675fdc3c4..7dacc9ee7b1f 100644 --- a/cypress/utils/apps/query_enhancements/saved_queries.js +++ b/cypress/utils/apps/query_enhancements/saved_queries.js @@ -258,3 +258,29 @@ export const verifyDiscoverPageState = ({ cy.getElementByTestId('osdQueryEditorUpdateButton').contains(END_TIME).should('exist'); } }; + +export const verifySavedQueryExistsAndHasCorrectStateWhenLoaded = ( + config, + savedQueriesNewUIEnabled = true +) => { + if (savedQueriesNewUIEnabled) { + cy.getElementByTestId('saved-query-management-popover-button').click(); + + cy.getElementByTestId('saved-query-management-open-button').click(); + + cy.getElementByTestId('euiFlyoutCloseButton') + .parent() + .contains(config.saveName) + .should('exist') + .click(); + + cy.getElementByTestId('open-query-action-button').click(); + } else { + cy.getElementByTestId('saved-query-management-popover-button').click(); + cy.getElementByTestId('save-query-panel').contains(config.saveName).should('exist').click(); + } + + // wait for saved queries to load. + cy.wait(2000); + verifyDiscoverPageState(config); +}; From 454ac705e73e3d9119a02b39c8fb68f9a78caff5 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Thu, 16 Jan 2025 16:49:36 -0800 Subject: [PATCH 18/36] Complete valid Saved Queries shown across Visualize Pages Signed-off-by: Argus Li --- .../saved_queries_popover.spec.js | 11 +++++++ .../apps/query_enhancements/saved_queries.js | 31 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js index 27ce910a149e..cc3b3c97039f 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js @@ -23,6 +23,7 @@ import { setDatePickerDatesAndSearchIfRelevant, verifySavedQueryExistsAndHasCorrectStateWhenLoaded, verifyDiscoverPageState, + verifyValidSavedQueriesShownOnVisualize, } from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is false. @@ -105,6 +106,16 @@ export const runSavedQueriesPopoverUITests = () => { verifySavedQueryExistsAndHasCorrectStateWhenLoaded(config, false); }); }); + + it('should only show DQL and Lucene saved Queries in Visualizations page', () => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'visualize', + isEnhancement: true, + }); + + verifyValidSavedQueriesShownOnVisualize(false); + }); }); }; diff --git a/cypress/utils/apps/query_enhancements/saved_queries.js b/cypress/utils/apps/query_enhancements/saved_queries.js index 7dacc9ee7b1f..7e969b7c22c0 100644 --- a/cypress/utils/apps/query_enhancements/saved_queries.js +++ b/cypress/utils/apps/query_enhancements/saved_queries.js @@ -259,6 +259,11 @@ export const verifyDiscoverPageState = ({ } }; +/** + * Verify that the query specified in the config was saved and can be loaded correctly. + * @param {SavedSearchTestConfig} config - the relevant config for the test case + * @param {boolean} savedQueriesNewUIEnabled - Has this flag been enabled (default is true) + */ export const verifySavedQueryExistsAndHasCorrectStateWhenLoaded = ( config, savedQueriesNewUIEnabled = true @@ -284,3 +289,29 @@ export const verifySavedQueryExistsAndHasCorrectStateWhenLoaded = ( cy.wait(2000); verifyDiscoverPageState(config); }; + +/** + * Verify that only DQL and Lucene saved queries are shown in the Visualize page. + * @param {boolean} savedQueriesNewUIEnabled - Has this flag been enabled (default is true) + */ +export const verifyValidSavedQueriesShownOnVisualize = ( + savedQueriesNewUIEnabled = true // eslint-disable-line no-unused-vars +) => { + if (savedQueriesNewUIEnabled) { + // Currently functionality has not been implemented for savedQueriesNewUI + } else { + cy.getElementByTestId('createVisualizationPromptButton').click(); + cy.getElementByTestId('visType-table').click(); + cy.getElementByTestId('savedObjectFinderItemList') + .findElementByTestIdLike('savedObjectTitledata') + .click(); + + cy.getElementByTestId('showFilterActions').click(); + cy.getElementByTestId('savedQueries').click(); + + cy.getElementByTestId('save-query-panel').contains('DQL'); + cy.getElementByTestId('save-query-panel').contains('Lucene'); + cy.getElementByTestId('save-query-panel').contains('OpenSearch SQL').should('not.exist'); + cy.getElementByTestId('save-query-panel').contains('PPL').should('not.exist'); + } +}; From 4ecaf80b27da26e522ae918720e8e1fce5e5669a Mon Sep 17 00:00:00 2001 From: Argus Li Date: Thu, 16 Jan 2025 18:15:18 -0800 Subject: [PATCH 19/36] Complete Popover delete saved query Signed-off-by: Argus Li --- .../saved_queries_popover.spec.js | 16 +++++++++++-- cypress/utils/apps/data_explorer/commands.js | 17 +++++++------ .../apps/query_enhancements/saved_queries.js | 24 ++++++++++++++++--- cypress/utils/commands.js | 4 ++++ 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js index cc3b3c97039f..af5730eaf246 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js @@ -24,6 +24,7 @@ import { verifySavedQueryExistsAndHasCorrectStateWhenLoaded, verifyDiscoverPageState, verifyValidSavedQueriesShownOnVisualize, + verifyQueryDoesNotExistInSavedQueries, } from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is false. @@ -93,7 +94,7 @@ export const runSavedQueriesPopoverUITests = () => { }); }); - it('should see and load all saved queries', () => { + it.skip('should see and load all saved queries', () => { testConfigurations.forEach((config) => { // Dates are cached for each dataset. This ensures the dates must be set by the saved query to display the expected results. cy.getElementByTestId('discoverNewButton').click(); @@ -107,7 +108,7 @@ export const runSavedQueriesPopoverUITests = () => { }); }); - it('should only show DQL and Lucene saved Queries in Visualizations page', () => { + it.skip('should only show DQL and Lucene saved Queries in Visualizations page', () => { cy.navigateToWorkSpaceSpecificPage({ workspaceName, page: 'visualize', @@ -116,6 +117,17 @@ export const runSavedQueriesPopoverUITests = () => { verifyValidSavedQueriesShownOnVisualize(false); }); + + it('should delete a saved query', () => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + cy.deleteSaveQuery('OpenSearch SQL-INDEX_PATTERN', false); + verifyQueryDoesNotExistInSavedQueries('OpenSearch SQL-INDEX_PATTERN', false); + }); }); }; diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index 91fa9a334c24..59c08f409112 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -125,7 +125,6 @@ Cypress.Commands.add( } ); -// eslint-disable-next-line no-unused-vars Cypress.Commands.add( 'saveQuery', ( @@ -173,13 +172,17 @@ Cypress.Commands.add('clearSaveQuery', () => { cy.getElementByTestId('saved-query-management-clear-button').click(); }); -Cypress.Commands.add('deleteSaveQuery', (name) => { - cy.getElementByTestId('saved-query-management-popover-button').click(); +Cypress.Commands.add('deleteSaveQuery', (name, savedQueriesNewUIEnabled = true) => { + if (savedQueriesNewUIEnabled) { + // to be implemented. + } else { + cy.getElementByTestId('saved-query-management-popover-button').click(); - cy.get(`[data-test-subj~="delete-saved-query-${name}-button"]`).click({ - force: true, - }); - cy.getElementByTestId('confirmModalConfirmButton').click(); + cy.getElementByTestIdLike(`delete-saved-query-${name}-button`).click({ + force: true, + }); + cy.getElementByTestId('confirmModalConfirmButton').click(); + } }); Cypress.Commands.add('switchDiscoverTable', (name) => { diff --git a/cypress/utils/apps/query_enhancements/saved_queries.js b/cypress/utils/apps/query_enhancements/saved_queries.js index 7e969b7c22c0..9606571ae6e5 100644 --- a/cypress/utils/apps/query_enhancements/saved_queries.js +++ b/cypress/utils/apps/query_enhancements/saved_queries.js @@ -294,9 +294,7 @@ export const verifySavedQueryExistsAndHasCorrectStateWhenLoaded = ( * Verify that only DQL and Lucene saved queries are shown in the Visualize page. * @param {boolean} savedQueriesNewUIEnabled - Has this flag been enabled (default is true) */ -export const verifyValidSavedQueriesShownOnVisualize = ( - savedQueriesNewUIEnabled = true // eslint-disable-line no-unused-vars -) => { +export const verifyValidSavedQueriesShownOnVisualize = (savedQueriesNewUIEnabled = true) => { if (savedQueriesNewUIEnabled) { // Currently functionality has not been implemented for savedQueriesNewUI } else { @@ -315,3 +313,23 @@ export const verifyValidSavedQueriesShownOnVisualize = ( cy.getElementByTestId('save-query-panel').contains('PPL').should('not.exist'); } }; + +/** + * Verify query does not exist in saved queries. + * @param {boolean} savedQueriesNewUIEnabled - Has this flag been enabled (default is true) + * @returns {string} Name of query to check. + */ +export const verifyQueryDoesNotExistInSavedQueries = ( + deletedQueryName, + savedQueriesNewUIEnabled = true +) => { + cy.reload(); + if (savedQueriesNewUIEnabled) { + // oh nana + } else { + cy.getElementByTestId('saved-query-management-popover-button').click(); + cy.getElementByTestId('osdSavedQueryManagementList') + .contains(deletedQueryName) + .should('not.exist'); + } +}; diff --git a/cypress/utils/commands.js b/cypress/utils/commands.js index cb9e2882e3c2..622671a54009 100644 --- a/cypress/utils/commands.js +++ b/cypress/utils/commands.js @@ -25,6 +25,10 @@ Cypress.Commands.add('getElementByTestId', (testId, options = {}) => { return cy.get(`[data-test-subj="${testId}"]`, options); }); +Cypress.Commands.add('getElementByTestIdLike', (testId, options = {}) => { + return cy.get(`[data-test-subj*="${testId}"]`, options); +}); + Cypress.Commands.add('getElementsByTestIds', (testIds, options = {}) => { const selectors = [testIds].flat(Infinity).map((testId) => `[data-test-subj="${testId}"]`); return cy.get(selectors.join(','), options); From 1746c6f5dae57f2b86773efabcac41464848e80a Mon Sep 17 00:00:00 2001 From: Argus Li Date: Thu, 16 Jan 2025 20:37:23 -0800 Subject: [PATCH 20/36] Add data-test-subj for flyoutbody and delete button. Signed-off-by: Argus Li --- .../public/ui/saved_query_flyouts/open_saved_query_flyout.tsx | 2 +- .../data/public/ui/saved_query_flyouts/saved_query_card.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/data/public/ui/saved_query_flyouts/open_saved_query_flyout.tsx b/src/plugins/data/public/ui/saved_query_flyouts/open_saved_query_flyout.tsx index b55afd023eac..88b428b8b999 100644 --- a/src/plugins/data/public/ui/saved_query_flyouts/open_saved_query_flyout.tsx +++ b/src/plugins/data/public/ui/saved_query_flyouts/open_saved_query_flyout.tsx @@ -325,7 +325,7 @@ export function OpenSavedQueryFlyout({

Saved queries

- + { setShowDeletionConfirmationModal(true); }} From 58251de46b2b39403fadbd5aae0d1da2afa74d73 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Thu, 16 Jan 2025 20:50:30 -0800 Subject: [PATCH 21/36] Complete flyout delete saved query Signed-off-by: Argus Li --- .../saved_queries_flyout.spec.js | 15 +++++++++++++-- cypress/utils/apps/data_explorer/commands.js | 11 ++++++++++- .../apps/query_enhancements/saved_queries.js | 4 +++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js index 0ab6149c8434..a24df3e0ab8a 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js @@ -21,8 +21,9 @@ import { import { generateAllTestConfigurations, setDatePickerDatesAndSearchIfRelevant, - verifyDiscoverPageState, verifySavedQueryExistsAndHasCorrectStateWhenLoaded, + verifyDiscoverPageState, + verifyQueryDoesNotExistInSavedQueries, } from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is true. @@ -91,7 +92,7 @@ export const runSavedQueriesFlyoutUITests = () => { }); }); - it('should see and load all saved queries', () => { + it.skip('should see and load all saved queries', () => { testConfigurations.forEach((config) => { cy.getElementByTestId('discoverNewButton').click(); setDatePickerDatesAndSearchIfRelevant( @@ -103,6 +104,16 @@ export const runSavedQueriesFlyoutUITests = () => { verifySavedQueryExistsAndHasCorrectStateWhenLoaded(config, true); }); }); + it('should delete a saved query', () => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + cy.deleteSaveQuery('OpenSearch SQL-INDEX_PATTERN', true); + verifyQueryDoesNotExistInSavedQueries('OpenSearch SQL-INDEX_PATTERN', true); + }); }); }; diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index 59c08f409112..b807d43e5fb5 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -174,7 +174,16 @@ Cypress.Commands.add('clearSaveQuery', () => { Cypress.Commands.add('deleteSaveQuery', (name, savedQueriesNewUIEnabled = true) => { if (savedQueriesNewUIEnabled) { - // to be implemented. + cy.getElementByTestId('saved-query-management-popover-button').click(); + + cy.getElementByTestId('saved-query-management-open-button').click(); + cy.getElementByTestId('euiFlyoutCloseButton') + .parent() + .contains(name) + .findElementByTestId('deleteSavedQueryButton') + .click(); + + cy.getElementByTestId('confirmModalConfirmButton').click(); } else { cy.getElementByTestId('saved-query-management-popover-button').click(); diff --git a/cypress/utils/apps/query_enhancements/saved_queries.js b/cypress/utils/apps/query_enhancements/saved_queries.js index 9606571ae6e5..b9cc249748ea 100644 --- a/cypress/utils/apps/query_enhancements/saved_queries.js +++ b/cypress/utils/apps/query_enhancements/saved_queries.js @@ -325,7 +325,9 @@ export const verifyQueryDoesNotExistInSavedQueries = ( ) => { cy.reload(); if (savedQueriesNewUIEnabled) { - // oh nana + cy.getElementByTestId('saved-query-management-popover-button').click(); + cy.getElementByTestId('saved-query-management-open-button').click(); + cy.getElementByTestId('savedQueriesFlyoutBody').contains(deletedQueryName).should('not.exist'); } else { cy.getElementByTestId('saved-query-management-popover-button').click(); cy.getElementByTestId('osdSavedQueryManagementList') From 3bac756b9c9bc56c1cf282a612c20d5db3ebdb11 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Fri, 17 Jan 2025 12:56:06 -0800 Subject: [PATCH 22/36] Add data-test-subj for saveAsNewQueryCheckbox Signed-off-by: Argus Li --- src/plugins/data/public/ui/saved_query_form/helpers.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/data/public/ui/saved_query_form/helpers.tsx b/src/plugins/data/public/ui/saved_query_form/helpers.tsx index f057326d3f1b..13e72c3cb39c 100644 --- a/src/plugins/data/public/ui/saved_query_form/helpers.tsx +++ b/src/plugins/data/public/ui/saved_query_form/helpers.tsx @@ -175,6 +175,7 @@ export function useSaveQueryFormContent({ id="save-as-new-query" onChange={(event) => setSaveAsNew?.(event.target.checked)} checked={saveAsNew} + data-test-subj="saveAsNewQueryCheckbox" label={i18n.translate('data.search.searchBar.SaveAsNewLabelText', { defaultMessage: 'Save as new query', })} From 0d98d743892294b044189b67982d4a02c5a12577 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Mon, 20 Jan 2025 16:23:14 -0800 Subject: [PATCH 23/36] Complete Flyout Update Saved Query Signed-off-by: Argus Li --- .../saved_queries_flyout.spec.js | 32 ++- cypress/utils/apps/data_explorer/commands.js | 63 ++++- cypress/utils/apps/data_explorer/index.d.ts | 43 ++- .../apps/query_enhancements/saved_queries.js | 262 ++++++++++++++++-- 4 files changed, 353 insertions(+), 47 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js index a24df3e0ab8a..6586acafbd4b 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js @@ -15,15 +15,15 @@ import { import { workspaceName, datasourceName, - setSearchConfigurations, } from '../../../../../utils/apps/query_enhancements/saved_search'; import { generateAllTestConfigurations, setDatePickerDatesAndSearchIfRelevant, - verifySavedQueryExistsAndHasCorrectStateWhenLoaded, verifyDiscoverPageState, verifyQueryDoesNotExistInSavedQueries, + setQueryConfigurations, + updateAndVerifySavedQuery, } from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is true. @@ -86,25 +86,33 @@ export const runSavedQueriesFlyoutUITests = () => { cy.setQueryLanguage(config.language); setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); - setSearchConfigurations(config); + setQueryConfigurations(config); verifyDiscoverPageState(config); cy.saveQuery(config.saveName, ' ', true, true, true); }); }); - it.skip('should see and load all saved queries', () => { + describe('should see and load all saved queries', () => { testConfigurations.forEach((config) => { - cy.getElementByTestId('discoverNewButton').click(); - setDatePickerDatesAndSearchIfRelevant( - config.language, - 'Aug 29, 2020 @ 00:00:00.000', - 'Aug 30, 2020 @ 00:00:00.000' - ); + it(`Load query name: ${config.testName}`, () => { + cy.getElementByTestId('discoverNewButton').click(); + setDatePickerDatesAndSearchIfRelevant( + config.language, + 'Aug 29, 2020 @ 00:00:00.000', + 'Aug 30, 2020 @ 00:00:00.000' + ); - verifySavedQueryExistsAndHasCorrectStateWhenLoaded(config, true); + cy.loadSaveQuery(config.saveName, true); + // wait for saved queries to load. + cy.wait(2000); + verifyDiscoverPageState(config); + }); + it(`should successfully update the loaded ${config.testName} saved query`, () => { + updateAndVerifySavedQuery(config, true); + }); }); }); - it('should delete a saved query', () => { + it.skip('should delete a saved query', () => { cy.navigateToWorkSpaceSpecificPage({ workspaceName, page: 'discover', diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index b807d43e5fb5..6d1a0ae964e6 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -125,14 +125,21 @@ Cypress.Commands.add( } ); +Cypress.Commands.add('deleteAllFilters', (savedQueriesNewUIEnabled = true) => { + if (savedQueriesNewUIEnabled) { + // the Close icon is from elastic. + cy.getElementsByTestIds('globalFilterBar').find('[class="euiBadge__iconButton"]').click(); + } +}); + Cypress.Commands.add( 'saveQuery', ( name, description = ' ', - savedQueriesNewUIEnabled = true, // eslint-disable-line no-unused-vars includeFilters = true, - includeTimeFilter = false + includeTimeFilter = false, + savedQueriesNewUIEnabled = true // eslint-disable-line no-unused-vars ) => { cy.whenTestIdNotFound('saved-query-management-popover', () => { cy.getElementByTestId('saved-query-management-popover-button').click(); @@ -156,12 +163,54 @@ Cypress.Commands.add( } ); -Cypress.Commands.add('loadSaveQuery', (name) => { - cy.getElementByTestId('saved-query-management-popover-button').click({ - force: true, - }); +Cypress.Commands.add( + 'updateSaveQuery', + ( + name = '', + saveAsNewQuery = false, + includeFilters = true, + includeTimeFilter = false, + savedQueriesNewUIEnabled = true // eslint-disable-line no-unused-vars + ) => { + cy.whenTestIdNotFound('saved-query-management-popover', () => { + cy.getElementByTestId('saved-query-management-popover-button').click(); + }); + cy.getElementByTestId('saved-query-management-save-button').click(); + + if (saveAsNewQuery) { + cy.getElementByTestId('saveAsNewQueryCheckbox').check(); + cy.getElementByTestId('saveQueryFormTitle').type(name); + } else if (saveAsNewQuery === true) { + cy.getElementByTestId('saveAsNewQueryCheckbox').uncheck(); + } + + if (includeFilters !== true) { + cy.getElementByTestId('saveQueryFormIncludeFiltersOption').click(); + } - cy.get(`[data-test-subj~="load-saved-query-${name}-button"]`).should('be.visible').click(); + if (includeTimeFilter !== false) { + cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); + } + + // The force is necessary as there is occasionally a popover that covers the button + cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); + cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); + } +); + +Cypress.Commands.add('loadSaveQuery', (name, savedQueriesNewUIEnabled = true) => { + if (savedQueriesNewUIEnabled) { + cy.getElementByTestId('saved-query-management-popover-button').click(); + + cy.getElementByTestId('saved-query-management-open-button').click(); + + cy.getElementByTestId('euiFlyoutCloseButton').parent().contains(name).should('exist').click(); + + cy.getElementByTestId('open-query-action-button').click(); + } else { + cy.getElementByTestId('saved-query-management-popover-button').click(); + cy.getElementByTestId('save-query-panel').contains(name).should('exist').click(); + } }); Cypress.Commands.add('clearSaveQuery', () => { diff --git a/cypress/utils/apps/data_explorer/index.d.ts b/cypress/utils/apps/data_explorer/index.d.ts index 75f17a1d59ca..5b9ca9745cd8 100644 --- a/cypress/utils/apps/data_explorer/index.d.ts +++ b/cypress/utils/apps/data_explorer/index.d.ts @@ -19,8 +19,47 @@ declare namespace Cypress { value: string, isEnhancement?: boolean ): Chainable; - saveQuery(name: string, description: string): Chainable; - loadSaveQuery(name: string): Chainable; + /** + * Deletes all filters in a Search. + * @param savedQueriesNewUIEnabled - Which UI to use. (defaults to true) + */ + deleteAllFilters(savedQueriesNewUIEnabled: boolean): void; + /** + * Save a query. + * @param name - Name of the query + * @param description - Description of the query + * @param includeFilters - Save filters + * @param includeTimeFilter - Save Time filter + * @param savedQueriesNewUIEnabled - Which UI to use. (defaults to true) + */ + saveQuery( + name: string, + description: string, + includeFilters: boolean, + includeTimeFilter: boolean, + savedQueriesNewUIEnabled: boolean + ): Chainable; + /** + * Update a saved query. + * @param name - Name of saved query if saved as new query. + * @param saveAsNewQuery - Save as a new query. + * @param includeFilters - Save filters. + * @param includeTimeFilter - Save Time filter. + * @param savedQueriesNewUIEnabled - Which UI to use. (defaults to true) + */ + updateSaveQuery( + name: string, + saveAsNewQuery: boolean, + includeFilters: boolean, + includeTimeFilter: boolean, + savedQueriesNewUIEnabled: boolean + ): void; + /** + * Load a saved query. + * @param name - Name of saved query. + * @param savedQueriesNewUIEnabled - Which UI to use. (defaults to true) + */ + loadSaveQuery(name: string, savedQueriesNewUIEnabled: boolean): Chainable; clearSaveQuery(): Chainable; deleteSaveQuery(name: string): Chainable; switchDiscoverTable(name: string): Chainable; diff --git a/cypress/utils/apps/query_enhancements/saved_queries.js b/cypress/utils/apps/query_enhancements/saved_queries.js index b9cc249748ea..d4be685e11a9 100644 --- a/cypress/utils/apps/query_enhancements/saved_queries.js +++ b/cypress/utils/apps/query_enhancements/saved_queries.js @@ -16,6 +16,34 @@ import { import { APPLIED_FILTERS } from './saved_search'; +/** + * The Alternate Absolute Start Time to use for saved query + * @constant + * @type {string} + * @default + */ +const ALTERNATE_START_TIME = 'Mar 21, 2021 @ 15:23:04.251'; + +/** + * The Alternate Absolute End Time to use for saved query + * @constant + * @type {string} + * @default + */ +const ALTERNATE_END_TIME = 'Aug 28, 2021 @ 15:38:14.646'; + +/** + * The alternate filter configuration to use for saved query + * @constant + * @type {string} + * @default + */ +export const ALTERNATE_APPLIED_FILTERS = { + field: 'category', + operator: 'is not one of', + value: 'Database', +}; + /** * Sets the top nav date if it is relevant for the passed language * @param {QueryEnhancementLanguage} language - query language @@ -65,6 +93,27 @@ const getQueryString = (dataset, language) => { } }; +/** + * Returns the query string to use for a given dataset+language + * @param {string} dataset - the dataset name to use + * @param {QueryEnhancementLanguage} language - the name of query language + * @returns {string} + */ +const getAlternateQueryString = (dataset, language) => { + switch (language) { + case QueryLanguages.DQL.name: + return 'bytes_transferred < 200'; + case QueryLanguages.Lucene.name: + return 'bytes_transferred: {* TO 200}'; + case QueryLanguages.SQL.name: + return `SELECT * FROM ${dataset} WHERE bytes_transferred < 200`; + case QueryLanguages.PPL.name: + return `source = ${dataset} | where bytes_transferred < 200`; + default: + throw new Error(`getQueryString encountered unsupported language: ${language}`); + } +}; + /** * Returns the expected hit count, if relevant, for the provided datasetType + language * @param {QueryEnhancementDataset} datasetType - the type of the dataset @@ -106,6 +155,47 @@ const getExpectedHitCount = (datasetType, language) => { } }; +/** + * Returns the expected hit count, if relevant, for the provided datasetType + language + * @param {QueryEnhancementDataset} datasetType - the type of the dataset + * @param {QueryEnhancementLanguage} language - the query language name + * @returns {number|undefined} + */ +const getAlternateExpectedHitCount = (datasetType, language) => { + switch (datasetType) { + case DatasetTypes.INDEX_PATTERN.name: + switch (language) { + case QueryLanguages.DQL.name: + return 30; + case QueryLanguages.Lucene.name: + return 30; + case QueryLanguages.SQL.name: + return undefined; + case QueryLanguages.PPL.name: + // TODO: Update this to 45 once Histogram is supported on 2.17 + return undefined; + default: + throw new Error( + `getExpectedHitCount encountered unsupported language for ${datasetType}: ${language}` + ); + } + case DatasetTypes.INDEXES.name: + switch (language) { + case QueryLanguages.SQL.name: + return undefined; + case QueryLanguages.PPL.name: + // TODO: Update this to 50 once Histogram is supported on 2.17 + return undefined; + default: + throw new Error( + `getExpectedHitCount encountered unsupported language for ${datasetType}: ${language}` + ); + } + default: + throw new Error(`getExpectedHitCount encountered unsupported datasetType: ${datasetType}`); + } +}; + /** * returns an array of data present in the results table to check against. This is used to ensure that sorting is working as expected * @param {QueryEnhancementDataset} datasetType - the type of the dataset @@ -174,9 +264,17 @@ const getSampleTableData = (datasetType, language) => { * @param {string} dataset - the dataset name * @param {QueryEnhancementDataset} datasetType - the type of the dataset * @param {QueryEnhancementLanguageData} language - the relevant data for the query language to use + * @param {String} [startTime = constants/START_TIME] - the absolute start time for the query in the form e.g. Jan 1, 2020 @ 15:17:18.005 + * @param {String} [endTime = constants/END_TIME] - the absolute end time for the query in the form e.g. Jan 1, 2020 @ 15:17:18.005 * @returns {SavedSearchTestConfig} */ -const generateTestConfiguration = (dataset, datasetType, language) => { +const generateTestConfiguration = ( + dataset, + datasetType, + language, + startTime = START_TIME, + endTime = END_TIME +) => { const baseConfig = { dataset, datasetType, @@ -184,6 +282,8 @@ const generateTestConfiguration = (dataset, datasetType, language) => { apiLanguage: language.apiName, saveName: `${language.name}-${datasetType}`, testName: `${language.name}-${datasetType}`, + startTime, + endTime, ...language.supports, }; @@ -195,6 +295,34 @@ const generateTestConfiguration = (dataset, datasetType, language) => { }; }; +/** + * Returns an alternate SavedSearchTestConfig + * @param {SavedSearchTestConfig} config - initial config that will be modified. + * @returns {SavedSearchTestConfig} + */ +const generateAlternateTestConfiguration = (config) => { + const baseConfig = { + dataset: config.dataset, + datasetType: config.datasetType, + language: config.language, + apiLanguage: config.apiLanguage, + saveName: config.saveName, + testName: config.testName, + startTime: ALTERNATE_START_TIME, + endTime: ALTERNATE_END_TIME, + filters: config.filters, + histogram: config.histogram, + selectFields: config.selectFields, + sort: config.sort, + }; + + return { + ...baseConfig, + queryString: getAlternateQueryString(config.dataset, config.language), + hitCount: getAlternateExpectedHitCount(config.datasetType, config.language), + }; +}; + /** * Returns an array of test configurations for every query language + dataset permutation * @returns {SavedSearchTestConfig[]} @@ -230,6 +358,8 @@ export const verifyDiscoverPageState = ({ hitCount, filters, histogram, + startTime, + endTime, }) => { if ([QueryLanguages.SQL.name, QueryLanguages.PPL.name].includes(language)) { cy.getElementByTestId('osdQueryEditor__multiLine').contains(queryString); @@ -254,40 +384,92 @@ export const verifyDiscoverPageState = ({ } if (language !== QueryLanguages.SQL.name) { - cy.getElementByTestId('osdQueryEditorUpdateButton').contains(START_TIME).should('exist'); - cy.getElementByTestId('osdQueryEditorUpdateButton').contains(END_TIME).should('exist'); + cy.getElementByTestId('osdQueryEditorUpdateButton').contains(startTime).should('exist'); + cy.getElementByTestId('osdQueryEditorUpdateButton').contains(endTime).should('exist'); } }; /** - * Verify that the query specified in the config was saved and can be loaded correctly. - * @param {SavedSearchTestConfig} config - the relevant config for the test case - * @param {boolean} savedQueriesNewUIEnabled - Has this flag been enabled (default is true) + * Verify that the discover page is in the correct state after loading a saved query have been run + * @param {SavedSearchTestConfig} testConfig - the relevant config for the test case */ -export const verifySavedQueryExistsAndHasCorrectStateWhenLoaded = ( - config, - savedQueriesNewUIEnabled = true -) => { - if (savedQueriesNewUIEnabled) { - cy.getElementByTestId('saved-query-management-popover-button').click(); +export const verifyAlternateDiscoverPageState = ({ + queryString, + language, + hitCount, + filters, + histogram, + startTime, + endTime, +}) => { + if ([QueryLanguages.SQL.name, QueryLanguages.PPL.name].includes(language)) { + cy.getElementByTestId('osdQueryEditor__multiLine').contains(queryString); + } else { + cy.getElementByTestId('osdQueryEditor__singleLine').contains(queryString); + } + cy.getElementByTestId('queryEditorLanguageSelector').contains(language); - cy.getElementByTestId('saved-query-management-open-button').click(); + if (filters) { + cy.getElementByTestId( + `filter filter-enabled filter-key-${ALTERNATE_APPLIED_FILTERS.field} filter-value-${ALTERNATE_APPLIED_FILTERS.value} filter-unpinned filter-negated` + ).should('exist'); + } + if (hitCount) { + cy.verifyHitCount(hitCount); + } - cy.getElementByTestId('euiFlyoutCloseButton') - .parent() - .contains(config.saveName) - .should('exist') - .click(); + if (histogram) { + // TODO: Uncomment this once bug is fixed, currently the interval is not saving + // https://github.com/opensearch-project/OpenSearch-Dashboards/issues/9077 + // cy.getElementByTestId('discoverIntervalSelect').should('have.value', 'w'); + } - cy.getElementByTestId('open-query-action-button').click(); - } else { - cy.getElementByTestId('saved-query-management-popover-button').click(); - cy.getElementByTestId('save-query-panel').contains(config.saveName).should('exist').click(); + if (language !== QueryLanguages.SQL.name) { + cy.getElementByTestId('osdQueryEditorUpdateButton').contains(startTime).should('exist'); + cy.getElementByTestId('osdQueryEditorUpdateButton').contains(endTime).should('exist'); } +}; - // wait for saved queries to load. - cy.wait(2000); - verifyDiscoverPageState(config); +/** + * Set the query configurations for the saved query + * @param {SavedSearchTestConfig} testConfig - the relevant config for the test case + */ +export const setQueryConfigurations = ({ filters, queryString, histogram }) => { + if (filters) { + cy.submitFilterFromDropDown( + APPLIED_FILTERS.field, + APPLIED_FILTERS.operator, + APPLIED_FILTERS.value, + true + ); + } + + cy.setQueryEditor(queryString, { parseSpecialCharSequences: false }); + + if (histogram) { + cy.getElementByTestId('discoverIntervalSelect').select('w'); + } +}; + +/** + * Set the query configurations for the saved query + * @param {SavedSearchTestConfig} testConfig - the relevant config for the test case + */ +export const setAlternateQueryConfigurations = ({ filters, queryString, histogram }) => { + if (filters) { + cy.submitFilterFromDropDown( + ALTERNATE_APPLIED_FILTERS.field, + ALTERNATE_APPLIED_FILTERS.operator, + ALTERNATE_APPLIED_FILTERS.value, + true + ); + } + + cy.setQueryEditor(queryString, { parseSpecialCharSequences: false }); + + if (histogram) { + cy.getElementByTestId('discoverIntervalSelect').select('w'); + } }; /** @@ -316,8 +498,8 @@ export const verifyValidSavedQueriesShownOnVisualize = (savedQueriesNewUIEnabled /** * Verify query does not exist in saved queries. + * @param {string} deletedQueryName - Name of the query that should not exist. * @param {boolean} savedQueriesNewUIEnabled - Has this flag been enabled (default is true) - * @returns {string} Name of query to check. */ export const verifyQueryDoesNotExistInSavedQueries = ( deletedQueryName, @@ -335,3 +517,31 @@ export const verifyQueryDoesNotExistInSavedQueries = ( .should('not.exist'); } }; + +/** + * Update and save the saved query with alternate config, then verify has been updated correctly. + * @param {SavedSearchTestConfig} config - the config for the test case to be updated + * @param {boolean} savedQueriesNewUIEnabled - Has this flag been enabled (default is true) + */ +export const updateAndVerifySavedQuery = (config, savedQueriesNewUIEnabled = true) => { + // Create alternate config + const alternateConfig = generateAlternateTestConfiguration(config); + cy.loadSaveQuery(config.saveName, true); + + // wait for saved query to load + cy.wait(2000); + + if (alternateConfig.filters) { + cy.deleteAllFilters(savedQueriesNewUIEnabled); + } + setAlternateQueryConfigurations(alternateConfig); + setDatePickerDatesAndSearchIfRelevant(config.language, ALTERNATE_START_TIME, ALTERNATE_END_TIME); + verifyAlternateDiscoverPageState(alternateConfig); + cy.updateSaveQuery('', false, true, true, savedQueriesNewUIEnabled); + + cy.reload(); + cy.loadSaveQuery(config.saveName, true); + // wait for saved query to load + cy.wait(2000); + verifyAlternateDiscoverPageState(alternateConfig); +}; From 51e9ce3757d3eb1fb92a0601a9e8dc7bcc8ab8fa Mon Sep 17 00:00:00 2001 From: Argus Li Date: Mon, 20 Jan 2025 19:26:21 -0800 Subject: [PATCH 24/36] Complete Flyout Save as New Saved Query Signed-off-by: Argus Li --- .../saved_queries_flyout.spec.js | 79 +++++++++++++------ cypress/utils/apps/data_explorer/commands.js | 25 ++++-- .../apps/query_enhancements/constants.js | 1 + .../apps/query_enhancements/saved_queries.js | 46 ++++++++++- 4 files changed, 116 insertions(+), 35 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js index 6586acafbd4b..6b2e0495ddb7 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js @@ -24,6 +24,8 @@ import { verifyQueryDoesNotExistInSavedQueries, setQueryConfigurations, updateAndVerifySavedQuery, + SAVE_AS_NEW_QUERY_SUFFIX, + validateSaveAsNewQueryMatchingNameHasError, } from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is true. @@ -73,28 +75,32 @@ export const runSavedQueriesFlyoutUITests = () => { }); const testConfigurations = generateAllTestConfigurations(); - testConfigurations.forEach((config) => { - it(`should successfully create a saved query for ${config.testName}`, () => { - cy.navigateToWorkSpaceSpecificPage({ - workspaceName, - page: 'discover', - isEnhancement: true, - }); - cy.setDataset(config.dataset, datasourceName, config.datasetType); + describe('should create initial saved queries', () => { + testConfigurations.forEach((config) => { + it(`should create saved query: ${config.testName}`, () => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + cy.setDataset(config.dataset, datasourceName, config.datasetType); - cy.setQueryLanguage(config.language); - setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); + cy.setQueryLanguage(config.language); + setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); - setQueryConfigurations(config); - verifyDiscoverPageState(config); - cy.saveQuery(config.saveName, ' ', true, true, true); + setQueryConfigurations(config); + verifyDiscoverPageState(config); + + cy.saveQuery(config.saveName, ' ', true, true, true); + }); }); }); - describe('should see and load all saved queries', () => { + describe('should test loading, saving and deleting saved queries', () => { testConfigurations.forEach((config) => { - it(`Load query name: ${config.testName}`, () => { + it(`should load saved query: ${config.testName}`, () => { cy.getElementByTestId('discoverNewButton').click(); setDatePickerDatesAndSearchIfRelevant( config.language, @@ -107,20 +113,41 @@ export const runSavedQueriesFlyoutUITests = () => { cy.wait(2000); verifyDiscoverPageState(config); }); - it(`should successfully update the loaded ${config.testName} saved query`, () => { + + it(`should update the loaded saved query: ${config.testName}`, () => { updateAndVerifySavedQuery(config, true); }); - }); - }); - it.skip('should delete a saved query', () => { - cy.navigateToWorkSpaceSpecificPage({ - workspaceName, - page: 'discover', - isEnhancement: true, - }); - cy.deleteSaveQuery('OpenSearch SQL-INDEX_PATTERN', true); - verifyQueryDoesNotExistInSavedQueries('OpenSearch SQL-INDEX_PATTERN', true); + const saveAsNewQueryName = config.testName + SAVE_AS_NEW_QUERY_SUFFIX; + it(`should modify saved query: ${config.testName} and save as new query: ${saveAsNewQueryName}`, () => { + if (config.filters) { + cy.deleteAllFilters(true); + } + setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); + + setQueryConfigurations(config); + verifyDiscoverPageState(config); + validateSaveAsNewQueryMatchingNameHasError(config.saveName); + cy.updateSaveQuery(saveAsNewQueryName, true, true, true, true); + + cy.reload(); + cy.loadSaveQuery(saveAsNewQueryName, true); + // wait for saved query to load + cy.wait(2000); + verifyDiscoverPageState(config); + }); + + it(`should delete the saved query: ${saveAsNewQueryName}`, () => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + cy.deleteSaveQuery(saveAsNewQueryName, true); + verifyQueryDoesNotExistInSavedQueries(saveAsNewQueryName, true); + }); + }); }); }); }; diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index 6d1a0ae964e6..4d560fa68cf8 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -178,20 +178,29 @@ Cypress.Commands.add( cy.getElementByTestId('saved-query-management-save-button').click(); if (saveAsNewQuery) { - cy.getElementByTestId('saveAsNewQueryCheckbox').check(); - cy.getElementByTestId('saveQueryFormTitle').type(name); - } else if (saveAsNewQuery === true) { - cy.getElementByTestId('saveAsNewQueryCheckbox').uncheck(); + cy.getElementByTestId('saveAsNewQueryCheckbox') + .parent() + .find('[class="euiCheckbox__label"]') + .click(); + cy.getElementByTestId('saveQueryFormTitle').should('not.be.disabled').type(name); + + // Selecting the saveAsNewQuery element deselects the include time filter option. + if (includeTimeFilter === true) { + cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); + } + } else if (saveAsNewQuery === false) { + // defaults to not selected. + + if (includeTimeFilter !== true) { + cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); + } } if (includeFilters !== true) { + // Always defaults to selected. cy.getElementByTestId('saveQueryFormIncludeFiltersOption').click(); } - if (includeTimeFilter !== false) { - cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); - } - // The force is necessary as there is occasionally a popover that covers the button cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); diff --git a/cypress/utils/apps/query_enhancements/constants.js b/cypress/utils/apps/query_enhancements/constants.js index 304fb902e2cb..ada958682aed 100644 --- a/cypress/utils/apps/query_enhancements/constants.js +++ b/cypress/utils/apps/query_enhancements/constants.js @@ -11,6 +11,7 @@ export const INDEX_NAME = 'data_logs_small_time_1'; export const DEFAULT_TIME_INDEX_PATTERN_NAME = 'data_logs_small_time_1*'; export const DEFAULT_NO_TIME_INDEX_PATTERN_NAME = 'data_logs_small_no_time_1*'; export const INDEX_PATTERN_NAME = `${DATASOURCE_NAME}::${DEFAULT_TIME_INDEX_PATTERN_NAME}`; +export const SAVE_QUERY_CONFLICT_NAME_ERROR_TEXT = 'Name conflicts with an existing saved query'; export const DATASET_CONFIGS = { index_pattern: { diff --git a/cypress/utils/apps/query_enhancements/saved_queries.js b/cypress/utils/apps/query_enhancements/saved_queries.js index d4be685e11a9..663a97524b11 100644 --- a/cypress/utils/apps/query_enhancements/saved_queries.js +++ b/cypress/utils/apps/query_enhancements/saved_queries.js @@ -12,10 +12,19 @@ import { WORKSPACE_NAME, START_TIME, END_TIME, + SAVE_QUERY_CONFLICT_NAME_ERROR_TEXT, } from './constants'; import { APPLIED_FILTERS } from './saved_search'; +/** + * Suffix when saving as new query. + * @constant + * @type {string} + * @default + */ +export const SAVE_AS_NEW_QUERY_SUFFIX = '-1'; + /** * The Alternate Absolute Start Time to use for saved query * @constant @@ -516,6 +525,9 @@ export const verifyQueryDoesNotExistInSavedQueries = ( .contains(deletedQueryName) .should('not.exist'); } + + // Two references to two buttons layered over each other. + cy.getElementByTestId('euiFlyoutCloseButton').first().click({ force: true }); }; /** @@ -534,8 +546,10 @@ export const updateAndVerifySavedQuery = (config, savedQueriesNewUIEnabled = tru if (alternateConfig.filters) { cy.deleteAllFilters(savedQueriesNewUIEnabled); } - setAlternateQueryConfigurations(alternateConfig); + setDatePickerDatesAndSearchIfRelevant(config.language, ALTERNATE_START_TIME, ALTERNATE_END_TIME); + + setAlternateQueryConfigurations(alternateConfig); verifyAlternateDiscoverPageState(alternateConfig); cy.updateSaveQuery('', false, true, true, savedQueriesNewUIEnabled); @@ -545,3 +559,33 @@ export const updateAndVerifySavedQuery = (config, savedQueriesNewUIEnabled = tru cy.wait(2000); verifyAlternateDiscoverPageState(alternateConfig); }; + +/** + * Save as new query, and validate that saving as an existing name leads to the correct error message. + * @param {string} matchingName - the name of an existing saved query + * @param {boolean} savedQueriesNewUIEnabled - Has this flag been enabled (default is true) + */ +export const validateSaveAsNewQueryMatchingNameHasError = ( + matchingName, + savedQueriesNewUIEnabled = true +) => { + if (savedQueriesNewUIEnabled) { + cy.whenTestIdNotFound('saved-query-management-popover', () => { + cy.getElementByTestId('saved-query-management-popover-button').click(); + }); + cy.getElementByTestId('saved-query-management-save-button').click(); + + cy.getElementByTestId('saveAsNewQueryCheckbox') + .parent() + .find('[class="euiCheckbox__label"]') + .click(); + cy.getElementByTestId('saveQueryFormTitle').should('not.be.disabled').type(matchingName); + + // The force is necessary as there is occasionally a popover that covers the button + cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); + + cy.contains(SAVE_QUERY_CONFLICT_NAME_ERROR_TEXT).should('be.visible'); + // Two references to two buttons layered over each other. + cy.getElementByTestId('euiFlyoutCloseButton').first().click({ force: true }); + } +}; From 7061a4313c0feb5ca1d49faecf96d88c02d199b2 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Mon, 20 Jan 2025 20:15:09 -0800 Subject: [PATCH 25/36] Complete Popout Save as New Saved Query Signed-off-by: Argus Li --- .../saved_queries_flyout.spec.js | 2 +- .../saved_queries_popover.spec.js | 118 +++++++++++------- cypress/utils/apps/data_explorer/commands.js | 79 ++++++------ cypress/utils/apps/data_explorer/index.d.ts | 6 +- .../apps/query_enhancements/saved_queries.js | 23 +++- 5 files changed, 140 insertions(+), 88 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js index 6b2e0495ddb7..193db35c284e 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_flyout.spec.js @@ -121,7 +121,7 @@ export const runSavedQueriesFlyoutUITests = () => { const saveAsNewQueryName = config.testName + SAVE_AS_NEW_QUERY_SUFFIX; it(`should modify saved query: ${config.testName} and save as new query: ${saveAsNewQueryName}`, () => { if (config.filters) { - cy.deleteAllFilters(true); + cy.deleteAllFilters(); } setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js index af5730eaf246..8e3d790a2c3d 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancements/saved_queries_popover.spec.js @@ -15,16 +15,18 @@ import { import { workspaceName, datasourceName, - setSearchConfigurations, } from '../../../../../utils/apps/query_enhancements/saved_search'; import { generateAllTestConfigurations, setDatePickerDatesAndSearchIfRelevant, - verifySavedQueryExistsAndHasCorrectStateWhenLoaded, verifyDiscoverPageState, verifyValidSavedQueriesShownOnVisualize, verifyQueryDoesNotExistInSavedQueries, + setQueryConfigurations, + updateAndVerifySavedQuery, + SAVE_AS_NEW_QUERY_SUFFIX, + validateSaveAsNewQueryMatchingNameHasError, } from '../../../../../utils/apps/query_enhancements/saved_queries'; // This spec assumes data.savedQueriesNewUI.enabled is false. @@ -75,58 +77,90 @@ export const runSavedQueriesPopoverUITests = () => { }); const testConfigurations = generateAllTestConfigurations(); - testConfigurations.forEach((config) => { - it(`should successfully create a saved query for ${config.testName}`, () => { - cy.navigateToWorkSpaceSpecificPage({ - workspaceName, - page: 'discover', - isEnhancement: true, - }); - cy.setDataset(config.dataset, datasourceName, config.datasetType); + describe('should create initial saved queries', () => { + testConfigurations.forEach((config) => { + it(`should successfully create a saved query for ${config.testName}`, () => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + cy.setDataset(config.dataset, datasourceName, config.datasetType); - cy.setQueryLanguage(config.language); - setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); + cy.setQueryLanguage(config.language); + setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); - setSearchConfigurations(config); - verifyDiscoverPageState(config); - cy.saveQuery(config.saveName, ' ', false, true, true); + setQueryConfigurations(config); + verifyDiscoverPageState(config); + cy.saveQuery(config.saveName, ' ', true, true, false); + }); }); }); - it.skip('should see and load all saved queries', () => { + describe('should test loading, saving and deleting saved queries', () => { testConfigurations.forEach((config) => { - // Dates are cached for each dataset. This ensures the dates must be set by the saved query to display the expected results. - cy.getElementByTestId('discoverNewButton').click(); - setDatePickerDatesAndSearchIfRelevant( - config.language, - 'Aug 29, 2020 @ 00:00:00.000', - 'Aug 30, 2020 @ 00:00:00.000' - ); - - verifySavedQueryExistsAndHasCorrectStateWhenLoaded(config, false); - }); - }); + it(`should load saved query: ${config.testName}`, () => { + cy.getElementByTestId('discoverNewButton').click(); + setDatePickerDatesAndSearchIfRelevant( + config.language, + 'Aug 29, 2020 @ 00:00:00.000', + 'Aug 30, 2020 @ 00:00:00.000' + ); + + cy.loadSaveQuery(config.saveName, false); + // wait for saved queries to load. + cy.wait(2000); + verifyDiscoverPageState(config); + }); - it.skip('should only show DQL and Lucene saved Queries in Visualizations page', () => { - cy.navigateToWorkSpaceSpecificPage({ - workspaceName, - page: 'visualize', - isEnhancement: true, - }); + it(`should update the loaded saved query: ${config.testName}`, () => { + updateAndVerifySavedQuery(config, false); + }); - verifyValidSavedQueriesShownOnVisualize(false); - }); + const saveAsNewQueryName = config.testName + SAVE_AS_NEW_QUERY_SUFFIX; + it(`should modify saved query: ${config.testName} and save as new query: ${saveAsNewQueryName}`, () => { + if (config.filters) { + cy.deleteAllFilters(); + } + setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); + + setQueryConfigurations(config); + verifyDiscoverPageState(config); + validateSaveAsNewQueryMatchingNameHasError(config.saveName, false); + cy.updateSaveQuery(saveAsNewQueryName, true, true, true, false); + + cy.reload(); + cy.getElementByTestId('discoverNewButton'); + cy.loadSaveQuery(saveAsNewQueryName, false); + // wait for saved query to load + cy.wait(2000); + verifyDiscoverPageState(config); + }); - it('should delete a saved query', () => { - cy.navigateToWorkSpaceSpecificPage({ - workspaceName, - page: 'discover', - isEnhancement: true, + it(`should delete the saved query: ${saveAsNewQueryName}`, () => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + cy.deleteSaveQuery(saveAsNewQueryName, false); + verifyQueryDoesNotExistInSavedQueries(saveAsNewQueryName, false); + }); }); + }); + describe('should only show valid saved queries in theVisualization page', () => { + it('should only show DQL and Lucene saved Queries', () => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'visualize', + isEnhancement: true, + }); - cy.deleteSaveQuery('OpenSearch SQL-INDEX_PATTERN', false); - verifyQueryDoesNotExistInSavedQueries('OpenSearch SQL-INDEX_PATTERN', false); + verifyValidSavedQueriesShownOnVisualize(false); + }); }); }); }; diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index 4d560fa68cf8..90f58e22a591 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -125,22 +125,14 @@ Cypress.Commands.add( } ); -Cypress.Commands.add('deleteAllFilters', (savedQueriesNewUIEnabled = true) => { - if (savedQueriesNewUIEnabled) { - // the Close icon is from elastic. - cy.getElementsByTestIds('globalFilterBar').find('[class="euiBadge__iconButton"]').click(); - } +Cypress.Commands.add('deleteAllFilters', () => { + // the Close icon is from elastic. + cy.getElementsByTestIds('globalFilterBar').find('[class="euiBadge__iconButton"]').click(); }); Cypress.Commands.add( 'saveQuery', - ( - name, - description = ' ', - includeFilters = true, - includeTimeFilter = false, - savedQueriesNewUIEnabled = true // eslint-disable-line no-unused-vars - ) => { + (name, description = ' ', includeFilters = true, includeTimeFilter = false) => { cy.whenTestIdNotFound('saved-query-management-popover', () => { cy.getElementByTestId('saved-query-management-popover-button').click(); }); @@ -170,40 +162,57 @@ Cypress.Commands.add( saveAsNewQuery = false, includeFilters = true, includeTimeFilter = false, - savedQueriesNewUIEnabled = true // eslint-disable-line no-unused-vars + savedQueriesNewUIEnabled = true ) => { cy.whenTestIdNotFound('saved-query-management-popover', () => { cy.getElementByTestId('saved-query-management-popover-button').click(); }); - cy.getElementByTestId('saved-query-management-save-button').click(); + if (savedQueriesNewUIEnabled) { + cy.getElementByTestId('saved-query-management-save-button').click(); + + if (saveAsNewQuery) { + cy.getElementByTestId('saveAsNewQueryCheckbox') + .parent() + .find('[class="euiCheckbox__label"]') + .click(); + cy.getElementByTestId('saveQueryFormTitle').should('not.be.disabled').type(name); + + // Selecting the saveAsNewQuery element deselects the include time filter option. + if (includeTimeFilter === true) { + cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); + } + } else if (saveAsNewQuery === false) { + // defaults to not selected. - if (saveAsNewQuery) { - cy.getElementByTestId('saveAsNewQueryCheckbox') - .parent() - .find('[class="euiCheckbox__label"]') - .click(); - cy.getElementByTestId('saveQueryFormTitle').should('not.be.disabled').type(name); + if (includeTimeFilter !== true) { + cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); + } + } - // Selecting the saveAsNewQuery element deselects the include time filter option. - if (includeTimeFilter === true) { - cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); + if (includeFilters !== true) { + // Always defaults to selected. + cy.getElementByTestId('saveQueryFormIncludeFiltersOption').click(); } - } else if (saveAsNewQuery === false) { - // defaults to not selected. - if (includeTimeFilter !== true) { + // The force is necessary as there is occasionally a popover that covers the button + cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); + cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); + } else { + if (saveAsNewQuery) { + cy.getElementByTestId('saved-query-management-save-as-new-button').click(); + cy.getElementByTestId('saveQueryFormTitle').should('not.be.disabled').type(name); + } else { + cy.getElementByTestId('saved-query-management-save-changes-button').click(); + } + if (includeTimeFilter === true) { cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); } + if (includeFilters !== true) { + // Always defaults to selected. + cy.getElementByTestId('saveQueryFormIncludeFiltersOption').click(); + } + cy.getElementByTestId('savedQueryFormSaveButton').click(); } - - if (includeFilters !== true) { - // Always defaults to selected. - cy.getElementByTestId('saveQueryFormIncludeFiltersOption').click(); - } - - // The force is necessary as there is occasionally a popover that covers the button - cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); - cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); } ); diff --git a/cypress/utils/apps/data_explorer/index.d.ts b/cypress/utils/apps/data_explorer/index.d.ts index 5b9ca9745cd8..feb4df5a3d81 100644 --- a/cypress/utils/apps/data_explorer/index.d.ts +++ b/cypress/utils/apps/data_explorer/index.d.ts @@ -21,9 +21,8 @@ declare namespace Cypress { ): Chainable; /** * Deletes all filters in a Search. - * @param savedQueriesNewUIEnabled - Which UI to use. (defaults to true) */ - deleteAllFilters(savedQueriesNewUIEnabled: boolean): void; + deleteAllFilters(): void; /** * Save a query. * @param name - Name of the query @@ -36,8 +35,7 @@ declare namespace Cypress { name: string, description: string, includeFilters: boolean, - includeTimeFilter: boolean, - savedQueriesNewUIEnabled: boolean + includeTimeFilter: boolean ): Chainable; /** * Update a saved query. diff --git a/cypress/utils/apps/query_enhancements/saved_queries.js b/cypress/utils/apps/query_enhancements/saved_queries.js index 663a97524b11..dfbad0dc8f2b 100644 --- a/cypress/utils/apps/query_enhancements/saved_queries.js +++ b/cypress/utils/apps/query_enhancements/saved_queries.js @@ -519,15 +519,15 @@ export const verifyQueryDoesNotExistInSavedQueries = ( cy.getElementByTestId('saved-query-management-popover-button').click(); cy.getElementByTestId('saved-query-management-open-button').click(); cy.getElementByTestId('savedQueriesFlyoutBody').contains(deletedQueryName).should('not.exist'); + // Two references to two buttons layered over each other. + cy.getElementByTestId('euiFlyoutCloseButton').first().click({ force: true }); } else { cy.getElementByTestId('saved-query-management-popover-button').click(); cy.getElementByTestId('osdSavedQueryManagementList') .contains(deletedQueryName) .should('not.exist'); + cy.getElementByTestId('saved-query-management-popover-button').click(); } - - // Two references to two buttons layered over each other. - cy.getElementByTestId('euiFlyoutCloseButton').first().click({ force: true }); }; /** @@ -538,13 +538,13 @@ export const verifyQueryDoesNotExistInSavedQueries = ( export const updateAndVerifySavedQuery = (config, savedQueriesNewUIEnabled = true) => { // Create alternate config const alternateConfig = generateAlternateTestConfiguration(config); - cy.loadSaveQuery(config.saveName, true); + cy.loadSaveQuery(config.saveName, savedQueriesNewUIEnabled); // wait for saved query to load cy.wait(2000); if (alternateConfig.filters) { - cy.deleteAllFilters(savedQueriesNewUIEnabled); + cy.deleteAllFilters(); } setDatePickerDatesAndSearchIfRelevant(config.language, ALTERNATE_START_TIME, ALTERNATE_END_TIME); @@ -554,7 +554,7 @@ export const updateAndVerifySavedQuery = (config, savedQueriesNewUIEnabled = tru cy.updateSaveQuery('', false, true, true, savedQueriesNewUIEnabled); cy.reload(); - cy.loadSaveQuery(config.saveName, true); + cy.loadSaveQuery(config.saveName, savedQueriesNewUIEnabled); // wait for saved query to load cy.wait(2000); verifyAlternateDiscoverPageState(alternateConfig); @@ -587,5 +587,16 @@ export const validateSaveAsNewQueryMatchingNameHasError = ( cy.contains(SAVE_QUERY_CONFLICT_NAME_ERROR_TEXT).should('be.visible'); // Two references to two buttons layered over each other. cy.getElementByTestId('euiFlyoutCloseButton').first().click({ force: true }); + } else { + cy.whenTestIdNotFound('saved-query-management-popover', () => { + cy.getElementByTestId('saved-query-management-popover-button').click(); + }); + cy.getElementByTestId('saved-query-management-save-as-new-button').click(); + cy.getElementByTestId('saveQueryFormTitle').should('not.be.disabled').type(matchingName); + + cy.getElementByTestId('savedQueryFormSaveButton').click(); + + cy.contains(SAVE_QUERY_CONFLICT_NAME_ERROR_TEXT).should('be.visible'); + cy.getElementByTestId('savedQueryFormCancelButton').click(); } }; From 45f8096f81e31096ec2a71d5926175b0dbe95c5c Mon Sep 17 00:00:00 2001 From: "opensearch-changeset-bot[bot]" <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 04:22:54 +0000 Subject: [PATCH 26/36] Changeset file for PR #9229 created/updated --- changelogs/fragments/9229.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/fragments/9229.yml diff --git a/changelogs/fragments/9229.yml b/changelogs/fragments/9229.yml new file mode 100644 index 000000000000..970934ff73f9 --- /dev/null +++ b/changelogs/fragments/9229.yml @@ -0,0 +1,2 @@ +test: +- Add cypress integration test for the old and new UI view saved queries. ([#9229](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/9229)) \ No newline at end of file From 965d16ab9cdd96818acf6cf0dc74e9f8b0aed0fd Mon Sep 17 00:00:00 2001 From: Argus Li Date: Tue, 21 Jan 2025 09:15:13 -0800 Subject: [PATCH 27/36] Fix merge Signed-off-by: Argus Li --- .../apps/query_enhancements/saved_search.js | 534 ------------------ 1 file changed, 534 deletions(-) delete mode 100644 cypress/utils/apps/query_enhancements/saved_search.js diff --git a/cypress/utils/apps/query_enhancements/saved_search.js b/cypress/utils/apps/query_enhancements/saved_search.js deleted file mode 100644 index 4a01c8a81aa2..000000000000 --- a/cypress/utils/apps/query_enhancements/saved_search.js +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - DatasetTypes, - DATASOURCE_NAME, - END_TIME, - INDEX_PATTERN_WITH_TIME, - INDEX_WITH_TIME_1, - QueryLanguages, - START_TIME, - WORKSPACE_NAME, -} from './constants'; - -const randomString = Math.random().toString(36); - -/** - * randomized workspace name - * @constant - * @type {string} - * @default - */ -export const workspaceName = `${WORKSPACE_NAME}-${randomString.substring(7)}`; - -/** - * randomized datasource name - * @constant - * @type {string} - * @default - */ -export const datasourceName = `${DATASOURCE_NAME}-${randomString.substring(0, 18)}`; - -/** - * The fields to select for saved search. Also takes shape of the API for saved search - * @constant - * @type {string[]} - * @default - */ -export const SELECTED_FIELD_COLUMNS = ['bytes_transferred', 'personal.name']; - -/** - * The field to sort for saved search. - * @constant - * @type {string} - * @default - */ -export const APPLIED_SORT = 'bytes_transferred'; - -/** - * The API shape of the sorted field for saved search - * @constant - * @type {string[][]} - * @default - */ -export const APPLIED_SORT_API = [[APPLIED_SORT, 'desc']]; - -/** - * The filter configuration to use for saved search - * @constant - * @type {{field: string, operator: string, value: string}} - * @default - */ -export const APPLIED_FILTERS = { - field: 'category', - operator: 'is one of', - value: 'Application', -}; - -/** - * Returns the query string to use for a given dataset+language - * @param {string} dataset - the dataset name to use - * @param {QueryEnhancementLanguage} language - the name of query language - * @returns {string} - */ -const getQueryString = (dataset, language) => { - switch (language) { - case QueryLanguages.DQL.name: - return 'bytes_transferred > 9950'; - case QueryLanguages.Lucene.name: - return 'bytes_transferred: {9950 TO *}'; - case QueryLanguages.SQL.name: - return `SELECT * FROM ${dataset} WHERE bytes_transferred > 9950`; - case QueryLanguages.PPL.name: - return `source = ${dataset} | where bytes_transferred > 9950`; - default: - throw new Error(`getQueryString encountered unsupported language: ${language}`); - } -}; - -/** - * Returns the expected hit count, if relevant, for the provided datasetType + language - * @param {QueryEnhancementDataset} datasetType - the type of the dataset - * @param {QueryEnhancementLanguage} language - the query language name - * @returns {number|undefined} - */ -const getExpectedHitCount = (datasetType, language) => { - switch (datasetType) { - case DatasetTypes.INDEX_PATTERN.name: - switch (language) { - case QueryLanguages.DQL.name: - return 28; - case QueryLanguages.Lucene.name: - return 28; - case QueryLanguages.SQL.name: - return undefined; - case QueryLanguages.PPL.name: - // TODO: Update this to 101 once Histogram is supported on 2.17 - return undefined; - default: - throw new Error( - `getExpectedHitCount encountered unsupported language for ${datasetType}: ${language}` - ); - } - case DatasetTypes.INDEXES.name: - switch (language) { - case QueryLanguages.SQL.name: - return undefined; - case QueryLanguages.PPL.name: - // TODO: Update this to 50 once Histogram is supported on 2.17 - return undefined; - default: - throw new Error( - `getExpectedHitCount encountered unsupported language for ${datasetType}: ${language}` - ); - } - default: - throw new Error(`getExpectedHitCount encountered unsupported datasetType: ${datasetType}`); - } -}; - -/** - * returns an array of data present in the results table to check against. This is used to ensure that sorting is working as expected - * @param {QueryEnhancementDataset} datasetType - the type of the dataset - * @param {QueryEnhancementLanguage} language - the query language name - * @returns {[[number,string]]|*[]} An array of table data. For each element, 0th index is the index of the table cell, and 1st index is the value in that table cell - */ -const getSampleTableData = (datasetType, language) => { - switch (datasetType) { - case DatasetTypes.INDEX_PATTERN.name: - switch (language) { - case QueryLanguages.DQL.name: - return [ - [1, '9,998'], - [2, 'Phyllis Dach'], - ]; - case QueryLanguages.Lucene.name: - return [ - [1, '9,998'], - [2, 'Phyllis Dach'], - ]; - case QueryLanguages.SQL.name: - return []; - case QueryLanguages.PPL.name: - return []; - default: - throw new Error( - `getSampleTableData encountered unsupported language for ${datasetType}: ${language}` - ); - } - case DatasetTypes.INDEXES.name: - switch (language) { - case QueryLanguages.SQL.name: - return []; - case QueryLanguages.PPL.name: - return []; - default: - throw new Error( - `getSampleTableData encountered unsupported language for ${datasetType}: ${language}` - ); - } - default: - throw new Error(`getSampleTableData encountered unsupported datasetType: ${datasetType}`); - } -}; - -/** - * The configurations needed for saved search tests - * @typedef {Object} SavedSearchTestConfig - * @property {string} dataset - the dataset name to use - * @property {QueryEnhancementDataset} datasetType - the type of dataset - * @property {QueryEnhancementLanguage} language - the name of query language as it appears in the dashboard app - * @property {string} apiLanguage - the name of query language as recognized by OpenSearch API - * @property {string} saveName - the name to use when saving the saved search - * @property {string} testName - the phrase to add to the test case's title - * @property {boolean} filters - whether the language supports filtering - * @property {boolean} histogram - whether the language supports histogram - * @property {boolean} selectFields - whether the language supports selecting fields to view data - * @property {boolean} sort - whether the language supports sorting by fields - * @property {string} queryString - the query to use for saved search associated with the language - * @property {number|undefined} hitCount - the hitCount of the applied search config, if relevant - * @property {[[number,string]]|*[]} sampleTableData - an array of some table data to test against to ensure that sorting is working as expected - */ - -/** - * Returns the SavedSearchTestConfig for the provided dataset, datasetType, and language - * @param {string} dataset - the dataset name - * @param {QueryEnhancementDataset} datasetType - the type of the dataset - * @param {QueryEnhancementLanguageData} language - the relevant data for the query language to use - * @returns {SavedSearchTestConfig} - */ -const generateTestConfiguration = (dataset, datasetType, language) => { - const baseConfig = { - dataset, - datasetType, - language: language.name, - apiLanguage: language.apiName, - saveName: `${language.name}-${datasetType}`, - testName: `${language.name}-${datasetType}`, - ...language.supports, - }; - - return { - ...baseConfig, - queryString: getQueryString(dataset, language.name), - hitCount: getExpectedHitCount(datasetType, language.name), - sampleTableData: getSampleTableData(datasetType, language.name), - }; -}; - -/** - * Returns an array of test configurations for every query language + dataset permutation - * @returns {SavedSearchTestConfig[]} - */ -export const generateAllTestConfigurations = () => { - return Object.values(DatasetTypes).flatMap((dataset) => - dataset.supportedLanguages.map((language) => { - let datasetToUse; - switch (dataset.name) { - case DatasetTypes.INDEX_PATTERN.name: - datasetToUse = INDEX_PATTERN_WITH_TIME; - break; - case DatasetTypes.INDEXES.name: - datasetToUse = INDEX_WITH_TIME_1; - break; - default: - throw new Error( - `generateAllTestConfigurations encountered unsupported dataset: ${dataset.name}` - ); - } - return generateTestConfiguration(datasetToUse, dataset.name, language); - }) - ); -}; - -/** - * Sets the top nav date if it is relevant for the passed language - * @param {QueryEnhancementLanguage} language - query language - */ -export const setDatePickerDatesAndSearchIfRelevant = (language) => { - if (language !== QueryLanguages.SQL.name) { - cy.setTopNavDate(START_TIME, END_TIME); - } -}; - -/** - * Set the search configurations for the saved search - * @param {SavedSearchTestConfig} testConfig - the relevant config for the test case - */ -export const setSearchConfigurations = ({ - filters, - queryString, - histogram, - selectFields, - sort, -}) => { - if (filters) { - cy.submitFilterFromDropDown( - APPLIED_FILTERS.field, - APPLIED_FILTERS.operator, - APPLIED_FILTERS.value, - true - ); - } - - cy.setQueryEditor(queryString, { parseSpecialCharSequences: false }); - - if (histogram) { - cy.getElementByTestId('discoverIntervalSelect').select('w'); - } - - if (selectFields) { - for (const field of SELECTED_FIELD_COLUMNS) { - cy.getElementByTestId(`fieldToggle-${field}`).click(); - } - - cy.getElementByTestId('querySubmitButton').should('be.visible'); - } - - if (sort) { - cy.getElementByTestId(`docTableHeaderFieldSort_${APPLIED_SORT}`).click(); - - // stop sorting based on timestamp - cy.getElementByTestId('docTableHeaderFieldSort_timestamp').click(); - cy.getElementByTestId('docTableHeaderFieldSort_timestamp').trigger('mouseover'); - cy.contains('div', 'Sort timestamp ascending').should('be.visible'); - - cy.getElementByTestId(`docTableHeaderFieldSort_${APPLIED_SORT}`).click(); - - // TODO: This reload shouldn't need to be here, but currently the sort doesn't always happen right away - // https://github.com/opensearch-project/OpenSearch-Dashboards/issues/9131 - cy.reload(); - cy.getElementByTestId('querySubmitButton').should('be.visible'); - } -}; - -/** - * Verify that the discover page is in the correct state after setSearchConfigurations have been run - * @param {SavedSearchTestConfig} testConfig - the relevant config for the test case - */ -export const verifyDiscoverPageState = ({ - dataset, - queryString, - language, - hitCount, - filters, - histogram, - selectFields, - sampleTableData, -}) => { - cy.getElementByTestId('datasetSelectorButton').contains(dataset); - if ([QueryLanguages.SQL.name, QueryLanguages.PPL.name].includes(language)) { - cy.getElementByTestId('osdQueryEditor__multiLine').contains(queryString); - } else { - cy.getElementByTestId('osdQueryEditor__singleLine').contains(queryString); - } - cy.getElementByTestId('queryEditorLanguageSelector').contains(language); - - if (filters) { - cy.getElementByTestId( - `filter filter-enabled filter-key-${APPLIED_FILTERS.field} filter-value-${APPLIED_FILTERS.value} filter-unpinned ` - ).should('exist'); - } - if (hitCount) { - cy.verifyHitCount(hitCount); - } - - if (histogram) { - // TODO: Uncomment this once bug is fixed, currently the interval is not saving - // https://github.com/opensearch-project/OpenSearch-Dashboards/issues/9077 - // cy.getElementByTestId('discoverIntervalSelect').should('have.value', 'w'); - } - - if (selectFields) { - cy.getElementByTestId('docTableHeaderField').should('have.length', 3); - cy.getElementByTestId('docTableHeader-timestamp').should('be.visible'); - for (const field of SELECTED_FIELD_COLUMNS) { - cy.getElementByTestId(`docTableHeader-${field}`).should('be.visible'); - cy.getElementByTestId(`docTableHeader-${field}`).should('be.visible'); - } - } - // verify first row to ensure sorting is working, but ignore the timestamp field as testing environment might have differing timezones - sampleTableData.forEach(([index, value]) => { - cy.getElementByTestId('osdDocTableCellDataField').eq(index).contains(value); - }); -}; - -/** - * After a saved search have been saved, verify the data in the assets page - * @param {SavedSearchTestConfig} testConfig - the relevant config for the test case - */ -export const verifySavedSearchInAssetsPage = ({ - apiLanguage, - dataset, - saveName, - queryString, - datasetType, - histogram, - selectFields, - sort, - filters, -}) => { - cy.navigateToWorkSpaceSpecificPage({ - workspaceName: workspaceName, - page: 'objects', - isEnhancement: true, - }); - - // TODO: Currently this test will only work if the last saved object is the relevant savedSearch - // Update below to make it work without that requirement. - cy.getElementByTestId('euiCollapsedItemActionsButton').last().click(); - - cy.intercept('POST', '/w/*/api/saved_objects/_bulk_get').as('savedObjectResponse'); - cy.getElementByTestId('savedObjectsTableAction-inspect').click(); - - cy.wait('@savedObjectResponse').then((interception) => { - const savedObjectAttributes = interception.response.body.saved_objects[0].attributes; - const searchSource = savedObjectAttributes.kibanaSavedObjectMeta.searchSourceJSON; - - expect(savedObjectAttributes.title).eq(saveName); - if (selectFields) { - expect(savedObjectAttributes.columns).eqls(SELECTED_FIELD_COLUMNS); - } - if (sort) { - expect(savedObjectAttributes.sort).eqls(APPLIED_SORT_API); - } - expect(searchSource).match( - // all special characters must be escaped - new RegExp(`"query":"${queryString.replaceAll(/([*{}])/g, (char) => `\\${char}`)}"`) - ); - expect(searchSource).match(new RegExp(`"language":"${apiLanguage}"`)); - expect(searchSource).match(new RegExp(`"title":"${dataset.replace('*', '\\*')}"`)); - expect(searchSource).match(new RegExp(`"type":"${datasetType}"`)); - - if (histogram) { - expect(searchSource).match(/"calendar_interval":"1w"/); - } - if (filters) { - expect(searchSource).match( - new RegExp(`"match_phrase":\{"${APPLIED_FILTERS.field}":"${APPLIED_FILTERS.value}"\}`) - ); - } - }); -}; - -/** - * Returns the API body that is needed when creating a saved search directly through an API call - * @param {SavedSearchTestConfig} config - language + dataset permutation configuration - * @param {string} workspaceId - workspace ID - * @param {string} datasourceId - datasource ID - * @param {string} indexPatternId - index pattern ID - * @returns {object} - */ -const getSavedObjectPostBody = (config, workspaceId, datasourceId, indexPatternId) => { - return { - attributes: { - title: config.saveName, - description: '', - hits: 0, - columns: config.selectFields ? SELECTED_FIELD_COLUMNS : undefined, - sort: config.sort ? APPLIED_SORT_API : undefined, - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: `{"query":{"query":"${config.queryString}","language":"${ - config.apiLanguage - }","dataset":${`{"id":"${ - config.datasetType === DatasetTypes.INDEX_PATTERN.name - ? indexPatternId - : `${datasourceId}::${config.dataset}` - }","timeFieldName":"timestamp","title":"${config.dataset}","type":"${ - config.datasetType - }"}`}},"highlightAll":true,"version":true,"aggs":{"2":{"date_histogram":{"field":"timestamp","calendar_interval":"1w","time_zone":"America/Los_Angeles","min_doc_count":1}}},"filter":[{"$state":{"store":"appState"},"meta":{"alias":null,"disabled":false,"key":"${ - APPLIED_FILTERS.field - }","negate":false,"params":["${APPLIED_FILTERS.value}"],"type":"phrases","value":"${ - APPLIED_FILTERS.value - }","indexRefName":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index"},"query":{"bool":{"minimum_should_match":1,"should":[{"match_phrase":{"${ - APPLIED_FILTERS.field - }":"${ - APPLIED_FILTERS.value - }"}}]}}}],"indexRefName":"kibanaSavedObjectMeta.searchSourceJSON.index"}`, - }, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - workspaces: [workspaceId], - }; -}; - -/** - * send a POST request to API to create a saved search object - * @param {SavedSearchTestConfig} config - the relevant config for the test case - */ -export const postRequestSaveSearch = (config) => { - cy.get('@WORKSPACE_ID').then((workspaceId) => { - cy.get('@DATASOURCE_ID').then((datasourceId) => { - cy.get('@INDEX_PATTERN_ID').then((indexPatternId) => { - // POST a saved search - cy.request({ - method: 'POST', - url: `/w/${workspaceId}/api/saved_objects/search?overwrite=true`, - headers: { - 'Content-Type': 'application/json; charset=utf-8', - 'osd-xsrf': true, - }, - body: getSavedObjectPostBody(config, workspaceId, datasourceId, indexPatternId), - failOnStatusCode: false, - }); - }); - }); - }); -}; - -/** - * Loads a saved search and updates it and verify that it is correct - * @param {SavedSearchTestConfig} config - the relevant config for the test case - * @param {boolean} saveAsNew - flag to determine whether to overwrite the saved search (false) or save as a new saved search (true) - */ -export const updateSavedSearchAndSaveAndVerify = (config, saveAsNew) => { - const saveName = config.saveName; - - cy.navigateToWorkSpaceSpecificPage({ - workspaceName: workspaceName, - page: 'discover', - isEnhancement: true, - }); - cy.loadSaveSearch(saveName); - - // Change the dataset type to use - const [newDataset, newDatasetType] = - config.datasetType === DatasetTypes.INDEX_PATTERN.name - ? [INDEX_WITH_TIME_1, DatasetTypes.INDEXES.name] - : [INDEX_PATTERN_WITH_TIME, DatasetTypes.INDEX_PATTERN.name]; - // If current language is PPL, update to OpenSearch SQL, else update to PPL - const newLanguage = - config.language === QueryLanguages.PPL.name ? QueryLanguages.SQL : QueryLanguages.PPL; - const newConfig = generateTestConfiguration(newDataset, newDatasetType, newLanguage); - - cy.setDataset(newConfig.dataset, datasourceName, newConfig.datasetType); - cy.setQueryLanguage(newConfig.language); - setDatePickerDatesAndSearchIfRelevant(newConfig.language); - setSearchConfigurations({ - ...newConfig, - // only select field if previous config did not select it, because otherwise it is already selected - selectFields: !config.selectFields ? newConfig.selectFields : false, - }); - cy.saveSearch(saveName, saveAsNew); - - // Load updated saved search and verify - cy.getElementByTestId('discoverNewButton').click(); - cy.loadSaveSearch(saveName, saveAsNew); - setDatePickerDatesAndSearchIfRelevant(newConfig.language); - verifyDiscoverPageState(newConfig); -}; From cc389906fd00d8a9bcb97a7eeed5c9ae939932ae Mon Sep 17 00:00:00 2001 From: Argus Li Date: Tue, 21 Jan 2025 10:03:07 -0800 Subject: [PATCH 28/36] Move data-test-subj changes to another PR. Signed-off-by: Argus Li --- .../public/ui/saved_query_flyouts/open_saved_query_flyout.tsx | 3 +-- .../data/public/ui/saved_query_flyouts/saved_query_card.tsx | 1 - src/plugins/data/public/ui/saved_query_form/helpers.tsx | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/plugins/data/public/ui/saved_query_flyouts/open_saved_query_flyout.tsx b/src/plugins/data/public/ui/saved_query_flyouts/open_saved_query_flyout.tsx index 88b428b8b999..d9c2941adc8d 100644 --- a/src/plugins/data/public/ui/saved_query_flyouts/open_saved_query_flyout.tsx +++ b/src/plugins/data/public/ui/saved_query_flyouts/open_saved_query_flyout.tsx @@ -325,7 +325,7 @@ export function OpenSavedQueryFlyout({

Saved queries

- + {selectedTabId === OPEN_QUERY_TAB_ID.SAVED_QUERIES ? 'Open' : 'Copy'} query
diff --git a/src/plugins/data/public/ui/saved_query_flyouts/saved_query_card.tsx b/src/plugins/data/public/ui/saved_query_flyouts/saved_query_card.tsx index 3fa417a1696d..a6e157b1222c 100644 --- a/src/plugins/data/public/ui/saved_query_flyouts/saved_query_card.tsx +++ b/src/plugins/data/public/ui/saved_query_flyouts/saved_query_card.tsx @@ -111,7 +111,6 @@ export function SavedQueryCard({ { setShowDeletionConfirmationModal(true); }} diff --git a/src/plugins/data/public/ui/saved_query_form/helpers.tsx b/src/plugins/data/public/ui/saved_query_form/helpers.tsx index 13e72c3cb39c..f057326d3f1b 100644 --- a/src/plugins/data/public/ui/saved_query_form/helpers.tsx +++ b/src/plugins/data/public/ui/saved_query_form/helpers.tsx @@ -175,7 +175,6 @@ export function useSaveQueryFormContent({ id="save-as-new-query" onChange={(event) => setSaveAsNew?.(event.target.checked)} checked={saveAsNew} - data-test-subj="saveAsNewQueryCheckbox" label={i18n.translate('data.search.searchBar.SaveAsNewLabelText', { defaultMessage: 'Save as new query', })} From a0e09b207f0a462c91c11645001ed4ec14f1ab3b Mon Sep 17 00:00:00 2001 From: Argus Li Date: Wed, 22 Jan 2025 11:56:25 -0800 Subject: [PATCH 29/36] Remove savedQueriesNewUI Signed-off-by: Argus Li --- .../saved_queries_flyout.spec.js | 14 +- .../saved_queries_popover.spec.js | 170 ------------------ cypress/utils/apps/data_explorer/commands.js | 111 ++++-------- cypress/utils/apps/data_explorer/index.d.ts | 8 +- .../apps/query_enhancements/saved_queries.js | 108 +++-------- 5 files changed, 73 insertions(+), 338 deletions(-) delete mode 100644 cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_popover.spec.js diff --git a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js index c71a09474792..f2c0f3ade3f4 100644 --- a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js +++ b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js @@ -95,7 +95,7 @@ export const runSavedQueriesFlyoutUITests = () => { setQueryConfigurations(config); verifyDiscoverPageState(config); - cy.saveQuery(config.saveName, ' ', true, true, true); + cy.saveQuery(config.saveName, ' ', true, true); }); }); }); @@ -110,14 +110,14 @@ export const runSavedQueriesFlyoutUITests = () => { 'Aug 30, 2020 @ 00:00:00.000' ); - cy.loadSaveQuery(config.saveName, true); + cy.loadSaveQuery(config.saveName); // wait for saved queries to load. cy.wait(2000); verifyDiscoverPageState(config); }); it(`should update the loaded saved query: ${config.testName}`, () => { - updateAndVerifySavedQuery(config, true); + updateAndVerifySavedQuery(config); }); const saveAsNewQueryName = config.testName + SAVE_AS_NEW_QUERY_SUFFIX; @@ -130,10 +130,10 @@ export const runSavedQueriesFlyoutUITests = () => { setQueryConfigurations(config); verifyDiscoverPageState(config); validateSaveAsNewQueryMatchingNameHasError(config.saveName); - cy.updateSaveQuery(saveAsNewQueryName, true, true, true, true); + cy.updateSaveQuery(saveAsNewQueryName, true, true, true); cy.reload(); - cy.loadSaveQuery(saveAsNewQueryName, true); + cy.loadSaveQuery(saveAsNewQueryName); // wait for saved query to load cy.wait(2000); verifyDiscoverPageState(config); @@ -146,8 +146,8 @@ export const runSavedQueriesFlyoutUITests = () => { isEnhancement: true, }); - cy.deleteSaveQuery(saveAsNewQueryName, true); - verifyQueryDoesNotExistInSavedQueries(saveAsNewQueryName, true); + cy.deleteSaveQuery(saveAsNewQueryName); + verifyQueryDoesNotExistInSavedQueries(saveAsNewQueryName); }); }); }); diff --git a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_popover.spec.js b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_popover.spec.js deleted file mode 100644 index b8f30fcb7e45..000000000000 --- a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_popover.spec.js +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - INDEX_PATTERN_WITH_TIME, - INDEX_WITH_TIME_1, - INDEX_WITH_TIME_2, - SECONDARY_ENGINE, - START_TIME, - END_TIME, -} from '../../../../../utils/constants'; - -import { - generateAllTestConfigurations, - verifyDiscoverPageState, - verifyValidSavedQueriesShownOnVisualize, - verifyQueryDoesNotExistInSavedQueries, - setQueryConfigurations, - updateAndVerifySavedQuery, - SAVE_AS_NEW_QUERY_SUFFIX, - validateSaveAsNewQueryMatchingNameHasError, -} from '../../../../../utils/apps/query_enhancements/saved_queries'; - -import { - getRandomizedWorkspaceName, - getRandomizedDatasourceName, - setDatePickerDatesAndSearchIfRelevant, -} from '../../../../../utils/apps/query_enhancements/shared'; - -const workspaceName = getRandomizedWorkspaceName(); -const datasourceName = getRandomizedDatasourceName(); - -// This spec assumes data.savedQueriesNewUI.enabled is false. -// These tests will not be run until the older legacy tests are migrated https://github.com/opensearch-project/OpenSearch-Dashboards/pull/9166#discussion_r1913687440 -export const runSavedQueriesPopoverUITests = () => { - describe.skip('saved queries popover UI', () => { - before(() => { - // Load test data - cy.setupTestData( - SECONDARY_ENGINE.url, - [ - `cypress/fixtures/query_enhancements/data_logs_1/${INDEX_WITH_TIME_1}.mapping.json`, - `cypress/fixtures/query_enhancements/data_logs_2/${INDEX_WITH_TIME_2}.mapping.json`, - ], - [ - `cypress/fixtures/query_enhancements/data_logs_1/${INDEX_WITH_TIME_1}.data.ndjson`, - `cypress/fixtures/query_enhancements/data_logs_2/${INDEX_WITH_TIME_2}.data.ndjson`, - ] - ); - // Add data source - cy.addDataSource({ - name: datasourceName, - url: SECONDARY_ENGINE.url, - authType: 'no_auth', - }); - - // Create workspace - cy.deleteWorkspaceByName(workspaceName); - cy.visit('/app/home'); - cy.createInitialWorkspaceWithDataSource(datasourceName, workspaceName); - cy.createWorkspaceIndexPatterns({ - workspaceName: workspaceName, - indexPattern: INDEX_PATTERN_WITH_TIME.replace('*', ''), - timefieldName: 'timestamp', - dataSource: datasourceName, - isEnhancement: true, - }); - }); - - after(() => { - // No need to explicitly delete all saved queries as deleting the workspace will delete associated saved queries - cy.deleteWorkspaceByName(workspaceName); - // // TODO: Modify deleteIndex to handle an array of index and remove hard code - cy.deleteDataSourceByName(datasourceName); - cy.deleteIndex(INDEX_WITH_TIME_1); - cy.deleteIndex(INDEX_WITH_TIME_2); - }); - - const testConfigurations = generateAllTestConfigurations(); - - describe('should create initial saved queries', () => { - testConfigurations.forEach((config) => { - it(`should successfully create a saved query for ${config.testName}`, () => { - cy.navigateToWorkSpaceSpecificPage({ - workspaceName, - page: 'discover', - isEnhancement: true, - }); - - cy.setDataset(config.dataset, datasourceName, config.datasetType); - - cy.setQueryLanguage(config.language); - setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); - - setQueryConfigurations(config); - verifyDiscoverPageState(config); - cy.saveQuery(config.saveName, ' ', true, true, false); - }); - }); - }); - - describe('should test loading, saving and deleting saved queries', () => { - testConfigurations.forEach((config) => { - it(`should load saved query: ${config.testName}`, () => { - cy.getElementByTestId('discoverNewButton').click(); - setDatePickerDatesAndSearchIfRelevant( - config.language, - 'Aug 29, 2020 @ 00:00:00.000', - 'Aug 30, 2020 @ 00:00:00.000' - ); - - cy.loadSaveQuery(config.saveName, false); - // wait for saved queries to load. - cy.wait(2000); - verifyDiscoverPageState(config); - }); - - it(`should update the loaded saved query: ${config.testName}`, () => { - updateAndVerifySavedQuery(config, false); - }); - - const saveAsNewQueryName = config.testName + SAVE_AS_NEW_QUERY_SUFFIX; - it(`should modify saved query: ${config.testName} and save as new query: ${saveAsNewQueryName}`, () => { - if (config.filters) { - cy.deleteAllFilters(); - } - setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); - - setQueryConfigurations(config); - verifyDiscoverPageState(config); - validateSaveAsNewQueryMatchingNameHasError(config.saveName, false); - cy.updateSaveQuery(saveAsNewQueryName, true, true, true, false); - - cy.reload(); - cy.getElementByTestId('discoverNewButton'); - cy.loadSaveQuery(saveAsNewQueryName, false); - // wait for saved query to load - cy.wait(2000); - verifyDiscoverPageState(config); - }); - - it(`should delete the saved query: ${saveAsNewQueryName}`, () => { - cy.navigateToWorkSpaceSpecificPage({ - workspaceName, - page: 'discover', - isEnhancement: true, - }); - - cy.deleteSaveQuery(saveAsNewQueryName, false); - verifyQueryDoesNotExistInSavedQueries(saveAsNewQueryName, false); - }); - }); - }); - describe('should only show valid saved queries in the Visualization page', () => { - it('should only show DQL and Lucene saved Queries', () => { - cy.navigateToWorkSpaceSpecificPage({ - workspaceName, - page: 'visualize', - isEnhancement: true, - }); - - verifyValidSavedQueriesShownOnVisualize(false); - }); - }); - }); -}; - -runSavedQueriesPopoverUITests(); diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index 0d9a93e87181..8c8fe68f6682 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -145,78 +145,50 @@ Cypress.Commands.add( Cypress.Commands.add( 'updateSaveQuery', - ( - name = '', - saveAsNewQuery = false, - includeFilters = true, - includeTimeFilter = false, - savedQueriesNewUIEnabled = true - ) => { + (name = '', saveAsNewQuery = false, includeFilters = true, includeTimeFilter = false) => { cy.whenTestIdNotFound('saved-query-management-popover', () => { cy.getElementByTestId('saved-query-management-popover-button').click(); }); - if (savedQueriesNewUIEnabled) { - cy.getElementByTestId('saved-query-management-save-button').click(); - - if (saveAsNewQuery) { - cy.getElementByTestId('saveAsNewQueryCheckbox') - .parent() - .find('[class="euiCheckbox__label"]') - .click(); - cy.getElementByTestId('saveQueryFormTitle').should('not.be.disabled').type(name); - - // Selecting the saveAsNewQuery element deselects the include time filter option. - if (includeTimeFilter === true) { - cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); - } - } else if (saveAsNewQuery === false) { - // defaults to not selected. - - if (includeTimeFilter !== true) { - cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); - } - } + cy.getElementByTestId('saved-query-management-save-button').click(); - if (includeFilters !== true) { - // Always defaults to selected. - cy.getElementByTestId('saveQueryFormIncludeFiltersOption').click(); - } + if (saveAsNewQuery) { + cy.getElementByTestId('saveAsNewQueryCheckbox') + .parent() + .find('[class="euiCheckbox__label"]') + .click(); + cy.getElementByTestId('saveQueryFormTitle').should('not.be.disabled').type(name); - // The force is necessary as there is occasionally a popover that covers the button - cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); - cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); - } else { - if (saveAsNewQuery) { - cy.getElementByTestId('saved-query-management-save-as-new-button').click(); - cy.getElementByTestId('saveQueryFormTitle').should('not.be.disabled').type(name); - } else { - cy.getElementByTestId('saved-query-management-save-changes-button').click(); - } + // Selecting the saveAsNewQuery element deselects the include time filter option. if (includeTimeFilter === true) { cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); } - if (includeFilters !== true) { - // Always defaults to selected. - cy.getElementByTestId('saveQueryFormIncludeFiltersOption').click(); + } else if (saveAsNewQuery === false) { + // defaults to not selected. + + if (includeTimeFilter !== true) { + cy.getElementByTestId('saveQueryFormIncludeTimeFilterOption').click(); } - cy.getElementByTestId('savedQueryFormSaveButton').click(); } + + if (includeFilters !== true) { + // Always defaults to selected. + cy.getElementByTestId('saveQueryFormIncludeFiltersOption').click(); + } + + // The force is necessary as there is occasionally a popover that covers the button + cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); + cy.getElementByTestId('euiToastHeader').contains('was saved').should('be.visible'); } ); -Cypress.Commands.add('loadSaveQuery', (name, savedQueriesNewUIEnabled = true) => { - if (savedQueriesNewUIEnabled) { - cy.getElementByTestId('saved-query-management-popover-button').click(); +Cypress.Commands.add('loadSaveQuery', (name) => { + cy.getElementByTestId('saved-query-management-popover-button').click(); - cy.getElementByTestId('saved-query-management-open-button').click(); + cy.getElementByTestId('saved-query-management-open-button').click(); - cy.getElementByTestId('euiFlyoutCloseButton').parent().contains(name).should('exist').click(); + cy.getElementByTestId('euiFlyoutCloseButton').parent().contains(name).should('exist').click(); - cy.getElementByTestId('open-query-action-button').click(); - } else { - cy.getElementByTestId('saved-query-management-popover-button').click(); - cy.getElementByTestId('save-query-panel').contains(name).should('exist').click(); - } + cy.getElementByTestId('open-query-action-button').click(); }); Cypress.Commands.add('clearSaveQuery', () => { @@ -227,26 +199,17 @@ Cypress.Commands.add('clearSaveQuery', () => { cy.getElementByTestId('saved-query-management-clear-button').click(); }); -Cypress.Commands.add('deleteSaveQuery', (name, savedQueriesNewUIEnabled = true) => { - if (savedQueriesNewUIEnabled) { - cy.getElementByTestId('saved-query-management-popover-button').click(); - - cy.getElementByTestId('saved-query-management-open-button').click(); - cy.getElementByTestId('euiFlyoutCloseButton') - .parent() - .contains(name) - .findElementByTestId('deleteSavedQueryButton') - .click(); +Cypress.Commands.add('deleteSaveQuery', (name) => { + cy.getElementByTestId('saved-query-management-popover-button').click(); - cy.getElementByTestId('confirmModalConfirmButton').click(); - } else { - cy.getElementByTestId('saved-query-management-popover-button').click(); + cy.getElementByTestId('saved-query-management-open-button').click(); + cy.getElementByTestId('euiFlyoutCloseButton') + .parent() + .contains(name) + .findElementByTestId('deleteSavedQueryButton') + .click(); - cy.getElementByTestIdLike(`delete-saved-query-${name}-button`).click({ - force: true, - }); - cy.getElementByTestId('confirmModalConfirmButton').click(); - } + cy.getElementByTestId('confirmModalConfirmButton').click(); }); Cypress.Commands.add('switchDiscoverTable', (name) => { diff --git a/cypress/utils/apps/data_explorer/index.d.ts b/cypress/utils/apps/data_explorer/index.d.ts index daf0c498eccf..95805f36e5a5 100644 --- a/cypress/utils/apps/data_explorer/index.d.ts +++ b/cypress/utils/apps/data_explorer/index.d.ts @@ -29,7 +29,6 @@ declare namespace Cypress { * @param description - Description of the query * @param includeFilters - Save filters * @param includeTimeFilter - Save Time filter - * @param savedQueriesNewUIEnabled - Which UI to use. (defaults to true) */ saveQuery( name: string, @@ -43,21 +42,18 @@ declare namespace Cypress { * @param saveAsNewQuery - Save as a new query. * @param includeFilters - Save filters. * @param includeTimeFilter - Save Time filter. - * @param savedQueriesNewUIEnabled - Which UI to use. (defaults to true) */ updateSaveQuery( name: string, saveAsNewQuery: boolean, includeFilters?: boolean, - includeTimeFilter?: boolean, - savedQueriesNewUIEnabled?: boolean + includeTimeFilter?: boolean ): void; /** * Load a saved query. * @param name - Name of saved query. - * @param savedQueriesNewUIEnabled - Which UI to use. (defaults to true) */ - loadSaveQuery(name: string, savedQueriesNewUIEnabled?: boolean): Chainable; + loadSaveQuery(name: string): Chainable; clearSaveQuery(): Chainable; deleteSaveQuery(name: string): Chainable; switchDiscoverTable(name: string): Chainable; diff --git a/cypress/utils/apps/query_enhancements/saved_queries.js b/cypress/utils/apps/query_enhancements/saved_queries.js index dfbad0dc8f2b..8c387af8ddec 100644 --- a/cypress/utils/apps/query_enhancements/saved_queries.js +++ b/cypress/utils/apps/query_enhancements/saved_queries.js @@ -15,7 +15,7 @@ import { SAVE_QUERY_CONFLICT_NAME_ERROR_TEXT, } from './constants'; -import { APPLIED_FILTERS } from './saved_search'; +import { APPLIED_FILTERS } from './saved'; /** * Suffix when saving as new query. @@ -481,64 +481,27 @@ export const setAlternateQueryConfigurations = ({ filters, queryString, histogra } }; -/** - * Verify that only DQL and Lucene saved queries are shown in the Visualize page. - * @param {boolean} savedQueriesNewUIEnabled - Has this flag been enabled (default is true) - */ -export const verifyValidSavedQueriesShownOnVisualize = (savedQueriesNewUIEnabled = true) => { - if (savedQueriesNewUIEnabled) { - // Currently functionality has not been implemented for savedQueriesNewUI - } else { - cy.getElementByTestId('createVisualizationPromptButton').click(); - cy.getElementByTestId('visType-table').click(); - cy.getElementByTestId('savedObjectFinderItemList') - .findElementByTestIdLike('savedObjectTitledata') - .click(); - - cy.getElementByTestId('showFilterActions').click(); - cy.getElementByTestId('savedQueries').click(); - - cy.getElementByTestId('save-query-panel').contains('DQL'); - cy.getElementByTestId('save-query-panel').contains('Lucene'); - cy.getElementByTestId('save-query-panel').contains('OpenSearch SQL').should('not.exist'); - cy.getElementByTestId('save-query-panel').contains('PPL').should('not.exist'); - } -}; - /** * Verify query does not exist in saved queries. * @param {string} deletedQueryName - Name of the query that should not exist. - * @param {boolean} savedQueriesNewUIEnabled - Has this flag been enabled (default is true) */ -export const verifyQueryDoesNotExistInSavedQueries = ( - deletedQueryName, - savedQueriesNewUIEnabled = true -) => { +export const verifyQueryDoesNotExistInSavedQueries = (deletedQueryName) => { cy.reload(); - if (savedQueriesNewUIEnabled) { - cy.getElementByTestId('saved-query-management-popover-button').click(); - cy.getElementByTestId('saved-query-management-open-button').click(); - cy.getElementByTestId('savedQueriesFlyoutBody').contains(deletedQueryName).should('not.exist'); - // Two references to two buttons layered over each other. - cy.getElementByTestId('euiFlyoutCloseButton').first().click({ force: true }); - } else { - cy.getElementByTestId('saved-query-management-popover-button').click(); - cy.getElementByTestId('osdSavedQueryManagementList') - .contains(deletedQueryName) - .should('not.exist'); - cy.getElementByTestId('saved-query-management-popover-button').click(); - } + cy.getElementByTestId('saved-query-management-popover-button').click(); + cy.getElementByTestId('saved-query-management-open-button').click(); + cy.getElementByTestId('savedQueriesFlyoutBody').contains(deletedQueryName).should('not.exist'); + // Two references to two buttons layered over each other. + cy.getElementByTestId('euiFlyoutCloseButton').first().click({ force: true }); }; /** * Update and save the saved query with alternate config, then verify has been updated correctly. * @param {SavedSearchTestConfig} config - the config for the test case to be updated - * @param {boolean} savedQueriesNewUIEnabled - Has this flag been enabled (default is true) */ -export const updateAndVerifySavedQuery = (config, savedQueriesNewUIEnabled = true) => { +export const updateAndVerifySavedQuery = (config) => { // Create alternate config const alternateConfig = generateAlternateTestConfiguration(config); - cy.loadSaveQuery(config.saveName, savedQueriesNewUIEnabled); + cy.loadSaveQuery(config.saveName); // wait for saved query to load cy.wait(2000); @@ -551,10 +514,10 @@ export const updateAndVerifySavedQuery = (config, savedQueriesNewUIEnabled = tru setAlternateQueryConfigurations(alternateConfig); verifyAlternateDiscoverPageState(alternateConfig); - cy.updateSaveQuery('', false, true, true, savedQueriesNewUIEnabled); + cy.updateSaveQuery('', false, true, true); cy.reload(); - cy.loadSaveQuery(config.saveName, savedQueriesNewUIEnabled); + cy.loadSaveQuery(config.saveName); // wait for saved query to load cy.wait(2000); verifyAlternateDiscoverPageState(alternateConfig); @@ -563,40 +526,23 @@ export const updateAndVerifySavedQuery = (config, savedQueriesNewUIEnabled = tru /** * Save as new query, and validate that saving as an existing name leads to the correct error message. * @param {string} matchingName - the name of an existing saved query - * @param {boolean} savedQueriesNewUIEnabled - Has this flag been enabled (default is true) */ -export const validateSaveAsNewQueryMatchingNameHasError = ( - matchingName, - savedQueriesNewUIEnabled = true -) => { - if (savedQueriesNewUIEnabled) { - cy.whenTestIdNotFound('saved-query-management-popover', () => { - cy.getElementByTestId('saved-query-management-popover-button').click(); - }); - cy.getElementByTestId('saved-query-management-save-button').click(); - - cy.getElementByTestId('saveAsNewQueryCheckbox') - .parent() - .find('[class="euiCheckbox__label"]') - .click(); - cy.getElementByTestId('saveQueryFormTitle').should('not.be.disabled').type(matchingName); - - // The force is necessary as there is occasionally a popover that covers the button - cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); - - cy.contains(SAVE_QUERY_CONFLICT_NAME_ERROR_TEXT).should('be.visible'); - // Two references to two buttons layered over each other. - cy.getElementByTestId('euiFlyoutCloseButton').first().click({ force: true }); - } else { - cy.whenTestIdNotFound('saved-query-management-popover', () => { - cy.getElementByTestId('saved-query-management-popover-button').click(); - }); - cy.getElementByTestId('saved-query-management-save-as-new-button').click(); - cy.getElementByTestId('saveQueryFormTitle').should('not.be.disabled').type(matchingName); +export const validateSaveAsNewQueryMatchingNameHasError = (matchingName) => { + cy.whenTestIdNotFound('saved-query-management-popover', () => { + cy.getElementByTestId('saved-query-management-popover-button').click(); + }); + cy.getElementByTestId('saved-query-management-save-button').click(); - cy.getElementByTestId('savedQueryFormSaveButton').click(); + cy.getElementByTestId('saveAsNewQueryCheckbox') + .parent() + .find('[class="euiCheckbox__label"]') + .click(); + cy.getElementByTestId('saveQueryFormTitle').should('not.be.disabled').type(matchingName); - cy.contains(SAVE_QUERY_CONFLICT_NAME_ERROR_TEXT).should('be.visible'); - cy.getElementByTestId('savedQueryFormCancelButton').click(); - } + // The force is necessary as there is occasionally a popover that covers the button + cy.getElementByTestId('savedQueryFormSaveButton').click({ force: true }); + + cy.contains(SAVE_QUERY_CONFLICT_NAME_ERROR_TEXT).should('be.visible'); + // Two references to two buttons layered over each other. + cy.getElementByTestId('euiFlyoutCloseButton').first().click({ force: true }); }; From 00351f919dfbd315630a6e3d05eb43bb4b2429b3 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Wed, 22 Jan 2025 13:24:14 -0800 Subject: [PATCH 30/36] Address all comments. Signed-off-by: Argus Li --- .../saved_queries_flyout.spec.js | 20 +- .../apps/query_enhancements/constants.js | 1 - .../utils/apps/query_enhancements/saved.js | 12 +- .../apps/query_enhancements/saved_queries.js | 260 ++---------------- .../utils/apps/query_enhancements/shared.js | 10 +- cypress/utils/index.d.ts | 9 + 6 files changed, 59 insertions(+), 253 deletions(-) diff --git a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js index f2c0f3ade3f4..4f709035ca0f 100644 --- a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js +++ b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js @@ -8,12 +8,9 @@ import { INDEX_WITH_TIME_1, INDEX_WITH_TIME_2, SECONDARY_ENGINE, - START_TIME, - END_TIME, } from '../../../../../utils/constants'; import { - generateAllTestConfigurations, verifyDiscoverPageState, verifyQueryDoesNotExistInSavedQueries, setQueryConfigurations, @@ -26,15 +23,18 @@ import { getRandomizedWorkspaceName, getRandomizedDatasourceName, setDatePickerDatesAndSearchIfRelevant, + generateAllTestConfigurations, } from '../../../../../utils/apps/query_enhancements/shared'; +import { generateSavedTestConfiguration } from '../../../../../utils/apps/query_enhancements/saved'; + const workspaceName = getRandomizedWorkspaceName(); const datasourceName = getRandomizedDatasourceName(); // This spec assumes data.savedQueriesNewUI.enabled is true. export const runSavedQueriesFlyoutUITests = () => { describe('saved queries flyout UI', () => { - before(() => { + beforeEach(() => { // Load test data cy.setupTestData( SECONDARY_ENGINE.url, @@ -67,7 +67,7 @@ export const runSavedQueriesFlyoutUITests = () => { }); }); - after(() => { + afterEach(() => { // No need to explicitly delete all saved queries as deleting the workspace will delete associated saved queries cy.deleteWorkspaceByName(workspaceName); // // TODO: Modify deleteIndex to handle an array of index and remove hard code @@ -76,7 +76,7 @@ export const runSavedQueriesFlyoutUITests = () => { cy.deleteIndex(INDEX_WITH_TIME_2); }); - const testConfigurations = generateAllTestConfigurations(); + const testConfigurations = generateAllTestConfigurations(generateSavedTestConfiguration); describe('should create initial saved queries', () => { testConfigurations.forEach((config) => { @@ -90,7 +90,7 @@ export const runSavedQueriesFlyoutUITests = () => { cy.setDataset(config.dataset, datasourceName, config.datasetType); cy.setQueryLanguage(config.language); - setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); + setDatePickerDatesAndSearchIfRelevant(config.language); setQueryConfigurations(config); verifyDiscoverPageState(config); @@ -112,7 +112,7 @@ export const runSavedQueriesFlyoutUITests = () => { cy.loadSaveQuery(config.saveName); // wait for saved queries to load. - cy.wait(2000); + cy.getElementByTestId('docTable').should('be.visible'); verifyDiscoverPageState(config); }); @@ -125,7 +125,7 @@ export const runSavedQueriesFlyoutUITests = () => { if (config.filters) { cy.deleteAllFilters(); } - setDatePickerDatesAndSearchIfRelevant(config.language, START_TIME, END_TIME); + setDatePickerDatesAndSearchIfRelevant(config.language); setQueryConfigurations(config); verifyDiscoverPageState(config); @@ -135,7 +135,7 @@ export const runSavedQueriesFlyoutUITests = () => { cy.reload(); cy.loadSaveQuery(saveAsNewQueryName); // wait for saved query to load - cy.wait(2000); + cy.getElementByTestId('docTable').should('be.visible'); verifyDiscoverPageState(config); }); diff --git a/cypress/utils/apps/query_enhancements/constants.js b/cypress/utils/apps/query_enhancements/constants.js index 5881a0ff774f..3d49f188ab48 100644 --- a/cypress/utils/apps/query_enhancements/constants.js +++ b/cypress/utils/apps/query_enhancements/constants.js @@ -7,7 +7,6 @@ export const DATASOURCE_NAME = 'data-logs-1'; export const WORKSPACE_NAME = 'query-ws'; export const START_TIME = 'Jan 1, 2020 @ 00:00:00.000'; export const END_TIME = 'Jan 1, 2024 @ 00:00:00.000'; -export const SAVE_QUERY_CONFLICT_NAME_ERROR_TEXT = 'Name conflicts with an existing saved query'; export const clusterName = 'test_cluster'; export const clusterConnection = 'http://localhost:9200'; diff --git a/cypress/utils/apps/query_enhancements/saved.js b/cypress/utils/apps/query_enhancements/saved.js index d6bce6482240..7fd4d9bcd570 100644 --- a/cypress/utils/apps/query_enhancements/saved.js +++ b/cypress/utils/apps/query_enhancements/saved.js @@ -10,6 +10,8 @@ import { INDEX_PATTERN_WITH_TIME, INDEX_WITH_TIME_1, QueryLanguages, + START_TIME, + END_TIME, } from './constants'; import { setDatePickerDatesAndSearchIfRelevant } from './shared'; @@ -55,7 +57,7 @@ export const APPLIED_FILTERS = { * @param {QueryEnhancementLanguage} language - the name of query language * @returns {string} */ -const getQueryString = (dataset, language) => { +export const getQueryString = (dataset, language) => { switch (language) { case QueryLanguages.DQL.name: return 'bytes_transferred > 9950'; @@ -76,7 +78,7 @@ const getQueryString = (dataset, language) => { * @param {QueryEnhancementLanguage} language - the query language name * @returns {number|undefined} */ -const getExpectedHitCount = (datasetType, language) => { +export const getExpectedHitCount = (datasetType, language) => { switch (datasetType) { case DatasetTypes.INDEX_PATTERN.name: switch (language) { @@ -117,7 +119,7 @@ const getExpectedHitCount = (datasetType, language) => { * @param {QueryEnhancementLanguage} language - the query language name * @returns {[[number,string]]|*[]} An array of table data. For each element, 0th index is the index of the table cell, and 1st index is the value in that table cell */ -const getSampleTableData = (datasetType, language) => { +export const getSampleTableData = (datasetType, language) => { switch (datasetType) { case DatasetTypes.INDEX_PATTERN.name: switch (language) { @@ -165,6 +167,8 @@ const getSampleTableData = (datasetType, language) => { * @property {string} apiLanguage - the name of query language as recognized by OpenSearch API * @property {string} saveName - the name to use when saving the saved search * @property {string} testName - the phrase to add to the test case's title + * @property {string} startTime - the absolute start time for the query in the form e.g. Jan 1, 2020 @ 15:17:18.005 + * @property {string} endTime - the absolute end time for the query in the form e.g. Jan 1, 2020 @ 15:17:18.005 * @property {boolean} filters - whether the language supports filtering * @property {boolean} histogram - whether the language supports histogram * @property {boolean} selectFields - whether the language supports selecting fields to view data @@ -189,6 +193,8 @@ export const generateSavedTestConfiguration = (dataset, datasetType, language) = apiLanguage: language.apiName, saveName: `${language.name}-${datasetType}`, testName: `${language.name}-${datasetType}`, + startTime: START_TIME, + endTime: END_TIME, ...language.supports, }; diff --git a/cypress/utils/apps/query_enhancements/saved_queries.js b/cypress/utils/apps/query_enhancements/saved_queries.js index 8c387af8ddec..7da35d62c604 100644 --- a/cypress/utils/apps/query_enhancements/saved_queries.js +++ b/cypress/utils/apps/query_enhancements/saved_queries.js @@ -3,20 +3,20 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { - DatasetTypes, - DATASOURCE_NAME, - INDEX_PATTERN_WITH_TIME, - INDEX_WITH_TIME_1, - QueryLanguages, - WORKSPACE_NAME, - START_TIME, - END_TIME, - SAVE_QUERY_CONFLICT_NAME_ERROR_TEXT, -} from './constants'; +import { DatasetTypes, QueryLanguages } from './constants'; import { APPLIED_FILTERS } from './saved'; +import { setDatePickerDatesAndSearchIfRelevant } from './shared'; + +/** + * Error text when there is a name conflict when saving a query. + * @constant + * @type {string} + * @default + */ +const SAVE_QUERY_CONFLICT_NAME_ERROR_TEXT = 'Name conflicts with an existing saved query'; + /** * Suffix when saving as new query. * @constant @@ -54,56 +54,7 @@ export const ALTERNATE_APPLIED_FILTERS = { }; /** - * Sets the top nav date if it is relevant for the passed language - * @param {QueryEnhancementLanguage} language - query language - */ -export const setDatePickerDatesAndSearchIfRelevant = (language, startTime, endTime) => { - if (language !== QueryLanguages.SQL.name) { - cy.setTopNavDate(startTime, endTime); - } -}; - -const randomString = Math.random().toString(36); - -/** - * randomized workspace name - * @constant - * @type {string} - * @default - */ -export const workspaceName = `${WORKSPACE_NAME}-${randomString.substring(7)}`; - -/** - * randomized datasource name - * @constant - * @type {string} - * @default - */ -export const datasourceName = `${DATASOURCE_NAME}-${randomString.substring(0, 18)}`; - -/** - * Returns the query string to use for a given dataset+language - * @param {string} dataset - the dataset name to use - * @param {QueryEnhancementLanguage} language - the name of query language - * @returns {string} - */ -const getQueryString = (dataset, language) => { - switch (language) { - case QueryLanguages.DQL.name: - return 'bytes_transferred > 9950'; - case QueryLanguages.Lucene.name: - return 'bytes_transferred: {9950 TO *}'; - case QueryLanguages.SQL.name: - return `SELECT * FROM ${dataset} WHERE bytes_transferred > 9950`; - case QueryLanguages.PPL.name: - return `source = ${dataset} | where bytes_transferred > 9950`; - default: - throw new Error(`getQueryString encountered unsupported language: ${language}`); - } -}; - -/** - * Returns the query string to use for a given dataset+language + * Returns the query string to use for a given dataset+language that is different from the output of getQueryString function * @param {string} dataset - the dataset name to use * @param {QueryEnhancementLanguage} language - the name of query language * @returns {string} @@ -124,48 +75,7 @@ const getAlternateQueryString = (dataset, language) => { }; /** - * Returns the expected hit count, if relevant, for the provided datasetType + language - * @param {QueryEnhancementDataset} datasetType - the type of the dataset - * @param {QueryEnhancementLanguage} language - the query language name - * @returns {number|undefined} - */ -const getExpectedHitCount = (datasetType, language) => { - switch (datasetType) { - case DatasetTypes.INDEX_PATTERN.name: - switch (language) { - case QueryLanguages.DQL.name: - return 28; - case QueryLanguages.Lucene.name: - return 28; - case QueryLanguages.SQL.name: - return undefined; - case QueryLanguages.PPL.name: - // TODO: Update this to 101 once Histogram is supported on 2.17 - return undefined; - default: - throw new Error( - `getExpectedHitCount encountered unsupported language for ${datasetType}: ${language}` - ); - } - case DatasetTypes.INDEXES.name: - switch (language) { - case QueryLanguages.SQL.name: - return undefined; - case QueryLanguages.PPL.name: - // TODO: Update this to 50 once Histogram is supported on 2.17 - return undefined; - default: - throw new Error( - `getExpectedHitCount encountered unsupported language for ${datasetType}: ${language}` - ); - } - default: - throw new Error(`getExpectedHitCount encountered unsupported datasetType: ${datasetType}`); - } -}; - -/** - * Returns the expected hit count, if relevant, for the provided datasetType + language + * Returns the expected hit count, if relevant, for the provided datasetType + language that is different from the output of getExpectedHitCount function * @param {QueryEnhancementDataset} datasetType - the type of the dataset * @param {QueryEnhancementLanguage} language - the query language name * @returns {number|undefined} @@ -206,108 +116,9 @@ const getAlternateExpectedHitCount = (datasetType, language) => { }; /** - * returns an array of data present in the results table to check against. This is used to ensure that sorting is working as expected - * @param {QueryEnhancementDataset} datasetType - the type of the dataset - * @param {QueryEnhancementLanguage} language - the query language name - * @returns {[[number,string]]|*[]} An array of table data. For each element, 0th index is the index of the table cell, and 1st index is the value in that table cell - */ -const getSampleTableData = (datasetType, language) => { - switch (datasetType) { - case DatasetTypes.INDEX_PATTERN.name: - switch (language) { - case QueryLanguages.DQL.name: - return [ - [1, '9,998'], - [2, 'Phyllis Dach'], - ]; - case QueryLanguages.Lucene.name: - return [ - [1, '9,998'], - [2, 'Phyllis Dach'], - ]; - case QueryLanguages.SQL.name: - return []; - case QueryLanguages.PPL.name: - return []; - default: - throw new Error( - `getSampleTableData encountered unsupported language for ${datasetType}: ${language}` - ); - } - case DatasetTypes.INDEXES.name: - switch (language) { - case QueryLanguages.SQL.name: - return []; - case QueryLanguages.PPL.name: - return []; - default: - throw new Error( - `getSampleTableData encountered unsupported language for ${datasetType}: ${language}` - ); - } - default: - throw new Error(`getSampleTableData encountered unsupported datasetType: ${datasetType}`); - } -}; - -/** - * The configurations needed for saved queries tests - * @typedef {Object} SavedSearchTestConfig - * @property {string} dataset - the dataset name to use - * @property {QueryEnhancementDataset} datasetType - the type of dataset - * @property {QueryEnhancementLanguage} language - the name of query language as it appears in the dashboard app - * @property {string} apiLanguage - the name of query language as recognized by OpenSearch API - * @property {string} saveName - the name to use when saving the saved query - * @property {string} testName - the phrase to add to the test case's title - * @property {boolean} filters - whether the language supports filtering - * @property {boolean} histogram - whether the language supports histogram - * @property {boolean} selectFields - whether the language supports selecting fields to view data - * @property {boolean} sort - whether the language supports sorting by fields - * @property {string} queryString - the query to use for saved query associated with the language - * @property {number|undefined} hitCount - the hitCount of the applied query config, if relevant - * @property {[[number,string]]|*[]} sampleTableData - an array of some table data to test against to ensure that sorting is working as expected - */ - -/** - * Returns the SavedSearchTestConfig for the provided dataset, datasetType, and language - * @param {string} dataset - the dataset name - * @param {QueryEnhancementDataset} datasetType - the type of the dataset - * @param {QueryEnhancementLanguageData} language - the relevant data for the query language to use - * @param {String} [startTime = constants/START_TIME] - the absolute start time for the query in the form e.g. Jan 1, 2020 @ 15:17:18.005 - * @param {String} [endTime = constants/END_TIME] - the absolute end time for the query in the form e.g. Jan 1, 2020 @ 15:17:18.005 - * @returns {SavedSearchTestConfig} - */ -const generateTestConfiguration = ( - dataset, - datasetType, - language, - startTime = START_TIME, - endTime = END_TIME -) => { - const baseConfig = { - dataset, - datasetType, - language: language.name, - apiLanguage: language.apiName, - saveName: `${language.name}-${datasetType}`, - testName: `${language.name}-${datasetType}`, - startTime, - endTime, - ...language.supports, - }; - - return { - ...baseConfig, - queryString: getQueryString(dataset, language.name), - hitCount: getExpectedHitCount(datasetType, language.name), - sampleTableData: getSampleTableData(datasetType, language.name), - }; -}; - -/** - * Returns an alternate SavedSearchTestConfig - * @param {SavedSearchTestConfig} config - initial config that will be modified. - * @returns {SavedSearchTestConfig} + * Returns an alternate SavedTestConfig + * @param {SavedTestConfig} config - initial config that will be modified. + * @returns {SavedTestConfig} */ const generateAlternateTestConfiguration = (config) => { const baseConfig = { @@ -332,34 +143,9 @@ const generateAlternateTestConfiguration = (config) => { }; }; -/** - * Returns an array of test configurations for every query language + dataset permutation - * @returns {SavedSearchTestConfig[]} - */ -export const generateAllTestConfigurations = () => { - return Object.values(DatasetTypes).flatMap((dataset) => - dataset.supportedLanguages.map((language) => { - let datasetToUse; - switch (dataset.name) { - case DatasetTypes.INDEX_PATTERN.name: - datasetToUse = INDEX_PATTERN_WITH_TIME; - break; - case DatasetTypes.INDEXES.name: - datasetToUse = INDEX_WITH_TIME_1; - break; - default: - throw new Error( - `generateAllTestConfigurations encountered unsupported dataset: ${dataset.name}` - ); - } - return generateTestConfiguration(datasetToUse, dataset.name, language); - }) - ); -}; - /** * Verify that the discover page is in the correct state after loading a saved query have been run - * @param {SavedSearchTestConfig} testConfig - the relevant config for the test case + * @param {SavedTestConfig} testConfig - the relevant config for the test case */ export const verifyDiscoverPageState = ({ queryString, @@ -400,7 +186,7 @@ export const verifyDiscoverPageState = ({ /** * Verify that the discover page is in the correct state after loading a saved query have been run - * @param {SavedSearchTestConfig} testConfig - the relevant config for the test case + * @param {SavedTestConfig} testConfig - the relevant config for the test case */ export const verifyAlternateDiscoverPageState = ({ queryString, @@ -441,7 +227,7 @@ export const verifyAlternateDiscoverPageState = ({ /** * Set the query configurations for the saved query - * @param {SavedSearchTestConfig} testConfig - the relevant config for the test case + * @param {SavedTestConfig} testConfig - the relevant config for the test case */ export const setQueryConfigurations = ({ filters, queryString, histogram }) => { if (filters) { @@ -462,7 +248,7 @@ export const setQueryConfigurations = ({ filters, queryString, histogram }) => { /** * Set the query configurations for the saved query - * @param {SavedSearchTestConfig} testConfig - the relevant config for the test case + * @param {SavedTestConfig} testConfig - the relevant config for the test case */ export const setAlternateQueryConfigurations = ({ filters, queryString, histogram }) => { if (filters) { @@ -496,7 +282,7 @@ export const verifyQueryDoesNotExistInSavedQueries = (deletedQueryName) => { /** * Update and save the saved query with alternate config, then verify has been updated correctly. - * @param {SavedSearchTestConfig} config - the config for the test case to be updated + * @param {SavedTestConfig} config - the config for the test case to be updated */ export const updateAndVerifySavedQuery = (config) => { // Create alternate config @@ -504,7 +290,7 @@ export const updateAndVerifySavedQuery = (config) => { cy.loadSaveQuery(config.saveName); // wait for saved query to load - cy.wait(2000); + cy.getElementByTestId('docTable').should('be.visible'); if (alternateConfig.filters) { cy.deleteAllFilters(); @@ -519,7 +305,7 @@ export const updateAndVerifySavedQuery = (config) => { cy.reload(); cy.loadSaveQuery(config.saveName); // wait for saved query to load - cy.wait(2000); + cy.getElementByTestId('docTable').should('be.visible'); verifyAlternateDiscoverPageState(alternateConfig); }; diff --git a/cypress/utils/apps/query_enhancements/shared.js b/cypress/utils/apps/query_enhancements/shared.js index 9fe5a24512f4..e5d09bb4aa12 100644 --- a/cypress/utils/apps/query_enhancements/shared.js +++ b/cypress/utils/apps/query_enhancements/shared.js @@ -72,9 +72,15 @@ export const generateAllTestConfigurations = (generateTestConfigurationCallback) /** * Sets the top nav date if it is relevant for the passed language * @param {QueryEnhancementLanguage} language - query language + * @param {string=} start - start datetime string + * @param {string=} end - end datetime string */ -export const setDatePickerDatesAndSearchIfRelevant = (language) => { +export const setDatePickerDatesAndSearchIfRelevant = ( + language, + start = START_TIME, + end = END_TIME +) => { if (language !== QueryLanguages.SQL.name) { - cy.setTopNavDate(START_TIME, END_TIME); + cy.setTopNavDate(start, end); } }; diff --git a/cypress/utils/index.d.ts b/cypress/utils/index.d.ts index 3d0cb66a0daa..d368425070a5 100644 --- a/cypress/utils/index.d.ts +++ b/cypress/utils/index.d.ts @@ -24,6 +24,15 @@ declare namespace Cypress { testIds: string | string[], options?: Partial ): Chainable; + /** + * Get an element which contains testId + * @example + * cy.getElementByTestIdLike('query') + */ + getElementByTestIdLike( + testId: string, + options?: Partial + ): Chainable; /** * Get an element by its test id * @example From 7e80e64179c4e7ae972c705f7d878313a0edbf18 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Thu, 23 Jan 2025 09:34:46 -0800 Subject: [PATCH 31/36] Fix cypress command namespacing. Signed-off-by: Argus Li --- .../apps/query_enhancements/saved_queries_flyout.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js index 4f709035ca0f..7f9123580547 100644 --- a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js +++ b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js @@ -57,7 +57,7 @@ export const runSavedQueriesFlyoutUITests = () => { // Create workspace cy.deleteWorkspaceByName(workspaceName); cy.visit('/app/home'); - cy.createInitialWorkspaceWithDataSource(datasourceName, workspaceName); + cy.osd.createInitialWorkspaceWithDataSource(datasourceName, workspaceName); cy.createWorkspaceIndexPatterns({ workspaceName: workspaceName, indexPattern: INDEX_PATTERN_WITH_TIME.replace('*', ''), From 2d2c081ae95cf40c0a9a27474eb38f031d483806 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Fri, 24 Jan 2025 09:18:28 -0800 Subject: [PATCH 32/36] Rename saved queries spec. Signed-off-by: Argus Li --- .../{saved_queries_flyout.spec.js => saved_queries.spec.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/{saved_queries_flyout.spec.js => saved_queries.spec.js} (100%) diff --git a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js similarity index 100% rename from cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries_flyout.spec.js rename to cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js From 7e2134844cfb66ca989948524e0400e0eb842bc7 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Fri, 24 Jan 2025 12:44:14 -0800 Subject: [PATCH 33/36] Remove references to flyout Signed-off-by: Argus Li --- .../apps/query_enhancements/saved_queries.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js index 7f9123580547..d53e263733cc 100644 --- a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js +++ b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js @@ -32,8 +32,8 @@ const workspaceName = getRandomizedWorkspaceName(); const datasourceName = getRandomizedDatasourceName(); // This spec assumes data.savedQueriesNewUI.enabled is true. -export const runSavedQueriesFlyoutUITests = () => { - describe('saved queries flyout UI', () => { +export const runSavedQueriesUITests = () => { + describe('saved queries UI', () => { beforeEach(() => { // Load test data cy.setupTestData( @@ -154,4 +154,4 @@ export const runSavedQueriesFlyoutUITests = () => { }); }; -runSavedQueriesFlyoutUITests(); +runSavedQueriesUITests(); From d193d640803ae45f4c8b69ecdae08e52e8c3476c Mon Sep 17 00:00:00 2001 From: Argus Li Date: Fri, 24 Jan 2025 13:48:08 -0800 Subject: [PATCH 34/36] Refactor tests to work with beforeEach and afterEach Signed-off-by: Argus Li --- .../query_enhancements/saved_queries.spec.js | 143 +++++++++--------- 1 file changed, 74 insertions(+), 69 deletions(-) diff --git a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js index d53e263733cc..5dc64fab5625 100644 --- a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js +++ b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js @@ -31,6 +31,73 @@ import { generateSavedTestConfiguration } from '../../../../../utils/apps/query_ const workspaceName = getRandomizedWorkspaceName(); const datasourceName = getRandomizedDatasourceName(); +const createSavedQuery = (config) => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + cy.setDataset(config.dataset, datasourceName, config.datasetType); + + cy.setQueryLanguage(config.language); + setDatePickerDatesAndSearchIfRelevant(config.language); + + setQueryConfigurations(config); + verifyDiscoverPageState(config); + + cy.saveQuery(config.saveName, ' ', true, true); +}; + +const loadSavedQuery = (config) => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + cy.getElementByTestId('discoverNewButton').click(); + setDatePickerDatesAndSearchIfRelevant( + config.language, + 'Aug 29, 2020 @ 00:00:00.000', + 'Aug 30, 2020 @ 00:00:00.000' + ); + + cy.loadSaveQuery(config.saveName); + // wait for saved queries to load. + cy.getElementByTestId('docTable').should('be.visible'); + verifyDiscoverPageState(config); +}; + +const modifyAndVerifySavedQuery = (config, saveAsNewQueryName) => { + if (config.filters) { + cy.deleteAllFilters(); + } + setDatePickerDatesAndSearchIfRelevant(config.language); + + setQueryConfigurations(config); + verifyDiscoverPageState(config); + validateSaveAsNewQueryMatchingNameHasError(config.saveName); + cy.updateSaveQuery(saveAsNewQueryName, true, true, true); + + cy.reload(); + cy.loadSaveQuery(saveAsNewQueryName); + // wait for saved query to load + cy.getElementByTestId('docTable').should('be.visible'); + verifyDiscoverPageState(config); +}; + +const deleteSavedQuery = (saveAsNewQueryName) => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + cy.deleteSaveQuery(saveAsNewQueryName); + verifyQueryDoesNotExistInSavedQueries(saveAsNewQueryName); +}; + // This spec assumes data.savedQueriesNewUI.enabled is true. export const runSavedQueriesUITests = () => { describe('saved queries UI', () => { @@ -78,77 +145,15 @@ export const runSavedQueriesUITests = () => { const testConfigurations = generateAllTestConfigurations(generateSavedTestConfiguration); - describe('should create initial saved queries', () => { - testConfigurations.forEach((config) => { - it(`should create saved query: ${config.testName}`, () => { - cy.navigateToWorkSpaceSpecificPage({ - workspaceName, - page: 'discover', - isEnhancement: true, - }); - - cy.setDataset(config.dataset, datasourceName, config.datasetType); - - cy.setQueryLanguage(config.language); - setDatePickerDatesAndSearchIfRelevant(config.language); - - setQueryConfigurations(config); - verifyDiscoverPageState(config); - - cy.saveQuery(config.saveName, ' ', true, true); - }); - }); - }); - - describe('should test loading, saving and deleting saved queries', () => { - testConfigurations.forEach((config) => { - it(`should load saved query: ${config.testName}`, () => { - cy.getElementByTestId('discoverNewButton').click(); - setDatePickerDatesAndSearchIfRelevant( - config.language, - 'Aug 29, 2020 @ 00:00:00.000', - 'Aug 30, 2020 @ 00:00:00.000' - ); - - cy.loadSaveQuery(config.saveName); - // wait for saved queries to load. - cy.getElementByTestId('docTable').should('be.visible'); - verifyDiscoverPageState(config); - }); - - it(`should update the loaded saved query: ${config.testName}`, () => { - updateAndVerifySavedQuery(config); - }); + testConfigurations.forEach((config) => { + it(`should create, load, update, modify and delete the saved query: ${config.testName}`, () => { + createSavedQuery(config); + loadSavedQuery(config); + updateAndVerifySavedQuery(config); const saveAsNewQueryName = config.testName + SAVE_AS_NEW_QUERY_SUFFIX; - it(`should modify saved query: ${config.testName} and save as new query: ${saveAsNewQueryName}`, () => { - if (config.filters) { - cy.deleteAllFilters(); - } - setDatePickerDatesAndSearchIfRelevant(config.language); - - setQueryConfigurations(config); - verifyDiscoverPageState(config); - validateSaveAsNewQueryMatchingNameHasError(config.saveName); - cy.updateSaveQuery(saveAsNewQueryName, true, true, true); - - cy.reload(); - cy.loadSaveQuery(saveAsNewQueryName); - // wait for saved query to load - cy.getElementByTestId('docTable').should('be.visible'); - verifyDiscoverPageState(config); - }); - - it(`should delete the saved query: ${saveAsNewQueryName}`, () => { - cy.navigateToWorkSpaceSpecificPage({ - workspaceName, - page: 'discover', - isEnhancement: true, - }); - - cy.deleteSaveQuery(saveAsNewQueryName); - verifyQueryDoesNotExistInSavedQueries(saveAsNewQueryName); - }); + modifyAndVerifySavedQuery(config, saveAsNewQueryName); + deleteSavedQuery(saveAsNewQueryName); }); }); }); From bc5878a5ce853652c0a9defa93d3ad5c19d43a3f Mon Sep 17 00:00:00 2001 From: Argus Li Date: Mon, 27 Jan 2025 14:35:28 -0800 Subject: [PATCH 35/36] Add force to click when loading saved query. This removes delay when waiting for toast to disperse. Signed-off-by: Argus Li --- cypress/utils/apps/data_explorer/commands.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cypress/utils/apps/data_explorer/commands.js b/cypress/utils/apps/data_explorer/commands.js index 8c8fe68f6682..54f30c682e62 100644 --- a/cypress/utils/apps/data_explorer/commands.js +++ b/cypress/utils/apps/data_explorer/commands.js @@ -187,8 +187,8 @@ Cypress.Commands.add('loadSaveQuery', (name) => { cy.getElementByTestId('saved-query-management-open-button').click(); cy.getElementByTestId('euiFlyoutCloseButton').parent().contains(name).should('exist').click(); - - cy.getElementByTestId('open-query-action-button').click(); + // click button through popover + cy.getElementByTestId('open-query-action-button').click({ force: true }); }); Cypress.Commands.add('clearSaveQuery', () => { From b162b296ccaf504be3b3ba2f113f402184e240d9 Mon Sep 17 00:00:00 2001 From: Argus Li Date: Mon, 27 Jan 2025 17:52:58 -0800 Subject: [PATCH 36/36] Fix test issue. Thank you @angle943 for finding a solution. Issue was caused by Cypress being too fast for the date picker to appear. Signed-off-by: Argus Li --- .../apps/query_enhancements/saved_queries.spec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js index 5dc64fab5625..c3d6e62c0d94 100644 --- a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js +++ b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/saved_queries.spec.js @@ -57,6 +57,8 @@ const loadSavedQuery = (config) => { }); cy.getElementByTestId('discoverNewButton').click(); + cy.setDataset(config.dataset, datasourceName, config.datasetType); + cy.setQueryLanguage(config.language); setDatePickerDatesAndSearchIfRelevant( config.language, 'Aug 29, 2020 @ 00:00:00.000',