From 9a4912f87bbe76be1496c629475951df51c25ae6 Mon Sep 17 00:00:00 2001 From: Evelyn Tanigawa Murasaki Date: Sat, 14 Feb 2026 16:01:13 -0300 Subject: [PATCH 1/2] main into 419 and alerting conditional filtering --- web/cypress/configure-env.sh | 75 +- web/cypress/e2e/coo/01.coo_bvt.cy.ts | 4 +- web/cypress/e2e/coo/01.coo_ivt.cy.ts | 5 +- web/cypress/e2e/coo/02.acm_alerting_ui.cy.ts | 18 +- .../e2e/incidents/00.coo_incidents_e2e.cy.ts | 4 +- web/cypress/e2e/incidents/01.incidents.cy.ts | 2 +- .../02.incidents-mocking-example.cy.ts | 2 +- .../regression/01.reg_filtering.cy.ts | 4 +- .../02.reg_ui_charts_comprehensive.cy.ts | 2 +- .../03-04.reg_e2e_firing_alerts.cy.ts | 3 +- .../regression/03.reg_api_calls.cy.ts | 5 +- .../regression/04.reg_redux_effects.cy.ts | 6 +- web/cypress/e2e/monitoring/00.bvt_admin.cy.ts | 4 - web/cypress/e2e/monitoring/00.bvt_dev.cy.ts | 5 - .../regression/01.reg_alerts_admin.cy.ts | 5 - .../regression/01.reg_alerts_dev.cy.ts | 5 - .../regression/02.reg_metrics_admin_1.cy.ts | 8 - .../regression/02.reg_metrics_admin_2.cy.ts | 8 - .../03.reg_legacy_dashboards_admin.cy.ts | 9 +- ...es.cy.ts => 00.coo_bvt_perses_admin.cy.ts} | 7 +- .../perses/00.coo_bvt_perses_admin_1.cy.ts | 38 + .../e2e/perses/01.coo_list_perses_admin.cy.ts | 60 + .../e2e/perses/02.coo_edit_perses_admin.cy.ts | 44 + .../perses/03.coo_create_perses_admin.cy.ts | 44 + .../e2e/perses/99.coo_rbac_perses_user1.cy.ts | 78 + .../e2e/perses/99.coo_rbac_perses_user2.cy.ts | 78 + .../e2e/virtualization/00.coo_ivt.cy.ts | 1 - .../virtualization/01.coo_ivt_alerts.cy.ts | 1 - .../virtualization/04.coo_ivt_perses.cy.ts | 4 +- .../fixtures/coo/acm-alerrule-test.yaml | 2 +- web/cypress/fixtures/coo/acm-install.sh | 86 +- web/cypress/fixtures/coo/acm-uiplugin.yaml | 2 +- web/cypress/fixtures/coo/acm-uninstall.sh | 2 +- .../openshift-cluster-sample-dashboard.yaml | 0 .../dashboards}/perses-dashboard-sample.yaml | 0 .../prometheus-overview-variables.yaml | 0 .../thanos-compact-overview-1var.yaml | 0 .../thanos-querier-datasource.yaml | 0 .../openshift-cluster-sample-dashboard.yaml | 1041 ++++++++++++ .../dashboards/perses-dashboard-sample.yaml | 564 +++++++ .../prometheus-overview-variables.yaml | 461 ++++++ .../thanos-compact-overview-1var.yaml | 1421 +++++++++++++++++ .../dashboards/thanos-querier-datasource.yaml | 24 + .../rbac/rbac_perses_e2e_ci_users.sh | 1196 ++++++++++++++ web/cypress/fixtures/coo/coo_stage.sh | 2 +- web/cypress/fixtures/coo/update-cha-image.sh | 45 + web/cypress/fixtures/monitoring/constants.ts | 1 + web/cypress/fixtures/perses/constants.ts | 127 +- web/cypress/support/commands/auth-commands.ts | 390 +++-- .../support/commands/incident-commands.ts | 1 - .../support/commands/operator-commands.ts | 160 +- .../support/commands/perses-commands.ts | 62 + .../support/commands/selector-commands.ts | 2 +- .../support/commands/utility-commands.ts | 48 + .../commands/virtualization-commands.ts | 5 +- .../incidents_prometheus_query_mocks/index.ts | 2 +- .../schema/fixture-converter.ts | 2 +- .../schema/fixture-schema.json | 2 +- .../schema/schema-validator.ts | 2 +- .../schema/validate-fixtures.ts | 2 +- .../schema/yaml-fixture-snippets.json | 2 +- .../incidents_prometheus_query_mocks/types.ts | 2 +- .../incidents_prometheus_query_mocks/utils.ts | 2 +- web/cypress/support/index.ts | 3 +- .../monitoring/00.bvt_monitoring.cy.ts | 2 +- .../00.bvt_monitoring_namespace.cy.ts | 4 +- .../support/monitoring/01.reg_alerts.cy.ts | 2 +- .../support/monitoring/02.reg_metrics_1.cy.ts | 15 +- .../support/monitoring/02.reg_metrics_2.cy.ts | 21 +- .../monitoring/03.reg_legacy_dashboards.cy.ts | 6 +- .../monitoring/04.reg_alerts_namespace.cy.ts | 10 +- .../05.reg_metrics_namespace_1.cy.ts | 18 +- .../05.reg_metrics_namespace_2.cy.ts | 22 +- .../06.reg_legacy_dashboards_namespace.cy.ts | 15 +- ...es.cy.ts => 00.coo_bvt_perses_admin.cy.ts} | 26 +- .../perses/00.coo_bvt_perses_admin_1.cy.ts | 236 +++ .../perses/01.coo_list_perses_admin.cy.ts | 362 +++++ .../01.coo_list_perses_admin_namespace.cy.ts | 133 ++ .../perses/02.coo_edit_perses_admin.cy.ts | 518 ++++++ .../perses/02.coo_edit_perses_admin_1.cy.ts | 281 ++++ .../perses/03.coo_create_perses_admin.cy.ts | 209 +++ .../perses/99.coo_rbac_perses_user1.cy.ts | 485 ++++++ .../perses/99.coo_rbac_perses_user2.cy.ts | 120 ++ web/cypress/support/test-tags.d.ts | 1 - web/cypress/views/acm-alerting-page.ts | 4 +- .../views/alerting-rule-details-page.ts | 2 +- web/cypress/views/alerting-rule-list-page.ts | 2 +- web/cypress/views/common.ts | 9 +- web/cypress/views/details-page.ts | 2 +- web/cypress/views/legacy-dashboards.ts | 31 +- web/cypress/views/list-page.ts | 37 +- web/cypress/views/metrics.ts | 110 +- web/cypress/views/nav.ts | 27 +- .../perses-dashboards-create-dashboard.ts | 67 + .../perses-dashboards-edit-datasources.ts | 95 ++ .../views/perses-dashboards-edit-variables.ts | 168 ++ .../perses-dashboards-list-dashboards.ts | 242 +++ web/cypress/views/perses-dashboards-panel.ts | 169 ++ .../views/perses-dashboards-panelgroup.ts | 96 ++ web/cypress/views/perses-dashboards.ts | 421 ++++- web/cypress/views/silence-alert-page.ts | 2 +- web/cypress/views/silence-details-page.ts | 2 +- web/cypress/views/silences-list-page.ts | 3 +- web/cypress/views/tour.ts | 56 +- web/cypress/views/troubleshooting-panel.ts | 4 +- web/src/components/data-test.ts | 117 +- 106 files changed, 9761 insertions(+), 581 deletions(-) rename web/cypress/e2e/perses/{01.coo_perses.cy.ts => 00.coo_bvt_perses_admin.cy.ts} (85%) create mode 100644 web/cypress/e2e/perses/00.coo_bvt_perses_admin_1.cy.ts create mode 100644 web/cypress/e2e/perses/01.coo_list_perses_admin.cy.ts create mode 100644 web/cypress/e2e/perses/02.coo_edit_perses_admin.cy.ts create mode 100644 web/cypress/e2e/perses/03.coo_create_perses_admin.cy.ts create mode 100644 web/cypress/e2e/perses/99.coo_rbac_perses_user1.cy.ts create mode 100644 web/cypress/e2e/perses/99.coo_rbac_perses_user2.cy.ts rename web/cypress/fixtures/coo/{ => coo121_perses/dashboards}/openshift-cluster-sample-dashboard.yaml (100%) rename web/cypress/fixtures/coo/{ => coo121_perses/dashboards}/perses-dashboard-sample.yaml (100%) rename web/cypress/fixtures/coo/{ => coo121_perses/dashboards}/prometheus-overview-variables.yaml (100%) rename web/cypress/fixtures/coo/{ => coo121_perses/dashboards}/thanos-compact-overview-1var.yaml (100%) rename web/cypress/fixtures/coo/{ => coo121_perses/dashboards}/thanos-querier-datasource.yaml (100%) create mode 100644 web/cypress/fixtures/coo/coo141_perses/dashboards/openshift-cluster-sample-dashboard.yaml create mode 100644 web/cypress/fixtures/coo/coo141_perses/dashboards/perses-dashboard-sample.yaml create mode 100644 web/cypress/fixtures/coo/coo141_perses/dashboards/prometheus-overview-variables.yaml create mode 100644 web/cypress/fixtures/coo/coo141_perses/dashboards/thanos-compact-overview-1var.yaml create mode 100644 web/cypress/fixtures/coo/coo141_perses/dashboards/thanos-querier-datasource.yaml create mode 100644 web/cypress/fixtures/coo/coo141_perses/rbac/rbac_perses_e2e_ci_users.sh create mode 100644 web/cypress/fixtures/coo/update-cha-image.sh create mode 100644 web/cypress/support/commands/perses-commands.ts rename web/cypress/support/perses/{00.coo_bvt_perses.cy.ts => 00.coo_bvt_perses_admin.cy.ts} (75%) create mode 100644 web/cypress/support/perses/00.coo_bvt_perses_admin_1.cy.ts create mode 100644 web/cypress/support/perses/01.coo_list_perses_admin.cy.ts create mode 100644 web/cypress/support/perses/01.coo_list_perses_admin_namespace.cy.ts create mode 100644 web/cypress/support/perses/02.coo_edit_perses_admin.cy.ts create mode 100644 web/cypress/support/perses/02.coo_edit_perses_admin_1.cy.ts create mode 100644 web/cypress/support/perses/03.coo_create_perses_admin.cy.ts create mode 100644 web/cypress/support/perses/99.coo_rbac_perses_user1.cy.ts create mode 100644 web/cypress/support/perses/99.coo_rbac_perses_user2.cy.ts create mode 100644 web/cypress/views/perses-dashboards-create-dashboard.ts create mode 100644 web/cypress/views/perses-dashboards-edit-datasources.ts create mode 100644 web/cypress/views/perses-dashboards-edit-variables.ts create mode 100644 web/cypress/views/perses-dashboards-list-dashboards.ts create mode 100644 web/cypress/views/perses-dashboards-panel.ts create mode 100644 web/cypress/views/perses-dashboards-panelgroup.ts diff --git a/web/cypress/configure-env.sh b/web/cypress/configure-env.sh index b98116dbf..45007b5e2 100755 --- a/web/cypress/configure-env.sh +++ b/web/cypress/configure-env.sh @@ -175,6 +175,7 @@ print_current_config() { print_var "CYPRESS_KONFLUX_COO_BUNDLE_IMAGE" "${CYPRESS_KONFLUX_COO_BUNDLE_IMAGE-}" print_var "CYPRESS_CUSTOM_COO_BUNDLE_IMAGE" "${CYPRESS_CUSTOM_COO_BUNDLE_IMAGE-}" print_var "CYPRESS_MCP_CONSOLE_IMAGE" "${CYPRESS_MCP_CONSOLE_IMAGE-}" + print_var "CYPRESS_CHA_IMAGE" "${CYPRESS_CHA_IMAGE-}" print_var "CYPRESS_TIMEZONE" "${CYPRESS_TIMEZONE-}" print_var "CYPRESS_MOCK_NEW_METRICS" "${CYPRESS_MOCK_NEW_METRICS-}" print_var "CYPRESS_SESSION" "${CYPRESS_SESSION-}" @@ -185,6 +186,7 @@ print_current_config() { print_var "CYPRESS_KONFLUX_KBV_BUNDLE_IMAGE" "${CYPRESS_KONFLUX_KBV_BUNDLE_IMAGE-}" print_var "CYPRESS_CUSTOM_KBV_BUNDLE_IMAGE" "${CYPRESS_CUSTOM_KBV_BUNDLE_IMAGE-}" print_var "CYPRESS_FBC_STAGE_KBV_IMAGE" "${CYPRESS_FBC_STAGE_KBV_IMAGE-}" + print_var "CYPRESS_LOGIN_IDP_DEV_USER" "${CYPRESS_LOGIN_IDP_DEV_USER-}" } main() { @@ -226,6 +228,7 @@ main() { local def_konflux_bundle=${CYPRESS_KONFLUX_COO_BUNDLE_IMAGE-} local def_custom_coo_bundle=${CYPRESS_CUSTOM_COO_BUNDLE_IMAGE-} local def_mcp_console_image=${CYPRESS_MCP_CONSOLE_IMAGE-} + local def_cha_image=${CYPRESS_CHA_IMAGE-} local def_timezone=${CYPRESS_TIMEZONE-} local def_mock_new_metrics=${CYPRESS_MOCK_NEW_METRICS-} local def_session=${CYPRESS_SESSION-} @@ -236,6 +239,7 @@ main() { local def_konflux_kbv_bundle=${CYPRESS_KONFLUX_KBV_BUNDLE_IMAGE-} local def_custom_kbv_bundle=${CYPRESS_CUSTOM_KBV_BUNDLE_IMAGE-} local def_fbc_stage_kbv_image=${CYPRESS_FBC_STAGE_KBV_IMAGE-} + local def_login_idp_dev_user=${CYPRESS_LOGIN_IDP_DEV_USER-} # Required basics local base_url while true; do @@ -295,7 +299,11 @@ main() { # User declined current, try to find kubeconfigs from Downloads if [[ -d "$HOME/Downloads" ]]; then local kubeconfig_files - mapfile -t kubeconfig_files < <(ls -t "$HOME/Downloads"/*kubeconfig* 2>/dev/null | head -10) + # Use 'while read' instead of 'mapfile' for bash 3.x compatibility (macOS) + kubeconfig_files=() + while IFS= read -r file; do + kubeconfig_files+=("$file") + done < <(ls -t "$HOME/Downloads"/*kubeconfig* 2>/dev/null | head -10) if [[ ${#kubeconfig_files[@]} -gt 0 ]]; then echo "" @@ -357,7 +365,11 @@ main() { # No current kubeconfig set, try to find kubeconfigs from Downloads if [[ -d "$HOME/Downloads" ]]; then local kubeconfig_files - mapfile -t kubeconfig_files < <(ls -t "$HOME/Downloads"/*kubeconfig* 2>/dev/null | head -10) + # Use 'while read' instead of 'mapfile' for bash 3.x compatibility (macOS) + kubeconfig_files=() + while IFS= read -r file; do + kubeconfig_files+=("$file") + done < <(ls -t "$HOME/Downloads"/*kubeconfig* 2>/dev/null | head -10) if [[ ${#kubeconfig_files[@]} -gt 0 ]]; then echo "" @@ -426,6 +438,9 @@ main() { local mcp_console_image mcp_console_image=$(ask "Monitoring Console Plugin UI image (CYPRESS_MCP_CONSOLE_IMAGE)" "$def_mcp_console_image") + local cha_image + cha_image=$(ask "Cluster Health Analyzer image (CYPRESS_CHA_IMAGE)" "$def_cha_image") + local timezone timezone=$(ask "Cluster timezone (CYPRESS_TIMEZONE)" "${def_timezone:-UTC}") @@ -468,7 +483,9 @@ main() { local fbc_stage_kbv_image fbc_stage_kbv_image=$(ask "KBV FBC image (CYPRESS_FBC_STAGE_KBV_IMAGE)" "$def_fbc_stage_kbv_image") - + local login_idp_dev_user + login_idp_dev_user=$(ask "Login identity provider dev user (CYPRESS_LOGIN_IDP_DEV_USER)" "$def_login_idp_dev_user") + # Build export lines with safe quoting local -a export_lines export_lines+=("export CYPRESS_BASE_URL='$(printf %s "$base_url" | escape_for_single_quotes)'" ) @@ -492,6 +509,9 @@ main() { if [[ -n "$mcp_console_image" ]]; then export_lines+=("export CYPRESS_MCP_CONSOLE_IMAGE='$(printf %s "$mcp_console_image" | escape_for_single_quotes)'" ) fi + if [[ -n "$cha_image" ]]; then + export_lines+=("export CYPRESS_CHA_IMAGE='$(printf %s "$cha_image" | escape_for_single_quotes)'" ) + fi if [[ -n "$timezone" ]]; then export_lines+=("export CYPRESS_TIMEZONE='$(printf %s "$timezone" | escape_for_single_quotes)'" ) fi @@ -515,7 +535,9 @@ main() { if [[ -n "$fbc_stage_kbv_image" ]]; then export_lines+=("export CYPRESS_FBC_STAGE_KBV_IMAGE='$(printf %s "$fbc_stage_kbv_image" | escape_for_single_quotes)'" ) fi - + if [[ -n "$login_idp_dev_user" ]]; then + export_lines+=("export CYPRESS_LOGIN_IDP_DEV_USER='$(printf %s "$login_idp_dev_user" | escape_for_single_quotes)'" ) + fi echo "" if is_sourced; then # Export directly into current shell @@ -534,29 +556,30 @@ main() { echo "" echo "Configured values:" - echo " CYPRESS_BASE_URL=$CYPRESS_BASE_URL" - echo " CYPRESS_LOGIN_IDP=${CYPRESS_LOGIN_IDP:-$login_idp}" - echo " CYPRESS_LOGIN_USERS=${CYPRESS_LOGIN_USERS:-$login_users}" - echo " CYPRESS_KUBECONFIG_PATH=${CYPRESS_KUBECONFIG_PATH:-$kubeconfig}" - [[ -n "${CYPRESS_MP_IMAGE-}$mp_image" ]] && echo " CYPRESS_MP_IMAGE=${CYPRESS_MP_IMAGE:-$mp_image}" - [[ -n "${CYPRESS_COO_NAMESPACE-}$coo_namespace" ]] && echo " CYPRESS_COO_NAMESPACE=${CYPRESS_COO_NAMESPACE:-$coo_namespace}" - echo " CYPRESS_SKIP_COO_INSTALL=${CYPRESS_SKIP_COO_INSTALL:-$skip_coo_install}" - echo " CYPRESS_COO_UI_INSTALL=${CYPRESS_COO_UI_INSTALL:-$coo_ui_install}" - [[ -n "${CYPRESS_KONFLUX_COO_BUNDLE_IMAGE-}$konflux_bundle" ]] && echo " CYPRESS_KONFLUX_COO_BUNDLE_IMAGE=${CYPRESS_KONFLUX_COO_BUNDLE_IMAGE:-$konflux_bundle}" - [[ -n "${CYPRESS_CUSTOM_COO_BUNDLE_IMAGE-}$custom_coo_bundle" ]] && echo " CYPRESS_CUSTOM_COO_BUNDLE_IMAGE=${CYPRESS_CUSTOM_COO_BUNDLE_IMAGE:-$custom_coo_bundle}" - [[ -n "${CYPRESS_MCP_CONSOLE_IMAGE-}$mcp_console_image" ]] && echo " CYPRESS_MCP_CONSOLE_IMAGE=${CYPRESS_MCP_CONSOLE_IMAGE:-$mcp_console_image}" - [[ -n "${CYPRESS_TIMEZONE-}$timezone" ]] && echo " CYPRESS_TIMEZONE=${CYPRESS_TIMEZONE:-$timezone}" - echo " CYPRESS_MOCK_NEW_METRICS=${CYPRESS_MOCK_NEW_METRICS:-$mock_new_metrics}" - echo " CYPRESS_SESSION=${CYPRESS_SESSION:-$session}" - echo " CYPRESS_DEBUG=${CYPRESS_DEBUG:-$debug}" - echo " CYPRESS_SKIP_ALL_INSTALL=${CYPRESS_SKIP_ALL_INSTALL:-$skip_all_install}" - echo " CYPRESS_SKIP_KBV_INSTALL=${CYPRESS_SKIP_KBV_INSTALL:-$skip_kbv_install}" - echo " CYPRESS_KBV_UI_INSTALL=${CYPRESS_KBV_UI_INSTALL:-$kbv_ui_install}" - [[ -n "${CYPRESS_KONFLUX_KBV_BUNDLE_IMAGE-}$konflux_kbv_bundle" ]] && echo " CYPRESS_KONFLUX_KBV_BUNDLE_IMAGE=${CYPRESS_KONFLUX_KBV_BUNDLE_IMAGE:-$konflux_kbv_bundle}" - [[ -n "${CYPRESS_CUSTOM_KBV_BUNDLE_IMAGE-}$custom_kbv_bundle" ]] && echo " CYPRESS_CUSTOM_KBV_BUNDLE_IMAGE=${CYPRESS_CUSTOM_KBV_BUNDLE_IMAGE:-$custom_kbv_bundle}" - [[ -n "${CYPRESS_FBC_STAGE_KBV_IMAGE-}$fbc_stage_kbv_image" ]] && echo " CYPRESS_FBC_STAGE_KBV_IMAGE=${CYPRESS_FBC_STAGE_KBV_IMAGE:-$fbc_stage_kbv_image}" + echo " CYPRESS_BASE_URL=$base_url" + echo " CYPRESS_LOGIN_IDP=$login_idp" + echo " CYPRESS_LOGIN_USERS=$login_users" + echo " CYPRESS_LOGIN_IDP_DEV_USER=$login_idp_dev_user" + echo " CYPRESS_KUBECONFIG_PATH=$kubeconfig" + [[ -n "$mp_image" ]] && echo " CYPRESS_MP_IMAGE=$mp_image" + [[ -n "$coo_namespace" ]] && echo " CYPRESS_COO_NAMESPACE=$coo_namespace" + echo " CYPRESS_SKIP_COO_INSTALL=$skip_coo_install" + echo " CYPRESS_COO_UI_INSTALL=$coo_ui_install" + [[ -n "$konflux_bundle" ]] && echo " CYPRESS_KONFLUX_COO_BUNDLE_IMAGE=$konflux_bundle" + [[ -n "$custom_coo_bundle" ]] && echo " CYPRESS_CUSTOM_COO_BUNDLE_IMAGE=$custom_coo_bundle" + [[ -n "$mcp_console_image" ]] && echo " CYPRESS_MCP_CONSOLE_IMAGE=$mcp_console_image" + [[ -n "$cha_image" ]] && echo " CYPRESS_CHA_IMAGE=$cha_image" + [[ -n "$timezone" ]] && echo " CYPRESS_TIMEZONE=$timezone" + echo " CYPRESS_MOCK_NEW_METRICS=$mock_new_metrics" + echo " CYPRESS_SESSION=$session" + echo " CYPRESS_DEBUG=$debug" + echo " CYPRESS_SKIP_ALL_INSTALL=$skip_all_install" + echo " CYPRESS_SKIP_KBV_INSTALL=$skip_kbv_install" + echo " CYPRESS_KBV_UI_INSTALL=$kbv_ui_install" + [[ -n "$konflux_kbv_bundle" ]] && echo " CYPRESS_KONFLUX_KBV_BUNDLE_IMAGE=$konflux_kbv_bundle" + [[ -n "$custom_kbv_bundle" ]] && echo " CYPRESS_CUSTOM_KBV_BUNDLE_IMAGE=$custom_kbv_bundle" + [[ -n "$fbc_stage_kbv_image" ]] && echo " CYPRESS_FBC_STAGE_KBV_IMAGE=$fbc_stage_kbv_image" } main "$@" - diff --git a/web/cypress/e2e/coo/01.coo_bvt.cy.ts b/web/cypress/e2e/coo/01.coo_bvt.cy.ts index 3a23242b6..fe33c5d66 100644 --- a/web/cypress/e2e/coo/01.coo_bvt.cy.ts +++ b/web/cypress/e2e/coo/01.coo_bvt.cy.ts @@ -28,6 +28,8 @@ describe('BVT: COO', { tags: ['@smoke', '@coo'] }, () => { it('1. Admin perspective - Observe Menu', () => { cy.log('Admin perspective - Observe Menu and verify all submenus'); + cy.reload(true); + cy.wait(10000); nav.sidenav.clickNavLink(['Observe', 'Alerting']); commonPages.titleShouldHaveText('Alerting'); nav.tabs.switchTab('Silences'); @@ -45,4 +47,4 @@ describe('BVT: COO', { tags: ['@smoke', '@coo'] }, () => { * TODO: To be replaced by COO validation such as Dashboards (Perses) scenarios */ -}); +}); \ No newline at end of file diff --git a/web/cypress/e2e/coo/01.coo_ivt.cy.ts b/web/cypress/e2e/coo/01.coo_ivt.cy.ts index 2f58da097..17d8201fb 100644 --- a/web/cypress/e2e/coo/01.coo_ivt.cy.ts +++ b/web/cypress/e2e/coo/01.coo_ivt.cy.ts @@ -25,10 +25,9 @@ describe('IVT: Monitoring UIPlugin + Virtualization', { tags: ['@smoke', '@coo'] it('1. Virtualization perspective - Observe Menu', () => { cy.log('Virtualization perspective - Observe Menu and verify all submenus'); cy.switchPerspective('Virtualization'); - cy.byAriaLabel('Welcome modal').should('be.visible'); guidedTour.closeKubevirtTour(); troubleshootingPanelPage.signalCorrelationShouldNotBeVisible(); - cy.switchPerspective('Administrator'); + cy.switchPerspective('Core platform', 'Administrator'); }); @@ -36,4 +35,4 @@ describe('IVT: Monitoring UIPlugin + Virtualization', { tags: ['@smoke', '@coo'] * TODO: To be replaced by COO validation such as Dashboards (Perses) scenarios */ -}); +}); \ No newline at end of file diff --git a/web/cypress/e2e/coo/02.acm_alerting_ui.cy.ts b/web/cypress/e2e/coo/02.acm_alerting_ui.cy.ts index 58b72fe87..7dce795fe 100644 --- a/web/cypress/e2e/coo/02.acm_alerting_ui.cy.ts +++ b/web/cypress/e2e/coo/02.acm_alerting_ui.cy.ts @@ -1,6 +1,7 @@ // 02.acm_alerting_ui.cy.ts // E2E test for validating ACM Alerting UI integration with Cluster Observability Operator (COO) import '../../support/commands/auth-commands'; +import { commonPages } from '../../views/common'; import { nav } from '../../views/nav'; import { acmAlertingPage } from '../../views/acm-alerting-page'; @@ -25,9 +26,11 @@ describe('ACM Alerting UI', { tags: ['@coo', '@alerts'] }, () => { }); it('Navigate to Fleet Management > local-cluster > Observe > Alerting', () => { - // wait for console page loading completed - cy.visit('/'); - cy.get('body', { timeout: 60000 }).should('contain.text', 'Administrator'); + // check monitoring-plugin UI is not been affected + nav.sidenav.clickNavLink(['Observe', 'Alerting']); + commonPages.titleShouldHaveText('Alerting') + nav.sidenav.clickNavLink(['Observe', 'Metrics']); + commonPages.titleShouldHaveText('Metrics'); // switch to Fleet Management page cy.switchPerspective('Fleet Management'); // close pop-up window @@ -42,17 +45,14 @@ describe('ACM Alerting UI', { tags: ['@coo', '@alerts'] }, () => { }); // click side menu -> Observe -> Alerting nav.sidenav.clickNavLink(['Observe', 'Alerting']); - // Wait for alert tab content to become visible - cy.get('section#alerts-tab-content', { timeout: 60000 }) - .should('be.visible'); // confirm Alerting page loading completed acmAlertingPage.shouldBeLoaded(); - // check three test alerts exist + // check test alerts exist expectedAlerts.forEach((alert) => { - cy.contains('a[data-test-id="alert-resource-link"]', alert, { timeout: 60000 }) + cy.contains('a[data-test-id="alert-resource-link"]', alert, { timeout: 120000 }) .should('be.visible'); }); cy.log('Verified all expected alerts are visible on the Alerting page'); cy.log('ACM Alerting UI test completed successfully'); }); -}); +}); \ No newline at end of file diff --git a/web/cypress/e2e/incidents/00.coo_incidents_e2e.cy.ts b/web/cypress/e2e/incidents/00.coo_incidents_e2e.cy.ts index 2819133e1..a1db71f10 100644 --- a/web/cypress/e2e/incidents/00.coo_incidents_e2e.cy.ts +++ b/web/cypress/e2e/incidents/00.coo_incidents_e2e.cy.ts @@ -17,11 +17,11 @@ const MCP = { }; const MP = { - namespace: Cypress.env('COO_NAMESPACE'), + namespace: 'openshift-monitoring', operatorName: 'Cluster Monitoring Operator', }; -describe('BVT: Incidents - e2e', { tags: ['@smoke', '@slow', '@incidents'] }, () => { +describe('BVT: Incidents - e2e', { tags: ['@smoke', '@slow', '@incidents', '@e2e-real'] }, () => { let currentAlertName: string; before(() => { diff --git a/web/cypress/e2e/incidents/01.incidents.cy.ts b/web/cypress/e2e/incidents/01.incidents.cy.ts index 104f7ca14..2d6e12f6b 100644 --- a/web/cypress/e2e/incidents/01.incidents.cy.ts +++ b/web/cypress/e2e/incidents/01.incidents.cy.ts @@ -22,7 +22,7 @@ const MCP = { }; const MP = { - namespace: Cypress.env('COO_NAMESPACE'), + namespace: 'openshift-monitoring', operatorName: 'Cluster Monitoring Operator', }; diff --git a/web/cypress/e2e/incidents/02.incidents-mocking-example.cy.ts b/web/cypress/e2e/incidents/02.incidents-mocking-example.cy.ts index a5e4efbe3..91ef3794f 100644 --- a/web/cypress/e2e/incidents/02.incidents-mocking-example.cy.ts +++ b/web/cypress/e2e/incidents/02.incidents-mocking-example.cy.ts @@ -22,7 +22,7 @@ const MCP = { }; const MP = { - namespace: Cypress.env('COO_NAMESPACE'), + namespace: 'openshift-monitoring', operatorName: 'Cluster Monitoring Operator', }; diff --git a/web/cypress/e2e/incidents/regression/01.reg_filtering.cy.ts b/web/cypress/e2e/incidents/regression/01.reg_filtering.cy.ts index 4d76098d6..b925a0962 100644 --- a/web/cypress/e2e/incidents/regression/01.reg_filtering.cy.ts +++ b/web/cypress/e2e/incidents/regression/01.reg_filtering.cy.ts @@ -21,7 +21,7 @@ const MCP = { }; const MP = { - namespace: Cypress.env('COO_NAMESPACE'), + namespace: 'openshift-monitoring', operatorName: 'Cluster Monitoring Operator', }; @@ -148,4 +148,4 @@ describe('Regression: Incidents Filtering', { tags: ['@incidents'] }, () => { incidentsPage.clearAllFilters(); }); -}); +}); \ No newline at end of file diff --git a/web/cypress/e2e/incidents/regression/02.reg_ui_charts_comprehensive.cy.ts b/web/cypress/e2e/incidents/regression/02.reg_ui_charts_comprehensive.cy.ts index c40c338e9..15754a12f 100644 --- a/web/cypress/e2e/incidents/regression/02.reg_ui_charts_comprehensive.cy.ts +++ b/web/cypress/e2e/incidents/regression/02.reg_ui_charts_comprehensive.cy.ts @@ -80,7 +80,7 @@ const MCP = { }; const MP = { - namespace: Cypress.env('COO_NAMESPACE'), + namespace: 'openshift-monitoring', operatorName: 'Cluster Monitoring Operator', }; diff --git a/web/cypress/e2e/incidents/regression/03-04.reg_e2e_firing_alerts.cy.ts b/web/cypress/e2e/incidents/regression/03-04.reg_e2e_firing_alerts.cy.ts index fe36011c4..532dde083 100644 --- a/web/cypress/e2e/incidents/regression/03-04.reg_e2e_firing_alerts.cy.ts +++ b/web/cypress/e2e/incidents/regression/03-04.reg_e2e_firing_alerts.cy.ts @@ -33,7 +33,7 @@ const MP = { operatorName: 'Cluster Monitoring Operator', }; -describe('Regression: Time-Based Alert Resolution (E2E with Firing Alerts)', { tags: ['@incidents', '@slow', '@flaky'] }, () => { +describe('Regression: Time-Based Alert Resolution (E2E with Firing Alerts)', { tags: ['@incidents', '@slow', '@e2e-real'] }, () => { let currentAlertName: string; before(() => { @@ -301,4 +301,3 @@ describe('Regression: Time-Based Alert Resolution (E2E with Firing Alerts)', { t }); }); - diff --git a/web/cypress/e2e/incidents/regression/03.reg_api_calls.cy.ts b/web/cypress/e2e/incidents/regression/03.reg_api_calls.cy.ts index 65c66c96f..38d98b063 100644 --- a/web/cypress/e2e/incidents/regression/03.reg_api_calls.cy.ts +++ b/web/cypress/e2e/incidents/regression/03.reg_api_calls.cy.ts @@ -22,11 +22,11 @@ const MCP = { }; const MP = { - namespace: Cypress.env('COO_NAMESPACE'), + namespace: 'openshift-monitoring', operatorName: 'Cluster Monitoring Operator', }; -describe('Regression: Silences Not Applied Correctly', { tags: ['@incidents', '@flaky'] }, () => { +describe('Regression: Silences Not Applied Correctly', { tags: ['@incidents'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP); @@ -125,4 +125,3 @@ describe('Regression: Silences Not Applied Correctly', { tags: ['@incidents', '@ }); }); - diff --git a/web/cypress/e2e/incidents/regression/04.reg_redux_effects.cy.ts b/web/cypress/e2e/incidents/regression/04.reg_redux_effects.cy.ts index 6e0933bed..ccb36c3c3 100644 --- a/web/cypress/e2e/incidents/regression/04.reg_redux_effects.cy.ts +++ b/web/cypress/e2e/incidents/regression/04.reg_redux_effects.cy.ts @@ -26,11 +26,11 @@ const MCP = { }; const MP = { - namespace: Cypress.env('COO_NAMESPACE'), + namespace: 'openshift-monitoring', operatorName: 'Cluster Monitoring Operator', }; -describe('Regression: Redux State Management', { tags: ['@incidents', '@incidents-redux', '@flaky'] }, () => { +describe('Regression: Redux State Management', { tags: ['@incidents', '@incidents-redux'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP); @@ -184,4 +184,4 @@ describe('Regression: Redux State Management', { tags: ['@incidents', '@incident incidentsPage.elements.incidentIdFilterChip().should('be.visible'); cy.log('SUCCESS: Incident reappears when conflicting filter removed'); }); -}); +}); \ No newline at end of file diff --git a/web/cypress/e2e/monitoring/00.bvt_admin.cy.ts b/web/cypress/e2e/monitoring/00.bvt_admin.cy.ts index ddaa68f1c..6ef745739 100644 --- a/web/cypress/e2e/monitoring/00.bvt_admin.cy.ts +++ b/web/cypress/e2e/monitoring/00.bvt_admin.cy.ts @@ -1,6 +1,5 @@ import { nav } from '../../views/nav'; import { alerts } from '../../fixtures/monitoring/alert'; -import { guidedTour } from '../../views/tour'; import { runBVTMonitoringTests } from '../../support/monitoring/00.bvt_monitoring.cy'; import { commonPages } from '../../views/common'; import { overviewPage } from '../../views/overview-page'; @@ -17,9 +16,6 @@ describe('BVT: Monitoring', { tags: ['@smoke', '@monitoring'] }, () => { }); beforeEach(() => { - cy.visit('/'); - guidedTour.close(); - cy.validateLogin(); nav.sidenav.clickNavLink(['Observe', 'Metrics']); commonPages.titleShouldHaveText('Metrics'); cy.changeNamespace("All Projects"); diff --git a/web/cypress/e2e/monitoring/00.bvt_dev.cy.ts b/web/cypress/e2e/monitoring/00.bvt_dev.cy.ts index 40efaa6d2..6a5064b93 100644 --- a/web/cypress/e2e/monitoring/00.bvt_dev.cy.ts +++ b/web/cypress/e2e/monitoring/00.bvt_dev.cy.ts @@ -1,9 +1,7 @@ import { nav } from '../../views/nav'; import { alerts } from '../../fixtures/monitoring/alert'; -import { guidedTour } from '../../views/tour'; import { runBVTMonitoringTestsNamespace } from '../../support/monitoring/00.bvt_monitoring_namespace.cy'; import { commonPages } from '../../views/common'; -import { overviewPage } from '../../views/overview-page'; // Set constants for the operators that need to be installed for tests. const MP = { namespace: 'openshift-monitoring', @@ -17,9 +15,6 @@ describe('BVT: Monitoring - Namespaced', { tags: ['@monitoring-dev', '@smoke-dev }); beforeEach(() => { - cy.visit('/'); - guidedTour.close(); - cy.validateLogin(); alerts.getWatchdogAlert(); nav.sidenav.clickNavLink(['Observe', 'Alerting']); commonPages.titleShouldHaveText('Alerting'); diff --git a/web/cypress/e2e/monitoring/regression/01.reg_alerts_admin.cy.ts b/web/cypress/e2e/monitoring/regression/01.reg_alerts_admin.cy.ts index 2a3bcd4c9..57dd666ae 100644 --- a/web/cypress/e2e/monitoring/regression/01.reg_alerts_admin.cy.ts +++ b/web/cypress/e2e/monitoring/regression/01.reg_alerts_admin.cy.ts @@ -2,7 +2,6 @@ import { alerts } from '../../../fixtures/monitoring/alert'; import { runAllRegressionAlertsTests } from '../../../support/monitoring/01.reg_alerts.cy'; import { commonPages } from '../../../views/common'; import { nav } from '../../../views/nav'; -import { guidedTour } from '../../../views/tour'; const MP = { namespace: 'openshift-monitoring', @@ -17,9 +16,6 @@ describe('Regression: Monitoring - Alerts (Administrator)', { tags: ['@monitorin }); beforeEach(() => { - cy.visit('/'); - guidedTour.close(); - cy.validateLogin(); alerts.getWatchdogAlert(); nav.sidenav.clickNavLink(['Observe', 'Metrics']); commonPages.titleShouldHaveText('Metrics'); @@ -36,4 +32,3 @@ describe('Regression: Monitoring - Alerts (Administrator)', { tags: ['@monitorin }); - diff --git a/web/cypress/e2e/monitoring/regression/01.reg_alerts_dev.cy.ts b/web/cypress/e2e/monitoring/regression/01.reg_alerts_dev.cy.ts index 529d2727e..9aa40740e 100644 --- a/web/cypress/e2e/monitoring/regression/01.reg_alerts_dev.cy.ts +++ b/web/cypress/e2e/monitoring/regression/01.reg_alerts_dev.cy.ts @@ -2,7 +2,6 @@ import { alerts } from '../../../fixtures/monitoring/alert'; import { runAllRegressionAlertsTestsNamespace } from '../../../support/monitoring/04.reg_alerts_namespace.cy'; import { commonPages } from '../../../views/common'; import { nav } from '../../../views/nav'; -import { guidedTour } from '../../../views/tour'; const MP = { namespace: 'openshift-monitoring', @@ -16,9 +15,6 @@ describe('Regression: Monitoring - Alerts Namespaced (Administrator)', { tags: [ }); beforeEach(() => { - cy.visit('/'); - guidedTour.close(); - cy.validateLogin(); alerts.getWatchdogAlert(); nav.sidenav.clickNavLink(['Observe', 'Alerting']); commonPages.titleShouldHaveText('Alerting'); @@ -32,4 +28,3 @@ describe('Regression: Monitoring - Alerts Namespaced (Administrator)', { tags: [ }); }); - diff --git a/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_1.cy.ts b/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_1.cy.ts index 109bebfde..b23aa7912 100644 --- a/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_1.cy.ts +++ b/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_1.cy.ts @@ -2,7 +2,6 @@ import { runAllRegressionMetricsTests1 } from '../../../support/monitoring/02.re import { runAllRegressionMetricsTestsNamespace1 } from '../../../support/monitoring/05.reg_metrics_namespace_1.cy'; import { commonPages } from '../../../views/common'; import { nav } from '../../../views/nav'; -import { guidedTour } from '../../../views/tour'; const MP = { namespace: 'openshift-monitoring', @@ -17,9 +16,6 @@ describe('Regression: Monitoring - Metrics (Administrator)', { tags: ['@monitori }); beforeEach(() => { - cy.visit('/'); - guidedTour.close(); - cy.validateLogin(); nav.sidenav.clickNavLink(['Observe', 'Metrics']); commonPages.titleShouldHaveText('Metrics'); cy.changeNamespace("All Projects"); @@ -40,9 +36,6 @@ describe('Regression: Monitoring - Metrics Namespaced (Administrator)', { tags: }); beforeEach(() => { - cy.visit('/'); - guidedTour.close(); - cy.validateLogin(); nav.sidenav.clickNavLink(['Observe', 'Metrics']); commonPages.titleShouldHaveText('Metrics'); cy.changeNamespace(MP.namespace); @@ -54,4 +47,3 @@ describe('Regression: Monitoring - Metrics Namespaced (Administrator)', { tags: }); }); - diff --git a/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_2.cy.ts b/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_2.cy.ts index 52242d6c2..fe5b90781 100644 --- a/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_2.cy.ts +++ b/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_2.cy.ts @@ -2,7 +2,6 @@ import { runAllRegressionMetricsTests2 } from '../../../support/monitoring/02.re import { runAllRegressionMetricsTestsNamespace2 } from '../../../support/monitoring/05.reg_metrics_namespace_2.cy'; import { commonPages } from '../../../views/common'; import { nav } from '../../../views/nav'; -import { guidedTour } from '../../../views/tour'; const MP = { namespace: 'openshift-monitoring', @@ -17,9 +16,6 @@ describe('Regression: Monitoring - Metrics (Administrator)', { tags: ['@monitori }); beforeEach(() => { - cy.visit('/'); - guidedTour.close(); - cy.validateLogin(); nav.sidenav.clickNavLink(['Observe', 'Metrics']); commonPages.titleShouldHaveText('Metrics'); cy.changeNamespace("All Projects"); @@ -40,9 +36,6 @@ describe('Regression: Monitoring - Metrics Namespaced (Administrator)', { tags: }); beforeEach(() => { - cy.visit('/'); - guidedTour.close(); - cy.validateLogin(); nav.sidenav.clickNavLink(['Observe', 'Metrics']); commonPages.titleShouldHaveText('Metrics'); cy.changeNamespace(MP.namespace); @@ -54,4 +47,3 @@ describe('Regression: Monitoring - Metrics Namespaced (Administrator)', { tags: }); }); - diff --git a/web/cypress/e2e/monitoring/regression/03.reg_legacy_dashboards_admin.cy.ts b/web/cypress/e2e/monitoring/regression/03.reg_legacy_dashboards_admin.cy.ts index 260872028..eeb831b42 100644 --- a/web/cypress/e2e/monitoring/regression/03.reg_legacy_dashboards_admin.cy.ts +++ b/web/cypress/e2e/monitoring/regression/03.reg_legacy_dashboards_admin.cy.ts @@ -2,7 +2,6 @@ import { runAllRegressionLegacyDashboardsTests } from '../../../support/monitori import { runAllRegressionLegacyDashboardsTestsNamespace } from '../../../support/monitoring/06.reg_legacy_dashboards_namespace.cy'; import { commonPages } from '../../../views/common'; import { nav } from '../../../views/nav'; -import { guidedTour } from '../../../views/tour'; const MP = { namespace: 'openshift-monitoring', @@ -17,9 +16,6 @@ describe('Regression: Monitoring - Legacy Dashboards (Administrator)', { tags: [ }); beforeEach(() => { - cy.visit('/'); - guidedTour.close(); - cy.validateLogin(); //when running only this file, beforeBlock changes the namespace to openshift-monitoring //so we need to change it back to All Projects before landing to Dashboards page in order to have API Performance dashboard loaded by default nav.sidenav.clickNavLink(['Observe', 'Metrics']); @@ -45,9 +41,6 @@ describe('Regression: Monitoring - Legacy Dashboards Namespaced (Administrator)' }); beforeEach(() => { - cy.visit('/'); - guidedTour.close(); - cy.validateLogin(); nav.sidenav.clickNavLink(['Observe', 'Dashboards']); commonPages.titleShouldHaveText('Dashboards'); cy.changeNamespace(MP.namespace); @@ -58,4 +51,4 @@ describe('Regression: Monitoring - Legacy Dashboards Namespaced (Administrator)' name: 'Administrator', }); -}); +}); \ No newline at end of file diff --git a/web/cypress/e2e/perses/01.coo_perses.cy.ts b/web/cypress/e2e/perses/00.coo_bvt_perses_admin.cy.ts similarity index 85% rename from web/cypress/e2e/perses/01.coo_perses.cy.ts rename to web/cypress/e2e/perses/00.coo_bvt_perses_admin.cy.ts index c9016c1d2..8fe7a7b8f 100644 --- a/web/cypress/e2e/perses/01.coo_perses.cy.ts +++ b/web/cypress/e2e/perses/00.coo_bvt_perses_admin.cy.ts @@ -1,5 +1,5 @@ import { nav } from '../../views/nav'; -import { runBVTCOOPersesTests } from '../../support/perses/00.coo_bvt_perses.cy'; +import { runBVTCOOPersesTests } from '../../support/perses/00.coo_bvt_perses_admin.cy'; import { guidedTour } from '../../views/tour'; // Set constants for the operators that need to be installed for tests. @@ -18,16 +18,13 @@ const MP = { operatorName: 'Cluster Monitoring Operator', }; -describe('BVT: COO - Dashboards (Perses) - Administrator perspective', { tags: ['@smoke', '@dashboards'] }, () => { +describe('BVT: COO - Dashboards (Perses) - Administrator perspective', { tags: ['@smoke', '@dashboards', '@perses'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP); }); beforeEach(() => { - cy.visit('/'); - guidedTour.close(); - cy.validateLogin(); nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); }); diff --git a/web/cypress/e2e/perses/00.coo_bvt_perses_admin_1.cy.ts b/web/cypress/e2e/perses/00.coo_bvt_perses_admin_1.cy.ts new file mode 100644 index 000000000..b975a872a --- /dev/null +++ b/web/cypress/e2e/perses/00.coo_bvt_perses_admin_1.cy.ts @@ -0,0 +1,38 @@ +import { nav } from '../../views/nav'; +//TODO: rename after customizable-dashboards gets merged +import { runBVTCOOPersesTests1 } from '../../support/perses/00.coo_bvt_perses_admin_1.cy'; +import { guidedTour } from '../../views/tour'; + +// Set constants for the operators that need to be installed for tests. +const MCP = { + namespace: 'openshift-cluster-observability-operator', + packageName: 'cluster-observability-operator', + operatorName: 'Cluster Observability Operator', + config: { + kind: 'UIPlugin', + name: 'monitoring', + }, +}; + +const MP = { + namespace: 'openshift-monitoring', + operatorName: 'Cluster Monitoring Operator', +}; + +//TODO: change tag to @smoke, @dashboards, @perses when customizable-dashboards gets merged +describe('BVT: COO - Dashboards (Perses) - Administrator perspective', { tags: ['@smoke-', '@dashboards-', '@perses-'] }, () => { + + before(() => { + cy.beforeBlockCOO(MCP, MP); + }); + + beforeEach(() => { + nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); + }); + + //TODO: rename after customizable-dashboards gets merged + runBVTCOOPersesTests1({ + name: 'Administrator', + }); + +}); \ No newline at end of file diff --git a/web/cypress/e2e/perses/01.coo_list_perses_admin.cy.ts b/web/cypress/e2e/perses/01.coo_list_perses_admin.cy.ts new file mode 100644 index 000000000..a91704708 --- /dev/null +++ b/web/cypress/e2e/perses/01.coo_list_perses_admin.cy.ts @@ -0,0 +1,60 @@ +import { nav } from '../../views/nav'; +import { runCOOListPersesDuplicateDashboardTests, runCOOListPersesTests } from '../../support/perses/01.coo_list_perses_admin.cy'; +import { runCOOListPersesTestsNamespace } from '../../support/perses/01.coo_list_perses_admin_namespace.cy'; + +// Set constants for the operators that need to be installed for tests. +const MCP = { + namespace: 'openshift-cluster-observability-operator', + packageName: 'cluster-observability-operator', + operatorName: 'Cluster Observability Operator', + config: { + kind: 'UIPlugin', + name: 'monitoring', + }, +}; + +const MP = { + namespace: 'openshift-monitoring', + operatorName: 'Cluster Monitoring Operator', +}; + +//TODO: change tag to @dashboards when customizable-dashboards gets merged +describe('COO - Dashboards (Perses) - List perses dashboards', { tags: ['@perses', '@dashboards-'] }, () => { + + before(() => { + cy.beforeBlockCOO(MCP, MP); + }); + + beforeEach(() => { + nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); + cy.wait(5000); + cy.changeNamespace('All Projects'); + }); + + runCOOListPersesTests({ + name: 'Administrator', + }); + + runCOOListPersesDuplicateDashboardTests({ + name: 'Administrator', + }); + +}); + +//TODO: change tag to @dashboards when customizable-dashboards gets merged +describe('COO - Dashboards (Perses) - List perses dashboards - Namespace', { tags: ['@perses', '@dashboards-'] }, () => { + + before(() => { + cy.beforeBlockCOO(MCP, MP); + }); + + beforeEach(() => { + nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); + cy.changeNamespace('All Projects'); + }); + + runCOOListPersesTestsNamespace({ + name: 'Administrator', + }); + +}); diff --git a/web/cypress/e2e/perses/02.coo_edit_perses_admin.cy.ts b/web/cypress/e2e/perses/02.coo_edit_perses_admin.cy.ts new file mode 100644 index 000000000..16b00276b --- /dev/null +++ b/web/cypress/e2e/perses/02.coo_edit_perses_admin.cy.ts @@ -0,0 +1,44 @@ +import { nav } from '../../views/nav'; +import { runCOOEditPersesTests1 } from '../../support/perses/02.coo_edit_perses_admin_1.cy'; +import { runCOOEditPersesTests } from '../../support/perses/02.coo_edit_perses_admin.cy'; + +// Set constants for the operators that need to be installed for tests. +const MCP = { + namespace: 'openshift-cluster-observability-operator', + packageName: 'cluster-observability-operator', + operatorName: 'Cluster Observability Operator', + config: { + kind: 'UIPlugin', + name: 'monitoring', + }, +}; + +const MP = { + namespace: 'openshift-monitoring', + operatorName: 'Cluster Monitoring Operator', +}; + +//TODO: change tag to @dashboards when customizable-dashboards gets merged +describe('COO - Dashboards (Perses) - Edit perses dashboard', { tags: ['@perses', '@dashboards-'] }, () => { + + before(() => { + cy.beforeBlockCOO(MCP, MP); + }); + + beforeEach(() => { + nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); + cy.wait(5000); + cy.changeNamespace('All Projects'); + }); + + runCOOEditPersesTests({ + name: 'Administrator', + }); + + runCOOEditPersesTests1({ + name: 'Administrator', + }); + +}); + + diff --git a/web/cypress/e2e/perses/03.coo_create_perses_admin.cy.ts b/web/cypress/e2e/perses/03.coo_create_perses_admin.cy.ts new file mode 100644 index 000000000..e250158bd --- /dev/null +++ b/web/cypress/e2e/perses/03.coo_create_perses_admin.cy.ts @@ -0,0 +1,44 @@ +import { nav } from '../../views/nav'; +import { runCOOCreatePersesTests } from '../../support/perses/03.coo_create_perses_admin.cy'; + +// Set constants for the operators that need to be installed for tests. +const MCP = { + namespace: 'openshift-cluster-observability-operator', + packageName: 'cluster-observability-operator', + operatorName: 'Cluster Observability Operator', + config: { + kind: 'UIPlugin', + name: 'monitoring', + }, +}; + +const MP = { + namespace: 'openshift-monitoring', + operatorName: 'Cluster Monitoring Operator', +}; + +//TODO: change tag to @dashboards when customizable-dashboards gets merged +describe('COO - Dashboards (Perses) - Create perses dashboard', { tags: ['@perses', '@dashboards-'] }, () => { + + before(() => { + cy.beforeBlockCOO(MCP, MP); + cy.setupPersesRBACandExtraDashboards(); + }); + + beforeEach(() => { + nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); + cy.wait(5000); + cy.changeNamespace('All Projects'); + }); + + after(() => { + cy.cleanupExtraDashboards(); + }); + + runCOOCreatePersesTests({ + name: 'Administrator', + }); + +}); + + diff --git a/web/cypress/e2e/perses/99.coo_rbac_perses_user1.cy.ts b/web/cypress/e2e/perses/99.coo_rbac_perses_user1.cy.ts new file mode 100644 index 000000000..f3e248466 --- /dev/null +++ b/web/cypress/e2e/perses/99.coo_rbac_perses_user1.cy.ts @@ -0,0 +1,78 @@ +import { nav } from '../../views/nav'; +import { runCOORBACPersesTestsDevUser1 } from '../../support/perses/99.coo_rbac_perses_user1.cy'; + + +// Set constants for the operators that need to be installed for tests. +const MCP = { + namespace: 'openshift-cluster-observability-operator', + packageName: 'cluster-observability-operator', + operatorName: 'Cluster Observability Operator', + config: { + kind: 'UIPlugin', + name: 'monitoring', + }, +}; + +const MP = { + namespace: 'openshift-monitoring', + operatorName: 'Cluster Monitoring Operator', +}; + +//TODO: change tag to @smoke, @dashboards, @perses when customizable-dashboards gets merged +describe('BVT: COO - Dashboards (Perses) - Administrator perspective', { tags: ['@smoke-', '@dashboards-', '@perses-dev'] }, () => { + + before(() => { + //TODO: https://issues.redhat.com/browse/OCPBUGS-58468 - when it gets fixed, installation can be don using non-admin user + // Step 1: Grant temporary cluster-admin role to dev user for COO/Perses installation + // cy.log('Granting temporary cluster-admin role to dev user for setup'); + // cy.adminCLI( + // `oc adm policy add-cluster-role-to-user cluster-admin ${Cypress.env('LOGIN_USERNAME')}`, + // ); + + // Step 2: Setup COO and Perses dashboards (requires admin privileges) + cy.beforeBlockCOO(MCP, MP); + cy.setupPersesRBACandExtraDashboards(); + + //TODO: https://issues.redhat.com/browse/OCPBUGS-58468 - when it gets fixed, installation can be don using non-admin user + // Step 3: Remove cluster-admin role - dev user now has limited permissions + // cy.log('Removing cluster-admin role from dev user'); + // cy.adminCLI( + // `oc adm policy remove-cluster-role-from-user cluster-admin ${Cypress.env('LOGIN_USERNAME')}`, + // ); + + // Step 4: Clear Cypress session cache and logout + // This is critical because beforeBlockCOO uses cy.session() which caches the login state + cy.log('Clearing Cypress session cache to ensure fresh login'); + Cypress.session.clearAllSavedSessions(); + + // Clear all cookies and storage to fully reset browser state + cy.clearAllCookies(); + cy.clearAllLocalStorage(); + cy.clearAllSessionStorage(); + + // Step 5: Re-login as dev user (now without cluster-admin role) + // Using cy.relogin() because it doesn't require oauthurl and handles the login page directly + cy.log('Re-logging in as dev user with limited permissions'); + cy.relogin( + Cypress.env('LOGIN_IDP_DEV_USER'), + Cypress.env('LOGIN_USERNAME1'), + Cypress.env('LOGIN_PASSWORD1'), + ); + cy.validateLogin(); + cy.closeOnboardingModalIfPresent(); + }); + + beforeEach(() => { + nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); + }); + + after(() => { + cy.cleanupExtraDashboards(); + }); + + //TODO: rename after customizable-dashboards gets merged + runCOORBACPersesTestsDevUser1({ + name: 'Administrator', + }); + +}); \ No newline at end of file diff --git a/web/cypress/e2e/perses/99.coo_rbac_perses_user2.cy.ts b/web/cypress/e2e/perses/99.coo_rbac_perses_user2.cy.ts new file mode 100644 index 000000000..f3fcea664 --- /dev/null +++ b/web/cypress/e2e/perses/99.coo_rbac_perses_user2.cy.ts @@ -0,0 +1,78 @@ +import { nav } from '../../views/nav'; +import { runCOORBACPersesTestsDevUser2 } from '../../support/perses/99.coo_rbac_perses_user2.cy'; + + +// Set constants for the operators that need to be installed for tests. +const MCP = { + namespace: 'openshift-cluster-observability-operator', + packageName: 'cluster-observability-operator', + operatorName: 'Cluster Observability Operator', + config: { + kind: 'UIPlugin', + name: 'monitoring', + }, +}; + +const MP = { + namespace: 'openshift-monitoring', + operatorName: 'Cluster Monitoring Operator', +}; + +//TODO: change tag to @smoke, @dashboards, @perses when customizable-dashboards gets merged +describe('BVT: COO - Dashboards (Perses) - Administrator perspective', { tags: ['@smoke-', '@dashboards-', '@perses-dev'] }, () => { + + before(() => { + //TODO: https://issues.redhat.com/browse/OCPBUGS-58468 - when it gets fixed, installation can be don using non-admin user + // Step 1: Grant temporary cluster-admin role to dev user for COO/Perses installation + // cy.log('Granting temporary cluster-admin role to dev user for setup'); + // cy.adminCLI( + // `oc adm policy add-cluster-role-to-user cluster-admin ${Cypress.env('LOGIN_USERNAME')}`, + // ); + + // Step 2: Setup COO and Perses dashboards (requires admin privileges) + cy.beforeBlockCOO(MCP, MP); + cy.setupPersesRBACandExtraDashboards(); + + //TODO: https://issues.redhat.com/browse/OCPBUGS-58468 - when it gets fixed, installation can be don using non-admin user + // Step 3: Remove cluster-admin role - dev user now has limited permissions + // cy.log('Removing cluster-admin role from dev user'); + // cy.adminCLI( + // `oc adm policy remove-cluster-role-from-user cluster-admin ${Cypress.env('LOGIN_USERNAME')}`, + // ); + + // Step 4: Clear Cypress session cache and logout + // This is critical because beforeBlockCOO uses cy.session() which caches the login state + cy.log('Clearing Cypress session cache to ensure fresh login'); + Cypress.session.clearAllSavedSessions(); + + // Clear all cookies and storage to fully reset browser state + cy.clearAllCookies(); + cy.clearAllLocalStorage(); + cy.clearAllSessionStorage(); + + // Step 5: Re-login as dev user (now without cluster-admin role) + // Using cy.relogin() because it doesn't require oauthurl and handles the login page directly + cy.log('Re-logging in as dev user with limited permissions'); + cy.relogin( + Cypress.env('LOGIN_IDP_DEV_USER'), + Cypress.env('LOGIN_USERNAME2'), + Cypress.env('LOGIN_PASSWORD2'), + ); + cy.validateLogin(); + cy.closeOnboardingModalIfPresent(); + }); + + beforeEach(() => { + nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); + }); + + after(() => { + cy.cleanupExtraDashboards(); + }); + + //TODO: rename after customizable-dashboards gets merged + runCOORBACPersesTestsDevUser2({ + name: 'Administrator', + }); + +}); \ No newline at end of file diff --git a/web/cypress/e2e/virtualization/00.coo_ivt.cy.ts b/web/cypress/e2e/virtualization/00.coo_ivt.cy.ts index e9ce793c4..7d8d76659 100644 --- a/web/cypress/e2e/virtualization/00.coo_ivt.cy.ts +++ b/web/cypress/e2e/virtualization/00.coo_ivt.cy.ts @@ -1,5 +1,4 @@ import { runBVTMonitoringTests } from '../../support/monitoring/00.bvt_monitoring.cy'; -import { runBVTMonitoringTestsNamespace } from '../../support/monitoring/00.bvt_monitoring_namespace.cy'; import { guidedTour } from '../../views/tour'; import { alerts } from '../../fixtures/monitoring/alert'; import { nav } from '../../views/nav'; diff --git a/web/cypress/e2e/virtualization/01.coo_ivt_alerts.cy.ts b/web/cypress/e2e/virtualization/01.coo_ivt_alerts.cy.ts index 8e2ac841c..5fb460f95 100644 --- a/web/cypress/e2e/virtualization/01.coo_ivt_alerts.cy.ts +++ b/web/cypress/e2e/virtualization/01.coo_ivt_alerts.cy.ts @@ -1,6 +1,5 @@ import { alerts } from '../../fixtures/monitoring/alert'; import { runAllRegressionAlertsTests } from '../../support/monitoring/01.reg_alerts.cy'; -import { runAllRegressionAlertsTestsNamespace } from '../../support/monitoring/04.reg_alerts_namespace.cy'; import { commonPages } from '../../views/common'; import { nav } from '../../views/nav'; import { guidedTour } from '../../views/tour'; diff --git a/web/cypress/e2e/virtualization/04.coo_ivt_perses.cy.ts b/web/cypress/e2e/virtualization/04.coo_ivt_perses.cy.ts index 893ab2857..8905c81e2 100644 --- a/web/cypress/e2e/virtualization/04.coo_ivt_perses.cy.ts +++ b/web/cypress/e2e/virtualization/04.coo_ivt_perses.cy.ts @@ -1,5 +1,5 @@ import { nav } from '../../views/nav'; -import { runBVTCOOPersesTests } from '../../support/perses/00.coo_bvt_perses.cy'; +import { runBVTCOOPersesTests } from '../../support/perses/00.coo_bvt_perses_admin.cy'; import { guidedTour } from '../../views/tour'; import { commonPages } from '../../views/common'; @@ -56,7 +56,7 @@ describe('Installation: Virtualization', { tags: ['@virtualization', '@slow'] }, }); }); -describe('IVT: COO - Dashboards (Perses) - Virtualization perspective', { tags: ['@virtualization', '@dashboards'] }, () => { +describe('IVT: COO - Dashboards (Perses) - Virtualization perspective', { tags: ['@virtualization', '@perses'] }, () => { beforeEach(() => { cy.visit('/'); diff --git a/web/cypress/fixtures/coo/acm-alerrule-test.yaml b/web/cypress/fixtures/coo/acm-alerrule-test.yaml index 5f2b564a1..480209941 100644 --- a/web/cypress/fixtures/coo/acm-alerrule-test.yaml +++ b/web/cypress/fixtures/coo/acm-alerrule-test.yaml @@ -39,4 +39,4 @@ data: labels: cluster: "{{ $labels.cluster }}" prometheus: "{{ $labels.prometheus }}" - severity: critical + severity: critical \ No newline at end of file diff --git a/web/cypress/fixtures/coo/acm-install.sh b/web/cypress/fixtures/coo/acm-install.sh index 661bd0a1f..4aea5333d 100755 --- a/web/cypress/fixtures/coo/acm-install.sh +++ b/web/cypress/fixtures/coo/acm-install.sh @@ -1,7 +1,23 @@ #!/bin/bash -set -eux -oc patch Scheduler cluster --type='json' -p '[{ "op": "replace", "path": "/spec/mastersSchedulable", "value": true }]' +#set -eux +set -x +# This script will install ACM, MCH, MCO, and other test resources. +# The script will skip installation when MCO CR existed. +echo "[INFO] Checking for existing MultiClusterObservability CR..." +MCO_NAMESPACE="open-cluster-management-observability" +MCO_NAME="observability" +# The 'oc get ...' command will have a non-zero exit code if the resource is not found. +if oc get multiclusterobservability ${MCO_NAME} -n ${MCO_NAMESPACE} >/dev/null 2>&1; then + echo "[INFO] MultiClusterObservability CR '${MCO_NAME}' already exists in '${MCO_NAMESPACE}'." + echo "[INFO] Skipping installation to avoid conflicts and assuming a previous step is managing it." + exit 0 +else + echo "[INFO] No existing MultiClusterObservability CR found. Proceeding with installation." +fi +# patch node +oc patch Scheduler cluster --type='json' -p '[{ "op": "replace", "path": "/spec/mastersSchedulable", "value": true }]' +# install acm oc apply -f - </dev/null 2>&1; then echo "[INFO] Creating namespace open-cluster-management-observability" oc create ns open-cluster-management-observability @@ -168,5 +185,64 @@ spec: EOF sleep 1m oc wait --for=condition=Ready pod -l alertmanager=observability,app=multicluster-observability-alertmanager -n open-cluster-management-observability --timeout=300s -oc -n open-cluster-management-observability get pod -oc -n open-cluster-management-observability get svc | grep -E 'alertmanager|rbac-query' +# enable UIPlugin +oc apply -f - < 0 + labels: + cluster: "{{ $labels.cluster }}" + prometheus: "{{ $labels.prometheus }}" + severity: critical +EOF \ No newline at end of file diff --git a/web/cypress/fixtures/coo/acm-uiplugin.yaml b/web/cypress/fixtures/coo/acm-uiplugin.yaml index cda8194f8..557c182b8 100644 --- a/web/cypress/fixtures/coo/acm-uiplugin.yaml +++ b/web/cypress/fixtures/coo/acm-uiplugin.yaml @@ -10,4 +10,4 @@ spec: url: 'https://alertmanager.open-cluster-management-observability.svc:9095' thanosQuerier: url: 'https://rbac-query-proxy.open-cluster-management-observability.svc:8443' - type: Monitoring + type: Monitoring \ No newline at end of file diff --git a/web/cypress/fixtures/coo/acm-uninstall.sh b/web/cypress/fixtures/coo/acm-uninstall.sh index 6193c3486..1f66fca76 100755 --- a/web/cypress/fixtures/coo/acm-uninstall.sh +++ b/web/cypress/fixtures/coo/acm-uninstall.sh @@ -42,4 +42,4 @@ oc delete ns open-cluster-management --ignore-not-found=true # oc get ns open-cluster-management-observability -o json | jq '.spec.finalizers=[]' | oc replace --raw "/api/v1/namespaces/open-cluster-management-observability/finalize" -f - || true # oc get ns open-cluster-management -o json | jq '.spec.finalizers=[]' | oc replace --raw "/api/v1/namespaces/open-cluster-management/finalize" -f - || true -echo "[ACM Uninstall] ✅ Completed cleanup." +echo "[ACM Uninstall] ✅ Completed cleanup." \ No newline at end of file diff --git a/web/cypress/fixtures/coo/openshift-cluster-sample-dashboard.yaml b/web/cypress/fixtures/coo/coo121_perses/dashboards/openshift-cluster-sample-dashboard.yaml similarity index 100% rename from web/cypress/fixtures/coo/openshift-cluster-sample-dashboard.yaml rename to web/cypress/fixtures/coo/coo121_perses/dashboards/openshift-cluster-sample-dashboard.yaml diff --git a/web/cypress/fixtures/coo/perses-dashboard-sample.yaml b/web/cypress/fixtures/coo/coo121_perses/dashboards/perses-dashboard-sample.yaml similarity index 100% rename from web/cypress/fixtures/coo/perses-dashboard-sample.yaml rename to web/cypress/fixtures/coo/coo121_perses/dashboards/perses-dashboard-sample.yaml diff --git a/web/cypress/fixtures/coo/prometheus-overview-variables.yaml b/web/cypress/fixtures/coo/coo121_perses/dashboards/prometheus-overview-variables.yaml similarity index 100% rename from web/cypress/fixtures/coo/prometheus-overview-variables.yaml rename to web/cypress/fixtures/coo/coo121_perses/dashboards/prometheus-overview-variables.yaml diff --git a/web/cypress/fixtures/coo/thanos-compact-overview-1var.yaml b/web/cypress/fixtures/coo/coo121_perses/dashboards/thanos-compact-overview-1var.yaml similarity index 100% rename from web/cypress/fixtures/coo/thanos-compact-overview-1var.yaml rename to web/cypress/fixtures/coo/coo121_perses/dashboards/thanos-compact-overview-1var.yaml diff --git a/web/cypress/fixtures/coo/thanos-querier-datasource.yaml b/web/cypress/fixtures/coo/coo121_perses/dashboards/thanos-querier-datasource.yaml similarity index 100% rename from web/cypress/fixtures/coo/thanos-querier-datasource.yaml rename to web/cypress/fixtures/coo/coo121_perses/dashboards/thanos-querier-datasource.yaml diff --git a/web/cypress/fixtures/coo/coo141_perses/dashboards/openshift-cluster-sample-dashboard.yaml b/web/cypress/fixtures/coo/coo141_perses/dashboards/openshift-cluster-sample-dashboard.yaml new file mode 100644 index 000000000..e8c14b903 --- /dev/null +++ b/web/cypress/fixtures/coo/coo141_perses/dashboards/openshift-cluster-sample-dashboard.yaml @@ -0,0 +1,1041 @@ +apiVersion: perses.dev/v1alpha2 +kind: PersesDashboard +metadata: + name: openshift-cluster-sample-dashboard + namespace: openshift-cluster-observability-operator +spec: + config: + display: + name: Kubernetes / Compute Resources / Cluster + variables: + - kind: ListVariable + spec: + display: + hidden: false + allowAllValue: false + allowMultiple: false + sort: alphabetical-asc + plugin: + kind: PrometheusLabelValuesVariable + spec: + labelName: cluster + matchers: + - up{job="kubelet", metrics_path="/metrics/cadvisor"} + name: cluster + panels: + "0_0": + kind: Panel + spec: + display: + name: CPU Utilisation + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent-decimal + thresholds: + steps: + - color: green + value: 0 + - color: red + value: 80 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: cluster:node_cpu:ratio_rate5m{cluster="$cluster"} + "0_1": + kind: Panel + spec: + display: + name: CPU Requests Commitment + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent-decimal + thresholds: + steps: + - color: green + value: 0 + - color: red + value: 80 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_cpu:kube_pod_container_resource_requests:sum{cluster="$cluster"}) / sum(kube_node_status_allocatable{job="kube-state-metrics",resource="cpu",cluster="$cluster"}) + "0_2": + kind: Panel + spec: + display: + name: CPU Limits Commitment + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent-decimal + thresholds: + steps: + - color: green + value: 0 + - color: red + value: 80 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_cpu:kube_pod_container_resource_limits:sum{cluster="$cluster"}) / sum(kube_node_status_allocatable{job="kube-state-metrics",resource="cpu",cluster="$cluster"}) + "0_3": + kind: Panel + spec: + display: + name: Memory Utilisation + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent-decimal + thresholds: + steps: + - color: green + value: 0 + - color: red + value: 80 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: 1 - sum(:node_memory_MemAvailable_bytes:sum{cluster="$cluster"}) / sum(node_memory_MemTotal_bytes{job="node-exporter",cluster="$cluster"}) + "0_4": + kind: Panel + spec: + display: + name: Memory Requests Commitment + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent-decimal + thresholds: + steps: + - color: green + value: 0 + - color: red + value: 80 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_memory:kube_pod_container_resource_requests:sum{cluster="$cluster"}) / sum(kube_node_status_allocatable{job="kube-state-metrics",resource="memory",cluster="$cluster"}) + "0_5": + kind: Panel + spec: + display: + name: Memory Limits Commitment + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent-decimal + thresholds: + steps: + - color: green + value: 0 + - color: red + value: 80 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_memory:kube_pod_container_resource_limits:sum{cluster="$cluster"}) / sum(kube_node_status_allocatable{job="kube-state-metrics",resource="memory",cluster="$cluster"}) + "1_0": + kind: Panel + spec: + display: + name: CPU Usage + plugin: + kind: TimeSeriesChart + spec: + legend: + mode: list + position: bottom + values: [] + visual: + areaOpacity: 1 + connectNulls: false + display: line + lineWidth: 0.25 + stack: all + yAxis: + format: + unit: decimal + min: 0 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster="$cluster"}) by (namespace) + seriesNameFormat: "{{namespace}}" + "2_0": + kind: Panel + spec: + display: + name: CPU Quota + plugin: + kind: Table + spec: + columnSettings: + - header: Time + hide: true + name: Time + - header: Pods + name: "Value #A" + - header: Workloads + name: "Value #B" + - header: CPU Usage + name: "Value #C" + - header: CPU Requests + name: "Value #D" + - header: CPU Requests % + name: "Value #E" + - header: CPU Limits + name: "Value #F" + - header: CPU Limits % + name: "Value #G" + - header: Namespace + name: namespace + - header: "" + name: /.*/ + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(kube_pod_owner{job="kube-state-metrics", cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: count(avg(namespace_workload_pod:kube_pod_owner:relabel{cluster="$cluster"}) by (workload, namespace)) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_cpu:kube_pod_container_resource_requests:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster="$cluster"}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_requests:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_cpu:kube_pod_container_resource_limits:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster="$cluster"}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_limits:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + "3_0": + kind: Panel + spec: + display: + name: Memory Usage (w/o cache) + plugin: + kind: TimeSeriesChart + spec: + legend: + mode: list + position: bottom + values: [] + visual: + areaOpacity: 1 + connectNulls: false + display: line + lineWidth: 0.25 + stack: all + yAxis: + format: + unit: bytes + min: 0 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(container_memory_rss{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", container!=""}) by (namespace) + seriesNameFormat: "{{namespace}}" + "4_0": + kind: Panel + spec: + display: + name: Requests by Namespace + plugin: + kind: Table + spec: + columnSettings: + - header: Time + hide: true + name: Time + - header: Pods + name: "Value #A" + - header: Workloads + name: "Value #B" + - header: Memory Usage + name: "Value #C" + - header: Memory Requests + name: "Value #D" + - header: Memory Requests % + name: "Value #E" + - header: Memory Limits + name: "Value #F" + - header: Memory Limits % + name: "Value #G" + - header: Namespace + name: namespace + - header: "" + name: /.*/ + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(kube_pod_owner{job="kube-state-metrics", cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: count(avg(namespace_workload_pod:kube_pod_owner:relabel{cluster="$cluster"}) by (workload, namespace)) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(container_memory_rss{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", container!=""}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_memory:kube_pod_container_resource_requests:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(container_memory_rss{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", container!=""}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_requests:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_memory:kube_pod_container_resource_limits:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(container_memory_rss{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", container!=""}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_limits:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + "5_0": + kind: Panel + spec: + display: + name: Current Network Usage + plugin: + kind: Table + spec: + columnSettings: + - header: Time + hide: true + name: Time + - header: Current Receive Bandwidth + name: "Value #A" + - header: Current Transmit Bandwidth + name: "Value #B" + - header: Rate of Received Packets + name: "Value #C" + - header: Rate of Transmitted Packets + name: "Value #D" + - header: Rate of Received Packets Dropped + name: "Value #E" + - header: Rate of Transmitted Packets Dropped + name: "Value #F" + - header: Namespace + name: namespace + - header: "" + name: /.*/ + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_receive_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_transmit_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_receive_packets_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_transmit_packets_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_receive_packets_dropped_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_transmit_packets_dropped_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "" + "6_0": + kind: Panel + spec: + display: + name: Receive Bandwidth + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_receive_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "6_1": + kind: Panel + spec: + display: + name: Transmit Bandwidth + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_transmit_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "7_0": + kind: Panel + spec: + display: + name: "Average Container Bandwidth by Namespace: Received" + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: avg(irate(container_network_receive_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "7_1": + kind: Panel + spec: + display: + name: "Average Container Bandwidth by Namespace: Transmitted" + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: avg(irate(container_network_transmit_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "8_0": + kind: Panel + spec: + display: + name: Rate of Received Packets + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_receive_packets_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "8_1": + kind: Panel + spec: + display: + name: Rate of Transmitted Packets + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_transmit_packets_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "9_0": + kind: Panel + spec: + display: + name: Rate of Received Packets Dropped + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_receive_packets_dropped_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "9_1": + kind: Panel + spec: + display: + name: Rate of Transmitted Packets Dropped + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_transmit_packets_dropped_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "10_0": + kind: Panel + spec: + display: + name: IOPS(Reads+Writes) + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: ceil(sum by(namespace) (rate(container_fs_reads_total{job="kubelet", metrics_path="/metrics/cadvisor", id!="", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", cluster="$cluster", namespace!=""}[$__rate_interval]) + rate(container_fs_writes_total{job="kubelet", metrics_path="/metrics/cadvisor", id!="", cluster="$cluster", namespace!=""}[$__rate_interval]))) + seriesNameFormat: "{{namespace}}" + "10_1": + kind: Panel + spec: + display: + name: ThroughPut(Read+Write) + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_reads_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", id!="", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", cluster="$cluster", namespace!=""}[$__rate_interval]) + rate(container_fs_writes_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "{{namespace}}" + "11_0": + kind: Panel + spec: + display: + name: Current Storage IO + plugin: + kind: Table + spec: + columnSettings: + - header: Time + hide: true + name: Time + - header: IOPS(Reads) + name: "Value #A" + - header: IOPS(Writes) + name: "Value #B" + - header: IOPS(Reads + Writes) + name: "Value #C" + - header: Throughput(Read) + name: "Value #D" + - header: Throughput(Write) + name: "Value #E" + - header: Throughput(Read + Write) + name: "Value #F" + - header: Namespace + name: namespace + - header: "" + name: /.*/ + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_reads_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_writes_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_reads_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval]) + rate(container_fs_writes_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_reads_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_writes_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_reads_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval]) + rate(container_fs_writes_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "" + layouts: + - kind: Grid + spec: + display: + title: Headlines + collapse: + open: true + items: + - x: 0 + "y": 1 + width: 4 + height: 3 + content: + $ref: "#/spec/panels/0_0" + - x: 4 + "y": 1 + width: 4 + height: 3 + content: + $ref: "#/spec/panels/0_1" + - x: 8 + "y": 1 + width: 4 + height: 3 + content: + $ref: "#/spec/panels/0_2" + - x: 12 + "y": 1 + width: 4 + height: 3 + content: + $ref: "#/spec/panels/0_3" + - x: 16 + "y": 1 + width: 4 + height: 3 + content: + $ref: "#/spec/panels/0_4" + - x: 20 + "y": 1 + width: 4 + height: 3 + content: + $ref: "#/spec/panels/0_5" + - kind: Grid + spec: + display: + title: CPU + collapse: + open: true + items: + - x: 0 + "y": 5 + width: 24 + height: 7 + content: + $ref: "#/spec/panels/1_0" + - kind: Grid + spec: + display: + title: CPU Quota + collapse: + open: true + items: + - x: 0 + "y": 13 + width: 24 + height: 7 + content: + $ref: "#/spec/panels/2_0" + - kind: Grid + spec: + display: + title: Memory + collapse: + open: true + items: + - x: 0 + "y": 21 + width: 24 + height: 7 + content: + $ref: "#/spec/panels/3_0" + - kind: Grid + spec: + display: + title: Memory Requests + collapse: + open: true + items: + - x: 0 + "y": 29 + width: 24 + height: 7 + content: + $ref: "#/spec/panels/4_0" + - kind: Grid + spec: + display: + title: Current Network Usage + collapse: + open: true + items: + - x: 0 + "y": 37 + width: 24 + height: 7 + content: + $ref: "#/spec/panels/5_0" + - kind: Grid + spec: + display: + title: Bandwidth + collapse: + open: true + items: + - x: 0 + "y": 45 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/6_0" + - x: 12 + "y": 45 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/6_1" + - kind: Grid + spec: + display: + title: Average Container Bandwidth by Namespace + collapse: + open: true + items: + - x: 0 + "y": 53 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/7_0" + - x: 12 + "y": 53 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/7_1" + - kind: Grid + spec: + display: + title: Rate of Packets + collapse: + open: true + items: + - x: 0 + "y": 61 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/8_0" + - x: 12 + "y": 61 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/8_1" + - kind: Grid + spec: + display: + title: Rate of Packets Dropped + collapse: + open: true + items: + - x: 0 + "y": 69 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/9_0" + - x: 12 + "y": 69 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/9_1" + - kind: Grid + spec: + display: + title: Storage IO + collapse: + open: true + items: + - x: 0 + "y": 77 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/10_0" + - x: 12 + "y": 77 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/10_1" + - kind: Grid + spec: + display: + title: Storage IO - Distribution + collapse: + open: true + items: + - x: 0 + "y": 85 + width: 24 + height: 7 + content: + $ref: "#/spec/panels/11_0" + duration: 1h \ No newline at end of file diff --git a/web/cypress/fixtures/coo/coo141_perses/dashboards/perses-dashboard-sample.yaml b/web/cypress/fixtures/coo/coo141_perses/dashboards/perses-dashboard-sample.yaml new file mode 100644 index 000000000..43e3dfe4e --- /dev/null +++ b/web/cypress/fixtures/coo/coo141_perses/dashboards/perses-dashboard-sample.yaml @@ -0,0 +1,564 @@ +apiVersion: perses.dev/v1alpha2 +kind: PersesDashboard +metadata: + name: perses-dashboard-sample + namespace: perses-dev +spec: + config: + display: + name: Perses Dashboard Sample + description: This is a sample dashboard + duration: 5m + datasources: + PrometheusLocal: + default: false + plugin: + kind: PrometheusDatasource + spec: + proxy: + kind: HTTPProxy + spec: + url: http://localhost:9090 + variables: + - kind: ListVariable + spec: + name: job + allowMultiple: false + allowAllValue: false + plugin: + kind: PrometheusLabelValuesVariable + spec: + labelName: job + - kind: ListVariable + spec: + name: instance + allowMultiple: false + allowAllValue: false + plugin: + kind: PrometheusLabelValuesVariable + spec: + labelName: instance + matchers: + - up{job=~"$job"} + - kind: ListVariable + spec: + name: interval + plugin: + kind: StaticListVariable + spec: + values: + - 1m + - 5m + - kind: TextVariable + spec: + name: text + value: test + constant: true + panels: + defaultTimeSeriesChart: + kind: Panel + spec: + display: + name: Default Time Series Panel + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: up + seriesTest: + kind: Panel + spec: + display: + name: "~130 Series" + description: This is a line chart + plugin: + kind: TimeSeriesChart + spec: + yAxis: + format: + unit: bytes + shortValues: true + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: rate(caddy_http_response_duration_seconds_sum[$interval]) + basicEx: + kind: Panel + spec: + display: + name: Single Query + plugin: + kind: TimeSeriesChart + spec: + yAxis: + format: + unit: decimal + legend: + position: right + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: Node memory - {{device}} {{instance}} + query: + 1 - node_filesystem_free_bytes{job='$job',instance=~'$instance',fstype!="rootfs",mountpoint!~"/(run|var).*",mountpoint!=""} + / node_filesystem_size_bytes{job='$job',instance=~'$instance'} + legendEx: + kind: Panel + spec: + display: + name: Legend Example + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + yAxis: + show: true + format: + unit: bytes + shortValues: true + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: Node memory total + query: + node_memory_MemTotal_bytes{job='$job',instance=~'$instance'} + - node_memory_MemFree_bytes{job='$job',instance=~'$instance'} - + node_memory_Buffers_bytes{job='$job',instance=~'$instance'} - node_memory_Cached_bytes{job='$job',instance=~'$instance'} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: Memory (buffers) - {{instance}} + query: node_memory_Buffers_bytes{job='$job',instance=~'$instance'} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: Cached Bytes + query: node_memory_Cached_bytes{job='$job',instance=~'$instance'} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: MemFree Bytes + query: node_memory_MemFree_bytes{job='$job',instance=~'$instance'} + testNodeQuery: + kind: Panel + spec: + display: + name: Test Query + description: Description text + plugin: + kind: TimeSeriesChart + spec: + yAxis: + format: + unit: decimal + decimalPlaces: 2 + legend: + position: right + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: node_load15{instance=~"(demo.do.prometheus.io:9100)",job='$job'} + seriesNameFormat: Test {{job}} {{instance}} + testQueryAlt: + kind: Panel + spec: + display: + name: Test Query Alt + description: Description text + plugin: + kind: TimeSeriesChart + spec: + legend: + position: right + yAxis: + format: + unit: percent-decimal + decimalPlaces: 1 + thresholds: + steps: + - value: 0.4 + name: "Alert: Warning condition example" + - value: 0.75 + name: "Alert: Critical condition example" + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: node_load1{instance=~"(demo.do.prometheus.io:9100)",job='$job'} + cpuLine: + kind: Panel + spec: + display: + name: CPU - Line (Multi Series) + description: This is a line chart test + plugin: + kind: TimeSeriesChart + spec: + yAxis: + show: false + label: CPU Label + format: + unit: percent-decimal + decimalPlaces: 0 + legend: + position: bottom + thresholds: + steps: + - value: 0.2 + - value: 0.35 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: "{{mode}} mode - {{job}} {{instance}}" + query: avg without (cpu)(rate(node_cpu_seconds_total{job='$job',instance=~'$instance',mode!="nice",mode!="steal",mode!="irq"}[$interval])) + cpuGauge: + kind: Panel + spec: + display: + name: CPU - Gauge (Multi Series) + description: This is a gauge chart test + plugin: + kind: GaugeChart + spec: + calculation: last-number + format: + unit: percent-decimal + thresholds: + steps: + - value: 0.2 + - value: 0.35 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: "{{mode}} mode - {{job}} {{instance}}" + query: avg without (cpu)(rate(node_cpu_seconds_total{job='$job',instance=~'$instance',mode!="nice",mode!="steal",mode!="irq"}[$interval])) + statSm: + kind: Panel + spec: + display: + name: Stat Sm + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: decimal + decimalPlaces: 1 + shortValues: true + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: node_time_seconds{job='$job',instance=~'$instance'} - node_boot_time_seconds{job='$job',instance=~'$instance'} + gaugeRAM: + kind: Panel + spec: + display: + name: RAM Used + description: This is a stat chart + plugin: + kind: GaugeChart + spec: + calculation: last-number + format: + unit: percent + thresholds: + steps: + - value: 85 + - value: 95 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: + 100 - ((node_memory_MemAvailable_bytes{job='$job',instance=~'$instance'} + * 100) / node_memory_MemTotal_bytes{job='$job',instance=~'$instance'}) + statRAM: + kind: Panel + spec: + display: + name: RAM Used + description: This is a stat chart + plugin: + kind: StatChart + spec: + calculation: last-number + format: + unit: percent + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: + 100 - ((node_memory_MemAvailable_bytes{job='$job',instance=~'$instance'} + * 100) / node_memory_MemTotal_bytes{job='$job',instance=~'$instance'}) + statTotalRAM: + kind: Panel + spec: + display: + name: RAM Total + description: This is a stat chart + plugin: + kind: StatChart + spec: + calculation: last-number + format: + unit: bytes + decimalPlaces: 1 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: node_memory_MemTotal_bytes{job='$job',instance=~'$instance'} + statMd: + kind: Panel + spec: + display: + name: Stat Md + plugin: + kind: StatChart + spec: + calculation: sum + format: + unit: decimal + decimalPlaces: 2 + shortValues: true + sparkline: + color: "#e65013" + width: 1.5 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: + avg(node_load15{job='node',instance=~'$instance'}) / count(count(node_cpu_seconds_total{job='node',instance=~'$instance'}) + by (cpu)) * 100 + statLg: + kind: Panel + spec: + display: + name: Stat Lg + description: This is a stat chart + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: + (((count(count(node_cpu_seconds_total{job='$job',instance=~'$instance'}) + by (cpu))) - avg(sum by (mode)(rate(node_cpu_seconds_total{mode="idle",job='$job',instance=~'$instance'}[$interval])))) + * 100) / count(count(node_cpu_seconds_total{job='$job',instance=~'$instance'}) + by (cpu)) + gaugeEx: + kind: Panel + spec: + display: + name: Gauge Ex + description: This is a gauge chart + plugin: + kind: GaugeChart + spec: + calculation: last-number + format: + unit: percent + thresholds: + steps: + - value: 85 + - value: 95 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: + (((count(count(node_cpu_seconds_total{job='$job',instance=~'$instance'}) + by (cpu))) - avg(sum by (mode)(rate(node_cpu_seconds_total{mode="idle",job='$job',instance=~'$instance'}[$interval])))) + * 100) / count(count(node_cpu_seconds_total{job='$job',instance=~'$instance'}) + by (cpu)) + gaugeAltEx: + kind: Panel + spec: + display: + name: Gauge Alt Ex + description: GaugeChart description text + plugin: + kind: GaugeChart + spec: + calculation: last-number + format: + unit: percent-decimal + decimalPlaces: 1 + thresholds: + steps: + - value: 0.5 + name: "Alert: Warning condition example" + - value: 0.75 + name: "Alert: Critical condition example" + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: node_load15{instance=~'$instance',job='$job'} + gaugeFormatTest: + kind: Panel + spec: + display: + name: Gauge Format Test + plugin: + kind: GaugeChart + spec: + calculation: last-number + format: + unit: bytes + max: 95000000 + thresholds: + steps: + - value: 71000000 + - value: 82000000 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: node_time_seconds{job='$job',instance=~'$instance'} - node_boot_time_seconds{job='$job',instance=~'$instance'} + layouts: + - kind: Grid + spec: + display: + title: Row 1 + collapse: + open: true + items: + - x: 0 + "y": 0 + width: 2 + height: 3 + content: + "$ref": "#/spec/panels/statRAM" + - x: 0 + "y": 4 + width: 2 + height: 3 + content: + "$ref": "#/spec/panels/statTotalRAM" + - x: 2 + "y": 0 + width: 4 + height: 6 + content: + "$ref": "#/spec/panels/statMd" + - x: 6 + "y": 0 + width: 10 + height: 6 + content: + "$ref": "#/spec/panels/statLg" + - x: 16 + "y": 0 + width: 4 + height: 6 + content: + "$ref": "#/spec/panels/gaugeFormatTest" + - x: 20 + "y": 0 + width: 4 + height: 6 + content: + "$ref": "#/spec/panels/gaugeRAM" + - kind: Grid + spec: + display: + title: Row 2 + collapse: + open: true + items: + - x: 0 + "y": 0 + width: 12 + height: 6 + content: + "$ref": "#/spec/panels/legendEx" + - x: 12 + "y": 0 + width: 12 + height: 6 + content: + "$ref": "#/spec/panels/basicEx" + - kind: Grid + spec: + display: + title: Row 3 + collapse: + open: false + items: + - x: 0 + "y": 0 + width: 24 + height: 6 + content: + "$ref": "#/spec/panels/cpuGauge" + - x: 0 + "y": 6 + width: 12 + height: 8 + content: + "$ref": "#/spec/panels/cpuLine" + - x: 12 + "y": 0 + width: 12 + height: 8 + content: + "$ref": "#/spec/panels/defaultTimeSeriesChart" \ No newline at end of file diff --git a/web/cypress/fixtures/coo/coo141_perses/dashboards/prometheus-overview-variables.yaml b/web/cypress/fixtures/coo/coo141_perses/dashboards/prometheus-overview-variables.yaml new file mode 100644 index 000000000..6c8c4439a --- /dev/null +++ b/web/cypress/fixtures/coo/coo141_perses/dashboards/prometheus-overview-variables.yaml @@ -0,0 +1,461 @@ +apiVersion: perses.dev/v1alpha2 +kind: PersesDashboard +metadata: + name: prometheus-overview + namespace: perses-dev +spec: + config: + display: + name: Prometheus / Overview + variables: + - kind: ListVariable + spec: + display: + name: job + hidden: false + allowAllValue: false + allowMultiple: false + plugin: + kind: PrometheusLabelValuesVariable + spec: + datasource: + kind: PrometheusDatasource + + labelName: job + matchers: + - prometheus_build_info{} + name: job + - kind: ListVariable + spec: + display: + name: instance + hidden: false + allowAllValue: false + allowMultiple: false + plugin: + kind: PrometheusLabelValuesVariable + spec: + datasource: + kind: PrometheusDatasource + + labelName: instance + matchers: + - prometheus_build_info{job="$job"} + name: instance + panels: + "0_0": + kind: Panel + spec: + display: + name: Prometheus Stats + plugin: + kind: Table + spec: + columnSettings: + - name: job + header: Job + - name: instance + header: Instance + - name: version + header: Version + - name: value + hide: true + - name: timestamp + hide: true + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: count by (job, instance, version) (prometheus_build_info{instance=~"$instance",job=~"$job"}) + "1_0": + kind: Panel + spec: + display: + name: Target Sync + description: Monitors target synchronization time for Prometheus instances + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (job, scrape_job, instance) ( + rate(prometheus_target_sync_length_seconds_sum{instance=~"$instance",job=~"$job"}[$__rate_interval]) + ) + seriesNameFormat: "{{job}} - {{instance}} - Metrics" + "1_1": + kind: Panel + spec: + display: + name: Targets + description: Shows discovered targets across Prometheus instances + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by (job, instance) (prometheus_sd_discovered_targets{instance=~"$instance",job=~"$job"}) + seriesNameFormat: "{{job}} - {{instance}} - Metrics" + "2_0": + kind: Panel + spec: + display: + name: Average Scrape Interval Duration + description: Shows average interval between scrapes for Prometheus targets + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |4- + rate( + prometheus_target_interval_length_seconds_sum{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + / + rate( + prometheus_target_interval_length_seconds_count{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + seriesNameFormat: "{{job}} - {{instance}} - {{interval}} Configured" + "2_1": + kind: Panel + spec: + display: + name: Scrape failures + description: Shows scrape failure metrics for Prometheus targets + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (job, instance) ( + rate( + prometheus_target_scrapes_exceeded_body_size_limit_total{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + ) + seriesNameFormat: "exceeded body size limit: {{job}} - {{instance}} - Metrics" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (job, instance) ( + rate( + prometheus_target_scrapes_exceeded_sample_limit_total{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + ) + seriesNameFormat: "exceeded sample limit: {{job}} - {{instance}} - Metrics" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (job, instance) ( + rate( + prometheus_target_scrapes_sample_duplicate_timestamp_total{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + ) + seriesNameFormat: "duplicate timestamp: {{job}} - {{instance}} - Metrics" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (job, instance) ( + rate( + prometheus_target_scrapes_sample_out_of_bounds_total{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + ) + seriesNameFormat: "out of bounds: {{job}} - {{instance}} - Metrics" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (job, instance) ( + rate( + prometheus_target_scrapes_sample_out_of_order_total{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + ) + seriesNameFormat: "out of order: {{job}} - {{instance}} - Metrics" + "2_2": + kind: Panel + spec: + display: + name: Appended Samples + description: Shows rate of samples appended to Prometheus TSDB + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + rate( + prometheus_tsdb_head_samples_appended_total{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + seriesNameFormat: "{{job}} - {{instance}} - {{remote_name}} - {{url}}" + "3_0": + kind: Panel + spec: + display: + name: Head Series + description: Shows number of series in Prometheus TSDB head + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: prometheus_tsdb_head_series{instance=~"$instance",job=~"$job"} + seriesNameFormat: "{{job}} - {{instance}} - Head Series" + "3_1": + kind: Panel + spec: + display: + name: Head Chunks + description: Shows number of chunks in Prometheus TSDB head + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: prometheus_tsdb_head_chunks{instance=~"$instance",job=~"$job"} + seriesNameFormat: "{{job}} - {{instance}} - Head Chunks" + "4_0": + kind: Panel + spec: + display: + name: Query Rate + description: Shows Prometheus query rate metrics + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + rate( + prometheus_engine_query_duration_seconds_count{instance=~"$instance",job=~"$job",slice="inner_eval"}[$__rate_interval] + ) + seriesNameFormat: "{{job}} - {{instance}} - Query Rate" + "4_1": + kind: Panel + spec: + display: + name: Stage Duration + description: Shows duration of different Prometheus query stages + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + max by (slice) ( + prometheus_engine_query_duration_seconds{instance=~"$instance",job=~"$job",quantile="0.9"} + ) + seriesNameFormat: "{{slice}} - Duration" + layouts: + - kind: Grid + spec: + display: + title: Prometheus Stats + items: + - x: 0 + "y": 0 + width: 24 + height: 8 + content: + $ref: "#/spec/panels/0_0" + - kind: Grid + spec: + display: + title: Discovery + items: + - x: 0 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/1_0" + - x: 12 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/1_1" + - kind: Grid + spec: + display: + title: Retrieval + items: + - x: 0 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/2_0" + - x: 8 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/2_1" + - x: 16 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/2_2" + - kind: Grid + spec: + display: + title: Storage + items: + - x: 0 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/3_0" + - x: 12 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/3_1" + - kind: Grid + spec: + display: + title: Query + items: + - x: 0 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/4_0" + - x: 12 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/4_1" + duration: 1h \ No newline at end of file diff --git a/web/cypress/fixtures/coo/coo141_perses/dashboards/thanos-compact-overview-1var.yaml b/web/cypress/fixtures/coo/coo141_perses/dashboards/thanos-compact-overview-1var.yaml new file mode 100644 index 000000000..caa580603 --- /dev/null +++ b/web/cypress/fixtures/coo/coo141_perses/dashboards/thanos-compact-overview-1var.yaml @@ -0,0 +1,1421 @@ +apiVersion: perses.dev/v1alpha2 +kind: PersesDashboard +metadata: + name: thanos-compact-overview + namespace: perses-dev +spec: + config: + display: + name: Thanos / Compact / Overview + variables: + - kind: ListVariable + spec: + display: + name: job + hidden: false + allowAllValue: false + allowMultiple: true + plugin: + kind: PrometheusLabelValuesVariable + spec: + datasource: + kind: PrometheusDatasource + + labelName: job + matchers: + - thanos_build_info{container="thanos-compact"} + name: job + - kind: ListVariable + spec: + display: + name: namespace + hidden: false + allowAllValue: false + allowMultiple: false + plugin: + kind: PrometheusLabelValuesVariable + spec: + datasource: + kind: PrometheusDatasource + + labelName: namespace + matchers: + - thanos_status{} + name: namespace + panels: + "0_0": + kind: Panel + spec: + display: + name: TODO Compaction Blocks + description: Shows number of blocks planned to be compacted. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by (namespace, job) (thanos_compact_todo_compaction_blocks{job=~"$job",namespace="$namespace"}) + seriesNameFormat: "{{job}} {{namespace}}" + "0_1": + kind: Panel + spec: + display: + name: TODO Compactions + description: Shows number of compaction operations to be done. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by (namespace, job) (thanos_compact_todo_compactions{job=~"$job",namespace="$namespace"}) + seriesNameFormat: "{{job}} {{namespace}}" + "0_2": + kind: Panel + spec: + display: + name: TODO Deletions + description: Shows number of blocks that have crossed their retention periods. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by (namespace, job) (thanos_compact_todo_deletion_blocks{job=~"$job",namespace="$namespace"}) + seriesNameFormat: "{{job}} {{namespace}}" + "0_3": + kind: Panel + spec: + display: + name: TODO Downsamples + description: Shows number of blocks to be downsampled. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by (namespace, job) (thanos_compact_todo_downsample_blocks{job=~"$job",namespace="$namespace"}) + seriesNameFormat: "{{job}} {{namespace}}" + "1_0": + kind: Panel + spec: + display: + name: Group Compactions + description: Shows rate of execution of compaction operations against blocks in a bucket, split by compaction resolution. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job, resolution) ( + rate(thanos_compact_group_compactions_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + seriesNameFormat: "Resolution: {{resolution}} - {{job}} {{namespace}}" + "1_1": + kind: Panel + spec: + display: + name: Group Compaction Errors + description: Shows the percentage of errors compared to the total number of executed compaction operations against blocks stored in bucket. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: percent + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |4- + sum by (namespace, job) ( + rate( + thanos_compact_group_compactions_failures_total{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + / + sum by (namespace, job) ( + rate(thanos_compact_group_compactions_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + * + 100 + seriesNameFormat: "{{job}} {{namespace}}" + "2_0": + kind: Panel + spec: + display: + name: Downsample Rate + description: Shows rate of execution of downsample operations against blocks stored in a bucket, split by resolution. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job, resolution) ( + rate(thanos_compact_downsample_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + seriesNameFormat: "Resolution: {{resolution}} - {{job}} {{namespace}}" + "2_1": + kind: Panel + spec: + display: + name: Downsample Errors + description: Shows the percentage of downsample errors compared to the total number of downsample operations done on block in buckets. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: percent + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |4- + sum by (namespace, job) ( + rate(thanos_compact_downsample_failed_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + / + sum by (namespace, job) ( + rate(thanos_compact_downsample_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + * + 100 + seriesNameFormat: "{{job}} {{namespace}}" + "2_2": + kind: Panel + spec: + display: + name: Downsample Durations + description: Shows the p50, p90, and p99 of the time it takes to complete downsample operation against blocks in a bucket, split by resolution. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.5, + sum by (namespace, job, resolution, le) ( + rate( + thanos_compact_downsample_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: "p50 Resolution: {{resolution}} - {{job}} {{namespace}}" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.9, + sum by (namespace, job, resolution, le) ( + rate( + thanos_compact_downsample_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: "p90 Resolution: {{resolution}} - {{job}} {{namespace}}" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.99, + sum by (namespace, job, resolution, le) ( + rate( + thanos_compact_downsample_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: "p99 Resolution: {{resolution}} - {{job}} {{namespace}}" + "3_0": + kind: Panel + spec: + display: + name: Sync Meta Rate + description: Shows rate of syncing block meta files from bucket into memory. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job) ( + rate(thanos_blocks_meta_syncs_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + seriesNameFormat: "{{job}} {{namespace}}" + "3_1": + kind: Panel + spec: + display: + name: Sync Meta Errors + description: Shows percentage of errors of meta file sync operation compared to total number of meta file syncs from bucket. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: percent + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |4- + sum by (namespace, job) ( + rate(thanos_blocks_meta_sync_failures_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + / + sum by (namespace, job) ( + rate(thanos_blocks_meta_syncs_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + * + 100 + seriesNameFormat: "{{job}} {{namespace}}" + "3_2": + kind: Panel + spec: + display: + name: Sync Meta Durations + description: Shows p50, p90 and p99 durations of the time it takes to sync meta files from blocks in bucket. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.5, + sum by (namespace, job, le) ( + rate( + thanos_blocks_meta_sync_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p50 {{job}} {{namespace}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.9, + sum by (namespace, job, le) ( + rate( + thanos_blocks_meta_sync_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p90 {{job}} {{namespace}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.99, + sum by (namespace, job, le) ( + rate( + thanos_blocks_meta_sync_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p99 {{job}} {{namespace}} + "4_0": + kind: Panel + spec: + display: + name: Deletion Rate + description: Shows the deletion rate of blocks already marked for deletion. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job) ( + rate(thanos_compact_blocks_cleaned_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + seriesNameFormat: "{{job}} {{namespace}}" + "4_1": + kind: Panel + spec: + display: + name: Deletion Errors + description: Shows rate of deletion failures for blocks already marked for deletion. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job) ( + rate( + thanos_compact_block_cleanup_failures_total{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + seriesNameFormat: "{{job}} {{namespace}}" + "4_2": + kind: Panel + spec: + display: + name: Marking Rate + description: Shows the rate at which blocks are marked for deletion (from GC and retention policy). + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job) ( + rate( + thanos_compact_blocks_marked_total{job=~"$job",marker="deletion-mark.json",namespace="$namespace"}[$__rate_interval] + ) + ) + seriesNameFormat: "{{job}} {{namespace}}" + "5_0": + kind: Panel + spec: + display: + name: Bucket Operations + description: Shows rate of executions of operations against object storage bucket. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: requests/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job, operation) ( + rate(thanos_objstore_bucket_operations_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + seriesNameFormat: "{{job}} {{operation}} {{namespace}}" + "5_1": + kind: Panel + spec: + display: + name: Bucket Operation Errors + description: Shows percentage of errors of operations against object storage bucket. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: percent + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |4- + sum by (namespace, job, operation) ( + rate( + thanos_objstore_bucket_operation_failures_total{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + / + sum by (namespace, job, operation) ( + rate(thanos_objstore_bucket_operations_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + * + 100 + seriesNameFormat: "{{job}} {{operation}} {{namespace}}" + "5_2": + kind: Panel + spec: + display: + name: Bucket Operation Latency + description: Shows latency of operations against object storage bucket. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.99, + sum by (namespace, job, operation, le) ( + rate( + thanos_objstore_bucket_operation_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p99 {{job}} {{operation}} {{namespace}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.9, + sum by (namespace, job, operation, le) ( + rate( + thanos_objstore_bucket_operation_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p90 {{job}} {{operation}} {{namespace}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.5, + sum by (namespace, job, operation, le) ( + rate( + thanos_objstore_bucket_operation_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p50 {{job}} {{operation}} {{namespace}} + "6_0": + kind: Panel + spec: + display: + name: Halted Compactors + description: Shows compactors that have been halted due to unexpected errors. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by (namespace, job) (thanos_compact_halted{job=~"$job",namespace="$namespace"}) + seriesNameFormat: "{{job}} {{namespace}}" + "7_0": + kind: Panel + spec: + display: + name: Garbage Collection + description: Shows rate of execution of removal of blocks, if their data is available as part of a block with a higher compaction level. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job) ( + rate(thanos_compact_garbage_collection_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + seriesNameFormat: "{{job}} {{namespace}}" + "7_1": + kind: Panel + spec: + display: + name: Garbage Collection Errors + description: Shows the percentage of garbage collection operations that resulted in errors. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: percent + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |4- + sum by (namespace, job) ( + rate( + thanos_compact_garbage_collection_failures_total{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + / + sum by (namespace, job) ( + rate(thanos_compact_garbage_collection_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + * + 100 + seriesNameFormat: "{{job}} {{namespace}}" + "7_2": + kind: Panel + spec: + display: + name: Garbage Collection Durations + description: Shows p50, p90 and p99 of how long it takes to execute garbage collection operations. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.5, + sum by (namespace, job, le) ( + rate( + thanos_compact_garbage_collection_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p50 {{job}} {{namespace}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.9, + sum by (namespace, job, le) ( + rate( + thanos_compact_garbage_collection_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p90 {{job}} {{namespace}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.99, + sum by (namespace, job, le) ( + rate( + thanos_compact_garbage_collection_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p99 {{job}} {{namespace}} + "8_0": + kind: Panel + spec: + display: + name: CPU Usage + description: Shows the CPU usage of the component. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + values: + - last + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: rate(process_cpu_seconds_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + seriesNameFormat: "{{pod}}" + "8_1": + kind: Panel + spec: + display: + name: Memory Usage + description: Shows various memory usage metrics of the component. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + values: + - last + yAxis: + format: + unit: bytes + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: go_memstats_alloc_bytes{job=~"$job",namespace="$namespace"} + seriesNameFormat: Alloc All {{pod}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: go_memstats_heap_alloc_bytes{job=~"$job",namespace="$namespace"} + seriesNameFormat: Alloc Heap {{pod}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: rate(go_memstats_alloc_bytes_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + seriesNameFormat: Alloc Rate All {{pod}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: rate(go_memstats_heap_alloc_bytes{job=~"$job",namespace="$namespace"}[$__rate_interval]) + seriesNameFormat: Alloc Rate Heap {{pod}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: go_memstats_stack_inuse_bytes{job=~"$job",namespace="$namespace"} + seriesNameFormat: Inuse Stack {{pod}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: go_memstats_heap_inuse_bytes{job=~"$job",namespace="$namespace"} + seriesNameFormat: Inuse Heap {{pod}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: process_resident_memory_bytes{job=~"$job",namespace="$namespace"} + seriesNameFormat: Resident Memory {{pod}} + "8_2": + kind: Panel + spec: + display: + name: Goroutines + description: Shows the number of goroutines being used by the component. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + values: + - last + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: go_goroutines{job=~"$job",namespace="$namespace"} + seriesNameFormat: "{{pod}}" + "8_3": + kind: Panel + spec: + display: + name: GC Duration + description: Shows the Go garbage collection pause durations for the component. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + values: + - last + yAxis: + format: + unit: seconds + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: go_gc_duration_seconds{job=~"$job",namespace="$namespace"} + seriesNameFormat: "{{quantile}} - {{pod}}" + layouts: + - kind: Grid + spec: + display: + title: TODO Operations + items: + - x: 0 + "y": 0 + width: 6 + height: 6 + content: + $ref: "#/spec/panels/0_0" + - x: 6 + "y": 0 + width: 6 + height: 6 + content: + $ref: "#/spec/panels/0_1" + - x: 12 + "y": 0 + width: 6 + height: 6 + content: + $ref: "#/spec/panels/0_2" + - x: 18 + "y": 0 + width: 6 + height: 6 + content: + $ref: "#/spec/panels/0_3" + - kind: Grid + spec: + display: + title: Group Compactions + items: + - x: 0 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/1_0" + - x: 12 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/1_1" + - kind: Grid + spec: + display: + title: Downsample Operations + items: + - x: 0 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/2_0" + - x: 8 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/2_1" + - x: 16 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/2_2" + - kind: Grid + spec: + display: + title: Sync Meta + items: + - x: 0 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/3_0" + - x: 8 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/3_1" + - x: 16 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/3_2" + - kind: Grid + spec: + display: + title: Block Deletion + items: + - x: 0 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/4_0" + - x: 8 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/4_1" + - x: 16 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/4_2" + - kind: Grid + spec: + display: + title: Bucket Operations + items: + - x: 0 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/5_0" + - x: 8 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/5_1" + - x: 16 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/5_2" + - kind: Grid + spec: + display: + title: Halted Compactors + items: + - x: 0 + "y": 0 + width: 24 + height: 8 + content: + $ref: "#/spec/panels/6_0" + - kind: Grid + spec: + display: + title: Garbage Collection + items: + - x: 0 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/7_0" + - x: 8 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/7_1" + - x: 16 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/7_2" + - kind: Grid + spec: + display: + title: Resources + items: + - x: 0 + "y": 0 + width: 6 + height: 8 + content: + $ref: "#/spec/panels/8_0" + - x: 6 + "y": 0 + width: 6 + height: 8 + content: + $ref: "#/spec/panels/8_1" + - x: 12 + "y": 0 + width: 6 + height: 8 + content: + $ref: "#/spec/panels/8_2" + - x: 18 + "y": 0 + width: 6 + height: 8 + content: + $ref: "#/spec/panels/8_3" + duration: 1h \ No newline at end of file diff --git a/web/cypress/fixtures/coo/coo141_perses/dashboards/thanos-querier-datasource.yaml b/web/cypress/fixtures/coo/coo141_perses/dashboards/thanos-querier-datasource.yaml new file mode 100644 index 000000000..3303b8e4f --- /dev/null +++ b/web/cypress/fixtures/coo/coo141_perses/dashboards/thanos-querier-datasource.yaml @@ -0,0 +1,24 @@ +apiVersion: perses.dev/v1alpha2 +kind: PersesDatasource +metadata: + name: thanos-querier-datasource + namespace: perses-dev +spec: + config: + display: + name: "Thanos Querier Datasource" + default: true + plugin: + kind: "PrometheusDatasource" + spec: + proxy: + kind: HTTPProxy + spec: + url: https://thanos-querier.openshift-monitoring.svc.cluster.local:9091 + secret: thanos-querier-datasource-secret + client: + tls: + enable: true + caCert: + type: file + certPath: /ca/service-ca.crt \ No newline at end of file diff --git a/web/cypress/fixtures/coo/coo141_perses/rbac/rbac_perses_e2e_ci_users.sh b/web/cypress/fixtures/coo/coo141_perses/rbac/rbac_perses_e2e_ci_users.sh new file mode 100644 index 000000000..51a3c85f0 --- /dev/null +++ b/web/cypress/fixtures/coo/coo141_perses/rbac/rbac_perses_e2e_ci_users.sh @@ -0,0 +1,1196 @@ +#!/bin/bash + +# User variables (passed as arguments) +USER1="${USER1}" +USER2="${USER2}" + +oc new-project perses-dev +oc new-project observ-test + +oc apply -f - < "${RANDOM_FILE}" --kubeconfig "${KUBECONFIG}" + +# Patch the CSV file env vars for cluster-health-analyzer +# Handle both US and UK spellings (analyser/analyzer) for compatibility +sed -i "s#value: .*cluster-health-analy[sz]er.*#value: ${CHA_IMAGE}#g" "${RANDOM_FILE}" + +# Patch the CSV file related images +sed -i "s#^\([[:space:]]*- image:\).*cluster-health-analy[sz]er.*#\1 ${CHA_IMAGE}#g" "${RANDOM_FILE}" + +# Apply the patched CSV resource file +oc replace -f "${RANDOM_FILE}" --kubeconfig "${KUBECONFIG}" + +# Wait for the operator to reconcile the change +sleep 25 + +# Wait for health-analyzer pod to be ready with the new image +OUTPUT=$(oc wait --for=condition=ready pods -l app.kubernetes.io/instance=health-analyzer -n "${MCP_NAMESPACE}" --timeout=120s --kubeconfig "${KUBECONFIG}") +echo "${OUTPUT}" + +echo "--------------------------------" +echo "Health-analyzer pod status:" +echo "--------------------------------" +oc get pods -l app.kubernetes.io/instance=health-analyzer -n "${MCP_NAMESPACE}" -o wide --kubeconfig "${KUBECONFIG}" +echo "--------------------------------" diff --git a/web/cypress/fixtures/monitoring/constants.ts b/web/cypress/fixtures/monitoring/constants.ts index 966f27ed1..9f05c1ad6 100644 --- a/web/cypress/fixtures/monitoring/constants.ts +++ b/web/cypress/fixtures/monitoring/constants.ts @@ -98,6 +98,7 @@ export enum MetricsPagePredefinedQueries { export enum MetricsPageQueryInput { EXPRESSION_PRESS_SHIFT_ENTER_FOR_NEWLINES = 'Expression (press Shift+Enter for newlines)', INSERT_EXAMPLE_QUERY = 'sort_desc(sum(sum_over_time(ALERTS{alertstate="firing"}[24h])) by (alertname))', + INSERT_EXAMPLE_QUERY_NAMESPACE = 'sort_desc(sum(sum_over_time(ALERTS{alertstate="firing", namespace="openshift-monitoring"}[24h])) by (alertname))', VECTOR_QUERY='vector(1)', CPU_USAGE = 'OpenShift_Metrics_QueryTable_sum(node_namespace_pod_container_container_cpu_usage_seconds_total_sum_irate) by (pod).csv', MEMORY_USAGE = 'OpenShift_Metrics_QueryTable_sum(container_memory_working_set_bytes{container!=__}) by (pod).csv', diff --git a/web/cypress/fixtures/perses/constants.ts b/web/cypress/fixtures/perses/constants.ts index 48f9e520b..8b2116950 100644 --- a/web/cypress/fixtures/perses/constants.ts +++ b/web/cypress/fixtures/perses/constants.ts @@ -21,14 +21,15 @@ export enum persesDashboardsRefreshInterval { } export const persesDashboardsDashboardDropdownCOO = { - ACCELERATORS_COMMON_METRICS:['Accelerators common metrics', 'perses'], - K8S_COMPUTE_RESOURCES_CLUSTER: ['Kubernetes / Compute Resources / Cluster', 'perses'], + ACCELERATORS_COMMON_METRICS:['Accelerators common metrics', 'perses', 'accelerators-dashboard'], + APM_DASHBOARD: ['Application Performance Monitoring (APM)', 'perses', 'apm-dashboard'], + K8S_COMPUTE_RESOURCES_CLUSTER: ['Kubernetes / Compute Resources / Cluster', 'perses', 'openshift-cluster-sample-dashboard'], } export const persesDashboardsDashboardDropdownPersesDev = { - PERSES_DASHBOARD_SAMPLE: ['Perses Dashboard Sample', 'perses'], - PROMETHEUS_OVERVIEW: ['Prometheus / Overview', 'perses'], - THANOS_COMPACT_OVERVIEW: ['Thanos / Compact / Overview', 'perses'], + PERSES_DASHBOARD_SAMPLE: ['Perses Dashboard Sample', 'perses', 'perses-dashboard-sample'], + PROMETHEUS_OVERVIEW: ['Prometheus / Overview', 'perses', 'prometheus-overview'], + THANOS_COMPACT_OVERVIEW: ['Thanos / Compact / Overview', 'perses', 'thanos-compact-overview'], } export enum persesDashboardsAcceleratorsCommonMetricsPanels { @@ -39,4 +40,120 @@ export enum persesDashboardsAcceleratorsCommonMetricsPanels { TEMPERATURE_CELCIUS = 'Temperature (Celsius)', SM_CLOCK_HERTZ = 'SM Clock (Hertz)', MEMORY_CLOCK_HERTZ = 'Memory Clock (Hertz)', +} + +export const listPersesDashboardsPageSubtitle = 'View and manage dashboards.'; + +export const listPersesDashboardsEmptyState = { + TITLE: 'No results found', + BODY: 'No results match the filter criteria. Clear filters to show results.', + +} + +export const persesDashboardsModalTitles ={ + EDIT_DASHBOARD_VARIABLES: 'Edit Dashboard Variables', + DASHBOARD_BUILT_IN_VARIABLES: 'Dashboard Built-in Variables', + ADD_VARIABLE: 'Add Variable', + EDIT_VARIABLE: 'Edit Variable', + EDIT_DASHBOARD_DATASOURCES: 'Edit Dashboard Datasources', + ADD_DATASOURCE: 'Add Datasource', + EDIT_DATASOURCE: 'Edit Datasource', + ADD_PANEL: 'Add Panel', + EDIT_PANEL: 'Edit Panel', + DELETE_PANEL: 'Delete Panel', + ADD_PANEL_GROUP: 'Add Panel Group', + EDIT_PANEL_GROUP: 'Edit Panel Group', + DELETE_PANEL_GROUP: 'Delete Panel Group', + EDIT_DASHBOARD_JSON: 'Edit Dashboard JSON', + SAVE_DASHBOARD: 'Save Dashboard', + DISCARD_CHANGES: 'Discard Changes', + VIEW_JSON_DIALOG: 'Dashboard JSON', + CREATE_DASHBOARD: 'Create Dashboard', +} + +export enum persesDashboardsAddListVariableSource { + STATIC_LIST_VARIABLE= 'Static List Variable', + DATASOURCE_VARIABLE= 'Datasource Variable', + PROMETHEUS_LABEL_VARIABLE= 'Prometheus Label Values Variable', + PROMETHEUS_NAMES_VARIABLE= 'Prometheus Label Names Variable', + PROMETHEUS_PROMQL_VARIABLE= 'Prometheus PromQL Variable', +} + +export enum persesDashboardsAddListVariableSort { + NONE = 'None', + ALPHABETICAL_ASC = 'Alphabetical, asc', + ALPHABETICAL_DESC = 'Alphabetical, desc', + NUMERICAL_ASC = 'Numerical, asc', + NUMERICAL_DESC = 'Numerical, desc', + ALPHABETICAL_CI_ASC = 'Alphabetical, case-insensitive, asc', + ALPHABETICAL_CI_DESC = 'Alphabetical, case-insensitive, desc', +} + +export const persesDashboardsRequiredFields = { + AddVariableNameField: 'String must contain at least 1 character(s)' +} + +export const persesDashboardsAddListPanelType = { + BAR_CHART: 'Bar Chart', + FLAME_CHART: 'Flame Chart', + GAUGE_CHART: 'Gauge Chart', + HEATMAP_CHART: 'HeatMap Chart', + HISTOGRAM_CHART: 'Histogram Chart', + MARKDOWN: 'Markdown', + LOGS_TABLE: 'Logs Table', + PIE_CHART: 'Pie Chart', + SCATTER_CHART: 'Scatter Chart', + STAT_CHART: 'Stat Chart', + STATUS_HISTORY_CHART: 'Status History Chart', + TABLE: 'Table', + TIME_SERIES_CHART: 'Time Series Chart', + TIME_SERIES_TABLE: 'Time Series Table', + TRACE_TABLE: 'Trace Table', + TRACING_GANTT_CHART: 'Tracing Gantt Chart', +} + +export const persesDashboardsAddPanelAddQueryType ={ + BAR_GAUGE_HEAT_HISTOGRAM_PIE_STAT_STATUS_TABLE_TIMESERIES : { + CLICKHOUSE_TIME_SERIES_QUERY: 'ClickHouse Time Series Query', + LOKI_TIME_SERIES_QUERY: 'Loki Time Series Query', + PROMETHEUS_TIME_SERIES_QUERY: 'Prometheus Time Series Query', + VICTORIALOGS_TIME_SERIES_QUERY: 'VictoriaLogs Time Series Query', + }, + FLAME_CHART : { + PYROSCOPE_PROFILE_QUERY: 'Pyroscope Profile Query', + }, + LOGS_TABLE : { + CLICKHOUSE_LOG_QUERY: 'ClickHouse Log Query', + LOKI_LOG_QUERY: 'Loki Log Query', + VICTORIALOGS_LOG_QUERY: 'Victorialogs Log Query', + }, + SCATTER_TRACE_TRACINGGANTT : { + TEMPO_TRACE_QUERY: 'Tempo Trace Query', + }, +} + +export const persesCreateDashboard = { + DIALOG_MAX_LENGTH_VALIDATION: 'Danger alert:bad request: code=400, message=cannot contain more than 75 characters, internal=cannot contain more than 75 characters', + DIALOG_DUPLICATED_NAME_PF_VALIDATION_PREFIX: 'Dashboard name ', + DIALOG_DUPLICATED_NAME_PF_VALIDATION_SUFFIX: ' already exists in this project: error status;', + DIALOG_DUPLICATED_NAME_BKD_VALIDATION: 'Danger alert:document already exists', +} + +export const persesDashboardsEmptyDashboard = { + TITLE: 'Empty Dashboard', + DESCRIPTION: 'To get started add something to your dashboard', +} + +export const persesDashboardSampleQueries = { + CPU_LINE_MULTI_SERIES: 'avg without (cpu)(rate(node_cpu_seconds_total{job=\'$job\',instance=\~\'$instance\',mode!=\"nice\",mode!=\"steal\",mode!=\"irq\"}[$interval]))', + CPU_LINE_MULTI_SERIES_LEGEND: '{{}{{}mode{}}{}} mode - {{}{{}job{}}{}} {{}{{}instance{}}{}}', + CPU_LINE_MULTI_SERIES_SERIES_SELECTOR: 'up{{}job=~"$job"{}}', +} + +export const persesDashboardsRenameDashboard = { + DIALOG_MAX_LENGTH_VALIDATION: 'Must be 75 or fewer characters long: error status;', +} + +export const persesDashboardsDuplicateDashboard = { + DIALOG_DUPLICATED_NAME_VALIDATION: "already exists", //use contains } \ No newline at end of file diff --git a/web/cypress/support/commands/auth-commands.ts b/web/cypress/support/commands/auth-commands.ts index 5ff651562..62cbf3bd7 100644 --- a/web/cypress/support/commands/auth-commands.ts +++ b/web/cypress/support/commands/auth-commands.ts @@ -3,11 +3,11 @@ import { guidedTour } from '../../views/tour'; -export {}; +export { }; declare global { namespace Cypress { interface Chainable { - switchPerspective(perspective: string); + switchPerspective(...perspectives: string[]); uiLogin(provider: string, username: string, password: string, oauthurl?: string); uiLogout(); cliLogin(username?, password?, hostapi?); @@ -17,199 +17,257 @@ declare global { adminCLI(command: string, options?); executeAndDelete(command: string); validateLogin(): Chainable; + relogin(provider: string, username: string, password: string): Chainable; } } } - // Core login function (used by both session and non-session versions) - function performLogin( - provider: string, - username: string, - password: string, - oauthurl: string - ): void { - cy.visit(Cypress.config('baseUrl')); - cy.log('Session - after visiting'); - cy.window().then( - ( - win: any, // eslint-disable-line @typescript-eslint/no-explicit-any - ) => { - // Check if auth is disabled (for a local development environment) - if (win.SERVER_FLAGS?.authDisabled) { - cy.task('log', ' skipping login, console is running with auth disabled'); - return; +// Core login function (used by both session and non-session versions) +function performLogin( + provider: string, + username: string, + password: string, + oauthurl: string +): void { + cy.visit(Cypress.config('baseUrl')); + cy.log('Session - after visiting'); + cy.window().then( + ( + win: any, // eslint-disable-line @typescript-eslint/no-explicit-any + ) => { + // Check if auth is disabled (for a local development environment) + if (win.SERVER_FLAGS?.authDisabled) { + cy.task('log', ' skipping login, console is running with auth disabled'); + return; + } + cy.exec( + `oc get node --selector=hypershift.openshift.io/managed --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, + ).then((result) => { + cy.log(result.stdout); + cy.task('log', result.stdout); + if (result.stdout.includes('Ready')) { + cy.log(`Attempting login via cy.origin to: ${oauthurl}`); + cy.task('log', `Attempting login via cy.origin to: ${oauthurl}`); + cy.origin( + oauthurl, + { args: { username, password } }, + ({ username, password }) => { + cy.get('#inputUsername').type(username); + cy.get('#inputPassword').type(password); + cy.get('button[type=submit]').click(); + }, + ); + } else { + cy.task('log', ` Logging in as ${username} using fallback on ${oauthurl}`); + cy.origin( + oauthurl, + { args: { provider, username, password } }, + ({ provider, username, password }) => { + cy.get('[data-test-id="login"]').should('be.visible'); + cy.get('body').then(($body) => { + if ($body.text().includes(provider)) { + cy.contains(provider).should('be.visible').click(); + } + }); + cy.get('#inputUsername').type(username); + cy.get('#inputPassword').type(password); + cy.get('button[type=submit]').click(); + } + ); } - cy.exec( - `oc get node --selector=hypershift.openshift.io/managed --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, - ).then((result) => { - cy.log(result.stdout); - cy.task('log', result.stdout); - if (result.stdout.includes('Ready')) { - cy.log(`Attempting login via cy.origin to: ${oauthurl}`); - cy.task('log', `Attempting login via cy.origin to: ${oauthurl}`); - cy.origin( - oauthurl, - { args: { username, password } }, - ({ username, password }) => { - cy.get('#inputUsername').type(username); - cy.get('#inputPassword').type(password); - cy.get('button[type=submit]').click(); - }, - ); - } else { - cy.task('log', ` Logging in as ${username} using fallback on ${oauthurl}`); - cy.origin( - oauthurl, - { args: { provider, username, password } }, - ({ provider, username, password }) => { - cy.get('[data-test-id="login"]').should('be.visible'); - cy.get('body').then(($body) => { - if ($body.text().includes(provider)) { - cy.contains(provider).should('be.visible').click(); - } - }); - cy.get('#inputUsername').type(username); - cy.get('#inputPassword').type(password); - cy.get('button[type=submit]').click(); - } - ); - } - }); - }, - ); - } + }); + }, + ); +} - Cypress.Commands.add('validateLogin', () => { - cy.visit('/'); - cy.wait(2000); - cy.byTestID("username", {timeout: 120000}).should('be.visible'); - guidedTour.close(); - }); +Cypress.Commands.add('validateLogin', () => { + cy.log('validateLogin'); + cy.visit('/'); + cy.wait(2000); + cy.byTestID("username", { timeout: 120000 }).should('be.visible'); + cy.wait(10000); + guidedTour.close(); +}); - // Session-wrapped login - Cypress.Commands.add( - 'login', - ( - provider: string = Cypress.env('LOGIN_IDP'), - username: string = Cypress.env('LOGIN_USERNAME'), - password: string = Cypress.env('LOGIN_PASSWORD'), - oauthurl: string, - ) => { - cy.session( - [provider, username], - () => { - performLogin(provider, username, password, oauthurl); - }, - { - cacheAcrossSpecs: true, - validate() { - cy.validateLogin(); - }, - }, - ); +// Session-wrapped login +Cypress.Commands.add( + 'login', + ( + provider: string = Cypress.env('LOGIN_IDP'), + username: string = Cypress.env('LOGIN_USERNAME'), + password: string = Cypress.env('LOGIN_PASSWORD'), + oauthurl: string, + ) => { + cy.session( + [provider, username], + () => { + performLogin(provider, username, password, oauthurl); + }, + { + cacheAcrossSpecs: true, + validate() { + cy.validateLogin(); + }, }, ); + }, +); - // Non-session login (for use within sessions) - Cypress.Commands.add('loginNoSession', (provider: string, username: string, password: string, oauthurl: string) => { - performLogin(provider, username, password, oauthurl); - cy.validateLogin(); +// Non-session login (for use within sessions) +Cypress.Commands.add('loginNoSession', (provider: string, username: string, password: string, oauthurl: string) => { + performLogin(provider, username, password, oauthurl); + cy.validateLogin(); +}); + +Cypress.Commands.add('switchPerspective', (...perspectives: string[]) => { + /* If side bar is collapsed then expand it + before switching perspecting */ + cy.wait(2000); + cy.get('body').then((body) => { + if (body.find('.pf-m-collapsed').length > 0) { + cy.get('#nav-toggle').click(); + } }); + nav.sidenav.switcher.changePerspectiveTo(...perspectives); + cy.wait(3000); + guidedTour.close(); +}); - Cypress.Commands.add('switchPerspective', (perspective: string) => { - /* If side bar is collapsed then expand it - before switching perspecting */ - cy.wait(2000); - cy.get('body').then((body) => { - if (body.find('.pf-m-collapsed').length > 0) { - cy.get('#nav-toggle').click(); +// To avoid influence from upstream login change +Cypress.Commands.add('uiLogin', (provider: string, username: string, password: string) => { + cy.log('Commands uiLogin'); + cy.clearCookie('openshift-session-token'); + cy.visit('/'); + cy.window().then( + ( + win: any, // eslint-disable-line @typescript-eslint/no-explicit-any + ) => { + if (win.SERVER_FLAGS?.authDisabled) { + cy.task('log', 'Skipping login, console is running with auth disabled'); + return; } - }); - nav.sidenav.switcher.changePerspectiveTo(perspective); - }); + cy.get('h1').should('have.text', 'Login'); + cy.get('body').then(($body) => { + if ($body.text().includes(provider)) { + cy.contains(provider).should('be.visible').click(); + } else if ($body.find('li.idp').length > 0) { + //Using the last idp if doesn't provider idp name + cy.get('li.idp').last().click(); + } + }); + cy.get('#inputUsername').type(username); + cy.get('#inputPassword').type(password); + cy.get('button[type=submit]').click(); + cy.byTestID('username', { timeout: 120000 }).should('be.visible'); + }, + ); + cy.switchPerspective('Administrator'); +}); - // To avoid influence from upstream login change - Cypress.Commands.add('uiLogin', (provider: string, username: string, password: string) => { - cy.log('Commands uiLogin'); +// Relogin command for use after clearing sessions +// Fetches OAuth URL and uses cy.origin() for cross-origin login like the other login commands +Cypress.Commands.add('relogin', (provider: string, username: string, password: string) => { + cy.log('Commands relogin - fetching OAuth URL and performing fresh login'); + + cy.uiLogout(); + // Get the OAuth URL from the cluster (same as performLoginAndAuth does) + cy.exec( + `oc get oauthclient openshift-browser-client -o go-template --template="{{index .redirectURIs 0}}" --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, + ).then((result) => { + if (result.stderr !== '') { + throw new Error(`Failed to get OAuth URL: ${result.stderr}`); + } + + const oauth = result.stdout; + const oauthurl = new URL(oauth); + const oauthorigin = oauthurl.origin; + cy.log(`OAuth origin: ${oauthorigin}`); + + // Now perform login using cy.origin() for cross-origin OAuth cy.clearCookie('openshift-session-token'); - cy.visit('/'); - cy.window().then( - ( - win: any, // eslint-disable-line @typescript-eslint/no-explicit-any - ) => { - if (win.SERVER_FLAGS?.authDisabled) { - cy.task('log', 'Skipping login, console is running with auth disabled'); - return; - } - cy.get('[data-test-id="login"]').should('be.visible'); + cy.visit(Cypress.config('baseUrl')); + + // Use cy.origin() for cross-origin login (OAuth is on a different domain) + cy.origin( + oauthorigin, + { args: { provider, username, password } }, + ({ provider, username, password }) => { + // Wait for login page to load + cy.get('[data-test-id="login"]', { timeout: 60000 }).should('be.visible'); + + // Select the IDP if available cy.get('body').then(($body) => { if ($body.text().includes(provider)) { cy.contains(provider).should('be.visible').click(); - } else if ($body.find('li.idp').length > 0) { - //Using the last idp if doesn't provider idp name - cy.get('li.idp').last().click(); } }); - cy.get('#inputUsername').type(username); + + // Fill in login form + cy.get('#inputUsername', { timeout: 30000 }).should('be.visible').type(username); cy.get('#inputPassword').type(password); cy.get('button[type=submit]').click(); - cy.byTestID('username', { timeout: 120000 }).should('be.visible'); - }, + } ); + + // Wait for successful login back on the main origin + cy.byTestID('username', { timeout: 120000 }).should('be.visible'); cy.switchPerspective('Administrator'); }); +}); - Cypress.Commands.add('uiLogout', () => { - cy.window().then( - ( - win: any, // eslint-disable-line @typescript-eslint/no-explicit-any - ) => { - if (win.SERVER_FLAGS?.authDisabled) { - cy.log('Skipping logout, console is running with auth disabled'); - return; - } - cy.log('Log out UI'); - cy.byTestID('username').click(); - cy.byTestID('log-out').should('be.visible'); - cy.byTestID('log-out').click({ force: true }); - }, - ); - }); +Cypress.Commands.add('uiLogout', () => { + cy.window().then( + ( + win: any, // eslint-disable-line @typescript-eslint/no-explicit-any + ) => { + if (win.SERVER_FLAGS?.authDisabled) { + cy.log('Skipping logout, console is running with auth disabled'); + return; + } + cy.log('Log out UI'); + cy.byTestID('username').click(); + cy.wait(1000); + cy.byTestID('log-out').should('be.visible'); + cy.wait(1000); + cy.byTestID('log-out').click({ force: true }); + }, + ); +}); - Cypress.Commands.add('cliLogin', (username?, password?, hostapi?) => { - const loginUsername = username || Cypress.env('LOGIN_USERNAME'); - const loginPassword = password || Cypress.env('LOGIN_PASSWORD'); - const hostapiurl = hostapi || Cypress.env('HOST_API'); - cy.exec( - `oc login -u ${loginUsername} -p ${loginPassword} ${hostapiurl} --insecure-skip-tls-verify=true`, - { failOnNonZeroExit: false }, - ).then((result) => { - cy.log(result.stderr); - cy.log(result.stdout); - }); +Cypress.Commands.add('cliLogin', (username?, password?, hostapi?) => { + const loginUsername = username || Cypress.env('LOGIN_USERNAME'); + const loginPassword = password || Cypress.env('LOGIN_PASSWORD'); + const hostapiurl = hostapi || Cypress.env('HOST_API'); + cy.exec( + `oc login -u ${loginUsername} -p ${loginPassword} ${hostapiurl} --insecure-skip-tls-verify=true`, + { failOnNonZeroExit: false }, + ).then((result) => { + cy.log(result.stderr); + cy.log(result.stdout); }); +}); - Cypress.Commands.add('cliLogout', () => { - cy.exec(`oc logout`, { failOnNonZeroExit: false }).then((result) => { - cy.log(result.stderr); - cy.log(result.stdout); - }); +Cypress.Commands.add('cliLogout', () => { + cy.exec(`oc logout`, { failOnNonZeroExit: false }).then((result) => { + cy.log(result.stderr); + cy.log(result.stdout); }); +}); - Cypress.Commands.add('adminCLI', (command: string) => { - const kubeconfig = Cypress.env('KUBECONFIG_PATH'); - cy.log(`Run admin command: ${command}`); - cy.exec(`${command} --kubeconfig ${kubeconfig}`); - }); - - Cypress.Commands.add('executeAndDelete', (command: string) => { - cy.exec(command, { failOnNonZeroExit: false }) - .then(result => { - if (result.code !== 0) { - cy.task('logError', `Command "${command}" failed: ${result.stderr || result.stdout}`); - } else { - cy.task('log', `Command "${command}" executed successfully`); - } - }); - }); \ No newline at end of file +Cypress.Commands.add('adminCLI', (command: string) => { + const kubeconfig = Cypress.env('KUBECONFIG_PATH'); + cy.log(`Run admin command: ${command}`); + cy.exec(`${command} --kubeconfig ${kubeconfig}`); +}); + +Cypress.Commands.add('executeAndDelete', (command: string) => { + cy.exec(command, { failOnNonZeroExit: false }) + .then(result => { + if (result.code !== 0) { + cy.task('logError', `Command "${command}" failed: ${result.stderr || result.stdout}`); + } else { + cy.task('log', `Command "${command}" executed successfully`); + } + }); +}); \ No newline at end of file diff --git a/web/cypress/support/commands/incident-commands.ts b/web/cypress/support/commands/incident-commands.ts index 8a88f4b3c..6a552d1ec 100644 --- a/web/cypress/support/commands/incident-commands.ts +++ b/web/cypress/support/commands/incident-commands.ts @@ -100,4 +100,3 @@ Cypress.Commands.add('createKubePodCrashLoopingAlert', (testName?: string) => { `oc delete -f ./cypress/fixtures/incidents/pod_crash_loop.yaml --ignore-not-found=true --kubeconfig ${kubeconfigPath}`, ); }); - diff --git a/web/cypress/support/commands/operator-commands.ts b/web/cypress/support/commands/operator-commands.ts index e0046a29a..ad35ba874 100644 --- a/web/cypress/support/commands/operator-commands.ts +++ b/web/cypress/support/commands/operator-commands.ts @@ -135,7 +135,8 @@ export const operatorAuthUtils = { Cypress.env('CUSTOM_COO_BUNDLE_IMAGE'), Cypress.env('FBC_STAGE_COO_IMAGE'), Cypress.env('MP_IMAGE'), - Cypress.env('MCP_CONSOLE_IMAGE') + Cypress.env('MCP_CONSOLE_IMAGE'), + Cypress.env('CHA_IMAGE') ]; return [...baseKey, ...envVars.filter(Boolean)]; @@ -206,7 +207,6 @@ const operatorUtils = { cy.log(`Monitoring plugin pod is now running in namespace: ${MP.namespace}`); cy.reload(true); }); - // }); } else { cy.log('MP_IMAGE is NOT set. Skipping patching the image in CMO operator CSV.'); @@ -240,7 +240,7 @@ const operatorUtils = { `oc label namespace ${MCP.namespace} openshift.io/cluster-monitoring=true --overwrite=true --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, ); cy.exec( - `operator-sdk run bundle --timeout=10m --namespace ${MCP.namespace} ${Cypress.env('KONFLUX_COO_BUNDLE_IMAGE')} --kubeconfig ${Cypress.env('KUBECONFIG_PATH')} --verbose `, + `operator-sdk run bundle --timeout=10m --namespace ${MCP.namespace} --security-context-config restricted ${Cypress.env('KONFLUX_COO_BUNDLE_IMAGE')} --kubeconfig ${Cypress.env('KUBECONFIG_PATH')} --verbose `, { timeout: installTimeoutMilliseconds }, ); } else if (Cypress.env('CUSTOM_COO_BUNDLE_IMAGE')) { @@ -256,7 +256,7 @@ const operatorUtils = { `oc label namespace ${MCP.namespace} openshift.io/cluster-monitoring=true --overwrite=true --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, ); cy.exec( - `operator-sdk run bundle --timeout=10m --namespace ${MCP.namespace} ${Cypress.env('CUSTOM_COO_BUNDLE_IMAGE')} --kubeconfig ${Cypress.env('KUBECONFIG_PATH')} --verbose `, + `operator-sdk run bundle --timeout=10m --namespace ${MCP.namespace} --security-context-config restricted ${Cypress.env('CUSTOM_COO_BUNDLE_IMAGE')} --kubeconfig ${Cypress.env('KUBECONFIG_PATH')} --verbose `, { timeout: installTimeoutMilliseconds }, ); } else if (Cypress.env('FBC_STAGE_COO_IMAGE')) { @@ -283,7 +283,9 @@ const operatorUtils = { waitForCOOReady(MCP: { namespace: string }): void { cy.log('Check Cluster Observability Operator status'); - cy.exec(`sleep 60 && oc get pods -n ${MCP.namespace} | grep observability-operator | awk '{print $1}'`, { timeout: readyTimeoutMilliseconds, failOnNonZeroExit: true }) + cy.exec(`oc project ${MCP.namespace} --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.exec(`sleep 60 && oc get pods -n ${MCP.namespace} | grep observability-operator | grep -v bundle | awk '{print $1}'`, { timeout: readyTimeoutMilliseconds, failOnNonZeroExit: true }) .its('stdout') // Get the captured output string .then((podName) => { // Trim any extra whitespace (newline, etc.) @@ -306,19 +308,36 @@ const operatorUtils = { nav.sidenav.clickNavLink([section, 'Installed Operators']); }); - cy.byTestID('name-filter-input').should('be.visible').type('Cluster Observability{enter}'); + cy.byTestID('name-filter-input').should('be.visible').type('Observability{enter}'); cy.get('[data-test="status-text"]', { timeout: installTimeoutMilliseconds }).eq(0).should('contain.text', 'Succeeded', { timeout: installTimeoutMilliseconds }); }, - setupMonitoringConsolePlugin(MCP: { namespace: string }): void { - cy.log('Set Monitoring Console Plugin image in operator CSV'); - if (Cypress.env('MCP_CONSOLE_IMAGE')) { - cy.log('MCP_CONSOLE_IMAGE is set. the image will be patched in COO operator CSV'); + /** + * Generic function to patch a component image in the COO CSV + * @param MCP - The MCP namespace configuration + * @param config - Configuration for the image patch + * @param config.envVar - The Cypress environment variable name (also used as the shell script env var) + * @param config.scriptPath - Path to the shell script that performs the patch + * @param config.componentName - Human-readable name for logging + */ + patchCOOCSVImage( + MCP: { namespace: string }, + config: { + envVar: string; + scriptPath: string; + componentName: string; + } + ): void { + const imageValue = Cypress.env(config.envVar); + cy.log(`Set ${config.componentName} image in operator CSV`); + + if (imageValue) { + cy.log(`${config.envVar} is set. The image will be patched in COO operator CSV`); cy.exec( - './cypress/fixtures/coo/update-mcp-image.sh', + config.scriptPath, { env: { - MCP_CONSOLE_IMAGE: Cypress.env('MCP_CONSOLE_IMAGE'), + [config.envVar]: imageValue, KUBECONFIG: Cypress.env('KUBECONFIG_PATH'), MCP_NAMESPACE: `${MCP.namespace}` }, @@ -327,33 +346,74 @@ const operatorUtils = { } ).then((result) => { expect(result.code).to.eq(0); - cy.log(`COO CSV updated successfully with Monitoring Console Plugin image: ${result.stdout}`); + cy.log(`COO CSV updated successfully with ${config.componentName} image: ${result.stdout}`); cy.reload(true); }); } else { - cy.log('MCP_CONSOLE_IMAGE is NOT set. Skipping patching the image in COO operator CSV.'); + cy.log(`${config.envVar} is NOT set. Skipping patching the image in COO operator CSV.`); } }, + setupMonitoringConsolePlugin(MCP: { namespace: string }): void { + operatorUtils.patchCOOCSVImage(MCP, { + envVar: 'MCP_CONSOLE_IMAGE', + scriptPath: './cypress/fixtures/coo/update-mcp-image.sh', + componentName: 'Monitoring Console Plugin' + }); + }, + + setupClusterHealthAnalyzer(MCP: { namespace: string }): void { + operatorUtils.patchCOOCSVImage(MCP, { + envVar: 'CHA_IMAGE', + scriptPath: './cypress/fixtures/coo/update-cha-image.sh', + componentName: 'cluster-health-analyzer' + }); + }, + setupDashboardsAndPlugins(MCP: { namespace: string }): void { cy.log('Create perses-dev namespace.'); cy.exec(`oc new-project perses-dev --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Create openshift-cluster-sample-dashboard instance.'); - cy.exec(`sed 's/namespace: openshift-cluster-observability-operator/namespace: ${MCP.namespace}/g' ./cypress/fixtures/coo/openshift-cluster-sample-dashboard.yaml | oc apply -f - --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + /** + * TODO: When COO1.4.0 is released, points COO_UI_INSTALL to install dashboards on COO1.4.0 folder + */ + if (Cypress.env('COO_UI_INSTALL')) { + cy.log('COO_UI_INSTALL is set. Installing dashboards on COO1.2.0 folder'); + + cy.log('Create openshift-cluster-sample-dashboard instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo121_perses/dashboards/openshift-cluster-sample-dashboard.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create perses-dashboard-sample instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo121_perses/dashboards/perses-dashboard-sample.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create prometheus-overview-variables instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo121_perses/dashboards/prometheus-overview-variables.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Create perses-dashboard-sample instance.'); - cy.exec(`oc apply -f ./cypress/fixtures/coo/perses-dashboard-sample.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Create thanos-compact-overview-1var instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo121_perses/dashboards/thanos-compact-overview-1var.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Create prometheus-overview-variables instance.'); - cy.exec(`oc apply -f ./cypress/fixtures/coo/prometheus-overview-variables.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Create Thanos Querier instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo121_perses/dashboards/thanos-querier-datasource.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + } else { + cy.log('COO_UI_INSTALL is not set. Installing dashboards on COO1.4.0 folder'); + + cy.log('Create openshift-cluster-sample-dashboard instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo141_perses/dashboards/openshift-cluster-sample-dashboard.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create perses-dashboard-sample instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo141_perses/dashboards/perses-dashboard-sample.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create prometheus-overview-variables instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo141_perses/dashboards/prometheus-overview-variables.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Create thanos-compact-overview-1var instance.'); - cy.exec(`oc apply -f ./cypress/fixtures/coo/thanos-compact-overview-1var.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Create thanos-compact-overview-1var instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo141_perses/dashboards/thanos-compact-overview-1var.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Create Thanos Querier instance.'); - cy.exec(`oc apply -f ./cypress/fixtures/coo/thanos-querier-datasource.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Create Thanos Querier instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo141_perses/dashboards/thanos-querier-datasource.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + } cy.exec( `oc label namespace ${MCP.namespace} openshift.io/cluster-monitoring=true --overwrite=true --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, @@ -426,7 +486,11 @@ const operatorUtils = { cy.log(`Korrel8r pod is now running in namespace: ${MCP.namespace}`); }); + cy.log(`Reloading the page`); cy.reload(true); + cy.log(`Waiting for 10 seconds before clicking the application launcher`); + cy.wait(10000); + cy.log(`Clicking the application launcher`); cy.byLegacyTestID(LegacyTestIDs.ApplicationLauncher).should('be.visible').click(); cy.byTestID(DataTestIDs.MastHeadApplicationItem).contains('Signal Correlation').should('be.visible'); }, @@ -488,22 +552,40 @@ const operatorUtils = { cy.executeAndDelete( `oc delete ${config.kind} ${config.name} --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, ); - - cy.log('Remove openshift-cluster-sample-dashboard instance.'); - cy.executeAndDelete(`sed 's/namespace: openshift-cluster-observability-operator/namespace: ${MCP.namespace}/g' ./cypress/fixtures/coo/openshift-cluster-sample-dashboard.yaml | oc delete -f - --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + if (Cypress.env('COO_UI_INSTALL')) { + cy.log('Remove openshift-cluster-sample-dashboard instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo121_perses/dashboards/openshift-cluster-sample-dashboard.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Remove perses-dashboard-sample instance.'); - cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/perses-dashboard-sample.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Remove perses-dashboard-sample instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo121_perses/dashboards/perses-dashboard-sample.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Remove prometheus-overview-variables instance.'); - cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/prometheus-overview-variables.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Remove prometheus-overview-variables instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo121_perses/dashboards/prometheus-overview-variables.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Remove thanos-compact-overview-1var instance.'); - cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/thanos-compact-overview-1var.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Remove thanos-compact-overview-1var instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo121_perses/dashboards/thanos-compact-overview-1var.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Remove Thanos Querier instance.'); - cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/thanos-querier-datasource.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Remove Thanos Querier instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo121_perses/dashboards/thanos-querier-datasource.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + } else { + cy.log('COO_UI_INSTALL is not set. Removing dashboards on COO1.4.0 folder'); + + cy.log('Remove openshift-cluster-sample-dashboard instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo141_perses/dashboards/openshift-cluster-sample-dashboard.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Remove perses-dashboard-sample instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo141_perses/dashboards/perses-dashboard-sample.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Remove prometheus-overview-variables instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo141_perses/dashboards/prometheus-overview-variables.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Remove thanos-compact-overview-1var instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo141_perses/dashboards/thanos-compact-overview-1var.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Remove Thanos Querier instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo141_perses/dashboards/thanos-querier-datasource.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + } cy.log('Remove perses-dev namespace'); cy.executeAndDelete(`oc delete namespace perses-dev --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); @@ -798,6 +880,7 @@ Cypress.Commands.add('beforeBlock', (MP: { namespace: string, operatorName: stri operatorUtils.installCOO(MCP); operatorUtils.waitForCOOReady(MCP); operatorUtils.setupMonitoringConsolePlugin(MCP); + operatorUtils.setupClusterHealthAnalyzer(MCP); operatorUtils.setupDashboardsAndPlugins(MCP); operatorUtils.setupTroubleshootingPanel(MCP); operatorUtils.setupMonitoringPluginImage(MP); @@ -813,15 +896,12 @@ Cypress.Commands.add('beforeBlock', (MP: { namespace: string, operatorName: stri Cypress.Commands.add('beforeBlockACM', (MCP, MP) => { cy.beforeBlockCOO(MCP, MP); - cy.log('=== [Setup] Installing ACM Operator & MCO ==='); + cy.log('=== [Setup] Installing ACM test resources ==='); cy.exec('bash ./cypress/fixtures/coo/acm-install.sh', { env: { KUBECONFIG: Cypress.env('KUBECONFIG_PATH'), }, failOnNonZeroExit: false, timeout: 1200000, // long time script }); - cy.exec(`oc apply -f ./cypress/fixtures/coo/acm-uiplugin.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - // add example alerts for test - cy.exec(`oc apply -f ./cypress/fixtures/coo/acm-alerrule-test.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); cy.log('ACM environment setup completed'); }); @@ -842,4 +922,4 @@ Cypress.Commands.add('closeOnboardingModalIfPresent', () => { cy.log('No onboarding modal found'); } }); -}); +}); \ No newline at end of file diff --git a/web/cypress/support/commands/perses-commands.ts b/web/cypress/support/commands/perses-commands.ts new file mode 100644 index 000000000..fd96e6275 --- /dev/null +++ b/web/cypress/support/commands/perses-commands.ts @@ -0,0 +1,62 @@ +export { }; + +declare global { + namespace Cypress { + interface Chainable { + setupPersesRBACandExtraDashboards(): Chainable; + cleanupExtraDashboards(): Chainable; + } + } + } + +Cypress.Commands.add('setupPersesRBACandExtraDashboards', () => { + + if (`${Cypress.env('LOGIN_USERNAME1')}` !== 'kubeadmin' && `${Cypress.env('LOGIN_USERNAME2')}` !== undefined) { + cy.exec( + './cypress/fixtures/coo/coo141_perses/rbac/rbac_perses_e2e_ci_users.sh', + { + env: { + USER1: `${Cypress.env('LOGIN_USERNAME1')}`, + USER2: `${Cypress.env('LOGIN_USERNAME2')}`, + }, + } + ); + + cy.log('Create openshift-cluster-sample-dashboard instance.'); + cy.exec(`sed 's/namespace: openshift-cluster-observability-operator/namespace: observ-test/g' ./cypress/fixtures/coo/coo141_perses/dashboards/openshift-cluster-sample-dashboard.yaml | oc apply -f - --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create perses-dashboard-sample instance.'); + cy.exec(`sed 's/namespace: perses-dev/namespace: observ-test/g' ./cypress/fixtures/coo/coo141_perses/dashboards/perses-dashboard-sample.yaml | oc apply -f - --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create prometheus-overview-variables instance.'); + cy.exec(`sed 's/namespace: perses-dev/namespace: observ-test/g' ./cypress/fixtures/coo/coo141_perses/dashboards/prometheus-overview-variables.yaml | oc apply -f - --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create thanos-compact-overview-1var instance.'); + cy.exec(`sed 's/namespace: perses-dev/namespace: observ-test/g' ./cypress/fixtures/coo/coo141_perses/dashboards/thanos-compact-overview-1var.yaml | oc apply -f - --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create Thanos Querier instance.'); + cy.exec(`sed 's/namespace: perses-dev/namespace: observ-test/g' ./cypress/fixtures/coo/coo141_perses/dashboards/thanos-querier-datasource.yaml | oc apply -f - --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + } +}); + +Cypress.Commands.add('cleanupExtraDashboards', () => { + + cy.log('Remove openshift-cluster-sample-dashboard instance.'); + cy.exec(`sed 's/namespace: openshift-cluster-observability-operator/namespace: observ-test/g' ./cypress/fixtures/coo/coo141_perses/dashboards/openshift-cluster-sample-dashboard.yaml | oc delete -f - --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Remove perses-dashboard-sample instance.'); + cy.exec(`sed 's/namespace: perses-dev/namespace: observ-test/g' ./cypress/fixtures/coo/coo141_perses/dashboards/perses-dashboard-sample.yaml | oc delete -f - --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Remove prometheus-overview-variables instance.'); + cy.exec(`sed 's/namespace: perses-dev/namespace: observ-test/g' ./cypress/fixtures/coo/coo141_perses/dashboards/prometheus-overview-variables.yaml | oc delete -f - --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Remove thanos-compact-overview-1var instance.'); + cy.exec(`sed 's/namespace: perses-dev/namespace: observ-test/g' ./cypress/fixtures/coo/coo141_perses/dashboards/thanos-compact-overview-1var.yaml | oc delete -f - --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Remove Thanos Querier instance.'); + cy.exec(`sed 's/namespace: perses-dev/namespace: observ-test/g' ./cypress/fixtures/coo/coo141_perses/dashboards/thanos-querier-datasource.yaml | oc delete -f - --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Remove observ-test namespace'); + cy.exec(`oc delete namespace observ-test --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + +}); diff --git a/web/cypress/support/commands/selector-commands.ts b/web/cypress/support/commands/selector-commands.ts index f397b8c79..788ab2396 100644 --- a/web/cypress/support/commands/selector-commands.ts +++ b/web/cypress/support/commands/selector-commands.ts @@ -113,4 +113,4 @@ Cypress.Commands.add( (role: string, options?: Partial) => { return cy.get(`[role="${role}"]`, options); } - ); + ); \ No newline at end of file diff --git a/web/cypress/support/commands/utility-commands.ts b/web/cypress/support/commands/utility-commands.ts index 7cce4066d..15d2fdd21 100644 --- a/web/cypress/support/commands/utility-commands.ts +++ b/web/cypress/support/commands/utility-commands.ts @@ -12,6 +12,7 @@ declare global { changeNamespace(namespace: string): Chainable; aboutModal(): Chainable; podImage(pod: string, namespace: string): Chainable; + assertNamespace(namespace: string, exists: boolean): Chainable; } } } @@ -116,6 +117,8 @@ Cypress.Commands.add('waitUntilWithCustomTimeout', ( Cypress.Commands.add('podImage', (pod: string, namespace: string) => { cy.log('Get pod image'); + cy.switchPerspective('Core platform', 'Administrator'); + cy.wait(5000); cy.clickNavLink(['Workloads', 'Pods']); cy.changeNamespace(namespace); cy.byTestID('page-heading').contains('Pods').should('be.visible'); @@ -140,3 +143,48 @@ Cypress.Commands.add('waitUntilWithCustomTimeout', ( }); + Cypress.Commands.add('assertNamespace', (namespace: string, exists: boolean) => { + cy.log('Asserting Namespace: ' + namespace + ' exists: ' + exists); + cy.wait(2000); + cy.get('body').then(($body) => { + const hasNamespaceBarDropdown = $body.find('[data-test-id="'+LegacyTestIDs.NamespaceBarDropdown+'"]').length > 0; + if (hasNamespaceBarDropdown) { + cy.byLegacyTestID(LegacyTestIDs.NamespaceBarDropdown).find('button').scrollIntoView().should('be.visible'); + cy.byLegacyTestID(LegacyTestIDs.NamespaceBarDropdown).find('button').scrollIntoView().should('be.visible').click({force: true}); + } else { + cy.get(Classes.NamespaceDropdown).scrollIntoView().should('be.visible'); + cy.get(Classes.NamespaceDropdown).scrollIntoView().should('be.visible').click({force: true}); + } + }); + cy.get('body').then(($body) => { + const hasShowSystemSwitch = $body.find('[data-test="'+DataTestIDs.NamespaceDropdownShowSwitch+'"]').length > 0; + if (hasShowSystemSwitch) { + cy.get('[data-test="'+DataTestIDs.NamespaceDropdownShowSwitch+'"]').then(($element)=> { + if ($element.attr('data-checked-state') !== 'true') { + cy.byTestID(DataTestIDs.NamespaceDropdownShowSwitch).siblings('span').eq(0).should('be.visible'); + cy.byTestID(DataTestIDs.NamespaceDropdownShowSwitch).siblings('span').eq(0).should('be.visible').click({force: true}); + } + }); + } + }); + cy.byTestID(DataTestIDs.NamespaceDropdownTextFilter).type(namespace, {delay: 100}); + if (exists) { + cy.log('Namespace: ' + namespace + ' exists'); + cy.byTestID(DataTestIDs.NamespaceDropdownMenuLink).contains(namespace).should('be.visible'); + } else { + cy.log('Namespace: ' + namespace + ' does not exist'); + cy.byTestID(DataTestIDs.NamespaceDropdownMenuLink).should('not.exist'); + } + + cy.get('body').then(($body) => { + const hasNamespaceBarDropdown = $body.find('[data-test-id="'+LegacyTestIDs.NamespaceBarDropdown+'"]').length > 0; + if (hasNamespaceBarDropdown) { + cy.byLegacyTestID(LegacyTestIDs.NamespaceBarDropdown).find('button').scrollIntoView().should('be.visible'); + cy.byLegacyTestID(LegacyTestIDs.NamespaceBarDropdown).find('button').scrollIntoView().should('be.visible').click({force: true}); + } else { + cy.get(Classes.NamespaceDropdownExpanded).scrollIntoView().should('be.visible'); + cy.get(Classes.NamespaceDropdownExpanded).scrollIntoView().should('be.visible').click({force: true}); + } + }); + + }); \ No newline at end of file diff --git a/web/cypress/support/commands/virtualization-commands.ts b/web/cypress/support/commands/virtualization-commands.ts index a308939f7..df86da394 100644 --- a/web/cypress/support/commands/virtualization-commands.ts +++ b/web/cypress/support/commands/virtualization-commands.ts @@ -218,8 +218,7 @@ const virtualizationUtils = { validate() { cy.validateLogin(); // Additional validation for Virtualization setup - cy.visit('/k8s/all-namespaces/virtualization-overview'); - cy.url().should('include', '/k8s/all-namespaces/virtualization-overview'); + cy.switchPerspective('Virtualization'); guidedTour.closeKubevirtTour(); }, @@ -242,4 +241,4 @@ const virtualizationUtils = { cy.log('Cleanup Virtualization (no session)'); virtualizationUtils.cleanup(KBV); cy.log('Cleanup Virtualization (no session) completed'); - }); + }); \ No newline at end of file diff --git a/web/cypress/support/incidents_prometheus_query_mocks/index.ts b/web/cypress/support/incidents_prometheus_query_mocks/index.ts index 12262988e..1e2f518fa 100644 --- a/web/cypress/support/incidents_prometheus_query_mocks/index.ts +++ b/web/cypress/support/incidents_prometheus_query_mocks/index.ts @@ -5,4 +5,4 @@ export * from './utils'; export * from './schema/fixture-converter'; export * from './mock-generators'; export * from './prometheus-mocks'; -export * from './schema/schema-validator'; +export * from './schema/schema-validator'; \ No newline at end of file diff --git a/web/cypress/support/incidents_prometheus_query_mocks/schema/fixture-converter.ts b/web/cypress/support/incidents_prometheus_query_mocks/schema/fixture-converter.ts index 7223bf3a4..0e3e4a07d 100644 --- a/web/cypress/support/incidents_prometheus_query_mocks/schema/fixture-converter.ts +++ b/web/cypress/support/incidents_prometheus_query_mocks/schema/fixture-converter.ts @@ -62,4 +62,4 @@ export function parseYamlFixture(yamlContent: string): IncidentScenarioFixture { } return result.fixture!; -} +} \ No newline at end of file diff --git a/web/cypress/support/incidents_prometheus_query_mocks/schema/fixture-schema.json b/web/cypress/support/incidents_prometheus_query_mocks/schema/fixture-schema.json index 58f90ef92..5633b4b21 100644 --- a/web/cypress/support/incidents_prometheus_query_mocks/schema/fixture-schema.json +++ b/web/cypress/support/incidents_prometheus_query_mocks/schema/fixture-schema.json @@ -191,4 +191,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/web/cypress/support/incidents_prometheus_query_mocks/schema/schema-validator.ts b/web/cypress/support/incidents_prometheus_query_mocks/schema/schema-validator.ts index 1dd1bbd1d..77482a991 100644 --- a/web/cypress/support/incidents_prometheus_query_mocks/schema/schema-validator.ts +++ b/web/cypress/support/incidents_prometheus_query_mocks/schema/schema-validator.ts @@ -52,4 +52,4 @@ export function validateAndParseYamlFixture(yamlContent: string): { errors: [`YAML parsing error: ${error instanceof Error ? error.message : 'Unknown error'}`] }; } -} +} \ No newline at end of file diff --git a/web/cypress/support/incidents_prometheus_query_mocks/schema/validate-fixtures.ts b/web/cypress/support/incidents_prometheus_query_mocks/schema/validate-fixtures.ts index cd52ad1da..67586dea7 100755 --- a/web/cypress/support/incidents_prometheus_query_mocks/schema/validate-fixtures.ts +++ b/web/cypress/support/incidents_prometheus_query_mocks/schema/validate-fixtures.ts @@ -103,4 +103,4 @@ if (args[0] === '--all') { }); } -process.exit(allValid ? 0 : 1); +process.exit(allValid ? 0 : 1); \ No newline at end of file diff --git a/web/cypress/support/incidents_prometheus_query_mocks/schema/yaml-fixture-snippets.json b/web/cypress/support/incidents_prometheus_query_mocks/schema/yaml-fixture-snippets.json index 91eaa0672..d15c79367 100644 --- a/web/cypress/support/incidents_prometheus_query_mocks/schema/yaml-fixture-snippets.json +++ b/web/cypress/support/incidents_prometheus_query_mocks/schema/yaml-fixture-snippets.json @@ -58,4 +58,4 @@ ], "description": "Timeline with severity escalation" } -} +} \ No newline at end of file diff --git a/web/cypress/support/incidents_prometheus_query_mocks/types.ts b/web/cypress/support/incidents_prometheus_query_mocks/types.ts index 1812a49b8..ee2c161ec 100644 --- a/web/cypress/support/incidents_prometheus_query_mocks/types.ts +++ b/web/cypress/support/incidents_prometheus_query_mocks/types.ts @@ -80,4 +80,4 @@ export interface AlertFixture { severity: 'critical' | 'warning' | 'info'; }>; }; -} +} \ No newline at end of file diff --git a/web/cypress/support/incidents_prometheus_query_mocks/utils.ts b/web/cypress/support/incidents_prometheus_query_mocks/utils.ts index 5807b8d7d..4d7e25a06 100644 --- a/web/cypress/support/incidents_prometheus_query_mocks/utils.ts +++ b/web/cypress/support/incidents_prometheus_query_mocks/utils.ts @@ -109,4 +109,4 @@ export function nowInClusterTimezone(): number { const timezone = Cypress.env('TIMEZONE') || 'UTC'; const now = Math.floor(TZDate.tz(timezone).getTime() / 1000); return now; -} +} \ No newline at end of file diff --git a/web/cypress/support/index.ts b/web/cypress/support/index.ts index 2a9dd2dbf..c79ec2353 100644 --- a/web/cypress/support/index.ts +++ b/web/cypress/support/index.ts @@ -26,7 +26,8 @@ Cypress.on('uncaught:exception', (err) => { message.includes('Unauthorized') || message.includes('Bad Gateway') || message.includes(`Cannot read properties of null (reading 'default')`) || - message.includes(`(intermediate value) is not a function`) + message.includes(`(intermediate value) is not a function`) || + message.includes(`Cannot read properties of null (reading '0')`) ) { console.warn('Ignored frontend exception:', err.message); return false; diff --git a/web/cypress/support/monitoring/00.bvt_monitoring.cy.ts b/web/cypress/support/monitoring/00.bvt_monitoring.cy.ts index bee9e9c38..f45afd27d 100644 --- a/web/cypress/support/monitoring/00.bvt_monitoring.cy.ts +++ b/web/cypress/support/monitoring/00.bvt_monitoring.cy.ts @@ -171,4 +171,4 @@ export function testBVTMonitoring(perspective: PerspectiveConfig) { listPage.ARRows.ARShouldBe(`${WatchdogAlert.ALERTNAME}`, `${WatchdogAlert.SEVERITY}`, 1, AlertsAlertState.FIRING); }); -} +} \ No newline at end of file diff --git a/web/cypress/support/monitoring/00.bvt_monitoring_namespace.cy.ts b/web/cypress/support/monitoring/00.bvt_monitoring_namespace.cy.ts index 362403552..7b9496e94 100644 --- a/web/cypress/support/monitoring/00.bvt_monitoring_namespace.cy.ts +++ b/web/cypress/support/monitoring/00.bvt_monitoring_namespace.cy.ts @@ -92,7 +92,7 @@ export function testBVTMonitoringTestsNamespace(perspective: PerspectiveConfig) cy.log('5.3 silence alert page'); commonPages.titleShouldHaveText('Silence alert'); - commonPages.projectDropdownShouldExist(); + commonPages.projectDropdownShouldNotExist(); // Launches create silence form silenceAlertPage.silenceAlertSectionDefault(); @@ -175,4 +175,4 @@ export function testBVTMonitoringTestsNamespace(perspective: PerspectiveConfig) listPage.ARRows.ARShouldBe(`${WatchdogAlert.ALERTNAME}`, `${WatchdogAlert.SEVERITY}`, 1, AlertsAlertState.FIRING); }); -} +} \ No newline at end of file diff --git a/web/cypress/support/monitoring/01.reg_alerts.cy.ts b/web/cypress/support/monitoring/01.reg_alerts.cy.ts index 6ddf75abd..c2e608636 100644 --- a/web/cypress/support/monitoring/01.reg_alerts.cy.ts +++ b/web/cypress/support/monitoring/01.reg_alerts.cy.ts @@ -262,4 +262,4 @@ export function testAlertsRegression(perspective: PerspectiveConfig) { }); -} +} \ No newline at end of file diff --git a/web/cypress/support/monitoring/02.reg_metrics_1.cy.ts b/web/cypress/support/monitoring/02.reg_metrics_1.cy.ts index c995ea0ed..603509549 100644 --- a/web/cypress/support/monitoring/02.reg_metrics_1.cy.ts +++ b/web/cypress/support/monitoring/02.reg_metrics_1.cy.ts @@ -159,13 +159,11 @@ export function testMetricsRegression1(perspective: PerspectiveConfig) { cy.log('4.5 Prepare to test Reset Zoom Button'); metricsPage.clickActionsDeleteAllQueries(); metricsPage.clickPredefinedQuery(MetricsPagePredefinedQueries.CPU_USAGE); - metricsPage.graphCardInlineInfoAssertion(true); metricsPage.clickGraphTimespanDropdown(GraphTimespan.ONE_WEEK); - metricsPage.graphCardInlineInfoAssertion(false); cy.log('4.6 Reset Zoom Button'); metricsPage.clickResetZoomButton(); - metricsPage.graphCardInlineInfoAssertion(true); + cy.byTestID(DataTestIDs.MetricGraphTimespanInput).should('have.attr', 'value', GraphTimespan.THIRTY_MINUTES); cy.log('4.7 Hide Graph Button'); metricsPage.clickHideGraphButton(); @@ -175,17 +173,14 @@ export function testMetricsRegression1(perspective: PerspectiveConfig) { metricsPage.clickShowGraphButton(); cy.byTestID(DataTestIDs.MetricGraph).should('be.visible'); - cy.log('4.9 Stacked Checkbox'); - cy.byTestID(DataTestIDs.MetricStackedCheckbox).should('not.exist'); - - cy.log('4.10 Disconnected Checkbox'); + cy.log('4.9 Disconnected Checkbox'); cy.byTestID(DataTestIDs.MetricDisconnectedCheckbox).should('be.visible'); - cy.log('4.11 Prepare to test Stacked Checkbox'); + cy.log('4.10 Prepare to test Stacked Checkbox'); metricsPage.clickActionsDeleteAllQueries(); metricsPage.clickInsertExampleQuery(); - cy.log('4.12 Stacked Checkbox'); + cy.log('4.11 Stacked Checkbox'); metricsPage.clickStackedCheckboxAndAssert(); }); @@ -193,7 +188,6 @@ export function testMetricsRegression1(perspective: PerspectiveConfig) { //https://issues.redhat.com/browse/OU-974 - [Metrics] - Units - undefined showing in Y axis and tooltip it(`${perspective.name} perspective - Metrics > Units`, () => { cy.log('5.1 Preparation to test Units dropdown'); - cy.visit('/monitoring/query-browser'); metricsPage.clickInsertExampleQuery(); metricsPage.unitsDropdownAssertion(); @@ -205,4 +199,3 @@ export function testMetricsRegression1(perspective: PerspectiveConfig) { }); } - diff --git a/web/cypress/support/monitoring/02.reg_metrics_2.cy.ts b/web/cypress/support/monitoring/02.reg_metrics_2.cy.ts index ee7f5921d..9a93ee397 100644 --- a/web/cypress/support/monitoring/02.reg_metrics_2.cy.ts +++ b/web/cypress/support/monitoring/02.reg_metrics_2.cy.ts @@ -15,6 +15,7 @@ export function testMetricsRegression2(perspective: PerspectiveConfig) { it(`${perspective.name} perspective - Metrics > Add Query - Run Queries - Kebab icon`, () => { cy.log('6.1 Preparation to test Add Query button'); + metricsPage.clickActionsDeleteAllQueries(); cy.byTestID(DataTestIDs.MetricsPageExpandCollapseRowButton).should('have.length', 1); metricsPage.clickInsertExampleQuery(); cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY); @@ -264,23 +265,8 @@ export function testMetricsRegression2(perspective: PerspectiveConfig) { }); - it(`${perspective.name} perspective - Metrics > Ungraphable results`, () => { - cy.log('8.1 Ungraphable results'); - metricsPage.clickPredefinedQuery(MetricsPagePredefinedQueries.CPU_USAGE); - metricsPage.clickPredefinedQuery(MetricsPagePredefinedQueries.MEMORY_USAGE); - metricsPage.clickPredefinedQuery(MetricsPagePredefinedQueries.FILESYSTEM_USAGE); - metricsPage.clickPredefinedQuery(MetricsPagePredefinedQueries.RECEIVE_BANDWIDTH); - metricsPage.clickPredefinedQuery(MetricsPagePredefinedQueries.TRANSMIT_BANDWIDTH); - metricsPage.clickPredefinedQuery(MetricsPagePredefinedQueries.RATE_OF_RECEIVED_PACKETS); - cy.byLegacyTestID(LegacyTestIDs.NamespaceBarDropdown).scrollIntoView(); - - cy.get(Classes.MetricsPageUngraphableResults).contains(MetricGraphEmptyState.UNGRAPHABLE_RESULTS).should('be.visible'); - cy.get(Classes.MetricsPageUngraphableResultsDescription).contains(MetricGraphEmptyState.UNGRAPHABLE_RESULTS_DESCRIPTION).should('be.visible'); - - }); - it(`${perspective.name} perspective - Metrics > No Datapoints`, () => { - cy.log('9.1 No Datapoints'); + cy.log('8.1 No Datapoints'); metricsPage.enterQueryInput(0, 'aaaaaaaaaa'); metricsPage.clickRunQueriesButton(); cy.byTestID(DataTestIDs.MetricGraphNoDatapointsFound).scrollIntoView().contains(MetricGraphEmptyState.NO_DATAPOINTS_FOUND).should('be.visible'); @@ -294,11 +280,10 @@ export function testMetricsRegression2(perspective: PerspectiveConfig) { }); it(`${perspective.name} perspective - Metrics > No Datapoints with alert`, () => { - cy.log('10.1 No Datapoints with alert'); + cy.log('9.1 No Datapoints with alert'); metricsPage.enterQueryInput(0, MetricsPageQueryInput.QUERY_WITH_ALERT); metricsPage.clickRunQueriesButton(); cy.byOUIAID(DataTestIDs.MetricsGraphAlertDanger).should('be.visible'); }); } - diff --git a/web/cypress/support/monitoring/03.reg_legacy_dashboards.cy.ts b/web/cypress/support/monitoring/03.reg_legacy_dashboards.cy.ts index 04ccdc1c1..9ae86762a 100644 --- a/web/cypress/support/monitoring/03.reg_legacy_dashboards.cy.ts +++ b/web/cypress/support/monitoring/03.reg_legacy_dashboards.cy.ts @@ -1,6 +1,6 @@ import { nav } from '../../views/nav'; import { legacyDashboardsPage } from '../../views/legacy-dashboards'; -import { API_PERFORMANCE_DASHBOARD_PANELS, LegacyDashboardsDashboardDropdown, MetricsPageQueryInput, WatchdogAlert } from '../../fixtures/monitoring/constants'; +import { LegacyDashboardsDashboardDropdown, MetricsPageQueryInput, WatchdogAlert } from '../../fixtures/monitoring/constants'; import { Classes, LegacyDashboardPageTestIDs, DataTestIDs } from '../../../src/components/data-test'; import { metricsPage } from '../../views/metrics'; import { alertingRuleDetailsPage } from '../../views/alerting-rule-details-page'; @@ -35,9 +35,7 @@ export function testLegacyDashboardsRegression(perspective: PerspectiveConfig) { legacyDashboardsPage.clickDashboardDropdown('API_PERFORMANCE'); cy.log('1.5 Dashboard API Performance panels'); - for (const panel of Object.values(API_PERFORMANCE_DASHBOARD_PANELS)) { - legacyDashboardsPage.dashboardAPIPerformancePanelAssertion(panel); - } + legacyDashboardsPage.dashboardAPIPerformancePanelAssertion(); cy.log('1.6 Inspect - API Request Duration by Verb - 99th Percentile'); cy.byTestID(LegacyDashboardPageTestIDs.Inspect).eq(0).scrollIntoView().should('be.visible').click(); diff --git a/web/cypress/support/monitoring/04.reg_alerts_namespace.cy.ts b/web/cypress/support/monitoring/04.reg_alerts_namespace.cy.ts index 3899bc067..1d1f9abf1 100644 --- a/web/cypress/support/monitoring/04.reg_alerts_namespace.cy.ts +++ b/web/cypress/support/monitoring/04.reg_alerts_namespace.cy.ts @@ -49,9 +49,8 @@ export function testAlertsRegressionNamespace(perspective: PerspectiveConfig) { cy.log('2.1 use sidebar nav to go to Observe > Alerting'); nav.tabs.switchTab('Silences'); silencesListPage.createSilence(); - commonPages.projectDropdownShouldExist(); cy.log('https://issues.redhat.com/browse/OU-1109 - [Namespace-level] - Dev user - Create a silence - namespace label does not have a value'); - silenceAlertPage.assertNamespaceLabelNamespaceValueDisabled('namespace', `${WatchdogAlert.NAMESPACE}`, true); + silenceAlertPage.assertLabelNameLabelValueRegExNegMatcher('namespace', `${WatchdogAlert.NAMESPACE}`, false, false); silenceAlertPage.assertCommentNoError(); silenceAlertPage.clickSubmit(); silenceAlertPage.assertCommentWithError(); @@ -127,13 +126,12 @@ export function testAlertsRegressionNamespace(perspective: PerspectiveConfig) { cy.log('3.10 Recreate silence'); silenceDetailsPage.recreateSilence(false); commonPages.titleShouldHaveText('Recreate silence'); - commonPages.projectDropdownShouldExist(); + commonPages.projectDropdownShouldNotExist(); silenceAlertPage.silenceAlertSectionDefault(); silenceAlertPage.durationSectionDefault(); silenceAlertPage.alertLabelsSectionDefault(); silenceAlertPage.assertLabelNameLabelValueRegExNegMatcher('alertname', `${WatchdogAlert.ALERTNAME}`, false, false); cy.log('https://issues.redhat.com/browse/OU-1109 - [Namespace-level] - Dev user - Create a silence - namespace label does not have a value'); - silenceAlertPage.assertNamespaceLabelNamespaceValueDisabled('namespace', `${WatchdogAlert.NAMESPACE}`, true); silenceAlertPage.assertLabelNameLabelValueRegExNegMatcher('namespace', `${WatchdogAlert.NAMESPACE}`, false, false); silenceAlertPage.assertLabelNameLabelValueRegExNegMatcher('prometheus', 'openshift-monitoring/k8s', false, false); silenceAlertPage.clickSubmit(); @@ -147,13 +145,13 @@ export function testAlertsRegressionNamespace(perspective: PerspectiveConfig) { silencesListPage.filter.byName( `${WatchdogAlert.ALERTNAME}`); silencesListPage.rows.editSilence(); commonPages.titleShouldHaveText('Edit silence'); + commonPages.projectDropdownShouldNotExist(); silenceAlertPage.silenceAlertSectionDefault(); silenceAlertPage.editAlertWarning(); silenceAlertPage.editDurationSectionDefault(); silenceAlertPage.alertLabelsSectionDefault(); silenceAlertPage.assertLabelNameLabelValueRegExNegMatcher('alertname', `${WatchdogAlert.ALERTNAME}`, false, false); cy.log('https://issues.redhat.com/browse/OU-1109 - [Namespace-level] - Dev user - Create a silence - namespace label does not have a value'); - silenceAlertPage.assertNamespaceLabelNamespaceValueDisabled('namespace', `${WatchdogAlert.NAMESPACE}`, true); silenceAlertPage.assertLabelNameLabelValueRegExNegMatcher('namespace', `${WatchdogAlert.NAMESPACE}`, false, false); silenceAlertPage.assertLabelNameLabelValueRegExNegMatcher('prometheus', 'openshift-monitoring/k8s', false, false); silenceAlertPage.clickSubmit(); @@ -273,4 +271,4 @@ export function testAlertsRegressionNamespace(perspective: PerspectiveConfig) { }); -} +} \ No newline at end of file diff --git a/web/cypress/support/monitoring/05.reg_metrics_namespace_1.cy.ts b/web/cypress/support/monitoring/05.reg_metrics_namespace_1.cy.ts index af6e5bfd3..36d3cf2a4 100644 --- a/web/cypress/support/monitoring/05.reg_metrics_namespace_1.cy.ts +++ b/web/cypress/support/monitoring/05.reg_metrics_namespace_1.cy.ts @@ -132,7 +132,7 @@ export function testMetricsRegressionNamespace1(perspective: PerspectiveConfig) cy.log('4.1 Insert Example Query'); metricsPage.clickInsertExampleQuery(); metricsPage.shouldBeLoadedWithGraph(); - cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY); + cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY_NAMESPACE); metricsPage.graphAxisXAssertion(GraphTimespan.THIRTY_MINUTES); cy.log('4.2 Graph Timespan Dropdown'); @@ -160,13 +160,11 @@ export function testMetricsRegressionNamespace1(perspective: PerspectiveConfig) metricsPage.clickActionsDeleteAllQueries(); metricsPage.clickPredefinedQuery(MetricsPagePredefinedQueries.RATE_OF_TRANSMITTED_PACKETS_DROPPED); metricsPage.clickPredefinedQuery(MetricsPagePredefinedQueries.RATE_OF_RECEIVED_PACKETS_DROPPED); - metricsPage.graphCardInlineInfoAssertion(true); metricsPage.clickGraphTimespanDropdown(GraphTimespan.ONE_WEEK); - metricsPage.graphCardInlineInfoAssertion(false); cy.log('4.6 Reset Zoom Button'); metricsPage.clickResetZoomButton(); - metricsPage.graphCardInlineInfoAssertion(true); + cy.byTestID(DataTestIDs.MetricGraphTimespanInput).should('have.attr', 'value', GraphTimespan.THIRTY_MINUTES); cy.log('4.7 Hide Graph Button'); metricsPage.clickHideGraphButton(); @@ -176,24 +174,20 @@ export function testMetricsRegressionNamespace1(perspective: PerspectiveConfig) metricsPage.clickShowGraphButton(); cy.byTestID(DataTestIDs.MetricGraph).should('be.visible'); - cy.log('4.9 Stacked Checkbox'); - cy.byTestID(DataTestIDs.MetricStackedCheckbox).should('be.visible'); - - cy.log('4.10 Disconnected Checkbox'); + cy.log('4.9 Disconnected Checkbox'); cy.byTestID(DataTestIDs.MetricDisconnectedCheckbox).should('be.visible'); - cy.log('4.11 Prepare to test Stacked Checkbox'); + cy.log('4.10 Prepare to test Stacked Checkbox'); metricsPage.clickActionsDeleteAllQueries(); metricsPage.clickInsertExampleQuery(); - cy.log('4.12 Stacked Checkbox'); + cy.log('4.11 Stacked Checkbox'); metricsPage.clickStackedCheckboxAndAssert(); }); //https://issues.redhat.com/browse/OU-974 - [Metrics] - Units - undefined showing in Y axis and tooltip it(`${perspective.name} perspective - Metrics > Units`, () => { cy.log('5.1 Preparation to test Units dropdown'); - cy.visit('/monitoring/query-browser'); metricsPage.clickInsertExampleQuery(); metricsPage.unitsDropdownAssertion(); @@ -203,4 +197,4 @@ export function testMetricsRegressionNamespace1(perspective: PerspectiveConfig) metricsPage.unitsAxisYAssertion(unit); }); }); -} +} \ No newline at end of file diff --git a/web/cypress/support/monitoring/05.reg_metrics_namespace_2.cy.ts b/web/cypress/support/monitoring/05.reg_metrics_namespace_2.cy.ts index 8636c2b8b..f02951ee5 100644 --- a/web/cypress/support/monitoring/05.reg_metrics_namespace_2.cy.ts +++ b/web/cypress/support/monitoring/05.reg_metrics_namespace_2.cy.ts @@ -18,7 +18,7 @@ export function testMetricsRegressionNamespace2(perspective: PerspectiveConfig) metricsPage.shouldBeLoaded(); cy.byTestID(DataTestIDs.MetricsPageExpandCollapseRowButton).should('have.length', 1); metricsPage.clickInsertExampleQuery(); - cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY); + cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY_NAMESPACE); cy.log('6.2 Only one query added, resulting in 2 rows'); metricsPage.clickActionsAddQuery(); @@ -26,7 +26,7 @@ export function testMetricsRegressionNamespace2(perspective: PerspectiveConfig) cy.byTestID(DataTestIDs.MetricsPageExpandCollapseRowButton).find('button').eq(0).should('have.attr', 'aria-expanded', 'true'); cy.byTestID(DataTestIDs.MetricsPageExpandCollapseRowButton).find('button').eq(1).should('have.attr', 'aria-expanded', 'true'); cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.EXPRESSION_PRESS_SHIFT_ENTER_FOR_NEWLINES); - cy.get(Classes.MetricsPageQueryInput).eq(1).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY); + cy.get(Classes.MetricsPageQueryInput).eq(1).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY_NAMESPACE); cy.log('6.3 Preparation to test Run Queries button'); cy.get(Classes.MetricsPageQueryInput).eq(0).should('be.visible').clear(); @@ -51,7 +51,7 @@ export function testMetricsRegressionNamespace2(perspective: PerspectiveConfig) metricsPage.expandCollapseRowAssertion(false, 0, true, true); metricsPage.expandCollapseRowAssertion(true, 1, true, true); cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.VECTOR_QUERY); - cy.get(Classes.MetricsPageQueryInput).eq(1).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY); + cy.get(Classes.MetricsPageQueryInput).eq(1).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY_NAMESPACE); cy.byTestID(DataTestIDs.MetricGraph).scrollIntoView().should('be.visible'); metricsPage.clickKebabDropdown(0); cy.get(Classes.MenuItemDisabled).contains(MetricsPageQueryKebabDropdown.HIDE_ALL_SERIES).should('be.visible'); @@ -64,7 +64,7 @@ export function testMetricsRegressionNamespace2(perspective: PerspectiveConfig) metricsPage.expandCollapseRowAssertion(true, 0, true, true); metricsPage.expandCollapseRowAssertion(true, 1, true, true); cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.VECTOR_QUERY); - cy.get(Classes.MetricsPageQueryInput).eq(1).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY); + cy.get(Classes.MetricsPageQueryInput).eq(1).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY_NAMESPACE); cy.byTestID(DataTestIDs.MetricGraph).scrollIntoView().should('be.visible'); metricsPage.clickKebabDropdown(0); cy.byTestID(DataTestIDs.MetricsPageHideShowAllSeriesDropdownItem).contains(MetricsPageQueryKebabDropdown.HIDE_ALL_SERIES).should('be.visible'); @@ -90,7 +90,7 @@ export function testMetricsRegressionNamespace2(perspective: PerspectiveConfig) cy.byTestID(DataTestIDs.MetricsPageExportCsvDropdownItem).should('not.exist'); metricsPage.clickKebabDropdown(1); cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.VECTOR_QUERY); - cy.get(Classes.MetricsPageQueryInput).eq(1).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY); + cy.get(Classes.MetricsPageQueryInput).eq(1).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY_NAMESPACE); cy.byTestID(DataTestIDs.MetricGraph).should('not.exist'); cy.byTestID(DataTestIDs.MetricsPageNoQueryEnteredTitle).should('be.visible'); cy.byTestID(DataTestIDs.MetricsPageNoQueryEntered).should('be.visible'); @@ -115,7 +115,7 @@ export function testMetricsRegressionNamespace2(perspective: PerspectiveConfig) cy.byTestID(DataTestIDs.MetricsPageExportCsvDropdownItem).contains(MetricsPageQueryKebabDropdown.EXPORT_AS_CSV).should('be.visible'); metricsPage.clickKebabDropdown(1); cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.VECTOR_QUERY); - cy.get(Classes.MetricsPageQueryInput).eq(1).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY); + cy.get(Classes.MetricsPageQueryInput).eq(1).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY_NAMESPACE); cy.byTestID(DataTestIDs.MetricGraph).scrollIntoView().should('be.visible'); cy.log('6.10 Kebab icon - Hide all series'); @@ -188,14 +188,14 @@ export function testMetricsRegressionNamespace2(perspective: PerspectiveConfig) cy.byTestID(DataTestIDs.MetricsPageDeleteQueryDropdownItem).contains(MetricsPageQueryKebabDropdown.DELETE_QUERY).should('be.visible').click(); cy.byTestID(DataTestIDs.MetricsPageExpandCollapseRowButton).should('have.length', 1); cy.byTestID(DataTestIDs.MetricsPageExpandCollapseRowButton).find('button').eq(0).should('have.attr', 'aria-expanded', 'true'); - cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY); + cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY_NAMESPACE); cy.byTestID(DataTestIDs.MetricsPageSelectAllUnselectAllButton).should('have.length', 1); cy.log('6.17 Kebab icon - Duplicate query'); metricsPage.clickKebabDropdown(0); cy.byTestID(DataTestIDs.MetricsPageDuplicateQueryDropdownItem).contains(MetricsPageQueryKebabDropdown.DUPLICATE_QUERY).should('be.visible').click(); - cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY); - cy.get(Classes.MetricsPageQueryInput).eq(1).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY); + cy.get(Classes.MetricsPageQueryInput).eq(0).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY_NAMESPACE); + cy.get(Classes.MetricsPageQueryInput).eq(1).should('contain', MetricsPageQueryInput.INSERT_EXAMPLE_QUERY_NAMESPACE); cy.byTestID(DataTestIDs.MetricsPageExpandCollapseRowButton).should('have.length', 2); metricsPage.expandCollapseRowAssertion(true, 1, true, true); cy.byTestID(DataTestIDs.MetricsPageExpandCollapseRowButton).find('button').eq(0).should('have.attr', 'aria-expanded', 'true'); @@ -284,8 +284,7 @@ export function testMetricsRegressionNamespace2(perspective: PerspectiveConfig) cy.byOUIAID(DataTestIDs.MetricsGraphAlertDanger).should('be.visible'); }); - //TODO remove skip when OU-1118 get answered/fixed - it.skip(`${perspective.name} perspective - Metrics > Empty state`, () => { + it(`${perspective.name} perspective - Metrics > Empty state`, () => { cy.log('11.1 Insert example query - Empty state'); cy.changeNamespace("default"); metricsPage.clickInsertExampleQuery(); @@ -299,4 +298,3 @@ export function testMetricsRegressionNamespace2(perspective: PerspectiveConfig) }); } - diff --git a/web/cypress/support/monitoring/06.reg_legacy_dashboards_namespace.cy.ts b/web/cypress/support/monitoring/06.reg_legacy_dashboards_namespace.cy.ts index 24c2828d1..4f57241fd 100644 --- a/web/cypress/support/monitoring/06.reg_legacy_dashboards_namespace.cy.ts +++ b/web/cypress/support/monitoring/06.reg_legacy_dashboards_namespace.cy.ts @@ -1,12 +1,13 @@ import { nav } from '../../views/nav'; import { legacyDashboardsPage } from '../../views/legacy-dashboards'; -import { KUBERNETES_COMPUTE_RESOURCES_NAMESPACE_PODS_PANELS, LegacyDashboardsDashboardDropdownNamespace, MetricsPageQueryInput, MetricsPageQueryInputByNamespace, WatchdogAlert } from '../../fixtures/monitoring/constants'; +import { LegacyDashboardsDashboardDropdownNamespace, MetricsPageQueryInputByNamespace, WatchdogAlert } from '../../fixtures/monitoring/constants'; import { Classes, LegacyDashboardPageTestIDs, DataTestIDs } from '../../../src/components/data-test'; import { metricsPage } from '../../views/metrics'; import { alertingRuleDetailsPage } from '../../views/alerting-rule-details-page'; import { alerts } from '../../fixtures/monitoring/alert'; import { listPage } from '../../views/list-page'; import { commonPages } from '../../views/common'; +import { guidedTour } from '../../views/tour'; export interface PerspectiveConfig { name: string; @@ -33,9 +34,7 @@ export function testLegacyDashboardsRegressionNamespace(perspective: Perspective legacyDashboardsPage.dashboardDropdownAssertion(LegacyDashboardsDashboardDropdownNamespace); cy.log('1.5 Dashboard Kubernetes Compute Resources Namespace Pods panels'); - for (const panel of Object.values(KUBERNETES_COMPUTE_RESOURCES_NAMESPACE_PODS_PANELS)) { - legacyDashboardsPage.dashboardKubernetesComputeResourcesNamespacePodsPanelAssertion(panel); - } + legacyDashboardsPage.dashboardKubernetesComputeResourcesNamespacePodsPanelAssertion(); cy.log('1.6 Inspect - CPU Utilisation (from requests)'); cy.byTestID(LegacyDashboardPageTestIDs.Inspect).eq(0).scrollIntoView().should('be.visible').click(); @@ -53,6 +52,7 @@ export function testLegacyDashboardsRegressionNamespace(perspective: Perspective cy.log('2.2 Empty state'); cy.changeNamespace('default'); + legacyDashboardsPage.shouldBeLoaded(); cy.byTestID(DataTestIDs.MetricGraphNoDatapointsFound).eq(0).scrollIntoView().should('be.visible'); legacyDashboardsPage.clickKebabDropdown(0); cy.byTestID(LegacyDashboardPageTestIDs.ExportAsCsv).should('be.visible'); @@ -62,6 +62,13 @@ export function testLegacyDashboardsRegressionNamespace(perspective: Perspective it(`${perspective.name} perspective - Dashboards (legacy) - No kebab dropdown`, () => { cy.log('3.1 Single Stat - No kebab dropdown'); + cy.visit('/'); + guidedTour.close(); + cy.validateLogin(); + nav.sidenav.clickNavLink(['Observe', 'Dashboards']); + commonPages.titleShouldHaveText('Dashboards'); + cy.changeNamespace('openshift-monitoring'); + legacyDashboardsPage.shouldBeLoaded(); cy.byLegacyTestID('chart-1').find('[data-test="'+DataTestIDs.KebabDropdownButton+'"]').should('not.exist'); cy.log('3.2 Table - No kebab dropdown'); diff --git a/web/cypress/support/perses/00.coo_bvt_perses.cy.ts b/web/cypress/support/perses/00.coo_bvt_perses_admin.cy.ts similarity index 75% rename from web/cypress/support/perses/00.coo_bvt_perses.cy.ts rename to web/cypress/support/perses/00.coo_bvt_perses_admin.cy.ts index 0e671193b..5fa469972 100644 --- a/web/cypress/support/perses/00.coo_bvt_perses.cy.ts +++ b/web/cypress/support/perses/00.coo_bvt_perses_admin.cy.ts @@ -1,7 +1,7 @@ import { persesDashboardsAcceleratorsCommonMetricsPanels, persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev } from '../../fixtures/perses/constants'; import { commonPages } from '../../views/common'; import { persesDashboardsPage } from '../../views/perses-dashboards'; -import { persesDataTestIDs } from '../../../src/components/data-test'; +import { persesMUIDataTestIDs } from '../../../src/components/data-test'; export interface PerspectiveConfig { name: string; @@ -31,8 +31,8 @@ export function testBVTCOOPerses(perspective: PerspectiveConfig) { cy.log(`2.1. use sidebar nav to go to Observe > Dashboards (Perses) > Accelerators common metrics dashboard`); cy.changeNamespace('openshift-cluster-observability-operator'); persesDashboardsPage.clickDashboardDropdown(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0] as keyof typeof persesDashboardsDashboardDropdownCOO); - cy.byDataTestID(persesDataTestIDs.variableDropdown+'-cluster').should('be.visible'); - persesDashboardsPage.panelGroupHeaderAssertion('Accelerators'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-cluster').should('be.visible'); + persesDashboardsPage.panelGroupHeaderAssertion('Accelerators', 'Open'); persesDashboardsPage.panelHeadersAcceleratorsCommonMetricsAssertion(); persesDashboardsPage.expandPanel(persesDashboardsAcceleratorsCommonMetricsPanels.GPU_UTILIZATION); persesDashboardsPage.collapsePanel(persesDashboardsAcceleratorsCommonMetricsPanels.GPU_UTILIZATION); @@ -42,17 +42,17 @@ export function testBVTCOOPerses(perspective: PerspectiveConfig) { cy.log(`3.1. use sidebar nav to go to Observe > Dashboards (Perses) > Perses Dashboard Sample dashboard`); cy.changeNamespace('perses-dev'); persesDashboardsPage.clickDashboardDropdown(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0] as keyof typeof persesDashboardsDashboardDropdownPersesDev); - cy.byDataTestID(persesDataTestIDs.variableDropdown+'-job').should('be.visible'); - cy.byDataTestID(persesDataTestIDs.variableDropdown+'-instance').should('be.visible'); - cy.byDataTestID(persesDataTestIDs.variableDropdown+'-interval').should('be.visible'); - cy.byDataTestID(persesDataTestIDs.variableDropdown+'-text').should('be.visible'); - persesDashboardsPage.panelGroupHeaderAssertion('Row 1'); - persesDashboardsPage.expandPanel('RAM Used'); - persesDashboardsPage.collapsePanel('RAM Used'); - persesDashboardsPage.statChartValueAssertion('RAM Used', true); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-job').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-instance').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-interval').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-text').should('be.visible'); + persesDashboardsPage.panelGroupHeaderAssertion('Row 1', 'Open'); + persesDashboardsPage.expandPanel('RAM Total'); + persesDashboardsPage.collapsePanel('RAM Total'); + persesDashboardsPage.statChartValueAssertion('RAM Total', true); persesDashboardsPage.searchAndSelectVariable('job', 'node-exporter'); - persesDashboardsPage.statChartValueAssertion('RAM Used', false); + persesDashboardsPage.statChartValueAssertion('RAM Total', false); }); -} +} \ No newline at end of file diff --git a/web/cypress/support/perses/00.coo_bvt_perses_admin_1.cy.ts b/web/cypress/support/perses/00.coo_bvt_perses_admin_1.cy.ts new file mode 100644 index 000000000..4ecbbc704 --- /dev/null +++ b/web/cypress/support/perses/00.coo_bvt_perses_admin_1.cy.ts @@ -0,0 +1,236 @@ +import { persesDashboardsAcceleratorsCommonMetricsPanels, persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev, persesDashboardsEmptyDashboard } from '../../fixtures/perses/constants'; +import { persesDashboardsPage } from '../../views/perses-dashboards'; +import { persesMUIDataTestIDs } from '../../../src/components/data-test'; +import { listPersesDashboardsPage } from '../../views/perses-dashboards-list-dashboards'; +import { persesDashboardsPanelGroup } from '../../views/perses-dashboards-panelgroup'; +import { persesDashboardsPanel } from '../../views/perses-dashboards-panel'; +import { persesDashboardsEditVariables } from '../../views/perses-dashboards-edit-variables'; +import { persesCreateDashboardsPage } from '../../views/perses-dashboards-create-dashboard'; +import { persesDashboardsAddListVariableSource } from '../../fixtures/perses/constants'; +import { persesDashboardSampleQueries } from '../../fixtures/perses/constants'; +import { persesDashboardsAddListPanelType } from '../../fixtures/perses/constants'; +import { commonPages } from '../../views/common'; + +export interface PerspectiveConfig { + name: string; + beforeEach?: () => void; +} + +export function runBVTCOOPersesTests1(perspective: PerspectiveConfig) { + testBVTCOOPerses1(perspective); +} + +export function testBVTCOOPerses1(perspective: PerspectiveConfig) { + + it(`1.${perspective.name} perspective - Dashboards (Perses) page`, () => { + cy.log(`1.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + persesDashboardsPage.shouldBeLoaded1(); + }); + + it(`2.${perspective.name} perspective - Accelerators common metrics dashboard `, () => { + cy.log(`2.1. use sidebar nav to go to Observe > Dashboards (Perses) > Accelerators common metrics dashboard`); + cy.changeNamespace('openshift-cluster-observability-operator'); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + cy.wait(2000); + + cy.log(`2.2. Select dashboard`); + persesDashboardsPage.clickDashboardDropdown(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0] as keyof typeof persesDashboardsDashboardDropdownCOO); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-cluster').should('be.visible'); + persesDashboardsPage.panelGroupHeaderAssertion('Accelerators', 'Open'); + persesDashboardsPage.panelHeadersAcceleratorsCommonMetricsAssertion(); + persesDashboardsPage.expandPanel(persesDashboardsAcceleratorsCommonMetricsPanels.GPU_UTILIZATION); + persesDashboardsPage.collapsePanel(persesDashboardsAcceleratorsCommonMetricsPanels.GPU_UTILIZATION); + }); + + it(`3.${perspective.name} perspective - Perses Dashboard Sample dashboard`, () => { + cy.log(`3.1. use sidebar nav to go to Observe > Dashboards (Perses) > Perses Dashboard Sample dashboard`); + cy.changeNamespace('perses-dev'); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + cy.wait(2000); + persesDashboardsPage.clickDashboardDropdown(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0] as keyof typeof persesDashboardsDashboardDropdownPersesDev); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-job').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-instance').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-interval').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-text').should('be.visible'); + persesDashboardsPage.panelGroupHeaderAssertion('Row 1', 'Open'); + persesDashboardsPage.expandPanel('RAM Total'); + persesDashboardsPage.collapsePanel('RAM Total'); + persesDashboardsPage.statChartValueAssertion('RAM Total', true); + persesDashboardsPage.searchAndSelectVariable('job', 'node-exporter'); + persesDashboardsPage.statChartValueAssertion('RAM Total', false); + }); + + it(`4.${perspective.name} perspective - Download and View JSON`, () => { + cy.log(`4.1. use sidebar nav to go to Observe > Dashboards (Perses) > Download and View JSON`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + persesDashboardsPage.downloadDashboard(true, persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2], 'JSON'); + persesDashboardsPage.downloadDashboard(true, persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2], 'YAML'); + persesDashboardsPage.downloadDashboard(true, persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2], 'YAML (CR v1alpha1)'); + persesDashboardsPage.downloadDashboard(true, persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2], 'YAML (CR v1alpha2)'); + persesDashboardsPage.viewJSON(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2], 'openshift-cluster-observability-operator'); + + }); + + it(`5.${perspective.name} perspective - Duplicate from a project to another, Rename and Delete`, () => { + cy.log(`5.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`5.2. Change namespace to perses-dev`); + cy.changeNamespace('perses-dev'); + listPersesDashboardsPage.countDashboards('3'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`5.3. Click on the Kebab icon - Duplicate to another project`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickDuplicateOption(); + listPersesDashboardsPage.duplicateDashboardEnterName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.duplicateDashboardSelectProjectDropdown('openshift-cluster-observability-operator'); + listPersesDashboardsPage.duplicateDashboardDuplicateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + persesDashboardsPage.shouldBeLoadedAfterDuplicate(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + persesDashboardsPage.backToListPersesDashboardsPage(); + + cy.log(`5.4. Click on the Kebab icon - Rename`); + cy.changeNamespace('openshift-cluster-observability-operator'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickRenameDashboardOption(); + listPersesDashboardsPage.renameDashboardEnterName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0] + ' - Renamed'); + listPersesDashboardsPage.renameDashboardRenameButton(); + + cy.log(`5.5. Click on the Kebab icon - Delete`); + listPersesDashboardsPage.clearAllFilters(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0] + ' - Renamed'); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`5.6. Click on the Kebab icon - Delete`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickDeleteOption(); + listPersesDashboardsPage.deleteDashboardDeleteButton(); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + + cy.log(`5.7. Search for the renamed dashboard`); + listPersesDashboardsPage.clearAllFilters(); + cy.changeNamespace('All Projects'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0] + ' - Renamed'); + listPersesDashboardsPage.countDashboards('0'); + listPersesDashboardsPage.clearAllFilters(); + + }); + + it(`6.${perspective.name} perspective - Create Dashboard with panel groups, panels and variables`, () => { + let dashboardName = 'Testing Dashboard - UP '; + let randomSuffix = Math.random().toString(5); + dashboardName += randomSuffix; + cy.log(`6.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`6.2. Click on Create button`); + listPersesDashboardsPage.clickCreateButton(); + persesCreateDashboardsPage.createDashboardShouldBeLoaded(); + + cy.log(`6.3. Create Dashboard`); + persesCreateDashboardsPage.selectProject('perses-dev'); + persesCreateDashboardsPage.enterDashboardName(dashboardName); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(dashboardName); + persesDashboardsPage.shouldBeLoadedEditionModeFromCreateDashboard(); + + cy.log(`6.4. Add Variable`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickButton('Add Variable'); + persesDashboardsEditVariables.addListVariable('interval', false, false, '', '', '', undefined, undefined); + persesDashboardsEditVariables.addListVariable_staticListVariable_enterValue('1m'); + persesDashboardsEditVariables.addListVariable_staticListVariable_enterValue('5m'); + persesDashboardsEditVariables.clickButton('Add'); + + persesDashboardsEditVariables.clickButton('Add Variable'); + persesDashboardsEditVariables.addListVariable('job', false, false, '', '', '', persesDashboardsAddListVariableSource.PROMETHEUS_LABEL_VARIABLE, undefined); + persesDashboardsEditVariables.addListVariable_promLabelValuesVariable_enterLabelName('job'); + persesDashboardsEditVariables.clickButton('Add'); + + persesDashboardsEditVariables.clickButton('Add Variable'); + persesDashboardsEditVariables.addListVariable('instance', false, false, '', '', '', persesDashboardsAddListVariableSource.PROMETHEUS_LABEL_VARIABLE, undefined); + persesDashboardsEditVariables.addListVariable_promLabelValuesVariable_enterLabelName('instance'); + persesDashboardsEditVariables.addListVariable_promLabelValuesVariable_addSeriesSelector(persesDashboardSampleQueries.CPU_LINE_MULTI_SERIES_SERIES_SELECTOR); + persesDashboardsEditVariables.clickButton('Add'); + + persesDashboardsEditVariables.clickButton('Apply'); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`6.5. Add Panel Group`); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('AddGroup'); + persesDashboardsPanelGroup.addPanelGroup('Panel Group Up', 'Open', ''); + + cy.log(`6.6. Add Panel`); + persesDashboardsPage.clickEditActionButton('AddPanel'); + persesDashboardsPanel.addPanelShouldBeLoaded(); + persesDashboardsPanel.addPanel('Up', 'Panel Group Up', persesDashboardsAddListPanelType.TIME_SERIES_CHART, 'This is a line chart test', 'up'); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`6.7. Back and check panel`); + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(dashboardName); + listPersesDashboardsPage.clickDashboard(dashboardName); + persesDashboardsPage.panelGroupHeaderAssertion('Panel Group Up', 'Open'); + persesDashboardsPage.assertPanel('Up', 'Panel Group Up', 'Open'); + persesDashboardsPage.assertVariableBeVisible('interval'); + persesDashboardsPage.assertVariableBeVisible('job'); + persesDashboardsPage.assertVariableBeVisible('instance'); + + cy.log(`6.8. Click on Edit button`); + persesDashboardsPage.clickEditButton(); + + cy.log(`6.9. Click on Edit Variables button and Delete all variables`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickDeleteVariableButton(0); + persesDashboardsEditVariables.clickDeleteVariableButton(0); + persesDashboardsEditVariables.clickDeleteVariableButton(0); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`6.10. Assert variables not exist`); + persesDashboardsPage.assertVariableNotExist('interval'); + persesDashboardsPage.assertVariableNotExist('job'); + persesDashboardsPage.assertVariableNotExist('instance'); + + cy.log(`6.11. Delete Panel`); + persesDashboardsPanel.deletePanel('Up'); + persesDashboardsPanel.clickDeletePanelButton(); + + cy.log(`6.12. Delete Panel Group`); + persesDashboardsPanelGroup.clickPanelGroupAction('Panel Group Up', 'delete'); + persesDashboardsPanelGroup.clickDeletePanelGroupButton(); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.get('h2').contains(persesDashboardsEmptyDashboard.TITLE).scrollIntoView().should('be.visible'); + cy.get('p').contains(persesDashboardsEmptyDashboard.DESCRIPTION).scrollIntoView().should('be.visible'); + + persesDashboardsPage.backToListPersesDashboardsPage(); + + cy.log(`6.13. Filter by Name`); + listPersesDashboardsPage.filter.byName(dashboardName); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`6.14. Click on the Kebab icon - Delete`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickDeleteOption(); + listPersesDashboardsPage.deleteDashboardDeleteButton(); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`6.15. Filter by Name`); + listPersesDashboardsPage.filter.byName(dashboardName); + listPersesDashboardsPage.countDashboards('0'); + listPersesDashboardsPage.clearAllFilters(); + + }); + +} \ No newline at end of file diff --git a/web/cypress/support/perses/01.coo_list_perses_admin.cy.ts b/web/cypress/support/perses/01.coo_list_perses_admin.cy.ts new file mode 100644 index 000000000..abdc5f982 --- /dev/null +++ b/web/cypress/support/perses/01.coo_list_perses_admin.cy.ts @@ -0,0 +1,362 @@ +import { persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev } from '../../fixtures/perses/constants'; +import { commonPages } from '../../views/common'; +import { listPersesDashboardsPage } from "../../views/perses-dashboards-list-dashboards"; +import { persesDashboardsPage } from '../../views/perses-dashboards'; + +export interface PerspectiveConfig { + name: string; + beforeEach?: () => void; +} + +export function runCOOListPersesTests(perspective: PerspectiveConfig) { + testCOOListPerses(perspective); +} + +export function runCOOListPersesDuplicateDashboardTests(perspective: PerspectiveConfig) { + testCOOListPersesDuplicateDashboard(perspective); +} + +export function testCOOListPerses(perspective: PerspectiveConfig) { + + it(`1.${perspective.name} perspective - List Dashboards (Perses) page`, () => { + cy.log(`1.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`1.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`1.3. Clear all filters`); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`1.4. Filter by Project and Name`); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.countDashboards('3'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PROMETHEUS_OVERVIEW[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`1.5. Clear all filters`); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`1.6. Filter by Project`); + listPersesDashboardsPage.filter.byProject('perses-dev'); + + cy.log(`1.7. Clear all filters`); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`1.8. Sort by Dashboard - Ascending`); + listPersesDashboardsPage.sortBy('Dashboard'); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0], 0); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownCOO.APM_DASHBOARD[0], 1); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0], 2); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0], 3); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.PROMETHEUS_OVERVIEW[0], 4); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0], 5); + + cy.log(`1.9. Sort by Dashboard - Descending`); + listPersesDashboardsPage.sortBy('Dashboard'); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0], 0); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.PROMETHEUS_OVERVIEW[0], 1); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0], 2); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0], 3); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownCOO.APM_DASHBOARD[0], 4); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0], 5); + + cy.log(`1.10. Filter by Name - Empty state`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2]); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + + cy.log(`1.11. Clear all filters`); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`1.12. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + }); + + + it(`2.${perspective.name} perspective - Kebab icon - Options available - Rename dashboard - Max length validation`, () => { + cy.log(`2.1. Filter by Name and click on the Kebab icon`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0]); + + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.assertKebabIconOptions(); + listPersesDashboardsPage.clickKebabIcon(); + + cy.log(`2.2. Click on the Kebab icon - Rename dashboard`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickRenameDashboardOption(); + listPersesDashboardsPage.renameDashboardEnterName('1234567890123456789012345678901234567890123456789012345678901234567890123456'); + listPersesDashboardsPage.renameDashboardRenameButton(); + listPersesDashboardsPage.assertRenameDashboardMaxLength(); + listPersesDashboardsPage.renameDashboardCancelButton(); + + cy.log(`2.3. Clear all filters and filter by Name`); + listPersesDashboardsPage.clearAllFilters(); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.clearAllFilters(); + + }); + + it(`3.${perspective.name} perspective - Kebab icon - Options available - Rename dashboard`, () => { + let dashboardName = 'Dashboard to test rename'; + let randomSuffix = Math.random().toString(5); + dashboardName += randomSuffix; + + cy.log(`3.1. Filter by Name and click on the Kebab icon`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0]); + + cy.log(`3.2. Click on the Kebab icon - Rename dashboard - Cancel`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickRenameDashboardOption(); + listPersesDashboardsPage.renameDashboardEnterName(dashboardName); + listPersesDashboardsPage.renameDashboardCancelButton(); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0], 0); + + cy.log(`3.3. Click on the Kebab icon - Rename dashboard - Rename`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickRenameDashboardOption(); + listPersesDashboardsPage.renameDashboardEnterName(dashboardName); + listPersesDashboardsPage.renameDashboardRenameButton(); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + + cy.log(`3.4. Clear all filters and filter by Name`); + listPersesDashboardsPage.clearAllFilters(); + listPersesDashboardsPage.filter.byName(dashboardName); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`3.5. Click on dashboard and verify the name`); + listPersesDashboardsPage.clickDashboard(dashboardName); + persesDashboardsPage.shouldBeLoaded1(); + persesDashboardsPage.shouldBeLoadedAfterRename(dashboardName); + persesDashboardsPage.backToListPersesDashboardsPage(); + + cy.log(`3.6. Rename back to the original name`); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(dashboardName); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`3.7. Click on the Kebab icon - Rename dashboard - Rename`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickRenameDashboardOption(); + listPersesDashboardsPage.renameDashboardEnterName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0]); + listPersesDashboardsPage.renameDashboardRenameButton(); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + + cy.log(`3.8. Clear all filters and filter by Name`); + listPersesDashboardsPage.clearAllFilters(); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`3.9. Click on dashboard and verify the name`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0]); + persesDashboardsPage.shouldBeLoaded1(); + persesDashboardsPage.shouldBeLoadedAfterRename(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0]); + persesDashboardsPage.backToListPersesDashboardsPage(); + + }); + + //TODO: Add test for Rename to an existing dashboard name to be addressed by https://issues.redhat.com/browse/OU-1220 + it(`4.${perspective.name} perspective - Kebab icon - Options available - Rename dashboard to an existing dashboard name`, () => { + cy.log(`4.1. Filter by Name and click on the Kebab icon`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0]); + + + cy.log(`4.2. Click on the Kebab icon - Rename dashboard - Rename`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickRenameDashboardOption(); + listPersesDashboardsPage.renameDashboardEnterName(persesDashboardsDashboardDropdownPersesDev.PROMETHEUS_OVERVIEW[0]); + listPersesDashboardsPage.renameDashboardRenameButton(); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + + cy.log(`4.3. Clear all filters and filter by Name`); + listPersesDashboardsPage.clearAllFilters(); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PROMETHEUS_OVERVIEW[0]); + listPersesDashboardsPage.countDashboards('2'); + + cy.log(`4.4. Sort by Last Modified - Descending`); + listPersesDashboardsPage.sortBy('Last Modified'); + listPersesDashboardsPage.sortBy('Last Modified'); + listPersesDashboardsPage.clickKebabIcon(0); + listPersesDashboardsPage.clickRenameDashboardOption(); + listPersesDashboardsPage.renameDashboardEnterName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0]); + listPersesDashboardsPage.renameDashboardRenameButton(); + cy.wait(2000); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`4.5. Clear all filters and filter by Name`); + listPersesDashboardsPage.clearAllFilters(); + listPersesDashboardsPage.filter.byProject('perses-dev'); + cy.wait(2000); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0]); + cy.wait(2000); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.clearAllFilters(); + }); +} + + export function testCOOListPersesDuplicateDashboard(perspective: PerspectiveConfig) { + + it(`5.${perspective.name} perspective - Duplicate - existing dashboard ID in the same project`, () => { + cy.log(`5.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`5.2. Filter by Name and click on the Kebab icon`); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`5.3. Click on the Kebab icon - Duplicate`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickDuplicateOption(); + listPersesDashboardsPage.assertDuplicateProjectDropdown('openshift-cluster-observability-operator'); + listPersesDashboardsPage.assertDuplicateProjectDropdown('perses-dev'); + listPersesDashboardsPage.duplicateDashboardEnterName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.duplicateDashboardDuplicateButton(); + listPersesDashboardsPage.assertDuplicateDashboardAlreadyExists(); + listPersesDashboardsPage.duplicateDashboardCancelButton(); + listPersesDashboardsPage.clearAllFilters(); + + }); + + it(`6.${perspective.name} perspective - Duplicate - existing dashboard name in the same project`, () => { + cy.log(`6.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`6.2. Filter by Name and click on the Kebab icon`); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`6.3. Click on the Kebab icon - Duplicate`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickDuplicateOption(); + listPersesDashboardsPage.duplicateDashboardEnterName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.duplicateDashboardDuplicateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + persesDashboardsPage.shouldBeLoadedAfterDuplicate(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + + cy.log(`6.4. Back to the list and duplicate to another project`); + persesDashboardsPage.backToListPersesDashboardsPage(); + + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('2'); + + cy.log(`6.5. Sort by Last Modified - Descending`); + listPersesDashboardsPage.sortBy('Last Modified'); + + cy.log(`6.6. Click on the Kebab icon - Duplicate with the same Dashboard name`); + listPersesDashboardsPage.clickKebabIcon(0); + listPersesDashboardsPage.clickDuplicateOption(); + listPersesDashboardsPage.duplicateDashboardEnterName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.duplicateDashboardDuplicateButton(); + listPersesDashboardsPage.assertDuplicateDashboardAlreadyExists(); + listPersesDashboardsPage.duplicateDashboardCancelButton(); + listPersesDashboardsPage.clearAllFilters(); + + }); + + it(`7.${perspective.name} perspective - Duplicate - existing dashboard ID in another project`, () => { + cy.log(`7.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`7.2. Filter by Name and click on the Kebab icon`); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('2'); + + cy.log(`7.3. Click on the Kebab icon - Duplicate`); + listPersesDashboardsPage.clickKebabIcon(0); + listPersesDashboardsPage.clickDuplicateOption(); + listPersesDashboardsPage.duplicateDashboardEnterName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.duplicateDashboardSelectProjectDropdown('openshift-cluster-observability-operator'); + listPersesDashboardsPage.duplicateDashboardDuplicateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + persesDashboardsPage.shouldBeLoadedAfterDuplicate(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + persesDashboardsPage.backToListPersesDashboardsPage(); + + }); + + it(`8.${perspective.name} perspective - Delete and Cancel and then Delete`, () => { + cy.log(`8.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`8.2. Filter by Name and click on the Kebab icon`); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('2'); + listPersesDashboardsPage.sortBy('Last Modified'); + listPersesDashboardsPage.sortBy('Last Modified'); + + cy.log(`8.4. Click on the Kebab icon - Delete`); + listPersesDashboardsPage.clickKebabIcon(0); + listPersesDashboardsPage.clickDeleteOption(); + listPersesDashboardsPage.deleteDashboardCancelButton(); + listPersesDashboardsPage.countDashboards('2'); + + cy.log(`8.5. Click on the Kebab icon - Delete`); + listPersesDashboardsPage.clickKebabIcon(0); + listPersesDashboardsPage.clickDeleteOption(); + listPersesDashboardsPage.deleteDashboardDeleteButton(); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`8.6. Filter by Name and click on the Kebab icon`); + listPersesDashboardsPage.filter.byProject('openshift-cluster-observability-operator'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`8.7. Click on the Kebab icon - Delete`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickDeleteOption(); + listPersesDashboardsPage.deleteDashboardDeleteButton(); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + listPersesDashboardsPage.clearAllFilters(); + + }); + } + + //TODO: Verify Duplicate Dashboard - Select project dropdown not only showing perses projects, but all namespaces you have access to, independently of having perses object (that creates a perses project) + // it(`9.${perspective.name} perspective - Verify Duplicate Dashboard - Select project dropdown not only showing perses projects, but all namespaces you have access to, independently of having perses object (that creates a perses project)`, () => { + // cy.log(`9.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + // commonPages.titleShouldHaveText('Dashboards'); + // listPersesDashboardsPage.shouldBeLoaded(); + + // cy.log(`9.2. Click on the Kebab icon - Duplicate`); + // listPersesDashboardsPage.clickKebabIcon(); + // listPersesDashboardsPage.clickDuplicateDashboardOption(); + // listPersesDashboardsPage.assertProjectDropdown('openshift-cluster-observability-operator'); + // openshift-monitoringas an example of a namespace that you have access to and does not have any perses object created yet, but you are able to create a dashboard + // listPersesDashboardsPage.assertProjectDropdown('openshift-monitoring'); + // }); + + //TODO: Delete namespace and check project dropdown does not load this namespace + // it(`10.${perspective.name} perspective - Delete namespace and check project dropdown does not load this namespace`, () => { + // OU-1192 - [Perses operator] - Delete namespace is not deleting perses project + // + // }); \ No newline at end of file diff --git a/web/cypress/support/perses/01.coo_list_perses_admin_namespace.cy.ts b/web/cypress/support/perses/01.coo_list_perses_admin_namespace.cy.ts new file mode 100644 index 000000000..43615d41c --- /dev/null +++ b/web/cypress/support/perses/01.coo_list_perses_admin_namespace.cy.ts @@ -0,0 +1,133 @@ +import { persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev } from '../../fixtures/perses/constants'; +import { commonPages } from '../../views/common'; +import { listPersesDashboardsPage } from "../../views/perses-dashboards-list-dashboards"; +import { persesDashboardsPage } from '../../views/perses-dashboards'; + +export interface PerspectiveConfig { + name: string; + beforeEach?: () => void; +} + +export function runCOOListPersesTestsNamespace(perspective: PerspectiveConfig) { + testCOOListPersesNamespace(perspective); +} + +export function testCOOListPersesNamespace(perspective: PerspectiveConfig) { + + it(`1.${perspective.name} perspective - List Dashboards (Perses) page`, () => { + cy.log(`1.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`1.2. Change namespace to perses-dev`); + cy.changeNamespace('perses-dev'); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.countDashboards('3'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PROMETHEUS_OVERVIEW[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`1.3. Clear all filters`); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`1.4. Sort by Dashboard - Ascending`); + listPersesDashboardsPage.sortBy('Dashboard'); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0], 0); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.PROMETHEUS_OVERVIEW[0], 1); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0], 2); + + cy.log(`1.5. Sort by Dashboard - Descending`); + listPersesDashboardsPage.sortBy('Dashboard'); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.THANOS_COMPACT_OVERVIEW[0], 0); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.PROMETHEUS_OVERVIEW[0], 1); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0], 2); + + + cy.log(`1.6. Change namespace to openshift-cluster-observability-operator`); + cy.changeNamespace('openshift-cluster-observability-operator'); + listPersesDashboardsPage.countDashboards('3'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`1.7. Clear all filters`); + listPersesDashboardsPage.clearAllFilters(); + + + cy.log(`1.8. Sort by Dashboard - Ascending`); + listPersesDashboardsPage.sortBy('Dashboard'); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0], 0); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownCOO.APM_DASHBOARD[0], 1); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0], 2); + + cy.log(`1.9. Sort by Dashboard - Descending`); + listPersesDashboardsPage.sortBy('Dashboard'); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0], 0); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownCOO.APM_DASHBOARD[0], 1); + listPersesDashboardsPage.assertDashboardName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0], 2); + + cy.log(`1.10. Filter by Name - Empty state`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PROMETHEUS_OVERVIEW[0]); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + + cy.log(`1.11. Clear all filters`); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`1.12. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.APM_DASHBOARD[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + persesDashboardsPage.shouldBeLoaded1(); + }); + + it(`2.${perspective.name} perspective - Duplicate from a project to another, Rename and Delete`, () => { + cy.log(`2.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`2.2. Change namespace to perses-dev`); + cy.changeNamespace('perses-dev'); + listPersesDashboardsPage.countDashboards('3'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`2.3. Click on the Kebab icon - Duplicate to another project`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickDuplicateOption(); + listPersesDashboardsPage.duplicateDashboardEnterName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.duplicateDashboardSelectProjectDropdown('openshift-cluster-observability-operator'); + listPersesDashboardsPage.duplicateDashboardDuplicateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + persesDashboardsPage.shouldBeLoadedAfterDuplicate(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + persesDashboardsPage.backToListPersesDashboardsPage(); + + cy.log(`2.4. Click on the Kebab icon - Rename`); + cy.changeNamespace('openshift-cluster-observability-operator'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickRenameDashboardOption(); + listPersesDashboardsPage.renameDashboardEnterName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0] + ' - Renamed'); + listPersesDashboardsPage.renameDashboardRenameButton(); + + cy.log(`2.5. Click on the Kebab icon - Delete`); + listPersesDashboardsPage.clearAllFilters(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0] + ' - Renamed'); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`2.6. Click on the Kebab icon - Delete`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickDeleteOption(); + listPersesDashboardsPage.deleteDashboardDeleteButton(); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + + cy.log(`2.7. Search for the renamed dashboard`); + listPersesDashboardsPage.clearAllFilters(); + cy.changeNamespace('All Projects'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0] + ' - Renamed'); + listPersesDashboardsPage.countDashboards('0'); + listPersesDashboardsPage.clearAllFilters(); + + }); + + +} \ No newline at end of file diff --git a/web/cypress/support/perses/02.coo_edit_perses_admin.cy.ts b/web/cypress/support/perses/02.coo_edit_perses_admin.cy.ts new file mode 100644 index 000000000..56cc6c09c --- /dev/null +++ b/web/cypress/support/perses/02.coo_edit_perses_admin.cy.ts @@ -0,0 +1,518 @@ +import { editPersesDashboardsAddVariable, persesMUIDataTestIDs, IDs, editPersesDashboardsAddDatasource } from '../../../src/components/data-test'; +import { persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev } from '../../fixtures/perses/constants'; +import { commonPages } from '../../views/common'; +import { listPersesDashboardsPage } from "../../views/perses-dashboards-list-dashboards"; +import { persesDashboardsPage } from '../../views/perses-dashboards'; +import { persesDashboardsPanelGroup } from '../../views/perses-dashboards-panelgroup'; +import { persesDashboardsEditDatasources } from '../../views/perses-dashboards-edit-datasources'; +import { persesDashboardsEditVariables } from '../../views/perses-dashboards-edit-variables'; + +export interface PerspectiveConfig { + name: string; + beforeEach?: () => void; +} + +export function runCOOEditPersesTests(perspective: PerspectiveConfig) { + testCOOEditPerses(perspective); +} + +export function testCOOEditPerses(perspective: PerspectiveConfig) { + + it(`1.${perspective.name} perspective - Edit perses dashboard page`, () => { + cy.log(`1.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`1.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`1.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`1.4. Click on Edit button`); + cy.wait(15000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.assertEditModeButtons(); + persesDashboardsPage.assertEditModePanelGroupButtons('Headlines'); + //already expanded + persesDashboardsPage.assertPanelActionButtons('CPU Usage'); + // tiny panel and modal is opened. So, expand first and then assert the buttons and finally collapse + // due to modal is opened and page is refreshed, it is not easy to assert buttons in the modal + persesDashboardsPage.assertPanelActionButtons('CPU Utilisation'); + + cy.log(`1.5. Click on Cancel button`); + persesDashboardsPage.clickEditActionButton('Cancel'); + + cy.log(`1.6. Change namespace to All Projects`); + cy.changeNamespace('All Projects'); + listPersesDashboardsPage.shouldBeLoaded(); + + }); + + it(`2.${perspective.name} perspective - Edit Toolbar - Edit Variables - Add List Variable`, () => { + cy.log(`2.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`2.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`2.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`2.4. Click on Edit button`); + cy.wait(10000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickButton('Add Variable'); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working + persesDashboardsEditVariables.addListVariable('ListVariable', true, true, 'AAA', 'Test', 'Test', undefined, undefined); + + cy.log(`2.5. Run query`); + persesDashboardsEditVariables.clickButton('Run Query'); + cy.get('h4').should('contain', 'Preview Values').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardAddVariablePreviewValuesCopy).should('be.visible'); + + cy.log(`2.6. Add variable`); + persesDashboardsEditVariables.clickButton('Add'); + + cy.log(`2.7. Apply changes`); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`2.8. Save dashboard`); + persesDashboardsPage.clickEditActionButton('Save'); + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working, so selecting "All" for now + persesDashboardsPage.searchAndSelectVariable('ListVariable', 'All'); + //TODO: END testing more to check if it is time constraint or cache issue + + }); + + it(`3.${perspective.name} perspective - Edit Toolbar - Edit Variables - Add Text Variable`, () => { + cy.log(`3.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`3.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`3.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`3.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditVariables'); + + cy.log(`3.5. Click on Dashboard Built-in Variables button`); + cy.get('#'+IDs.persesDashboardEditVariablesModalBuiltinButton).should('have.attr', 'aria-expanded', 'false').click(); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('#'+IDs.persesDashboardEditVariablesModalBuiltinButton).should('have.attr', 'aria-expanded', 'true') + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('#'+IDs.persesDashboardEditVariablesModalBuiltinButton).click(); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('#'+IDs.persesDashboardEditVariablesModalBuiltinButton).should('have.attr', 'aria-expanded', 'false'); + + cy.log(`3.6. Add variable`); + persesDashboardsEditVariables.clickButton('Add Variable'); + persesDashboardsEditVariables.addTextVariable('TextVariable', true, 'Test', 'Test', 'Test'); + persesDashboardsEditVariables.clickButton('Add'); + + cy.log(`3.7. Apply changes`); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`3.8. Save dashboard`); + persesDashboardsPage.clickEditActionButton('Save'); + + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + + cy.log(`3.9. Search and type variable`); + persesDashboardsPage.searchAndTypeVariable('TextVariable', ''); + + }); + + it(`4.${perspective.name} perspective - Edit Toolbar - Edit Variables - Visibility, Move up/down, Edit and Delete Variable`, () => { + cy.log(`4.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`4.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`4.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`4.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + + cy.log(`4.5. Click on Edit Variables button`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + + cy.log(`4.6. Toggle variable visibility`); + persesDashboardsEditVariables.toggleVariableVisibility(0, false); + + cy.log(`4.7. Move variable up`); + persesDashboardsEditVariables.moveVariableUp(1); + + cy.log(`4.8. Click on Edit variable button`); + persesDashboardsEditVariables.clickEditVariableButton(0); + + cy.log(`4.9. Edit list variable`); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working + persesDashboardsEditVariables.addListVariable('ListVariable123', false, false, '123', 'Test123', 'Test123', undefined, undefined); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`4.10. Delete variable`); + persesDashboardsEditVariables.clickDeleteVariableButton(2); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`4.11. Save dashboard`); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`4.12. Search and select variable`); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working, so selecting "All" for now + persesDashboardsPage.searchAndSelectVariable('ListVariable123', 'All'); + + cy.log(`4.13. Assert variable not be visible`); + persesDashboardsPage.assertVariableNotBeVisible('cluster'); + + cy.log(`4.14. Assert variable not exist`); + persesDashboardsPage.assertVariableNotExist('TextVariable'); + + cy.log(`4.15. Recover dashboard`); + persesDashboardsPage.clickEditButton(); + + cy.log(`4.16. Click on Edit Variables button`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + + cy.log(`4.16. Toggle variable visibility`); + persesDashboardsEditVariables.toggleVariableVisibility(1, true); + + cy.log(`4.17. Delete variable`); + persesDashboardsEditVariables.clickDeleteVariableButton(0); + + cy.log(`4.17. Apply changes`); + persesDashboardsEditVariables.clickButton('Apply'); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`4.18. Assert variable be visible`); + persesDashboardsPage.assertVariableBeVisible('cluster'); + + cy.log(`4.19. Assert variable not exist`); + persesDashboardsPage.assertVariableNotExist('TextVariable'); + + }); + + it(`5.${perspective.name} perspective - Edit Toolbar - Edit Variables - Add Variable - Required field validation`, () => { + cy.log(`5.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`5.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`5.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`5.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditVariables'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('button').contains('Add Variable').should('be.visible').click(); + cy.get('input[name="'+editPersesDashboardsAddVariable.inputName+'"]').clear(); + persesDashboardsEditVariables.clickButton('Add'); + persesDashboardsEditVariables.assertRequiredFieldValidation('Name'); + persesDashboardsEditVariables.clickButton('Cancel'); + persesDashboardsEditVariables.clickButton('Cancel'); + }); + + /**TODO: https://issues.redhat.com/browse/OU-1054 is targeted for COO1.5.0, so, commenting all Datasources related scenarios + it(`6.${perspective.name} perspective - Edit Toolbar - Edit Datasources - Add and Delete Prometheus Datasource`, () => { + cy.log(`6.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`6.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`6.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`6.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditDatasources'); + + cy.log(`6.5. Verify existing datasources`); + persesDashboardsEditDatasources.assertDatasource(0, 'PrometheusLocal', 'PrometheusDatasource', ''); + + cy.log(`6.6. Add datasource`); + persesDashboardsEditDatasources.clickButton('Add Datasource'); + persesDashboardsEditDatasources.addDatasource('Datasource1', true, 'Prometheus Datasource', 'Datasource1', 'Datasource1'); + persesDashboardsEditDatasources.clickButton('Add'); + persesDashboardsEditDatasources.assertDatasource(1, 'Datasource1', 'PrometheusDatasource', 'Datasource1'); + + cy.log(`6.7. Add second datasource`); + persesDashboardsEditDatasources.clickButton('Add Datasource'); + persesDashboardsEditDatasources.addDatasource('Datasource2', true, 'Prometheus Datasource', 'Datasource2', 'Datasource2'); + persesDashboardsEditDatasources.clickButton('Add'); + persesDashboardsEditDatasources.assertDatasource(2, 'Datasource2', 'PrometheusDatasource', 'Datasource2'); + + cy.log(`6.8. Delete first datasource`); + persesDashboardsEditDatasources.clickDeleteDatasourceButton(1); + persesDashboardsEditDatasources.assertDatasourceNotExist('Datasource1'); + + persesDashboardsEditDatasources.clickButton('Apply'); + //https://issues.redhat.com/browse/OU-1160 - Datasource is not saved + // persesDashboardsPage.clickEditActionButton('Save'); + }); + + it(`7.${perspective.name} perspective - Edit Toolbar - Edit Datasources - Edit Prometheus Datasource`, () => { + cy.log(`7.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`7.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`7.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`7.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditDatasources'); + + cy.log(`7.5. Verify existing datasources`); + persesDashboardsEditDatasources.assertDatasource(0,'PrometheusLocal', 'PrometheusDatasource', ''); + + cy.log(`7.6. Edit datasource`); + persesDashboardsEditDatasources.clickEditDatasourceButton(0); + persesDashboardsEditDatasources.addDatasource('PrometheusLocal', false, 'Prometheus Datasource', 'Datasource1', 'Datasource1'); + persesDashboardsEditDatasources.clickButton('Apply'); + persesDashboardsEditDatasources.assertDatasource(0,'PrometheusLocal', 'PrometheusDatasource', 'Datasource1'); + persesDashboardsEditDatasources.clickButton('Cancel'); + persesDashboardsPage.clickEditActionButton('Cancel'); + + }); + + // it(`8.${perspective.name} perspective - Edit Toolbar - Edit Datasources - Add Tempo Datasource`, () => { + // }); + + it(`8.${perspective.name} perspective - Edit Toolbar - Edit Datasources - Required field validation`, () => { + cy.log(`8.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`8.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`8.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`8.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditDatasources'); + + cy.log(`8.5. Add datasource`); + persesDashboardsEditDatasources.clickButton('Add Datasource'); + + cy.log(`8.6. Clear out Name field`); + cy.get('input[name="'+editPersesDashboardsAddDatasource.inputName+'"]').clear(); + persesDashboardsEditDatasources.clickButton('Add'); + + cy.log(`8.7. Assert required field validation`); + persesDashboardsEditDatasources.assertRequiredFieldValidation('Name'); + persesDashboardsEditDatasources.clickButton('Cancel'); + + cy.log(`8.8. Cancel changes`); + persesDashboardsEditDatasources.clickButton('Cancel'); + persesDashboardsPage.clickEditActionButton('Cancel'); + + }); +*/ + + it(`6.${perspective.name} perspective - Edit Toolbar - Add Panel Group`, () => { + cy.log(`6.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`6.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`6.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`6.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('AddGroup'); + + cy.log(`6.5. Add panel group`); + persesDashboardsPanelGroup.addPanelGroup('PanelGroup1', 'Open', ''); + + cy.log(`6.6. Save panel group`); + persesDashboardsPage.clickEditActionButton('Save'); + persesDashboardsPage.panelGroupHeaderAssertion('PanelGroup1', 'Open'); + + cy.log(`6.7. Back and check panel group`); + //TODO: START testing more to check if it is time constraint or cache issue + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + persesDashboardsPage.panelGroupHeaderAssertion('PanelGroup1', 'Open'); + + }); + + it(`7.${perspective.name} perspective - Edit Toolbar - Edit Panel Group`, () => { + cy.log(`7.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`7.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`7.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`7.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup1', 'edit'); + //TODO: https://issues.redhat.com/browse/OU-1223 - Upstream ref: [Edit Dashboard] - Edit Panel Group from closed/opened vice-versa is not shown right away + persesDashboardsPanelGroup.editPanelGroup('PanelGroup2', 'Closed', ''); + persesDashboardsPage.clickEditActionButton('Save'); + //persesDashboardsPage.panelGroupHeaderAssertion('PanelGroup2', 'Closed'); //TODO: uncomment when https://issues.redhat.com/browse/OU-1223 is fixed + + cy.log(`7.5. Back and check panel group`); + //TODO: START testing more to check if it is time constraint or cache issue + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + persesDashboardsPage.panelGroupHeaderAssertion('PanelGroup2', 'Closed'); + + }); + + it(`8.${perspective.name} perspective - Edit Toolbar - Move Panel Group Down and Up`, () => { + cy.log(`8.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`8.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`8.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`8.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup2', 'moveDown'); + + cy.log(`8.5. Save panel group`); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`8.6. Assert panel group order`); + persesDashboardsPage.assertPanelGroupOrder('Row 1', 0); + persesDashboardsPage.assertPanelGroupOrder('PanelGroup2', 1); + persesDashboardsPage.assertPanelGroupOrder('Row 2', 2); + + cy.log(`8.7. Back and check panel group order`); + //TODO: START testing more to check if it is time constraint or cache issue + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + persesDashboardsPage.assertPanelGroupOrder('Row 1', 0); + persesDashboardsPage.assertPanelGroupOrder('PanelGroup2', 1); + persesDashboardsPage.assertPanelGroupOrder('Row 2', 2); + + cy.log(`8.8. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + + cy.log(`8.9. Move panel group up`); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup2', 'moveUp'); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`8.10. Assert panel group order`); + persesDashboardsPage.assertPanelGroupOrder('PanelGroup2', 0); + persesDashboardsPage.assertPanelGroupOrder('Row 1', 1); + persesDashboardsPage.assertPanelGroupOrder('Row 2', 2); + + cy.log(`8.11. Back and check panel group order`); + //TODO: START testing more to check if it is time constraint or cache issue + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + persesDashboardsPage.assertPanelGroupOrder('PanelGroup2', 0); + persesDashboardsPage.assertPanelGroupOrder('Row 1', 1); + persesDashboardsPage.assertPanelGroupOrder('Row 2', 2); + }); + + it(`9.${perspective.name} perspective - Edit Toolbar - Delete Panel Group`, () => { + cy.log(`9.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`9.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`9.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`9.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup2', 'delete'); + persesDashboardsPanelGroup.clickDeletePanelGroupButton(); + persesDashboardsPage.clickEditActionButton('Save'); + persesDashboardsPage.assertPanelGroupNotExist('PanelGroup2'); + + cy.log(`9.5. Back and check panel group`); + //TODO: START testing more to check if it is time constraint or cache issue + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + persesDashboardsPage.assertPanelGroupNotExist('PanelGroup2'); + }); + +} \ No newline at end of file diff --git a/web/cypress/support/perses/02.coo_edit_perses_admin_1.cy.ts b/web/cypress/support/perses/02.coo_edit_perses_admin_1.cy.ts new file mode 100644 index 000000000..f5deb7522 --- /dev/null +++ b/web/cypress/support/perses/02.coo_edit_perses_admin_1.cy.ts @@ -0,0 +1,281 @@ +import { IDs, editPersesDashboardsAddPanel } from '../../../src/components/data-test'; +import { persesDashboardsAddListPanelType, persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev } from '../../fixtures/perses/constants'; +import { commonPages } from '../../views/common'; +import { listPersesDashboardsPage } from "../../views/perses-dashboards-list-dashboards"; +import { persesDashboardsPage } from '../../views/perses-dashboards'; +import { persesDashboardsEditDatasources } from '../../views/perses-dashboards-edit-datasources'; +import { persesDashboardsEditVariables } from '../../views/perses-dashboards-edit-variables'; +import { persesDashboardsPanel } from '../../views/perses-dashboards-panel'; +import { persesDashboardsPanelGroup } from '../../views/perses-dashboards-panelgroup'; + +export interface PerspectiveConfig { + name: string; + beforeEach?: () => void; +} + +export function runCOOEditPersesTests1(perspective: PerspectiveConfig) { + testCOOEditPerses1(perspective); +} + +export function testCOOEditPerses1(perspective: PerspectiveConfig) { + + it(`10.${perspective.name} perspective - Edit Toolbar - Add Panel`, () => { + cy.log(`10.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`10.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`10.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + + const panelTypeKeys = Object.keys(persesDashboardsAddListPanelType) as (keyof typeof persesDashboardsAddListPanelType)[]; + panelTypeKeys.forEach((typeKey) => { + const panelName = persesDashboardsAddListPanelType[typeKey]; // e.g., 'Bar Chart' + + cy.log(`10.4. Click on Edit button`); + persesDashboardsPage.clickEditButton(); + + cy.log(`10.5. Click on Add Group - PanelGroup ` + panelName); + persesDashboardsPage.clickEditActionButton('AddGroup'); + persesDashboardsPanelGroup.addPanelGroup('PanelGroup ' + panelName, 'Open', ''); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`10.6. Click on Edit button`); + persesDashboardsPage.clickEditButton(); + + cy.log(`10.7. Click on Add Panel button` + panelName); + persesDashboardsPage.clickEditActionButton('AddPanel'); + persesDashboardsPanel.addPanelShouldBeLoaded(); + persesDashboardsPanel.addPanel(panelName, 'PanelGroup ' + panelName, panelName); + persesDashboardsPage.assertPanel(panelName, 'PanelGroup ' + panelName, 'Open'); + persesDashboardsPage.clickEditActionButton('Save'); + }); + }); + + it(`11.${perspective.name} perspective - Edit Toolbar - Edit Panel`, () => { + cy.log(`11.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`11.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`11.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + + cy.log(`11.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + + const panelTypeKeys = Object.keys(persesDashboardsAddListPanelType) as (keyof typeof persesDashboardsAddListPanelType)[]; + const lastKey = panelTypeKeys[panelTypeKeys.length - 1]; // Get the last KEY from the array + const lastPanelName = persesDashboardsAddListPanelType[lastKey]; // Use the KEY to get the VALUE + + cy.log(`11.5. Click on Edit Panel button` + lastPanelName + ' to Panel1'); + persesDashboardsPage.clickPanelAction(lastPanelName, 'edit'); + persesDashboardsPanel.editPanel('Panel1', 'PanelGroup ' + lastPanelName, persesDashboardsAddListPanelType.BAR_CHART, 'Description1'); + persesDashboardsPage.assertPanel('Panel1', 'PanelGroup ' + lastPanelName, 'Open'); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`11.6. Click on Edit Panel button from Panel 1 to` + lastPanelName); + persesDashboardsPage.clickEditButton(); + + persesDashboardsPage.clickPanelAction('Panel1', 'edit'); + persesDashboardsPanel.editPanel(lastPanelName, 'PanelGroup ' + lastPanelName, lastPanelName, 'Description1'); + persesDashboardsPage.assertPanel(lastPanelName, 'PanelGroup ' + lastPanelName, 'Open'); + persesDashboardsPage.clickEditActionButton('Save'); + + }); + + it(`12.${perspective.name} perspective - Edit Toolbar - Delete Panel`, () => { + cy.log(`12.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`12.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`12.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + + const panelTypeKeys = Object.keys(persesDashboardsAddListPanelType) as (keyof typeof persesDashboardsAddListPanelType)[]; + + panelTypeKeys.reverse().forEach((typeKey) => { + const panelName = persesDashboardsAddListPanelType[typeKey]; // e.g., 'Bar Chart' + cy.log(`12.4. Delete Panel` + panelName); + persesDashboardsPage.clickEditButton(); + persesDashboardsPanel.deletePanel(panelName); + persesDashboardsPanel.clickDeletePanelButton(); + + cy.log(`12.5. Delete Panel Group` + panelName); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup ' + panelName, 'delete'); + persesDashboardsPanelGroup.clickDeletePanelGroupButton(); + persesDashboardsPage.clickEditActionButton('Save'); + }); + }); + + it(`13.${perspective.name} perspective - Edit Toolbar - Duplicate Panel`, () => { + cy.log(`13.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`13.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`13.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + + cy.log(`13.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + + cy.log(`13.5. Collapse Row 1 Panel Group`); + persesDashboardsPage.collapsePanelGroup('Row 1'); + + cy.log(`13.6. Click on Duplicate Panel button`); + persesDashboardsPage.clickPanelAction('Legend Example', 'duplicate'); + + cy.log(`13.7. Assert duplicated panel`); + persesDashboardsPage.assertDuplicatedPanel('Legend Example', 2); + + }); + + it(`14.${perspective.name} perspective - Edit Toolbar - Perform changes and Cancel`, () => { + cy.log(`14.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`14.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`14.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`14.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickButton('Add Variable'); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working + persesDashboardsEditVariables.addListVariable('ListVariable', true, true, 'AAA', 'Test', 'Test', undefined, undefined); + + cy.log(`14.5. Add variable`); + persesDashboardsEditVariables.clickButton('Add'); + + cy.log(`14.6. Apply changes`); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`14.7. Assert Variable before cancelling`); + persesDashboardsPage.searchAndSelectVariable('ListVariable', 'All'); + + cy.log(`14.8. Click on Add Panel Group button`); + persesDashboardsPage.clickEditActionButton('AddGroup'); + persesDashboardsPanelGroup.addPanelGroup('PanelGroup Perform Changes and Cancel', 'Open', ''); + + cy.log(`14.9. Click on Add Panel button`); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup Perform Changes and Cancel', 'addPanel'); + persesDashboardsPanel.addPanel('Panel Perform Changes and Cancel', 'PanelGroup Perform Changes and Cancel', 'Bar Chart'); + + cy.log(`14.10. Click on Cancel button`); + persesDashboardsPage.clickEditActionButton('Cancel'); + + cy.log(`14.11. Assert variable not exist`); + persesDashboardsPage.assertVariableNotExist('ListVariable'); + + cy.log(`14.12. Assert panel group not exist`); + persesDashboardsPage.assertPanelGroupNotExist('PanelGroup Perform Changes and Cancel'); + + cy.log(`14.13. Assert panel not exist`); + persesDashboardsPage.assertPanelNotExist('Panel Perform Changes and Cancel'); + + }); + + /** + * OU-886 Mark dashboards and datasources created using CRD as readonly + * + * Admin user and dev users with persesdashboard-editor-role will be able to edit dashboards using CRD. + * + */ + it(`15.${perspective.name} perspective - Try to editAccelerators and APM dashboards`, () => { + cy.log(`15.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`15.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`15.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`15.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickButton('Add Variable'); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working + persesDashboardsEditVariables.addListVariable('ListVariable', true, true, 'AAA', 'Test', 'Test', undefined, undefined); + + cy.log(`15.5. Add variable`); + persesDashboardsEditVariables.clickButton('Add'); + + cy.log(`15.6. Apply changes`); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`15.7. Assert Variable before saving`); + persesDashboardsPage.searchAndSelectVariable('ListVariable', 'All'); + + cy.log(`15.8. Click on Add Panel Group button`); + persesDashboardsPage.clickEditActionButton('AddGroup'); + persesDashboardsPanelGroup.addPanelGroup('PanelGroup Perform Changes and Save', 'Open', ''); + + cy.log(`15.9. Click on Add Panel button`); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup Perform Changes and Save', 'addPanel'); + persesDashboardsPanel.addPanel('Panel Perform Changes and Save', 'PanelGroup Perform Changes and Save', 'Bar Chart'); + + cy.log(`15.10. Click on Save button`); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`15.11. Back and check panel group`); + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + + cy.log(`15.12. Assert Variable before deleting`); + persesDashboardsPage.searchAndSelectVariable('ListVariable', 'All'); + + cy.log(`15.13. Assert panel group exists`); + persesDashboardsPage.panelGroupHeaderAssertion('PanelGroup Perform Changes and Save', 'Open'); + + cy.log(`15.14. Assert panel exists`); + persesDashboardsPage.assertPanel('Panel Perform Changes and Save', 'PanelGroup Perform Changes and Save', 'Open'); + + cy.log(`15.15. Click on Edit button`); + persesDashboardsPage.clickEditButton(); + + cy.log(`15.16. Delete variable`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickDeleteVariableButton(1); + persesDashboardsEditVariables.clickButton('Apply'); + persesDashboardsPage.assertVariableNotExist('ListVariable'); + + cy.log(`15.17. Delete panel group`); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup Perform Changes and Save', 'delete'); + persesDashboardsPanelGroup.clickDeletePanelGroupButton(); + persesDashboardsPage.clickEditActionButton('Save'); + persesDashboardsPage.assertPanelGroupNotExist('PanelGroup Perform Changes and Save'); + + }); + +} \ No newline at end of file diff --git a/web/cypress/support/perses/03.coo_create_perses_admin.cy.ts b/web/cypress/support/perses/03.coo_create_perses_admin.cy.ts new file mode 100644 index 000000000..9108db85e --- /dev/null +++ b/web/cypress/support/perses/03.coo_create_perses_admin.cy.ts @@ -0,0 +1,209 @@ +import { listPersesDashboardsPage } from "../../views/perses-dashboards-list-dashboards"; +import { persesDashboardsPage } from '../../views/perses-dashboards'; +import { persesDashboardsAddListPanelType, persesDashboardSampleQueries, persesDashboardsEmptyDashboard } from '../../fixtures/perses/constants'; +import { persesCreateDashboardsPage } from '../../views/perses-dashboards-create-dashboard'; +import { persesDashboardsPanelGroup } from "../../views/perses-dashboards-panelgroup"; +import { persesDashboardsPanel } from "../../views/perses-dashboards-panel"; +import { persesDashboardsEditVariables } from "../../views/perses-dashboards-edit-variables"; +import { persesDashboardsAddListVariableSource } from "../../fixtures/perses/constants"; + +export interface PerspectiveConfig { + name: string; + beforeEach?: () => void; +} + +export function runCOOCreatePersesTests(perspective: PerspectiveConfig) { + testCOOCreatePerses(perspective); +} + +export function testCOOCreatePerses(perspective: PerspectiveConfig) { + + it(`1.${perspective.name} perspective - Create Dashboard validation with max length`, () => { + let dashboardName = 'Test Dashboard'; + let randomSuffix = Math.random().toString(5); + dashboardName += randomSuffix; + cy.log(`1.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`1.2. Click on Create button`); + listPersesDashboardsPage.clickCreateButton(); + persesCreateDashboardsPage.createDashboardShouldBeLoaded(); + + cy.log(`1.3. Verify Project dropdown`); + persesCreateDashboardsPage.assertProjectDropdown('openshift-cluster-observability-operator'); + persesCreateDashboardsPage.assertProjectDropdown('observ-test'); + persesCreateDashboardsPage.assertProjectDropdown('perses-dev'); + + cy.log(`1.4. Verify Max Length Validation`); + persesCreateDashboardsPage.selectProject('openshift-cluster-observability-operator'); + persesCreateDashboardsPage.enterDashboardName('1234567890123456789012345678901234567890123456789012345678901234567890123456'); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesCreateDashboardsPage.assertMaxLengthValidation(); + + cy.log(`1.5. Verify Name input`); + persesCreateDashboardsPage.enterDashboardName(dashboardName); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(dashboardName); + persesDashboardsPage.shouldBeLoadedEditionModeFromCreateDashboard(); + + }); + + it(`2.${perspective.name} perspective - Create Dashboard with duplicated name in the same project`, () => { + //dashboard name with spaces + let dashboardName = 'Dashboard to test duplication'; + let randomSuffix = Math.random().toString(5); + dashboardName += randomSuffix; + cy.log(`2.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`2.2. Click on Create button`); + listPersesDashboardsPage.clickCreateButton(); + + cy.log(`2.3. Verify Project dropdown`); + persesCreateDashboardsPage.selectProject('openshift-cluster-observability-operator'); + persesCreateDashboardsPage.enterDashboardName(dashboardName); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(dashboardName); + persesDashboardsPage.shouldBeLoadedEditionModeFromCreateDashboard(); + + cy.log(`2.4. Create another dashboard with the same name`); + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.clickCreateButton(); + persesCreateDashboardsPage.selectProject('openshift-cluster-observability-operator'); + persesCreateDashboardsPage.enterDashboardName(dashboardName); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesCreateDashboardsPage.assertDuplicatedNameValidation(dashboardName); + + //dashboard name without spaces + cy.log(`2.5. Create another dashboard with the same name without spaces`); + dashboardName = 'DashboardToTestDuplication'; + dashboardName += randomSuffix; + persesCreateDashboardsPage.enterDashboardName(dashboardName); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(dashboardName); + persesDashboardsPage.shouldBeLoadedEditionModeFromCreateDashboard(); + + cy.log(`2.6. Create another dashboard with the same name without spaces`); + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.clickCreateButton(); + persesCreateDashboardsPage.selectProject('openshift-cluster-observability-operator'); + persesCreateDashboardsPage.enterDashboardName(dashboardName); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesCreateDashboardsPage.assertDuplicatedNameValidation(dashboardName); + + cy.log(`2.7. Create another dashboard with the same name in other project`); + persesCreateDashboardsPage.selectProject('perses-dev'); + persesCreateDashboardsPage.enterDashboardName(dashboardName); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(dashboardName); + persesDashboardsPage.shouldBeLoadedEditionModeFromCreateDashboard(); + + }); + + it(`3.${perspective.name} perspective - Create Dashboard with panel groups, panels and variables`, () => { + let dashboardName = 'Testing Dashboard - UP '; + let randomSuffix = Math.random().toString(5); + dashboardName += randomSuffix; + cy.log(`3.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`3.2. Click on Create button`); + listPersesDashboardsPage.clickCreateButton(); + persesCreateDashboardsPage.createDashboardShouldBeLoaded(); + + cy.log(`3.3. Create Dashboard`); + persesCreateDashboardsPage.selectProject('perses-dev'); + persesCreateDashboardsPage.enterDashboardName(dashboardName); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(dashboardName); + persesDashboardsPage.shouldBeLoadedEditionModeFromCreateDashboard(); + + cy.log(`3.4. Add Variable`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickButton('Add Variable'); + persesDashboardsEditVariables.addListVariable('interval', false, false, '', '', '', undefined, undefined); + persesDashboardsEditVariables.addListVariable_staticListVariable_enterValue('1m'); + persesDashboardsEditVariables.addListVariable_staticListVariable_enterValue('5m'); + persesDashboardsEditVariables.clickButton('Add'); + + persesDashboardsEditVariables.clickButton('Add Variable'); + persesDashboardsEditVariables.addListVariable('job', false, false, '', '', '', persesDashboardsAddListVariableSource.PROMETHEUS_LABEL_VARIABLE, undefined); + persesDashboardsEditVariables.addListVariable_promLabelValuesVariable_enterLabelName('job'); + persesDashboardsEditVariables.clickButton('Add'); + + persesDashboardsEditVariables.clickButton('Add Variable'); + persesDashboardsEditVariables.addListVariable('instance', false, false, '', '', '', persesDashboardsAddListVariableSource.PROMETHEUS_LABEL_VARIABLE, undefined); + persesDashboardsEditVariables.addListVariable_promLabelValuesVariable_enterLabelName('instance'); + persesDashboardsEditVariables.addListVariable_promLabelValuesVariable_addSeriesSelector(persesDashboardSampleQueries.CPU_LINE_MULTI_SERIES_SERIES_SELECTOR); + persesDashboardsEditVariables.clickButton('Add'); + + persesDashboardsEditVariables.clickButton('Apply'); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`3.5. Add Panel Group`); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('AddGroup'); + persesDashboardsPanelGroup.addPanelGroup('Panel Group Up', 'Open', ''); + + cy.log(`3.6. Add Panel`); + persesDashboardsPage.clickEditActionButton('AddPanel'); + persesDashboardsPanel.addPanelShouldBeLoaded(); + persesDashboardsPanel.addPanel('Up', 'Panel Group Up', persesDashboardsAddListPanelType.TIME_SERIES_CHART, 'This is a line chart test', 'up'); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`3.7. Back and check panel`); + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(dashboardName); + listPersesDashboardsPage.clickDashboard(dashboardName); + persesDashboardsPage.panelGroupHeaderAssertion('Panel Group Up', 'Open'); + persesDashboardsPage.assertPanel('Up', 'Panel Group Up', 'Open'); + persesDashboardsPage.assertVariableBeVisible('interval'); + persesDashboardsPage.assertVariableBeVisible('job'); + persesDashboardsPage.assertVariableBeVisible('instance'); + + cy.log(`3.8. Click on Edit button`); + persesDashboardsPage.clickEditButton(); + + cy.log(`3.9. Click on Edit Variables button and Delete all variables`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickDeleteVariableButton(0); + persesDashboardsEditVariables.clickDeleteVariableButton(0); + persesDashboardsEditVariables.clickDeleteVariableButton(0); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`3.10. Assert variables not exist`); + persesDashboardsPage.assertVariableNotExist('interval'); + persesDashboardsPage.assertVariableNotExist('job'); + persesDashboardsPage.assertVariableNotExist('instance'); + + cy.log(`3.11. Delete Panel`); + persesDashboardsPanel.deletePanel('Up'); + persesDashboardsPanel.clickDeletePanelButton(); + + cy.log(`3.12. Delete Panel Group`); + persesDashboardsPanelGroup.clickPanelGroupAction('Panel Group Up', 'delete'); + persesDashboardsPanelGroup.clickDeletePanelGroupButton(); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.get('h2').contains(persesDashboardsEmptyDashboard.TITLE).scrollIntoView().should('be.visible'); + cy.get('p').contains(persesDashboardsEmptyDashboard.DESCRIPTION).scrollIntoView().should('be.visible'); + + }); + + //TODO: Verify Create project dropdown not only showing perses projects, but all namespaces you have access to, independently of having perses object (that creates a perses project) + // it(`4.${perspective.name} perspective - Verify Create project dropdown not only showing perses projects, but all namespaces you have access to, independently of having perses object (that creates a perses project)`, () => { + // cy.log(`4.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + // listPersesDashboardsPage.shouldBeLoaded(); + + // cy.log(`4.2. Click on Create button`); + // listPersesDashboardsPage.clickCreateButton(); + // persesCreateDashboardsPage.createDashboardShouldBeLoaded(); + + // cy.log(`4.3. Verify Project dropdown`); + // persesCreateDashboardsPage.assertProjectDropdown('openshift-cluster-observability-operator'); + // openshift-monitoringas an example of a namespace that you have access to and does not have any perses object created yet, but you are able to create a dashboard + // persesCreateDashboardsPage.assertProjectDropdown('openshift-monitoring); + + // }); + +} \ No newline at end of file diff --git a/web/cypress/support/perses/99.coo_rbac_perses_user1.cy.ts b/web/cypress/support/perses/99.coo_rbac_perses_user1.cy.ts new file mode 100644 index 000000000..eb5905c44 --- /dev/null +++ b/web/cypress/support/perses/99.coo_rbac_perses_user1.cy.ts @@ -0,0 +1,485 @@ +import { persesDashboardsPage } from '../../views/perses-dashboards'; +import { listPersesDashboardsPage } from '../../views/perses-dashboards-list-dashboards'; +import { persesCreateDashboardsPage } from '../../views/perses-dashboards-create-dashboard'; +import { persesDashboardsAddListVariableSource, persesDashboardSampleQueries, persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev, persesDashboardsEmptyDashboard } from '../../fixtures/perses/constants'; +import { persesDashboardsEditVariables } from '../../views/perses-dashboards-edit-variables'; +import { persesDashboardsPanelGroup } from '../../views/perses-dashboards-panelgroup'; +import { persesAriaLabels } from '../../../src/components/data-test'; +import { persesDashboardsPanel } from '../../views/perses-dashboards-panel'; +import { persesDashboardsAddListPanelType } from '../../fixtures/perses/constants'; + +export interface PerspectiveConfig { + name: string; + beforeEach?: () => void; +} + +export function runCOORBACPersesTestsDevUser1(perspective: PerspectiveConfig) { + testCOORBACPersesTestsDevUser1(perspective); +} + +/** + * User1 has access to: + * - openshift-cluster-observability-operator namespace as persesdashboard-editor-role and persesdatasource-editor-role + * - observ-test namespace as persesdashboard-viewer-role and persesdatasource-viewer-role + * - no access to perses-dev namespace + */ +export function testCOORBACPersesTestsDevUser1(perspective: PerspectiveConfig) { + + it(`1.${perspective.name} perspective - List Dashboards - Namespace validation and Dashboard search`, () => { + cy.log(`1.1. Namespace validation`); + listPersesDashboardsPage.shouldBeLoaded(); + cy.assertNamespace('All Projects', true); + cy.assertNamespace('openshift-cluster-observability-operator', true); + cy.assertNamespace('observ-test', true); + cy.assertNamespace('perses-dev', false); + + cy.log(`1.2. All Projects validation - Dashboard search - ${persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2]} dashboard`); + cy.changeNamespace('All Projects'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + + cy.log(`1.3. All Projects validation - Dashboard search - ${persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]} dashboard`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.countDashboards('2'); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + + cy.log(`1.4. All Projects validation - Dashboard search - ${persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]} dashboard`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.removeTag('perses-dev'); + + }); + + it(`2.${perspective.name} perspective - Edit button validation - Editable dashboard`, () => { + cy.log(`2.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`2.2 change namespace to openshift-cluster-observability-operator`); + cy.changeNamespace('openshift-cluster-observability-operator'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`2.3. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`2.4. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`2.5. Click on Edit button`); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.assertEditModeButtons(); + persesDashboardsPage.assertEditModePanelGroupButtons('Headlines'); + //already expanded + persesDashboardsPage.assertPanelActionButtons('CPU Usage'); + // tiny panel and modal is opened. So, expand first and then assert the buttons and finally collapse + // due to modal is opened and page is refreshed, it is not easy to assert buttons in the modal + persesDashboardsPage.assertPanelActionButtons('CPU Utilisation'); + + cy.log(`2.6. Click on Edit Variables button - Add components`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickButton('Add Variable'); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working + persesDashboardsEditVariables.addListVariable('ListVariable', true, true, 'AAA', 'Test', 'Test', undefined, undefined); + + cy.log(`2.7. Add variable`); + persesDashboardsEditVariables.clickButton('Add'); + + cy.log(`2.8. Apply changes`); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`2.9. Assert Variable before saving`); + persesDashboardsPage.searchAndSelectVariable('ListVariable', 'All'); + + cy.log(`2.10. Click on Add Panel Group button`); + persesDashboardsPage.clickEditActionButton('AddGroup'); + persesDashboardsPanelGroup.addPanelGroup('PanelGroup Perform Changes and Save', 'Open', ''); + + cy.log(`2.11. Click on Add Panel button`); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup Perform Changes and Save', 'addPanel'); + persesDashboardsPanel.addPanel('Panel Perform Changes and Save', 'PanelGroup Perform Changes and Save', persesDashboardsAddListPanelType.TIME_SERIES_CHART, undefined, 'up'); + cy.wait(2000); + + cy.log(`2.13. Click on Save button`); + persesDashboardsPage.clickEditActionButton('Save'); + cy.wait(2000); + + cy.log(`2.14. Assert Panel with Data - Export Time Series Data As CSV button is visible and clickable `); + cy.wait(2000); + cy.byAriaLabel(persesAriaLabels.PanelExportTimeSeriesDataAsCSV).eq(0).click({ force: true }); + cy.wait(1000); + persesDashboardsPage.assertFilename('panelPerformChangesAndSave_data.csv'); + + cy.wait(2000); + + cy.log(`2.15. Back and check changes`); + persesDashboardsPage.backToListPersesDashboardsPage(); + cy.changeNamespace('openshift-cluster-observability-operator'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + persesDashboardsPage.shouldBeLoaded1(); + persesDashboardsPage.searchAndSelectVariable('ListVariable', 'All'); + persesDashboardsPage.panelGroupHeaderAssertion('PanelGroup Perform Changes and Save', 'Open'); + persesDashboardsPage.assertPanel('Panel Perform Changes and Save', 'PanelGroup Perform Changes and Save', 'Open'); + + cy.log(`2.16. Click on Edit Variables button - Delete components`); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickDeleteVariableButton(1); + persesDashboardsEditVariables.clickButton('Apply'); + persesDashboardsPage.assertVariableNotExist('ListVariable'); + + cy.log(`2.17. Click on Delete Panel button`); + persesDashboardsPanel.deletePanel('Panel Perform Changes and Save'); + persesDashboardsPanel.clickDeletePanelButton(); + + cy.log(`2.18. Click on Delete Panel Group button`); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup Perform Changes and Save', 'delete'); + persesDashboardsPanelGroup.clickDeletePanelGroupButton(); + persesDashboardsPage.clickEditActionButton('Save'); + persesDashboardsPage.assertPanelGroupNotExist('PanelGroup Perform Changes and Save'); + persesDashboardsPage.assertPanelNotExist('Panel Perform Changes and Save'); + persesDashboardsPage.assertVariableNotExist('ListVariable'); + + }); + + it(`3.${perspective.name} perspective - Edit button validation - Not editable dashboard`, () => { + cy.log(`3.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`3.2 change namespace to observ-test`); + cy.changeNamespace('observ-test'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`3.3. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`3.4. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`3.5. Verify Edit button is not editable`); + persesDashboardsPage.assertEditButtonIsDisabled(); + + }); + + it(`4.${perspective.name} perspective - Create button validation - Disabled / Enabled`, () => { + cy.log(`4.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`4.2 change namespace to observ-test`); + cy.changeNamespace('observ-test'); + + cy.log(`4.3. Verify Create button is disabled`); + listPersesDashboardsPage.assertCreateButtonIsDisabled(); + + cy.log(`4.4 change namespace to openshift-cluster-observability-operator`); + cy.changeNamespace('openshift-cluster-observability-operator'); + + cy.log(`4.5. Verify Create button is enabled`); + listPersesDashboardsPage.assertCreateButtonIsEnabled(); + + cy.log(`4.2 change namespace to All Projects`); + cy.changeNamespace('All Projects'); + + cy.log(`4.3. Verify Create button is enabled`); + listPersesDashboardsPage.assertCreateButtonIsEnabled(); + + }); + + //TODO: OU-1195 Create, Duplicate - Project dropdown + + it(`5.${perspective.name} perspective - Create Dashboard with panel groups, panels and variables`, () => { + let dashboardName = 'Testing Dashboard - UP '; + let randomSuffix = Math.random().toString(5); + dashboardName += randomSuffix; + cy.log(`5.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + //TODO: uncomment when but gets fixed + cy.changeNamespace('openshift-cluster-observability-operator'); + + cy.log(`5.2. Click on Create button`); + listPersesDashboardsPage.clickCreateButton(); + persesCreateDashboardsPage.createDashboardShouldBeLoaded(); + + cy.log(`5.3. Create Dashboard`); + persesCreateDashboardsPage.selectProject('openshift-cluster-observability-operator'); + persesCreateDashboardsPage.enterDashboardName(dashboardName); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(dashboardName); + persesDashboardsPage.shouldBeLoadedEditionModeFromCreateDashboard(); + + cy.log(`5.4. Add Variable`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickButton('Add Variable'); + persesDashboardsEditVariables.addListVariable('interval', false, false, '', '', '', undefined, undefined); + persesDashboardsEditVariables.addListVariable_staticListVariable_enterValue('1m'); + persesDashboardsEditVariables.addListVariable_staticListVariable_enterValue('5m'); + persesDashboardsEditVariables.clickButton('Add'); + + persesDashboardsEditVariables.clickButton('Add Variable'); + persesDashboardsEditVariables.addListVariable('job', false, false, '', '', '', persesDashboardsAddListVariableSource.PROMETHEUS_LABEL_VARIABLE, undefined); + persesDashboardsEditVariables.addListVariable_promLabelValuesVariable_enterLabelName('job'); + persesDashboardsEditVariables.clickButton('Add'); + + persesDashboardsEditVariables.clickButton('Add Variable'); + persesDashboardsEditVariables.addListVariable('instance', false, false, '', '', '', persesDashboardsAddListVariableSource.PROMETHEUS_LABEL_VARIABLE, undefined); + persesDashboardsEditVariables.addListVariable_promLabelValuesVariable_enterLabelName('instance'); + persesDashboardsEditVariables.addListVariable_promLabelValuesVariable_addSeriesSelector(persesDashboardSampleQueries.CPU_LINE_MULTI_SERIES_SERIES_SELECTOR); + persesDashboardsEditVariables.clickButton('Add'); + + persesDashboardsEditVariables.clickButton('Apply'); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`5.5. Add Panel Group`); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('AddGroup'); + persesDashboardsPanelGroup.addPanelGroup('Panel Group Up', 'Open', ''); + + cy.log(`5.6. Add Panel`); + persesDashboardsPage.clickEditActionButton('AddPanel'); + persesDashboardsPanel.addPanelShouldBeLoaded(); + persesDashboardsPanel.addPanel('Up', 'Panel Group Up', persesDashboardsAddListPanelType.TIME_SERIES_CHART, 'This is a line chart test', 'up'); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`5.7. Back and check panel`); + persesDashboardsPage.backToListPersesDashboardsPage(); + cy.changeNamespace('openshift-cluster-observability-operator'); + listPersesDashboardsPage.filter.byName(dashboardName); + listPersesDashboardsPage.clickDashboard(dashboardName); + persesDashboardsPage.panelGroupHeaderAssertion('Panel Group Up', 'Open'); + persesDashboardsPage.assertPanel('Up', 'Panel Group Up', 'Open'); + persesDashboardsPage.assertVariableBeVisible('interval'); + persesDashboardsPage.assertVariableBeVisible('job'); + persesDashboardsPage.assertVariableBeVisible('instance'); + + cy.log(`5.8. Click on Edit button`); + persesDashboardsPage.clickEditButton(); + + cy.log(`5.9. Click on Edit Variables button and Delete all variables`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickDeleteVariableButton(0); + persesDashboardsEditVariables.clickDeleteVariableButton(0); + persesDashboardsEditVariables.clickDeleteVariableButton(0); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`5.10. Assert variables not exist`); + persesDashboardsPage.assertVariableNotExist('interval'); + persesDashboardsPage.assertVariableNotExist('job'); + persesDashboardsPage.assertVariableNotExist('instance'); + + cy.log(`5.11. Delete Panel`); + persesDashboardsPanel.deletePanel('Up'); + persesDashboardsPanel.clickDeletePanelButton(); + + cy.log(`5.12. Delete Panel Group`); + persesDashboardsPanelGroup.clickPanelGroupAction('Panel Group Up', 'delete'); + persesDashboardsPanelGroup.clickDeletePanelGroupButton(); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.get('h2').contains(persesDashboardsEmptyDashboard.TITLE).scrollIntoView().should('be.visible'); + cy.get('p').contains(persesDashboardsEmptyDashboard.DESCRIPTION).scrollIntoView().should('be.visible'); + + }); + + it(`6.${perspective.name} perspective - Kebab icon - Enabled / Disabled`, () => { + cy.log(`6.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`6.2. Change namespace to observ-test`); + cy.changeNamespace('observ-test'); + + cy.log(`6.3. Assert Kebab icon is disabled`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.assertKebabIconDisabled(); + + cy.log(`6.4. Change namespace to openshift-cluster-observability-operator`); + cy.changeNamespace('openshift-cluster-observability-operator'); + + cy.log(`6.5. Assert Kebab icon is enabled`); + listPersesDashboardsPage.clearAllFilters(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.assertKebabIconOptions(); + listPersesDashboardsPage.clickKebabIcon(); + + cy.log(`6.2. Change namespace to All Projects`); + cy.changeNamespace('All Projects'); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`6.3. Filter by Project and Name`); + listPersesDashboardsPage.filter.byProject('observ-test'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.assertKebabIconDisabled(); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`6.4. Filter by Project and Name`); + listPersesDashboardsPage.filter.byProject('openshift-cluster-observability-operator'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.assertKebabIconOptions(); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clearAllFilters(); + + }); + + + it(`7.${perspective.name} perspective - Rename to a new dashboard name`, () => { + let dashboardName = 'Renamed dashboard '; + let randomSuffix = Math.random().toString(5); + dashboardName += randomSuffix; + + cy.log(`7.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`7.2. Change namespace to openshift-cluster-observability-operator`); + cy.changeNamespace('openshift-cluster-observability-operator'); + + cy.log(`7.3. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`7.4. Click on the Kebab icon - Rename`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickRenameDashboardOption(); + listPersesDashboardsPage.renameDashboardEnterName(dashboardName); + listPersesDashboardsPage.renameDashboardRenameButton(); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`7.5. Filter by Name`); + listPersesDashboardsPage.filter.byName(dashboardName); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.clickDashboard(dashboardName); + persesDashboardsPage.shouldBeLoaded1(); + persesDashboardsPage.shouldBeLoadedAfterRename(dashboardName); + persesDashboardsPage.backToListPersesDashboardsPage(); + + cy.log(`7.6. Rename back to the original name`); + cy.changeNamespace('openshift-cluster-observability-operator'); + listPersesDashboardsPage.filter.byName(dashboardName); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickRenameDashboardOption(); + listPersesDashboardsPage.renameDashboardEnterName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.renameDashboardRenameButton(); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`7.7. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + persesDashboardsPage.shouldBeLoaded1(); + persesDashboardsPage.shouldBeLoadedAfterRename(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + persesDashboardsPage.backToListPersesDashboardsPage(); + + }); + + //TODO: OU-1195 Create, Duplicate - Project dropdown + it(`8.${perspective.name} perspective - Duplicate and verify project dropdown and Delete`, () => { + let dashboardName = 'Duplicate dashboard '; + let randomSuffix = Math.random().toString(5); + dashboardName += randomSuffix; + + cy.log(`8.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`8.2. Change namespace to openshift-cluster-observability-operator`); + cy.changeNamespace('openshift-cluster-observability-operator'); + + cy.log(`8.3. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`8.4. Click on the Kebab icon - Duplicate`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickDuplicateOption(); + + cy.log(`8.5. Assert project dropdown options`); + listPersesDashboardsPage.assertDuplicateProjectDropdownOptions('openshift-cluster-observability-operator', true); + listPersesDashboardsPage.assertDuplicateProjectDropdownOptions('observ-test', false); + listPersesDashboardsPage.assertDuplicateProjectDropdownOptions('perses-dev', false); + + cy.log(`8.6. Enter new dashboard name`); + listPersesDashboardsPage.duplicateDashboardEnterName(dashboardName); + listPersesDashboardsPage.duplicateDashboardDuplicateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(dashboardName); + persesDashboardsPage.shouldBeLoadedAfterDuplicate(dashboardName); + persesDashboardsPage.backToListPersesDashboardsPage(); + + cy.log(`8.7. Filter by Name`); + listPersesDashboardsPage.filter.byName(dashboardName); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`8.8. Click on the Kebab icon - Delete`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickDeleteOption(); + listPersesDashboardsPage.deleteDashboardDeleteButton(); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`8.9. Filter by Name`); + listPersesDashboardsPage.filter.byName(dashboardName); + listPersesDashboardsPage.countDashboards('0'); + listPersesDashboardsPage.clearAllFilters(); + + }); + + it(`9.${perspective.name} perspective - Delete dashboard`, () => { + cy.log(`9.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`9.3. Filter by Name`); + listPersesDashboardsPage.filter.byName('Testing Dashboard - UP'); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`9.4. Click on the Kebab icon - Delete`); + listPersesDashboardsPage.clickKebabIcon(); + listPersesDashboardsPage.clickDeleteOption(); + listPersesDashboardsPage.deleteDashboardDeleteButton(); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.countDashboards('0'); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`9.5. Filter by Name`); + listPersesDashboardsPage.filter.byName('Testing Dashboard - UP'); + listPersesDashboardsPage.countDashboards('0'); + listPersesDashboardsPage.clearAllFilters(); + + }); + + // it(`17.${perspective.name} perspective - Import button validation - Enabled / Disabled`, () => { + // // Enabled for openshift-cluster-observability-operator namespace + // // Disabled for observ-test namespace + // }); + + // it(`18.${perspective.name} perspective - Import button validation - Enabled - YAML - project and namespace in the file mismatches`, () => { + // // Enabled for openshift-cluster-observability-operator namespace + // }); + + // it(`19.${perspective.name} perspective - Import button validation - Enabled - YAML project and namespace in the file matches`, () => { + // // Enabled for openshift-cluster-observability-operator namespace + // }); + + // it(`20.${perspective.name} perspective - Import button validation - Enabled - JSON - project and namespace in the file mismatches`, () => { + // // Enabled for openshift-cluster-observability-operator namespace + // }); + + // it(`21.${perspective.name} perspective - Import button validation - Enabled - JSON project and namespace in the file matches`, () => { + // // Enabled for openshift-cluster-observability-operator namespace + // }); + + +} \ No newline at end of file diff --git a/web/cypress/support/perses/99.coo_rbac_perses_user2.cy.ts b/web/cypress/support/perses/99.coo_rbac_perses_user2.cy.ts new file mode 100644 index 000000000..251f3c164 --- /dev/null +++ b/web/cypress/support/perses/99.coo_rbac_perses_user2.cy.ts @@ -0,0 +1,120 @@ +import { persesDashboardsPage } from '../../views/perses-dashboards'; +import { listPersesDashboardsPage } from '../../views/perses-dashboards-list-dashboards'; +import { persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev } from '../../fixtures/perses/constants'; + +export interface PerspectiveConfig { + name: string; + beforeEach?: () => void; +} + +export function runCOORBACPersesTestsDevUser2(perspective: PerspectiveConfig) { + testCOORBACPersesTestsDevUser2(perspective); +} + +/** + * User2 has access to: + * - perses-dev namespace as persesdashboard-viewer-role and persesdatasource-viewer-role + * - no access to openshift-cluster-observability-operator and observ-test namespaces + */ +export function testCOORBACPersesTestsDevUser2(perspective: PerspectiveConfig) { + + it(`1.${perspective.name} perspective - List Dashboards - Namespace validation and Dashboard search`, () => { + cy.log(`1.1. Namespace validation`); + listPersesDashboardsPage.shouldBeLoaded(); + cy.assertNamespace('All Projects', true); + cy.assertNamespace('openshift-cluster-observability-operator', false); + cy.assertNamespace('observ-test', false); + cy.assertNamespace('perses-dev', true); + + cy.log(`1.2. All Projects validation - Dashboard search - ${persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]} dashboard`); + cy.changeNamespace('All Projects'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.removeTag('perses-dev'); + + cy.changeNamespace('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + + cy.log(`1.3. All Projects validation - Dashboard search - ${persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2]} dashboard`); + cy.changeNamespace('All Projects'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0]); + + cy.log(`1.4. All Projects validation - Dashboard search - ${persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]} dashboard`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[0]); + + }); + + it(`2.${perspective.name} perspective - Edit button validation - Not Editable dashboard`, () => { + cy.log(`2.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`2.2 change namespace to perses-dev`); + cy.changeNamespace('perses-dev'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`2.3. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`2.4. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + persesDashboardsPage.shouldBeLoaded1(); + persesDashboardsPage.assertEditButtonIsDisabled(); + + }); + + it(`3.${perspective.name} perspective - Create button validation - Disabled`, () => { + cy.log(`3.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`3.2. Verify Create button is disabled`); + listPersesDashboardsPage.assertCreateButtonIsDisabled(); + + cy.log(`3.3 change namespace to perses-dev`); + cy.changeNamespace('perses-dev'); + + cy.log(`3.4. Verify Create button is disabled`); + listPersesDashboardsPage.assertCreateButtonIsDisabled(); + + }); + + it(`4.${perspective.name} perspective - Kebab icon - Disabled`, () => { + cy.log(`4.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`4.2. Change namespace to perses-dev`); + cy.changeNamespace('perses-dev'); + + cy.log(`4.3. Assert Kebab icon is disabled`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.assertKebabIconDisabled(); + listPersesDashboardsPage.clearAllFilters(); + + cy.log(`4.4. Change namespace to All Projects`); + cy.changeNamespace('All Projects'); + + cy.log(`4.5. Assert Kebab icon is disabled`); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.assertKebabIconDisabled(); + listPersesDashboardsPage.clearAllFilters(); + + }); + + // it(`5.${perspective.name} perspective - Import button validation - Disabled`, () => { + // // Disabled for perses-dev namespace + // + // }); + + +} \ No newline at end of file diff --git a/web/cypress/support/test-tags.d.ts b/web/cypress/support/test-tags.d.ts index 4b10efaa5..d35493423 100644 --- a/web/cypress/support/test-tags.d.ts +++ b/web/cypress/support/test-tags.d.ts @@ -19,4 +19,3 @@ declare namespace Cypress { } export {}; - diff --git a/web/cypress/views/acm-alerting-page.ts b/web/cypress/views/acm-alerting-page.ts index 1c8ee8a86..5efbe80d9 100644 --- a/web/cypress/views/acm-alerting-page.ts +++ b/web/cypress/views/acm-alerting-page.ts @@ -1,5 +1,3 @@ -import { DataTestIDs, Classes } from "../../src/components/data-test"; - export const acmAlertingPage = { shouldBeLoaded: () => { cy.log('acmAlertingPage.shouldBeLoaded'); @@ -8,4 +6,4 @@ export const acmAlertingPage = { // To Do: // other page check could be list here }, -}; +}; \ No newline at end of file diff --git a/web/cypress/views/alerting-rule-details-page.ts b/web/cypress/views/alerting-rule-details-page.ts index 90462502b..02d32bd3d 100644 --- a/web/cypress/views/alerting-rule-details-page.ts +++ b/web/cypress/views/alerting-rule-details-page.ts @@ -64,4 +64,4 @@ export const alertingRuleDetailsPage = { cy.byTestID(DataTestIDs.MetricHideShowGraphButton).scrollIntoView().contains('Show graph').should('be.visible').click(); cy.byTestID(DataTestIDs.MetricGraph).should('be.visible'); }, -}; +}; \ No newline at end of file diff --git a/web/cypress/views/alerting-rule-list-page.ts b/web/cypress/views/alerting-rule-list-page.ts index 807956c41..4a3719c4b 100644 --- a/web/cypress/views/alerting-rule-list-page.ts +++ b/web/cypress/views/alerting-rule-list-page.ts @@ -60,4 +60,4 @@ export const alertingRuleListPage = { cy.byOUIAID(DataTestIDs.Table).should('not.exist'); }, -}; +}; \ No newline at end of file diff --git a/web/cypress/views/common.ts b/web/cypress/views/common.ts index 49b2dfa1b..eb133579b 100644 --- a/web/cypress/views/common.ts +++ b/web/cypress/views/common.ts @@ -1,13 +1,18 @@ import { detailsPage } from "./details-page"; -import { nav } from "./nav"; import { DataTestIDs, Classes } from "../../src/components/data-test"; export const commonPages = { projectDropdownShouldNotExist: () => cy.byLegacyTestID('namespace-bar-dropdown').should('not.exist'), projectDropdownShouldExist: () => cy.byLegacyTestID('namespace-bar-dropdown').should('exist'), titleShouldHaveText: (title: string) => { + cy.wait(15000); cy.log('commonPages.titleShouldHaveText - ' + `${title}`); - cy.bySemanticElement('h1', title).should('be.visible'); + cy.bySemanticElement('h1', title).scrollIntoView().should('be.visible'); + }, + + titleModalShouldHaveText: (title: string) => { + cy.log('commonPages.titleModalShouldHaveText - ' + `${title}`); + cy.bySemanticElement('h2', title).scrollIntoView().should('be.visible'); }, linkShouldExist: (linkName: string) => { diff --git a/web/cypress/views/details-page.ts b/web/cypress/views/details-page.ts index 6fc1e5cfe..77c36aceb 100644 --- a/web/cypress/views/details-page.ts +++ b/web/cypress/views/details-page.ts @@ -122,4 +122,4 @@ export const detailsPage = { }, -}; +}; \ No newline at end of file diff --git a/web/cypress/views/legacy-dashboards.ts b/web/cypress/views/legacy-dashboards.ts index c7bbbc82c..ab90b09b8 100644 --- a/web/cypress/views/legacy-dashboards.ts +++ b/web/cypress/views/legacy-dashboards.ts @@ -1,7 +1,6 @@ import { commonPages } from "./common"; import { LegacyDashboardPageTestIDs, DataTestIDs, Classes, IDs, LegacyTestIDs } from "../../src/components/data-test"; import { MonitoringPageTitles, LegacyDashboardsTimeRange, MonitoringRefreshInterval, LegacyDashboardsDashboardDropdown, API_PERFORMANCE_DASHBOARD_PANELS, LegacyDashboardsDashboardDropdownNamespace, KUBERNETES_COMPUTE_RESOURCES_NAMESPACE_PODS_PANELS } from "../fixtures/monitoring/constants"; -import { clickIfExist } from "./utils"; export const legacyDashboardsPage = { @@ -10,14 +9,14 @@ export const legacyDashboardsPage = { commonPages.titleShouldHaveText(MonitoringPageTitles.DASHBOARDS); cy.byTestID(LegacyDashboardPageTestIDs.TimeRangeDropdown).contains(LegacyDashboardsTimeRange.LAST_30_MINUTES).should('be.visible'); cy.byTestID(LegacyDashboardPageTestIDs.PollIntervalDropdown).contains(MonitoringRefreshInterval.THIRTY_SECONDS).should('be.visible'); - //TODO: Uncomment when OU-949 gets merged - // cy.byLegacyTestID('namespace-bar-dropdown').find('span').invoke('text').then((text) => { - // if (text === 'Project: All Projects') { - // cy.byTestID(LegacyDashboardPageTestIDs.DashboardDropdown).find('input').should('have.value', LegacyDashboardsDashboardDropdown.API_PERFORMANCE[0]).and('be.visible'); - // } else { - // cy.byTestID(LegacyDashboardPageTestIDs.DashboardDropdown).find('input').should('have.value', LegacyDashboardsDashboardDropdownNamespace.K8S_COMPUTE_RESOURCES_NAMESPACE_PODS[0]).and('be.visible'); - // } - // }); + + cy.byLegacyTestID('namespace-bar-dropdown').find('span').invoke('text').then((text) => { + if (text === 'Project: All Projects') { + cy.byTestID(LegacyDashboardPageTestIDs.DashboardDropdown).find('input').should('have.value', LegacyDashboardsDashboardDropdown.API_PERFORMANCE[0]).and('be.visible'); + } else { + cy.byTestID(LegacyDashboardPageTestIDs.DashboardDropdown).find('input').should('have.value', LegacyDashboardsDashboardDropdownNamespace.K8S_COMPUTE_RESOURCES_NAMESPACE_PODS[0]).and('be.visible'); + } + }); }, clickTimeRangeDropdown: (timeRange: LegacyDashboardsTimeRange) => { @@ -77,25 +76,25 @@ export const legacyDashboardsPage = { cy.byTestID(LegacyDashboardPageTestIDs.DashboardDropdown).find('button').should('be.visible').click(); }, - dashboardAPIPerformancePanelAssertion: (panel: API_PERFORMANCE_DASHBOARD_PANELS) => { + dashboardAPIPerformancePanelAssertion: () => { cy.log('legacyDashboardsPage.dashboardAPIPerformancePanelAssertion'); function formatDataTestID(panel: API_PERFORMANCE_DASHBOARD_PANELS): string { return panel.toLowerCase().replace(/\s+/g, '-').concat('-chart'); } - const dataTestID = Object.values(API_PERFORMANCE_DASHBOARD_PANELS).map(formatDataTestID); - dataTestID.forEach((dataTestID) => { + const dataTestIDs = Object.values(API_PERFORMANCE_DASHBOARD_PANELS).map(formatDataTestID); + dataTestIDs.forEach((dataTestID) => { cy.log('Data test ID: ' + dataTestID); cy.byTestID(dataTestID).scrollIntoView().should('be.visible'); }); }, - dashboardKubernetesComputeResourcesNamespacePodsPanelAssertion: (panel: KUBERNETES_COMPUTE_RESOURCES_NAMESPACE_PODS_PANELS) => { + dashboardKubernetesComputeResourcesNamespacePodsPanelAssertion: () => { cy.log('legacyDashboardsPage.dashboardKubernetesComputeResourcesNamespacePodsPanelAssertion'); function formatDataTestID(panel: KUBERNETES_COMPUTE_RESOURCES_NAMESPACE_PODS_PANELS): string { return panel.toLowerCase().replace(/\s+/g, '-').concat('-chart'); } - const dataTestID = Object.values(KUBERNETES_COMPUTE_RESOURCES_NAMESPACE_PODS_PANELS).map(formatDataTestID); - dataTestID.forEach((dataTestID) => { + const dataTestIDs = Object.values(KUBERNETES_COMPUTE_RESOURCES_NAMESPACE_PODS_PANELS).map(formatDataTestID); + dataTestIDs.forEach((dataTestID) => { cy.log('Data test ID: ' + dataTestID); cy.byTestID(dataTestID).scrollIntoView().should('be.visible'); }); @@ -138,4 +137,4 @@ export const legacyDashboardsPage = { }, -}; +}; \ No newline at end of file diff --git a/web/cypress/views/list-page.ts b/web/cypress/views/list-page.ts index f4b910f17..1a2fc3874 100644 --- a/web/cypress/views/list-page.ts +++ b/web/cypress/views/list-page.ts @@ -60,13 +60,20 @@ export const listPage = { */ byName: (name: string) => { cy.log('listPage.filter.byName'); - try { + cy.get('body').then(($body) => { + const hasFilterbyName419 = $body.find('[data-test-id="' + LegacyTestIDs.NameLabelDropdown + '"]').length > 0; + if (hasFilterbyName419) { + cy.byLegacyTestID(LegacyTestIDs.NameLabelDropdown).scrollIntoView().click(); + cy.byLegacyTestID(LegacyTestIDs.NameLabelDropdownOptions).contains('Name').click(); + } else { cy.byTestID(DataTestIDs.NameLabelDropdown).scrollIntoView().click(); cy.byTestID(DataTestIDs.NameLabelDropdownOptions).contains('Name').click(); - cy.byTestID(DataTestIDs.NameInput).scrollIntoView().as('input').should('be.visible'); - cy.get('@input', { timeout: 10000 }).scrollIntoView().type(name + '{enter}'); - cy.get('@input', { timeout: 10000 }).scrollIntoView().should('have.attr', 'value', name); - + } + }); + try { + cy.byTestID(DataTestIDs.NameInput).scrollIntoView().as('input').should('be.visible'); + cy.get('@input', { timeout: 10000 }).scrollIntoView().type(name + '{enter}'); + cy.get('@input', { timeout: 10000 }).scrollIntoView().should('have.attr', 'value', name); } catch (error) { cy.log(`${error.message}`); @@ -78,14 +85,22 @@ export const listPage = { */ byLabel: (label: string) => { cy.log('listPage.filter.byLabel'); - cy.byTestID(DataTestIDs.NameLabelDropdown).scrollIntoView().click(); - cy.byTestID(DataTestIDs.NameLabelDropdownOptions).contains('Label').click(); + cy.get('body').then(($body) => { + const hasFilterbyName419 = $body.find('[data-test-id="' + LegacyTestIDs.NameLabelDropdown + '"]').length > 0; + if (hasFilterbyName419) { + cy.byLegacyTestID(LegacyTestIDs.NameLabelDropdown).scrollIntoView().click(); + cy.byLegacyTestID(LegacyTestIDs.NameLabelDropdownOptions).contains('Label').click(); + } else { + cy.byTestID(DataTestIDs.NameLabelDropdown).scrollIntoView().click(); + cy.byTestID(DataTestIDs.NameLabelDropdownOptions).contains('Label').click(); + } + }); cy.byLegacyTestID(LegacyTestIDs.ItemFilter).scrollIntoView() .as('input').should('be.visible'); cy.get('@input', { timeout: 10000 }).scrollIntoView().type(label + '{enter}').should('have.attr', 'value', label); cy.byTestID(DataTestIDs.LabelSuggestion).contains(label).click(); }, - + clearAllFilters: () => { cy.log('listPage.filter.clearAllFilters'); try { @@ -178,7 +193,7 @@ export const listPage = { cy.log('listPage.ARRows.countShouldBe'); cy.byTestID(DataTestIDs.AlertingRuleResourceIcon).should('have.length', count); }, - + //pf-6 only ARShouldBe: (alert: string, severity: string, total: number, state: string) => { cy.log('listPage.ARRows.ARShouldBe'); @@ -190,7 +205,7 @@ export const listPage = { cy.byTestID(DataTestIDs.AlertingRuleTotalAlertsBadge).contains(total).should('exist'); cy.byTestID(DataTestIDs.AlertingRuleStateBadge).contains(state).should('exist'); } - + }, AShouldBe: (alert: string, severity: string, namespace: string) => { cy.log('listPage.ARRows.AShouldBe'); @@ -198,7 +213,7 @@ export const listPage = { cy.byTestID(DataTestIDs.AlertResourceLink).contains(alert).should('exist'); cy.byTestID(DataTestIDs.SeverityBadge).contains(severity).should('exist'); cy.byTestID(DataTestIDs.AlertNamespace).contains(namespace).should('exist'); //pf-6 only - + }, //pf-6 only expandRow: () => { diff --git a/web/cypress/views/metrics.ts b/web/cypress/views/metrics.ts index 195e63c13..d974dd117 100644 --- a/web/cypress/views/metrics.ts +++ b/web/cypress/views/metrics.ts @@ -1,5 +1,5 @@ import { commonPages } from "./common"; -import { DataTestIDs, Classes, LegacyTestIDs, IDs } from "../../src/components/data-test"; +import { DataTestIDs, Classes, IDs } from "../../src/components/data-test"; import { MetricsPageUnits, MonitoringRefreshInterval, MetricsPageQueryInput, MetricsPageActions, MetricGraphEmptyState, MetricsPagePredefinedQueries, MetricsPageQueryKebabDropdown, GraphTimespan } from "../fixtures/monitoring/constants"; export const metricsPage = { @@ -289,23 +289,19 @@ export const metricsPage = { clickGraphTimespanDropdown: (timespan: GraphTimespan) => { cy.log('metricsPage.clickGraphTimespanDropdown'); - cy.byTestID(DataTestIDs.MetricGraphTimespanDropdown).should('be.visible').click(); + cy.byTestID(DataTestIDs.MetricGraphTimespanDropdown).scrollIntoView().should('be.visible').click(); cy.get(Classes.MenuItem).contains(timespan).should('be.visible').click(); cy.byPFRole('progressbar').should('be.visible'); cy.byPFRole('progressbar').should('not.exist'); - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('be.visible'); - cy.byTestID(DataTestIDs.MetricGraph).find('[data-ouia-component-id^="' + DataTestIDs.MetricsGraphAlertDanger + '"]').should('not.exist'); }, enterGraphTimespan: (timespan: GraphTimespan) => { cy.log('metricsPage.enterGraphTimespan'); - cy.byTestID(DataTestIDs.MetricGraphTimespanInput).type('{selectall}{backspace}', {delay: 1000}); + cy.byTestID(DataTestIDs.MetricGraphTimespanInput).scrollIntoView().should('be.visible').type('{selectall}{backspace}', {delay: 1000}); cy.byTestID(DataTestIDs.MetricGraphTimespanInput).type(timespan); cy.byTestID(DataTestIDs.MetricGraphTimespanInput).should('have.attr', 'value', timespan); cy.byPFRole('progressbar').should('be.visible'); cy.byPFRole('progressbar').should('not.exist'); - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('be.visible'); - cy.byTestID(DataTestIDs.MetricGraph).find('[data-ouia-component-id^="' + DataTestIDs.MetricsGraphAlertDanger + '"]').should('not.exist'); }, graphTimespanDropdownAssertion: () => { @@ -321,7 +317,7 @@ export const metricsPage = { clickResetZoomButton: () => { cy.log('metricsPage.clickResetZoomButton'); - cy.byTestID(DataTestIDs.MetricResetZoomButton).should('be.visible').click(); + cy.byTestID(DataTestIDs.MetricResetZoomButton).scrollIntoView().should('be.visible').click(); }, clickHideGraphButton: () => { @@ -338,18 +334,18 @@ export const metricsPage = { clickDisconnectedCheckbox: () => { cy.log('metricsPage.clickDisconnectedCheckbox'); - cy.byTestID(DataTestIDs.MetricDisconnectedCheckbox).should('be.visible').click(); + cy.byTestID(DataTestIDs.MetricDisconnectedCheckbox).scrollIntoView().should('be.visible').click(); }, clickStackedCheckbox: () => { cy.log('metricsPage.clickStackedCheckbox'); - cy.byTestID(DataTestIDs.MetricStackedCheckbox).should('be.visible').click(); + cy.byTestID(DataTestIDs.MetricStackedCheckbox).scrollIntoView().should('be.visible').click(); }, clickStackedCheckboxAndAssert: () => { cy.log('metricsPage.clickStackedCheckboxAndAssert'); cy.get('[id^="' + IDs.ChartAxis1ChartLabel + '"]').invoke('text').as('yAxisLabel'); - cy.byTestID(DataTestIDs.MetricStackedCheckbox).should('be.visible').click(); + cy.byTestID(DataTestIDs.MetricStackedCheckbox).scrollIntoView().should('be.visible').click(); cy.get('[id^="' + IDs.ChartAxis1ChartLabel + '"]').then(() => { cy.get('@yAxisLabel').then((value) => { cy.get('[id^="' + IDs.ChartAxis1ChartLabel + '"]').should('not.contain', value); @@ -361,7 +357,7 @@ export const metricsPage = { graphCardInlineInfoAssertion: (visible: boolean) => { cy.log('metricsPage.graphCardInlineInfoAssertion'); if (visible) { - cy.get(Classes.GraphCardInlineInfo).should('be.visible'); + cy.get(Classes.GraphCardInlineInfo).scrollIntoView().should('be.visible'); } else { cy.get(Classes.GraphCardInlineInfo).should('not.exist'); } @@ -369,7 +365,7 @@ export const metricsPage = { predefinedQueriesAssertion: () => { cy.log('metricsPage.predefinedQueriesAssertion'); - cy.byTestID(DataTestIDs.TypeaheadSelectInput).should('be.visible').click(); + cy.byTestID(DataTestIDs.TypeaheadSelectInput).scrollIntoView().should('be.visible').click(); const queries = Object.values(MetricsPagePredefinedQueries); queries.forEach((query) => { @@ -380,7 +376,7 @@ export const metricsPage = { clickPredefinedQuery: (query: MetricsPagePredefinedQueries) => { cy.log('metricsPage.clickPredefinedQuery'); - cy.byTestID(DataTestIDs.TypeaheadSelectInput).should('be.visible').click(); + cy.byTestID(DataTestIDs.TypeaheadSelectInput).scrollIntoView().should('be.visible').click(); cy.get(Classes.MetricsPagePredefinedQueriesMenuItem).contains(query).should('be.visible').click(); }, @@ -441,46 +437,50 @@ export const metricsPage = { */ graphAxisXAssertion: (graphTimespan: GraphTimespan) => { cy.log('metricsPage.graphAxisAssertion'); - - switch (graphTimespan) { - case GraphTimespan.FIVE_MINUTES: - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 20); - break; - case GraphTimespan.FIFTEEN_MINUTES: - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 15); - break; - case GraphTimespan.THIRTY_MINUTES: - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length.lte', 30); - break; - case GraphTimespan.ONE_HOUR: - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 12); - break; - case GraphTimespan.TWO_HOURS: - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 24); - break; - case GraphTimespan.SIX_HOURS: - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 12); - break; - case GraphTimespan.TWELVE_HOURS: - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 12); - break; - case GraphTimespan.ONE_DAY: - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 24); - break; - case GraphTimespan.TWO_DAYS: - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 16); - break; - case GraphTimespan.ONE_WEEK: - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 14); - break; - case GraphTimespan.TWO_WEEKS: - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 14); - break; - default: //30m is default - cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 15); - break; - } - + cy.get('body').then($body => { + if ($body.find('[id^="' + IDs.ChartAxis0ChartLabel + '"]').length > 0) { + switch (graphTimespan) { + case GraphTimespan.FIVE_MINUTES: + cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 20); + break; + case GraphTimespan.FIFTEEN_MINUTES: + cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 15); + break; + case GraphTimespan.THIRTY_MINUTES: + cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length.lte', 30); + break; + case GraphTimespan.ONE_HOUR: + cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 12); + break; + case GraphTimespan.TWO_HOURS: + cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 24); + break; + case GraphTimespan.SIX_HOURS: + cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 12); + break; + case GraphTimespan.TWELVE_HOURS: + cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 12); + break; + case GraphTimespan.ONE_DAY: + cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 24); + break; + case GraphTimespan.TWO_DAYS: + cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 16); + break; + case GraphTimespan.ONE_WEEK: + cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 14); + break; + case GraphTimespan.TWO_WEEKS: + cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 14); + break; + default: //30m is default + cy.get('[id^="' + IDs.ChartAxis0ChartLabel + '"]').should('have.length', 15); + break; + } + } else { + cy.byTestID(DataTestIDs.MetricGraphNoDatapointsFound).scrollIntoView().contains(MetricGraphEmptyState.NO_DATAPOINTS_FOUND).should('be.visible'); + } + }); }, enterQueryInput: (index: number, query: string) => { @@ -586,4 +586,4 @@ export const metricsPage = { cy.byTestID(DataTestIDs.MetricsPageSeriesButton).should('not.exist'); }, -}; +}; \ No newline at end of file diff --git a/web/cypress/views/nav.ts b/web/cypress/views/nav.ts index ae7b580ca..d2135007a 100644 --- a/web/cypress/views/nav.ts +++ b/web/cypress/views/nav.ts @@ -6,12 +6,25 @@ export const nav = { cy.clickNavLink(path); }, switcher: { - changePerspectiveTo: (perspective: string) => { - cy.log('Switch perspective - ' + `${perspective}`); - cy.byLegacyTestID('perspective-switcher-toggle').scrollIntoView().should('be.visible'); - cy.byLegacyTestID('perspective-switcher-toggle').scrollIntoView().should('be.visible').click({force: true}); - cy.byLegacyTestID('perspective-switcher-menu-option').contains(perspective).should('be.visible'); - cy.byLegacyTestID('perspective-switcher-menu-option').contains(perspective).should('be.visible').click({force: true}); + changePerspectiveTo: (...perspectives: string[]) => { + cy.get('body').then((body) => { + if (body.find('button[data-test-id="perspective-switcher-toggle"]:visible').length > 0) { + cy.byLegacyTestID('perspective-switcher-toggle').scrollIntoView().click({ force: true }); + + cy.get('[data-test-id="perspective-switcher-menu-option"]').then(($options) => { + const foundPerspective = perspectives.find(p => $options.text().includes(p)); + if (foundPerspective) { + cy.byLegacyTestID('perspective-switcher-menu-option') + .contains(foundPerspective) + .click({ force: true }); + } else { + cy.log('No matching perspective found'); + cy.get('body').type('{esc}'); + } + }); + + } + }); }, shouldHaveText: (perspective: string) => { cy.log('Should have text - ' + `${perspective}`); @@ -28,4 +41,4 @@ export const nav = { cy.get(Classes.HorizontalNav).contains(tabname).should('be.visible').click(); } } -}; +}; \ No newline at end of file diff --git a/web/cypress/views/perses-dashboards-create-dashboard.ts b/web/cypress/views/perses-dashboards-create-dashboard.ts new file mode 100644 index 000000000..4022978f3 --- /dev/null +++ b/web/cypress/views/perses-dashboards-create-dashboard.ts @@ -0,0 +1,67 @@ +import { Classes, IDs } from "../../src/components/data-test"; +import { persesCreateDashboard, persesDashboardsModalTitles } from "../fixtures/perses/constants"; + +export const persesCreateDashboardsPage = { + + createDashboardShouldBeLoaded: () => { + cy.log('persesCreateDashboardsPage.createDashboardShouldBeLoaded'); + cy.byPFRole('dialog').find('h1').should('have.text', persesDashboardsModalTitles.CREATE_DASHBOARD); + cy.get(Classes.PersesCreateDashboardProjectDropdown).should('be.visible'); + cy.get('#' + IDs.persesDashboardCreateDashboardName).should('be.visible'); + cy.byPFRole('dialog').find('button').contains('Create').should('be.visible'); + cy.byPFRole('dialog').find('button').contains('Cancel').should('be.visible'); + }, + + selectProject: (project: string) => { + cy.log('persesCreateDashboardsPage.selectProject'); + cy.get(Classes.PersesCreateDashboardProjectDropdown).should('be.visible').click({ force: true }); + cy.byPFRole('menuitem').contains(project).should('be.visible').click({ force: true }); + }, + + assertProjectDropdown: (project: string) => { + cy.log('persesCreateDashboardsPage.assertProjectDropdown'); + cy.get(Classes.PersesCreateDashboardProjectDropdown).should('be.visible').click({ force: true }); + cy.byPFRole('menuitem').contains(project).should('be.visible'); + cy.get(Classes.PersesCreateDashboardProjectDropdown).should('be.visible').click({ force: true }); + }, + + assertProjectNotExistsInDropdown: (project: string) => { + cy.log('persesCreateDashboardsPage.assertProjectNotExistsInDropdown'); + cy.get(Classes.PersesCreateDashboardProjectDropdown).should('be.visible').click({ force: true }); + cy.byPFRole('menu').find('li').then((items) => { + items.each((index, item) => { + cy.log('Project: ' + item.innerText); + if (item.innerText === project) { + expect(item).to.not.exist; + } + }); + }); + cy.get(Classes.PersesCreateDashboardProjectDropdown).should('be.visible').click({ force: true }); + }, + + enterDashboardName: (name: string) => { + cy.log('persesCreateDashboardsPage.enterDashboardName'); + cy.get('#' + IDs.persesDashboardCreateDashboardName).should('be.visible').clear().type(name); + }, + + createDashboardDialogCreateButton: () => { + cy.log('persesCreateDashboardsPage.clickCreateButton'); + cy.byPFRole('dialog').find('button').contains('Create').should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + assertMaxLengthValidation: () => { + cy.log('persesCreateDashboardsPage.assertMaxLengthValidation'); + cy.byPFRole('dialog').find('h4').should('have.text', persesCreateDashboard.DIALOG_MAX_LENGTH_VALIDATION).should('be.visible'); + }, + + assertDuplicatedNameValidation: (dashboardName: string) => { + cy.log('persesCreateDashboardsPage.assertDuplicatedNameValidation'); + if (dashboardName.includes(' ')) { + cy.byPFRole('dialog').find('h4').should('have.text', persesCreateDashboard.DIALOG_DUPLICATED_NAME_BKD_VALIDATION).should('be.visible'); + } else { + cy.byPFRole('dialog').find(Classes.PersesCreateDashboardDashboardNameError).should('have.text', `${persesCreateDashboard.DIALOG_DUPLICATED_NAME_PF_VALIDATION_PREFIX}"${dashboardName}"${persesCreateDashboard.DIALOG_DUPLICATED_NAME_PF_VALIDATION_SUFFIX}`).should('be.visible'); + } + }, + +} \ No newline at end of file diff --git a/web/cypress/views/perses-dashboards-edit-datasources.ts b/web/cypress/views/perses-dashboards-edit-datasources.ts new file mode 100644 index 000000000..975d39250 --- /dev/null +++ b/web/cypress/views/perses-dashboards-edit-datasources.ts @@ -0,0 +1,95 @@ +import { commonPages } from "./common"; +import { persesAriaLabels, persesMUIDataTestIDs, editPersesDashboardsAddDatasource, IDs } from "../../src/components/data-test"; +import { persesDashboardsModalTitles, persesDashboardsRequiredFields } from "../fixtures/perses/constants"; + +export const persesDashboardsEditDatasources = { + + shouldBeLoaded: () => { + cy.log('persesDashboardsEditVariables.shouldBeLoaded'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.EDIT_DASHBOARD_DATASOURCES); + cy.byAriaLabel(persesAriaLabels.EditDashboardDatasourcesTable).should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('button').contains('Apply').should('be.visible').and('have.attr', 'disabled'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('button').contains('Cancel').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('button').contains('Add Datasource').should('be.visible'); + }, + + assertDatasource: (index: number, name: string, type: 'PrometheusDatasource' | 'TempoDatasource', description: string) => { + cy.log('persesDashboardsEditDatasources.assertDatasource'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('tbody').find('tr').eq(index).find('th').contains(name).should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('tbody').find('tr').eq(index).find('td').eq(0).contains(type).should('be.visible'); + if (description !== '') { + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('tbody').find('tr').eq(index).find('td').eq(1).contains(description).should('be.visible'); + } + }, + + assertDatasourceNotExist: (name: string) => { + cy.log('persesDashboardsEditDatasources.assertDatasource'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('th').contains(name).should('not.exist'); + }, + + clickButton: (button: 'Apply' | 'Cancel' | 'Add Datasource' | 'Add') => { + cy.log('persesDashboardsEditDatasources.clickButton'); + if (button === 'Cancel') { + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('button').contains(button).should('be.visible').click(); + cy.wait(1000); + cy.get('body').then((body) => { + if (body.find('#'+IDs.persesDashboardDiscardChangesDialog).length > 0 && body.find('#'+IDs.persesDashboardDiscardChangesDialog).is(':visible')) { + cy.bySemanticElement('button', 'Discard Changes').scrollIntoView().should('be.visible').click({ force: true }); + } + }); + } else { + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('button').contains(button).should('be.visible').click(); + } + }, + + addDatasource: (name: string, defaultDatasource: boolean, pluginOptions: 'Prometheus Datasource' | 'Tempo Datasource', displayLabel?: string, description?: string) => { + cy.log('persesDashboardsEditDatasources.addDatasource'); + cy.get('input[name="'+editPersesDashboardsAddDatasource.inputName+'"]').clear().type(name); + if (displayLabel !== undefined) { + cy.get('input[name="'+editPersesDashboardsAddDatasource.inputDisplayLabel+'"]').clear().type(displayLabel); + } + if (description !== undefined) { + cy.get('input[name="'+editPersesDashboardsAddDatasource.inputDescription+'"]').clear().type(description); + } + + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('input[name="'+editPersesDashboardsAddDatasource.inputDefaultDatasource+'"]').then((checkbox) => { + if ((checkbox.not(':checked') && defaultDatasource) || (checkbox.is(':checked') && !defaultDatasource)) { + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('input[name="'+editPersesDashboardsAddDatasource.inputDefaultDatasource+'"]').click(); + } + }); + + persesDashboardsEditDatasources.clickDropdownAndSelectOption('Source', pluginOptions); + + }, + + clickDropdownAndSelectOption: (label: string, option: string) => { + cy.log('persesDashboardsEditVariables.selectVariableType'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('label').contains(label).siblings('div').click(); + cy.get('li').contains(option).should('be.visible').click(); + }, + + assertRequiredFieldValidation: (field: string) => { + cy.log('persesDashboardsEditVariables.assertRequiredFieldValidation'); + + switch (field) { + case 'Name': + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('label').contains(field).siblings('p').should('have.text', persesDashboardsRequiredFields.AddVariableNameField); + break; + } + }, + + clickDiscardChangesButton: () => { + cy.log('persesDashboardsEditVariables.clickDiscardChangesButton'); + cy.bySemanticElement('button', 'Discard Changes').scrollIntoView().should('be.visible').click({ force: true }); + }, + + clickEditDatasourceButton: (index: number) => { + cy.log('persesDashboardsEditDatasources.clickEditDatasourceButton'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('[data-testid="'+persesMUIDataTestIDs.editDashboardEditVariableDatasourceEditButton+'"]').eq(index).should('be.visible').click(); + }, + + clickDeleteDatasourceButton: (index: number) => { + cy.log('persesDashboardsEditDatasources.clickDeleteDatasourceButton'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('[data-testid="'+persesMUIDataTestIDs.editDashboardEditVariableDatasourceDeleteButton+'"]').eq(index).should('be.visible').click(); + }, +} \ No newline at end of file diff --git a/web/cypress/views/perses-dashboards-edit-variables.ts b/web/cypress/views/perses-dashboards-edit-variables.ts new file mode 100644 index 000000000..b278ea7a8 --- /dev/null +++ b/web/cypress/views/perses-dashboards-edit-variables.ts @@ -0,0 +1,168 @@ +import { commonPages } from "./common"; +import { persesAriaLabels, persesMUIDataTestIDs, IDs, editPersesDashboardsAddVariable } from "../../src/components/data-test"; +import { persesDashboardsModalTitles, persesDashboardsAddListVariableSource, persesDashboardsAddListVariableSort, persesDashboardsRequiredFields } from "../fixtures/perses/constants"; + +export const persesDashboardsEditVariables = { + + shouldBeLoaded: () => { + cy.log('persesDashboardsEditVariables.shouldBeLoaded'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.EDIT_DASHBOARD_VARIABLES); + cy.byAriaLabel(persesAriaLabels.EditDashboardVariablesTable).should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('button').contains('Apply').should('be.visible').and('have.attr', 'disabled'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('button').contains('Cancel').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('button').contains('Add Variable').should('be.visible'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.DASHBOARD_BUILT_IN_VARIABLES); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('#'+IDs.persesDashboardEditVariablesModalBuiltinButton).should('have.attr', 'aria-expanded', 'false'); + }, + + clickButton: (button: 'Apply' | 'Cancel' | 'Add Variable' | 'Add' | 'Run Query') => { + cy.log('persesDashboardsEditVariables.clickButton'); + cy.wait(3000); + if (button === 'Cancel') { + cy.get('body').then((body) => { + if (body.find('#'+IDs.persesDashboardDiscardChangesDialog).length > 0 && body.find('#'+IDs.persesDashboardDiscardChangesDialog).is(':visible')) { + cy.bySemanticElement('button', 'Discard Changes').scrollIntoView().should('be.visible').click({ force: true }); + } + }); + } else { + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('button').contains(button).should('be.visible').click(); + } + }, + + addTextVariable: (name: string, constant: boolean, displayLabel?: string, description?: string, value?: string) => { + cy.log('persesDashboardsEditVariables.addTextVariable'); + cy.get('input[name="'+editPersesDashboardsAddVariable.inputName+'"]').clear().type(name); + + const displayLabelInput = displayLabel !== undefined ? displayLabel : name; + const descriptionInput = description !== undefined ? description : name; + const valueInput = value !== undefined ? value : ''; + + cy.get('input[name="'+editPersesDashboardsAddVariable.inputDisplayLabel+'"]').clear().type(displayLabelInput); + cy.get('input[name="'+editPersesDashboardsAddVariable.inputDescription+'"]').clear().type(descriptionInput); + cy.get('input[name="'+editPersesDashboardsAddVariable.inputValue+'"]').clear().type(valueInput); + if (constant) { + cy.get('input[name="'+editPersesDashboardsAddVariable.inputConstant+'"]').click(); + } + }, + + addListVariable: ( + name: string, + allowMultiple: boolean, + allowAllValue: boolean, + customAllValue?: string, + displayLabel?: string, + description?: string, + source?: persesDashboardsAddListVariableSource, + sort?: persesDashboardsAddListVariableSort) => { + cy.log('persesDashboardsEditVariables.addListVariable'); + cy.get('input[name="'+editPersesDashboardsAddVariable.inputName+'"]').clear().type(name); + + if (displayLabel !== undefined && displayLabel !== '') { + cy.get('input[name="'+editPersesDashboardsAddVariable.inputDisplayLabel+'"]').clear().type(displayLabel); + } + if (description !== undefined && description !== '' ) { + cy.get('input[name="'+editPersesDashboardsAddVariable.inputDescription+'"]').clear().type(description); + } + persesDashboardsEditVariables.clickDropdownAndSelectOption('Type', 'List'); + + if (source !== undefined) { + persesDashboardsEditVariables.clickDropdownAndSelectOption('Source', source); + } + if (sort !== undefined) { + persesDashboardsEditVariables.clickDropdownAndSelectOption('Sort', sort); + } + if (allowMultiple) { + cy.get('input[name="'+editPersesDashboardsAddVariable.inputAllowMultiple+'"]').click(); + } + if (allowAllValue) { + cy.get('input[name="'+editPersesDashboardsAddVariable.inputAllowAllValue+'"]').click(); + if (customAllValue !== undefined && customAllValue !== '') { + cy.get('input[name="'+editPersesDashboardsAddVariable.inputCustomAllValue+'"]').clear().type(customAllValue); + } + } + }, + + addListVariable_staticListVariable_enterValue: (value: string) => { + cy.log('persesDashboardsEditVariables.addListVariable_staticListVariable_enterValue'); + cy.wait(2000); + cy.get('h6').contains('List Options').next('div').eq(0).find('input[role="combobox"]').click().type(value+'{enter}'); + cy.wait(2000); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardAddVariableRunQueryButton).click(); + cy.wait(2000); + cy.get('h4').contains('Preview Values').parent('div').siblings('div').contains(value).should('be.visible'); + }, + + addListVariable_promLabelValuesVariable_enterLabelName: (labelName: string) => { + cy.log('persesDashboardsEditVariables.addListVariable_promLabelValuesVariable_enterLabelName'); + cy.wait(2000); + cy.get('label').contains('Label Name').next('div').find('input').click().type(labelName); + cy.wait(2000); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardAddVariableRunQueryButton).click(); + cy.wait(2000); + }, + + addListVariable_promLabelValuesVariable_addSeriesSelector: (seriesSelector: string) => { + cy.log('persesDashboardsEditVariables.addListVariable_promLabelValuesVariable_addSeriesSelector'); + cy.wait(2000); + cy.bySemanticElement('button', 'Add Series Selector').click(); + cy.get('label').contains('Series Selector').next('div').find('input').click().type(seriesSelector); + cy.wait(2000); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardAddVariableRunQueryButton).click(); + cy.wait(2000); + }, + + /** + * + * @param label - label of the dropdown + * @param option - option to select + */ + clickDropdownAndSelectOption: (label: string, option: string) => { + cy.log('persesDashboardsEditVariables.selectVariableType'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('label').contains(label).siblings('div').click(); + cy.get('li').contains(option).should('be.visible').click(); + }, + + assertRequiredFieldValidation: (field: string) => { + cy.log('persesDashboardsEditVariables.assertRequiredFieldValidation'); + + switch (field) { + case 'Name': + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('label').contains(field).siblings('p').should('have.text', persesDashboardsRequiredFields.AddVariableNameField); + break; + } + }, + + clickDiscardChangesButton: () => { + cy.log('persesDashboardsEditVariables.clickDiscardChangesButton'); + cy.bySemanticElement('button', 'Discard Changes').scrollIntoView().should('be.visible').click({ force: true }); + }, + + toggleVariableVisibility: (index: number, visible: boolean) => { + cy.log('persesDashboardsEditVariables.toggleVariableVisibility'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('input[type="checkbox"]').eq(index).then((checkbox) => { + if ((checkbox.not(':checked') && visible) || (checkbox.is(':checked') && !visible)) { + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('input[type="checkbox"]').eq(index).click(); + } + }); + }, + + moveVariableUp: (index: number) => { + cy.log('persesDashboardsEditVariables.moveVariableUp'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('[data-testid="'+persesMUIDataTestIDs.editDashboardEditVariableMoveUpButton+'"]').eq(index).should('be.visible').click(); + }, + + moveVariableDown: (index: number) => { + cy.log('persesDashboardsEditVariables.moveVariableDown'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('[data-testid="'+persesMUIDataTestIDs.editDashboardEditVariableMoveDownButton+'"]').eq(index).should('be.visible').click(); + }, + + clickEditVariableButton: (index: number) => { + cy.log('persesDashboardsEditVariables.clickEditVariableButton'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('[data-testid="'+persesMUIDataTestIDs.editDashboardEditVariableDatasourceEditButton+'"]').eq(index).should('be.visible').click(); + }, + + clickDeleteVariableButton: (index: number) => { + cy.log('persesDashboardsEditVariables.clickDeleteVariableButton'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('[data-testid="'+persesMUIDataTestIDs.editDashboardEditVariableDatasourceDeleteButton+'"]').eq(index).should('be.visible').click(); + }, +} \ No newline at end of file diff --git a/web/cypress/views/perses-dashboards-list-dashboards.ts b/web/cypress/views/perses-dashboards-list-dashboards.ts new file mode 100644 index 000000000..9886625f4 --- /dev/null +++ b/web/cypress/views/perses-dashboards-list-dashboards.ts @@ -0,0 +1,242 @@ +import { commonPages } from "./common"; +import { DataTestIDs, Classes, listPersesDashboardsOUIAIDs, listPersesDashboardsDataTestIDs, IDs, persesAriaLabels } from "../../src/components/data-test"; +import { listPersesDashboardsEmptyState, listPersesDashboardsPageSubtitle, persesDashboardsDuplicateDashboard, persesDashboardsRenameDashboard } from "../fixtures/perses/constants"; +import { MonitoringPageTitles } from "../fixtures/monitoring/constants"; + +export const listPersesDashboardsPage = { + + emptyState: () => { + cy.log('listPersesDashboardsPage.emptyState'); + cy.byTestID(listPersesDashboardsDataTestIDs.EmptyStateTitle).should('be.visible').contains(listPersesDashboardsEmptyState.TITLE); + cy.byTestID(listPersesDashboardsDataTestIDs.EmptyStateBody).should('be.visible').contains(listPersesDashboardsEmptyState.BODY); + cy.byTestID(listPersesDashboardsDataTestIDs.ClearAllFiltersButton).should('be.visible'); + }, + + shouldBeLoaded: () => { + cy.log('listPersesDashboardsPage.shouldBeLoaded'); + cy.byOUIAID(listPersesDashboardsOUIAIDs.PersesBreadcrumb).should('not.exist'); + commonPages.titleShouldHaveText(MonitoringPageTitles.DASHBOARDS); + cy.byOUIAID(listPersesDashboardsOUIAIDs.PageHeaderSubtitle).should('contain', listPersesDashboardsPageSubtitle).should('be.visible'); + cy.byTestID(DataTestIDs.PersesCreateDashboardButton).scrollIntoView().should('be.visible'); + cy.byTestID(DataTestIDs.FavoriteStarButton).should('be.visible'); + cy.byOUIAID(listPersesDashboardsOUIAIDs.PersesDashListDataViewTable).should('be.visible'); + + }, + + filter: { + byName: (name: string) => { + cy.log('listPersesDashboardsPage.filter.byName'); + cy.wait(1000); + cy.byOUIAID(listPersesDashboardsOUIAIDs.persesListDataViewFilters).contains('button',/Name|Project/).click( { force: true }); + cy.wait(1000); + cy.get(Classes.FilterDropdownOption).should('be.visible').contains('Name').click( { force: true }); + cy.wait(1000); + cy.byTestID(listPersesDashboardsDataTestIDs.NameFilter).should('be.visible').type(name); + cy.wait(1000); + cy.byTestID(listPersesDashboardsDataTestIDs.NameFilter).find('input').should('have.attr', 'value', name); + cy.wait(2000); + }, + byProject: (project: string) => { + cy.log('listPersesDashboardsPage.filter.byProject'); + cy.byOUIAID(listPersesDashboardsOUIAIDs.persesListDataViewFilters).contains('button',/Name|Project/).click( { force: true }); + cy.wait(1000); + cy.get(Classes.FilterDropdownOption).should('be.visible').contains('Project').click( { force: true }); + cy.wait(1000); + cy.byTestID(listPersesDashboardsDataTestIDs.ProjectFilter).should('be.visible').type(project); + cy.wait(1000); + cy.byTestID(listPersesDashboardsDataTestIDs.ProjectFilter).find('input').should('have.attr', 'value', project); + cy.wait(2000); + }, + }, + + countDashboards: (count: string) => { + cy.log('listPersesDashboardsPage.countDashboards'); + cy.wait(2000); + cy.get('#'+ IDs.persesDashboardCount,).find(Classes.PersesListDashboardCount).invoke('text').should((text) => { + const total = text.split('of')[1].trim(); + expect(total).to.equal(count); + }); + }, + + clearAllFilters: () => { + cy.log('listPersesDashboardsPage.clearAllFilters'); + cy.byOUIAID(listPersesDashboardsOUIAIDs.persesListDataViewHeaderClearAllFiltersButton).click(); + cy.wait(5000); + }, + + sortBy: (column: string) => { + cy.log('listPersesDashboardsPage.sortBy'); + cy.byOUIAID(listPersesDashboardsOUIAIDs.persesListDataViewHeaderSortButton).contains(column).scrollIntoView().click(); + }, + + /** + * If index is not provided, it asserts the existence of the dashboard by appending the name to the prefix to build data-test id, expecting to be unique + * If index is provided, it asserts the existence of the dashboard by the index. + * @param name - The name of the dashboard to assert + * @param index - The index of the dashboard to assert (optional) + */ + assertDashboardName: (name: string, index?: number) => { + cy.log('listPersesDashboardsPage.assertDashboardName'); + const idx = index !== undefined ? index : 0; + if (index === undefined) { + cy.byTestID(listPersesDashboardsDataTestIDs.DashboardLinkPrefix+name).should('be.visible').contains(name); + } else { + cy.byOUIAID(listPersesDashboardsOUIAIDs.persesListDataViewTableDashboardNameTD+idx.toString()).should('be.visible').contains(name); + } + }, + + clickDashboard: (name: string, index?: number) => { + const idx = index !== undefined ? index : 0; + cy.log('listPersesDashboardsPage.clickDashboard'); + // cy.byTestID(listPersesDashboardsDataTestIDs.DashboardLinkPrefix+name).eq(idx).should('be.visible').click(); + cy.get('a').contains(name).eq(idx).should('be.visible').click(); + cy.wait(15000); + }, + + removeTag: (value: string) => { + cy.log('listPersesDashboardsPage.removeTag'); + cy.byAriaLabel('Close '+ value).click(); + }, + + clickCreateButton: () => { + cy.log('persesDashboardsPage.clickCreateButton'); + cy.byTestID(DataTestIDs.PersesCreateDashboardButton).scrollIntoView().should('be.visible').and('not.have.attr', 'disabled'); + cy.byTestID(DataTestIDs.PersesCreateDashboardButton).click({ force: true }); + cy.wait(2000); + }, + + assertCreateButtonIsEnabled: () => { + cy.log('persesDashboardsPage.assertCreateButtonIsEnabled'); + cy.byTestID(DataTestIDs.PersesCreateDashboardButton).scrollIntoView().should('be.visible').should('not.have.attr', 'disabled'); + }, + + assertCreateButtonIsDisabled: () => { + cy.log('persesDashboardsPage.assertCreateButtonIsDisabled'); + cy.byTestID(DataTestIDs.PersesCreateDashboardButton).scrollIntoView().should('be.visible').should('have.attr', 'disabled'); + }, + + clickKebabIcon: (index?: number) => { + const idx = index !== undefined ? index : 0; + cy.log('persesDashboardsPage.clickKebabIcon'); + cy.byAriaLabel(persesAriaLabels.persesDashboardKebabIcon).eq(idx).scrollIntoView().should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + assertKebabIconOptions: () => { + cy.log('persesDashboardsPage.assertKebabIconOptions'); + cy.byPFRole('menuitem').contains('Rename dashboard').should('be.visible'); + cy.byPFRole('menuitem').contains('Duplicate dashboard').should('be.visible'); + cy.byPFRole('menuitem').contains('Delete dashboard').should('be.visible'); + }, + + assertKebabIconDisabled: () => { + cy.log('persesDashboardsPage.assertKebabIconDisabled'); + cy.byAriaLabel(persesAriaLabels.persesDashboardKebabIcon).scrollIntoView().should('be.visible').should('have.attr', 'disabled'); + }, + + clickRenameDashboardOption: () => { + cy.log('listPersesDashboardsPage.clickRenameDashboardOption'); + cy.wait(1000); + cy.byPFRole('menuitem').contains('Rename dashboard').should('be.visible').click({ force: true }); + cy.wait(1000); + }, + + renameDashboardEnterName: (name: string) => { + cy.log('listPersesDashboardsPage.renameDashboardEnterName'); + cy.get('#'+IDs.persesDashboardRenameDashboardName).should('be.visible').clear().type(name); + cy.wait(1000); + }, + + renameDashboardCancelButton: () => { + cy.log('listPersesDashboardsPage.renameDashboardCancel'); + cy.byPFRole('dialog').find('button').contains('Cancel').should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + renameDashboardRenameButton: () => { + cy.log('listPersesDashboardsPage.renameDashboardRename'); + cy.byPFRole('dialog').find('button').contains('Rename').should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + assertRenameDashboardMaxLength: () => { + cy.log('listPersesDashboardsPage.assertRenameDashboardMaxLength'); + cy.byPFRole('dialog').find(Classes.PersesCreateDashboardDashboardNameError).should('have.text', persesDashboardsRenameDashboard.DIALOG_MAX_LENGTH_VALIDATION).should('be.visible'); + }, + + clickDuplicateOption: () => { + cy.log('listPersesDashboardsPage.clickDuplicateOption'); + cy.byPFRole('menuitem').contains('Duplicate dashboard').should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + assertDuplicateProjectDropdown: (project: string) => { + cy.log('listPersesDashboardsPage.assertDuplicateProjectDropdown'); + cy.get(Classes.PersesCreateDashboardProjectDropdown).should('be.visible').click({ force: true }); + cy.byPFRole('option').contains(project).should('be.visible'); + cy.get(Classes.PersesCreateDashboardProjectDropdown).should('be.visible').click({ force: true }); + }, + + duplicateDashboardEnterName: (name: string) => { + cy.log('listPersesDashboardsPage.duplicateDashboardEnterName'); + cy.get('#' + IDs.persesDashboardDuplicateDashboardName).should('be.visible').clear().type(name); + cy.wait(1000); + }, + + duplicateDashboardCancelButton: () => { + cy.log('listPersesDashboardsPage.duplicateDashboardCancel'); + cy.byPFRole('dialog').find('button').contains('Cancel').should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + duplicateDashboardDuplicateButton: () => { + cy.log('listPersesDashboardsPage.duplicateDashboardDuplicate'); + cy.byPFRole('dialog').find('button').contains('Duplicate').should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + assertDuplicateDashboardAlreadyExists: () => { + cy.log('listPersesDashboardsPage.assertDuplicateDashboardAlreadyExists'); + cy.byPFRole('dialog').find(Classes.PersesCreateDashboardDashboardNameError) + .contains(persesDashboardsDuplicateDashboard.DIALOG_DUPLICATED_NAME_VALIDATION) + .should('be.visible'); + }, + + duplicateDashboardSelectProjectDropdown: (project: string) => { + cy.log('listPersesDashboardsPage.duplicateDashboardSelectProjectDropdown'); + cy.get(Classes.PersesCreateDashboardProjectDropdown).should('be.visible').click({ force: true }); + cy.byPFRole('option').contains(project).should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + assertDuplicateProjectDropdownOptions: (project: string, contains: boolean) => { + cy.log('listPersesDashboardsPage.assertDuplicateProjectDropdownOptions'); + cy.get(Classes.PersesCreateDashboardProjectDropdown).should('be.visible').click({ force: true }); + if (contains) { + cy.byPFRole('option').contains(project).should('be.visible'); + cy.log('Project: ' + project + ' is available in the dropdown'); + } else { + cy.byPFRole('option').should('not.contain', project); + cy.log('Project: ' + project + ' is not available in the dropdown'); + } + cy.get(Classes.PersesCreateDashboardProjectDropdown).should('be.visible').click({ force: true }); + }, + + clickDeleteOption: () => { + cy.log('listPersesDashboardsPage.clickDeleteOption'); + cy.byPFRole('menuitem').contains('Delete dashboard').should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + deleteDashboardCancelButton: () => { + cy.log('listPersesDashboardsPage.deleteDashboardCancel'); + cy.byPFRole('dialog').find('button').contains('Cancel').should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + deleteDashboardDeleteButton: () => { + cy.log('listPersesDashboardsPage.deleteDashboardDelete'); + cy.byPFRole('dialog').find('button').contains('Delete').should('be.visible').click({ force: true }); + cy.wait(2000); + }, +} \ No newline at end of file diff --git a/web/cypress/views/perses-dashboards-panel.ts b/web/cypress/views/perses-dashboards-panel.ts new file mode 100644 index 000000000..7ee5a096d --- /dev/null +++ b/web/cypress/views/perses-dashboards-panel.ts @@ -0,0 +1,169 @@ +import { commonPages } from "./common"; +import { persesAriaLabels, IDs, editPersesDashboardsAddPanel, Classes } from "../../src/components/data-test"; +import { persesDashboardsModalTitles, persesDashboardsAddPanelAddQueryType, persesDashboardsAddListPanelType } from "../fixtures/perses/constants"; + +export const persesDashboardsPanel = { + + addPanelShouldBeLoaded: () => { + cy.log('persesDashboardsPanel.addPanelShouldBeLoaded'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.ADD_PANEL); + cy.get('input[name="' + editPersesDashboardsAddPanel.inputName + '"]').should('be.visible'); + cy.get('#' + IDs.persesDashboardAddPanelForm).find('label').contains('Group').should('be.visible'); + cy.get('input[name="' + editPersesDashboardsAddPanel.inputDescription + '"]').should('be.visible'); + cy.get('#' + IDs.persesDashboardAddPanelForm).find('label').contains('Type').should('be.visible'); + cy.get('#' + IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Add').should('be.visible').and('have.attr', 'disabled'); + cy.get('#' + IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Cancel').should('be.visible'); + }, + + clickButton: (button: 'Add' | 'Cancel') => { + cy.log('persesDashboardsPanel.clickButton'); + if (button === 'Cancel') { + cy.get('#' + IDs.persesDashboardAddPanelForm).siblings('div').find('button').contains(button).should('be.visible').click(); + cy.wait(1000); + cy.get('body').then((body) => { + if (body.find('#' + IDs.persesDashboardDiscardChangesDialog).length > 0 && body.find('#' + IDs.persesDashboardDiscardChangesDialog).is(':visible')) { + cy.bySemanticElement('button', 'Discard Changes').scrollIntoView().should('be.visible').click({ force: true }); + } + }); + } else { + cy.get('#' + IDs.persesDashboardAddPanelForm).siblings('div').find('button').contains(button).should('be.visible').click(); + } + }, + + clickDropdownAndSelectOption: (label: string, option: string) => { + cy.log('persesDashboardsPanel.clickDropdownAndSelectOption'); + cy.get('#' + IDs.persesDashboardAddPanelForm).find('label').contains(label).siblings('div').click(); + cy.wait(1000); + cy.get('li').contains(new RegExp(`^${option}$`)).should('be.visible').click(); + }, + + assertRequiredFieldValidation: (field: string) => { + cy.log('persesDashboardsPanel.assertRequiredFieldValidation'); + + switch (field) { + case 'Name': + cy.get('#' + IDs.persesDashboardAddPanelForm).find('label').contains(field).siblings('p').should('have.text', 'Required'); + break; + } + }, + + addPanel: (name: string, group: string, type: string, description?: string, query?: string | 'up' | 'haproxy_up', legend?: string) => { + cy.log('persesDashboardsPanel.addPanel'); + cy.wait(2000); + cy.get('input[name="' + editPersesDashboardsAddPanel.inputName + '"]').clear().type(name); + if (description !== undefined && description !== '') { + cy.get('input[name="' + editPersesDashboardsAddPanel.inputDescription + '"]').clear().type(description); + } + persesDashboardsPanel.clickDropdownAndSelectOption('Group', group); + + cy.wait(1000); + persesDashboardsPanel.clickDropdownAndSelectOption('Type', type); + + switch (type) { + //BAR_GAUGE_HEAT_HISTOGRAM_PIE_STAT_STATUS_TABLE_TIMESERIES + case persesDashboardsAddListPanelType.BAR_CHART: + // case persesDashboardsAddListPanelType.HEATMAP_CHART: + // case persesDashboardsAddListPanelType.HISTOGRAM_CHART: + // case persesDashboardsAddListPanelType.PIE_CHART: + // case persesDashboardsAddListPanelType.STAT_CHART: + case persesDashboardsAddListPanelType.STATUS_HISTORY_CHART: + case persesDashboardsAddListPanelType.TABLE: + case persesDashboardsAddListPanelType.TIME_SERIES_CHART: + case persesDashboardsAddListPanelType.TIME_SERIES_TABLE: + + cy.wait(2000); + persesDashboardsPanel.clickDropdownAndSelectOption('Query Type', persesDashboardsAddPanelAddQueryType.BAR_GAUGE_HEAT_HISTOGRAM_PIE_STAT_STATUS_TABLE_TIMESERIES.PROMETHEUS_TIME_SERIES_QUERY); + cy.wait(2000); + if (query !== undefined && query !== '') { + persesDashboardsPanel.enterPromQLQuery(query); + } + else { + persesDashboardsPanel.enterPromQLQuery('up'); + } + if (legend !== undefined && legend !== '') { + cy.get('label').contains('Legend').next('div').find('input').click().type(legend); + } + break; + } + cy.get('#'+IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Add').should('be.visible').click(); + }, + + enterPromQLQuery: (query: string | 'up' | 'haproxy_up') => { + cy.log('persesDashboardsPanel.enterPromQLQuery'); + cy.get('[data-testid="promql_expression_editor"] .cm-line') + .then(($el) => { + $el[0].textContent = `${query}`; + $el[0].dispatchEvent(new Event('input', { bubbles: true })); + $el[0].dispatchEvent(new Event('blur', { bubbles: true })); + }); + cy.wait(3000); + cy.get('body').then(($body) => { + const $el = $body.find('[data-testid="promql_expression_editor"] .cm-tooltip-autocomplete.cm-tooltip.cm-tooltip-below li[aria-selected="true"]'); + if ($el.length > 0) { + // Use native DOM events since $el[0] is a raw DOM element + $el[0].dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true })); + $el[0].dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); + } + }); + + cy.wait(3000); + cy.get('[data-testid="promql_expression_editor"] .cm-line').click(); + cy.wait(3000); + cy.bySemanticElement('button', 'Run Query').scrollIntoView().should('be.visible').click({ force: true }); + cy.wait(3000); + }, + + editPanelShouldBeLoaded: () => { + cy.log('persesDashboardsPanel.editPanelShouldBeLoaded'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.ADD_PANEL); + cy.get('input[name="' + editPersesDashboardsAddPanel.inputName + '"]').should('be.visible'); + cy.get('#' + IDs.persesDashboardAddPanelForm).find('label').contains('Group').should('be.visible'); + cy.get('input[name="' + editPersesDashboardsAddPanel.inputDescription + '"]').should('be.visible'); + cy.get('#' + IDs.persesDashboardAddPanelForm).find('label').contains('Type').should('be.visible'); + cy.get('#' + IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Apply').should('be.visible').and('have.attr', 'disabled'); + cy.get('#' + IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Cancel').should('be.visible'); + }, + + editPanel: (name: string, group: string, type: string, description?: string) => { + cy.log('persesDashboardsPanel.editPanel'); + cy.get('input[name="' + editPersesDashboardsAddPanel.inputName + '"]').clear().type(name); + if (description !== undefined && description !== '') { + cy.get('input[name="' + editPersesDashboardsAddPanel.inputDescription + '"]').clear().type(description); + } + persesDashboardsPanel.clickDropdownAndSelectOption('Group', group); + persesDashboardsPanel.clickDropdownAndSelectOption('Type', type); + cy.get('#' + IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Apply').should('be.visible').click(); + }, + + clickPanelGroupAction: (panelGroup: string, button: 'addPanel' | 'edit' | 'delete' | 'moveDown' | 'moveUp') => { + cy.log('persesDashboardsPage.clickPanelActions'); + + switch (button) { + case 'addPanel': + cy.byAriaLabel(persesAriaLabels.AddPanelToGroupPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'edit': + cy.byAriaLabel(persesAriaLabels.EditPanelGroupPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'delete': + cy.byAriaLabel(persesAriaLabels.DeletePanelGroupPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'moveDown': + cy.byAriaLabel(persesAriaLabels.MovePanelGroupPrefix + panelGroup + persesAriaLabels.MovePanelGroupDownSuffix).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'moveUp': + cy.byAriaLabel(persesAriaLabels.MovePanelGroupPrefix + panelGroup + persesAriaLabels.MovePanelGroupUpSuffix).scrollIntoView().should('be.visible').click({ force: true }); + break; + } + }, + + deletePanel: (panel: string) => { + cy.log('persesDashboardsPage.deletePanel'); + cy.byAriaLabel(persesAriaLabels.EditPanelDeleteButtonPrefix + panel).scrollIntoView().should('be.visible').click({ force: true }); + }, + + clickDeletePanelButton: () => { + cy.log('persesDashboardsPage.clickDeletePanelButton'); + cy.bySemanticElement('button', 'Delete').scrollIntoView().should('be.visible').click({ force: true }); + }, +} \ No newline at end of file diff --git a/web/cypress/views/perses-dashboards-panelgroup.ts b/web/cypress/views/perses-dashboards-panelgroup.ts new file mode 100644 index 000000000..02cfdb7ae --- /dev/null +++ b/web/cypress/views/perses-dashboards-panelgroup.ts @@ -0,0 +1,96 @@ +import { commonPages } from "./common"; +import { persesAriaLabels, persesMUIDataTestIDs, IDs } from "../../src/components/data-test"; +import { persesDashboardsModalTitles, persesDashboardsRequiredFields } from "../fixtures/perses/constants"; + +export const persesDashboardsPanelGroup = { + + addPanelGroupShouldBeLoaded: () => { + cy.log('persesDashboardsPanelGroup.addPanelGroupShouldBeLoaded'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.ADD_PANEL_GROUP); + cy.byDataTestID(persesMUIDataTestIDs.addPanelGroupFormName).should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).find('input').eq(1).should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).find('input').eq(2).should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).parent('div').siblings('div').find('button').contains('Apply').should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).parent('div').siblings('div').find('button').contains('Cancel').should('be.visible'); + }, + + clickButton: (button: 'Add' | 'Cancel') => { + cy.log('persesDashboardsPanelGroup.clickButton'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).parent('div').siblings('div').find('button').contains(button).should('be.visible').click(); + }, + + assertRequiredFieldValidation: (field: string) => { + cy.log('persesDashboardsPanelGroup.assertRequiredFieldValidation'); + + switch (field) { + case 'Name': + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('label').contains(field).siblings('p').should('have.text', persesDashboardsRequiredFields.AddVariableNameField); + break; + } + }, + + addPanelGroup: (name: string, collapse_state: 'Open' | 'Closed', repeat_variable: string) => { + cy.log('persesDashboardsPanelGroup.addPanelGroup'); + cy.wait(2000); + cy.byDataTestID(persesMUIDataTestIDs.addPanelGroupFormName).find('input').clear().type(name); + cy.byPFRole('dialog').find('div[role="combobox"]').eq(0).click(); + cy.byPFRole('option').contains(collapse_state).click(); + if (repeat_variable !== undefined && repeat_variable !== '') { + cy.byPFRole('dialog').find('div[role="combobox"]').eq(1).click(); + cy.byPFRole('option').contains(repeat_variable).click(); + } + cy.byPFRole('dialog').find('button').contains('Add').should('be.visible').click({ force: true }); + }, + + editPanelGroupShouldBeLoaded: () => { + cy.log('persesDashboardsPanelGroup.editPanelGroupShouldBeLoaded'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.EDIT_PANEL_GROUP); + cy.byDataTestID(persesMUIDataTestIDs.addPanelGroupFormName).should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).find('input').eq(1).should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).find('input').eq(2).should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).parent('div').siblings('div').find('button').contains('Apply').should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).parent('div').siblings('div').find('button').contains('Cancel').should('be.visible'); + }, + + editPanelGroup: (name: string, collapse_state: 'Open' | 'Closed', repeat_variable: string) => { + cy.log('persesDashboardsPanelGroup.editPanelGroup'); + cy.byDataTestID(persesMUIDataTestIDs.addPanelGroupFormName).find('input').clear().type(name); + cy.byPFRole('dialog').find('div[role="combobox"]').eq(0).click(); + cy.byPFRole('option').contains(collapse_state).click(); + if (repeat_variable !== undefined && repeat_variable !== '') { + cy.byPFRole('dialog').find('div[role="combobox"]').eq(1).click(); + cy.byPFRole('option').contains(repeat_variable).click(); + } + cy.bySemanticElement('button', 'Apply').should('be.visible').click(); + }, + + clickPanelGroupAction: (panelGroup: string, button: 'addPanel' | 'edit' | 'delete' | 'moveDown' | 'moveUp') => { + cy.log('persesDashboardsPage.clickPanelActions'); + + switch (button) { + case 'addPanel': + cy.byAriaLabel(persesAriaLabels.AddPanelToGroupPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'edit': + cy.byAriaLabel(persesAriaLabels.EditPanelGroupPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'delete': + cy.byAriaLabel(persesAriaLabels.DeletePanelGroupPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'moveDown': + cy.byAriaLabel(persesAriaLabels.MovePanelGroupPrefix + panelGroup + persesAriaLabels.MovePanelGroupDownSuffix).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'moveUp': + cy.byAriaLabel(persesAriaLabels.MovePanelGroupPrefix + panelGroup + persesAriaLabels.MovePanelGroupUpSuffix).scrollIntoView().should('be.visible').click({ force: true }); + break; + } + + }, + + clickDeletePanelGroupButton: () => { + cy.log('persesDashboardsPage.clickDeletePanelGroupButton'); + cy.bySemanticElement('button', 'Delete').scrollIntoView().should('be.visible').click({ force: true }); + }, + + +} \ No newline at end of file diff --git a/web/cypress/views/perses-dashboards.ts b/web/cypress/views/perses-dashboards.ts index 9448cd1af..cf10a44d2 100644 --- a/web/cypress/views/perses-dashboards.ts +++ b/web/cypress/views/perses-dashboards.ts @@ -1,6 +1,7 @@ import { commonPages } from "./common"; -import { DataTestIDs, Classes, LegacyTestIDs, persesAriaLabels, persesDataTestIDs } from "../../src/components/data-test"; +import { DataTestIDs, Classes, LegacyTestIDs, persesAriaLabels, persesMUIDataTestIDs, listPersesDashboardsOUIAIDs, IDs, persesDashboardDataTestIDs, listPersesDashboardsDataTestIDs } from "../../src/components/data-test"; import { MonitoringPageTitles } from "../fixtures/monitoring/constants"; +import { listPersesDashboardsPageSubtitle, persesDashboardsEmptyDashboard, persesDashboardsModalTitles } from "../fixtures/perses/constants"; import { persesDashboardsTimeRange, persesDashboardsRefreshInterval, persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev, persesDashboardsAcceleratorsCommonMetricsPanels } from "../fixtures/perses/constants"; export const persesDashboardsPage = { @@ -8,83 +9,170 @@ export const persesDashboardsPage = { shouldBeLoaded: () => { cy.log('persesDashboardsPage.shouldBeLoaded'); commonPages.titleShouldHaveText(MonitoringPageTitles.DASHBOARDS); - cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).contains(persesDashboardsTimeRange.LAST_30_MINUTES).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.ZoomInButton).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.ZoomOutButton).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.RefreshButton).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).contains(persesDashboardsRefreshInterval.OFF).should('be.visible'); - cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('input').should('be.visible'); - cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').should('be.visible'); - cy.byLegacyTestID(LegacyTestIDs.PersesDashboardSection).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).contains(persesDashboardsTimeRange.LAST_30_MINUTES).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.ZoomInButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.ZoomOutButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.RefreshButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).contains(persesDashboardsRefreshInterval.OFF).scrollIntoView().should('be.visible'); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('input').scrollIntoView().should('be.visible'); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').scrollIntoView().should('be.visible'); + cy.byLegacyTestID(LegacyTestIDs.PersesDashboardSection).scrollIntoView().should('be.visible'); }, + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + shouldBeLoaded1: () => { + cy.log('persesDashboardsPage.shouldBeLoaded'); + commonPages.titleShouldHaveText(MonitoringPageTitles.DASHBOARDS); + cy.byOUIAID(listPersesDashboardsOUIAIDs.PageHeaderSubtitle).scrollIntoView().should('contain', listPersesDashboardsPageSubtitle).should('be.visible'); + + cy.byTestID(persesDashboardDataTestIDs.editDashboardButtonToolbar).scrollIntoView().should('be.visible'); + + cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).contains(persesDashboardsTimeRange.LAST_30_MINUTES).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.ZoomInButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.ZoomOutButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.RefreshButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).contains(persesDashboardsRefreshInterval.OFF).scrollIntoView().should('be.visible'); + + cy.get('#' + IDs.persesDashboardDownloadButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.ViewJSONButton).scrollIntoView().should('be.visible'); + + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('input').scrollIntoView().should('be.visible'); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').scrollIntoView().should('be.visible'); + }, + + shouldBeLoadedEditionMode: (dashboardName: string) => { + cy.log('persesDashboardsPage.shouldBeLoadedEditionMode'); + cy.wait(10000); + commonPages.titleShouldHaveText(MonitoringPageTitles.DASHBOARDS); + cy.byOUIAID(listPersesDashboardsOUIAIDs.PageHeaderSubtitle).scrollIntoView().should('contain', listPersesDashboardsPageSubtitle).should('be.visible'); + // cy.byTestID(listPersesDashboardsDataTestIDs.PersesBreadcrumbDashboardNameItem).scrollIntoView().should('contain', dashboardName.toLowerCase().replace(/ /g, '_')).should('be.visible'); + cy.byTestID(listPersesDashboardsDataTestIDs.PersesBreadcrumbDashboardNameItem).scrollIntoView().should('contain', dashboardName).should('be.visible'); + persesDashboardsPage.assertEditModeButtons(); + + cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).contains(persesDashboardsTimeRange.LAST_30_MINUTES).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.ZoomInButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.ZoomOutButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.RefreshButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).contains(persesDashboardsRefreshInterval.OFF).scrollIntoView().should('be.visible'); + + cy.get('#' + IDs.persesDashboardDownloadButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.EditJSONButton).scrollIntoView().should('be.visible'); + + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('input').scrollIntoView().should('be.visible'); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('input').should('have.value', dashboardName); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').scrollIntoView().should('be.visible'); + + }, + + shouldBeLoadedEditionModeFromCreateDashboard: () => { + cy.log('persesDashboardsPage.shouldBeLoadedEditionModeFromCreateDashboard'); + cy.wait(10000); + cy.get('h2').contains(persesDashboardsEmptyDashboard.TITLE).scrollIntoView().should('be.visible'); + cy.get('p').contains(persesDashboardsEmptyDashboard.DESCRIPTION).scrollIntoView().should('be.visible'); + + cy.get('h2').siblings('div').find('[aria-label="Add panel"]').scrollIntoView().should('be.visible'); + cy.get('h2').siblings('div').find('[aria-label="Edit variables"]').scrollIntoView().should('be.visible'); + }, + + shouldBeLoadedAfterRename: (dashboardName: string) => { + cy.log('persesDashboardsPage.shouldBeLoadedAfterRename'); + persesDashboardsPage.shouldBeLoadedAfter(dashboardName); + }, + + shouldBeLoadedAfterDuplicate: (dashboardName: string) => { + cy.log('persesDashboardsPage.shouldBeLoadedAfterDuplicate'); + persesDashboardsPage.shouldBeLoadedAfter(dashboardName); + }, + + shouldBeLoadedAfter: (dashboardName: string) => { + cy.log('persesDashboardsPage.shouldBeLoadedAfter'); + cy.byTestID(listPersesDashboardsDataTestIDs.PersesBreadcrumbDashboardNameItem).scrollIntoView().should('contain', dashboardName).should('be.visible'); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('input').should('have.value', dashboardName); + }, + clickTimeRangeDropdown: (timeRange: persesDashboardsTimeRange) => { cy.log('persesDashboardsPage.clickTimeRangeDropdown'); - cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).should('be.visible').click({force: true}); - cy.byPFRole('option').contains(timeRange).should('be.visible').click({force: true}); + cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).scrollIntoView().should('be.visible').click({ force: true }); + cy.byPFRole('option').contains(timeRange).scrollIntoView().should('be.visible').click({ force: true }); }, timeRangeDropdownAssertion: () => { cy.log('persesDashboardsPage.timeRangeDropdownAssertion'); - cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).should('be.visible').click({force: true}); + cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).scrollIntoView().should('be.visible').click({ force: true }); const timeRanges = Object.values(persesDashboardsTimeRange); timeRanges.forEach((timeRange) => { cy.log('Time range: ' + timeRange); - cy.byPFRole('option').contains(timeRange).should('be.visible'); + cy.byPFRole('option').contains(timeRange).scrollIntoView().should('be.visible'); }); - cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).should('be.visible').click({force: true}); + cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).scrollIntoView().should('be.visible').click({ force: true }); }, clickRefreshButton: () => { cy.log('persesDashboardsPage.clickRefreshButton'); - cy.byAriaLabel(persesAriaLabels.RefreshButton).should('be.visible').click(); + cy.byAriaLabel(persesAriaLabels.RefreshButton).scrollIntoView().should('be.visible').click(); }, clickRefreshIntervalDropdown: (interval: persesDashboardsRefreshInterval) => { cy.log('persesDashboardsPage.clickRefreshIntervalDropdown'); - cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).should('be.visible').click({force: true}); - cy.byPFRole('option').contains(interval).should('be.visible').click({force: true}); + cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).scrollIntoView().should('be.visible').click({ force: true }); + cy.byPFRole('option').contains(interval).scrollIntoView().should('be.visible').click({ force: true }); }, refreshIntervalDropdownAssertion: () => { cy.log('persesDashboardsPage.refreshIntervalDropdownAssertion'); - cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).should('be.visible').click({force: true}); + cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).scrollIntoView().should('be.visible').click({ force: true }); const intervals = Object.values(persesDashboardsRefreshInterval); intervals.forEach((interval) => { cy.log('Refresh interval: ' + interval); - cy.byPFRole('option').contains(interval).should('be.visible'); + cy.byPFRole('option').contains(interval).scrollIntoView().should('be.visible'); }); //Closing the dropdown by clicking on the OFF option, because the dropdown is not accessible while the menu is open, even forcing it - cy.byPFRole('option').contains(persesDashboardsRefreshInterval.OFF).should('be.visible').click({force: true}); - + cy.byPFRole('option').contains(persesDashboardsRefreshInterval.OFF).scrollIntoView().should('be.visible').click({ force: true }); + }, clickDashboardDropdown: (dashboard: keyof typeof persesDashboardsDashboardDropdownCOO | keyof typeof persesDashboardsDashboardDropdownPersesDev) => { cy.log('persesDashboardsPage.clickDashboardDropdown'); - cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').should('be.visible').click({force: true}); - cy.byPFRole('option').contains(dashboard).should('be.visible').click({force: true}); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').scrollIntoView().should('be.visible').click({ force: true }); + cy.byPFRole('option').contains(dashboard).should('be.visible').click({ force: true }); }, dashboardDropdownAssertion: (constants: typeof persesDashboardsDashboardDropdownCOO | typeof persesDashboardsDashboardDropdownPersesDev) => { cy.log('persesDashboardsPage.dashboardDropdownAssertion'); - cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').should('be.visible').click({force: true}); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').scrollIntoView().should('be.visible').click({ force: true }); const dashboards = Object.values(constants); dashboards.forEach((dashboard) => { cy.log('Dashboard: ' + dashboard[0]); - cy.get(Classes.MenuItem).contains(dashboard[0]).should('be.visible'); + cy.get(Classes.MenuItem).contains(dashboard[0]).scrollIntoView().should('be.visible'); if (dashboard[1] !== '') { - cy.get(Classes.MenuItem).should('contain', dashboard[0]).and('contain', dashboard[1]); + cy.get(Classes.MenuItem).scrollIntoView().should('contain', dashboard[0]).and('contain', dashboard[1]); } }); cy.wait(1000); - cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').should('be.visible').click({force: true}); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').scrollIntoView().should('be.visible').click({ force: true }); }, - panelGroupHeaderAssertion: (panelGroupHeader: string) => { + panelGroupHeaderAssertion: (panelGroupHeader: string, collapse_state: 'Open' | 'Closed') => { cy.log('persesDashboardsPage.panelGroupHeaderAssertion'); - cy.byDataTestID(persesDataTestIDs.panelGroupHeader).contains(panelGroupHeader).should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.panelGroupHeader).contains(panelGroupHeader).scrollIntoView().should('be.visible'); + if (collapse_state === 'Open') { + cy.byAriaLabel(persesAriaLabels.CollapseGroupButtonPrefix + panelGroupHeader).scrollIntoView().should('be.visible'); + } else { + cy.byAriaLabel(persesAriaLabels.OpenGroupButtonPrefix + panelGroupHeader).scrollIntoView().should('be.visible'); + } + }, + + assertPanelGroupNotExist: (panelGroup: string) => { + cy.log('persesDashboardsPage.assertPanelGroupNotExist'); + cy.byAriaLabel(persesAriaLabels.OpenGroupButtonPrefix + panelGroup).should('not.exist'); + cy.byAriaLabel(persesAriaLabels.CollapseGroupButtonPrefix + panelGroup).should('not.exist'); + }, + + assertPanelGroupOrder: (panelGroup: string, order: number) => { + cy.log('persesDashboardsPage.assertPanelGroupOrder'); + cy.byDataTestID(persesMUIDataTestIDs.panelGroupHeader).eq(order).find('h2').contains(panelGroup).scrollIntoView().should('be.visible'); }, panelHeadersAcceleratorsCommonMetricsAssertion: () => { @@ -93,34 +181,289 @@ export const persesDashboardsPage = { const panels = Object.values(persesDashboardsAcceleratorsCommonMetricsPanels); panels.forEach((panel) => { cy.log('Panel: ' + panel); - cy.byDataTestID(persesDataTestIDs.panelHeader).find('h6').contains(panel).scrollIntoView().should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(panel).scrollIntoView().should('be.visible'); }); }, - expandPanel: (panel: keyof typeof persesDashboardsAcceleratorsCommonMetricsPanels | string) => { + expandPanel: (panel: string) => { cy.log('persesDashboardsPage.expandPanel'); - cy.byDataTestID(persesDataTestIDs.panelHeader).find('h6').contains(panel).scrollIntoView().siblings('div').eq(2).find('[data-testid="ArrowExpandIcon"]').click({force: true}); + persesDashboardsPage.clickPanelAction(panel, 'expand'); }, - collapsePanel: (panel: keyof typeof persesDashboardsAcceleratorsCommonMetricsPanels | string) => { + collapsePanel: (panel: string) => { cy.log('persesDashboardsPage.collapsePanel'); - cy.byDataTestID(persesDataTestIDs.panelHeader).find('h6').contains(panel).scrollIntoView().siblings('div').eq(2).find('[data-testid="ArrowCollapseIcon"]').click({force: true}); + persesDashboardsPage.clickPanelAction(panel, 'collapse'); + }, + + expandPanelGroup: (panelGroup: string) => { + cy.log('persesDashboardsPage.expandPanelGroup'); + cy.byAriaLabel(persesAriaLabels.OpenGroupButtonPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + }, + + collapsePanelGroup: (panelGroup: string) => { + cy.log('persesDashboardsPage.collapsePanelGroup'); + cy.byAriaLabel(persesAriaLabels.CollapseGroupButtonPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); }, statChartValueAssertion: (panel: keyof typeof persesDashboardsAcceleratorsCommonMetricsPanels | string, noData: boolean) => { cy.log('persesDashboardsPage.statChartValueAssertion'); cy.wait(2000); if (noData) { - cy.byDataTestID(persesDataTestIDs.panelHeader).find('h6').contains(panel).scrollIntoView().parents('header').siblings('figure').find('p').should('contain', 'No data').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(panel).scrollIntoView().parents('header').siblings('figure').find('p').should('contain', 'No data').should('be.visible'); } else { - cy.byDataTestID(persesDataTestIDs.panelHeader).find('h6').contains(panel).scrollIntoView().parents('header').siblings('figure').find('h3').should('not.contain', 'No data').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(panel).scrollIntoView().parents('header').siblings('figure').find('h3').should('not.contain', 'No data').should('be.visible'); } }, searchAndSelectVariable: (variable: string, value: string) => { cy.log('persesDashboardsPage.searchAndSelectVariable'); - cy.byDataTestID(persesDataTestIDs.variableDropdown+'-'+variable).find('input').type(value); - cy.byPFRole('option').contains(value).click({force: true}); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown + '-' + variable).find('input').type(value); + cy.byPFRole('option').contains(value).click({ force: true }); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown + '-' + variable).find('button').click({ force: true }); + cy.wait(1000); + }, + + searchAndTypeVariable: (variable: string, value: string) => { + cy.log('persesDashboardsPage.searchAndTypeVariable'); + if (value !== undefined && value !== '') { + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown + '-' + variable).find('input').type(value); + } + cy.wait(1000); + }, + + assertVariableBeVisible: (variable: string) => { + cy.log('persesDashboardsPage.assertVariableBeVisible'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown + '-' + variable).should('be.visible'); + }, + + assertVariableNotExist: (variable: string) => { + cy.log('persesDashboardsPage.assertVariableNotExist'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown + '-' + variable).should('not.exist'); + }, + + assertVariableNotBeVisible: (variable: string) => { + cy.log('persesDashboardsPage.assertVariableNotBeVisible'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown + '-' + variable).should('not.be.visible'); + }, + + clickEditButton: () => { + cy.log('persesDashboardsPage.clickEditButton'); + cy.byTestID(persesDashboardDataTestIDs.editDashboardButtonToolbar).scrollIntoView().should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + assertEditButtonIsDisabled: () => { + cy.log('persesDashboardsPage.assertEditButtonIsDisabled'); + cy.byTestID(persesDashboardDataTestIDs.editDashboardButtonToolbar).scrollIntoView().should('be.visible').should('have.attr', 'disabled'); + }, + + assertEditModeButtons: () => { + cy.log('persesDashboardsPage.assertEditModeButtons'); + cy.byTestID(persesDashboardDataTestIDs.editDashboardButtonToolbar).should('not.exist'); + cy.byAriaLabel(persesAriaLabels.EditVariablesButton).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.EditDatasourcesButton).should('not.exist'); + cy.byAriaLabel(persesAriaLabels.AddPanelButton).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.AddGroupButton).should('be.visible'); + cy.bySemanticElement('button', 'Save').should('be.visible'); + cy.byTestID(persesDashboardDataTestIDs.cancelButtonToolbar).should('be.visible'); + }, + + clickEditActionButton: (button: 'EditVariables' | 'AddPanel' | 'AddGroup' | 'Save' | 'Cancel') => { + cy.log('persesDashboardsPage.clickEditActionButton'); + cy.wait(2000); + switch (button) { + case 'EditVariables': + cy.byAriaLabel(persesAriaLabels.EditVariablesButton).eq(0).scrollIntoView().should('be.visible').click({ force: true }); + break; + //TODO: OU-1054 target for COO1.5.0, so, commenting out for now + // case 'EditDatasources': + // cy.byAriaLabel(persesAriaLabels.EditDatasourcesButton).scrollIntoView().should('be.visible').click({ force: true }); + // break; + case 'AddPanel': + cy.byAriaLabel(persesAriaLabels.AddPanelButton).eq(0).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'AddGroup': + cy.byAriaLabel(persesAriaLabels.AddGroupButton).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'Save': + cy.bySemanticElement('button', 'Save').scrollIntoView().should('be.visible').click({ force: true }); + persesDashboardsPage.clickSaveDashboardButton(); + persesDashboardsPage.closeSuccessAlert(); + break; + case 'Cancel': + cy.byTestID(persesDashboardDataTestIDs.cancelButtonToolbar).scrollIntoView().should('be.visible').click({ force: true }); + cy.wait(1000); + persesDashboardsPage.clickDiscardChangesButton(); + break; + } + }, + + assertEditModePanelGroupButtons: (panelGroup: string) => { + cy.log('persesDashboardsPage.assertEditModePanelGroupButtons'); + cy.byAriaLabel(persesAriaLabels.AddPanelToGroupPrefix + panelGroup).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.EditPanelGroupPrefix + panelGroup).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.DeletePanelGroupPrefix + panelGroup).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.MovePanelGroupPrefix + panelGroup + persesAriaLabels.MovePanelGroupDownSuffix).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.MovePanelGroupPrefix + panelGroup + persesAriaLabels.MovePanelGroupUpSuffix).scrollIntoView().should('be.visible'); + }, + + clickPanelAction: (panel: string, button: 'expand' | 'collapse' | 'edit' | 'duplicate' | 'delete') => { + cy.log('persesDashboardsPage.clickPanelActions'); + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(panel).siblings('div').eq(0).then((element1) => { + if (element1.find('[data-testid="MenuIcon"]').length > 0 && element1.find('[data-testid="MenuIcon"]').is(':visible')) { + cy.byAriaLabel(persesAriaLabels.EditPanelActionMenuButtonPrefix + panel).should('be.visible').click({ force: true }); + } + }); + + switch (button) { + case 'expand': + cy.byAriaLabel(persesAriaLabels.EditPanelExpandCollapseButtonPrefix + panel + persesAriaLabels.EditPanelExpandCollapseButtonSuffix).find('[data-testid="ArrowExpandIcon"]').eq(0).invoke('show').click({ force: true }); + break; + case 'collapse': + cy.byAriaLabel(persesAriaLabels.EditPanelExpandCollapseButtonPrefix + panel + persesAriaLabels.EditPanelExpandCollapseButtonSuffix).find('[data-testid="ArrowCollapseIcon"]').eq(1).should('be.visible').click({ force: true }); + break; + case 'edit': + cy.byAriaLabel(persesAriaLabels.EditPanelPrefix + panel).should('be.visible').click({ force: true }); + break; + case 'duplicate': + cy.byAriaLabel(persesAriaLabels.EditPanelDuplicateButtonPrefix + panel).should('be.visible').click({ force: true }); + break; + case 'delete': + cy.byAriaLabel(persesAriaLabels.EditPanelDeleteButtonPrefix + panel).should('be.visible').click({ force: true }); + break; + } + }, + + assertPanelActionButtons: (panel: string) => { + cy.log('persesDashboardsPage.assertPanelActionButtons'); + + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(panel).siblings('div').eq(1).then((element1) => { + if (element1.find('[data-testid="MenuIcon"]').length > 0 && element1.find('[data-testid="MenuIcon"]').is(':visible')) { + cy.byAriaLabel(persesAriaLabels.EditPanelExpandCollapseButtonPrefix + panel + persesAriaLabels.EditPanelExpandCollapseButtonSuffix).find('[data-testid="ArrowExpandIcon"]').eq(0).should('be.visible').click(); + } + cy.byAriaLabel(persesAriaLabels.EditPanelExpandCollapseButtonPrefix + panel + persesAriaLabels.EditPanelExpandCollapseButtonSuffix).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.EditPanelPrefix + panel).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.EditPanelDuplicateButtonPrefix + panel).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.EditPanelDeleteButtonPrefix + panel).should('be.visible'); + }); + + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(panel).siblings('div').eq(2).then((element1) => { + if (element1.find('[data-testid="ArrowCollapseIcon"]').length > 0 && element1.find('[data-testid="ArrowCollapseIcon"]').is(':visible')) { + cy.byAriaLabel(persesAriaLabels.EditPanelExpandCollapseButtonPrefix + panel + persesAriaLabels.EditPanelExpandCollapseButtonSuffix).find('[data-testid="ArrowCollapseIcon"]').eq(0).click({ force: true }); + } + }); + }, + + clickSaveDashboardButton: () => { + cy.log('persesDashboardsPage.clickSaveDashboardButton'); + cy.wait(2000); + cy.get('body').then((body) => { + if (body.find('[data-testid="CloseIcon"]').length > 0 && body.find('[data-testid="CloseIcon"]').is(':visible')) { + cy.bySemanticElement('button', 'Save Changes').scrollIntoView().should('be.visible').click({ force: true }); + } + }); + cy.wait(2000); + }, + + backToListPersesDashboardsPage: () => { + cy.log('persesDashboardsPage.backToListPersesDashboardsPage'); + cy.byTestID(listPersesDashboardsDataTestIDs.PersesBreadcrumbDashboardItem).scrollIntoView().should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + clickDiscardChangesButton: () => { + cy.log('persesDashboardsPage.clickDiscardChangesButton'); + cy.get('body').then((body) => { + if (body.find('#'+IDs.persesDashboardDiscardChangesDialog).length > 0 && body.find('#'+IDs.persesDashboardDiscardChangesDialog).is(':visible')) { + cy.bySemanticElement('button', 'Discard Changes').scrollIntoView().should('be.visible').click({ force: true }); + } + }); + }, + + assertPanel: (name: string, group: string, collapse_state: 'Open' | 'Closed') => { + cy.log('persesDashboardsPage.assertPanel'); + persesDashboardsPage.panelGroupHeaderAssertion(group, collapse_state); + if (collapse_state === 'Open') { + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(name).should('be.visible'); + } else { + cy.byAriaLabel(persesAriaLabels.OpenGroupButtonPrefix + group).scrollIntoView().should('be.visible').click({ force: true }); + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(name).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.CollapseGroupButtonPrefix + group).should('be.visible').click({ force: true }); + } + }, + + assertPanelNotExist: (name: string) => { + cy.log('persesDashboardsPage.assertPanelNotExist'); + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(name).should('not.exist'); + }, + + downloadDashboard: (clearFolder: boolean, dashboardName: string, format: 'JSON' | 'YAML' | 'YAML (CR v1alpha1)' | 'YAML (CR v1alpha2)') => { + cy.log('persesDashboardsPage.downloadDashboard'); + + if (clearFolder) { + cy.task('clearDownloads'); + } + + cy.get('#'+ IDs.persesDashboardDownloadButton).scrollIntoView().should('be.visible').click({ force: true }); + cy.byPFRole('menuitem').contains(format).should('be.visible').click({ force: true }); cy.wait(1000); + let filename: string; + if (format === 'YAML (CR v1alpha1)') { + filename = dashboardName + '-cr-v1alpha1' + '.yaml'; + } else if (format === 'YAML (CR v1alpha2)') { + filename = dashboardName + '-cr-v1alpha2' + '.yaml'; + } else { + filename = dashboardName + '.' + format.toLowerCase(); + } + persesDashboardsPage.assertFilename(filename); + }, + + assertFilename: (fileNameExp: string) => { + cy.log('persesDashboardsPage.assertFilename'); + let downloadedFileName: string | null = null; + const downloadsFolder = Cypress.config('downloadsFolder'); + const expectedFileNamePattern = fileNameExp; + + cy.waitUntil(() => { + return cy.task('getFilesInFolder', downloadsFolder).then((currentFiles: string[]) => { + const matchingFile = currentFiles.find(file => file.includes(expectedFileNamePattern)); + if (matchingFile) { + downloadedFileName = matchingFile; + return true; + } + return false; + }); + }, { + timeout: 20000, + interval: 1000, + errorMsg: `File matching "${expectedFileNamePattern}" was not downloaded within timeout.` + }); + + cy.then(() => { + expect(downloadedFileName).to.not.be.null; + cy.task('doesFileExist', { fileName: downloadedFileName }).should('be.true'); + }); + }, + + viewJSON: (dashboardName: string, namespace: string) => { + cy.log('persesDashboardsPage.viewJSON'); + cy.byAriaLabel(persesAriaLabels.ViewJSONButton).scrollIntoView().should('be.visible').click({ force: true }); + cy.byPFRole('dialog').find('h2').contains(persesDashboardsModalTitles.VIEW_JSON_DIALOG).scrollIntoView().should('be.visible'); + cy.byAriaLabel('Close').should('be.visible').click({ force: true }); + }, + + assertDuplicatedPanel: (panel: string, amount: number) => { + cy.log('persesDashboardsPage.assertDuplicatedPanel'); + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').filter(`:contains("${panel}")`).should('have.length', amount); + }, + + closeSuccessAlert: () => { + cy.log('persesDashboardsPage.closeSuccessAlert'); + cy.wait(2000); + cy.get('body').then((body) => { + if (body.find('h4').length > 0 && body.find('h4').is(':visible')) { + cy.get('h4').siblings('div').find('button').scrollIntoView().should('be.visible').click({ force: true }); + } + }); }, -} +} \ No newline at end of file diff --git a/web/cypress/views/silence-alert-page.ts b/web/cypress/views/silence-alert-page.ts index 950eb75e0..003a9a80e 100644 --- a/web/cypress/views/silence-alert-page.ts +++ b/web/cypress/views/silence-alert-page.ts @@ -269,4 +269,4 @@ export const silenceAlertPage = { cy.get(Classes.SilenceAlertTitle).should('contain.text', 'invalid silence: at least one matcher must not match the empty string'); }, -}; +}; \ No newline at end of file diff --git a/web/cypress/views/silence-details-page.ts b/web/cypress/views/silence-details-page.ts index 6645be8e2..6b1e6f2b9 100644 --- a/web/cypress/views/silence-details-page.ts +++ b/web/cypress/views/silence-details-page.ts @@ -73,4 +73,4 @@ export const silenceDetailsPage = { throw error; } } -}; +}; \ No newline at end of file diff --git a/web/cypress/views/silences-list-page.ts b/web/cypress/views/silences-list-page.ts index 6f8ff4a98..9db45583a 100644 --- a/web/cypress/views/silences-list-page.ts +++ b/web/cypress/views/silences-list-page.ts @@ -88,6 +88,7 @@ export const silencesListPage = { clickAlertKebab: () => { cy.log('silencesListPage.rows.clickAlertKebab'); + cy.wait(2000); cy.byTestID(DataTestIDs.KebabDropdownButton).should('be.visible').click(); }, @@ -107,4 +108,4 @@ export const silencesListPage = { commonPages.confirmExpireAlert(yes); } }, -} +} \ No newline at end of file diff --git a/web/cypress/views/tour.ts b/web/cypress/views/tour.ts index 9884cede1..a0b04f692 100644 --- a/web/cypress/views/tour.ts +++ b/web/cypress/views/tour.ts @@ -1,17 +1,43 @@ export const guidedTour = { - close: () => { - cy.get('body').then(($body) => { - if ($body.find(`[data-test="guided-tour-modal"]`).length > 0) { - cy.byTestID('tour-step-footer-secondary').contains('Skip tour').click(); - } - }); - }, + close: () => { + const modalSelector = 'button[data-ouia-component-id="clustersOnboardingModal-ModalBoxCloseButton"]' + cy.log('close guided tour'); + cy.get('body').then(($body) => { + //Core platform modal + if ($body.find(`[data-test="guided-tour-modal"]`).length > 0) { + cy.log('Core platform modal detected, attempting to close...'); + cy.byTestID('tour-step-footer-secondary').contains('Skip tour').click(); + } + //Kubevirt modal + else if ($body.find(`[aria-label="Welcome modal"]`).length > 0) { + cy.log('Kubevirt modal detected, attempting to close...'); + cy.get('[aria-label="Close"]').should('be.visible').click(); + } + //ACM Onboarding modal + else if ($body.find(modalSelector).length > 0) { + cy.log('Onboarding modal detected, attempting to close...'); + cy.get(modalSelector, { timeout: 20000 }) + .should('be.visible') + .should('not.be.disabled') + .click({ force: true }); + + cy.get(modalSelector, { timeout: 10000 }) + .should('not.exist') + .then(() => cy.log('Modal successfully closed')); + } + // Prevents navigating away from the page before the tour is closed + cy.wait(2000); + }); + }, - closeKubevirtTour: () => { - cy.get('body').then(($body) => { - if ($body.find(`[aria-label="Welcome modal"]`).length > 0) { - cy.get('[aria-label="Close"]').should('be.visible').click(); - } - }); - }, - }; \ No newline at end of file + closeKubevirtTour: () => { + cy.log('close Kubevirt tour'); + cy.get('body').then(($body) => { + if ($body.find(`[aria-label="Welcome modal"]`).length > 0) { + cy.get('[aria-label="Close"]').should('be.visible').click(); + } + // Prevents navigating away from the page before the tour is closed + cy.wait(2000); + }); + }, +}; \ No newline at end of file diff --git a/web/cypress/views/troubleshooting-panel.ts b/web/cypress/views/troubleshooting-panel.ts index e11b91a5f..58731c6a1 100644 --- a/web/cypress/views/troubleshooting-panel.ts +++ b/web/cypress/views/troubleshooting-panel.ts @@ -5,7 +5,9 @@ export const troubleshootingPanelPage = { openSignalCorrelation: () => { cy.log('troubleshootingPanelPage.openSignalCorrelation'); cy.byLegacyTestID(LegacyTestIDs.ApplicationLauncher).should('be.visible').click(); + cy.wait(3000); cy.byTestID(DataTestIDs.MastHeadApplicationItem).contains('Signal Correlation').should('be.visible').click(); + cy.wait(3000); }, signalCorrelationShouldNotBeVisible: () => { @@ -27,4 +29,4 @@ export const troubleshootingPanelPage = { }, -}; +}; \ No newline at end of file diff --git a/web/src/components/data-test.ts b/web/src/components/data-test.ts index 4f08dc0aa..f93eef735 100644 --- a/web/src/components/data-test.ts +++ b/web/src/components/data-test.ts @@ -19,6 +19,7 @@ export const DataTestIDs = { ExpireSilenceButton: 'expire-silence-button', ExpireXSilencesButton: 'expire-x-silences-button', Expression: 'expression', + FavoriteStarButton: 'favorite-button', KebabDropdownButton: 'kebab-dropdown-button', MastHeadHelpIcon: 'help-dropdown-toggle', MastHeadApplicationItem: 'application-launcher-item', @@ -59,6 +60,7 @@ export const DataTestIDs = { NamespaceDropdownShowSwitch: 'showSystemSwitch', NamespaceDropdownTextFilter: 'dropdown-text-filter', PersesDashboardDropdown: 'dashboard-dropdown', + PersesCreateDashboardButton: 'create-dashboard-button-list-page', SeverityBadgeHeader: 'severity-badge-header', SeverityBadge: 'severity-badge', SilenceAlertDropdownItem: 'silence-alert-dropdown-item', @@ -170,11 +172,23 @@ export const LegacyTestIDs = { PersesDashboardSection: 'dashboard', NamespaceBarDropdown: 'namespace-bar-dropdown', ApplicationLauncher: 'application-launcher', + NameLabelDropdown: 'dropdown-button', + NameLabelDropdownOptions: 'dropdown-menu', }; export const IDs = { ChartAxis0ChartLabel: 'chart-axis-0-ChartLabel', //id^=IDs.ChartAxis0ChartLabel AxisX ChartAxis1ChartLabel: 'chart-axis-1-ChartLabel', //id^=IDs.ChartAxis1ChartLabel AxisY + persesDashboardCount: 'options-menu-top-pagination', + persesDashboardDownloadButton: 'download-dashboard-button', + persesDashboardActionMenuModal: 'action-menu', + persesDashboardEditVariablesModalBuiltinButton: 'builtin', + persesDashboardAddPanelGroupForm: 'panel-group-editor-form', + persesDashboardAddPanelForm: 'panel-editor-form', + persesDashboardDiscardChangesDialog: 'discard-dialog', + persesDashboardCreateDashboardName: 'text-input-create-dashboard-dialog-name', + persesDashboardRenameDashboardName: 'rename-modal-text-input', + persesDashboardDuplicateDashboardName: 'duplicate-modal-dashboard-name-form-group-text-input', }; export const Classes = { @@ -202,6 +216,11 @@ export const Classes = { MetricsPageQueryAutocomplete: '.cm-tooltip-autocomplete.cm-tooltip.cm-tooltip-below', MoreLessTag: '.pf-v6-c-label-group__label, .pf-v5-c-chip-group__label', NamespaceDropdown: '.pf-v6-c-menu-toggle.co-namespace-dropdown__menu-toggle', + NamespaceDropdownExpanded: + '.pf-v6-c-menu-toggle.pf-m-expanded.co-namespace-dropdown__menu-toggle', + PersesCreateDashboardProjectDropdown: '.pf-v6-c-menu-toggle.pf-m-full-width', + PersesCreateDashboardDashboardNameError: '.pf-v6-c-helper-text__item-text', + PersesListDashboardCount: '.pf-v6-c-menu-toggle__text', SectionHeader: '.pf-v6-c-title.pf-m-h2, .co-section-heading', TableHeaderColumn: '.pf-v6-c-table__button, .pf-c-table__button', SilenceAlertTitle: '.pf-v6-c-alert__title, .pf-v5-c-alert__title', @@ -221,10 +240,106 @@ export const persesAriaLabels = { RefreshIntervalDropdown: 'Select refresh interval. Currently set to 0s', ZoomInButton: 'Zoom in', ZoomOutButton: 'Zoom out', + ViewJSONButton: 'View JSON', + EditJSONButton: 'Edit JSON', + EditVariablesButton: 'Edit variables', + EditDatasourcesButton: 'Edit datasources', + AddPanelButton: 'Add panel', + AddGroupButton: 'Add panel group', + OpenGroupButtonPrefix: 'expand group ', + CollapseGroupButtonPrefix: 'collapse group ', + //PanelGroup toolbar buttons + AddPanelToGroupPrefix: 'add panel to group ', + EditPanelGroupPrefix: 'edit group ', + DeletePanelGroupPrefix: 'delete group ', + MovePanelGroupPrefix: 'move group ', + MovePanelGroupDownSuffix: ' down', + MovePanelGroupUpSuffix: ' up', + EditDashboardVariablesTable: 'table of variables', + EditDashboardDatasourcesTable: 'table of datasources', + //Panel toolbar buttons + EditPanelActionMenuButtonPrefix: 'show panel actions for ', + EditPanelExpandCollapseButtonPrefix: 'toggle panel ', + EditPanelExpandCollapseButtonSuffix: ' view mode', + EditPanelPrefix: 'edit panel ', + EditPanelDuplicateButtonPrefix: 'duplicate panel ', + EditPanelDeleteButtonPrefix: 'delete panel ', + EditPanelMovePanelButtonPrefix: 'move panel ', + PanelExportTimeSeriesDataAsCSV: 'Export time series data as CSV', + //Add Panel tabs + AddPanelTabs: 'Panel configuration tabs', + //List Page + persesDashboardKebabIcon: 'Kebab toggle', }; -export const persesDataTestIDs = { +//data-testid from MUI components +export const persesMUIDataTestIDs = { variableDropdown: 'variable', + panelGroup: 'panel-group', panelGroupHeader: 'panel-group-header', panelHeader: 'panel', + editDashboardVariablesModal: 'variable-editor', + editDashboardDatasourcesModal: 'datasource-editor', + editDashboardAddVariableRunQueryButton: 'run_query_button', + editDashboardAddVariablePreviewValuesCopy: 'ClipboardOutlineIcon', + editDashboardEditVariableMoveDownButton: 'ArrowDownIcon', + editDashboardEditVariableMoveUpButton: 'ArrowUpIcon', + editDashboardEditVariableDatasourceEditButton: 'PencilIcon', + editDashboardEditVariableDatasourceDeleteButton: 'TrashCanIcon', + addPanelGroupFormName: 'panel-group-editor-name', +}; + +export const persesDashboardDataTestIDs = { + createDashboardButtonToolbar: 'create-dashboard-button-list-page', + editDashboardButtonToolbar: 'edit-dashboard-button-toolbar', + cancelButtonToolbar: 'cancel-button-toolbar', +}; + +export const listPersesDashboardsDataTestIDs = { + PersesBreadcrumbDashboardItem: 'perses-dashboards-breadcrumb-dashboard-item', + PersesBreadcrumbDashboardNameItem: 'perses-dashboards-breadcrumb-dashboard-name-item', + NameFilter: 'name-filter', + ProjectFilter: 'project-filter', + EmptyStateTitle: 'empty-state-title', + EmptyStateBody: 'empty-state-body', + ClearAllFiltersButton: 'clear-all-filters-button', + DashboardLinkPrefix: 'perseslistpage-', +}; + +export const listPersesDashboardsOUIAIDs = { + PageHeaderSubtitle: 'PageHeader-subtitle', + PersesBreadcrumb: 'perses-dashboards-breadcrumb', + PersesDashListDataViewTable: 'PersesDashList-DataViewTable', + persesListDataViewHeaderClearAllFiltersButton: 'PersesDashList-DataViewHeader-clear-all-filters', + persesListDataViewFilters: 'DataViewFilters', + persesListDataViewHeaderSortButton: 'PersesDashList-DataViewTable-th', + persesListDataViewTableDashboardNameTD: 'PersesDashList-DataViewTable-td-', +}; + +//name attribute from MUI components +export const editPersesDashboardsAddVariable = { + inputName: 'spec.name', + inputDisplayLabel: 'spec.display.name', + inputDescription: 'spec.display.description', + //type='Text' + inputValue: 'spec.value', + inputConstant: 'spec.constant', + //type='List' + inputCapturingRegexp: 'spec.capturingRegexp', + inputAllowMultiple: 'spec.allowMultiple', + inputAllowAllValue: 'spec.allowAllValue', + inputCustomAllValue: 'spec.customAllValue', +}; + +//name attribute from MUI components +export const editPersesDashboardsAddDatasource = { + inputName: 'name', + inputDefaultDatasource: 'spec.default', + inputDisplayLabel: 'title', + inputDescription: 'description', +}; + +export const editPersesDashboardsAddPanel = { + inputName: 'panelDefinition.spec.display.name', + inputDescription: 'panelDefinition.spec.display.description', }; From f5a32b686f8f0c02ff68ddb845c7989571740ca2 Mon Sep 17 00:00:00 2001 From: Evelyn Tanigawa Murasaki Date: Sat, 14 Feb 2026 17:28:58 -0300 Subject: [PATCH 2/2] perses tags --- web/package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/package.json b/web/package.json index 2fafe3c69..e52386194 100644 --- a/web/package.json +++ b/web/package.json @@ -41,6 +41,8 @@ "test-cypress-incidents": "node --max-old-space-size=4096 ./node_modules/.bin/cypress run --browser chrome --headless --env grepTags='@incidents --@flaky --@demo'", "test-cypress-smoke": "node --max-old-space-size=4096 ./node_modules/.bin/cypress run --browser chrome --headless --env grepTags='@smoke --@flaky --@demo'", "test-cypress-fast": "node --max-old-space-size=4096 ./node_modules/.bin/cypress run --browser chrome --headless --env grepTags='@smoke --@slow --@demo --@flaky'", + "test-cypress-perses-dev": "node --max-old-space-size=4096 ./node_modules/.bin/cypress run --browser chrome --headless --env grepTags='@perses-dev --@demo'", + "test-cypress-perses": "node --max-old-space-size=4096 ./node_modules/.bin/cypress run --browser chrome --headless --env grepTags='@perses --@smoke --@flaky --@demo'", "ts-node": "ts-node -O '{\"module\":\"commonjs\"}'" }, "dependencies": {