diff --git a/web/cypress.config.ts b/web/cypress.config.ts index 6c64a6812..6c6a516b5 100644 --- a/web/cypress.config.ts +++ b/web/cypress.config.ts @@ -17,11 +17,20 @@ export default defineConfig({ }, env: { grepFilterSpecs: true, - HOST_API: process.env.CYPRESS_BASE_URL.replace(/console-openshift-console.apps/, 'api').concat( + HOST_API: (process.env.CYPRESS_BASE_URL || '').replace(/console-openshift-console.apps/, 'api').concat( ':6443', ), - LOGIN_USERNAME: process.env.CYPRESS_LOGIN_USERS.split(',')[0].split(':')[0], - LOGIN_PASSWORD: process.env.CYPRESS_LOGIN_USERS.split(',')[0].split(':')[1], + // User 0 credentials - as kubeadmin or even non-admin user + // specifically for perses e2e tests, user0 is considered as console admin user to install COO and create RBAC roles and bindings + LOGIN_USERNAME: (process.env.CYPRESS_LOGIN_USERS || '').split(',')[0]?.split(':')[0] || '', + LOGIN_PASSWORD: (process.env.CYPRESS_LOGIN_USERS || '').split(',')[0]?.split(':')[1] || '', + // User 1 credentials + // User 2 credentials + // specifically for perses e2e tests, user1 and user2 are considered as perses e2e users to test RBAC access to dashboards + LOGIN_USERNAME1: (process.env.CYPRESS_LOGIN_USERS || '').split(',')[1]?.split(':')[0] || '', + LOGIN_PASSWORD1: (process.env.CYPRESS_LOGIN_USERS || '').split(',')[1]?.split(':')[1] || '', + LOGIN_USERNAME2: (process.env.CYPRESS_LOGIN_USERS || '').split(',')[2]?.split(':')[0] || '', + LOGIN_PASSWORD2: (process.env.CYPRESS_LOGIN_USERS || '').split(',')[2]?.split(':')[1] || '', TIMEZONE: process.env.CYPRESS_TIMEZONE || 'UTC', MOCK_NEW_METRICS: process.env.CYPRESS_MOCK_NEW_METRICS || 'false', COO_NAMESPACE: process.env.CYPRESS_COO_NAMESPACE || 'openshift-cluster-observability-operator', diff --git a/web/cypress/README.md b/web/cypress/README.md index 17c589e6b..9e0c0fc87 100644 --- a/web/cypress/README.md +++ b/web/cypress/README.md @@ -66,7 +66,8 @@ Creates `export-env.sh` that you can source later: `source export-env.sh` |----------|-------------|---------| | `CYPRESS_BASE_URL` | OpenShift Console URL | `https://console-openshift-console.apps...` | | `CYPRESS_LOGIN_IDP` | Identity provider name | `flexy-htpasswd-provider` or `kube:admin` | -| `CYPRESS_LOGIN_USERS` | Login credentials | `username:password` or `kubeadmin:password` | +| `CYPRESS_LOGIN_IDP_DEV_USER`| Identity provider name for devuser | `flexy-htpasswd-provider` or `my_htpasswd_provider`| +| `CYPRESS_LOGIN_USERS` | Login credentials | `username:password` or `kubeadmin:password` or `kubeadmin:password,user1:password,user2:password` | | `CYPRESS_KUBECONFIG_PATH` | Path to kubeconfig file | `~/Downloads/kubeconfig` | ### Plugin Image Configuration diff --git a/web/cypress/configure-env.sh b/web/cypress/configure-env.sh index e8df45372..eab835863 100755 --- a/web/cypress/configure-env.sh +++ b/web/cypress/configure-env.sh @@ -186,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() { @@ -238,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 @@ -481,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)'" ) @@ -531,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 @@ -553,6 +559,7 @@ main() { 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" 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..30f6c107b --- /dev/null +++ b/web/cypress/e2e/perses/03.coo_create_perses_admin.cy.ts @@ -0,0 +1,45 @@ +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/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/coo121_perses_dashboards/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/coo121_perses_dashboards/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/coo121_perses_dashboards/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/coo121_perses_dashboards/perses-dashboard-sample.yaml rename to web/cypress/fixtures/coo/coo121_perses/dashboards/perses-dashboard-sample.yaml diff --git a/web/cypress/fixtures/coo/coo121_perses_dashboards/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/coo121_perses_dashboards/prometheus-overview-variables.yaml rename to web/cypress/fixtures/coo/coo121_perses/dashboards/prometheus-overview-variables.yaml diff --git a/web/cypress/fixtures/coo/coo121_perses_dashboards/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/coo121_perses_dashboards/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/coo121_perses_dashboards/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/coo121_perses_dashboards/thanos-querier-datasource.yaml rename to web/cypress/fixtures/coo/coo121_perses/dashboards/thanos-querier-datasource.yaml diff --git a/web/cypress/fixtures/coo/coo121_perses_dashboards/perses-datasource-sample.yaml b/web/cypress/fixtures/coo/coo121_perses_dashboards/perses-datasource-sample.yaml deleted file mode 100644 index cf7df0241..000000000 --- a/web/cypress/fixtures/coo/coo121_perses_dashboards/perses-datasource-sample.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: perses.dev/v1alpha1 -kind: PersesDatasource -metadata: - name: perses-datasource-sample - namespace: perses-dev -spec: - config: - display: - name: 'Default Datasource' - default: true - plugin: - kind: 'PrometheusDatasource' - spec: - directUrl: 'https://prometheus.demo.prometheus.io' \ No newline at end of file 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 similarity index 100% rename from web/cypress/fixtures/coo/coo141_perses_dashboards/openshift-cluster-sample-dashboard.yaml rename to web/cypress/fixtures/coo/coo141_perses/dashboards/openshift-cluster-sample-dashboard.yaml 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 similarity index 100% rename from web/cypress/fixtures/coo/coo141_perses_dashboards/perses-dashboard-sample.yaml rename to web/cypress/fixtures/coo/coo141_perses/dashboards/perses-dashboard-sample.yaml 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 similarity index 100% rename from web/cypress/fixtures/coo/coo141_perses_dashboards/prometheus-overview-variables.yaml rename to web/cypress/fixtures/coo/coo141_perses/dashboards/prometheus-overview-variables.yaml 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 similarity index 100% rename from web/cypress/fixtures/coo/coo141_perses_dashboards/thanos-compact-overview-1var.yaml rename to web/cypress/fixtures/coo/coo141_perses/dashboards/thanos-compact-overview-1var.yaml 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 similarity index 100% rename from web/cypress/fixtures/coo/coo141_perses_dashboards/thanos-querier-datasource.yaml rename to web/cypress/fixtures/coo/coo141_perses/dashboards/thanos-querier-datasource.yaml 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 100755 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 - < export CYPRESS_LOGIN_IDP=kube:admin -export CYPRESS_LOGIN_USERS=kubeadmin: +export CYPRESS_LOGIN_IDP_DEV_USER=my_htpasswd_provider +export CYPRESS_LOGIN_USERS=kubeadmin:password,user1:password,user2:password export CYPRESS_KUBECONFIG_PATH=~/Downloads/kubeconfig # Set the following var to use custom Monitoring Plugin image (that goes on Cluster Monitoring Operator). The image will be patched in CMO CSV. diff --git a/web/cypress/fixtures/perses/constants.ts b/web/cypress/fixtures/perses/constants.ts index ca231b4bc..18dca52e3 100644 --- a/web/cypress/fixtures/perses/constants.ts +++ b/web/cypress/fixtures/perses/constants.ts @@ -68,13 +68,14 @@ export const persesDashboardsModalTitles ={ 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 Variable', - PROMETHEUS_NAMES_VARIABLE= 'Prometheus Names Variable', + PROMETHEUS_LABEL_VARIABLE= 'Prometheus Label Values Variable', + PROMETHEUS_NAMES_VARIABLE= 'Prometheus Label Names Variable', PROMETHEUS_PROMQL_VARIABLE= 'Prometheus PromQL Variable', } @@ -110,3 +111,41 @@ export const persesDashboardsAddListPanelType = { 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"{}}', +} diff --git a/web/cypress/support/commands/auth-commands.ts b/web/cypress/support/commands/auth-commands.ts index 3d5b71c8f..62cbf3bd7 100644 --- a/web/cypress/support/commands/auth-commands.ts +++ b/web/cypress/support/commands/auth-commands.ts @@ -3,7 +3,7 @@ import { guidedTour } from '../../views/tour'; -export {}; +export { }; declare global { namespace Cypress { interface Chainable { @@ -17,203 +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.log('validateLogin'); - cy.visit('/'); - cy.wait(2000); - cy.byTestID("username", {timeout: 120000}).should('be.visible'); - cy.wait(10000); - 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', (...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(); +// 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(...perspectives); - cy.wait(3000); - guidedTour.close(); - }); + 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/operator-commands.ts b/web/cypress/support/commands/operator-commands.ts index 927ace76d..d9f0d428f 100644 --- a/web/cypress/support/commands/operator-commands.ts +++ b/web/cypress/support/commands/operator-commands.ts @@ -23,6 +23,8 @@ declare global { setupCOO(MCP: { namespace: string, operatorName: string, packageName: string }, MP: { namespace: string, operatorName: string }); beforeBlockACM( MCP: { namespace: string; operatorName: string; packageName: string }, MP: { namespace: string; operatorName: string },): Chainable; closeOnboardingModalIfPresent(): Chainable; + setupPersesRBACandExtraDashboards(): Chainable; + cleanupExtraDashboards(): Chainable; } } } @@ -382,36 +384,36 @@ const operatorUtils = { 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.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.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.exec(`oc apply -f ./cypress/fixtures/coo/coo121_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/coo121_perses_dashboards/thanos-compact-overview-1var.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo121_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/coo121_perses_dashboards/thanos-querier-datasource.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + 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.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.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.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/coo141_perses_dashboards/thanos-compact-overview-1var.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + 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/coo141_perses_dashboards/thanos-querier-datasource.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo141_perses/dashboards/thanos-querier-datasource.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); } @@ -486,7 +488,10 @@ const operatorUtils = { cy.log(`Korrel8r pod is now running in namespace: ${MCP.namespace}`); }); - cy.wait(30000); + 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'); @@ -552,36 +557,36 @@ const operatorUtils = { 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.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/coo121_perses_dashboards/perses-dashboard-sample.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + 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/coo121_perses_dashboards/prometheus-overview-variables.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + 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/coo121_perses_dashboards/thanos-compact-overview-1var.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + 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/coo121_perses_dashboards/thanos-querier-datasource.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + 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.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.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.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.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.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')}`); @@ -923,3 +928,56 @@ Cypress.Commands.add('closeOnboardingModalIfPresent', () => { } }); }); + +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/utility-commands.ts b/web/cypress/support/commands/utility-commands.ts index 17385d1ea..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; } } } @@ -142,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/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..e9114e679 --- /dev/null +++ b/web/cypress/support/perses/03.coo_create_perses_admin.cy.ts @@ -0,0 +1,188 @@ +import { listPersesDashboardsPage } from "../../views/list-perses-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`); + persesDashboardsPage.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); + + }); + + 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`); + persesDashboardsPage.clickCreateButton(); + + cy.log(`2.3. Verify Project dropdown`); + persesCreateDashboardsPage.selectProject('openshift-cluster-observability-operator'); + persesCreateDashboardsPage.enterDashboardName(dashboardName); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(dashboardName); + + cy.log(`2.4. Create another dashboard with the same name`); + persesDashboardsPage.backToListPersesDashboardsPage(); + persesDashboardsPage.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); + + cy.log(`2.6. Create another dashboard with the same name without spaces`); + persesDashboardsPage.backToListPersesDashboardsPage(); + persesDashboardsPage.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); + + }); + + 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`); + persesDashboardsPage.clickCreateButton(); + persesCreateDashboardsPage.createDashboardShouldBeLoaded(); + + cy.log(`3.3. Create Dashboard`); + persesCreateDashboardsPage.selectProject('perses-dev'); + persesCreateDashboardsPage.enterDashboardName(dashboardName); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(dashboardName); + + 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.toLowerCase().replace(/ /g, '_')); + listPersesDashboardsPage.clickDashboard(dashboardName.toLowerCase().replace(/ /g, '_')); + 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'); + + }); + +} 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..1f48df14e --- /dev/null +++ b/web/cypress/support/perses/99.coo_rbac_perses_user1.cy.ts @@ -0,0 +1,367 @@ +import { persesDashboardsPage } from '../../views/perses-dashboards'; +import { listPersesDashboardsPage } from '../../views/list-perses-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[2]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2]); + + cy.log(`1.3. All Projects validation - Dashboard search - ${persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]} dashboard`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + listPersesDashboardsPage.countDashboards('2'); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + + cy.log(`1.4. All Projects validation - Dashboard search - ${persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]} dashboard`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + 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[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`2.4. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + 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[2]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + 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[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`3.4. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + 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`); + persesDashboardsPage.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`); + persesDashboardsPage.assertCreateButtonIsEnabled(); + + cy.log(`4.2 change namespace to All Projects`); + cy.changeNamespace('All Projects'); + + cy.log(`4.3. Verify Create button is enabled`); + persesDashboardsPage.assertCreateButtonIsEnabled(); + + }); + + 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`); + persesDashboardsPage.clickCreateButton(); + persesCreateDashboardsPage.createDashboardShouldBeLoaded(); + + cy.log(`5.3. Create Dashboard`); + persesCreateDashboardsPage.selectProject('openshift-cluster-observability-operator'); + persesCreateDashboardsPage.enterDashboardName(dashboardName); + persesCreateDashboardsPage.createDashboardDialogCreateButton(); + persesDashboardsPage.shouldBeLoadedEditionMode(dashboardName); + + 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.toLowerCase().replace(/ /g, '_')); + listPersesDashboardsPage.clickDashboard(dashboardName.toLowerCase().replace(/ /g, '_')); + 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`, () => { + // // Enabled for openshift-cluster-observability-operator namespace + // // Rename + // // Duplicate + // // Delete + // // Disabled for observ-test namespace or enabled but with options disabled + // // Rename + // // Duplicate + // // Delete + // }); + + // it(`7.${perspective.name} perspective - Rename to an existing dashboard name with spaces`, () => { + // + // }); + + // it(`8.${perspective.name} perspective - Rename to an existing dashboard name without spaces`, () => { + // + // }); + + // it(`8.${perspective.name} perspective - Rename to a new dashboard name`, () => { + // + // }); + + // it(`9.${perspective.name} perspective - Duplicate and verify project dropdown`, () => { + // // openshift-cluster-observability-operator namespace + // // observ-test namespace not available + // // perses-dev namespace not available + // }); + + // it(`10.${perspective.name} perspective - Duplicate to an existing dashboard name with spaces`, () => { + // + // }); + + // it(`11.${perspective.name} perspective - Duplicate to an existing dashboard name without spaces`, () => { + // + // }); + + // it(`12.${perspective.name} perspective - Duplicate to a new dashboard name in the same project`, () => { + // + // }); + + // it(`13.${perspective.name} perspective - Delete and Cancel - Enabled`, () => { + // + // }); + + // it(`14.${perspective.name} perspective - Delete and Confirm`, () => { + // + // }); + + // it(`15.${perspective.name} perspective - Delete all dashboard from a project to check empty state`, () => { + // + // }); + + // it(`16.${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 + // + // }); + + // 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 + // }); + + +} 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..99f5686b1 --- /dev/null +++ b/web/cypress/support/perses/99.coo_rbac_perses_user2.cy.ts @@ -0,0 +1,103 @@ +import { persesDashboardsPage } from '../../views/perses-dashboards'; +import { listPersesDashboardsPage } from '../../views/list-perses-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[2]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.filter.byProject('perses-dev'); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.removeTag('perses-dev'); + + cy.changeNamespace('perses-dev'); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + + 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[2]); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2]); + + cy.log(`1.4. All Projects validation - Dashboard search - ${persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]} dashboard`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + listPersesDashboardsPage.emptyState(); + listPersesDashboardsPage.removeTag(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + + }); + + 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[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`2.4. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + 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`); + persesDashboardsPage.assertCreateButtonIsDisabled(); + + cy.log(`3.3 change namespace to perses-dev`); + cy.changeNamespace('perses-dev'); + + cy.log(`3.4. Verify Create button is disabled`); + persesDashboardsPage.assertCreateButtonIsDisabled(); + + }); + + // it(`4.${perspective.name} perspective - Kebab icon - Disabled`, () => { + // // Disabled for perses-dev namespace + // // Rename + // // Duplicate + // // Delete + // }); + + // it(`5.${perspective.name} perspective - Import button validation - Disabled`, () => { + // // Disabled for perses-dev namespace + // + // }); + + +} diff --git a/web/cypress/views/list-perses-dashboards.ts b/web/cypress/views/list-perses-dashboards.ts index bc9c22977..adf8dd647 100644 --- a/web/cypress/views/list-perses-dashboards.ts +++ b/web/cypress/views/list-perses-dashboards.ts @@ -14,7 +14,7 @@ export const listPersesDashboardsPage = { shouldBeLoaded: () => { cy.log('listPersesDashboardsPage.shouldBeLoaded'); - cy.byOUIAID(listPersesDashboardsOUIAIDs.PersesBreadcrumb).should('contain', 'Dashboards').should('be.visible'); + cy.byOUIAID(listPersesDashboardsOUIAIDs.PersesBreadcrumb).should('not.exist'); commonPages.titleShouldHaveText(MonitoringPageTitles.DASHBOARDS); cy.byOUIAID(listPersesDashboardsOUIAIDs.PageHeaderSubtitle).should('contain', listPersesDashboardsPageSubtitle).should('be.visible'); cy.byTestID(DataTestIDs.FavoriteStarButton).should('be.visible'); @@ -80,4 +80,9 @@ export const listPersesDashboardsPage = { cy.byTestID(listPersesDashboardsDataTestIDs.DashboardLinkPrefix+name).eq(idx).should('be.visible').click(); cy.wait(15000); }, + + removeTag: (value: string) => { + cy.log('listPersesDashboardsPage.removeTag'); + cy.byAriaLabel('Close '+ value).click(); + }, } 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..252a3edb5 --- /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'); + } + }, + +} diff --git a/web/cypress/views/perses-dashboards-edit-variables.ts b/web/cypress/views/perses-dashboards-edit-variables.ts index 9a1b393e9..5aaeb4c0e 100644 --- a/web/cypress/views/perses-dashboards-edit-variables.ts +++ b/web/cypress/views/perses-dashboards-edit-variables.ts @@ -82,6 +82,35 @@ export const persesDashboardsEditVariables = { } }, + 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 diff --git a/web/cypress/views/perses-dashboards-panel.ts b/web/cypress/views/perses-dashboards-panel.ts index a016281f2..7ee5a096d 100644 --- a/web/cypress/views/perses-dashboards-panel.ts +++ b/web/cypress/views/perses-dashboards-panel.ts @@ -1,41 +1,40 @@ import { commonPages } from "./common"; -import { persesAriaLabels, persesMUIDataTestIDs, IDs, editPersesDashboardsAddPanel } from "../../src/components/data-test"; -import { persesDashboardsModalTitles, persesDashboardsRequiredFields, persesDashboardsAddListPanelType } from "../fixtures/perses/constants"; -import { persesDashboardsPage } from "./perses-dashboards"; +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'); + 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.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')) { + 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(); + 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.get('#' + IDs.persesDashboardAddPanelForm).find('label').contains(label).siblings('div').click(); cy.wait(1000); - cy.get('li').contains(option).should('be.visible').click(); + cy.get('li').contains(new RegExp(`^${option}$`)).should('be.visible').click(); }, assertRequiredFieldValidation: (field: string) => { @@ -43,43 +42,97 @@ export const persesDashboardsPanel = { switch (field) { case 'Name': - cy.get('#'+IDs.persesDashboardAddPanelForm).find('label').contains(field).siblings('p').should('have.text', 'Required'); + cy.get('#' + IDs.persesDashboardAddPanelForm).find('label').contains(field).siblings('p').should('have.text', 'Required'); break; } }, - addPanel: (name: string, group: string, type: string, description?: string) => { + 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); + cy.get('input[name="' + editPersesDashboardsAddPanel.inputName + '"]').clear().type(name); if (description !== undefined && description !== '') { - cy.get('input[name="'+editPersesDashboardsAddPanel.inputDescription+'"]').clear().type(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'); + 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); + cy.get('input[name="' + editPersesDashboardsAddPanel.inputName + '"]').clear().type(name); if (description !== undefined && description !== '') { - cy.get('input[name="'+editPersesDashboardsAddPanel.inputDescription+'"]').clear().type(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(); + 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') => { diff --git a/web/cypress/views/perses-dashboards-panelgroup.ts b/web/cypress/views/perses-dashboards-panelgroup.ts index 37e9e77cc..02cfdb7ae 100644 --- a/web/cypress/views/perses-dashboards-panelgroup.ts +++ b/web/cypress/views/perses-dashboards-panelgroup.ts @@ -39,7 +39,7 @@ export const persesDashboardsPanelGroup = { cy.byPFRole('dialog').find('div[role="combobox"]').eq(1).click(); cy.byPFRole('option').contains(repeat_variable).click(); } - cy.bySemanticElement('button', 'Add').should('be.visible').click(); + cy.byPFRole('dialog').find('button').contains('Add').should('be.visible').click({ force: true }); }, editPanelGroupShouldBeLoaded: () => { diff --git a/web/cypress/views/perses-dashboards.ts b/web/cypress/views/perses-dashboards.ts index 73e850fd4..3d677a83e 100644 --- a/web/cypress/views/perses-dashboards.ts +++ b/web/cypress/views/perses-dashboards.ts @@ -1,7 +1,7 @@ import { commonPages } from "./common"; import { DataTestIDs, Classes, LegacyTestIDs, persesAriaLabels, persesMUIDataTestIDs, listPersesDashboardsOUIAIDs, IDs, persesDashboardDataTestIDs, listPersesDashboardsDataTestIDs } from "../../src/components/data-test"; import { MonitoringPageTitles } from "../fixtures/monitoring/constants"; -import { listPersesDashboardsPageSubtitle, persesDashboardsModalTitles } from "../fixtures/perses/constants"; +import { listPersesDashboardsPageSubtitle, persesDashboardsEmptyDashboard, persesDashboardsModalTitles } from "../fixtures/perses/constants"; import { persesDashboardsTimeRange, persesDashboardsRefreshInterval, persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev, persesDashboardsAcceleratorsCommonMetricsPanels } from "../fixtures/perses/constants"; export const persesDashboardsPage = { @@ -39,7 +39,33 @@ export const persesDashboardsPage = { 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'); + }, + + shouldBeLoadedEditionMode: (dashboardName: string) => { + cy.log('persesDashboardsPage.shouldBeLoadedEditionMode'); + 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'); + 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'); + + 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'); }, @@ -88,7 +114,7 @@ export const persesDashboardsPage = { clickDashboardDropdown: (dashboard: keyof typeof persesDashboardsDashboardDropdownCOO | keyof typeof persesDashboardsDashboardDropdownPersesDev) => { cy.log('persesDashboardsPage.clickDashboardDropdown'); cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').scrollIntoView().should('be.visible').click({ force: true }); - cy.byPFRole('option').contains(dashboard).scrollIntoView().should('be.visible').click({ force: true }); + cy.byPFRole('option').contains(dashboard).should('be.visible').click({ force: true }); }, dashboardDropdownAssertion: (constants: typeof persesDashboardsDashboardDropdownCOO | typeof persesDashboardsDashboardDropdownPersesDev) => { @@ -204,6 +230,28 @@ export const persesDashboardsPage = { cy.wait(2000); }, + assertEditButtonIsDisabled: () => { + cy.log('persesDashboardsPage.assertEditButtonIsDisabled'); + cy.byTestID(persesDashboardDataTestIDs.editDashboardButtonToolbar).scrollIntoView().should('be.visible').should('have.attr', 'disabled'); + }, + + 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'); + }, + assertEditModeButtons: () => { cy.log('persesDashboardsPage.assertEditModeButtons'); cy.byTestID(persesDashboardDataTestIDs.editDashboardButtonToolbar).should('not.exist'); @@ -220,14 +268,14 @@ export const persesDashboardsPage = { cy.wait(2000); switch (button) { case 'EditVariables': - cy.byAriaLabel(persesAriaLabels.EditVariablesButton).scrollIntoView().should('be.visible').click({ force: true }); + 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).scrollIntoView().should('be.visible').click({ force: true }); + 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 }); @@ -235,6 +283,7 @@ export const persesDashboardsPage = { 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 }); @@ -291,18 +340,24 @@ export const persesDashboardsPage = { 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: () => { @@ -323,11 +378,11 @@ export const persesDashboardsPage = { cy.log('persesDashboardsPage.assertPanel'); persesDashboardsPage.panelGroupHeaderAssertion(group, collapse_state); if (collapse_state === 'Open') { - cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(name).scrollIntoView().should('be.visible'); + 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).scrollIntoView().should('be.visible'); - cy.byAriaLabel(persesAriaLabels.CollapseGroupButtonPrefix + 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 }); } }, @@ -352,10 +407,10 @@ export const persesDashboardsPage = { } else { filename = dashboardName + '.' + format.toLowerCase(); } - persesDashboardsPage.assertFilename(true, filename); + persesDashboardsPage.assertFilename(filename); }, - assertFilename: (clearFolder: boolean, fileNameExp: string) => { + assertFilename: (fileNameExp: string) => { cy.log('persesDashboardsPage.assertFilename'); let downloadedFileName: string | null = null; const downloadsFolder = Cypress.config('downloadsFolder'); @@ -393,4 +448,14 @@ export const persesDashboardsPage = { 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 }); + } + }); + }, } diff --git a/web/package.json b/web/package.json index 71bfa0652..f8e093091 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": { diff --git a/web/src/components/data-test.ts b/web/src/components/data-test.ts index d4aa5b5c3..9a1ee6d90 100644 --- a/web/src/components/data-test.ts +++ b/web/src/components/data-test.ts @@ -60,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', @@ -183,6 +184,7 @@ export const IDs = { persesDashboardAddPanelGroupForm: 'panel-group-editor-form', persesDashboardAddPanelForm: 'panel-editor-form', persesDashboardDiscardChangesDialog: 'discard-dialog', + persesDashboardCreateDashboardName: 'text-input-create-dashboard-dialog-name', }; export const Classes = { @@ -210,6 +212,10 @@ 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', @@ -231,6 +237,7 @@ export const persesAriaLabels = { ZoomInButton: 'Zoom in', ZoomOutButton: 'Zoom out', ViewJSONButton: 'View JSON', + EditJSONButton: 'Edit JSON', EditVariablesButton: 'Edit variables', EditDatasourcesButton: 'Edit datasources', AddPanelButton: 'Add panel', @@ -254,6 +261,9 @@ export const persesAriaLabels = { EditPanelDuplicateButtonPrefix: 'duplicate panel ', EditPanelDeleteButtonPrefix: 'delete panel ', EditPanelMovePanelButtonPrefix: 'move panel ', + PanelExportTimeSeriesDataAsCSV: 'Export time series data as CSV', + //Add Panel tabs + AddPanelTabs: 'Panel configuration tabs', }; //data-testid from MUI components