From 5db8065e5918e382706587aa925a30144d1d7505 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Mon, 20 Nov 2023 17:19:24 -0800 Subject: [PATCH 01/21] Refactored alerting test, and added wait logic to reduce flakiness. (#953) Signed-off-by: AWSHurneyt --- .../monitors_dashboard_spec.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cypress/integration/plugins/alerting-dashboards-plugin/monitors_dashboard_spec.js b/cypress/integration/plugins/alerting-dashboards-plugin/monitors_dashboard_spec.js index ba8898ee6..7a42a6481 100644 --- a/cypress/integration/plugins/alerting-dashboards-plugin/monitors_dashboard_spec.js +++ b/cypress/integration/plugins/alerting-dashboards-plugin/monitors_dashboard_spec.js @@ -38,7 +38,7 @@ const clusterHealthMonitor = { severity: '1', condition: { script: { - source: 'ctx.results[0].status != "green"', + source: 'ctx.results[0].status != "blue"', lang: 'painless', }, }, @@ -107,8 +107,13 @@ describe('Monitors dashboard page', () => { }); it('Displays expected number of alerts', () => { + // Wait for table to finish loading + cy.get('tbody > tr').should(($tr) => + expect($tr).to.have.length.greaterThan(1) + ); + // Ensure the 'Monitor name' column is sorted in ascending order by sorting another column first - cy.contains('Last updated by').click({ force: true }); + cy.contains('Last notification time').click({ force: true }); cy.contains('Monitor name').click({ force: true }); testMonitors.forEach((entry) => { From c875187321b59a7aa89101516409aa1d73429883 Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Wed, 29 Nov 2023 13:51:59 +0800 Subject: [PATCH 02/21] feat: use ipv4 by default to fix CI flow (#960) * feat: use ipv4 by default to fix CI flow Signed-off-by: SuZhou-Joe * feat: remove duplicate NODE_OPTIONS Signed-off-by: SuZhou-Joe * fix: hang test cases Signed-off-by: SuZhou-Joe * fix: typo Signed-off-by: SuZhou-Joe * Revert "fix: hang test cases" This reverts commit b7caeb72c59fd577154870cadea0652bbcf6d3b1. Signed-off-by: SuZhou-Joe * fix: enable dev-shm to address hang test Signed-off-by: SuZhou-Joe * feat: add wait to fix hang Signed-off-by: SuZhou-Joe * feat: revert image version back to 2.308.0-1 Signed-off-by: SuZhou-Joe * feat: downgrade chrome version to v115 Signed-off-by: SuZhou-Joe * feat: revert chromuim downgrade logic Signed-off-by: SuZhou-Joe --------- Signed-off-by: SuZhou-Joe --- .github/workflows/cypress-workflow-vanilla-snapshot-based.yml | 2 ++ .github/workflows/lint_checker.yml | 2 ++ .github/workflows/release-e2e-workflow-template-windows.yml | 2 ++ .github/workflows/release-e2e-workflow-template.yml | 2 ++ .github/workflows/release-signoff-chrome.yml | 2 ++ .github/workflows/release-signoff-chromium-ad-only.yml | 2 ++ .github/workflows/release-signoff-chromium-ism-only.yml | 2 ++ .../workflows/release-signoff-chromium-tests-in-memory-0.yml | 2 ++ .../workflows/release-signoff-chromium-tests-in-memory-10.yml | 2 ++ .../workflows/release-signoff-chromium-tests-in-memory-20.yml | 2 ++ .../workflows/release-signoff-chromium-tests-in-memory-5.yml | 2 ++ .github/workflows/release-signoff-chromium.yml | 2 ++ .github/workflows/release-signoff-electron.yml | 2 ++ .github/workflows/release-signoff-firefox.yml | 2 ++ 14 files changed, 28 insertions(+) diff --git a/.github/workflows/cypress-workflow-vanilla-snapshot-based.yml b/.github/workflows/cypress-workflow-vanilla-snapshot-based.yml index d24593e7a..f8d4d1a74 100644 --- a/.github/workflows/cypress-workflow-vanilla-snapshot-based.yml +++ b/.github/workflows/cypress-workflow-vanilla-snapshot-based.yml @@ -17,6 +17,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Set up JDK uses: actions/setup-java@v1 diff --git a/.github/workflows/lint_checker.yml b/.github/workflows/lint_checker.yml index 64a19ea38..c963d7a11 100644 --- a/.github/workflows/lint_checker.yml +++ b/.github/workflows/lint_checker.yml @@ -14,6 +14,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Checkout cypress-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-e2e-workflow-template-windows.yml b/.github/workflows/release-e2e-workflow-template-windows.yml index e7ff7a6ae..3f8553a84 100644 --- a/.github/workflows/release-e2e-workflow-template-windows.yml +++ b/.github/workflows/release-e2e-workflow-template-windows.yml @@ -20,6 +20,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Set up JDK uses: actions/setup-java@v1 diff --git a/.github/workflows/release-e2e-workflow-template.yml b/.github/workflows/release-e2e-workflow-template.yml index 33ad16985..20fe3fa4d 100644 --- a/.github/workflows/release-e2e-workflow-template.yml +++ b/.github/workflows/release-e2e-workflow-template.yml @@ -23,6 +23,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Set up JDK uses: actions/setup-java@v1 diff --git a/.github/workflows/release-signoff-chrome.yml b/.github/workflows/release-signoff-chrome.yml index dec0b5fd0..9dc47ddb4 100644 --- a/.github/workflows/release-signoff-chrome.yml +++ b/.github/workflows/release-signoff-chrome.yml @@ -11,6 +11,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium-ad-only.yml b/.github/workflows/release-signoff-chromium-ad-only.yml index 14b9c8551..96cf1bc8e 100644 --- a/.github/workflows/release-signoff-chromium-ad-only.yml +++ b/.github/workflows/release-signoff-chromium-ad-only.yml @@ -11,6 +11,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium-ism-only.yml b/.github/workflows/release-signoff-chromium-ism-only.yml index c920f7f01..08aa34055 100644 --- a/.github/workflows/release-signoff-chromium-ism-only.yml +++ b/.github/workflows/release-signoff-chromium-ism-only.yml @@ -11,6 +11,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml index 8c9a7e416..8e4604747 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml @@ -11,6 +11,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml index 17e82077f..599054bb4 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml @@ -11,6 +11,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml index fbc92bbe8..3a32342cf 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml @@ -11,6 +11,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml index b49d4e4f7..8b2b6faf7 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml @@ -11,6 +11,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium.yml b/.github/workflows/release-signoff-chromium.yml index 6059c7f54..15015ef74 100644 --- a/.github/workflows/release-signoff-chromium.yml +++ b/.github/workflows/release-signoff-chromium.yml @@ -11,6 +11,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-electron.yml b/.github/workflows/release-signoff-electron.yml index 8d874748e..140c69b52 100644 --- a/.github/workflows/release-signoff-electron.yml +++ b/.github/workflows/release-signoff-electron.yml @@ -11,6 +11,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-firefox.yml b/.github/workflows/release-signoff-firefox.yml index a1e6b4a68..0f99fa5ed 100644 --- a/.github/workflows/release-signoff-firefox.yml +++ b/.github/workflows/release-signoff-firefox.yml @@ -11,6 +11,8 @@ jobs: CI: 1 # avoid warnings like "tput: No value for $TERM and no -T specified" TERM: xterm + # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment + NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' steps: - name: Checkout functional-test uses: actions/checkout@v2 From a6e67f96d75fa76a74a4912c9cbc28544f952562 Mon Sep 17 00:00:00 2001 From: leanneeliatra <131779422+leanneeliatra@users.noreply.github.com> Date: Wed, 29 Nov 2023 09:38:17 +0000 Subject: [PATCH 03/21] Integration tests for broken safari link (#940) * copy link lint fix Signed-off-by: leanne.laceybyrne@eliatra.com * testing visit to copyed link works Signed-off-by: leanne.laceybyrne@eliatra.com * copy from clipboard and visit copied link Signed-off-by: leanne.laceybyrne@eliatra.com * Update copy_link.js Signed-off-by: leanneeliatra <131779422+leanneeliatra@users.noreply.github.com> * renamed copy_link and moved file location Signed-off-by: leanne.laceybyrne@eliatra.com --------- Signed-off-by: leanne.laceybyrne@eliatra.com Signed-off-by: leanneeliatra <131779422+leanneeliatra@users.noreply.github.com> --- .../dashboard_share_copy_link_test.js | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 cypress/integration/core-opensearch-dashboards/opensearch-dashboards/dashboard_share_copy_link_test.js diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/dashboard_share_copy_link_test.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/dashboard_share_copy_link_test.js new file mode 100644 index 000000000..b955145c5 --- /dev/null +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/dashboard_share_copy_link_test.js @@ -0,0 +1,40 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +import { STACK_MANAGEMENT_PATH } from '../../../utils/dashboards/constants'; + +if (Cypress.env('SECURITY_ENABLED')) { + describe('Copy Link functionality working', () => { + it('Tests the link copys and can be routed to in Safari', () => { + cy.visit(STACK_MANAGEMENT_PATH); + cy.waitForLoader(); + cy.getElementByTestId('toggleNavButton').click(); + cy.get('span[title="Discover"]').click(); + cy.getElementByTestId('shareTopNavButton').click(); + cy.getElementByTestId('copyShareUrlButton').click(); + + // Capture the copied content + cy.window().then((win) => { + // Access the clipboard contents + cy.document().then(() => { + cy.wait(1000); // Wait for clipboard data to be available + cy.log('Trying to read clipboard data...'); + + // Read the clipboard text + cy.wrap(win.navigator.clipboard.readText()).then((clipboardData) => { + cy.log('url copied:', clipboardData); + + // Assert that the clipboard has data + expect(clipboardData).to.have.length.greaterThan(0); + + cy.visit(clipboardData); + cy.waitForLoader(); + + // Now on copied URL page + }); + }); + }); + }); + }); +} From 652537e1833c1ab639c73a214cfc17a8efad69d3 Mon Sep 17 00:00:00 2001 From: "Qingyang(Abby) Hu" Date: Tue, 5 Dec 2023 19:23:26 -0800 Subject: [PATCH 04/21] skip flaky tests (#966) Signed-off-by: Qingyang(Abby) Hu --- .../apps/data_explorer/discover.spec.js | 6 ++++-- .../apps/data_explorer/doc_navigation.spec.js | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover.spec.js index f7d28e7c6..f4c766d2b 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover.spec.js @@ -146,7 +146,8 @@ describe('discover app', { scrollBehavior: false }, () => { } ); - describe('nested query', () => { + // https://github.com/opensearch-project/OpenSearch-Dashboards/issues/5495 + describe.skip('nested query', () => { before(() => { cy.setTopNavDate(DE_DEFAULT_START_TIME, DE_DEFAULT_END_TIME); cy.waitForSearch(); @@ -158,7 +159,8 @@ describe('discover app', { scrollBehavior: false }, () => { }); }); - describe('data-shared-item', function () { + // https://github.com/opensearch-project/OpenSearch-Dashboards/issues/5495 + describe.skip('data-shared-item', function () { it('should have correct data-shared-item title and description', () => { const expected = { title: 'A Saved Search', diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_navigation.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_navigation.spec.js index 07c957905..747ac8013 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_navigation.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_navigation.spec.js @@ -89,6 +89,8 @@ describe('doc link in discover', () => { cy.waitForSearch(); + cy.wait(500); + cy.getElementByTestId(`docTableExpandToggleColumn-0`) .should('be.visible') .click(); From 941f2defd6bc133c5796d37e7593f99c345f343c Mon Sep 17 00:00:00 2001 From: Kajetan Nobel Date: Wed, 20 Dec 2023 02:42:26 +0100 Subject: [PATCH 05/21] Read-only tenant mode tests (#792) * feat: introduces read-only tenant mode tests Signed-off-by: Kajetan Nobel * feat: move loadSampleData to before Signed-off-by: Kajetan Nobel * fix: add data to correct tenant, fix for version 2.9.0 Signed-off-by: Kajetan Nobel * feat: retest and improve switching tenant Signed-off-by: Kajetan Nobel --------- Signed-off-by: Kajetan Nobel Signed-off-by: Kajetan Nobel --- .../security-dashboards-plugin/readonly.js | 95 +++++++++++++++++++ .../switch_tenant.js | 23 ++++- cypress/utils/commands.js | 9 ++ 3 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 cypress/integration/plugins/security-dashboards-plugin/readonly.js diff --git a/cypress/integration/plugins/security-dashboards-plugin/readonly.js b/cypress/integration/plugins/security-dashboards-plugin/readonly.js new file mode 100644 index 000000000..6f7f8730d --- /dev/null +++ b/cypress/integration/plugins/security-dashboards-plugin/readonly.js @@ -0,0 +1,95 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import roleWithoutTestJson from '../../../fixtures/plugins/security-dashboards-plugin/roles/roleWithoutTest'; +import { BASE_PATH } from '../../../utils/base_constants'; +import { ADMIN_AUTH, CURRENT_TENANT } from '../../../utils/commands'; +import { switchTenantTo } from './switch_tenant'; + +const TEST_CONFIG = { + role: { + name: 'test_readonly_role', + json: Object.assign({}, roleWithoutTestJson, { + tenant_permissions: [ + { + tenant_patterns: ['test_readonly_tenant'], + allowed_actions: ['kibana_all_read'], + }, + ], + }), + }, + tenant: { + name: 'test_readonly_tenant', + description: 'Testing read-only tenant mode', + }, + user: { + username: 'test_readonly_user', + password: 'testUserPassword123', + }, +}; + +if (Cypress.env('SECURITY_ENABLED')) { + describe('Read Only mode', () => { + before(() => { + cy.server(); + + cy.createTenant(TEST_CONFIG.tenant.name, { + description: TEST_CONFIG.tenant.description, + }); + + cy.createInternalUser(TEST_CONFIG.user.username, { + password: TEST_CONFIG.user.password, + }); + + cy.createRole(TEST_CONFIG.role.name, TEST_CONFIG.role.json); + + cy.createRoleMapping(TEST_CONFIG.role.name, { + users: [ADMIN_AUTH.username, TEST_CONFIG.user.username], + }); + + /* Add sample data to testing tenant */ + CURRENT_TENANT.newTenant = TEST_CONFIG.tenant.name; + cy.visit(BASE_PATH, { + onBeforeLoad(window) { + window.sessionStorage.setItem( + 'opendistro::security::tenant::show_popup', + false + ); + window.localStorage.setItem( + 'opendistro::security::tenant::saved', + `"${TEST_CONFIG.tenant.name}"` + ); + window.localStorage.setItem('home:newThemeModal:show', false); + }, + }); + cy.waitForLoader(); + switchTenantTo(TEST_CONFIG.tenant.name); + cy.loadSampleData('logs'); + }); + + it('should be able to modify the dashboard as admin', () => { + cy.visit(BASE_PATH); + cy.waitForLoader(); + + cy.visitDashboard('[Logs] Web Traffic'); + + cy.getElementByTestId('dashboardClone').should('exist'); + cy.getElementByTestId('dashboardEditMode').should('exist'); + }); + + it('should not be able to modify the dashboard when is performing as a custom readonly tenant', () => { + ADMIN_AUTH.newUser = TEST_CONFIG.user.username; + ADMIN_AUTH.newPassword = TEST_CONFIG.user.password; + + cy.visit(BASE_PATH); + cy.waitForLoader(); + + cy.visitDashboard('[Logs] Web Traffic'); + + cy.getElementByTestId('dashboardClone').should('not.exist'); + cy.getElementByTestId('dashboardEditMode').should('not.exist'); + }); + }); +} diff --git a/cypress/integration/plugins/security-dashboards-plugin/switch_tenant.js b/cypress/integration/plugins/security-dashboards-plugin/switch_tenant.js index 5666eca8f..8deda4a28 100644 --- a/cypress/integration/plugins/security-dashboards-plugin/switch_tenant.js +++ b/cypress/integration/plugins/security-dashboards-plugin/switch_tenant.js @@ -16,11 +16,24 @@ export function switchTenantTo(newTenant) { }).as('waitForAccountInfo'); cy.getElementByTestId('switch-tenants').click(); - //should ensures the dialog window is fully loaded and the radios can be selected. - cy.get('[id="' + newTenant + '"][name="tenantSwitchRadios"]').should( - 'be.enabled' - ); - cy.get('.euiRadio__label[for="' + newTenant + '"]').click(); + + if (['global', 'private'].includes(newTenant)) { + cy.get('[id="' + newTenant + '"][name="tenantSwitchRadios"]').should( + 'be.enabled' + ); + cy.get('.euiRadio__label[for="' + newTenant + '"]').click(); + } else { + cy.get('[id="custom"][name="tenantSwitchRadios"]').should('be.enabled'); + + cy.getElementByTestId('tenant-switch-modal') + .find('[data-test-subj="comboBoxInput"]') + .click(); + + // typo in data-test-subj + cy.getElementByTestId('comboBoxOptionsList ') + .find(`[title="${newTenant}"]`) + .click(); + } cy.intercept({ method: 'POST', diff --git a/cypress/utils/commands.js b/cypress/utils/commands.js index a5a127e9b..016826415 100644 --- a/cypress/utils/commands.js +++ b/cypress/utils/commands.js @@ -516,3 +516,12 @@ Cypress.Commands.add( }); } ); + +// type: logs, ecommerce, flights +Cypress.Commands.add('loadSampleData', (type) => { + cy.request({ + method: 'POST', + headers: { 'osd-xsrf': 'opensearch-dashboards' }, + url: `${BASE_PATH}/api/sample_data/${type}`, + }); +}); From 76270ea9217b387dd64ab05754bcaf13d6a05985 Mon Sep 17 00:00:00 2001 From: Manasvini B Suryanarayana Date: Wed, 20 Dec 2023 18:46:18 -0800 Subject: [PATCH 06/21] Add test orchestrator script to trigger remote workflow runner outside functional test repo for cypress tests (#971) Issue details - https://github.com/opensearch-project/OpenSearch-Dashboards/issues/5392 Signed-off-by: manasvinibs --- .github/workflows/remote-cypress-workflow.yml | 36 ++++++ poll_remote_workflow.sh | 103 ++++++++++++++++ remoteCypress.sh | 113 ++++++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 .github/workflows/remote-cypress-workflow.yml create mode 100644 poll_remote_workflow.sh create mode 100755 remoteCypress.sh diff --git a/.github/workflows/remote-cypress-workflow.yml b/.github/workflows/remote-cypress-workflow.yml new file mode 100644 index 000000000..9e75fdef9 --- /dev/null +++ b/.github/workflows/remote-cypress-workflow.yml @@ -0,0 +1,36 @@ +name: Trigger Remote Cypress Workflow + +on: + workflow_dispatch: + inputs: + repo: + description: 'Name of the repository in {owner}/{repository} format' + required: true + workflow_name: + description: 'Name of the Github workflow yml file in the component repository' + required: true + os_url: + description: 'Release artifact of OpenSearch' + required: true + osd_url: + description: 'Release artifact of OpenSearch Dashboards' + required: true + branch_ref: + description: 'Test branch name or commit reference id' + required: true + +jobs: + trigger-cypress: + runs-on: ubuntu-latest + name: Remote Cypress Tests + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Run Bash Script + env: + GITHUB_SECRET_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ./remoteCypress.sh -r "${{ github.event.inputs.repo }}" -w "${{ github.event.inputs.workflow_name }}" -o "${{ github.event.inputs.os_url }}" -d "${{ github.event.inputs.osd_url }}" -b "${{ github.event.inputs.branch_ref }}" + diff --git a/poll_remote_workflow.sh b/poll_remote_workflow.sh new file mode 100644 index 000000000..e3d575d23 --- /dev/null +++ b/poll_remote_workflow.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +# Accessing the secret as an environment variable using GitHub actions while invoking this script +GITHUB_TOKEN=$GITHUB_SECRET_TOKEN +REPO="$1" +UNIQUE_WORKFLOW_ID="$2" +API_URL="$3" + +# Function to check the status of the remote github workflow by constantly polling the workflow-run +check_remote_workflow_status() { + local run_id + local status + local conclusion + local run_details + local workflow_runs + local matching_workflow + local polling_run_id_retries=1 + local polling_workflow_completion_retries=1 + local max_polling_run_id_retries=5 # Keep polling for the first 5 minutes to fetch the workflow run id till the workflow gets generated + local max_polling_workflow_completion_retries=12 # Set the polling window period to be 1 hour + + # Check if a matching workflow object was found + while [ -z "$matching_workflow" ] && [ $polling_run_id_retries -le $max_polling_run_id_retries ]; do + echo "Querying for the workflow run id..." + sleep 60 # Wait for 1 minute before polling for the workflow run_id till it gets created + + # Make a GET request to the GitHub API to get the list of workflow runs + workflow_runs=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "$API_URL/runs") + + # Extract the JSON object whose "name" field contains the string with a unique id of the workflow + matching_workflow=$(echo "$workflow_runs" | jq --arg unique_id "$UNIQUE_WORKFLOW_ID" '.workflow_runs[] | select(.name | contains($unique_id))') + ((polling_run_id_retries++)) + + done + echo "matching_workflow: $matching_workflow" + + if [ -n "$matching_workflow" ]; then + # Extract the "jobs_url" and "run_id" values from the matching object + jobs_url=$(echo "$matching_workflow" | jq -r '.jobs_url') + run_id=$(echo "$matching_workflow" | jq -r '.id') + echo "Jobs URL: $jobs_url" + echo "Run Id: $run_id" + + # Poll the status until the workflow is completed + while [ $polling_workflow_completion_retries -le $max_polling_workflow_completion_retries ]; do + echo "Checking the workflow run API status, attempt: $polling_workflow_completion_retries" + + run_details=$(curl -L -H "Authorization: Bearer $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/$REPO/actions/runs/$run_id") + echo "Workflow run details: $run_details" + + # Extract status and conclusion from the run details + status=$(echo "$run_details" | jq -r ".status") + conclusion=$(echo "$run_details" | jq -r ".conclusion") + + # Check if the status indicates that the workflow is complete + if [[ "$status" == "completed" ]]; then + echo "Workflow completed with status: $status" + + # Check if it was successful + if [[ $conclusion == "success" ]]; then + echo "Remote workflow completed successfully." + return 0 # Success + elif [[ $conclusion == "failure" ]]; then + echo "Remote workflow completed with errors. Conclusion: $conclusion" + + job_details=$(curl -L -H "Authorization: Bearer $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "$jobs_url") + + # Parse the workflow to find any failures in the test + failures=$(echo "$run_details" | jq -r '.jobs[] | select(.conclusion == "failure") | .name') + echo "Test failures: $failures" + + return 1 # Failure + else + echo "Remote workflow completed with unexpected conclusion. Conclusion: $conclusion" + return 1 # Failure + fi + else + echo "Remote workflow is still running. Waiting..." + sleep 300 # Wait for 5 minutes before checking again + ((polling_workflow_completion_retries++)) + fi + done + else + echo "No matching workflow run object found even after retries. Exiting..." + return 1 # Failure + fi + + echo "Remote workflow didn't complete within the specified time." + return 1 # Failure +} + +check_remote_workflow_status + +exit 0 \ No newline at end of file diff --git a/remoteCypress.sh b/remoteCypress.sh new file mode 100755 index 000000000..a2de652af --- /dev/null +++ b/remoteCypress.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +set -e + +function usage() { + echo "" + echo "This script triggers GitHub workflow runners within the component repository which runs Cypress integration tests on a remote OpenSearch/Dashboards cluster." + echo "--------------------------------------------------------------------------" + echo "Usage: $0 [args]" + echo "Required arguments:" + echo -e "-r REPO\t, Name of the repository in {owner}/{repository} format" + echo -e "-w GITHUB_WORKFLOW_NAME\t, Name of the GitHub workflow file name with .yml extension that contain jobs that run Cypress tests in the component repository. For example, main.yaml" + echo -e "-o OS_URL\t, Release artifact of the OpenSearch" + echo -e "-d OSD_URL\t, Release artifact of the OpenSearch Dashboards" + echo -e "-b BRANCH_REF\t Test Branch name or commit reference id" + echo -e "-i BUILD_ID\t Release-specific build id for reference" + echo "--------------------------------------------------------------------------" +} + +# Parse command-line arguments +while getopts ":h:r:w:o:d:b:i:" opt; do + case $opt in + h) + usage + exit 1 + ;; + r) + REPO="$OPTARG" + ;; + w) + WORKFLOW_NAME="$OPTARG" + ;; + o) + OS_URL="$OPTARG" + ;; + d) + OSD_URL="$OPTARG" + ;; + b) + BRANCH_REF="$OPTARG" + ;; + i) + BUILD_ID="$OPTARG" + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +# Check if required arguments are provided +if [[ -z "$REPO" || -z "$WORKFLOW_NAME" || -z "$OS_URL" || -z "$OSD_URL" || -z "$BRANCH_REF" ]]; then + echo "Error: Missing required arguments. See usage below." + usage + exit 1 +fi + +# Accessing the secret as an environment variable using Github actions while invoking this script +GITHUB_TOKEN=$GITHUB_SECRET_TOKEN +# This is to uniquely identify each execution workflow. This ID has to be appended to the workflow_run +# name in the component repository yaml file for polling purpose. +UNIQUE_WORKFLOW_ID=$(uuidgen) +echo "Unique Execution ID: $UNIQUE_WORKFLOW_ID" +# For now we are using Github action API to trigger github workflows in plugins component +# ToDo: We can explore other test runners such as Jenkins to integrate with. +API_URL="https://api.github.com/repos/$REPO/actions/workflows/$WORKFLOW_NAME" +PAYLOAD="{\"ref\": \"$BRANCH_REF\",\"inputs\":{\"build_id\":\"$BUILD_ID\", \"OS_URL\":\"$OS_URL\", \"OSD_URL\":\"$OSD_URL\", \"UNIQUE_ID\":\"$UNIQUE_WORKFLOW_ID\"}}" + +# Maximum number of retries for triggering the remote runner +MAX_RETRIES=3 + +# Trigger the remote GitHub workflow using curl and the PAT token +trigger_remote_workflow() { + curl -L -X POST -H "Authorization: Bearer $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + -w "%{http_code}" \ + "$API_URL/dispatches" -d "$PAYLOAD" +} + +echo "Triggering the remote GitHub workflow for Cypress tests in the repository: $REPO" + +# Attempt to trigger the remote workflow with retries +for ((i = 1; i <= MAX_RETRIES; i++)); do + echo "Attempting to trigger the remote workflow (Attempt $i)" + status_code=$(trigger_remote_workflow) + echo "status_code: $status_code" + + if [[ $status_code -ge 200 && $status_code -lt 300 ]]; then + echo "Remote workflow triggered successfully." + break + else + echo "Failed to trigger the remote workflow. Retrying..." + sleep 10 # Adds a delay between retries + fi + + if [ $i -eq $MAX_RETRIES ]; then + echo "Maximum number of retries reached. Exiting." + exit 1 + fi +done + + +# Check the status of the remote workflow +source ./poll_remote_workflow.sh "$REPO" "$UNIQUE_WORKFLOW_ID" "$API_URL" +echo "Return code: $?" + +exit 0 From 0a9f5264bfd4b01c1aec7582dd3a0e8c23e3d531 Mon Sep 17 00:00:00 2001 From: Amardeepsingh Siglani Date: Wed, 20 Dec 2023 20:47:12 -0800 Subject: [PATCH 07/21] added wait before selecting Cluster Health API (#977) Signed-off-by: Amardeepsingh Siglani --- .../alerting-dashboards-plugin/cluster_metrics_monitor_spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cypress/integration/plugins/alerting-dashboards-plugin/cluster_metrics_monitor_spec.js b/cypress/integration/plugins/alerting-dashboards-plugin/cluster_metrics_monitor_spec.js index 9d6c165ec..7bf18d9ce 100644 --- a/cypress/integration/plugins/alerting-dashboards-plugin/cluster_metrics_monitor_spec.js +++ b/cypress/integration/plugins/alerting-dashboards-plugin/cluster_metrics_monitor_spec.js @@ -116,6 +116,7 @@ describe('ClusterMetricsMonitor', () => { cy.get('input[name="name"]').type(SAMPLE_CLUSTER_METRICS_HEALTH_MONITOR); // Wait for the API types to load and then type in the Cluster Health API + cy.wait(5000); cy.get('[data-test-subj="clusterMetricsApiTypeComboBox"]').type( 'cluster health{enter}' ); From 1fa3e2be617203290b56174e4d448a0e2db1c7e2 Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Wed, 27 Dec 2023 11:37:49 +0800 Subject: [PATCH 08/21] feat: remove useless vanilla test (#975) * feat: skip flaky test Signed-off-by: SuZhou-Joe * feat: remove useless test case Signed-off-by: SuZhou-Joe * feat: remove useless reference Signed-off-by: SuZhou-Joe --------- Signed-off-by: SuZhou-Joe --- ...ypress-workflow-vanilla-snapshot-based.yml | 95 ---- DEVELOPER_GUIDE.md | 2 +- .../dashboard_filtering_spec.js | 421 ------------------ 3 files changed, 1 insertion(+), 517 deletions(-) delete mode 100644 .github/workflows/cypress-workflow-vanilla-snapshot-based.yml delete mode 100644 cypress/integration/core-opensearch-dashboards/vanilla-opensearch-dashboards/dashboard_filtering_spec.js diff --git a/.github/workflows/cypress-workflow-vanilla-snapshot-based.yml b/.github/workflows/cypress-workflow-vanilla-snapshot-based.yml deleted file mode 100644 index f8d4d1a74..000000000 --- a/.github/workflows/cypress-workflow-vanilla-snapshot-based.yml +++ /dev/null @@ -1,95 +0,0 @@ -name: Snapshot based E2E Cypress tests workflow -on: - pull_request: - branches: - - main - - dev-* - push: - branches: - - main - - dev-* -jobs: - tests: - name: Run Cypress E2E tests - runs-on: ubuntu-latest - env: - # prevents extra Cypress installation progress messages - CI: 1 - # avoid warnings like "tput: No value for $TERM and no -T specified" - TERM: xterm - # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment - NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' - steps: - - name: Set up JDK - uses: actions/setup-java@v1 - with: - java-version: 14 - - name: Checkout monetery-test - uses: actions/checkout@v2 - with: - repository: ${{github.repository}} - path: monetery-test - # TODO: Qualifier not supported yet for OSD snapshot - # - name: Get package version - # working-directory: monetery-test - # run: | - # echo "VERSION=$(yarn --silent pkg-version)" >> $GITHUB_ENV - - name: Get package version - working-directory: monetery-test - run: | - echo "VERSION=$(yarn --silent pkg-version)" >> $GITHUB_ENV - - name: Get and run OpenSearch - run: | - wget https://ci.opensearch.org/ci/dbc/distribution-build-opensearch/${{ env.VERSION }}/latest/linux/x64/tar/builds/opensearch/dist/opensearch-min-${{ env.VERSION }}-linux-x64.tar.gz - tar -xzf opensearch-min-${{ env.VERSION }}-linux-x64.tar.gz - cd opensearch-${{ env.VERSION }}/ - bin/opensearch & - timeout 300 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:9200)" != "200" ]]; do sleep 5; done' - - name: Get OpenSearch-Dashboards - run: | - wget https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/${{ env.VERSION }}/latest/linux/x64/tar/builds/opensearch-dashboards/dist/opensearch-dashboards-min-${{ env.VERSION }}-linux-x64.tar.gz - tar -xzf opensearch-dashboards-min-${{ env.VERSION }}-linux-x64.tar.gz - - name: Run OpenSearch-Dashboards server - run: | - cd opensearch-dashboards-${{ env.VERSION }}-linux-x64 - bin/opensearch-dashboards serve & - timeout 300 bash -c 'while [[ "$(curl -s localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' - - name: Get Cypress version - id: cypress_version - run: | - cypress_version_temp=$(cat ./monetery-test/package.json | jq -r '.devDependencies.cypress') - echo "cypress_version=$cypress_version_temp" >> $GITHUB_ENV - - name: Cache Cypress - id: cache-cypress - uses: actions/cache@v1 - with: - path: ~/.cache/Cypress - key: cypress-cache-v2-${{ runner.os }}-${{ hashFiles('**/package.json') }} - env: - CYPRESS_INSTALL_BINARY: ${{ steps.cypress_version.outputs.cypress_version }} - - run: npx cypress cache list - - run: npx cypress cache path - - name: Cypress tests - uses: cypress-io/github-action@v2 - with: - working-directory: monetery-test - command: yarn cypress:run-without-security --browser chromium --spec 'cypress/integration/core-opensearch-dashboards/vanilla-opensearch-dashboards/*.js' - wait-on: 'http://localhost:5601' - # Screenshots are only captured on failure, will change this once we do visual regression tests - - uses: actions/upload-artifact@v1 - if: failure() - with: - name: cypress-screenshots - path: monetery-test/cypress/screenshots - # Test run video was always captured, so this action uses "always()" condition - - uses: actions/upload-artifact@v1 - if: always() - with: - name: cypress-videos - path: monetery-test/cypress/videos - # Test reports was always captured, so this action uses "always()" condition - - uses: actions/upload-artifact@v1 - if: always() - with: - name: cypress-results - path: monetery-test/cypress/results diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index 5bc2c3d17..61b451ef7 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -76,7 +76,7 @@ To run tests against a local cluster without security: ``` -$ yarn cypress:run-without-security --spec "cypress/integration/core-opensearch-dashboards/vanilla-opensearch-dashboards/*.js" +$ yarn cypress:run-without-security --spec "cypress/integration/core-opensearch-dashboards/opensearch-dashboards/*.js" ``` with security: diff --git a/cypress/integration/core-opensearch-dashboards/vanilla-opensearch-dashboards/dashboard_filtering_spec.js b/cypress/integration/core-opensearch-dashboards/vanilla-opensearch-dashboards/dashboard_filtering_spec.js deleted file mode 100644 index 5df26fcf1..000000000 --- a/cypress/integration/core-opensearch-dashboards/vanilla-opensearch-dashboards/dashboard_filtering_spec.js +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - TestFixtureHandler, - CommonUI, - DashboardPage, - MiscUtils, -} from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; - -/** - * dashboard_filtering test suite description: - * 1) Create a new dashboard, and populate it with visualizations - * 2) Set a filter that excludes all data, and check the visualizations for proper updates - * 3) Set the existing filter to be pinned, re-check the visualizations - * 4) Remove the filter, and check the visualizations for proper updates - * 5) Create a new dashboard, and populate it with a pie graph - * 6) Apply different filters to the pie graph and check the pie graph for proper updates - * 7) Remove all filters and ensure that the pie graph reverts to its original format - * 8) Test adding another pie graph to the dashboard and applying a filter to both graphs - */ - -const testFixtureHandler = new TestFixtureHandler( - cy, - Cypress.env('openSearchUrl') -); -const commonUI = new CommonUI(cy); -const dashboardPage = new DashboardPage(cy); -const miscUtils = new MiscUtils(cy); -describe('dashboard filtering', () => { - before(() => { - testFixtureHandler.clearJSONMapping( - 'cypress/fixtures/dashboard/data/mappings.json.txt' - ); - - testFixtureHandler.importJSONMapping( - 'cypress/fixtures/dashboard/opensearch_dashboards/mappings.json.txt' - ); - testFixtureHandler.importJSONMapping( - 'cypress/fixtures/dashboard/data/mappings.json.txt' - ); - - testFixtureHandler.importJSONDoc( - 'cypress/fixtures/dashboard/opensearch_dashboards/data.json.txt' - ); - testFixtureHandler.importJSONDoc( - 'cypress/fixtures/dashboard/data/data.json.txt' - ); - }); - - after(() => { - testFixtureHandler.clearJSONMapping( - 'cypress/fixtures/dashboard/data/mappings.json.txt' - ); - }); - - // The commands that run in "before" and "beforeEach" hooks take place - // during the first test in the test suite associated with them. - // Since importing the test environment stores large amounts of information in local memory, - // the test that the "before" hook above runs in tends to run significantly slower. - // This buffer test below helps prevent unnecessary slowdown during testing - it('Buffer test for importing test environment data', () => {}); - - describe('Adding and removing filters from a dashboard', () => { - before(() => { - // Go to the Dashboards list page - miscUtils.visitPage('app/dashboards/list'); - - // Click the "Create dashboard" button - miscUtils.createNewDashboard(); - // Change the time to be between Jan 1 2018 and Apr 13, 2018 - cy.setTopNavDate( - 'Jan 1, 2018 @ 00:00:00.000', - 'Apr 13, 2018 @ 00:00:00.000' - ); - - // Add all "Filter Bytes Test" visualizations - dashboardPage.addDashboardPanels( - 'Filter Bytes Test', - 'visualization', - true - ); - - // Click the "Add" button and add all "Saved Searches" - dashboardPage.addDashboardPanels('Filter Bytes Test', 'search', false); - }); - - describe('adding a filter that excludes all data', () => { - before(() => { - // Clear add filters to properly clean the environment for the test - commonUI.removeAllFilters(); - - // Add filter - commonUI.addFilterRetrySelection('bytes', 'is', '12345678'); - }); - - it('Nonpinned filter: filters on pie charts', () => { - // Check that none of the pie charts are occupied with data (show "No results found") - commonUI.checkElementDoesNotExist('svg > g > g.arcs > path.slice'); - }); - - it('Nonpinned filter: area, bar and heatmap charts filtered', () => { - // Check that none of the charts are filled with data - commonUI.checkElementDoesNotExist('svg > g > g.series'); - }); - - it('Nonpinned filter: data tables are filtered', () => { - // Check that none of the data tables are filled with data - commonUI.checkElementDoesNotExist('[data-test-subj="dataGridRowCell"]'); - }); - - it('Nonpinned filter: goal and guages are filtered', () => { - // Goal label should be 0, gauge label should be 0% - commonUI.checkValuesExistInComponent('svg > g > g > text.chart-label', [ - '0', - '0%', - ]); - }); - - it('Nonpinned filter: tsvb time series shows no data message', () => { - // The no data message should be visible - commonUI.checkElementExists('[data-test-subj="noTSVBDataMessage"]', 1); - }); - - it('Nonpinned filter: metric value shows no data', () => { - // The metrics should show '-' - commonUI.checkValuesExistInComponent('.mtrVis__value', [' - ']); - }); - - it('Nonpinned filter: tag cloud values are filtered', () => { - commonUI.checkElementComponentDoesNotExist( - '[data-test-subj="tagCloudVisualization"]', - 'svg > g > text' - ); - }); - - it('Nonpinned filter: tsvb metric is filtered', () => { - commonUI.checkValuesExistInComponent( - '[data-test-subj="tsvbMetricValue"]', - ['0 custom template'] - ); - }); - - it('Nonpinned filter: tsvb top n is filtered', () => { - commonUI.checkElementContainsValue( - '[data-test-subj="tsvbTopNValue"]', - 2, - '0' - ); - }); - - it('Nonpinned filter: saved search is filtered', () => { - commonUI.checkElementDoesNotExist( - '[data-test-subj="docTableExpandToggleColumn"]' - ); - }); - - it('Nonpinned filter: vega is filtered', () => { - commonUI.checkValuesDoNotExistInComponent('.vgaVis__view text', [ - '5,000', - ]); - }); - }); - - describe('using a pinned filter that excludes all data', () => { - before(() => { - // Clear add filters to properly clean environment for the test - commonUI.removeAllFilters(); - - commonUI.addFilterRetrySelection('bytes', 'is', '12345678'); - - commonUI.pinFilter('bytes'); - }); - - it('Pinned filter: filters on pie charts', () => { - // Check that none of the pie charts are occupied with data (show "No results found") - commonUI.checkElementDoesNotExist('svg > g > g.arcs > path.slice'); - }); - - it('Pinned filter: area, bar and heatmap charts filtered', () => { - // Check that none of the charts are filled with data - commonUI.checkElementDoesNotExist('svg > g > g.series'); - }); - - it('Pinned filter: data tables are filtered', () => { - // Check that none of the data tables are filled with data - commonUI.checkElementDoesNotExist('[data-test-subj="dataGridRowCell"]'); - }); - - it('Pinned filter: goal and guages are filtered', () => { - // Goal label should be 0, gauge label should be 0% - commonUI.checkValuesExistInComponent('svg > g > g > text.chart-label', [ - '0', - '0%', - ]); - }); - - it('Pinned filter: metric value shows no data', () => { - // The metrics should show '-' - commonUI.checkValuesExistInComponent('.mtrVis__value', [' - ']); - }); - - it('Pinned filter: tag cloud values are filtered', () => { - commonUI.checkElementComponentDoesNotExist( - '[data-test-subj="tagCloudVisualization"]', - 'svg > g > text' - ); - }); - - it('Pinned filter: tsvb metric is filtered', () => { - commonUI.checkValuesExistInComponent( - '[data-test-subj="tsvbMetricValue"]', - ['0 custom template'] - ); - }); - - it('Pinned filter: tsvb top n is filtered', () => { - commonUI.checkElementContainsValue( - '[data-test-subj="tsvbTopNValue"]', - 2, - '0' - ); - }); - - it('Pinned filter: saved search is filtered', () => { - commonUI.checkElementDoesNotExist( - '[data-test-subj="docTableExpandToggleColumn"]' - ); - }); - - it('Pinned filter: vega is filtered', () => { - commonUI.checkValuesDoNotExistInComponent('.vgaVis__view text', [ - '5,000', - ]); - }); - }); - - describe('disabling a filter unfilters the data on', () => { - before(() => { - // TO DO: create delete filter helper function - // Clear add filters to properly clean environment for the test - commonUI.removeAllFilters(); - - commonUI.addFilterRetrySelection('bytes', 'is', '12345678'); - - commonUI.removeFilter('bytes'); - }); - - it('Filter disabled: pie charts', () => { - // Check that there are 5 slice in the pie charts - commonUI.checkElementExists('svg > g > g.arcs > path.slice', 5); - }); - - it('Filter disabled: area, bar and heatmap charts', () => { - // Check that there are 3 charts - commonUI.checkElementExists('svg > g > g.series', 3); - }); - - it('Filter disabled: data tables', () => { - // Check that there are 20 table cells / 10 rows - commonUI.checkElementExists('[data-test-subj="dataGridRowCell"]', 20); - }); - - it.skip('Filter disabled: goal and guages', () => { - // Goal label should be 7,544, and the gauge label should be 39.958%% - // Inconsistency: original code says that the goal label should have "7,544", - // but sometimes the goal displays "7,565". It may have been related to a - // data loading issue. - commonUI.checkValuesExistInComponent('svg > g > g > text.chart-label', [ - '7,544', - '39.958%', - ]); - }); - - it('Filter disabled: metric value', () => { - // The metrics should show '101' - commonUI.checkValuesExistInComponent('.mtrVis__value', ['101']); - }); - - it('Filter disabled: tag cloud', () => { - commonUI.checkValuesExistInComponent( - '[data-test-subj="tagCloudVisualization"]', - ['9,972', '4,886', '1,944', '9,025'] - ); - }); - - it('Filter disabled: tsvb metric', () => { - commonUI.checkValuesExistInComponent( - '[data-test-subj="tsvbMetricValue"]', - ['50,465 custom template'] - ); - }); - - it('Filter disabled: tsvb top n', () => { - commonUI.checkElementContainsValue( - '[data-test-subj="tsvbTopNValue"]', - 2, - '6,308.125' - ); - }); - - it('Filter disabled: tsvb markdown', () => { - commonUI.checkValuesExistInComponent( - '[data-test-subj="tsvbMarkdown"]', - ['7,209.286'] - ); - }); - - it('Filter disabled: saved search is filtered', () => { - commonUI.checkElementExists( - '[data-test-subj="docTableExpandToggleColumn"]', - 1 - ); - }); - - it('Filter disabled: vega is filtered', () => { - commonUI.checkValuesExistInComponent('.vgaVis__view text', ['5,000']); - }); - }); - }); - // TO DO: continue making helper functions for repeated actions. - // TO DO: better subdivide the nested filtering tests to improve consistency. - // For example, if the test runner stops after renaming the "Rendering Test: animal sounds pie" - // visualization, future runs of the test suite will fail due to being unable to find the visualization - // under the expected name. - - describe('nested filtering', () => { - before(() => { - // Go to the Dashboards list page - miscUtils.visitPage('app/dashboards/list'); - - // Click the "Create dashboard" button - miscUtils.createNewDashboard(20000); - - // Change the time to be between Jan 1 2018 and Apr 13, 2018 - cy.setTopNavDate( - 'Jan 1, 2018 @ 00:00:00.000', - 'Apr 13, 2018 @ 00:00:00.000' - ); - - dashboardPage.addDashboardPanels( - 'Rendering Test: animal sounds pie', - 'visualization', - false - ); - }); - - it('visualization saved with a query filters data', () => { - commonUI.checkElementExists('svg > g > g.arcs > path.slice', 5); - - dashboardPage.openVisualizationContextMenu( - 'Rendering Test: animal sounds pie' - ); - dashboardPage.clickEditVisualization(); - - miscUtils.setQuery('weightLbs:>50'); - commonUI.checkElementExists('svg > g > g.arcs > path.slice', 3); - - dashboardPage.saveDashboardVisualization( - 'Rendering Test: animal sounds pie', - false, - false - ); - - miscUtils.goToDashboardPage(); - commonUI.checkElementExists('svg > g > g.arcs > path.slice', 3); - }); - - it('Nested visualization filter pills filters data as expected', () => { - dashboardPage.openVisualizationContextMenu( - 'Rendering Test: animal sounds pie' - ); - dashboardPage.clickEditVisualization(); - - commonUI.pieChartFilterOnSlice('grr'); - commonUI.checkElementExists('svg > g > g.arcs > path.slice', 1); - - dashboardPage.saveDashboardVisualization( - 'animal sounds pie', - false, - false - ); - - miscUtils.goToDashboardPage(); - commonUI.checkElementExists('svg > g > g.arcs > path.slice', 1); - }); - - it('Removing filter pills and query unfiters data as expected', () => { - dashboardPage.openVisualizationContextMenu('animal sounds pie'); - dashboardPage.clickEditVisualization(); - - miscUtils.removeQuery(); - commonUI.pieChartRemoveFilter('sound.keyword'); - commonUI.checkElementExists('svg > g > g.arcs > path.slice', 5); - - dashboardPage.saveDashboardVisualization( - 'Rendering Test: animal sounds pie', - false, - false - ); - miscUtils.goToDashboardPage(); - - commonUI.checkElementExists('svg > g > g.arcs > path.slice', 5); - }); - it('Pie chart linked to saved search filters data', () => { - dashboardPage.addDashboardPanels( - 'Filter Test: animals: linked to search with filter', - 'visualization', - false - ); - commonUI.checkElementExists('svg > g > g.arcs > path.slice', 7); - }); - - it('Pie chart linked to saved search filters shows no data with conflicting dashboard query', () => { - miscUtils.setQuery('weightLbs<40'); - commonUI.checkElementExists('svg > g > g.arcs > path.slice', 5); - }); - }); -}); From 8391566c473f78499887aae90b45e4800335a38d Mon Sep 17 00:00:00 2001 From: Derek Ho Date: Wed, 10 Jan 2024 12:58:57 -0500 Subject: [PATCH 09/21] Remove instances of hard admin credentials (#981) * Remove instances of hard admin credentials https://github.com/opensearch-project/opensearch-build/pull/4302 Signed-off-by: Derek Ho --- .../release-e2e-workflow-template-windows.yml | 10 ++++++---- .github/workflows/release-e2e-workflow-template.yml | 10 ++++++---- .github/workflows/release-signoff-chrome.yml | 4 +++- .github/workflows/release-signoff-chromium-ad-only.yml | 4 +++- .../workflows/release-signoff-chromium-ism-only.yml | 4 +++- .../release-signoff-chromium-tests-in-memory-0.yml | 4 +++- .../release-signoff-chromium-tests-in-memory-10.yml | 4 +++- .../release-signoff-chromium-tests-in-memory-20.yml | 4 +++- .../release-signoff-chromium-tests-in-memory-5.yml | 4 +++- .github/workflows/release-signoff-chromium.yml | 4 +++- .github/workflows/release-signoff-electron.yml | 4 +++- .github/workflows/release-signoff-firefox.yml | 4 +++- cypress.json | 2 +- integtest.sh | 10 ++++++---- 14 files changed, 49 insertions(+), 23 deletions(-) mode change 100755 => 100644 integtest.sh diff --git a/.github/workflows/release-e2e-workflow-template-windows.yml b/.github/workflows/release-e2e-workflow-template-windows.yml index 3f8553a84..f5b9a8873 100644 --- a/.github/workflows/release-e2e-workflow-template-windows.yml +++ b/.github/workflows/release-e2e-workflow-template-windows.yml @@ -22,6 +22,8 @@ jobs: TERM: xterm # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' + # 2.12 onwards security demo configuration require a custom admin password + OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' steps: - name: Set up JDK uses: actions/setup-java@v1 @@ -62,8 +64,8 @@ jobs: else echo "Keep OpenSearch Security" nohup ./opensearch-windows-install.bat & - timeout 900 bash -c 'while [[ "$(curl -o /dev/null -w ''%{http_code}'' -u admin:admin -k https://localhost:9200)" != "200" ]]; do echo sleeping 5; sleep 5; done' - curl -sk https://localhost:9200/_cluster/health?pretty -u admin:admin + timeout 900 bash -c 'while [[ "$(curl -o /dev/null -w ''%{http_code}'' -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k https://localhost:9200)" != "200" ]]; do echo sleeping 5; sleep 5; done' + curl -sk https://localhost:9200/_cluster/health?pretty -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} fi netstat -anP tcp | grep LISTEN | grep 9200 || netstat -ntlp | grep 9200 shell: bash @@ -104,8 +106,8 @@ jobs: else echo "Keep Dashboards Security" bin/opensearch-dashboards.bat & - timeout 300 bash -c 'while [[ "$(curl -k http://localhost:5601/api/status -u admin:admin | jq -r '.status.overall.state')" != "green" ]]; do echo sleeping 5; sleep 5; done' - curl -sk localhost:5601/api/status -u admin:admin | jq + timeout 300 bash -c 'while [[ "$(curl -k http://localhost:5601/api/status -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} | jq -r '.status.overall.state')" != "green" ]]; do echo sleeping 5; sleep 5; done' + curl -sk localhost:5601/api/status -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} | jq fi netstat -anP tcp | grep LISTEN | grep 5601 || netstat -ntlp | grep 5601 shell: bash diff --git a/.github/workflows/release-e2e-workflow-template.yml b/.github/workflows/release-e2e-workflow-template.yml index 20fe3fa4d..bc0788427 100644 --- a/.github/workflows/release-e2e-workflow-template.yml +++ b/.github/workflows/release-e2e-workflow-template.yml @@ -25,6 +25,8 @@ jobs: TERM: xterm # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' + # 2.12 onwards security demo configuration require a custom admin password + OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' steps: - name: Set up JDK uses: actions/setup-java@v1 @@ -61,8 +63,8 @@ jobs: else echo "Keep OpenSearch Security" ./opensearch-tar-install.sh & - timeout 900 bash -c 'while [[ "$(curl -o /dev/null -w ''%{http_code}'' -u admin:admin -k https://localhost:9200)" != "200" ]]; do sleep 5; done' - curl https://localhost:9200 -u admin:admin --insecure + timeout 900 bash -c 'while [[ "$(curl -o /dev/null -w ''%{http_code}'' -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k https://localhost:9200)" != "200" ]]; do sleep 5; done' + curl https://localhost:9200 -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} --insecure fi - name: Get OpenSearch-Dashboards run: | @@ -92,8 +94,8 @@ jobs: else echo "Keep Dashboards Security" bin/opensearch-dashboards serve ${{ inputs.osd-serve-args }} & - timeout 300 bash -c 'while [[ "$(curl -u admin:admin -k http://localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' - curl http://localhost:5601/api/status -u admin:admin --insecure + timeout 300 bash -c 'while [[ "$(curl -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k http://localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' + curl http://localhost:5601/api/status -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} --insecure fi - name: Get Cypress version id: cypress_version diff --git a/.github/workflows/release-signoff-chrome.yml b/.github/workflows/release-signoff-chrome.yml index 9dc47ddb4..8c8bfd0fa 100644 --- a/.github/workflows/release-signoff-chrome.yml +++ b/.github/workflows/release-signoff-chrome.yml @@ -13,6 +13,8 @@ jobs: TERM: xterm # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' + # 2.12 onwards security demo configuration require a custom admin password + OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' steps: - name: Checkout functional-test uses: actions/checkout@v2 @@ -29,7 +31,7 @@ jobs: tar -xzf opensearch-${{ env.VERSION }}-linux-x64.tar.gz cd opensearch-${{ env.VERSION }}/ ./opensearch-tar-install.sh & - timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:admin -k https://localhost:9200)" != "200" ]]; do sleep 5; done' + timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k https://localhost:9200)" != "200" ]]; do sleep 5; done' - name: Get OpenSearch-Dashboards run: | wget https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/${{ env.VERSION }}/latest/linux/x64/tar/dist/opensearch-dashboards/opensearch-dashboards-${{ env.VERSION }}-linux-x64.tar.gz diff --git a/.github/workflows/release-signoff-chromium-ad-only.yml b/.github/workflows/release-signoff-chromium-ad-only.yml index 96cf1bc8e..4fe8bd70c 100644 --- a/.github/workflows/release-signoff-chromium-ad-only.yml +++ b/.github/workflows/release-signoff-chromium-ad-only.yml @@ -13,6 +13,8 @@ jobs: TERM: xterm # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' + # 2.12 onwards security demo configuration require a custom admin password + OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' steps: - name: Checkout functional-test uses: actions/checkout@v2 @@ -29,7 +31,7 @@ jobs: tar -xzf opensearch-${{ env.VERSION }}-linux-x64.tar.gz cd opensearch-${{ env.VERSION }}/ ./opensearch-tar-install.sh & - timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:admin -k https://localhost:9200)" != "200" ]]; do sleep 5; done' + timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k https://localhost:9200)" != "200" ]]; do sleep 5; done' - name: Get OpenSearch-Dashboards run: | wget https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/${{ env.VERSION }}/latest/linux/x64/tar/dist/opensearch-dashboards/opensearch-dashboards-${{ env.VERSION }}-linux-x64.tar.gz diff --git a/.github/workflows/release-signoff-chromium-ism-only.yml b/.github/workflows/release-signoff-chromium-ism-only.yml index 08aa34055..ef26b7fe0 100644 --- a/.github/workflows/release-signoff-chromium-ism-only.yml +++ b/.github/workflows/release-signoff-chromium-ism-only.yml @@ -13,6 +13,8 @@ jobs: TERM: xterm # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' + # 2.12 onwards security demo configuration require a custom admin password + OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' steps: - name: Checkout functional-test uses: actions/checkout@v2 @@ -29,7 +31,7 @@ jobs: tar -xzf opensearch-${{ env.VERSION }}-linux-x64.tar.gz cd opensearch-${{ env.VERSION }}/ ./opensearch-tar-install.sh & - timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:admin -k https://localhost:9200)" != "200" ]]; do sleep 5; done' + timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k https://localhost:9200)" != "200" ]]; do sleep 5; done' - name: Get OpenSearch-Dashboards run: | wget https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/${{ env.VERSION }}/latest/linux/x64/tar/dist/opensearch-dashboards/opensearch-dashboards-${{ env.VERSION }}-linux-x64.tar.gz diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml index 8e4604747..853787808 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml @@ -13,6 +13,8 @@ jobs: TERM: xterm # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' + # 2.12 onwards security demo configuration require a custom admin password + OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' steps: - name: Checkout functional-test uses: actions/checkout@v2 @@ -29,7 +31,7 @@ jobs: tar -xzf opensearch-${{ env.VERSION }}-linux-x64.tar.gz cd opensearch-${{ env.VERSION }}/ ./opensearch-tar-install.sh & - timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:admin -k https://localhost:9200)" != "200" ]]; do sleep 5; done' + timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k https://localhost:9200)" != "200" ]]; do sleep 5; done' - name: Get OpenSearch-Dashboards run: | wget https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/${{ env.VERSION }}/latest/linux/x64/tar/dist/opensearch-dashboards/opensearch-dashboards-${{ env.VERSION }}-linux-x64.tar.gz diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml index 599054bb4..d8e7f3600 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml @@ -13,6 +13,8 @@ jobs: TERM: xterm # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' + # 2.12 onwards security demo configuration require a custom admin password + OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' steps: - name: Checkout functional-test uses: actions/checkout@v2 @@ -29,7 +31,7 @@ jobs: tar -xzf opensearch-${{ env.VERSION }}-linux-x64.tar.gz cd opensearch-${{ env.VERSION }}/ ./opensearch-tar-install.sh & - timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:admin -k https://localhost:9200)" != "200" ]]; do sleep 5; done' + timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k https://localhost:9200)" != "200" ]]; do sleep 5; done' - name: Get OpenSearch-Dashboards run: | wget https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/${{ env.VERSION }}/latest/linux/x64/tar/dist/opensearch-dashboards/opensearch-dashboards-${{ env.VERSION }}-linux-x64.tar.gz diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml index 3a32342cf..756bf5bd9 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml @@ -13,6 +13,8 @@ jobs: TERM: xterm # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' + # 2.12 onwards security demo configuration require a custom admin password + OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' steps: - name: Checkout functional-test uses: actions/checkout@v2 @@ -29,7 +31,7 @@ jobs: tar -xzf opensearch-${{ env.VERSION }}-linux-x64.tar.gz cd opensearch-${{ env.VERSION }}/ ./opensearch-tar-install.sh & - timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:admin -k https://localhost:9200)" != "200" ]]; do sleep 5; done' + timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k https://localhost:9200)" != "200" ]]; do sleep 5; done' - name: Get OpenSearch-Dashboards run: | wget https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/${{ env.VERSION }}/latest/linux/x64/tar/dist/opensearch-dashboards/opensearch-dashboards-${{ env.VERSION }}-linux-x64.tar.gz diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml index 8b2b6faf7..7550416b1 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml @@ -13,6 +13,8 @@ jobs: TERM: xterm # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' + # 2.12 onwards security demo configuration require a custom admin password + OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' steps: - name: Checkout functional-test uses: actions/checkout@v2 @@ -29,7 +31,7 @@ jobs: tar -xzf opensearch-${{ env.VERSION }}-linux-x64.tar.gz cd opensearch-${{ env.VERSION }}/ ./opensearch-tar-install.sh & - timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:admin -k https://localhost:9200)" != "200" ]]; do sleep 5; done' + timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k https://localhost:9200)" != "200" ]]; do sleep 5; done' - name: Get OpenSearch-Dashboards run: | wget https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/${{ env.VERSION }}/latest/linux/x64/tar/dist/opensearch-dashboards/opensearch-dashboards-${{ env.VERSION }}-linux-x64.tar.gz diff --git a/.github/workflows/release-signoff-chromium.yml b/.github/workflows/release-signoff-chromium.yml index 15015ef74..c7f422b8f 100644 --- a/.github/workflows/release-signoff-chromium.yml +++ b/.github/workflows/release-signoff-chromium.yml @@ -13,6 +13,8 @@ jobs: TERM: xterm # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' + # 2.12 onwards security demo configuration require a custom admin password + OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' steps: - name: Checkout functional-test uses: actions/checkout@v2 @@ -29,7 +31,7 @@ jobs: tar -xzf opensearch-${{ env.VERSION }}-linux-x64.tar.gz cd opensearch-${{ env.VERSION }}/ ./opensearch-tar-install.sh & - timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:admin -k https://localhost:9200)" != "200" ]]; do sleep 5; done' + timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k https://localhost:9200)" != "200" ]]; do sleep 5; done' - name: Get OpenSearch-Dashboards run: | wget https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/${{ env.VERSION }}/latest/linux/x64/tar/dist/opensearch-dashboards/opensearch-dashboards-${{ env.VERSION }}-linux-x64.tar.gz diff --git a/.github/workflows/release-signoff-electron.yml b/.github/workflows/release-signoff-electron.yml index 140c69b52..b9dfd022c 100644 --- a/.github/workflows/release-signoff-electron.yml +++ b/.github/workflows/release-signoff-electron.yml @@ -13,6 +13,8 @@ jobs: TERM: xterm # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' + # 2.12 onwards security demo configuration require a custom admin password + OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' steps: - name: Checkout functional-test uses: actions/checkout@v2 @@ -29,7 +31,7 @@ jobs: tar -xzf opensearch-${{ env.VERSION }}-linux-x64.tar.gz cd opensearch-${{ env.VERSION }}/ ./opensearch-tar-install.sh & - timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:admin -k https://localhost:9200)" != "200" ]]; do sleep 5; done' + timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k https://localhost:9200)" != "200" ]]; do sleep 5; done' - name: Get OpenSearch-Dashboards run: | wget https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/${{ env.VERSION }}/latest/linux/x64/tar/dist/opensearch-dashboards/opensearch-dashboards-${{ env.VERSION }}-linux-x64.tar.gz diff --git a/.github/workflows/release-signoff-firefox.yml b/.github/workflows/release-signoff-firefox.yml index 0f99fa5ed..1cd110729 100644 --- a/.github/workflows/release-signoff-firefox.yml +++ b/.github/workflows/release-signoff-firefox.yml @@ -13,6 +13,8 @@ jobs: TERM: xterm # make Node run in ipv4 first so that cypress can detect 5601 port in CI environment NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' + # 2.12 onwards security demo configuration require a custom admin password + OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' steps: - name: Checkout functional-test uses: actions/checkout@v2 @@ -29,7 +31,7 @@ jobs: tar -xzf opensearch-${{ env.VERSION }}-linux-x64.tar.gz cd opensearch-${{ env.VERSION }}/ ./opensearch-tar-install.sh & - timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:admin -k https://localhost:9200)" != "200" ]]; do sleep 5; done' + timeout 900 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} -k https://localhost:9200)" != "200" ]]; do sleep 5; done' - name: Get OpenSearch-Dashboards run: | wget https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/${{ env.VERSION }}/latest/linux/x64/tar/dist/opensearch-dashboards/opensearch-dashboards-${{ env.VERSION }}-linux-x64.tar.gz diff --git a/cypress.json b/cypress.json index f79ebf340..9de868129 100644 --- a/cypress.json +++ b/cypress.json @@ -14,7 +14,7 @@ "SECURITY_ENABLED": false, "AGGREGATION_VIEW": false, "username": "admin", - "password": "admin", + "password": "myStrongPassword123!", "ENDPOINT_WITH_PROXY": false, "MANAGED_SERVICE_ENDPOINT": false, "VISBUILDER_ENABLED": true, diff --git a/integtest.sh b/integtest.sh old mode 100755 new mode 100644 index 3adcb0436..cd97c1da7 --- a/integtest.sh +++ b/integtest.sh @@ -80,11 +80,13 @@ fi if [ -z "$CREDENTIAL" ] then - CREDENTIAL="admin:admin" - USERNAME=`echo $CREDENTIAL | awk -F ':' '{print $1}'` - PASSWORD=`echo $CREDENTIAL | awk -F ':' '{print $2}'` + # Starting in 2.12.0, security demo configuration script requires an initial admin password + CREDENTIAL="admin:myStrongPassword123!" fi +USERNAME=`echo $CREDENTIAL | awk -F ':' '{print $1}'` +PASSWORD=`echo $CREDENTIAL | awk -F ':' '{print $2}'` + # User can send custom browser path through env variable if [ -z "$BROWSER_PATH" ] then @@ -113,4 +115,4 @@ then else echo "run security disabled tests" yarn cypress:run-without-security --browser "$BROWSER_PATH" --spec "$TEST_FILES" -fi +fi \ No newline at end of file From 6cba7a6b3cff3633055b4a0cedb2bd34bdc52870 Mon Sep 17 00:00:00 2001 From: Derek Ho Date: Fri, 12 Jan 2024 09:22:56 -0500 Subject: [PATCH 10/21] Adapt recent changes in the security plugin to pass integ test (#995) Signed-off-by: Derek Ho --- cypress/integration/plugins/security/internalusers_spec.js | 2 +- cypress/utils/plugins/security/commands.js | 4 ++-- cypress/utils/plugins/security/constants.js | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cypress/integration/plugins/security/internalusers_spec.js b/cypress/integration/plugins/security/internalusers_spec.js index ee2b838e1..dde1c9e18 100644 --- a/cypress/integration/plugins/security/internalusers_spec.js +++ b/cypress/integration/plugins/security/internalusers_spec.js @@ -57,7 +57,7 @@ if (Cypress.env('SECURITY_ENABLED')) { } ); - cy.contains('span', 'Create internal user'); + cy.contains('span', 'Create user account'); cy.url().should((url) => { expect(url).to.not.contain('/users/create'); diff --git a/cypress/utils/plugins/security/commands.js b/cypress/utils/plugins/security/commands.js index 654b5110e..a110d980e 100644 --- a/cypress/utils/plugins/security/commands.js +++ b/cypress/utils/plugins/security/commands.js @@ -6,7 +6,7 @@ import { SEC_API_CONFIG_PATH, SEC_API_ROLES_PATH, - SEC_API_INTERNAL_USERS_PATH, + SEC_API_INTERNAL_ACCOUNTS_PATH, SEC_API_ACTIONGROUPS_PATH, SEC_API_TENANTS_PATH, SEC_API_AUDIT_PATH, @@ -48,7 +48,7 @@ Cypress.Commands.add( Cypress.Commands.add( 'mockInternalUsersAction', function (fixtureFileName, funcMockedOn) { - cy.intercept(SEC_API_INTERNAL_USERS_PATH, { + cy.intercept(SEC_API_INTERNAL_ACCOUNTS_PATH, { fixture: fixtureFileName, }).as('getInternalUsersDetails'); diff --git a/cypress/utils/plugins/security/constants.js b/cypress/utils/plugins/security/constants.js index 1f8009ba0..2fcfb46c0 100644 --- a/cypress/utils/plugins/security/constants.js +++ b/cypress/utils/plugins/security/constants.js @@ -55,6 +55,8 @@ export const SEC_API_ACTIONGROUPS_PATH = BASE_SEC_API_PATH + '/actiongroups'; export const SEC_API_TENANTS_PATH = BASE_SEC_API_PATH + '/tenants'; export const SEC_API_INTERNAL_USERS_PATH = BASE_SEC_API_PATH + '/internalusers'; +export const SEC_API_INTERNAL_ACCOUNTS_PATH = + BASE_SEC_API_PATH + '/internalaccounts'; export const SEC_API_ACCOUNT_PATH = BASE_SEC_API_PATH + '/account'; From 23541222bea056b750153333bf9a9788ddefe3cb Mon Sep 17 00:00:00 2001 From: Lin Wang Date: Mon, 15 Jan 2024 09:52:49 +0800 Subject: [PATCH 11/21] add admin credentials for regular release signoff workflow (#994) Signed-off-by: Lin Wang --- .github/workflows/release-signoff-chrome.yml | 2 +- .github/workflows/release-signoff-chromium-ad-only.yml | 2 +- .github/workflows/release-signoff-chromium-ism-only.yml | 2 +- .../workflows/release-signoff-chromium-tests-in-memory-0.yml | 2 +- .../workflows/release-signoff-chromium-tests-in-memory-10.yml | 2 +- .../workflows/release-signoff-chromium-tests-in-memory-20.yml | 2 +- .../workflows/release-signoff-chromium-tests-in-memory-5.yml | 2 +- .github/workflows/release-signoff-chromium.yml | 2 +- .github/workflows/release-signoff-electron.yml | 2 +- .github/workflows/release-signoff-firefox.yml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release-signoff-chrome.yml b/.github/workflows/release-signoff-chrome.yml index 8c8bfd0fa..7fe376364 100644 --- a/.github/workflows/release-signoff-chrome.yml +++ b/.github/workflows/release-signoff-chrome.yml @@ -50,7 +50,7 @@ jobs: run: | cd opensearch-dashboards-${{ env.VERSION }} bin/opensearch-dashboards serve & - timeout 300 bash -c 'while [[ "$(curl -s localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' + timeout 300 bash -c 'while [[ "$(curl -s -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' - name: Get Cypress version id: cypress_version run: | diff --git a/.github/workflows/release-signoff-chromium-ad-only.yml b/.github/workflows/release-signoff-chromium-ad-only.yml index 4fe8bd70c..02a9b1eb0 100644 --- a/.github/workflows/release-signoff-chromium-ad-only.yml +++ b/.github/workflows/release-signoff-chromium-ad-only.yml @@ -50,7 +50,7 @@ jobs: run: | cd opensearch-dashboards-${{ env.VERSION }} bin/opensearch-dashboards serve & - timeout 300 bash -c 'while [[ "$(curl -s localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' + timeout 300 bash -c 'while [[ "$(curl -s -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' - name: Get Cypress version id: cypress_version run: | diff --git a/.github/workflows/release-signoff-chromium-ism-only.yml b/.github/workflows/release-signoff-chromium-ism-only.yml index ef26b7fe0..4abb54461 100644 --- a/.github/workflows/release-signoff-chromium-ism-only.yml +++ b/.github/workflows/release-signoff-chromium-ism-only.yml @@ -50,7 +50,7 @@ jobs: run: | cd opensearch-dashboards-${{ env.VERSION }} bin/opensearch-dashboards serve & - timeout 300 bash -c 'while [[ "$(curl -s localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' + timeout 300 bash -c 'while [[ "$(curl -s -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' - name: Get Cypress version id: cypress_version run: | diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml index 853787808..100d8b487 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml @@ -50,7 +50,7 @@ jobs: run: | cd opensearch-dashboards-${{ env.VERSION }} bin/opensearch-dashboards serve & - timeout 300 bash -c 'while [[ "$(curl -s localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' + timeout 300 bash -c 'while [[ "$(curl -s -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' - name: Get Cypress version id: cypress_version run: | diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml index d8e7f3600..d180e1a01 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml @@ -50,7 +50,7 @@ jobs: run: | cd opensearch-dashboards-${{ env.VERSION }} bin/opensearch-dashboards serve & - timeout 300 bash -c 'while [[ "$(curl -s localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' + timeout 300 bash -c 'while [[ "$(curl -s -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' - name: Get Cypress version id: cypress_version run: | diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml index 756bf5bd9..5114ca711 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml @@ -50,7 +50,7 @@ jobs: run: | cd opensearch-dashboards-${{ env.VERSION }} bin/opensearch-dashboards serve & - timeout 300 bash -c 'while [[ "$(curl -s localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' + timeout 300 bash -c 'while [[ "$(curl -s -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' - name: Get Cypress version id: cypress_version run: | diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml index 7550416b1..6a6c83d6f 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml @@ -50,7 +50,7 @@ jobs: run: | cd opensearch-dashboards-${{ env.VERSION }} bin/opensearch-dashboards serve & - timeout 300 bash -c 'while [[ "$(curl -s localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' + timeout 300 bash -c 'while [[ "$(curl -s -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' - name: Get Cypress version id: cypress_version run: | diff --git a/.github/workflows/release-signoff-chromium.yml b/.github/workflows/release-signoff-chromium.yml index c7f422b8f..2e01bf67b 100644 --- a/.github/workflows/release-signoff-chromium.yml +++ b/.github/workflows/release-signoff-chromium.yml @@ -50,7 +50,7 @@ jobs: run: | cd opensearch-dashboards-${{ env.VERSION }} bin/opensearch-dashboards serve & - timeout 300 bash -c 'while [[ "$(curl -s localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' + timeout 300 bash -c 'while [[ "$(curl -s -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' - name: Get Cypress version id: cypress_version run: | diff --git a/.github/workflows/release-signoff-electron.yml b/.github/workflows/release-signoff-electron.yml index b9dfd022c..d81a4acea 100644 --- a/.github/workflows/release-signoff-electron.yml +++ b/.github/workflows/release-signoff-electron.yml @@ -50,7 +50,7 @@ jobs: run: | cd opensearch-dashboards-${{ env.VERSION }} bin/opensearch-dashboards serve & - timeout 300 bash -c 'while [[ "$(curl -s localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' + timeout 300 bash -c 'while [[ "$(curl -s -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' - name: Get Cypress version id: cypress_version run: | diff --git a/.github/workflows/release-signoff-firefox.yml b/.github/workflows/release-signoff-firefox.yml index 1cd110729..add0895c9 100644 --- a/.github/workflows/release-signoff-firefox.yml +++ b/.github/workflows/release-signoff-firefox.yml @@ -50,7 +50,7 @@ jobs: run: | cd opensearch-dashboards-${{ env.VERSION }} bin/opensearch-dashboards serve & - timeout 300 bash -c 'while [[ "$(curl -s localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' + timeout 300 bash -c 'while [[ "$(curl -s -u admin:${{ env.OPENSEARCH_INITIAL_ADMIN_PASSWORD }} localhost:5601/api/status | jq -r '.status.overall.state')" != "green" ]]; do sleep 5; done' - name: Get Cypress version id: cypress_version run: | From 8cd68dc509eeb01ca7658f1f784201ce117cf009 Mon Sep 17 00:00:00 2001 From: Jialiang Liang <109499885+RyanL1997@users.noreply.github.com> Date: Sun, 14 Jan 2024 19:48:14 -0800 Subject: [PATCH 12/21] Add functional test for datasources at observability dashboards plugin (#987) * Add functional test for datasources at observability dashboards plugin Signed-off-by: Ryan Liang * Extend the header locating to 2 mins Signed-off-by: Ryan Liang * Fix lint Signed-off-by: Ryan Liang --------- Signed-off-by: Ryan Liang --- .../7_datasources_dashboard.spec.js | 82 +++++++++++++++++++ .../observability-dashboards/constants.js | 7 ++ 2 files changed, 89 insertions(+) create mode 100644 cypress/integration/plugins/observability-dashboards/7_datasources_dashboard.spec.js diff --git a/cypress/integration/plugins/observability-dashboards/7_datasources_dashboard.spec.js b/cypress/integration/plugins/observability-dashboards/7_datasources_dashboard.spec.js new file mode 100644 index 000000000..ac554e5d1 --- /dev/null +++ b/cypress/integration/plugins/observability-dashboards/7_datasources_dashboard.spec.js @@ -0,0 +1,82 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/// + +import { BASE_PATH } from '../../../utils/base_constants'; + +import { + DATASOURCES_API_PREFIX, + DATASOURCES_PATH, +} from '../../../utils/plugins/observability-dashboards/constants'; + +const manageDataSourcesTag = 'button[data-test-subj="manage"]'; +const newDataSourcesTag = 'button[data-test-subj="new"]'; +const createS3Button = '[data-test-subj="datasource_card_s3glue"]'; +const createPrometheusButton = '[data-test-subj="datasource_card_prometheus"]'; + +const visitDatasourcesHomePage = () => { + cy.visit(BASE_PATH + DATASOURCES_API_PREFIX); +}; + +const visitDatasourcesCreationPage = () => { + cy.visit(BASE_PATH + DATASOURCES_PATH.DATASOURCES_CREATION_BASE); +}; + +describe('Integration tests for datasources plugin', () => { + it('Navigates to datasources plugin and expects the correct header', () => { + visitDatasourcesHomePage(); + cy.get('[data-test-subj="dataconnections-header"]', { + timeout: 120000, + }).should('exist'); + }); + + it('Tests navigation between tabs', () => { + visitDatasourcesHomePage(); + + cy.get(manageDataSourcesTag) + .should('have.class', 'euiTab-isSelected') + .and('have.attr', 'aria-selected', 'true'); + cy.get(manageDataSourcesTag).click(); + cy.url().should('include', '/manage'); + + cy.get(newDataSourcesTag).click(); + cy.get(newDataSourcesTag) + .should('have.class', 'euiTab-isSelected') + .and('have.attr', 'aria-selected', 'true'); + cy.url().should('include', '/new'); + + cy.get(createS3Button).should('be.visible'); + cy.get(createPrometheusButton).should('be.visible'); + }); + + it('Tests navigation of S3 datasources creation page with hash', () => { + visitDatasourcesCreationPage(); + + cy.get(createS3Button).should('be.visible').click(); + cy.url().should( + 'include', + DATASOURCES_PATH.DATASOURCES_CONFIG_BASE + '/AmazonS3AWSGlue' + ); + + cy.get('h1.euiTitle.euiTitle--medium') + .should('be.visible') + .and('contain', 'Configure Amazon S3 data source'); + }); + + it('Tests navigation of Prometheus datasources creation page with hash', () => { + visitDatasourcesCreationPage(); + + cy.get(createPrometheusButton).should('be.visible').click(); + cy.url().should( + 'include', + DATASOURCES_PATH.DATASOURCES_CONFIG_BASE + '/Prometheus' + ); + + cy.get('h4.euiTitle.euiTitle--medium') + .should('be.visible') + .and('contain', 'Configure Prometheus data source'); + }); +}); diff --git a/cypress/utils/plugins/observability-dashboards/constants.js b/cypress/utils/plugins/observability-dashboards/constants.js index d73a64f21..6041c929d 100644 --- a/cypress/utils/plugins/observability-dashboards/constants.js +++ b/cypress/utils/plugins/observability-dashboards/constants.js @@ -6,6 +6,13 @@ import { BASE_PATH } from '../../base_constants'; export const delayTime = 1500; +//Datasources API Constants +export const DATASOURCES_API_PREFIX = '/app/datasources'; +export const DATASOURCES_PATH = { + DATASOURCES_CREATION_BASE: `${DATASOURCES_API_PREFIX}#/new`, + DATASOURCES_CONFIG_BASE: `${DATASOURCES_API_PREFIX}#/configure`, +}; + // trace analytics export const TRACE_ID = '8832ed6abbb2a83516461960c89af49d'; export const SPAN_ID = 'a673bc074b438374'; From 73f6db1b968c3c164ef2554851cf8c3bd97e5987 Mon Sep 17 00:00:00 2001 From: "Qingyang(Abby) Hu" Date: Sun, 21 Jan 2024 19:05:05 -0800 Subject: [PATCH 13/21] add suppress observer (#969) Signed-off-by: Qingyang(Abby) Hu --- .../apps/vis_type_table/embed.spec.js | 8 ++++++++ .../plugins/observability-dashboards/constants.js | 10 +++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/vis_type_table/embed.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/vis_type_table/embed.spec.js index 4ddaee868..071a5b67f 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/vis_type_table/embed.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/vis_type_table/embed.spec.js @@ -48,6 +48,13 @@ describe('table visualization in embedded mode', () => { '115', ]; + const suppressResizeObserverIssue = () => { + // exception is thrown on loading EuiDataGrid in cypress only, ignore for now + cy.on('uncaught:exception', (err) => { + if (err.message.includes('ResizeObserver loop')) return false; + }); + }; + before(() => { cy.deleteIndex(TABLE_INDEX_ID); cy.deleteIndexPattern(TABLE_INDEX_PATTERN); @@ -153,6 +160,7 @@ describe('table visualization in embedded mode', () => { expect(data).to.deep.eq(expectedData); }); cy.tbClickTableCellAction(2, 0, 0, 'expand', 0, true); + suppressResizeObserverIssue(); cy.tbClickFilterFromExpand('filter out'); cy.reload(); cy.tbGetTableDataFromVisualization().then((data) => { diff --git a/cypress/utils/plugins/observability-dashboards/constants.js b/cypress/utils/plugins/observability-dashboards/constants.js index 6041c929d..4b9ace2c3 100644 --- a/cypress/utils/plugins/observability-dashboards/constants.js +++ b/cypress/utils/plugins/observability-dashboards/constants.js @@ -43,7 +43,7 @@ export const testIndexDataSet = [ }, ]; -export const supressResizeObserverIssue = () => { +export const suppressResizeObserverIssue = () => { // exception is thrown on loading EuiDataGrid in cypress only, ignore for now cy.on('uncaught:exception', (err) => { if (err.message.includes('ResizeObserver loop')) return false; @@ -185,7 +185,7 @@ export const landOnEventVisualizations = () => { cy.get('button[id="main-content-vis"]', { timeout: TIMEOUT_DELAY }) .contains('Visualizations') .click(); - supressResizeObserverIssue(); + suppressResizeObserverIssue(); cy.wait(delayTime); }; @@ -256,7 +256,7 @@ export const moveToCreatePage = () => { }) .eq(0) .click(); - supressResizeObserverIssue(); + suppressResizeObserverIssue(); cy.wait(delayTime * 2); cy.get('[data-test-subj="createPageTitle"]', { timeout: TIMEOUT_DELAY, @@ -267,7 +267,7 @@ export const moveToApplication = (name) => { cy.visit(`${BASE_PATH}/app/observability-applications#`, { waitForGetTenant: true, }); - supressResizeObserverIssue(); + suppressResizeObserverIssue(); cy.wait(delayTime * 2); cy.get(`[data-test-subj="${name}ApplicationLink"]`, { timeout: TIMEOUT_DELAY, @@ -286,7 +286,7 @@ export const moveToEditPage = () => { cy.get('[data-test-subj="editApplicationButton"]', { timeout: TIMEOUT_DELAY, }).click(); - supressResizeObserverIssue(); + suppressResizeObserverIssue(); cy.wait(delayTime); cy.get('[data-test-subj="createPageTitle"]', { timeout: TIMEOUT_DELAY, From 860444cd76859262197222d52fe2407247cae348 Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 11:09:28 +0800 Subject: [PATCH 14/21] [Tests] Set default tenancy to global for data explorer tests (#959) (#963) Signed-off-by: manasvinibs (cherry picked from commit e7647a1c62e5de3d69d2f58b1cfe794d83aa132c) Co-authored-by: Manasvini B Suryanarayana --- .../apps/data_explorer/aaa_before.spec.js | 3 +++ .../apps/data_explorer/date_nanos.spec.js | 4 +++- .../apps/data_explorer/date_nanos_mixed.spec.js | 3 ++- .../apps/data_explorer/discover.spec.js | 2 ++ .../apps/data_explorer/discover_histogram.spec.js | 2 ++ .../apps/data_explorer/doc_navigation.spec.js | 2 ++ .../apps/data_explorer/doc_table.spec.js | 2 ++ .../opensearch-dashboards/apps/data_explorer/errors.spec.js | 2 ++ .../apps/data_explorer/field_data.spec.js | 2 ++ .../apps/data_explorer/field_visualize.spec.js | 2 ++ .../apps/data_explorer/filter_editor.spec.js | 2 ++ .../apps/data_explorer/index_pattern_with_encoded_id.spec.js | 2 ++ .../apps/data_explorer/index_pattern_without_field.spec.js | 2 ++ .../apps/data_explorer/inspector.spec.js | 2 ++ .../apps/data_explorer/large_string.spec.js | 2 ++ .../apps/data_explorer/saved_queries.spec.js | 2 ++ .../apps/data_explorer/shared_links.spec.js | 2 ++ .../opensearch-dashboards/apps/data_explorer/sidebar.spec.js | 2 ++ .../apps/data_explorer/source_filter.spec.js | 2 ++ .../apps/data_explorer/zzz_after.spec.js | 2 ++ cypress/utils/commands.js | 5 +++++ 21 files changed, 47 insertions(+), 2 deletions(-) diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/aaa_before.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/aaa_before.spec.js index 8b56fb15c..e7e5af5c2 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/aaa_before.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/aaa_before.spec.js @@ -3,10 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { CURRENT_TENANT } from '../../../../../utils/commands'; + /// describe('Before', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; cy.deleteAllIndices(); cy.deleteSavedObjectByType('index-pattern'); }); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos.spec.js index ccdbc3490..b17c78124 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos.spec.js @@ -7,6 +7,8 @@ import { TestFixtureHandler, MiscUtils, } from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { CURRENT_TENANT } from '../../../../../utils/commands'; + const testFixtureHandler = new TestFixtureHandler( cy, Cypress.env('openSearchUrl') @@ -18,6 +20,7 @@ describe('date_nanos', () => { const fromTime = 'Sep 21, 2019 @ 20:31:44.000'; const toTime = 'Sep 23, 2019 @ 03:31:44.000'; before(() => { + CURRENT_TENANT.newTenant = 'global'; // import date nanos testFixtureHandler.importJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/date_nanos/mappings.json.txt' @@ -29,7 +32,6 @@ describe('date_nanos', () => { cy.setAdvancedSetting({ defaultIndex: 'date-nanos', }); - miscUtils.visitPage('app/data-explorer/discover#/'); cy.waitForLoader(); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos_mixed.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos_mixed.spec.js index 19aca0b41..07e48047f 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos_mixed.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/date_nanos_mixed.spec.js @@ -7,6 +7,7 @@ import { TestFixtureHandler, MiscUtils, } from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { CURRENT_TENANT } from '../../../../../utils/commands'; const miscUtils = new MiscUtils(cy); const testFixtureHandler = new TestFixtureHandler( @@ -16,6 +17,7 @@ const testFixtureHandler = new TestFixtureHandler( describe('date_nanos_mixed', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; //import date nanos testFixtureHandler.importJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/date_nanos_mix/mappings.json.txt' @@ -27,7 +29,6 @@ describe('date_nanos_mixed', () => { cy.setAdvancedSetting({ defaultIndex: 'timestamp-*', }); - miscUtils.visitPage('app/data-explorer/discover#/'); cy.waitForLoader(); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover.spec.js index f4c766d2b..760ad48b3 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover.spec.js @@ -11,6 +11,7 @@ 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( @@ -25,6 +26,7 @@ const indexSet = [ describe('discover app', { scrollBehavior: false }, () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; // import logstash functional testFixtureHandler.importJSONDocIfNeeded( indexSet, diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover_histogram.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover_histogram.spec.js index 444e68c90..3003b5e8b 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover_histogram.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/discover_histogram.spec.js @@ -7,6 +7,7 @@ import { TestFixtureHandler, MiscUtils, } from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { CURRENT_TENANT } from '../../../../../utils/commands'; const miscUtils = new MiscUtils(cy); const testFixtureHandler = new TestFixtureHandler( @@ -21,6 +22,7 @@ const indexSet = [ describe('discover histogram', { scrollBehavior: false }, () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; cy.log('load opensearch-dashboards index with default index pattern'); // import long window logstash index pattern diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_navigation.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_navigation.spec.js index 747ac8013..40ad4c7d9 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_navigation.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_navigation.spec.js @@ -7,6 +7,7 @@ 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( @@ -21,6 +22,7 @@ const indexSet = [ describe('doc link in discover', () => { beforeEach(() => { + CURRENT_TENANT.newTenant = 'global'; // import logstash functional testFixtureHandler.importJSONDocIfNeeded( indexSet, diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_table.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_table.spec.js index 656ddb3bf..e79c33fb3 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_table.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/doc_table.spec.js @@ -7,6 +7,7 @@ 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( @@ -21,6 +22,7 @@ const indexSet = [ describe('discover doc table', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; // import logstash functional testFixtureHandler.importJSONDocIfNeeded( indexSet, diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/errors.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/errors.spec.js index fba6d481d..8f2fb99f9 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/errors.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/errors.spec.js @@ -11,6 +11,7 @@ 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( @@ -20,6 +21,7 @@ const testFixtureHandler = new TestFixtureHandler( describe('errors', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; // import invalid_scripted_field testFixtureHandler.importJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/invalid_scripted_field/mappings.json.txt' diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/field_data.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/field_data.spec.js index 126956296..2cbf475ae 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/field_data.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/field_data.spec.js @@ -7,6 +7,7 @@ import { TestFixtureHandler, MiscUtils, } from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { CURRENT_TENANT } from '../../../../../utils/commands'; const miscUtils = new MiscUtils(cy); const testFixtureHandler = new TestFixtureHandler( @@ -21,6 +22,7 @@ const indexSet = [ describe('discover tab', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; // import logstash functional testFixtureHandler.importJSONDocIfNeeded( indexSet, diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/field_visualize.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/field_visualize.spec.js index 5bd420669..5b9083bfe 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/field_visualize.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/field_visualize.spec.js @@ -7,6 +7,7 @@ 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( @@ -21,6 +22,7 @@ const indexSet = [ describe('discover field visualize button', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; testFixtureHandler.importJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/discover/discover.mappings.json.txt' ); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/filter_editor.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/filter_editor.spec.js index 1ecd717ec..18c3c5c3c 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/filter_editor.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/filter_editor.spec.js @@ -7,6 +7,7 @@ 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( @@ -21,6 +22,7 @@ const indexSet = [ describe('discover filter editor', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; testFixtureHandler.importJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/discover/discover.mappings.json.txt' ); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_with_encoded_id.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_with_encoded_id.spec.js index b848203fb..6d99eecc5 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_with_encoded_id.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_with_encoded_id.spec.js @@ -11,6 +11,7 @@ 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( @@ -20,6 +21,7 @@ const testFixtureHandler = new TestFixtureHandler( describe('index pattern with encoded id', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; testFixtureHandler.importJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/index_pattern_with_encoded_id/mappings.json.txt' ); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_without_field.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_without_field.spec.js index 7601381d0..bc09964e2 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_without_field.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/index_pattern_without_field.spec.js @@ -7,6 +7,7 @@ import { TestFixtureHandler, MiscUtils, } from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { CURRENT_TENANT } from '../../../../../utils/commands'; const miscUtils = new MiscUtils(cy); const testFixtureHandler = new TestFixtureHandler( @@ -16,6 +17,7 @@ const testFixtureHandler = new TestFixtureHandler( describe('index pattern without field spec', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; testFixtureHandler.importJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/index_pattern_without_timefield/mappings.json.txt' ); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/inspector.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/inspector.spec.js index 3688be2ff..afc9b6c55 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/inspector.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/inspector.spec.js @@ -11,6 +11,7 @@ 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( @@ -25,6 +26,7 @@ const indexSet = [ describe('inspector', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; // import logstash functional testFixtureHandler.importJSONDocIfNeeded( indexSet, diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/large_string.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/large_string.spec.js index e7a5fcb1c..825bcbd60 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/large_string.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/large_string.spec.js @@ -7,6 +7,7 @@ import { TestFixtureHandler, MiscUtils, } from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { CURRENT_TENANT } from '../../../../../utils/commands'; const miscUtils = new MiscUtils(cy); const testFixtureHandler = new TestFixtureHandler( @@ -16,6 +17,7 @@ const testFixtureHandler = new TestFixtureHandler( describe('test large strings', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; testFixtureHandler.importJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/empty_opensearch_dashboards/mappings.json.txt' ); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/saved_queries.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/saved_queries.spec.js index 7179a4280..8173db2cb 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/saved_queries.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/saved_queries.spec.js @@ -11,6 +11,7 @@ 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( @@ -27,6 +28,7 @@ describe('saved queries saved objects', () => { const fromTime = 'Sep 20, 2015 @ 08:00:00.000'; const toTime = 'Sep 21, 2015 @ 08:00:00.000'; before(() => { + CURRENT_TENANT.newTenant = 'global'; testFixtureHandler.importJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/discover/discover.mappings.json.txt' ); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/shared_links.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/shared_links.spec.js index 2adbfcdbb..61b9ae7f9 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/shared_links.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/shared_links.spec.js @@ -11,6 +11,7 @@ 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( @@ -25,6 +26,7 @@ const indexSet = [ describe('shared links', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; testFixtureHandler.importJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/discover/discover.mappings.json.txt' ); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/sidebar.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/sidebar.spec.js index 18b3ac9d2..4cf36e93c 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/sidebar.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/sidebar.spec.js @@ -7,6 +7,7 @@ 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( @@ -21,6 +22,7 @@ const indexSet = [ describe('discover sidebar', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; testFixtureHandler.importJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/discover/discover.mappings.json.txt' ); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/source_filter.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/source_filter.spec.js index e884b8435..b5e2d39a5 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/source_filter.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/source_filter.spec.js @@ -7,6 +7,7 @@ import { TestFixtureHandler, MiscUtils, } from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { CURRENT_TENANT } from '../../../../../utils/commands'; const miscUtils = new MiscUtils(cy); const testFixtureHandler = new TestFixtureHandler( @@ -16,6 +17,7 @@ const testFixtureHandler = new TestFixtureHandler( describe('source filters', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; testFixtureHandler.importJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/visualize_source-filters/mappings.json.txt' ); diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/zzz_after.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/zzz_after.spec.js index dea9bb66c..12d7407d2 100644 --- a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/zzz_after.spec.js +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/zzz_after.spec.js @@ -6,6 +6,7 @@ /// import { TestFixtureHandler } from '@opensearch-dashboards-test/opensearch-dashboards-test-library'; +import { CURRENT_TENANT } from '../../../../../utils/commands'; const testFixtureHandler = new TestFixtureHandler( cy, @@ -14,6 +15,7 @@ const testFixtureHandler = new TestFixtureHandler( describe('After', () => { before(() => { + CURRENT_TENANT.newTenant = 'global'; //cy.deleteAllIndices(); testFixtureHandler.clearJSONMapping( 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/logstash/logstash.mappings.json.txt' diff --git a/cypress/utils/commands.js b/cypress/utils/commands.js index 016826415..19f84fb66 100644 --- a/cypress/utils/commands.js +++ b/cypress/utils/commands.js @@ -426,6 +426,11 @@ Cypress.Commands.add('setAdvancedSetting', (changes) => { .request({ method: 'POST', url, + qs: Cypress.env('SECURITY_ENABLED') + ? { + security_tenant: CURRENT_TENANT.defaultTenant, + } + : {}, headers: { 'content-type': 'application/json;charset=UTF-8', 'osd-xsrf': true, From cd1dd23d2eafd5d3f8a6b02293d2b6166e92893f Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Tue, 23 Jan 2024 16:20:00 +0800 Subject: [PATCH 15/21] feat: Setup assistant agent & workflow file. (#1002) * feat: enable setup Signed-off-by: SuZhou-Joe * feat: using a external mock service to mock a dummy LLM Signed-off-by: SuZhou-Joe * feat: use local dummy server Signed-off-by: SuZhou-Joe * feat: add some basic test cases Signed-off-by: SuZhou-Joe * feat: run with server Signed-off-by: SuZhou-Joe * feat: use ml-commons api to setup test agent manually Signed-off-by: SuZhou-Joe * feat: remove flow_framework.enabled config Signed-off-by: SuZhou-Joe * feat: remove visualization as skills repo is not bundled in snapshot Signed-off-by: SuZhou-Joe * feat: add flag config Signed-off-by: SuZhou-Joe * feat: optimize stop command Signed-off-by: SuZhou-Joe * feat: move setup steps to support/index.js Signed-off-by: SuZhou-Joe --------- Signed-off-by: SuZhou-Joe --- .../assistant-release-e2e-workflow.yml | 25 +++ cypress.json | 3 +- .../agent-framework-response.json | 5 + .../cluster_settings.json | 9 + .../dashboards-assistant/flow-template.json | 157 ++++++++++++++++++ .../suggestion-response.json | 5 + .../chatbot_agent_framework_spec.js | 45 +++++ cypress/support/assistant-dummy-llm.js | 49 ++++++ cypress/support/index.js | 17 ++ .../plugins/dashboards-assistant/commands.js | 154 +++++++++++++++++ .../plugins/dashboards-assistant/constants.js | 17 ++ package.json | 3 +- 12 files changed, 487 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/assistant-release-e2e-workflow.yml create mode 100644 cypress/fixtures/plugins/dashboards-assistant/agent-framework-response.json create mode 100644 cypress/fixtures/plugins/dashboards-assistant/cluster_settings.json create mode 100644 cypress/fixtures/plugins/dashboards-assistant/flow-template.json create mode 100644 cypress/fixtures/plugins/dashboards-assistant/suggestion-response.json create mode 100644 cypress/integration/plugins/dashboards-assistant/chatbot_agent_framework_spec.js create mode 100644 cypress/support/assistant-dummy-llm.js create mode 100644 cypress/utils/plugins/dashboards-assistant/commands.js create mode 100644 cypress/utils/plugins/dashboards-assistant/constants.js diff --git a/.github/workflows/assistant-release-e2e-workflow.yml b/.github/workflows/assistant-release-e2e-workflow.yml new file mode 100644 index 000000000..952fd4cdd --- /dev/null +++ b/.github/workflows/assistant-release-e2e-workflow.yml @@ -0,0 +1,25 @@ +name: Assistant Release tests workflow in Bundled OpenSearch Dashboards +on: + pull_request: + branches: ['**'] +jobs: + changes: + runs-on: ubuntu-latest + outputs: + tests: ${{ steps.filter.outputs.tests }} + steps: + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + tests: + - 'cypress/**/dashboards-assistant/**' + + tests: + needs: changes + if: ${{ needs.changes.outputs.tests == 'true' }} + uses: ./.github/workflows/release-e2e-workflow-template.yml + with: + test-name: dashboards assistant + test-command: env CYPRESS_DASHBOARDS_ASSISTANT_ENABLED=true yarn cypress:run-with-security --browser chromium --spec 'cypress/integration/plugins/dashboards-assistant/*' + osd-serve-args: --assistant.chat.enabled=true --assistant.chat.rootAgentName="Cypress test agent" diff --git a/cypress.json b/cypress.json index 9de868129..2b6abb7db 100644 --- a/cypress.json +++ b/cypress.json @@ -20,6 +20,7 @@ "VISBUILDER_ENABLED": true, "DATASOURCE_MANAGEMENT_ENABLED": false, "ML_COMMONS_DASHBOARDS_ENABLED": true, - "WAIT_FOR_LOADER_BUFFER_MS": 0 + "WAIT_FOR_LOADER_BUFFER_MS": 0, + "DASHBOARDS_ASSISTANT_ENABLED": false } } diff --git a/cypress/fixtures/plugins/dashboards-assistant/agent-framework-response.json b/cypress/fixtures/plugins/dashboards-assistant/agent-framework-response.json new file mode 100644 index 000000000..202214c63 --- /dev/null +++ b/cypress/fixtures/plugins/dashboards-assistant/agent-framework-response.json @@ -0,0 +1,5 @@ +{ + "completion": " ```json\n{\n \"thought\": \"Now I know the final answer\",\n \"final_answer\": \"The indices in your cluster are the names listed in the response obtained from using a tool to get information about the OpenSearch indices. This included index names like .plugins-ml-model-group, security-auditlog-2024.01.16, opensearch_dashboards_sample_data_ecommerce and others along with health, status and other details.\"\n}\n```\n", + "stop_reason": "stop_sequence", + "stop": "\n\nHuman:" +} diff --git a/cypress/fixtures/plugins/dashboards-assistant/cluster_settings.json b/cypress/fixtures/plugins/dashboards-assistant/cluster_settings.json new file mode 100644 index 000000000..29e65ef6f --- /dev/null +++ b/cypress/fixtures/plugins/dashboards-assistant/cluster_settings.json @@ -0,0 +1,9 @@ +{ + "persistent": { + "plugins.ml_commons.only_run_on_ml_node": false, + "plugins.ml_commons.memory_feature_enabled": true, + "plugins.ml_commons.trusted_connector_endpoints_regex": [ + "^http://127.0.0.1:3000$" + ] + } +} diff --git a/cypress/fixtures/plugins/dashboards-assistant/flow-template.json b/cypress/fixtures/plugins/dashboards-assistant/flow-template.json new file mode 100644 index 000000000..1abc02395 --- /dev/null +++ b/cypress/fixtures/plugins/dashboards-assistant/flow-template.json @@ -0,0 +1,157 @@ +{ + "name": "Cypress-register-agent", + "description": "Cypress Flow template", + "use_case": "REGISTER_AGENT", + "version": { + "template": "1.0.0", + "compatibility": ["2.12.0", "3.0.0"] + }, + "workflows": { + "provision": { + "user_params": {}, + "nodes": [ + { + "id": "create_connector_1", + "type": "create_connector", + "previous_node_inputs": {}, + "user_inputs": { + "version": "1", + "name": "Claude instant runtime Connector", + "protocol": "aws_sigv4", + "description": "The connector to BedRock service for claude model", + "actions": [ + { + "headers": { + "x-amz-content-sha256": "required", + "content-type": "application/json" + }, + "method": "GET", + "request_body": "{\"prompt\":\"${parameters.prompt}\", \"max_tokens_to_sample\":${parameters.max_tokens_to_sample}, \"temperature\":${parameters.temperature}, \"anthropic_version\":\"${parameters.anthropic_version}\" }", + "action_type": "predict", + "url": "http://127.0.0.1:3000" + } + ], + "credential": { + "access_key": "", + "secret_key": "" + }, + "parameters": { + "endpoint": "bedrock-runtime.us-west-2.amazonaws.com", + "content_type": "application/json", + "auth": "Sig_V4", + "max_tokens_to_sample": "8000", + "service_name": "bedrock", + "temperature": "0.0001", + "response_filter": "$.completion", + "region": "us-west-2", + "anthropic_version": "bedrock-2023-05-31" + } + } + }, + { + "id": "register_model_2", + "type": "register_remote_model", + "previous_node_inputs": { + "create_connector_1": "connector_id" + }, + "user_inputs": { + "description": "test model", + "deploy": true, + "name": "claude-instant" + } + }, + { + "id": "cat_index_tool", + "type": "create_tool", + "previous_node_inputs": {}, + "user_inputs": { + "type": "CatIndexTool", + "name": "CatIndexTool", + "description": "Use this tool to get OpenSearch index information: (health, status, index, uuid, primary count, replica count, docs.count, docs.deleted, store.size, primary.store.size).", + "parameters": { + "index": ".kibana" + } + } + }, + { + "id": "sub_agent", + "type": "register_agent", + "previous_node_inputs": { + "cat_index_tool": "tools", + "register_model_2": "model_id" + }, + "user_inputs": { + "parameters": {}, + "app_type": "chatbot", + "name": "Cypress test sub Agent", + "description": "this is a test agent", + "llm.parameters": { + "max_iteration": "5", + "stop_when_no_tool_found": "true", + "response_filter": "$.completion" + }, + "memory": { + "type": "conversation_index" + }, + "type": "conversational" + } + }, + { + "id": "agent_tool", + "type": "create_tool", + "previous_node_inputs": { + "sub_agent": "agent_id" + }, + "user_inputs": { + "description": "Agent Tool", + "include_output_in_agent_response": true, + "type": "AgentTool", + "parameters": { + "max_iteration": "5" + }, + "name": "AgentTool" + } + }, + { + "id": "ml_model_tool", + "type": "create_tool", + "previous_node_inputs": { + "register_model_2": "model_id" + }, + "user_inputs": { + "parameters": { + "prompt": "\n\nHuman:\" turn\" You are an AI that only speaks JSON. Do not write normal text. Output should follow example JSON format: \n\n {\"response\": [\"question1\", \"question2\"]}\n\n. \n\nHuman:\" turn\":You will be given a chat history between OpenSearch Assistant and a Human.\nUse the context provided to generate follow up questions the Human would ask to the Assistant.\nThe Assistant can answer general questions about logs, traces and metrics.\nAssistant can access a set of tools listed below to answer questions given by the Human:\nQuestion suggestions generator tool\nHere's the chat history between the human and the Assistant.\n${parameters.AgentTool.output}\nUse the following steps to generate follow up questions Human may ask after the response of the Assistant:\nStep 1. Use the chat history to understand what human is trying to search and explore.\nStep 2. Understand what capabilities the assistant has with the set of tools it has access to.\nStep 3. Use the above context and generate follow up questions.Step4:You are an AI that only speaks JSON. Do not write normal text. Output should follow example JSON format: \n\n {\"response\": [\"question1\", \"question2\"]} \n \n----------------\n\nAssistant:" + }, + "description": "A general tool to answer any question.", + "alias": "language_model_tool", + "include_output_in_agent_response": true, + "name": "QuestionSuggestor", + "type": "MLModelTool" + } + }, + { + "id": "root_agent", + "type": "register_agent", + "previous_node_inputs": { + "agent_tool": "tools", + "register_model_2": "model_id", + "ml_model_tool": "tools" + }, + "user_inputs": { + "parameters": { + "prompt": "Answer the question as best you can." + }, + "app_type": "chatbot", + "name": "Cypress test agent", + "description": "this is the root agent", + "tools_order": ["agent_tool", "ml_model_tool"], + "memory": { + "type": "conversation_index" + }, + "type": "flow" + } + } + ] + } + } +} diff --git a/cypress/fixtures/plugins/dashboards-assistant/suggestion-response.json b/cypress/fixtures/plugins/dashboards-assistant/suggestion-response.json new file mode 100644 index 000000000..f30bb088a --- /dev/null +++ b/cypress/fixtures/plugins/dashboards-assistant/suggestion-response.json @@ -0,0 +1,5 @@ +{ + "completion": { + "response": ["suggestion1", "suggestion2"] + } +} diff --git a/cypress/integration/plugins/dashboards-assistant/chatbot_agent_framework_spec.js b/cypress/integration/plugins/dashboards-assistant/chatbot_agent_framework_spec.js new file mode 100644 index 000000000..f56244401 --- /dev/null +++ b/cypress/integration/plugins/dashboards-assistant/chatbot_agent_framework_spec.js @@ -0,0 +1,45 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +import { BASE_PATH } from '../../../utils/constants'; + +if (Cypress.env('DASHBOARDS_ASSISTANT_ENABLED')) { + describe('Assistant basic spec', () => { + before(() => { + // Set welcome screen tracking to false + localStorage.setItem('home:welcome:show', 'false'); + // Set new theme modal to false + localStorage.setItem('home:newThemeModal:show', 'false'); + }); + + beforeEach(() => { + // Visit ISM OSD + cy.visit(`${BASE_PATH}/app/home`); + + // Common text to wait for to confirm page loaded, give up to 60 seconds for initial load + cy.get(`input[placeholder="Ask question"]`, { timeout: 60000 }).should( + 'be.length', + 1 + ); + }); + + describe('Interact with Agent framework', () => { + it('toggle Chatbot and enable to interact', () => { + // enable to toggle and show Chatbot + cy.get(`img[aria-label="toggle chat flyout icon"]`).click(); + + // click suggestions to generate response + cy.contains('What are the indices in my cluster?').click(); + + // should have a LLM Response + cy.contains( + 'The indices in your cluster are the names listed in the response obtained from using a tool to get information about the OpenSearch indices.' + ); + + // should have a suggestion section + cy.get(`[aria-label="chat suggestions"]`).should('be.length', 1); + }); + }); + }); +} diff --git a/cypress/support/assistant-dummy-llm.js b/cypress/support/assistant-dummy-llm.js new file mode 100644 index 000000000..1000453f8 --- /dev/null +++ b/cypress/support/assistant-dummy-llm.js @@ -0,0 +1,49 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +const http = require('http'); +const agentFrameworkJson = require('../fixtures/plugins/dashboards-assistant/agent-framework-response.json'); +const suggestionJson = require('../fixtures/plugins/dashboards-assistant/suggestion-response.json'); + +const MATCH_AGENT_FRAMEWORK_PROMPT = + 'Assistant is designed to be able to assist with a wide range of tasks'; +const MATCH_SUGGESTION_PROMPT = 'You are an AI that only speaks JSON'; + +const server = http.createServer((req, res) => { + // Set the content type to JSON + res.setHeader('Content-Type', 'application/json'); + + let requestBody = ''; + + // Listen for data events to capture the request body + req.on('data', (chunk) => { + requestBody += chunk; + }); + + // Listen for the end of the request + req.on('end', () => { + try { + // Why add a delay here? reference: https://github.com/opensearch-project/ml-commons/issues/1894 + setTimeout(() => { + if (requestBody.includes(MATCH_AGENT_FRAMEWORK_PROMPT)) { + return res.end(JSON.stringify(agentFrameworkJson)); + } else if (requestBody.includes(MATCH_SUGGESTION_PROMPT)) { + return res.end(JSON.stringify(suggestionJson)); + } + + res.end(''); + }, 100); + } catch (error) { + // Handle JSON parsing errors + res.statusCode = 400; + res.end(JSON.stringify({ error: 'Invalid JSON in the request body' })); + } + }); +}); + +// Listen on port 3000 +const PORT = 3000; +server.listen(PORT, () => { + console.log(`Server is listening on port ${PORT}`); +}); diff --git a/cypress/support/index.js b/cypress/support/index.js index 6b13ed838..d747f9873 100644 --- a/cypress/support/index.js +++ b/cypress/support/index.js @@ -30,6 +30,7 @@ import '../utils/plugins/alerting-dashboards-plugin/commands'; import '../utils/plugins/ml-commons-dashboards/commands'; import '../utils/plugins/security-analytics-dashboards-plugin/commands'; import '../utils/plugins/notifications-dashboards/commands'; +import '../utils/plugins/dashboards-assistant/commands'; import 'cypress-real-events'; @@ -56,3 +57,19 @@ if (Cypress.env('ENDPOINT_WITH_PROXY')) { Cypress.Cookies.preserveOnce('security_authentication'); }); } + +/** + * Make setup step in here so that all the test files in dashboards-assistant + * won't need to call these commands. + */ +if (Cypress.env('DASHBOARDS_ASSISTANT_ENABLED')) { + before(() => { + cy.addAssistantRequiredSettings(); + cy.registerRootAgent(); + cy.startDummyServer(); + }); + after(() => { + cy.cleanRootAgent(); + cy.stopDummyServer(); + }); +} diff --git a/cypress/utils/plugins/dashboards-assistant/commands.js b/cypress/utils/plugins/dashboards-assistant/commands.js new file mode 100644 index 000000000..51df1be8a --- /dev/null +++ b/cypress/utils/plugins/dashboards-assistant/commands.js @@ -0,0 +1,154 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import FlowTemplateJSON from '../../../fixtures/plugins/dashboards-assistant/flow-template.json'; +import { BACKEND_BASE_PATH } from '../../constants'; +import { ML_COMMONS_API } from './constants'; +import clusterSettings from '../../../fixtures/plugins/dashboards-assistant/cluster_settings.json'; + +Cypress.Commands.add('addAssistantRequiredSettings', () => { + cy.request('PUT', `${BACKEND_BASE_PATH}/_cluster/settings`, clusterSettings); +}); + +const agentParameters = { + connectorId: '', + modelId: '', + conversationalAgentId: '', + rootAgentId: '', +}; + +Cypress.Commands.add('registerRootAgent', () => { + // ML needs 10 seconds to initialize its master key + // The ML encryption master key has not been initialized yet. Please retry after waiting for 10 seconds. + cy.wait(10000); + /** + * TODO use flow framework if the plugin get integrate in the future. + */ + // cy.request( + // 'POST', + // `${BACKEND_BASE_PATH}${FLOW_FRAMEWORK_API.CREATE_FLOW_TEMPLATE}`, + // FlowTemplateJSON + // ).then((resp) => { + // usingWorkflowId = resp.body.workflow_id; + // if (usingWorkflowId) { + // cy.request( + // 'POST', + // `${BACKEND_BASE_PATH}${FLOW_FRAMEWORK_API.CREATE_FLOW_TEMPLATE}/${usingWorkflowId}/_provision` + // ); + // /** + // * wait for 2s + // */ + // cy.wait(2000); + // } else { + // throw new Error(resp); + // } + // }); + const nodesMap = {}; + FlowTemplateJSON.workflows.provision.nodes.forEach((node) => { + nodesMap[node.type] = nodesMap[node.type] || []; + nodesMap[node.type].push(node); + }); + cy.request( + 'POST', + `${BACKEND_BASE_PATH}${ML_COMMONS_API.CREATE_CONNECTOR}`, + nodesMap.create_connector[0].user_inputs + ) + .then((resp) => { + agentParameters.connectorId = resp.body.connector_id; + return cy.request( + 'POST', + `${BACKEND_BASE_PATH}${ML_COMMONS_API.CREATE_MODEL}?deploy=true`, + { + ...nodesMap.register_remote_model[0].user_inputs, + connector_id: agentParameters.connectorId, + function_name: 'remote', + } + ); + }) + .then((resp) => { + agentParameters.modelId = resp.body.model_id; + return cy.request( + 'POST', + `${BACKEND_BASE_PATH}${ML_COMMONS_API.CREATE_AGENT}`, + { + ...nodesMap.register_agent[0].user_inputs, + llm: { + parameters: + nodesMap.register_agent[0].user_inputs['llm.parameters'], + model_id: agentParameters.modelId, + }, + tools: [nodesMap.create_tool[0]].map((item) => item.user_inputs), + } + ); + }) + .then((resp) => { + agentParameters.conversationalAgentId = resp.body.agent_id; + return cy.request( + 'POST', + `${BACKEND_BASE_PATH}${ML_COMMONS_API.CREATE_AGENT}`, + { + ...nodesMap.register_agent[1].user_inputs, + tools: [ + { + ...nodesMap.create_tool[1].user_inputs, + parameters: { + ...nodesMap.create_tool[1].user_inputs.parameters, + agent_id: agentParameters.conversationalAgentId, + }, + }, + { + ...nodesMap.create_tool[2].user_inputs, + parameters: { + ...nodesMap.create_tool[2].user_inputs.parameters, + model_id: agentParameters.modelId, + }, + }, + ], + } + ); + }) + .then((resp) => { + agentParameters.rootAgentId = resp.body.agent_id; + }); +}); + +Cypress.Commands.add('cleanRootAgent', () => { + return; + /** + * TODO wait for flow framework to be built into snapshot. + */ + // cy.request( + // 'POST', + // `${BACKEND_BASE_PATH}${FLOW_FRAMEWORK_API.CREATE_FLOW_TEMPLATE}/${usingWorkflowId}/_deprovision` + // ); + // /** + // * wait for 2s + // */ + // cy.wait(2000); +}); + +Cypress.Commands.add('startDummyServer', () => { + // Not a good practice to start a server inside Cypress https://docs.cypress.io/guides/references/best-practices#Web-Servers + // But in out case, we need to reuse release e2e template and let's make it a tradeoff. + cy.exec(`nohup yarn start-dummy-llm-server > /dev/null 2>&1 &`); +}); + +Cypress.Commands.add('stopDummyServer', () => { + /** + * For windows and Linux + */ + cy.exec(`netstat -ano | grep "3000" | awk '{print $5}' | xargs kill -9`, { + failOnNonZeroExit: false, + }).then((result) => { + if (result.stderr) { + /** + * For Macos + */ + cy.exec(`lsof -ti :3000 -sTCP:LISTEN | xargs kill`, { + failOnNonZeroExit: false, + }); + } + }); +}); diff --git a/cypress/utils/plugins/dashboards-assistant/constants.js b/cypress/utils/plugins/dashboards-assistant/constants.js new file mode 100644 index 000000000..16592accb --- /dev/null +++ b/cypress/utils/plugins/dashboards-assistant/constants.js @@ -0,0 +1,17 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +// export const WORKFLOW_API_PREFIX = '/_plugins/_flow_framework/workflow'; +export const ML_COMMONS_API_PREFIX = '/_plugins/_ml'; + +// export const FLOW_FRAMEWORK_API = { +// CREATE_FLOW_TEMPLATE: WORKFLOW_API_PREFIX, +// }; + +export const ML_COMMONS_API = { + CREATE_CONNECTOR: `${ML_COMMONS_API_PREFIX}/connectors/_create`, + CREATE_MODEL: `${ML_COMMONS_API_PREFIX}/models/_register`, + CREATE_AGENT: `${ML_COMMONS_API_PREFIX}/agents/_register`, +}; diff --git a/package.json b/package.json index 19b3ea8e9..ee6bd4bc8 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "osd:ciGroup6": "echo \"apps/data_explorer/aaa_before.spec.js,apps/data_explorer/date_nanos_mixed.spec.js,apps/data_explorer/date_nanos.spec.js,apps/data_explorer/discover_histogram.spec.js,apps/data_explorer/discover.spec.js,apps/data_explorer/zzz_after.spec.js\"", "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: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\"", + "start-dummy-llm-server": "node ./cypress/support/assistant-dummy-llm.js" }, "repository": { "type": "git", From 8b797224e34bdf0955be14c6553ea1699d17923d Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Tue, 23 Jan 2024 22:57:40 +0800 Subject: [PATCH 16/21] feat: add test map for dashboards-assistant (#1005) Signed-off-by: SuZhou-Joe --- test_finder.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/test_finder.sh b/test_finder.sh index ee4314641..35b9c5238 100755 --- a/test_finder.sh +++ b/test_finder.sh @@ -22,6 +22,7 @@ OSD_COMPONENT_TEST_MAP=( "OpenSearch-Dashboards:opensearch-dashboards" "searchRelevanceDashboards:search-relevance-dashboards" "mlCommonsDashboards:ml-commons-dashboards" "securityAnalyticsDashboards:security-analytics-dashboards-plugin" + "assistantDashboards:dashboards-assistant" ) if [ -z $TEST_TYPE ]; then From a1d3ca1ecef3e25777dbb850793db72d506f22f6 Mon Sep 17 00:00:00 2001 From: Shenoy Pratik Date: Thu, 25 Jan 2024 06:54:20 +0530 Subject: [PATCH 17/21] Update notebooks tests (#1001) * add notebooks tests Signed-off-by: Shenoy Pratik * remove explicit wait on page load Signed-off-by: Shenoy Pratik --------- Signed-off-by: Shenoy Pratik --- .../6_notebooks.spec.js | 229 +++++++++--------- .../observability-dashboards/constants.js | 4 + 2 files changed, 125 insertions(+), 108 deletions(-) diff --git a/cypress/integration/plugins/observability-dashboards/6_notebooks.spec.js b/cypress/integration/plugins/observability-dashboards/6_notebooks.spec.js index e8ba8d56c..49a4dc7e9 100644 --- a/cypress/integration/plugins/observability-dashboards/6_notebooks.spec.js +++ b/cypress/integration/plugins/observability-dashboards/6_notebooks.spec.js @@ -6,18 +6,28 @@ /// import { - delayTime, + SAMPLE_SQL_QUERY, TEST_NOTEBOOK, SAMPLE_URL, - SQL_QUERY_TEXT, - PPL_QUERY_TEXT, BASE_PATH, + delayTime, + MARKDOWN_TEXT, } from '../../../utils/constants'; +import { skipOn } from '@cypress/skip-test'; + +const moveToNotebookHome = () => { + cy.visit(`${BASE_PATH}/app/observability-notebooks#/`); +}; + const moveToTestNotebook = () => { cy.visit(`${BASE_PATH}/app/observability-notebooks#/`, { timeout: delayTime * 3, }); + + // Reload page to load notebooks if they are not flushed in OpenSearch index yet. + cy.reload(); + cy.get('.euiTableCellContent') .contains(TEST_NOTEBOOK, { timeout: delayTime * 3, @@ -25,138 +35,141 @@ const moveToTestNotebook = () => { .click(); }; -describe('Testing paragraphs', () => { +describe('Testing notebook actions', () => { + before(() => { + moveToNotebookHome(); + cy.get('a[data-test-subj="createNotebookPrimaryBtn"]').click(); + cy.get('input[data-test-subj="custom-input-modal-input"]').focus(); + cy.get('input[data-test-subj="custom-input-modal-input"]').type( + TEST_NOTEBOOK + ); + cy.get( + 'button[data-test-subj="custom-input-modal-confirm-button"]' + ).click(); + cy.get('h1[data-test-subj="notebookTitle"]') + .contains(TEST_NOTEBOOK) + .should('exist'); + }); + beforeEach(() => { moveToTestNotebook(); }); + it('Creates a code paragraph', () => { + cy.get('button[data-test-subj="emptyNotebookAddCodeBlockBtn"]').click(); + cy.get('textarea[data-test-subj="editorArea-0"]').should('exist'); + cy.get('button[data-test-subj="runRefreshBtn-0"]').contains('Run').click(); + cy.get('div[data-test-subj="paragraphInputErrorText"]') + .contains('Input is required.') + .should('exist'); + }); + it('Renders markdown', () => { - cy.get('.euiTextArea').should('not.exist'); + cy.get('button[data-test-subj="paragraphToggleInputBtn"]').click(); + cy.get('.euiCodeBlock').click(); + cy.get('textarea[data-test-subj="editorArea-0"]').clear(); + cy.get('textarea[data-test-subj="editorArea-0"]').focus(); + cy.get('textarea[data-test-subj="editorArea-0"]').type(MARKDOWN_TEXT); + + cy.get('button[data-test-subj="runRefreshBtn-0"]').click(); + cy.get('textarea[data-test-subj="editorArea-0"]').should('not.exist'); cy.get(`a[href="${SAMPLE_URL}"]`).should('exist'); cy.get('code').contains('POST').should('exist'); cy.get('td').contains('b2').should('exist'); }); - it('Shows output message', () => { - cy.get('button[aria-label="Toggle show input"]').click(); - cy.wait(delayTime); - cy.get('.euiTextColor').contains('Last successful run').should('exist'); - - cy.get('pre.input').eq(0).click(); - cy.wait(delayTime); - cy.get('.euiTextArea').type('Another text'); - cy.wait(delayTime); + it('Adds a SQL query paragraph', () => { + cy.get('button[data-test-subj="AddParagraphButton"]').click(); + cy.get('button[data-test-subj="AddCodeBlockBtn"]').click(); - cy.get('.euiTextColor').contains('Last successful run').should('exist'); - }); + cy.get('textarea[data-test-subj="editorArea-1"]').clear(); + cy.get('textarea[data-test-subj="editorArea-1"]').focus(); + cy.get('textarea[data-test-subj="editorArea-1"]').type(SAMPLE_SQL_QUERY); + cy.get('button[data-test-subj="runRefreshBtn-1"]').click(); - it('Duplicates paragraphs', () => { - cy.get('.euiButtonIcon[aria-label="Open paragraph menu"]').eq(0).click(); - cy.wait(delayTime); - cy.get('.euiContextMenuItem__text').contains('Duplicate').eq(0).click(); - cy.wait(delayTime); - cy.get('.euiButton__text').contains('Run').click(); - cy.wait(delayTime); + cy.get('textarea[data-test-subj="editorArea-1"]').should('not.exist'); + cy.get('div[data-test-subj="queryOutputText"]') + .contains('select 1') + .should('exist'); - cy.get(`a[href="${SAMPLE_URL}"]`).should('have.length.gte', 2); + cy.get('.euiDataGrid__overflow').should('exist'); }); +}); - it('Adds a dashboards visualization paragraph', () => { - cy.contains('Add paragraph').click(); - cy.wait(delayTime); - cy.get('.euiContextMenuItem__text').contains('Visualization').click(); - cy.wait(delayTime); - - cy.get('.euiButton__text').contains('Run').click(); - cy.wait(delayTime); - cy.get('.euiTextColor') - .contains('Visualization is required.') +describe('Test reporting integration if plugin installed', () => { + beforeEach(() => { + moveToNotebookHome(); + cy.get('.euiTableCellContent').contains(TEST_NOTEBOOK).click(); + cy.get('h1[data-test-subj="notebookTitle"]') + .contains(TEST_NOTEBOOK) .should('exist'); - - cy.get('.euiButton__text').contains('Browse').click(); - cy.wait(delayTime); - cy.get('.euiFieldSearch') - .focus() - .type('[Flights] Flight Count and Average Ticket Price{enter}'); - cy.wait(delayTime); - cy.get('.euiButton__text').contains('Select').click(); - cy.wait(delayTime); - cy.get('.euiButton__text').contains('Run').click(); - cy.wait(delayTime); - cy.get('div.visualization').should('exist'); + cy.get('body').then(($body) => { + skipOn($body.find('#reportingActionsButton').length <= 0); + }); }); - it('Adds a SQL query paragraph', () => { - cy.contains('Add paragraph').click(); - cy.wait(delayTime); - cy.get('.euiContextMenuItem__text').contains('Code block').click(); - cy.wait(delayTime); - - cy.get('.euiTextArea').type(SQL_QUERY_TEXT); - cy.wait(delayTime); - cy.get('.euiButton__text').contains('Run').click(); - cy.wait(delayTime * 5); - - cy.get('b').contains( - 'select * from opensearch_dashboards_sample_data_flights limit 20' - ); - - cy.get('.euiDataGrid__overflow').should('exist'); + it('Create in-context PDF report from notebook', () => { + cy.get('#reportingActionsButton').click(); + cy.get('button.euiContextMenuItem:nth-child(1)') + .contains('Download PDF') + .click(); + cy.get('#downloadInProgressLoadingModal').should('exist'); }); - it('Adds a PPL query paragraph', () => { - cy.contains('Add paragraph').click(); - cy.wait(delayTime); - cy.get('.euiContextMenuItem__text').contains('Code block').click(); - cy.wait(delayTime); - - cy.get('.euiTextArea').type(PPL_QUERY_TEXT); - cy.wait(delayTime); - cy.get('.euiButton__text').contains('Run').click(); - cy.wait(delayTime * 5); - - cy.get('b').contains('source=opensearch_dashboards_sample_data_flights'); - - cy.get('.euiDataGrid__overflow').should('exist'); + it('Create in-context PNG report from notebook', () => { + cy.get('#reportingActionsButton').click(); + cy.get('button.euiContextMenuItem:nth-child(2)') + .contains('Download PNG') + .click(); + cy.get('#downloadInProgressLoadingModal').should('exist'); }); - it('Runs all paragraphs', () => { - cy.wait(delayTime * 3); // need to wait for paragraphs to load first - cy.get('[data-test-subj="notebook-paragraph-actions-button"]').click(); - cy.wait(delayTime); - cy.get('.euiContextMenuItem__text').contains('Run all paragraphs').click(); - cy.wait(delayTime); - - cy.get(`a[href="${SAMPLE_URL}"]`).should('exist'); + it('Create on-demand report definition from context menu', () => { + cy.get('#reportingActionsButton').click(); + cy.get('button.euiContextMenuItem:nth-child(3)') + .contains('Create report definition') + .click(); + cy.location('pathname', { timeout: delayTime * 3 }).should( + 'include', + '/reports-dashboards' + ); + cy.get('#reportSettingsName').type('Create notebook on-demand report'); + cy.get('#createNewReportDefinition').click({ force: true }); }); - it('Deletes paragraphs', () => { - cy.wait(delayTime * 3); - cy.get('[data-test-subj="notebook-paragraph-actions-button"]').click(); - cy.wait(delayTime); - cy.get('.euiContextMenuItem__text') - .contains('Delete all paragraphs') + it('View reports homepage from context menu', () => { + cy.get('#reportingActionsButton').click(); + cy.get('button.euiContextMenuItem:nth-child(4)') + .contains('View reports') .click(); - cy.wait(delayTime); - cy.get('.euiButton__text').contains('Delete').click(); - cy.wait(delayTime); - - cy.get('.euiTextAlign').contains('No paragraphs').should('exist'); + cy.location('pathname', { timeout: delayTime * 3 }).should( + 'include', + '/reports-dashboards' + ); }); +}); +describe('clean up all test data', () => { it('Cleans up test notebooks', () => { - cy.get('[data-test-subj="notebook-notebook-actions-button"]').click(); - cy.wait(delayTime); - cy.get('.euiContextMenuItem__text').contains('Delete notebook').click(); - cy.wait(delayTime); - - cy.get('button.euiButton--danger').should('be.disabled'); - - cy.get('input.euiFieldText[placeholder="delete"]').type('delete'); - cy.get('button.euiButton--danger').should('not.be.disabled'); - cy.get('.euiButton__text').contains('Delete').click(); - cy.wait(delayTime * 3); - - cy.get('.euiText').contains('No notebooks').should('exist'); + moveToNotebookHome(); + cy.get('input[data-test-subj="checkboxSelectAll"]').click(); + cy.get('button[data-test-subj="notebookTableActionBtn"]').click(); + cy.get('button[data-test-subj="deleteNotebookBtn"]').click(); + cy.get( + 'button[data-test-subj="delete-notebook-modal-delete-button"]' + ).should('be.disabled'); + + cy.get('input[data-test-subj="delete-notebook-modal-input"]').focus(); + cy.get('input[data-test-subj="delete-notebook-modal-input"]').type( + 'delete' + ); + cy.get( + 'button[data-test-subj="delete-notebook-modal-delete-button"]' + ).should('not.be.disabled'); + cy.get( + 'button[data-test-subj="delete-notebook-modal-delete-button"]' + ).click(); + moveToNotebookHome(); + cy.get('div[data-test-subj="notebookEmptyTableText"]').should('exist'); }); }); diff --git a/cypress/utils/plugins/observability-dashboards/constants.js b/cypress/utils/plugins/observability-dashboards/constants.js index 4b9ace2c3..72487eb8b 100644 --- a/cypress/utils/plugins/observability-dashboards/constants.js +++ b/cypress/utils/plugins/observability-dashboards/constants.js @@ -111,6 +111,10 @@ POST _plugins/_sql/_explain | a3 | b3 | c3 | d3 | `; +export const SAMPLE_SQL_QUERY = `%sql +select 1 +`; + export const SQL_QUERY_TEXT = `%sql select * from opensearch_dashboards_sample_data_flights limit 20 `; From 26ab107182b16246afdde786e15e33cab38f3cb3 Mon Sep 17 00:00:00 2001 From: Eric Wei Date: Mon, 29 Jan 2024 19:28:22 -0800 Subject: [PATCH 18/21] Add tests for data source selector (#965) * add tests for data source selector Signed-off-by: Eric * add global tenant Signed-off-by: Eric * add to ciGroup Signed-off-by: Eric --------- Signed-off-by: Eric --- .../data_source_selector.spec.js | 90 +++++++++++++++++++ package.json | 2 +- 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/data_source_selector.spec.js diff --git a/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/data_source_selector.spec.js b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/data_source_selector.spec.js new file mode 100644 index 000000000..3b5916d0f --- /dev/null +++ b/cypress/integration/core-opensearch-dashboards/opensearch-dashboards/apps/data_explorer/data_source_selector.spec.js @@ -0,0 +1,90 @@ +/* + * 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') +); + +describe('Data source selector', () => { + before(() => { + CURRENT_TENANT.newTenant = 'global'; + testFixtureHandler.importJSONMapping( + 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/index_pattern_without_timefield/mappings.json.txt' + ); + testFixtureHandler.importJSONDoc( + 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/index_pattern_without_timefield/data.json.txt' + ); + + miscUtils.visitPage('app/data-explorer/discover#/'); + cy.waitForLoader(); + }); + + after(() => { + testFixtureHandler.clearJSONMapping( + 'cypress/fixtures/dashboard/opensearch_dashboards/data_explorer/index_pattern_without_timefield/mappings.json.txt' + ); + cy.deleteSavedObjectByType('index-pattern'); + }); + + it('displays all data sources by default', () => { + cy.get('[data-test-subj="dataExplorerDSSelect"]').click(); + cy.get('.euiComboBoxOptionsList').should('exist'); + cy.get('.euiComboBoxOption__content').should('have.length', 2); + }); + + it('filters options based on user input', () => { + cy.get('[data-test-subj="dataExplorerDSSelect"] input').type('without', { + force: true, + }); + cy.get('.euiComboBoxOption__content').should('have.length', 1); + cy.get('.euiComboBoxOption__content') + .first() + .should('contain', 'without-timefield'); + }); + + it('updates the visual length of the dropdown based on filtered results', () => { + cy.get('[data-test-subj="dataExplorerDSSelect"] input').clear({ + force: true, + }); + cy.get('[data-test-subj="dataExplorerDSSelect"] input').type( + 'without-timefield', + { + force: true, + } + ); + cy.get('.euiComboBoxOptionsList').then(($listAfterFilter) => { + const heightAfterFilter = $listAfterFilter.height(); + cy.get('[data-test-subj="dataExplorerDSSelect"] input').clear({ + force: true, + }); + cy.get('.euiComboBoxOptionsList').should(($listAll) => { + expect($listAll.height()).to.be.greaterThan(heightAfterFilter); + }); + }); + }); + + it('selects the correct option when clicked', () => { + cy.get('[data-test-subj="dataExplorerDSSelect"] input').type( + 'with-timefield', + { + force: true, + } + ); + + cy.contains('.euiComboBoxOption__content', 'with-timefield').click(); + cy.get('[data-test-subj="dataExplorerDSSelect"] .euiComboBoxPill').should( + 'contain', + 'with-timefield' + ); + }); +}); diff --git a/package.json b/package.json index ee6bd4bc8..e34026091 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "osd:ciGroup3": "echo \"apps/vis-augmenter/*.js\"", "osd:ciGroup4": "echo \"dashboard_sample_data_with_datasource_spec.js,dashboard_sanity_test_spec.js\"", "osd:ciGroup5": "echo \"datasource-management-plugin/*.js\"", - "osd:ciGroup6": "echo \"apps/data_explorer/aaa_before.spec.js,apps/data_explorer/date_nanos_mixed.spec.js,apps/data_explorer/date_nanos.spec.js,apps/data_explorer/discover_histogram.spec.js,apps/data_explorer/discover.spec.js,apps/data_explorer/zzz_after.spec.js\"", + "osd:ciGroup6": "echo \"apps/data_explorer/aaa_before.spec.js,apps/data_explorer/data_source_selector.spec.js,apps/data_explorer/date_nanos_mixed.spec.js,apps/data_explorer/date_nanos.spec.js,apps/data_explorer/discover_histogram.spec.js,apps/data_explorer/discover.spec.js,apps/data_explorer/zzz_after.spec.js\"", "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\"", From 32cba8323cc07910b2e9c7babc8dc3b424adc684 Mon Sep 17 00:00:00 2001 From: Hailong Cui Date: Tue, 30 Jan 2024 14:44:43 +0800 Subject: [PATCH 19/21] Add functional test for dashboard assistant trace page (#1012) * Add functional test for trace page Signed-off-by: Hailong Cui * update to ask question direclty instead of click Signed-off-by: Hailong Cui * replace focus with click Signed-off-by: Hailong Cui * add wait before input Signed-off-by: Hailong Cui * address review comments Signed-off-by: Hailong Cui --------- Signed-off-by: Hailong Cui --- .../agent-framework-thought-response.json | 5 + .../chatbot_agent_framework_spec.js | 10 +- .../chatbot_interaction_trace_spec.js | 104 ++++++++++++++++++ cypress/support/assistant-dummy-llm.js | 8 +- 4 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 cypress/fixtures/plugins/dashboards-assistant/agent-framework-thought-response.json create mode 100644 cypress/integration/plugins/dashboards-assistant/chatbot_interaction_trace_spec.js diff --git a/cypress/fixtures/plugins/dashboards-assistant/agent-framework-thought-response.json b/cypress/fixtures/plugins/dashboards-assistant/agent-framework-thought-response.json new file mode 100644 index 000000000..3ce8aa6b0 --- /dev/null +++ b/cypress/fixtures/plugins/dashboards-assistant/agent-framework-thought-response.json @@ -0,0 +1,5 @@ +{ + "completion": " ```json\n{\n \"thought\": \"Thought: Let me use tool to figure out\",\n \"action\": \"CatIndexTool\",\n \"action_input\": \"\"}\n```\n", + "stop_reason": "stop_sequence", + "stop": "\n\nHuman:" +} \ No newline at end of file diff --git a/cypress/integration/plugins/dashboards-assistant/chatbot_agent_framework_spec.js b/cypress/integration/plugins/dashboards-assistant/chatbot_agent_framework_spec.js index f56244401..82e26c306 100644 --- a/cypress/integration/plugins/dashboards-assistant/chatbot_agent_framework_spec.js +++ b/cypress/integration/plugins/dashboards-assistant/chatbot_agent_framework_spec.js @@ -26,11 +26,11 @@ if (Cypress.env('DASHBOARDS_ASSISTANT_ENABLED')) { describe('Interact with Agent framework', () => { it('toggle Chatbot and enable to interact', () => { - // enable to toggle and show Chatbot - cy.get(`img[aria-label="toggle chat flyout icon"]`).click(); - - // click suggestions to generate response - cy.contains('What are the indices in my cluster?').click(); + // input question + cy.wait(1000); + cy.get(`input[placeholder="Ask question"]`) + .click() + .type('What are the indices in my cluster?{enter}'); // should have a LLM Response cy.contains( diff --git a/cypress/integration/plugins/dashboards-assistant/chatbot_interaction_trace_spec.js b/cypress/integration/plugins/dashboards-assistant/chatbot_interaction_trace_spec.js new file mode 100644 index 000000000..3b11bb8da --- /dev/null +++ b/cypress/integration/plugins/dashboards-assistant/chatbot_interaction_trace_spec.js @@ -0,0 +1,104 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { BASE_PATH } from '../../../utils/constants'; + +if (Cypress.env('DASHBOARDS_ASSISTANT_ENABLED')) { + describe('Interaction trace spec', () => { + before(() => { + // Set welcome screen tracking to false + localStorage.setItem('home:welcome:show', 'false'); + // Set new theme modal to false + localStorage.setItem('home:newThemeModal:show', 'false'); + + cy.visit(`${BASE_PATH}/app/home`); + // cy.waitForLoader(); + + // Common text to wait for to confirm page loaded, give up to 120 seconds for initial load + cy.get(`input[placeholder="Ask question"]`, { timeout: 120000 }).as( + 'chatInput' + ); + cy.get('@chatInput').should('be.length', 1); + + cy.wait(1000); + + cy.get('@chatInput') + .click() + .type('What are the indices in my cluster?{enter}'); + + // should have a LLM Response + cy.contains( + 'The indices in your cluster are the names listed in the response obtained from using a tool to get information about the OpenSearch indices.' + ); + }); + + // clean up localStorage items + after(() => { + localStorage.removeItem('home:welcome:show'); + localStorage.removeItem('home:newThemeModal:show'); + }); + + describe('Trace page', () => { + it('open trace page and verify page content', () => { + // click How was this generated? to view trace + cy.contains('How was this generated?').click(); + + cy.get(`.llm-chat-flyout .llm-chat-flyout-body`).as('tracePage'); + cy.get('@tracePage') + .find(`button[aria-label="back"]`) + .should('have.length', 1); + + cy.get('@tracePage') + .find(`button[aria-label="close"]`) + .should('have.length', 0); + + // title + cy.get('@tracePage').contains('h1', 'How was this generated'); + + // question + cy.get('@tracePage').contains('What are the indices in my cluster?'); + + // result + cy.get('@tracePage').contains( + 'The indices in your cluster are the names listed in the response obtained from using a tool to get information about the OpenSearch indices.' + ); + }); + + it('tools invocation displayed in trace steps', () => { + // trace + cy.get(`.llm-chat-flyout .llm-chat-flyout-body`).as('tracePage'); + cy.get('@tracePage').find('.euiAccordion').should('have.length', 1); + + cy.get('@tracePage') + .find('.euiAccordion') + // tool name + .contains('Step 1 - CatIndexTool') + .click({ force: true }); + + // tool output + cy.contains('Output: health status index'); + }); + + it('trace page display correctly in fullscreen mode', () => { + cy.get(`.llm-chat-flyout-header`) + .find(`button[aria-label="fullScreen"]`) + .click({ force: true }); + + // show close button + cy.get(`.llm-chat-flyout .llm-chat-flyout-body`).as('tracePage'); + cy.get('@tracePage') + .find(`button[aria-label="close"]`) + .should('have.length', 1); + + cy.get('@tracePage') + .find(`button[aria-label="back"]`) + .should('have.length', 0); + + // both chat and trace are both displayed + cy.contains('How was this generated?').click(); + }); + }); + }); +} diff --git a/cypress/support/assistant-dummy-llm.js b/cypress/support/assistant-dummy-llm.js index 1000453f8..930f6b223 100644 --- a/cypress/support/assistant-dummy-llm.js +++ b/cypress/support/assistant-dummy-llm.js @@ -4,11 +4,13 @@ */ const http = require('http'); const agentFrameworkJson = require('../fixtures/plugins/dashboards-assistant/agent-framework-response.json'); +const agentFrameworkThoughtJson = require('../fixtures/plugins/dashboards-assistant/agent-framework-thought-response.json'); const suggestionJson = require('../fixtures/plugins/dashboards-assistant/suggestion-response.json'); const MATCH_AGENT_FRAMEWORK_PROMPT = 'Assistant is designed to be able to assist with a wide range of tasks'; const MATCH_SUGGESTION_PROMPT = 'You are an AI that only speaks JSON'; +const TOOL_RESPONSE = 'TOOL RESPONSE:'; const server = http.createServer((req, res) => { // Set the content type to JSON @@ -27,7 +29,11 @@ const server = http.createServer((req, res) => { // Why add a delay here? reference: https://github.com/opensearch-project/ml-commons/issues/1894 setTimeout(() => { if (requestBody.includes(MATCH_AGENT_FRAMEWORK_PROMPT)) { - return res.end(JSON.stringify(agentFrameworkJson)); + if (requestBody.includes(TOOL_RESPONSE)) { + return res.end(JSON.stringify(agentFrameworkJson)); + } else { + return res.end(JSON.stringify(agentFrameworkThoughtJson)); + } } else if (requestBody.includes(MATCH_SUGGESTION_PROMPT)) { return res.end(JSON.stringify(suggestionJson)); } From 98ec499d5eb5b9119b7227f6f6b5f6964dabe830 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Mon, 29 Jan 2024 23:22:04 -0800 Subject: [PATCH 20/21] Add minimal Cypress tests for integrations (#990) * Add tests for integrations Signed-off-by: Simeon Widdis * Add check for test instance page opening Signed-off-by: Simeon Widdis * Empty commit to re-trigger run Signed-off-by: Simeon Widdis * Decouple integrations add and search tests Signed-off-by: Simeon Widdis * Move instance name constant to test Signed-off-by: Simeon Widdis * Add integrations teardown process Signed-off-by: Simeon Widdis --------- Signed-off-by: Simeon Widdis --- .../7_integrations.spec.js | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 cypress/integration/plugins/observability-dashboards/7_integrations.spec.js diff --git a/cypress/integration/plugins/observability-dashboards/7_integrations.spec.js b/cypress/integration/plugins/observability-dashboards/7_integrations.spec.js new file mode 100644 index 000000000..2baefcff6 --- /dev/null +++ b/cypress/integration/plugins/observability-dashboards/7_integrations.spec.js @@ -0,0 +1,108 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/// + +import { BASE_PATH } from '../../../utils/base_constants'; + +const moveToAvailableNginxIntegration = () => { + cy.visit(`${BASE_PATH}/app/integrations#/available/nginx`); +}; + +const moveToAddedIntegrations = () => { + cy.visit(`${BASE_PATH}/app/integrations#/installed`); +}; + +const createSamples = () => { + moveToAvailableNginxIntegration(); + cy.get('[data-test-subj="try-it-button"]').click(); + cy.get('.euiToastHeader__title').should('contain', 'successfully'); +}; + +const integrationsTeardown = () => { + // Delete all integration instances + cy.request({ + method: 'GET', + form: false, + url: `api/integrations/store`, + headers: { + 'content-type': 'application/json;charset=UTF-8', + 'osd-xsrf': true, + }, + }).then((response) => { + for (const instance of response.body.data.hits) { + cy.request({ + method: 'DELETE', + url: `/api/integrations/store/${instance.id}`, + headers: { + 'content-type': 'application/json;charset=UTF-8', + 'osd-xsrf': true, + }, + }); + } + }); + // Also clean up indices + cy.request({ + method: 'POST', + form: false, + url: 'api/console/proxy', + headers: { + 'content-type': 'application/json;charset=UTF-8', + 'osd-xsrf': true, + }, + qs: { + path: `ss4o_logs-nginx-*`, // All tests work with ss4o nginx data + method: 'DELETE', + }, + body: '{}', + }); +}; + +describe('Add nginx integration instance flow', () => { + beforeEach(() => { + createSamples(); + }); + + afterEach(() => { + integrationsTeardown(); + }); + + it('Navigates to nginx page and triggers the adds the instance flow', () => { + const testInstanceName = 'test_integration_cypress'; + moveToAvailableNginxIntegration(); + cy.get('[data-test-subj="add-integration-button"]').click(); + cy.get('[data-test-subj="new-instance-name"]').should( + 'have.value', + 'nginx Integration' + ); + cy.get('[data-test-subj="create-instance-button"]').should('be.disabled'); + // Modifies the name of the integration + cy.get('[data-test-subj="new-instance-name"]').clear(); + cy.get('[data-test-subj="new-instance-name"]').type(testInstanceName); + // Validates the created sample index + cy.get('[data-test-subj="data-source-name"]').type( + 'ss4o_logs-nginx-sample-sample{enter}' + ); + cy.get('[data-test-subj="create-instance-button"]').click(); + cy.get('[data-test-subj="eventHomePageTitle"]').should( + 'contain', + testInstanceName + ); + }); + + it('Navigates to installed integrations page and verifies that installed integration exists', () => { + const sampleName = 'nginx-sample'; + moveToAddedIntegrations(); + cy.contains(sampleName).should('exist'); + cy.get('input[type="search"]').eq(0).focus(); + cy.get('input[type="search"]').eq(0).type(`${sampleName}{enter}`); + cy.get('.euiTableRow').should('have.length', 1); //Filters correctly to the test integration instance + cy.get(`[data-test-subj="${sampleName}IntegrationLink"]`).click(); + cy.get('[data-test-subj="eventHomePageTitle"]').should( + 'contain', + sampleName + ); + }); +}); From b5a0786c0d4050a50115df15ea36549ff96a74b6 Mon Sep 17 00:00:00 2001 From: Lin Wang Date: Wed, 31 Jan 2024 10:01:44 +0800 Subject: [PATCH 21/21] feat: add CYPRESS_NO_COMMAND_LOG to release signoff workflows (#1009) Signed-off-by: Lin Wang --- .github/workflows/release-signoff-chrome.yml | 2 ++ .github/workflows/release-signoff-chromium-ad-only.yml | 2 ++ .github/workflows/release-signoff-chromium-ism-only.yml | 2 ++ .../workflows/release-signoff-chromium-tests-in-memory-0.yml | 2 ++ .../workflows/release-signoff-chromium-tests-in-memory-10.yml | 2 ++ .../workflows/release-signoff-chromium-tests-in-memory-20.yml | 2 ++ .../workflows/release-signoff-chromium-tests-in-memory-5.yml | 2 ++ .github/workflows/release-signoff-chromium.yml | 2 ++ .github/workflows/release-signoff-electron.yml | 2 ++ .github/workflows/release-signoff-firefox.yml | 2 ++ 10 files changed, 20 insertions(+) diff --git a/.github/workflows/release-signoff-chrome.yml b/.github/workflows/release-signoff-chrome.yml index 7fe376364..e6bdb4775 100644 --- a/.github/workflows/release-signoff-chrome.yml +++ b/.github/workflows/release-signoff-chrome.yml @@ -15,6 +15,8 @@ jobs: NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' # 2.12 onwards security demo configuration require a custom admin password OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' + # Disable command log to unhang + CYPRESS_NO_COMMAND_LOG: 1 steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium-ad-only.yml b/.github/workflows/release-signoff-chromium-ad-only.yml index 02a9b1eb0..d4db844d9 100644 --- a/.github/workflows/release-signoff-chromium-ad-only.yml +++ b/.github/workflows/release-signoff-chromium-ad-only.yml @@ -15,6 +15,8 @@ jobs: NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' # 2.12 onwards security demo configuration require a custom admin password OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' + # Disable command log to unhang + CYPRESS_NO_COMMAND_LOG: 1 steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium-ism-only.yml b/.github/workflows/release-signoff-chromium-ism-only.yml index 4abb54461..6f0d5d3d1 100644 --- a/.github/workflows/release-signoff-chromium-ism-only.yml +++ b/.github/workflows/release-signoff-chromium-ism-only.yml @@ -15,6 +15,8 @@ jobs: NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' # 2.12 onwards security demo configuration require a custom admin password OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' + # Disable command log to unhang + CYPRESS_NO_COMMAND_LOG: 1 steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml index 100d8b487..674c34d36 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-0.yml @@ -15,6 +15,8 @@ jobs: NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' # 2.12 onwards security demo configuration require a custom admin password OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' + # Disable command log to unhang + CYPRESS_NO_COMMAND_LOG: 1 steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml index d180e1a01..8501c9e80 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-10.yml @@ -15,6 +15,8 @@ jobs: NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' # 2.12 onwards security demo configuration require a custom admin password OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' + # Disable command log to unhang + CYPRESS_NO_COMMAND_LOG: 1 steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml index 5114ca711..2a71090f6 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-20.yml @@ -15,6 +15,8 @@ jobs: NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' # 2.12 onwards security demo configuration require a custom admin password OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' + # Disable command log to unhang + CYPRESS_NO_COMMAND_LOG: 1 steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml b/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml index 6a6c83d6f..66db12ab4 100644 --- a/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml +++ b/.github/workflows/release-signoff-chromium-tests-in-memory-5.yml @@ -15,6 +15,8 @@ jobs: NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' # 2.12 onwards security demo configuration require a custom admin password OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' + # Disable command log to unhang + CYPRESS_NO_COMMAND_LOG: 1 steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-chromium.yml b/.github/workflows/release-signoff-chromium.yml index 2e01bf67b..405cec501 100644 --- a/.github/workflows/release-signoff-chromium.yml +++ b/.github/workflows/release-signoff-chromium.yml @@ -15,6 +15,8 @@ jobs: NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' # 2.12 onwards security demo configuration require a custom admin password OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' + # Disable command log to unhang + CYPRESS_NO_COMMAND_LOG: 1 steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-electron.yml b/.github/workflows/release-signoff-electron.yml index d81a4acea..2270882ef 100644 --- a/.github/workflows/release-signoff-electron.yml +++ b/.github/workflows/release-signoff-electron.yml @@ -15,6 +15,8 @@ jobs: NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' # 2.12 onwards security demo configuration require a custom admin password OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' + # Disable command log to unhang + CYPRESS_NO_COMMAND_LOG: 1 steps: - name: Checkout functional-test uses: actions/checkout@v2 diff --git a/.github/workflows/release-signoff-firefox.yml b/.github/workflows/release-signoff-firefox.yml index add0895c9..340de6dc7 100644 --- a/.github/workflows/release-signoff-firefox.yml +++ b/.github/workflows/release-signoff-firefox.yml @@ -15,6 +15,8 @@ jobs: NODE_OPTIONS: '--max-old-space-size=6144 --dns-result-order=ipv4first' # 2.12 onwards security demo configuration require a custom admin password OPENSEARCH_INITIAL_ADMIN_PASSWORD: 'myStrongPassword123!' + # Disable command log to unhang + CYPRESS_NO_COMMAND_LOG: 1 steps: - name: Checkout functional-test uses: actions/checkout@v2