From eefa3287b049c7efef77e98b03a5362668f435c5 Mon Sep 17 00:00:00 2001 From: Anan Date: Wed, 23 Oct 2024 10:57:28 -0700 Subject: [PATCH] Add tests for query enhancement discover covering basic functions and shared links Signed-off-by: Anan --- .../discover_enhancement.spec.js | 287 ++++++++++++++++++ .../shared_links_enhancement.spec.js | 224 ++++++++++++++ cypress/utils/dashboards/commands.js | 109 ++++++- .../dashboards/data_explorer/commands.js | 91 ++++-- cypress/utils/dashboards/index.d.ts | 13 +- package-lock.json | 18 +- package.json | 3 +- 7 files changed, 692 insertions(+), 53 deletions(-) create mode 100644 cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover_enhancement.spec.js create mode 100644 cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/shared_links_enhancement.spec.js diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover_enhancement.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover_enhancement.spec.js new file mode 100644 index 000000000..2e631b32e --- /dev/null +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover_enhancement.spec.js @@ -0,0 +1,287 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + TestFixtureHandler, + MiscUtils, +} from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { CURRENT_TENANT } from '../../../../../utils/commands'; +import { + DE_DEFAULT_END_TIME, + DE_DEFAULT_START_TIME, +} 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( + 'discover query enhancement basic functions', + { scrollBehavior: false }, + () => { + const isEnhancement = true; + before(() => { + CURRENT_TENANT.newTenant = 'global'; + cy.log('load opensearch-dashboards index with default index pattern'); + + // import long window logstash index pattern + testFixtureHandler.importJSONDoc( + 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/long_window_logstash_index_pattern/data.json.txt' + ); + + // 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' + ); + + // import long window logstash + testFixtureHandler.importJSONMapping( + 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/long_window_logstash/mappings.json.txt' + ); + + testFixtureHandler.importJSONDoc( + 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/long_window_logstash/data.json.txt' + ); + + cy.setAdvancedSetting({ + defaultIndex: 'long-window-logstash-*', + 'dateFormat:tz': 'Europe/Berlin', + 'query:enhancements:enabled': true, + 'home:useNewHomePage': true, + }); + + cy.reload(); + + // Go to the Discover page + miscUtils.visitPage('app/data-explorer/discover#/'); + }); + + after(() => { + miscUtils.visitPage('app/management/opensearch-dashboards/settings'); + cy.waitForLoader(isEnhancement); + cy.getElementByTestId('advancedSetting-resetField-dateFormat:tz').click({ + force: true, + }); + cy.getElementByTestId('advancedSetting-saveButton').click({ + force: true, + }); + testFixtureHandler.clearJSONMapping( + 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/long_window_logstash/mappings.json.txt' + ); + cy.deleteIndex('long-window-logstash-0'); + cy.deleteSavedObjectByType('index-pattern'); + cy.setAdvancedSetting({ + defaultIndex: '', + 'dateFormat:tz': 'Browser', + 'query:enhancements:enabled': false, + 'home:useNewHomePage': false, + }); + + cy.reload(); + cy.clearCache(); + }); + + describe('no result panel', () => { + before(() => { + cy.selectDatasetForEnhancement('long-window-logstash-*'); + // Set a time range where we know there will be no data + const fromTime = 'Jan 1, 2024 @ 00:00:00.000'; + const toTime = 'Jan 2, 2024 @ 00:00:00.000'; + cy.setTopNavDateWithRetry(fromTime, toTime, isEnhancement); + }); + + it('should show no results', () => { + // Check for the presence of the no results component + cy.getElementByTestId('discoverNoResults').should('be.visible'); + cy.getElementByTestId('discoverNoResultsTimefilter') + .should('be.visible') + .should( + 'contain.text', + 'Try selecting a different data source, expanding your time range or modifying the query & filters.' + ); + }); + }); + + describe('render discover with side bar, top nav and canvas', () => { + before(() => { + // Set a time range where we know there will be no data + const fromTime = 'Nov 01, 2017 @ 00:00:00.000'; + const toTime = 'Mar 21, 2018 @ 00:00:00.000'; + cy.setTopNavDateWithRetry(fromTime, toTime, isEnhancement); + }); + + it('should show side bar with DatasetSelector', () => { + // Test dataset selector exist + cy.getElementByTestId(`datasetSelectorButton`).should('exist'); + + // Also verify the sidebar has the field list sections + cy.getElementByTestId('fieldList-selected').should('exist'); + cy.getElementByTestId('fieldList-unpopular').should('exist'); + }); + + it('should show top nav header', () => { + // Test main header container + cy.get('.headerAppActionMenuSection').should('exist'); + cy.getElementByTestId('headerAppActionMenu').should('exist'); + + // Test navigation menu + cy.getElementByTestId('top-nav').should('exist'); + + // Test all action buttons exist + cy.getElementByTestId('discoverSaveButton').should('exist'); + cy.getElementByTestId('discoverOpenButton').should('exist'); + cy.getElementByTestId('discoverNewButton').should('exist'); + cy.getElementByTestId('openInspectorButton').should('exist'); + cy.getElementByTestId('shareTopNavButton').should('exist'); + + // Test date picker exists + cy.getElementByTestId('superDatePickerToggleQuickMenuButton').should( + 'exist' + ); + }); + + it('should show globalQueryEditor', () => { + // Test the query editor and the query language selector components exist + cy.getElementByTestId('globalQueryEditor').should('exist'); + cy.getElementByTestId('queryEditorLanguageSelector').should('exist'); + }); + + it('should show discoverTable', () => { + // Test main discover table container exists + cy.getElementByTestId('discoverTable').should('exist'); + + // Test table exists and has correct structure + cy.getElementByTestId('docTable').should('exist'); + + // Test header cells exist + cy.getElementByTestId('docTableHeader').should('exist'); + cy.getElementByTestId('docTableHeaderField').should('exist'); + cy.getElementByTestId(`docTableHeader-@timestamp`).should('exist'); + cy.getElementByTestId(`docTableHeader-_source`).should('exist'); + + // Test table toggle and body exists + cy.getElementByTestId('docTableExpandToggleColumn').should('exist'); + cy.getElementByTestId('docTableField').should('exist'); + }); + }); + + describe('filters and queries', () => { + before(() => { + // Set a time range where we know there will be no data + const fromTime = 'Nov 01, 2017 @ 00:00:00.000'; + const toTime = 'Mar 21, 2018 @ 00:00:00.000'; + cy.setTopNavDateWithRetry(fromTime, toTime, isEnhancement); + }); + + it('should persist across refresh', function () { + // Set up query and filter + cy.setTopNavQuery('response:200', true, isEnhancement); + cy.getElementByTestId('showFilterActions').click(); + cy.submitFilterFromDropDown( + 'extension.keyword', + 'is one of', + 'jpg', + isEnhancement + ); + cy.reload(); + cy.get('.osdQueryEditor__input .monaco-editor .view-lines').should( + 'contain.text', + 'response:200' + ); + cy.get('[data-test-subj~="filter-key-extension.keyword"]') + .should('be.visible') + .click(); + cy.get('button[aria-label="Delete"]').click(); + }); + }); + + describe('save search', () => { + const saveSearch1 = 'Save Search # 1'; + const saveSearch2 = 'Modified Save Search # 1'; + + it('should show correct time range string by timepicker', function () { + cy.setTopNavDateWithRetry( + DE_DEFAULT_START_TIME, + DE_DEFAULT_END_TIME, + isEnhancement + ); + cy.verifyTimeConfig(DE_DEFAULT_START_TIME, DE_DEFAULT_END_TIME); + }); + + it('save search should display save search name in breadcrumb', function () { + cy.saveSearch(saveSearch1, isEnhancement); + cy.getElementByTestId('headerAppActionMenu') + .should('be.visible') + .should('contain', saveSearch1); + }); + + it('load save search should show save search name in breadcrumb', function () { + cy.loadSaveSearch(saveSearch1, isEnhancement); + + cy.getElementByTestId('headerAppActionMenu') + .should('be.visible') + .should('contain', saveSearch1); + }); + + it('renaming a save search should modify name in breadcrumb', function () { + cy.loadSaveSearch(saveSearch1, isEnhancement); + cy.saveSearch(saveSearch2, isEnhancement); + + cy.getElementByTestId('headerAppActionMenu') + .should('be.visible') + .should('contain', saveSearch2); + }); + + it('should show the correct hit count', function () { + cy.loadSaveSearch(saveSearch2, isEnhancement); + cy.setTopNavDateWithRetry( + DE_DEFAULT_START_TIME, + DE_DEFAULT_END_TIME, + isEnhancement + ); + const expectedHitCount = '31'; + cy.verifyHitCount(expectedHitCount); + }); + + it('should show correct time range string in chart', function () { + cy.getElementByTestId('discoverIntervalDateRange').should( + 'have.text', + `${DE_DEFAULT_START_TIME} - ${DE_DEFAULT_END_TIME} per` + ); + }); + + it('should show correct initial chart interval of Auto', function () { + cy.getElementByTestId('discoverIntervalSelect') + .get('option') + .first() + .should('have.text', 'Auto'); + }); + + it('should not show "no results"', () => { + cy.getElementByTestId('discoverNoResults').should('not.exist'); + }); + + it('should reload the saved search with persisted query to show the initial hit count', function () { + // apply query some changes + cy.setTopNavQuery('DE', true, isEnhancement); + cy.verifyHitCount('3'); + + // reset to persisted state + cy.getElementByTestId('resetSavedSearch').click(); + const expectedHitCount = '31'; + cy.verifyHitCount(expectedHitCount); + }); + }); + } +); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/shared_links_enhancement.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/shared_links_enhancement.spec.js new file mode 100644 index 000000000..9e652f537 --- /dev/null +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/shared_links_enhancement.spec.js @@ -0,0 +1,224 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + MiscUtils, + TestFixtureHandler, +} from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { + DE_DEFAULT_END_TIME, + DE_DEFAULT_START_TIME, +} from '../../../../../utils/constants'; +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('shared links', () => { + const isEnhancement = true; + before(() => { + CURRENT_TENANT.newTenant = 'global'; + cy.fleshTenantSettings(); + 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' + ); + + // 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' + ); + + cy.setAdvancedSetting({ + defaultIndex: 'logstash-*', + 'query:enhancements:enabled': true, + 'home:useNewHomePage': true, + }); + + cy.reload(); + + miscUtils.visitPage('app/data-explorer/discover#/'); + cy.waitForLoader(isEnhancement); + cy.selectDatasetForEnhancement('logstash-*'); + cy.setTopNavDateWithRetry( + DE_DEFAULT_START_TIME, + DE_DEFAULT_END_TIME, + isEnhancement + ); + cy.waitForSearch(); + }); + + beforeEach(() => { + CURRENT_TENANT.newTenant = 'global'; + cy.fleshTenantSettings(); + cy.selectDatasetForEnhancement('logstash-*'); + }); + + after(() => { + cy.deleteIndex(indexSet.join(',')); + cy.setAdvancedSetting({ + defaultIndex: '', + 'query:enhancements:enabled': false, + 'home:useNewHomePage': false, + }); + + cy.reload(); + cy.clearCache(); + }); + + describe('shared links with state in query', () => { + it('should allow for copying the snapshot URL', function () { + const url = `http://localhost:5601/app/data-explorer/discover#/?_a=(discover:(columns:!(_source),isDirty:!f,sort:!()),metadata:(view:discover))&_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2015-09-19T13:31:44.000Z',to:'2015-09-24T01:31:44.000Z'))&_q=(filters:!(),query:(dataset:(id:'logstash-*',timeFieldName:'@timestamp',title:'logstash-*',type:INDEX_PATTERN),language:kuery,query:''))`; + let sharedUrl; + cy.getElementByTestId('shareTopNavButton').should('be.visible').click(); + cy.getElementByTestId('copyShareUrlButton') + .should('be.visible') + .should('have.attr', 'data-share-url') + .then((copiedUrl) => { + sharedUrl = copiedUrl.replace( + /\?security_tenant=(global|private)/, + '' + ); + expect(sharedUrl).to.equal(url); + }); + cy.request(url).its('status').should('eq', 200); + }); + + it('should allow for copying the snapshot URL with filter and query', function () { + const url = `http://localhost:5601/app/data-explorer/discover#/?_a=(discover:(columns:!(_source),isDirty:!f,sort:!()),metadata:(view:discover))&_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2015-09-19T13:31:44.000Z',to:'2015-09-24T01:31:44.000Z'))&_q=(filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'logstash-*',key:geo.src,negate:!f,params:(query:FR),type:phrase),query:(match_phrase:(geo.src:FR)))),query:(dataset:(id:'logstash-*',timeFieldName:'@timestamp',title:'logstash-*',type:INDEX_PATTERN),language:kuery,query:'geo.dest:KH'))`; + let sharedUrl; + cy.setTopNavQuery('geo.dest:KH', true, true); + cy.getElementByTestId('showFilterActions').click(); + cy.submitFilterFromDropDown('geo.src', 'is', 'FR', isEnhancement); + cy.getElementByTestId('shareTopNavButton').should('be.visible').click(); + cy.getElementByTestId('copyShareUrlButton') + .should('be.visible') + .should('have.attr', 'data-share-url') + .then((copiedUrl) => { + sharedUrl = copiedUrl.replace( + /\?security_tenant=(global|private)/, + '' + ); + expect(sharedUrl).to.equal(url); + }); + cy.request(url).its('status').should('eq', 200); + cy.getElementByTestId('shareTopNavButton').should('be.visible').click(); + }); + + it('should allow for copying the snapshot URL as a short URL', function () { + cy.getElementByTestId('shareTopNavButton').should('be.visible').click(); + cy.getElementByTestId('useShortUrl') + .should('be.visible') + .invoke('attr', 'aria-checked', 'true'); + cy.wait(1000); + // For some reasons, after making the toggle true, the data-share-url do not get updated in the cypress test + // Thus only testing if the button is clickable, instead of comparing the actual URL + cy.getElementByTestId('copyShareUrlButton').should('be.visible').click(); + }); + + it('should allow for copying the saved object URL', function () { + const url = + 'http://localhost:5601/app/data-explorer/discover/#/view/ab12e3c0-f231-11e6-9486-733b1ac9221a?_g=%28filters%3A%21%28%29%2CrefreshInterval%3A%28pause%3A%21t%2Cvalue%3A0%29%2Ctime%3A%28from%3A%272015-09-19T13%3A31%3A44.000Z%27%2Cto%3A%272015-09-24T01%3A31%3A44.000Z%27%29%29'; + + cy.getElementByTestId('shareTopNavButton').should('be.visible').click(); + cy.getElementByTestId('exportAsSavedObject') + .get('.euiRadio__input') + .should('be.disabled'); + + // Load a save search + cy.loadSaveSearch('A Saved Search', isEnhancement); + cy.waitForLoader(isEnhancement); + cy.getElementByTestId('shareTopNavButton').should('be.visible').click(); + cy.getElementByTestId('exportAsSavedObject').should('be.visible').click(); + cy.getElementByTestId('copyShareUrlButton') + .invoke('attr', 'data-share-url') + .should('eq', url) + .then((url) => { + cy.log(url); + cy.request(url).its('status').should('eq', 200); + }); + }); + }); + + describe('shared links with state in sessionStorage', () => { + before(() => { + CURRENT_TENANT.newTenant = 'global'; + cy.fleshTenantSettings(); + cy.setAdvancedSetting({ + 'state:storeInSessionStorage': true, + }); + + miscUtils.visitPage('app/data-explorer/discover#/'); + cy.waitForLoader(isEnhancement); + cy.getElementByTestId(`datasetSelectorButton`).click(); + cy.getElementByTestId(`datasetOption-logstash-*`).click(); + cy.setTopNavDateWithRetry( + DE_DEFAULT_START_TIME, + DE_DEFAULT_END_TIME, + isEnhancement + ); + cy.waitForSearch(); + }); + + after(() => { + CURRENT_TENANT.newTenant = 'global'; + cy.fleshTenantSettings(); + cy.deleteSavedObjectByType('config'); + }); + + it('should allow for copying the snapshot URL', function () { + cy.getElementByTestId('shareTopNavButton').should('be.visible').click(); + cy.getElementByTestId('copyShareUrlButton') + .invoke('attr', 'data-share-url') + .then((url) => { + cy.log(url); + cy.request(url).its('status').should('eq', 200); + }); + }); + + it('should allow for copying the snapshot URL as a short URL', function () { + cy.getElementByTestId('shareTopNavButton').should('be.visible').click(); + cy.getElementByTestId('useShortUrl').should('be.visible').click(); + cy.getElementByTestId('copyShareUrlButton') + .invoke('attr', 'data-share-url') + .then((url) => { + cy.log(url); + cy.request(url).its('status').should('eq', 200); + }); + }); + + it('should allow for copying the saved object URL', function () { + cy.getElementByTestId('shareTopNavButton').should('be.visible').click(); + cy.getElementByTestId('exportAsSavedObject') + .get('.euiRadio__input') + .should('be.disabled'); + + // Load a save search + cy.loadSaveSearch('A Saved Search', isEnhancement); + cy.waitForLoader(isEnhancement); + cy.getElementByTestId('shareTopNavButton').should('be.visible').click(); + cy.getElementByTestId('exportAsSavedObject').should('be.visible').click(); + cy.getElementByTestId('copyShareUrlButton') + .invoke('attr', 'data-share-url') + .then((url) => { + cy.log(url); + cy.request(url).its('status').should('eq', 200); + }); + }); + }); +}); diff --git a/cypress/utils/dashboards/commands.js b/cypress/utils/dashboards/commands.js index 348465b92..296769d12 100644 --- a/cypress/utils/dashboards/commands.js +++ b/cypress/utils/dashboards/commands.js @@ -9,8 +9,9 @@ import './vis_type_table/commands'; import './vis_type_vega/commands'; import './vis-augmenter/commands'; import './data_explorer/commands'; +import moment from 'moment'; -Cypress.Commands.add('waitForLoader', () => { +Cypress.Commands.add('waitForLoader', (isEnhancement = false) => { const opts = { log: false }; Cypress.log({ @@ -18,28 +19,41 @@ Cypress.Commands.add('waitForLoader', () => { displayName: 'wait', message: 'page load', }); + cy.wait(Cypress.env('WAIT_FOR_LOADER_BUFFER_MS')); - cy.getElementByTestId('homeIcon', opts); // Update to `homeLoader` once useExpandedHeader is enabled + + // Use recentItemsSectionButton for query enhancement, otherwise use homeIcon + cy.getElementByTestId( + isEnhancement ? 'recentItemsSectionButton' : 'homeIcon', + opts + ); }); -Cypress.Commands.add('setTopNavQuery', (value, submit = true) => { - const opts = { log: false }; +Cypress.Commands.add( + 'setTopNavQuery', + (value, submit = true, isEnhancement = false) => { + const opts = { log: false }; - Cypress.log({ - name: 'setTopNavQuery', - displayName: 'set query', - message: value, - }); + Cypress.log({ + name: 'setTopNavQuery', + displayName: 'set query', + message: value, + }); - cy.getElementByTestId('queryInput', opts) - .clear(opts) - .type(value, opts) - .blur(opts); + const selector = isEnhancement + ? '.osdQueryEditor__input .monaco-editor .inputarea' // find by class + : '[data-test-subj="queryInput"]'; - if (submit) { - cy.updateTopNav(opts); + Cypress.log({ message: `isEnhancement is ${isEnhancement}` }); + Cypress.log({ message: `selector is ${selector}` }); + + cy.get(selector, opts).clear(opts).type(value, opts).blur(opts); + + if (submit) { + cy.updateTopNav(opts); + } } -}); +); Cypress.Commands.add('setTopNavDate', (start, end, submit = true) => { const opts = { log: false }; @@ -116,6 +130,69 @@ Cypress.Commands.add('setTopNavDate', (start, end, submit = true) => { } }); +Cypress.Commands.add( + 'setTopNavDateWithRetry', + (start, end, isEnhancement = false) => { + const MAX_RETRIES = 3; + const RETRY_DELAY = 1000; + + const parseDateString = (dateStr) => { + // Remove any trailing milliseconds if present (e.g., .000) + const cleanStr = dateStr.replace(/\.\d{3}$/, ''); + return moment(cleanStr, 'MMM DD, YYYY @ HH:mm:ss'); + }; + + const areDatesEqual = (date1Str, date2Str) => { + const date1 = parseDateString(date1Str); + const date2 = parseDateString(date2Str); + return date1.isSame(date2); + }; + + const verifyDates = () => { + return cy + .get('[data-test-subj="superDatePickerstartDatePopoverButton"]') + .should('be.visible') + .invoke('text') + .then((startText) => { + return cy + .get('[data-test-subj="superDatePickerendDatePopoverButton"]') + .should('be.visible') + .invoke('text') + .then((endText) => { + const startDateCorrect = areDatesEqual(startText.trim(), start); + const endDateCorrect = areDatesEqual(endText.trim(), end); + return { startDateCorrect, endDateCorrect }; + }); + }); + }; + + const attemptSetDates = (attempt = 1) => { + cy.log(`Attempt ${attempt} of ${MAX_RETRIES} to set dates`); + + return cy + .setTopNavDate(start, end) + .then(() => { + cy.waitForLoader(isEnhancement); + }) + .then(() => verifyDates()) + .then(({ startDateCorrect, endDateCorrect }) => { + if (!startDateCorrect || !endDateCorrect) { + if (attempt < MAX_RETRIES) { + cy.wait(RETRY_DELAY); + return attemptSetDates(attempt + 1); + } else { + throw new Error( + `Failed to set dates correctly after ${MAX_RETRIES} attempts` + ); + } + } + }); + }; + + return attemptSetDates(); + } +); + Cypress.Commands.add('updateTopNav', (options) => { cy.getElementByTestId('querySubmitButton', options).click({ force: true }); }); diff --git a/cypress/utils/dashboards/data_explorer/commands.js b/cypress/utils/dashboards/data_explorer/commands.js index a0ccff2e2..b87e363d2 100644 --- a/cypress/utils/dashboards/data_explorer/commands.js +++ b/cypress/utils/dashboards/data_explorer/commands.js @@ -17,7 +17,7 @@ Cypress.Commands.add('verifyTimeConfig', (start, end) => { .should('have.text', end); }); -Cypress.Commands.add('saveSearch', (name) => { +Cypress.Commands.add('saveSearch', (name, isEnhancement) => { cy.log('in func save search'); const opts = { log: false }; @@ -26,10 +26,10 @@ Cypress.Commands.add('saveSearch', (name) => { cy.getElementByTestId('confirmSaveSavedObjectButton').click({ force: true }); // Wait for page to load - cy.waitForLoader(); + cy.waitForLoader(isEnhancement); }); -Cypress.Commands.add('loadSaveSearch', (name) => { +Cypress.Commands.add('loadSaveSearch', (name, isEnhancement) => { const opts = { log: false, force: true, @@ -38,7 +38,7 @@ Cypress.Commands.add('loadSaveSearch', (name) => { cy.getElementByTestId('discoverOpenButton', opts).click(opts); cy.getElementByTestId(`savedObjectTitle${toTestId(name)}`).click(); - cy.waitForLoader(); + cy.waitForLoader(isEnhancement); }); Cypress.Commands.add('verifyHitCount', (count) => { @@ -57,45 +57,51 @@ Cypress.Commands.add('waitForSearch', () => { cy.getElementByTestId('docTable'); }); -Cypress.Commands.add('prepareTest', (fromTime, toTime, interval) => { - cy.setTopNavDate(fromTime, toTime); - cy.waitForLoader(); - // wait until the search has been finished - cy.waitForSearch(); - cy.get('select').select(`${interval}`); - cy.waitForLoader(); - cy.waitForSearch(); -}); +Cypress.Commands.add( + 'prepareTest', + (fromTime, toTime, interval, isEnhancement) => { + cy.setTopNavDate(fromTime, toTime); + cy.waitForLoader(isEnhancement); + // wait until the search has been finished + cy.waitForSearch(); + cy.get('select').select(`${interval}`); + cy.waitForLoader(isEnhancement); + cy.waitForSearch(); + } +); Cypress.Commands.add('verifyMarkCount', (count) => { cy.getElementByTestId('docTable').find('mark').should('have.length', count); }); -Cypress.Commands.add('submitFilterFromDropDown', (field, operator, value) => { - cy.getElementByTestId('addFilter').click(); - cy.getElementByTestId('filterFieldSuggestionList') - .should('be.visible') - .click() - .type(`${field}{downArrow}{enter}`) - .trigger('blur', { force: true }); - - cy.getElementByTestId('filterOperatorList') - .should('be.visible') - .click() - .type(`${operator}{downArrow}{enter}`) - .trigger('blur', { force: true }); +Cypress.Commands.add( + 'submitFilterFromDropDown', + (field, operator, value, isEnhancement = false) => { + cy.getElementByTestId(isEnhancement ? 'addFilters' : 'addFilter').click(); + cy.getElementByTestId('filterFieldSuggestionList') + .should('be.visible') + .click() + .type(`${field}{downArrow}{enter}`) + .trigger('blur', { force: true }); - if (value) { - cy.get('[data-test-subj^="filterParamsComboBox"]') + cy.getElementByTestId('filterOperatorList') .should('be.visible') .click() - .type(`${value}{downArrow}{enter}`) + .type(`${operator}{downArrow}{enter}`) .trigger('blur', { force: true }); - } - cy.getElementByTestId('saveFilter').click({ force: true }); - cy.waitForLoader(); -}); + if (value) { + cy.get('[data-test-subj^="filterParamsComboBox"]') + .should('be.visible') + .click() + .type(`${value}{downArrow}{enter}`) + .trigger('blur', { force: true }); + } + + cy.getElementByTestId('saveFilter').click({ force: true }); + cy.waitForLoader(isEnhancement); + } +); Cypress.Commands.add('saveQuery', (name, description) => { cy.whenTestIdNotFound('saved-query-management-popover', () => { @@ -156,6 +162,25 @@ Cypress.Commands.add('switchDiscoverTable', (name) => { }); }); +Cypress.Commands.add('selectDatasetForEnhancement', (indexPattern) => { + Cypress.log({ + name: 'selectDataset', + displayName: 'select dataset', + message: indexPattern, + }); + + cy.get('.datasetSelector__button').click(); + + cy.get('.euiSelectable.datasetSelector__selectable').should('be.visible'); + + cy.get('.euiSelectableListItem') + .contains(indexPattern) + .should('be.visible') + .click(); + + cy.get('.datasetSelector__button').should('contain.text', indexPattern); +}); + function checkForElementVisibility() { cy.getElementsByTestIds('queryInput') .should('be.visible') diff --git a/cypress/utils/dashboards/index.d.ts b/cypress/utils/dashboards/index.d.ts index 8b2f42d09..6c3fbf3b4 100644 --- a/cypress/utils/dashboards/index.d.ts +++ b/cypress/utils/dashboards/index.d.ts @@ -8,14 +8,14 @@ declare namespace Cypress { * @example * cy.waitForLoader() */ - waitForLoader(): Chainable; + waitForLoader(isEnhancement?: boolean): Chainable; /** * Set the top nav query value * @example * cy.setTopNavQuery('products.base_price > 40') */ - setTopNavQuery(value: string): Chainable; + setTopNavQuery(value: string, submit?: boolean, isEnhancement?: boolean): Chainable; /** * Set the top nav date range. @@ -25,6 +25,15 @@ declare namespace Cypress { */ setTopNavDate(start: string, end: string): Chainable; + /** + * Set the top nav date range for query enhancement, which has async issue and causes the SuperDatePicker to render out of current DOM. + * TODO: fix the bug and remove this function. + * Date format: MMM D, YYYY @ HH:mm:ss.SSS + * @example + * cy.setTopNavDateWithRetry('Oct 5, 2022 @ 00:57:06.429', 'Oct 6, 2022 @ 00:57:06.429', true) + */ + setTopNavDateWithRetry(start: string, end: string, isEnhancement?: boolean): Chainable; + /** * Clicks the update button on the top nav. * @example diff --git a/package-lock.json b/package-lock.json index b2e54dae1..b00a64aef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,8 @@ "eslint-plugin-prettier": "^4.0.0", "husky": "^6.0.0", "luxon": "^3.2.1", - "mocha-junit-reporter": "^2.0.0" + "mocha-junit-reporter": "^2.0.0", + "moment": "^2.29.4" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -2929,6 +2930,15 @@ "node": ">=10" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -6344,6 +6354,12 @@ } } }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "dev": true + }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", diff --git a/package.json b/package.json index 59d66bc47..a3e4b2a51 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,8 @@ "eslint-plugin-prettier": "^4.0.0", "husky": "^6.0.0", "luxon": "^3.2.1", - "mocha-junit-reporter": "^2.0.0" + "mocha-junit-reporter": "^2.0.0", + "moment": "^2.29.4" }, "overrides": { "tough-cookie": "^4.1.3",