diff --git a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/dataset_selector.spec.js b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/dataset_selector.spec.js index 8e6cedb6f7e..5bacbdb9ab1 100644 --- a/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/dataset_selector.spec.js +++ b/cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements/dataset_selector.spec.js @@ -3,111 +3,137 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { DATASOURCE_NAME, START_TIME, END_TIME } from '../../../../../utils/apps/constants'; -import { SECONDARY_ENGINE } from '../../../../../utils/constants'; -import { getRandomizedWorkspaceName } from '../../../../../utils/apps/query_enhancements/shared'; - -const workspace = getRandomizedWorkspaceName(); - -describe('dataset selector', { scrollBehavior: false }, () => { - before(() => { - cy.setupTestData( - SECONDARY_ENGINE.url, - ['cypress/fixtures/query_enhancements/data_logs_1/data_logs_small_time_1.mapping.json'], - ['cypress/fixtures/query_enhancements/data_logs_1/data_logs_small_time_1.data.ndjson'] - ); - - // Add data source - cy.addDataSource({ - name: `${DATASOURCE_NAME}`, - url: `${SECONDARY_ENGINE.url}`, - authType: 'no_auth', - }); - }); - after(() => { - cy.deleteDataSourceByName(`${DATASOURCE_NAME}`); - cy.deleteIndex('data_logs_small_time_1'); - }); - beforeEach(() => { - // Create workspace - cy.deleteWorkspaceByName(workspace); - cy.visit('/app/home'); - cy.osd.createInitialWorkspaceWithDataSource(DATASOURCE_NAME, workspace); - cy.navigateToWorkSpaceSpecificPage({ - workspaceName: workspace, - page: 'discover', - isEnhancement: true, - }); - }); - - afterEach(() => { - cy.deleteWorkspaceByName(`${workspace}`); - }); - - describe('select indices', () => { - it('with SQL as default language', function () { - cy.setIndexAsDataset('data_logs_small_time_1', DATASOURCE_NAME, 'OpenSearch SQL'); - - // SQL should already be selected - cy.getElementByTestId('queryEditorLanguageSelector').should('contain', 'OpenSearch SQL'); - cy.waitForLoader(true); - - // SQL query should be executed and sending back result - cy.get(`[data-test-subj="queryResultCompleteMsg"]`).should('be.visible'); - - // Switch language to PPL - cy.setQueryLanguage('PPL'); - cy.setTopNavDate(START_TIME, END_TIME); - - cy.waitForLoader(true); - cy.get(`[data-test-subj="queryResultCompleteMsg"]`).should('be.visible'); - }); - - it('with PPL as default language', function () { - cy.setIndexAsDataset('data_logs_small_time_1', DATASOURCE_NAME, 'PPL'); - - // PPL should already be selected - cy.getElementByTestId('queryEditorLanguageSelector').should('contain', 'PPL'); - - cy.setTopNavDate(START_TIME, END_TIME); - - cy.waitForLoader(true); - - // Query should finish running with timestamp and finish time in the footer - cy.getElementByTestId('queryResultCompleteMsg').should('be.visible'); - cy.getElementByTestId('queryEditorFooterTimestamp').should('contain', 'timestamp'); - - // Switch language to SQL - cy.setQueryLanguage('OpenSearch SQL'); - - cy.waitForLoader(true); - cy.getElementByTestId('queryResultCompleteMsg').should('be.visible'); - cy.getElementByTestId('queryEditorFooterTimestamp').should('contain', 'timestamp'); - }); - }); +import { + INDEX_PATTERN_WITH_TIME, + INDEX_WITH_TIME_1, + INDEX_WITH_TIME_2, + SECONDARY_ENGINE, +} from '../../../../../utils/constants'; + +import { + generateAllTestConfigurations, + getRandomizedWorkspaceName, + getRandomizedDatasourceName, + setDatePickerDatesAndSearchIfRelevant, + getDefaultQuery, +} from '../../../../../utils/apps/query_enhancements/shared'; + +import { verifyDiscoverPageState } from '../../../../../utils/apps/query_enhancements/saved'; + +import { + generateDatasetSelectorTestConfiguration, + verifyBaseState, + setUpBaseState, +} from '../../../../../utils/apps/query_enhancements/dataset_selector'; + +const workspaceName = getRandomizedWorkspaceName(); +const dataSourceName = getRandomizedDatasourceName(); + +export const runDatasetSelectorTests = () => { + describe('dataset selector', { scrollBehavior: false }, () => { + beforeEach(() => { + // 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', + }); - describe('index pattern', () => { - it('create index pattern and select it', function () { - // Create and select index pattern for data_logs_small_time_1* + // Create workspace + cy.deleteWorkspaceByName(workspaceName); + cy.visit('/app/home'); + cy.osd.createInitialWorkspaceWithDataSource(dataSourceName, workspaceName); cy.createWorkspaceIndexPatterns({ - workspaceName: workspace, - indexPattern: 'data_logs_small_time_1', + workspaceName: workspaceName, + indexPattern: INDEX_PATTERN_WITH_TIME.replace('*', ''), timefieldName: 'timestamp', - indexPatternHasTimefield: true, - dataSource: DATASOURCE_NAME, + dataSource: dataSourceName, isEnhancement: true, }); + }); - cy.navigateToWorkSpaceHomePage(workspace); + afterEach(() => { + 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); + }); - cy.waitForLoader(true); - cy.setIndexPatternAsDataset('data_logs_small_time_1*', DATASOURCE_NAME); - // setting OpenSearch SQL as the code following it does not work if this test is isolated - cy.setQueryLanguage('OpenSearch SQL'); + generateAllTestConfigurations(generateDatasetSelectorTestConfiguration).forEach((config) => { + it(`should be able to select and load ${config.testName} dataset-language combination using advanced dataset selector`, () => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + if (config.datasetType === 'INDEX_PATTERN') { + cy.setIndexPatternFromAdvancedSelector(config.dataset, dataSourceName, config.language); + } else { + cy.setIndexAsDataset(config.dataset, dataSourceName, config.language); + } + setDatePickerDatesAndSearchIfRelevant(config.language); + + verifyDiscoverPageState({ + dataset: config.dataset, + queryString: getDefaultQuery(config.dataset, config.language), + language: config.language, + hitCount: config.hitCount, + }); + + // verify time field is present in the result + cy.getElementByTestId('docTableHeaderField').contains('Time'); + }); - cy.waitForLoader(true); - cy.waitForSearch(); - cy.getElementByTestId(`queryResultCompleteMsg`).should('be.visible'); + it(`select the ${config.testName} dataset-language combination and cancelling the workflow restores the original state`, () => { + cy.navigateToWorkSpaceSpecificPage({ + workspaceName, + page: 'discover', + isEnhancement: true, + }); + + // Setup the base state + setUpBaseState(INDEX_PATTERN_WITH_TIME, dataSourceName); + + // Verify if the base state is setup properly + verifyBaseState(INDEX_PATTERN_WITH_TIME); + + // Try setting the dataset-language combination but click on cancel + if (config.datasetType === 'INDEX_PATTERN') { + cy.setIndexPatternFromAdvancedSelector( + config.dataset, + dataSourceName, + config.language, + 'cancel' + ); + } else { + cy.setIndexAsDataset( + config.dataset, + dataSourceName, + config.language, + 'timestamp', + 'cancel' + ); + } + + // Verify if the base state is retained + verifyBaseState(INDEX_PATTERN_WITH_TIME); + }); }); }); -}); +}; + +runDatasetSelectorTests(); diff --git a/cypress/utils/apps/query_enhancements/commands.js b/cypress/utils/apps/query_enhancements/commands.js index 558f06427eb..4a28218233d 100644 --- a/cypress/utils/apps/query_enhancements/commands.js +++ b/cypress/utils/apps/query_enhancements/commands.js @@ -139,28 +139,36 @@ Cypress.Commands.add('deleteAllDataSources', () => { }); }); -Cypress.Commands.add('setIndexAsDataset', (index, dataSourceName, language) => { - cy.getElementByTestId('datasetSelectorButton').should('be.visible').click(); - cy.getElementByTestId(`datasetSelectorAdvancedButton`).click(); - cy.get(`[title="Indexes"]`).click(); - cy.get(`[title="${dataSourceName}"]`).click(); - // this element is sometimes dataSourceName masked by another element - cy.get(`[title="${index}"]`).should('be.visible').click({ force: true }); - cy.getElementByTestId('datasetSelectorNext').click(); - - if (language) { - cy.getElementByTestId('advancedSelectorLanguageSelect').select(language); - } +Cypress.Commands.add( + 'setIndexAsDataset', + (index, dataSourceName, language, timeFieldName = 'timestamp', finalAction = 'submit') => { + cy.getElementByTestId('datasetSelectorButton').should('be.visible').click(); + cy.getElementByTestId(`datasetSelectorAdvancedButton`).click(); + cy.get(`[title="Indexes"]`).click(); + cy.get(`[title="${dataSourceName}"]`).click(); + // this element is sometimes dataSourceName masked by another element + cy.get(`[title="${index}"]`).should('be.visible').click({ force: true }); + cy.getElementByTestId('datasetSelectorNext').click(); + + if (language) { + cy.getElementByTestId('advancedSelectorLanguageSelect').select(language); + } - cy.getElementByTestId('advancedSelectorTimeFieldSelect').select('timestamp'); - cy.getElementByTestId('advancedSelectorConfirmButton').click(); + cy.getElementByTestId('advancedSelectorTimeFieldSelect').select(timeFieldName); - // verify that it has been selected - cy.getElementByTestId('datasetSelectorButton').should( - 'contain.text', - `${dataSourceName}::${index}` - ); -}); + if (finalAction === 'submit') { + cy.getElementByTestId('advancedSelectorConfirmButton').click(); + + // verify that it has been selected + cy.getElementByTestId('datasetSelectorButton').should( + 'contain.text', + `${dataSourceName}::${index}` + ); + } else { + cy.get('[type="button"]').contains('Cancel').click(); + } + } +); Cypress.Commands.add('setIndexPatternAsDataset', (indexPattern, dataSourceName) => { cy.getElementByTestId('datasetSelectorButton').should('be.visible').click(); @@ -173,6 +181,36 @@ Cypress.Commands.add('setIndexPatternAsDataset', (indexPattern, dataSourceName) ); }); +Cypress.Commands.add( + 'setIndexPatternFromAdvancedSelector', + (indexPattern, dataSourceName, language, finalAction = 'submit') => { + cy.getElementByTestId('datasetSelectorButton').should('be.visible').click(); + cy.getElementByTestId(`datasetSelectorAdvancedButton`).click(); + cy.get(`[title="Index Patterns"]`).click(); + + cy.get(`[title="${dataSourceName}::${indexPattern}"]`) + .should('be.visible') + .click({ force: true }); + cy.getElementByTestId('datasetSelectorNext').click(); + + if (language) { + cy.getElementByTestId('advancedSelectorLanguageSelect').select(language); + } + + if (finalAction === 'submit') { + cy.getElementByTestId('advancedSelectorConfirmButton').click(); + + // verify that it has been selected + cy.getElementByTestId('datasetSelectorButton').should( + 'contain.text', + `${dataSourceName}::${indexPattern}` + ); + } else { + cy.get('[type="button"]').contains('Cancel').click(); + } + } +); + Cypress.Commands.add('setDataset', (dataset, dataSourceName, type) => { switch (type) { case 'INDEX_PATTERN': diff --git a/cypress/utils/apps/query_enhancements/dataset_selector.js b/cypress/utils/apps/query_enhancements/dataset_selector.js new file mode 100644 index 00000000000..b6983d6c5ba --- /dev/null +++ b/cypress/utils/apps/query_enhancements/dataset_selector.js @@ -0,0 +1,91 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { getDefaultQuery, setDatePickerDatesAndSearchIfRelevant } from './shared'; +import { verifyDiscoverPageState } from './saved'; +import { DatasetTypes, QueryLanguages } from './constants'; + +/** + * 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 query = 'status_code:500'; +const language = 'DQL'; + +const getExpectedHitCount = (datasetType, language) => { + switch (datasetType) { + case DatasetTypes.INDEX_PATTERN.name: + switch (language) { + case QueryLanguages.DQL.name: + return '20,000'; + case QueryLanguages.Lucene.name: + return '20,000'; + 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 10,894 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}`); + } +}; + +export const generateDatasetSelectorTestConfiguration = (dataset, datasetType, language) => { + const baseConfig = { + dataset, + datasetType, + language: language.name, + testName: `${language.name}-${datasetType}`, + }; + + return { + ...baseConfig, + queryString: getDefaultQuery(dataset, language.name), + hitCount: getExpectedHitCount(datasetType, language.name), + }; +}; + +export const verifyBaseState = (dataset) => { + verifyDiscoverPageState({ + dataset: dataset, + queryString: query, + language: language, + hitCount: '2,229', + }); +}; + +export const setUpBaseState = (dataset, dataSourceName) => { + // Setting up the dataset + cy.setDataset(dataset, dataSourceName, 'INDEX_PATTERN'); + + // set Language + cy.setQueryLanguage(language); + + // Setting the TimeRange + setDatePickerDatesAndSearchIfRelevant(language); + + // Setting up Query + cy.setQueryEditor(query); +};