diff --git a/cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/data.json.txt b/cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/data.json.txt new file mode 100644 index 000000000..2cd7ad0d3 --- /dev/null +++ b/cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/data.json.txt @@ -0,0 +1,23 @@ +{ + "type": "doc", + "value": { + "id": "3", + "index": "timestamp-nanos", + "source": { + "timestamp": "2019-01-01T12:10:30.123456789Z" + }, + "type": "_doc" + } +} + +{ + "type": "doc", + "value": { + "id": "4", + "index": "timestamp-nanos", + "source": { + "timestamp": "2019-01-01T12:10:30.123498765Z" + }, + "type": "_doc" + } +} diff --git a/cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/data_with_index_pattern.json.txt b/cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/data_with_index_pattern.json.txt new file mode 100644 index 000000000..b1284b91f --- /dev/null +++ b/cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/data_with_index_pattern.json.txt @@ -0,0 +1,65 @@ +{ + "type": "doc", + "value": { + "id": "index-pattern:timestamp-*", + "index": ".kibana", + "source": { + "index-pattern": { + "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"timestamp\",\"type\":\"date\",\"esTypes\":[\"date\",\"date_nanos\"],\"count\":2,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName": "timestamp", + "title": "timestamp-*", + "fieldFormatMap": "{\"timestamp\":{\"id\":\"date_nanos\"}}" + }, + "type": "index-pattern" + }, + "type": "_doc" + } +} + +{ + "type": "doc", + "value": { + "id": "2", + "index": "timestamp-millis", + "source": { + "timestamp": "2019-01-01T12:10:30.124Z" + }, + "type": "_doc" + } +} + +{ + "type": "doc", + "value": { + "id": "1", + "index": "timestamp-millis", + "source": { + "timestamp": "2019-01-01T12:10:30.123Z" + }, + "type": "_doc" + } +} + +{ + "type": "doc", + "value": { + "id": "3", + "index": "timestamp-nanos", + "source": { + "timestamp": "2019-01-01T12:10:30.123456789Z" + }, + "type": "_doc" + } +} + +{ + "type": "doc", + "value": { + "id": "4", + "index": "timestamp-nanos", + "source": { + "timestamp": "2019-01-02T12:10:30.123498765Z" + }, + "type": "_doc" + } +} diff --git a/cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/mappings.json.txt b/cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/mappings.json.txt new file mode 100644 index 000000000..eaeaeee37 --- /dev/null +++ b/cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/mappings.json.txt @@ -0,0 +1,45 @@ +{ + "type": "index", + "value": { + "aliases": { + }, + "index": "timestamp-millis", + "mappings": { + "properties": { + "timestamp": { + "type": "date" + } + } + }, + "settings": { + "index": { + "number_of_replicas": "1", + "number_of_shards": "1", + "codec": "best_compression" + } + } + } +} + +{ + "type": "index", + "value": { + "aliases": { + }, + "index": "timestamp-nanos", + "mappings": { + "properties": { + "timestamp": { + "type": "date_nanos" + } + } + }, + "settings": { + "index": { + "number_of_replicas": "1", + "number_of_shards": "1", + "codec": "best_compression" + } + } + } +} diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancement/dataset_navigator.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancement/dataset_navigator.spec.js new file mode 100644 index 000000000..71dc1f92a --- /dev/null +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancement/dataset_navigator.spec.js @@ -0,0 +1,213 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +import { + MiscUtils, + TestFixtureHandler, +} from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { CURRENT_TENANT } from '../../../../../utils/commands'; +import { clusterName, clusterConnection } from '../../../../../utils/constants'; + +const miscUtils = new MiscUtils(cy); +const testFixtureHandler = new TestFixtureHandler( + cy, + Cypress.env('openSearchUrl') +); + +const indexSet = [ + 'logstash-2015.09.22', + 'logstash-2015.09.21', + 'logstash-2015.09.20', +]; + +describe('dataset navigator', { scrollBehavior: false }, () => { + before(() => { + CURRENT_TENANT.newTenant = 'global'; + cy.fleshTenantSettings(); + }); + + describe('empty state', () => { + it('no index pattern', function () { + // Go to the Discover page + miscUtils.visitPage( + `app/data-explorer/discover#/?_g=(filters:!(),time:(from:'2015-09-19T13:31:44.000Z',to:'2015-09-24T01:31:44.000Z'))` + ); + + cy.waitForLoaderNewHeader(); + cy.getElementByTestId('discoverNoIndexPatterns'); + }); + }); + + describe('select indices', () => { + before(() => { + testFixtureHandler.importJSONMapping( + 'cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/mappings.json.txt' + ); + + testFixtureHandler.importJSONDoc( + 'cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/data.json.txt' + ); + + // Since default cluster is removed, need to create a data source connection + miscUtils.visitPage( + 'app/management/opensearch-dashboards/dataSources/create' + ); + cy.intercept('POST', '/api/saved_objects/data-source').as( + 'createDataSourceRequest' + ); + cy.getElementByTestId(`datasource_card_opensearch`).click(); + cy.get('[name="dataSourceTitle"]').type(clusterName); + cy.get('[name="endpoint"]').type(clusterConnection); + cy.getElementByTestId('createDataSourceFormAuthTypeSelect').click(); + cy.get(`button[id="no_auth"]`).click(); + + cy.getElementByTestId('createDataSourceButton').click(); + cy.wait('@createDataSourceRequest').then((interception) => { + expect(interception.response.statusCode).to.equal(200); + }); + cy.location('pathname', { timeout: 6000 }).should( + 'include', + 'app/management/opensearch-dashboards/dataSources' + ); + + // Go to the Discover page + miscUtils.visitPage(`app/data-explorer/discover#/`); + + cy.waitForLoaderNewHeader(); + }); + + it('with SQL as default language', function () { + cy.getElementByTestId(`datasetSelectorButton`).click(); + cy.getElementByTestId(`datasetSelectorAdvancedButton`).click(); + cy.get(`[title="Indexes"]`).click(); + cy.get(`[title=${clusterName}]`).click(); + cy.get(`[title="timestamp-nanos"]`).click(); + cy.getElementByTestId('datasetSelectorNext').click(); + + cy.get(`[class="euiModalHeader__title"]`).should( + 'contain', + 'Step 2: Configure data' + ); + // should have two options: SQL and PPL + cy.getElementByTestId('advancedSelectorLanguageSelect') + .get('option') + .should('have.length', 2); + + //select SQL + cy.getElementByTestId('advancedSelectorLanguageSelect').select( + 'OpenSearch SQL' + ); + cy.getElementByTestId('advancedSelectorConfirmButton').click(); + + cy.waitForLoaderNewHeader(); + + // SQL should already be selected + cy.getElementByTestId('queryEditorLanguageSelector').should( + 'contain', + 'OpenSearch SQL' + ); + cy.waitForLoaderNewHeader(); + + // 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.waitForLoaderNewHeader(); + cy.get(`[data-test-subj="queryResultCompleteMsg"]`).should('be.visible'); + }); + + it('with PPL as default language', function () { + cy.getElementByTestId(`datasetSelectorButton`).click(); + cy.getElementByTestId(`datasetSelectorAdvancedButton`).click(); + cy.get(`[title="Indexes"]`).click(); + cy.get(`[title=${clusterName}]`).click(); + cy.get(`[title="timestamp-nanos"]`).click(); + cy.getElementByTestId('datasetSelectorNext').click(); + + cy.get(`[class="euiModalHeader__title"]`).should( + 'contain', + 'Step 2: Configure data' + ); + + //select PPL + cy.getElementByTestId('advancedSelectorLanguageSelect').select('PPL'); + + cy.getElementByTestId(`advancedSelectorTimeFieldSelect`).select( + 'timestamp' + ); + cy.getElementByTestId('advancedSelectorConfirmButton').click(); + + cy.waitForLoaderNewHeader(); + + // PPL should already be selected + cy.getElementByTestId('queryEditorLanguageSelector').should( + 'contain', + 'PPL' + ); + + const fromTime = 'Sep 19, 2018 @ 00:00:00.000'; + const toTime = 'Sep 21, 2019 @ 00:00:00.000'; + cy.setTopNavDate(fromTime, toTime); + + cy.waitForLoaderNewHeader(); + + // 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.waitForLoaderNewHeader(); + cy.getElementByTestId('queryResultCompleteMsg').should('be.visible'); + cy.getElementByTestId('queryEditorFooterTimestamp').should( + 'contain', + 'timestamp' + ); + }); + }); + + describe('index pattern', () => { + it('create index pattern and select it', function () { + // import logstash functional + testFixtureHandler.importJSONDocIfNeeded( + indexSet, + 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/logstash/logstash.mappings.json.txt', + 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/logstash/logstash.json.txt' + ); + testFixtureHandler.importJSONMapping( + 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/discover/discover.mappings.json.txt' + ); + + testFixtureHandler.importJSONDoc( + 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/discover/discover.json.txt' + ); + + // Go to the Discover page + miscUtils.visitPage( + `app/data-explorer/discover#/?_g=(filters:!(),time:(from:'2015-09-19T13:31:44.000Z',to:'2015-09-24T01:31:44.000Z'))` + ); + + cy.get(`[class~="datasetSelector__button"]`).click(); + cy.getElementByTestId(`datasetOption-logstash-*`).click(); + + cy.waitForLoaderNewHeader(); + cy.waitForSearch(); + cy.verifyHitCount('14,004'); + }); + }); + + after(() => { + cy.deleteIndex('timestamp-nanos'); + // delete the data source connection + miscUtils.visitPage('app/management/opensearch-dashboards/dataSources/'); + cy.get(`[class="euiTableRowCell"]`).contains(clusterName).click(); + cy.getElementByTestId('editDatasourceDeleteIcon').click(); + cy.getElementByTestId('confirmModalConfirmButton').click(); + }); +}); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancement/queries.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancement/queries.spec.js new file mode 100644 index 000000000..d8a076c5b --- /dev/null +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/query_enhancement/queries.spec.js @@ -0,0 +1,126 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +import { + MiscUtils, + TestFixtureHandler, +} from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { CURRENT_TENANT } from '../../../../../utils/commands'; + +const miscUtils = new MiscUtils(cy); +const testFixtureHandler = new TestFixtureHandler( + cy, + Cypress.env('openSearchUrl') +); + +const indexSet = [ + 'logstash-2015.09.22', + 'logstash-2015.09.21', + 'logstash-2015.09.20', +]; + +describe('query enhancement queries', { scrollBehavior: false }, () => { + before(() => { + CURRENT_TENANT.newTenant = 'global'; + cy.fleshTenantSettings(); + + testFixtureHandler.importJSONMapping( + 'cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/mappings.json.txt' + ); + + testFixtureHandler.importJSONDoc( + 'cypress/fixtures/dashboard/opensearch_dashboards/query_enhancement/data_with_index_pattern.json.txt' + ); + + // Go to the Discover page + miscUtils.visitPage(`app/data-explorer/discover#/`); + + cy.setAdvancedSetting({ + defaultIndex: 'timestamp-*', + }); + + // Go to the Discover page + miscUtils.visitPage( + `app/data-explorer/discover#/?_g=(filters:!(),time:(from:'2018-09-19T13:31:44.000Z',to:'2019-09-24T01:31:44.000Z'))` + ); + + cy.get(`[class~="datasetSelector__button"]`).click(); + cy.get(`[data-test-subj="datasetOption-timestamp-*"]`).click(); + + cy.waitForLoaderNewHeader(); + cy.waitForSearch(); + }); + + describe('send queries', () => { + it('with DQL', function () { + const query = `_id:1`; + cy.setSingleLineQueryEditor(query); + cy.waitForLoaderNewHeader(); + cy.waitForSearch(); + cy.verifyHitCount(1); + + //query should persist across refresh + cy.reload(); + cy.verifyHitCount(1); + }); + + it('with Lucene', function () { + cy.setQueryLanguage('Lucene'); + + const query = `_id:1`; + cy.setSingleLineQueryEditor(query); + cy.waitForLoaderNewHeader(); + cy.waitForSearch(); + cy.verifyHitCount(1); + + //query should persist across refresh + cy.reload(); + cy.verifyHitCount(1); + }); + + it('with SQL', function () { + cy.setQueryLanguage('OpenSearch SQL'); + + // default SQL query should be set + cy.waitForLoaderNewHeader(); + cy.getElementByTestId(`osdQueryEditor__multiLine`).contains( + `SELECT * FROM timestamp-* LIMIT 10` + ); + cy.getElementByTestId(`queryResultCompleteMsg`).should('be.visible'); + + //query should persist across refresh + cy.reload(); + cy.getElementByTestId(`queryResultCompleteMsg`).should('be.visible'); + + cy.getElementByTestId(`osdQueryEditor__multiLine`).type(`{backspace}`); + cy.getElementByTestId(`querySubmitButton`).click(); + cy.waitForSearch(); + cy.getElementByTestId(`queryResultCompleteMsg`).should('be.visible'); + }); + + it('with PPL', function () { + cy.setQueryLanguage('PPL'); + + // default PPL query should be set + cy.waitForLoaderNewHeader(); + cy.getElementByTestId(`osdQueryEditor__multiLine`).contains( + `source = timestamp-*` + ); + cy.waitForSearch(); + cy.getElementByTestId('queryResultCompleteMsg').click(); + cy.get('[class="euiText euiText--small"]').then((text) => cy.log(text)); + cy.verifyHitCount(4); + + //query should persist across refresh + cy.reload(); + cy.verifyHitCount(4); + }); + + after(() => { + cy.deleteIndex('timestamp-nanos'); + cy.deleteIndex('timestamp-milis'); + cy.deleteSavedObject('index-pattern', 'index-pattern:timestamp-*'); + }); + }); +}); diff --git a/cypress/utils/dashboards/commands.js b/cypress/utils/dashboards/commands.js index bbabd73f1..fd92e5cd4 100644 --- a/cypress/utils/dashboards/commands.js +++ b/cypress/utils/dashboards/commands.js @@ -9,6 +9,7 @@ import './vis_type_table/commands'; import './vis_type_vega/commands'; import './vis-augmenter/commands'; import './data_explorer/commands'; +import './query_enhancement/commands'; Cypress.Commands.add('waitForLoader', () => { const opts = { log: false }; diff --git a/cypress/utils/dashboards/constants.js b/cypress/utils/dashboards/constants.js index 4079a5235..92e4d3baa 100644 --- a/cypress/utils/dashboards/constants.js +++ b/cypress/utils/dashboards/constants.js @@ -24,3 +24,4 @@ export * from './vis_type_timeline/constants'; export * from './vis-augmenter/constants'; export * from './data_explorer/constants'; export * from './vis_type_vega/constants'; +export * from './query_enhancement/constants'; diff --git a/cypress/utils/dashboards/query_enhancement/commands.js b/cypress/utils/dashboards/query_enhancement/commands.js new file mode 100644 index 000000000..88f852c9b --- /dev/null +++ b/cypress/utils/dashboards/query_enhancement/commands.js @@ -0,0 +1,47 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +Cypress.Commands.add('waitForLoaderNewHeader', () => { + const opts = { log: false }; + + Cypress.log({ + name: 'waitForPageLoad', + displayName: 'wait', + message: 'page load', + }); + cy.wait(Cypress.env('WAIT_FOR_LOADER_BUFFER_MS')); + cy.getElementByTestId('recentItemsSectionButton', opts); +}); + +Cypress.Commands.add('setSingleLineQueryEditor', (value, submit = true) => { + const opts = { log: false }; + + Cypress.log({ + name: 'setSingleLineQueryEditor', + displayName: 'set query', + message: value, + }); + + cy.getElementByTestId('osdQueryEditor__singleLine', opts).type(value, opts); + + if (submit) { + cy.updateTopNav(opts); + } +}); + +Cypress.Commands.add('setQueryLanguage', (value, submit = true) => { + const opts = { log: false }; + + Cypress.log({ + name: 'setQueryLanguage', + displayName: 'set language', + message: value, + }); + + cy.getElementByTestId(`queryEditorLanguageSelector`).click(); + cy.get(`[class~="languageSelector__menuItem"]`).contains(value).click({ + force: true, + }); +}); diff --git a/cypress/utils/dashboards/query_enhancement/constants.js b/cypress/utils/dashboards/query_enhancement/constants.js new file mode 100644 index 000000000..62d6c0ffb --- /dev/null +++ b/cypress/utils/dashboards/query_enhancement/constants.js @@ -0,0 +1,7 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export const clusterName = 'test_cluster'; +export const clusterConnection = 'http://localhost:9200'; diff --git a/package.json b/package.json index 024e3877c..7a4100b9d 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "osd:ciGroup7": "echo apps/data_explorer/aaa_before.spec.js,apps/data_explorer/doc_navigation.spec.js,apps/data_explorer/doc_table.spec.js,apps/data_explorer/errors.spec.js,apps/data_explorer/field_data.spec.js,apps/data_explorer/zzz_after.spec.js", "osd:ciGroup8": "echo apps/data_explorer/aaa_before.spec.js,apps/data_explorer/field_visualize.spec.js,apps/data_explorer/filter_editor.spec.js,apps/data_explorer/index_pattern_with_encoded_id.spec.js,apps/data_explorer/index_pattern_without_field.spec.js,apps/data_explorer/zzz_after.spec.js", "osd:ciGroup9": "echo apps/data_explorer/aaa_before.spec.js,apps/data_explorer/inspector.spec.js,apps/data_explorer/large_string.spec.js,apps/data_explorer/saved_queries.spec.js,apps/data_explorer/shared_links.spec.js,apps/data_explorer/sidebar.spec.js,apps/data_explorer/source_filter.spec.js,apps/data_explorer/zzz_after.spec.js", + "osd:ciGroup10": "echo apps/query_enhancement/*.js", "start-dummy-llm-server": "node ./cypress/support/assistant-dummy-llm.js" }, "repository": {