From 931bee23c5a94030d1089f9463694d85721e3f0a Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 09:34:20 -0800 Subject: [PATCH] Updating app analytics jest and cypress tests (#1398) (#1417) * some updates * beginning assertion * fix typo * TEMPORARY: only run app analytics github action * included wait for all requests * explicitly add sample data flights and logs * otel imported * update otel requests * reintroduce otel data * switch browser to electron * fixed issues with timepicker not being shared properly, separated app and explorer times * small updates to spec * fix some of the time logic * small fixes to spec * double click to open service flyout, doesn't work otherwise * click to render chart * fixed issue where availability lines weren't showing up due to deleted parsing * extra character for query while autocomplete issue is being worked on * uncomment everything whoops * typing bandaid * intercept loading panel and remove waits * minimally viable testing * switch back to electron * temp load data for ftr run * change waiting order * only need one loading panels wait * update ftr tests * include two network intercepts * ftr test update delete success getter * add intercept after selection * take into account new name * manual wait to isolate other issues * repeat test 10 times to check for flakiness * revert repeat 10 tests * updated snapshots * remove ftr test * go back to running all integration tests * reduce usage of within * run app analytics test 10 times on github runner * add wait to avoid test avoiding checkbox * explain why i have a wait * remove repeating tests * small changes * change and remove some jest tests --------- (cherry picked from commit 3733eeb5ed5177ef645780bf724d780c2089ed79) Signed-off-by: Paul Sebastian Signed-off-by: github-actions[bot] Co-authored-by: github-actions[bot] --- .../app_analytics_test/app_analytics.spec.js | 111 +- .cypress/utils/app_constants.js | 106 +- .../workflows/integration-tests-workflow.yml | 25 +- .../__snapshots__/flyout.test.tsx.snap | 1152 +++++++++++++++++ .../__snapshots__/utils.test.tsx.snap | 129 ++ .../__tests__/flyout.test.tsx | 27 + .../__tests__/utils.test.tsx | 94 ++ .../__snapshots__/search.test.tsx.snap | 3 + public/components/common/search/search.tsx | 8 +- .../custom_panels/helpers/utils.tsx | 4 + .../event_analytics/explorer/explorer.tsx | 8 +- .../event_analytics/explorer/log_explorer.tsx | 17 +- test/panels_constants.tsx | 1 + 13 files changed, 1596 insertions(+), 89 deletions(-) create mode 100644 public/components/application_analytics/__tests__/__snapshots__/flyout.test.tsx.snap create mode 100644 public/components/application_analytics/__tests__/__snapshots__/utils.test.tsx.snap create mode 100644 public/components/application_analytics/__tests__/flyout.test.tsx create mode 100644 public/components/application_analytics/__tests__/utils.test.tsx diff --git a/.cypress/integration/app_analytics_test/app_analytics.spec.js b/.cypress/integration/app_analytics_test/app_analytics.spec.js index b875d4f3b5..f1147d5a12 100644 --- a/.cypress/integration/app_analytics_test/app_analytics.spec.js +++ b/.cypress/integration/app_analytics_test/app_analytics.spec.js @@ -7,7 +7,6 @@ import { suppressResizeObserverIssue } from '../../utils/constants'; import { - delay, moveToHomePage, moveToCreatePage, moveToApplication, @@ -32,17 +31,23 @@ import { composition, newName, TYPING_DELAY, - timeoutDelay + timeoutDelay, + loadAllData } from '../../utils/app_constants'; suppressResizeObserverIssue();//needs to be in file once describe('Creating application', () => { + before(() => { + loadAllData(); + }); + beforeEach(() => { moveToCreatePage(); }); it('Suggests correct autocompletion', () => { + cy.get('[data-test-subj="createPageTitle"').should('contain', 'Create application'); cy.get('[data-test-subj="logSourceAccordion"]').trigger('mouseover').click(); cy.get('[data-test-subj="searchAutocompleteTextArea"]').click(); cy.get('.aa-List').find('.aa-Item').should('have.length', 1); @@ -87,15 +92,15 @@ describe('Creating application', () => { cy.get('[data-test-subj="createButton"]').should('not.be.disabled'); cy.get('[data-test-subj="createAndSetButton"]').should('be.disabled'); expectMessageOnHover('createAndSetButton', 'Log source is required to set availability.'); - cy.get('[data-test-subj="searchAutocompleteTextArea"]').focus().type(' ' + baseQuery); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').click().type(' ' + baseQuery); cy.get('[data-test-subj="traceGroupsAccordion"]').trigger('mouseover').click(); cy.get('[data-test-subj="traceGroupsComboBox"]').scrollIntoView().type('http'); - cy.get('.euiFilterSelectItem').contains(trace_one).trigger('click'); - cy.get('.euiFilterSelectItem').contains(trace_two).trigger('click'); + cy.get('.euiFilterSelectItem').contains(trace_one).trigger('mouseover').click(); + cy.get('.euiFilterSelectItem').contains(trace_two).trigger('mouseover').click(); cy.get('[data-test-subj="traceGroupsCountBadge"]').should('contain', '2'); cy.get('[data-test-subj="createButton"]').should('not.be.disabled'); cy.get('[data-test-subj="createButton"]').click(); - cy.get('.euiTableRow').should('have.length.lessThan', 2);//Replaces Wait + cy.get('.euiTableRow').should('have.length.lessThan', 2); cy.get('[data-test-subj="applicationTitle"]').should('contain', nameOne); cy.get('[data-test-subj="app-analytics-panelTab"]').click(); cy.get('[data-test-subj="addFirstVisualizationText"]').should('exist'); @@ -113,14 +118,12 @@ describe('Creating application', () => { cy.get('[data-test-subj="searchAutocompleteTextArea"]').click(); cy .get('[data-test-subj="searchAutocompleteTextArea"]') - .focus() + .click() .type(' ' + baseQuery); cy.get('[data-test-subj="servicesEntitiesAccordion"]').trigger('mouseover').click(); cy.get('[data-test-subj="servicesEntitiesComboBox"]').scrollIntoView(); - cy.wait(delay*3); cy.get('[data-test-subj="servicesEntitiesComboBox"]').trigger('mouseover').click(); - cy.wait(delay*3);//Dropdown menu needs to work properly - cy.get('.euiFilterSelectItem').contains(service_one).click({ force: true }); + cy.get('.euiFilterSelectItem').contains(service_one).trigger('click'); cy.get('[data-test-subj="servicesEntitiesCountBadge"]').should('contain', '1'); cy.get('[data-test-subj="traceGroupsAccordion"]').trigger('mouseover').click(); cy.get('[data-test-subj="traceGroupsComboBox"]').scrollIntoView().type('http'); @@ -139,7 +142,7 @@ describe('Creating application', () => { it('Shows clear modals before clearing', () => { cy.get('[data-test-subj="logSourceAccordion"]').trigger('mouseover').click(); cy.get('[data-test-subj="clearLogSourceButton"]').should('be.disabled'); - cy.get('[data-test-subj="searchAutocompleteTextArea"]').focus().type(' ' + baseQuery); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').click().type(' ' + baseQuery); cy.get('[data-test-subj="clearLogSourceButton"]').click(); cy.get('.euiButton--danger').contains('Clear').click(); cy.get('[data-test-subj="searchAutocompleteTextArea"]').should('contain.value', ''); @@ -162,10 +165,9 @@ describe('Creating application', () => { }); it('Saves time range for each application', () => { - cy.wait(delay);//Fail to load without cy.get('[data-test-subj="nameFormRow"]').type(nameTwo); cy.get('[data-test-subj="logSourceAccordion"]').trigger('mouseover').click(); - cy.get('[data-test-subj="searchAutocompleteTextArea"]').focus().type(' ' +baseQuery); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').click().type(' ' +baseQuery); cy.get('[data-test-subj="createButton"]').should('not.be.disabled'); cy.get('[data-test-subj="createButton"]').click(); cy.get('.euiTableRow').should('have.length.lessThan', 1); @@ -175,7 +177,6 @@ describe('Creating application', () => { cy.get('.euiBreadcrumb[href="#/"]').click(); cy.get('.euiTableRow').should('have.length.greaterThan', 1); cy.get(`[data-test-subj="${nameOne}ApplicationLink"]`).click(); - cy.wait(delay*3); cy.get('.euiTableRow').should('have.length.lessThan', 1); cy.get('[data-test-subj="applicationTitle"]').should('contain', nameOne); changeTimeTo24('months'); @@ -198,14 +199,14 @@ describe('Setting availability', () => { moveToCreatePage(); cy.get('[data-test-subj="nameFormRow"]').type(nameThree); cy.get('[data-test-subj="logSourceAccordion"]').trigger('mouseover').click(); - cy.get('[data-test-subj="searchAutocompleteTextArea"]').focus(); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').click(); cy.focused().type(' source = ',); cy.focused().type('{enter}'); - cy.wait(delay);//needed for page to create correctly cy.get('[data-test-subj="createAndSetButton"]').click({ force: true }); cy.get('.euiTableRow').should('have.length.lessThan', 1); cy.get('[data-test-subj="applicationTitle"]').should('contain', nameThree); cy.get('.euiBreadcrumb[href="#/"]').click(); + cy.get(`[data-test-subj="${nameThree}ApplicationLink"]`); cy.get('[data-test-subj="setAvailabilityHomePageLink"]').first().click(); cy.get('[data-test-subj="applicationTitle"]').should('contain', nameThree); cy.get('.euiTab-isSelected[id="app-analytics-log"]').should('exist', { timeout: timeoutDelay }); @@ -230,7 +231,6 @@ describe('Viewing application', () => { }); it('Has working breadcrumbs', () => { - cy.wait(delay);//List not loading without cy.get('.euiBreadcrumb').contains(nameOne).click(); cy.get('[data-test-subj="applicationTitle"]').should('contain', nameOne); cy.get('.euiBreadcrumb[href="#/"]').click(); @@ -261,11 +261,10 @@ describe('Viewing application', () => { }); it('Adds filter when Trace group name is clicked', () => { - cy.wait(delay);//List not loading without cy.get('[data-test-subj="trace-groups-service-operation-accordian"]').click(); cy.get('[data-test-subj="dashboard-table-trace-group-name-button"]').contains('client_create_order').click(); cy.get('[data-test-subj="client_create_orderFilterBadge"]').should('exist'); - cy.get('[data-test-subj="filterBadge"]').eq(1).click(); + cy.get('[data-test-subj="filterBadge"]').eq(0).click(); cy.get('[data-test-subj="deleteFilterIcon"]').click(); cy.get('[data-test-subj="client_create_orderFilterBadge"]').should('not.exist'); }); @@ -274,12 +273,11 @@ describe('Viewing application', () => { cy.get('[data-test-subj="app-analytics-serviceTab"]').click(); cy.get('.euiLink').contains('authentication').click(); cy.get('[data-test-subj="serviceDetailFlyoutTitle"]').should('be.visible'); - cy.get('[data-test-subj="serviceDetailFlyout"]').within(($flyout) => { - cy.get('[data-test-subj="Number of connected servicesDescriptionList"]').should('contain', '3'); - cy.get('[data-text="Errors"]').click(); - cy.get('.ytitle').contains('Error rate').should('exist'); - }); - cy.get('[data-test-subj="dataGridRowCell"] button').contains('718dc32a693c8a17').click(); + cy.get('[data-test-subj="Number of connected servicesDescriptionList"]').should('contain', '3'); + cy.get('[data-text="Errors"]').eq(1).click(); // Selecting errors tab within flyout + cy.get('.ytitle').contains('Error rate').should('exist'); + cy.get('[data-test-subj="dataGridRowCell"]').eq(0).click({force: true}); // absolutely doesn't click no matter what unless theres a double click + cy.get('button[data-test-subj="spanId-link"]').eq(0).click({force: true}); cy.get('[data-test-subj="spanDetailFlyout"]').contains('Span detail').should('be.visible'); cy.get('[data-test-subj="ServiceDescriptionList"]').should('contain', 'authentication'); cy.get('[data-test-subj="euiFlyoutCloseButton"]').click(); @@ -298,7 +296,7 @@ describe('Viewing application', () => { cy.get('[data-test-subj="traceDetailFlyout"]').should('not.exist'); cy.get('[title="03f9c770db5ee2f1caac0afc36db49ba"]').click(); cy.get('[data-text="Span list"]').click(); - cy.get('[data-test-subj="dataGridRowCell"] button').contains('d67c5bb617ba9203').click(); + cy.get('[data-test-subj="dataGridRowCell"]').contains('d67c5bb617ba9203').click(); cy.get('[data-test-subj="spanDetailFlyout"]').should('be.visible'); cy.get('[data-test-subj="euiFlyoutCloseButton"]').click(); cy.get('[data-test-subj="spanDetailFlyout"]').should('not.exist'); @@ -306,8 +304,7 @@ describe('Viewing application', () => { it('Opens span detail flyout when Span ID is clicked', () => { cy.get('[data-test-subj="app-analytics-traceTab"]').click(); - cy.wait(delay); - cy.get('input[type="search"]').focus().type(`5ff3516909562c60`); + cy.get('input[type="search"]').click().type(`5ff3516909562c60`); cy.get('[data-test-subj="dataGridRowCell"]').contains('5ff3516909562c60').click(); cy.get('[data-test-subj="spanDetailFlyout"]').should('be.visible'); cy.get('[data-test-subj="spanDetailFlyout"]').within(($flyout) => { @@ -332,18 +329,19 @@ describe('Viewing application', () => { it('Saves visualization #1 to panel', () => { cy.get('[data-test-subj="app-analytics-panelTab"]').click(); cy.get('[data-test-subj="addVisualizationButton"]').first().click(); + cy.get('[data-test-subj="superDatePickerApplyTimeButton"]').click(); cy.get('[id="explorerPlotComponent"]').should('exist'); cy.get('[data-test-subj="searchAutocompleteTextArea"]').click(); cy.get('.aa-List').find('.aa-Item').should('have.length', 11); - cy.get('[data-test-subj="searchAutocompleteTextArea"]').focus().type(query_one, {delay: TYPING_DELAY}); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').focus(); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').type(' ' + query_one, {delay: TYPING_DELAY}) changeTimeTo24('months'); cy.get('[data-test-subj="main-content-visTab"]').click(); cy.get('[data-test-subj="eventExplorer__saveManagementPopover"]').click(); cy.get('[data-test-subj="eventExplorer__querySaveName"]').click().type(visOneName); cy.get('[data-test-subj="eventExplorer__querySaveConfirm"]').click(); - cy.wait(delay); + cy.get('.euiToast').contains(`Saved successfully`); cy.get('[data-test-subj="app-analytics-panelTab"]').click(); - cy.wait(delay); cy.get('[data-test-subj="Flights to VeniceVisualizationPanel"]').should('exist'); cy.get('[id="explorerPlotComponent"]').should('exist'); cy.get('[class="trace bars"]').should('exist'); @@ -354,9 +352,9 @@ describe('Viewing application', () => { cy.get('[aria-label="actionMenuButton"]').click(); cy.get('[data-test-subj="editVizContextMenuItem"]').click(); cy.get('[data-test-subj="superDatePickerShowDatesButton"]').should('contain', 'Last 24 months'); + cy.get('[data-test-subj="superDatePickerApplyTimeButton"]').click(); cy.get('.euiTab[id="availability-panel"]').click(); - cy.wait(delay); cy.get('[data-test-subj="comboBoxInput"]').click(); cy.get('[data-test-subj="comboBoxOptionsList "] button span').contains('Time series').click({ force: true }); cy.focused().type('{enter}'); @@ -388,40 +386,34 @@ describe('Viewing application', () => { it('Saves visualization #2 to panel with availability level', () => { changeTimeTo24('months'); cy.get('[data-test-subj="app-analytics-logTab"]').click(); + cy.get('[data-test-subj="superDatePickerApplyTimeButton"]').click(); cy.get('[id="explorerPlotComponent"]', { timeout: timeoutDelay }).should('exist'); - cy.get('[data-test-subj="searchAutocompleteTextArea"]').focus().type(query_two, {delay: TYPING_DELAY}); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').focus(); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').type(' ' + query_two, {delay: TYPING_DELAY}) cy.get('[data-test-subj="superDatePickerApplyTimeButton"]').click(); - cy.wait(delay); cy.get('[data-test-subj="main-content-visTab"]').click(); cy.get('.euiTab[id="availability-panel"]').click(); - cy.wait(delay); cy.get('[data-test-subj="comboBoxInput"]').click(); cy.get('[data-test-subj="comboBoxOptionsList "] button span').contains('Time series').click({ force: true }); cy.get('[data-test-subj="addAvailabilityButton"]').click(); cy.get('[data-test-subj="euiColorPickerAnchor"]').click(); cy.get('[aria-label="Select #9170B8 as the color"]').click(); - cy.wait(delay); cy.get('[data-test-subj="nameFieldText"]').click().type('Super'); cy.get('[data-test-subj="expressionSelect"]').select('<'); cy.get('[data-test-subj="valueFieldNumber"]').clear().type('5.5'); cy.get('[data-test-subj="visualizeEditorRenderButton"]').click(); - cy.wait(delay); cy.get('[data-test-subj="addAvailabilityButton"]').click(); cy.get('[data-test-subj="euiColorPickerAnchor"]').first().click(); cy.get('[aria-label="Select #CA8EAE as the color"]').click(); - cy.wait(delay); cy.get('[data-test-subj="nameFieldText"]').first().click().type('Cool'); cy.get('[data-test-subj="expressionSelect"]').first().select('>'); cy.get('[data-test-subj="valueFieldNumber"]').first().clear().type('0'); cy.get('[data-test-subj="visualizeEditorRenderButton"]').click(); - cy.wait(delay); cy.get('[data-test-subj="eventExplorer__saveManagementPopover"]').click(); cy.get('[data-test-subj="eventExplorer__querySaveName"]').click().type(visTwoName); - cy.wait(delay); cy.get('[data-test-subj="eventExplorer__querySaveConfirm"]').click(); - cy.wait(delay); + cy.get('.euiToast').contains(`Saved successfully`); cy.get('[data-test-subj="app-analytics-panelTab"]').click(); - cy.wait(delay); cy.get('[id="explorerPlotComponent"]').should('have.length', 2); moveToHomePage(); cy.get('[data-test-subj="SuperAvailabilityBadge"][style="background-color: rgb(145, 112, 184); color: rgb(0, 0, 0);"]').should('contain', 'Super'); @@ -429,7 +421,6 @@ describe('Viewing application', () => { it('Configuration tab shows details', () => { cy.get('[data-test-subj="app-analytics-configTab"]').click(); - cy.wait(delay); cy.get('[data-test-subj="configBaseQueryCode"]').should('contain', baseQuery); cy.get('[aria-label="List of services and entities"]').find('li').should('have.length', 1); cy.get('[aria-label="List of trace groups"]').find('li').should('have.length', 2); @@ -439,14 +430,16 @@ describe('Viewing application', () => { it('Changes availability visualization', () => { cy.get('[data-test-subj="app-analytics-configTab"]').click(); - cy.wait(delay); cy.get('select').select(visOneName); - cy.wait(delay); + cy.intercept('PUT', `**/api/observability/application`).as('selectUpdate'); + cy.wait('@selectUpdate') + cy.wait(2000); // despite the previous wait grabbing the call that updates the panel select, it doesn't appear without this moveToHomePage(); + cy.intercept('GET', `**/api/observability/operational_panels/panels/**`).as('loadingPanels') + cy.wait('@loadingPanels'); cy.get('[data-test-subj="AvailableAvailabilityBadge"][style="background-color: rgb(84, 179, 153); color: rgb(0, 0, 0);"]').should('contain', 'Available'); moveToApplication(nameOne); cy.get('[data-test-subj="app-analytics-configTab"]').click(); - cy.wait(delay); cy.get('select').find('option:selected').should('have.text', visOneName); }) }); @@ -454,31 +447,30 @@ describe('Viewing application', () => { describe('Separate from other plugins', () => { it('Hides application visualizations in Event Analytics', () => { cy.visit(`${Cypress.env('opensearchDashboards')}/app/observability-dashboards#/event_analytics`); - cy.wait(delay * 3); // When there are saved queries or visualizations there are two buttons cy.get('body').then(($body) => { if ($body.find('.euiButton').length == 2) { cy.get('input.euiFieldSearch').type(visOneName, {delay: TYPING_DELAY}); - cy.wait(delay); + cy.get('.euiTableCellContent__text').contains('No items found').should('exist'); cy.get('input.euiFieldSearch').clear().type(visTwoName, {delay: TYPING_DELAY}); - cy.wait(delay); + cy.get('.euiTableCellContent__text').contains('No items found').should('exist'); cy.get('[class="euiFormControlLayoutClearButton"]').click(); - cy.wait(delay); + cy.get('[data-test-subj="tablePaginationPopoverButton"]').click(); cy.get('.euiContextMenuItem__text').contains('50 rows').click(); cy.get('.euiCheckbox__input[data-test-subj="checkboxSelectAll"]').click(); - cy.wait(delay); + cy.get('[data-test-subj="eventHomeAction"]').click(); - cy.wait(delay); + cy.get('[data-test-subj="eventHomeAction__delete"]').click(); - cy.wait(delay); + cy.get('[data-test-subj="popoverModal__deleteButton"]').should('be.disabled'); cy.get('[data-test-subj="popoverModal__deleteTextInput"]').type('delete'); cy.get('[data-test-subj="popoverModal__deleteButton"]').should('not.be.disabled'); cy.get('[data-test-subj="popoverModal__deleteButton"]').click(); - cy.wait(delay); + } }) }); @@ -490,9 +482,7 @@ describe('Separate from other plugins', () => { cy.get('[data-test-subj="operationalPanelsActionsButton"]', { timeout: timeoutDelay }).click(); cy.get('[data-test-subj="addSampleContextMenuItem"]', { timeout: timeoutDelay }).click(); cy.get('[data-test-subj="confirmModalConfirmButton"]', { timeout: timeoutDelay }).click(); - cy.wait(delay * 2); cy.get('.euiLink').contains('[Logs] Web traffic Panel').first().click(); - cy.wait(delay * 2); cy.get('[data-test-subj="addVisualizationButton"]').click(); cy.get('.euiContextMenuItem__text').contains('Select existing visualization').click(); cy.get('option').contains(visOneName).should('not.exist'); @@ -560,15 +550,12 @@ describe('Application Analytics home page', () => { cy.get('[data-test-subj="appAnalyticsActionsButton"]').click(); cy.get('[data-test-subj="renameApplicationContextMenuItem"]').should('be.disabled'); cy.get('[data-test-subj="appAnalyticsActionsButton"]').click(); - cy.get('.euiTableRow').first().within(($row) => { - cy.get('.euiCheckbox').click(); - }); - cy.wait(delay); + cy.get('.euiTableRow').first().find('.euiCheckbox').click(); + cy.wait(2000); // checkbox being clicked has a small delay before enabling action button cy.get('[data-test-subj="appAnalyticsActionsButton"]').click(); cy.get('[data-test-subj="renameApplicationContextMenuItem"]').click(); - cy.get('[data-test-subj="customModalFieldText"]').clear().focus().type(newName); + cy.get('[data-test-subj="customModalFieldText"]').clear().click().type(newName); cy.get('[data-test-subj="runModalButton"]').click(); - cy.wait(delay); cy.get('.euiToast').contains(`Application successfully renamed to "${newName}"`); cy.get('.euiTableRow').first().within(($row) => { cy.get('.euiLink').contains(newName).should('exist'); diff --git a/.cypress/utils/app_constants.js b/.cypress/utils/app_constants.js index 1ea09e351a..5064e4f165 100644 --- a/.cypress/utils/app_constants.js +++ b/.cypress/utils/app_constants.js @@ -5,11 +5,110 @@ export const delay = 1000; export const timeoutDelay = 30000; -export const TYPING_DELAY = 150; +export const TYPING_DELAY = 450; + +export const loadAllData = () => { + // flights and web logs, not using ecommerce currently + loadAllSampleData(); + + loadOtelData(); +} + +export const loadOtelData = () => { + testIndexDataSet.forEach(({ mapping_url, data_url, index }) => + dumpDataSet(mapping_url, data_url, index) + ); +} + +export const loadAllSampleData = () => { + // Deleting all indices, cypress doesn't support conditionals in any way so to create a single + // line of execution, need to start from a clean slate + cy.request( + 'DELETE', + `${Cypress.env('opensearch')}/index*,sample*,opensearch_dashboards*,test*,cypress*` + ); + + cy.visit(`${Cypress.env('opensearchDashboards')}/app/home#/tutorial_directory`); + + // Load sample flights data + cy.get(`button[data-test-subj="addSampleDataSetflights"]`).click({ + force: true, + }); + // Load sample logs data + cy.get(`button[data-test-subj="addSampleDataSetlogs"]`).click({ + force: true, + }); + + // Verify that sample data is add by checking toast notification + cy.contains('Sample flight data installed', { timeout: 60000 }); + cy.contains('Sample web logs installed', { timeout: 60000 }); +} + +// took dumpDataSet and testIndexDataSet from https://github.com/opensearch-project/opensearch-dashboards-functional-test/blob/main/cypress/integration/plugins/observability-dashboards/0_before.spec.js +const dumpDataSet = (mapping_url, data_url, index) => { + cy.request({ + method: 'PUT', + failOnStatusCode: false, + url: `${Cypress.env('opensearch')}/${index}`, + headers: { + 'content-type': 'application/json;charset=UTF-8', + 'osd-xsrf': true, + }, + }); + + cy.request(mapping_url).then((response) => { + cy.request({ + method: 'POST', + form: false, + url: `${Cypress.env('opensearch')}/${index}/_mapping`, + headers: { + 'content-type': 'application/json;charset=UTF-8', + 'osd-xsrf': true, + }, + body: response.body, + }); + }); + + cy.request(data_url).then((response) => { + cy.request({ + method: 'POST', + form: false, + url: `${Cypress.env('opensearch')}/${index}/_bulk`, + headers: { + 'content-type': 'application/json;charset=UTF-8', + 'osd-xsrf': true, + }, + body: response.body, + }); + }); +}; + +const testIndexDataSet = [ + { + mapping_url: + 'https://raw.githubusercontent.com/opensearch-project/dashboards-observability/main/.cypress/utils/otel-v1-apm-service-map-mappings.json', + data_url: + 'https://raw.githubusercontent.com/opensearch-project/dashboards-observability/main/.cypress/utils/otel-v1-apm-service-map.json', + index: 'otel-v1-apm-service-map', + }, + { + mapping_url: + 'https://raw.githubusercontent.com/opensearch-project/dashboards-observability/main/.cypress/utils/otel-v1-apm-span-000001-mappings.json', + data_url: + 'https://raw.githubusercontent.com/opensearch-project/dashboards-observability/main/.cypress/utils/otel-v1-apm-span-000001.json', + index: 'otel-v1-apm-span-000001', + }, + { + mapping_url: + 'https://raw.githubusercontent.com/opensearch-project/dashboards-observability/main/.cypress/utils/otel-v1-apm-span-000001-mappings.json', + data_url: + 'https://raw.githubusercontent.com/opensearch-project/dashboards-observability/main/.cypress/utils/otel-v1-apm-span-000002.json', + index: 'otel-v1-apm-span-000002', + }, +]; export const moveToHomePage = () => { cy.visit(`${Cypress.env('opensearchDashboards')}/app/observability-applications#/`); - cy.wait(delay * 3); cy.get('.euiTitle').contains('Applications').should('exist'); }; @@ -32,12 +131,11 @@ export const moveToEditPage = () => { moveToApplication(nameOne); cy.get('[data-test-subj="app-analytics-configTab"]').click(); cy.get('[data-test-subj="editApplicationButton"]').click(); - cy.wait(delay); cy.get('[data-test-subj="createPageTitle"]').should('contain', 'Edit application'); }; export const changeTimeTo24 = (timeUnit) => { - cy.get('[data-test-subj="superDatePickerToggleQuickMenuButton"]').trigger('mouseover').click(); + cy.get('[data-test-subj="superDatePickerToggleQuickMenuButton"]').trigger('mouseover').click({ force: true }); cy.get('[aria-label="Time unit"]').select(timeUnit); cy.get('.euiButton').contains('Apply').click(); cy.get('[data-test-subj="superDatePickerApplyTimeButton"]').click(); diff --git a/.github/workflows/integration-tests-workflow.yml b/.github/workflows/integration-tests-workflow.yml index c9b5397ea1..1809e241b0 100644 --- a/.github/workflows/integration-tests-workflow.yml +++ b/.github/workflows/integration-tests-workflow.yml @@ -23,16 +23,17 @@ jobs: matrix: os: [ubuntu-latest] java: [11] - testgroups: [ - app_analytics_test, - datasources_test, - event_analytics_test, - integrations_test, - metrics_analytics_test, - notebooks_test, - panels_test, - trace_analytics_test - ] + testgroups: + [ + app_analytics_test, + datasources_test, + event_analytics_test, + integrations_test, + metrics_analytics_test, + notebooks_test, + panels_test, + trace_analytics_test, + ] include: - os: ubuntu-latest cypress_cache_folder: ~/.cache/Cypress @@ -134,7 +135,7 @@ jobs: cd OpenSearch-Dashboards nohup yarn start --no-base-path --no-watch | tee dashboard.log & - - name : Check If OpenSearch Dashboards Is Ready + - name: Check If OpenSearch Dashboards Is Ready if: ${{ runner.os == 'Linux' }} run: | cd ./OpenSearch-Dashboards @@ -165,7 +166,7 @@ jobs: - name: Run Cypress tests for test group of ${{ matrix.testgroups }} run: | cd ./OpenSearch-Dashboards/plugins/dashboards-observability - yarn cypress:run --browser chrome --headless --spec '.cypress/integration/${{ matrix.testgroups }}/*' + yarn cypress:run --headless --spec '.cypress/integration/${{ matrix.testgroups }}/*' - name: Capture failure screenshots uses: actions/upload-artifact@v1 diff --git a/public/components/application_analytics/__tests__/__snapshots__/flyout.test.tsx.snap b/public/components/application_analytics/__tests__/__snapshots__/flyout.test.tsx.snap new file mode 100644 index 0000000000..619b7b293b --- /dev/null +++ b/public/components/application_analytics/__tests__/__snapshots__/flyout.test.tsx.snap @@ -0,0 +1,1152 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Trace Detail Render Flyout component render trace detail 1`] = ` + + +
+ + Overview + +
+
+ +
+ +
+ + + mockTrace + + , + "title": + Trace ID + , + }, + ] + } + type="column" + > +
+ +
+ +
+ +
+ Trace ID +
+
+
+
+
+
+ +
+ +
+ + mockTrace + +
+
+
+
+
+
+ +
+ +
+
+ + + - + + , + "title": + Trace group name + , + }, + ] + } + type="column" + > +
+ +
+ +
+ +
+ Trace group name +
+
+
+
+
+
+ +
+ +
+ + - + +
+
+
+
+
+
+ +
+ +
+
+ + + , + "title": + Latency + , + }, + ] + } + type="column" + > +
+ +
+ +
+ +
+ Latency +
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+ +
+
+ + + , + "title": + Last updated + , + }, + ] + } + type="column" + > +
+ +
+ +
+ +
+ Last updated +
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+ +
+
+ + + + + , + "title": + Errors + , + }, + ] + } + type="column" + > +
+ +
+ +
+ +
+ Errors +
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+ +
+ +
+ + +
+
+ + +
+ + +
+ + Time spent by service + +
+
+
+ +
+
+ +
+ +
+ + +
+ + +
+ +
+ + +
+ +
+ + + +
+ + +
+
+ + +
+ +
+ +
+ + +
+ + Spans + + + (0) + +
+
+
+
+
+ +
+ +
+ + + Select view of spans + + +
+ + + + + + + + + + +
+
+
+
+
+
+
+ +
+
+
+ + +
+ + +
+
+ + + +
+ + +
+
+ +
+ + Payload + +
+
+ +
+ + +`; diff --git a/public/components/application_analytics/__tests__/__snapshots__/utils.test.tsx.snap b/public/components/application_analytics/__tests__/__snapshots__/utils.test.tsx.snap new file mode 100644 index 0000000000..87f4811bce --- /dev/null +++ b/public/components/application_analytics/__tests__/__snapshots__/utils.test.tsx.snap @@ -0,0 +1,129 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Utils application analytics helper functions validates and renders getListItem function 1`] = ` +
+ + + example description + + , + "title": + example + , + }, + ] + } + type="column" + > +
+ +
+ +
+ +
+ example +
+
+
+
+
+
+ +
+ +
+ + example description + +
+
+
+
+
+
+ +
+ +
+`; diff --git a/public/components/application_analytics/__tests__/flyout.test.tsx b/public/components/application_analytics/__tests__/flyout.test.tsx new file mode 100644 index 0000000000..597d9afbbf --- /dev/null +++ b/public/components/application_analytics/__tests__/flyout.test.tsx @@ -0,0 +1,27 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { configure, mount } from 'enzyme'; +import Adapter from 'enzyme-adapter-react-16'; +import httpClientMock from '../../../../test/__mocks__/httpClientMock'; +import { TraceDetailRender } from '../components/flyout_components/trace_detail_render'; + +describe('Trace Detail Render Flyout component', () => { + configure({ adapter: new Adapter() }); + + it('render trace detail', () => { + const wrapper = mount( + {}} + mode="jaeger" + /> + ); + + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/public/components/application_analytics/__tests__/utils.test.tsx b/public/components/application_analytics/__tests__/utils.test.tsx new file mode 100644 index 0000000000..f57cd91df8 --- /dev/null +++ b/public/components/application_analytics/__tests__/utils.test.tsx @@ -0,0 +1,94 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { configure, mount } from 'enzyme'; +import httpClientMock from '../../../../test/__mocks__/httpClientMock'; +import Adapter from 'enzyme-adapter-react-16'; +import PPLService from 'public/services/requests/ppl'; + +import { + isNameValid, + getListItem, + fetchAppById, + removeTabData, + initializeTabData, + fetchPanelsVizIdList, + calculateAvailability, +} from '../helpers/utils'; +import { HttpResponse } from '../../../../../../src/core/public/http/types'; + +describe('Utils application analytics helper functions', () => { + configure({ adapter: new Adapter() }); + + it('validates isNameValid function', () => { + expect(isNameValid('example', [])).toStrictEqual([]); + expect(isNameValid('example', ['example'])).toStrictEqual(['Name must be unique.']); + expect(isNameValid('', [])).toStrictEqual(['Name must not be empty.']); + expect(isNameValid('example123example123example123example123example123', [])).toStrictEqual([ + 'Name must be less than 50 characters.', + ]); + }); + + it('validates and renders getListItem function', () => { + const wrapper = mount(getListItem('example', 'example description')); + expect(wrapper).toMatchSnapshot(); + }); + + it('validates calculateAvailability function', () => { + const client = httpClientMock; + client.get = jest.fn(() => { + return (Promise.resolve({ + objectId: '1fwqYIwBFPafSCH7X4bf', + lastUpdatedTimeMs: 1703093973554, + createdTimeMs: 1702420439006, + tenant: '', + operationalPanel: { + name: "sample's Panel", + visualizations: [ + { + id: 'panel_viz_c1c8f4ce-426a-46c9-80d6-4c3b2ab587e2', + savedVisualizationId: + 'observability-visualization:bc88fae0-9f5e-11ee-8972-ff1ca912e352', + x: 0, + y: 0, + w: 6, + h: 4, + }, + ], + timeRange: { + to: 'now', + from: 'now-24h', + }, + queryFilter: { + query: '', + language: 'ppl', + }, + applicationId: '1PwqYIwBFPafSCH7X4Zv', + }, + }) as unknown) as HttpResponse; + }); + const pplService = ({ + http: jest.fn(), + fetch: jest.fn(), + } as unknown) as PPLService; + const application = { + id: '1PwqYIwBFPafSCH7X4Zv', + dateCreated: '1702420438885', + dateModified: '1702420439112', + name: 'sample', + description: '', + baseQuery: 'source = opensearch_dashboards_sample_data_ecommerce ', + servicesEntities: [], + traceGroups: [], + panelId: '1fwqYIwBFPafSCH7X4bf', + availability: { + name: '', + color: 'loading', + availabilityVisId: '', + }, + }; + calculateAvailability(client, pplService, application, '', () => {}); + }); +}); diff --git a/public/components/common/search/__tests__/__snapshots__/search.test.tsx.snap b/public/components/common/search/__tests__/__snapshots__/search.test.tsx.snap index eb6a831c68..67dbe9c1e0 100644 --- a/public/components/common/search/__tests__/__snapshots__/search.test.tsx.snap +++ b/public/components/common/search/__tests__/__snapshots__/search.test.tsx.snap @@ -921,6 +921,7 @@ exports[`Explorer Search component renders basic component 1`] = ` >