From 827041fe73d7ea99ef71b5d71ea7881261e877a9 Mon Sep 17 00:00:00 2001 From: Evelyn Tanigawa Murasaki Date: Mon, 29 Dec 2025 18:54:40 -0300 Subject: [PATCH] edit perses dashboards --- web/cypress/e2e/coo/01.coo_bvt.cy.ts | 2 + .../e2e/perses/02.coo_edit_perses_admin.cy.ts | 45 + .../openshift-cluster-sample-dashboard.yaml | 0 .../perses-dashboard-sample.yaml | 0 .../perses-datasource-sample.yaml | 14 + .../prometheus-overview-variables.yaml | 0 .../thanos-compact-overview-1var.yaml | 0 .../thanos-querier-datasource.yaml | 0 .../openshift-cluster-sample-dashboard.yaml | 1041 ++++++++++++ .../perses-dashboard-sample.yaml | 564 +++++++ .../prometheus-overview-variables.yaml | 461 ++++++ .../thanos-compact-overview-1var.yaml | 1421 +++++++++++++++++ .../thanos-querier-datasource.yaml | 24 + web/cypress/fixtures/perses/constants.ts | 63 +- .../support/commands/operator-commands.ts | 98 +- .../perses/00.coo_bvt_perses_admin.cy.ts | 12 +- .../perses/00.coo_bvt_perses_admin_1.cy.ts | 27 +- .../perses/02.coo_edit_perses_admin.cy.ts | 517 ++++++ .../perses/02.coo_edit_perses_admin_1.cy.ts | 318 ++++ web/cypress/views/common.ts | 6 + web/cypress/views/list-perses-dashboards.ts | 1 + .../perses-dashboards-edit-datasources.ts | 95 ++ .../views/perses-dashboards-edit-variables.ts | 139 ++ web/cypress/views/perses-dashboards-panel.ts | 116 ++ .../views/perses-dashboards-panelgroup.ts | 96 ++ web/cypress/views/perses-dashboards.ts | 342 +++- web/cypress/views/troubleshooting-panel.ts | 2 + web/src/components/data-test.ts | 66 + 28 files changed, 5381 insertions(+), 89 deletions(-) create mode 100644 web/cypress/e2e/perses/02.coo_edit_perses_admin.cy.ts rename web/cypress/fixtures/coo/{ => coo121_perses_dashboards}/openshift-cluster-sample-dashboard.yaml (100%) rename web/cypress/fixtures/coo/{ => coo121_perses_dashboards}/perses-dashboard-sample.yaml (100%) create mode 100644 web/cypress/fixtures/coo/coo121_perses_dashboards/perses-datasource-sample.yaml rename web/cypress/fixtures/coo/{ => coo121_perses_dashboards}/prometheus-overview-variables.yaml (100%) rename web/cypress/fixtures/coo/{ => coo121_perses_dashboards}/thanos-compact-overview-1var.yaml (100%) rename web/cypress/fixtures/coo/{ => coo121_perses_dashboards}/thanos-querier-datasource.yaml (100%) create mode 100644 web/cypress/fixtures/coo/coo141_perses_dashboards/openshift-cluster-sample-dashboard.yaml create mode 100644 web/cypress/fixtures/coo/coo141_perses_dashboards/perses-dashboard-sample.yaml create mode 100644 web/cypress/fixtures/coo/coo141_perses_dashboards/prometheus-overview-variables.yaml create mode 100644 web/cypress/fixtures/coo/coo141_perses_dashboards/thanos-compact-overview-1var.yaml create mode 100644 web/cypress/fixtures/coo/coo141_perses_dashboards/thanos-querier-datasource.yaml create mode 100644 web/cypress/support/perses/02.coo_edit_perses_admin.cy.ts create mode 100644 web/cypress/support/perses/02.coo_edit_perses_admin_1.cy.ts create mode 100644 web/cypress/views/perses-dashboards-edit-datasources.ts create mode 100644 web/cypress/views/perses-dashboards-edit-variables.ts create mode 100644 web/cypress/views/perses-dashboards-panel.ts create mode 100644 web/cypress/views/perses-dashboards-panelgroup.ts diff --git a/web/cypress/e2e/coo/01.coo_bvt.cy.ts b/web/cypress/e2e/coo/01.coo_bvt.cy.ts index 3a23242b..fd997194 100644 --- a/web/cypress/e2e/coo/01.coo_bvt.cy.ts +++ b/web/cypress/e2e/coo/01.coo_bvt.cy.ts @@ -28,6 +28,8 @@ describe('BVT: COO', { tags: ['@smoke', '@coo'] }, () => { it('1. Admin perspective - Observe Menu', () => { cy.log('Admin perspective - Observe Menu and verify all submenus'); + cy.reload(true); + cy.wait(10000); nav.sidenav.clickNavLink(['Observe', 'Alerting']); commonPages.titleShouldHaveText('Alerting'); nav.tabs.switchTab('Silences'); diff --git a/web/cypress/e2e/perses/02.coo_edit_perses_admin.cy.ts b/web/cypress/e2e/perses/02.coo_edit_perses_admin.cy.ts new file mode 100644 index 00000000..01417416 --- /dev/null +++ b/web/cypress/e2e/perses/02.coo_edit_perses_admin.cy.ts @@ -0,0 +1,45 @@ +import { nav } from '../../views/nav'; +import { runCOOEditPersesTests1 } from '../../support/perses/02.coo_edit_perses_admin_1.cy'; +import { runCOOEditPersesTests } from '../../support/perses/02.coo_edit_perses_admin.cy'; + +// Set constants for the operators that need to be installed for tests. +const MCP = { + namespace: 'openshift-cluster-observability-operator', + packageName: 'cluster-observability-operator', + operatorName: 'Cluster Observability Operator', + config: { + kind: 'UIPlugin', + name: 'monitoring', + }, +}; + +const MP = { + namespace: 'openshift-monitoring', + operatorName: 'Cluster Monitoring Operator', +}; + +//TODO: change tag to @dashboards when customizable-dashboards gets merged +describe('COO - Dashboards (Perses) - Edit perses dashboard', { tags: ['@perses', '@dashboards-'] }, () => { + + before(() => { + cy.beforeBlockCOO(MCP, MP); + }); + + beforeEach(() => { + nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); + cy.wait(5000); + cy.changeNamespace('All Projects'); + }); + + runCOOEditPersesTests({ + name: 'Administrator', + }); + + runCOOEditPersesTests1({ + name: 'Administrator', + }); + +}); + + + diff --git a/web/cypress/fixtures/coo/openshift-cluster-sample-dashboard.yaml b/web/cypress/fixtures/coo/coo121_perses_dashboards/openshift-cluster-sample-dashboard.yaml similarity index 100% rename from web/cypress/fixtures/coo/openshift-cluster-sample-dashboard.yaml rename to web/cypress/fixtures/coo/coo121_perses_dashboards/openshift-cluster-sample-dashboard.yaml diff --git a/web/cypress/fixtures/coo/perses-dashboard-sample.yaml b/web/cypress/fixtures/coo/coo121_perses_dashboards/perses-dashboard-sample.yaml similarity index 100% rename from web/cypress/fixtures/coo/perses-dashboard-sample.yaml rename to web/cypress/fixtures/coo/coo121_perses_dashboards/perses-dashboard-sample.yaml diff --git a/web/cypress/fixtures/coo/coo121_perses_dashboards/perses-datasource-sample.yaml b/web/cypress/fixtures/coo/coo121_perses_dashboards/perses-datasource-sample.yaml new file mode 100644 index 00000000..cf7df024 --- /dev/null +++ b/web/cypress/fixtures/coo/coo121_perses_dashboards/perses-datasource-sample.yaml @@ -0,0 +1,14 @@ +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/prometheus-overview-variables.yaml b/web/cypress/fixtures/coo/coo121_perses_dashboards/prometheus-overview-variables.yaml similarity index 100% rename from web/cypress/fixtures/coo/prometheus-overview-variables.yaml rename to web/cypress/fixtures/coo/coo121_perses_dashboards/prometheus-overview-variables.yaml diff --git a/web/cypress/fixtures/coo/thanos-compact-overview-1var.yaml b/web/cypress/fixtures/coo/coo121_perses_dashboards/thanos-compact-overview-1var.yaml similarity index 100% rename from web/cypress/fixtures/coo/thanos-compact-overview-1var.yaml rename to web/cypress/fixtures/coo/coo121_perses_dashboards/thanos-compact-overview-1var.yaml diff --git a/web/cypress/fixtures/coo/thanos-querier-datasource.yaml b/web/cypress/fixtures/coo/coo121_perses_dashboards/thanos-querier-datasource.yaml similarity index 100% rename from web/cypress/fixtures/coo/thanos-querier-datasource.yaml rename to web/cypress/fixtures/coo/coo121_perses_dashboards/thanos-querier-datasource.yaml diff --git a/web/cypress/fixtures/coo/coo141_perses_dashboards/openshift-cluster-sample-dashboard.yaml b/web/cypress/fixtures/coo/coo141_perses_dashboards/openshift-cluster-sample-dashboard.yaml new file mode 100644 index 00000000..e8c14b90 --- /dev/null +++ b/web/cypress/fixtures/coo/coo141_perses_dashboards/openshift-cluster-sample-dashboard.yaml @@ -0,0 +1,1041 @@ +apiVersion: perses.dev/v1alpha2 +kind: PersesDashboard +metadata: + name: openshift-cluster-sample-dashboard + namespace: openshift-cluster-observability-operator +spec: + config: + display: + name: Kubernetes / Compute Resources / Cluster + variables: + - kind: ListVariable + spec: + display: + hidden: false + allowAllValue: false + allowMultiple: false + sort: alphabetical-asc + plugin: + kind: PrometheusLabelValuesVariable + spec: + labelName: cluster + matchers: + - up{job="kubelet", metrics_path="/metrics/cadvisor"} + name: cluster + panels: + "0_0": + kind: Panel + spec: + display: + name: CPU Utilisation + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent-decimal + thresholds: + steps: + - color: green + value: 0 + - color: red + value: 80 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: cluster:node_cpu:ratio_rate5m{cluster="$cluster"} + "0_1": + kind: Panel + spec: + display: + name: CPU Requests Commitment + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent-decimal + thresholds: + steps: + - color: green + value: 0 + - color: red + value: 80 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_cpu:kube_pod_container_resource_requests:sum{cluster="$cluster"}) / sum(kube_node_status_allocatable{job="kube-state-metrics",resource="cpu",cluster="$cluster"}) + "0_2": + kind: Panel + spec: + display: + name: CPU Limits Commitment + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent-decimal + thresholds: + steps: + - color: green + value: 0 + - color: red + value: 80 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_cpu:kube_pod_container_resource_limits:sum{cluster="$cluster"}) / sum(kube_node_status_allocatable{job="kube-state-metrics",resource="cpu",cluster="$cluster"}) + "0_3": + kind: Panel + spec: + display: + name: Memory Utilisation + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent-decimal + thresholds: + steps: + - color: green + value: 0 + - color: red + value: 80 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: 1 - sum(:node_memory_MemAvailable_bytes:sum{cluster="$cluster"}) / sum(node_memory_MemTotal_bytes{job="node-exporter",cluster="$cluster"}) + "0_4": + kind: Panel + spec: + display: + name: Memory Requests Commitment + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent-decimal + thresholds: + steps: + - color: green + value: 0 + - color: red + value: 80 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_memory:kube_pod_container_resource_requests:sum{cluster="$cluster"}) / sum(kube_node_status_allocatable{job="kube-state-metrics",resource="memory",cluster="$cluster"}) + "0_5": + kind: Panel + spec: + display: + name: Memory Limits Commitment + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent-decimal + thresholds: + steps: + - color: green + value: 0 + - color: red + value: 80 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_memory:kube_pod_container_resource_limits:sum{cluster="$cluster"}) / sum(kube_node_status_allocatable{job="kube-state-metrics",resource="memory",cluster="$cluster"}) + "1_0": + kind: Panel + spec: + display: + name: CPU Usage + plugin: + kind: TimeSeriesChart + spec: + legend: + mode: list + position: bottom + values: [] + visual: + areaOpacity: 1 + connectNulls: false + display: line + lineWidth: 0.25 + stack: all + yAxis: + format: + unit: decimal + min: 0 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster="$cluster"}) by (namespace) + seriesNameFormat: "{{namespace}}" + "2_0": + kind: Panel + spec: + display: + name: CPU Quota + plugin: + kind: Table + spec: + columnSettings: + - header: Time + hide: true + name: Time + - header: Pods + name: "Value #A" + - header: Workloads + name: "Value #B" + - header: CPU Usage + name: "Value #C" + - header: CPU Requests + name: "Value #D" + - header: CPU Requests % + name: "Value #E" + - header: CPU Limits + name: "Value #F" + - header: CPU Limits % + name: "Value #G" + - header: Namespace + name: namespace + - header: "" + name: /.*/ + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(kube_pod_owner{job="kube-state-metrics", cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: count(avg(namespace_workload_pod:kube_pod_owner:relabel{cluster="$cluster"}) by (workload, namespace)) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_cpu:kube_pod_container_resource_requests:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster="$cluster"}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_requests:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_cpu:kube_pod_container_resource_limits:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster="$cluster"}) by (namespace) / sum(namespace_cpu:kube_pod_container_resource_limits:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + "3_0": + kind: Panel + spec: + display: + name: Memory Usage (w/o cache) + plugin: + kind: TimeSeriesChart + spec: + legend: + mode: list + position: bottom + values: [] + visual: + areaOpacity: 1 + connectNulls: false + display: line + lineWidth: 0.25 + stack: all + yAxis: + format: + unit: bytes + min: 0 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(container_memory_rss{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", container!=""}) by (namespace) + seriesNameFormat: "{{namespace}}" + "4_0": + kind: Panel + spec: + display: + name: Requests by Namespace + plugin: + kind: Table + spec: + columnSettings: + - header: Time + hide: true + name: Time + - header: Pods + name: "Value #A" + - header: Workloads + name: "Value #B" + - header: Memory Usage + name: "Value #C" + - header: Memory Requests + name: "Value #D" + - header: Memory Requests % + name: "Value #E" + - header: Memory Limits + name: "Value #F" + - header: Memory Limits % + name: "Value #G" + - header: Namespace + name: namespace + - header: "" + name: /.*/ + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(kube_pod_owner{job="kube-state-metrics", cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: count(avg(namespace_workload_pod:kube_pod_owner:relabel{cluster="$cluster"}) by (workload, namespace)) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(container_memory_rss{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", container!=""}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_memory:kube_pod_container_resource_requests:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(container_memory_rss{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", container!=""}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_requests:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(namespace_memory:kube_pod_container_resource_limits:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(container_memory_rss{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", container!=""}) by (namespace) / sum(namespace_memory:kube_pod_container_resource_limits:sum{cluster="$cluster"}) by (namespace) + seriesNameFormat: "" + "5_0": + kind: Panel + spec: + display: + name: Current Network Usage + plugin: + kind: Table + spec: + columnSettings: + - header: Time + hide: true + name: Time + - header: Current Receive Bandwidth + name: "Value #A" + - header: Current Transmit Bandwidth + name: "Value #B" + - header: Rate of Received Packets + name: "Value #C" + - header: Rate of Transmitted Packets + name: "Value #D" + - header: Rate of Received Packets Dropped + name: "Value #E" + - header: Rate of Transmitted Packets Dropped + name: "Value #F" + - header: Namespace + name: namespace + - header: "" + name: /.*/ + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_receive_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_transmit_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_receive_packets_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_transmit_packets_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_receive_packets_dropped_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_transmit_packets_dropped_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "" + "6_0": + kind: Panel + spec: + display: + name: Receive Bandwidth + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_receive_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "6_1": + kind: Panel + spec: + display: + name: Transmit Bandwidth + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_transmit_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "7_0": + kind: Panel + spec: + display: + name: "Average Container Bandwidth by Namespace: Received" + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: avg(irate(container_network_receive_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "7_1": + kind: Panel + spec: + display: + name: "Average Container Bandwidth by Namespace: Transmitted" + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: avg(irate(container_network_transmit_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "8_0": + kind: Panel + spec: + display: + name: Rate of Received Packets + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_receive_packets_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "8_1": + kind: Panel + spec: + display: + name: Rate of Transmitted Packets + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_transmit_packets_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "9_0": + kind: Panel + spec: + display: + name: Rate of Received Packets Dropped + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_receive_packets_dropped_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "9_1": + kind: Panel + spec: + display: + name: Rate of Transmitted Packets Dropped + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum(irate(container_network_transmit_packets_dropped_total{job="kubelet", metrics_path="/metrics/cadvisor", cluster="$cluster", namespace=~".+"}[$__rate_interval])) by (namespace) + seriesNameFormat: "{{namespace}}" + "10_0": + kind: Panel + spec: + display: + name: IOPS(Reads+Writes) + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: ceil(sum by(namespace) (rate(container_fs_reads_total{job="kubelet", metrics_path="/metrics/cadvisor", id!="", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", cluster="$cluster", namespace!=""}[$__rate_interval]) + rate(container_fs_writes_total{job="kubelet", metrics_path="/metrics/cadvisor", id!="", cluster="$cluster", namespace!=""}[$__rate_interval]))) + seriesNameFormat: "{{namespace}}" + "10_1": + kind: Panel + spec: + display: + name: ThroughPut(Read+Write) + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_reads_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", id!="", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", cluster="$cluster", namespace!=""}[$__rate_interval]) + rate(container_fs_writes_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "{{namespace}}" + "11_0": + kind: Panel + spec: + display: + name: Current Storage IO + plugin: + kind: Table + spec: + columnSettings: + - header: Time + hide: true + name: Time + - header: IOPS(Reads) + name: "Value #A" + - header: IOPS(Writes) + name: "Value #B" + - header: IOPS(Reads + Writes) + name: "Value #C" + - header: Throughput(Read) + name: "Value #D" + - header: Throughput(Write) + name: "Value #E" + - header: Throughput(Read + Write) + name: "Value #F" + - header: Namespace + name: namespace + - header: "" + name: /.*/ + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_reads_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_writes_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_reads_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval]) + rate(container_fs_writes_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_reads_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_writes_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by(namespace) (rate(container_fs_reads_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval]) + rate(container_fs_writes_bytes_total{job="kubelet", metrics_path="/metrics/cadvisor", device=~"(/dev.+)|mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+", id!="", cluster="$cluster", namespace!=""}[$__rate_interval])) + seriesNameFormat: "" + layouts: + - kind: Grid + spec: + display: + title: Headlines + collapse: + open: true + items: + - x: 0 + "y": 1 + width: 4 + height: 3 + content: + $ref: "#/spec/panels/0_0" + - x: 4 + "y": 1 + width: 4 + height: 3 + content: + $ref: "#/spec/panels/0_1" + - x: 8 + "y": 1 + width: 4 + height: 3 + content: + $ref: "#/spec/panels/0_2" + - x: 12 + "y": 1 + width: 4 + height: 3 + content: + $ref: "#/spec/panels/0_3" + - x: 16 + "y": 1 + width: 4 + height: 3 + content: + $ref: "#/spec/panels/0_4" + - x: 20 + "y": 1 + width: 4 + height: 3 + content: + $ref: "#/spec/panels/0_5" + - kind: Grid + spec: + display: + title: CPU + collapse: + open: true + items: + - x: 0 + "y": 5 + width: 24 + height: 7 + content: + $ref: "#/spec/panels/1_0" + - kind: Grid + spec: + display: + title: CPU Quota + collapse: + open: true + items: + - x: 0 + "y": 13 + width: 24 + height: 7 + content: + $ref: "#/spec/panels/2_0" + - kind: Grid + spec: + display: + title: Memory + collapse: + open: true + items: + - x: 0 + "y": 21 + width: 24 + height: 7 + content: + $ref: "#/spec/panels/3_0" + - kind: Grid + spec: + display: + title: Memory Requests + collapse: + open: true + items: + - x: 0 + "y": 29 + width: 24 + height: 7 + content: + $ref: "#/spec/panels/4_0" + - kind: Grid + spec: + display: + title: Current Network Usage + collapse: + open: true + items: + - x: 0 + "y": 37 + width: 24 + height: 7 + content: + $ref: "#/spec/panels/5_0" + - kind: Grid + spec: + display: + title: Bandwidth + collapse: + open: true + items: + - x: 0 + "y": 45 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/6_0" + - x: 12 + "y": 45 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/6_1" + - kind: Grid + spec: + display: + title: Average Container Bandwidth by Namespace + collapse: + open: true + items: + - x: 0 + "y": 53 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/7_0" + - x: 12 + "y": 53 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/7_1" + - kind: Grid + spec: + display: + title: Rate of Packets + collapse: + open: true + items: + - x: 0 + "y": 61 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/8_0" + - x: 12 + "y": 61 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/8_1" + - kind: Grid + spec: + display: + title: Rate of Packets Dropped + collapse: + open: true + items: + - x: 0 + "y": 69 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/9_0" + - x: 12 + "y": 69 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/9_1" + - kind: Grid + spec: + display: + title: Storage IO + collapse: + open: true + items: + - x: 0 + "y": 77 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/10_0" + - x: 12 + "y": 77 + width: 12 + height: 7 + content: + $ref: "#/spec/panels/10_1" + - kind: Grid + spec: + display: + title: Storage IO - Distribution + collapse: + open: true + items: + - x: 0 + "y": 85 + width: 24 + height: 7 + content: + $ref: "#/spec/panels/11_0" + duration: 1h \ No newline at end of file diff --git a/web/cypress/fixtures/coo/coo141_perses_dashboards/perses-dashboard-sample.yaml b/web/cypress/fixtures/coo/coo141_perses_dashboards/perses-dashboard-sample.yaml new file mode 100644 index 00000000..43e3dfe4 --- /dev/null +++ b/web/cypress/fixtures/coo/coo141_perses_dashboards/perses-dashboard-sample.yaml @@ -0,0 +1,564 @@ +apiVersion: perses.dev/v1alpha2 +kind: PersesDashboard +metadata: + name: perses-dashboard-sample + namespace: perses-dev +spec: + config: + display: + name: Perses Dashboard Sample + description: This is a sample dashboard + duration: 5m + datasources: + PrometheusLocal: + default: false + plugin: + kind: PrometheusDatasource + spec: + proxy: + kind: HTTPProxy + spec: + url: http://localhost:9090 + variables: + - kind: ListVariable + spec: + name: job + allowMultiple: false + allowAllValue: false + plugin: + kind: PrometheusLabelValuesVariable + spec: + labelName: job + - kind: ListVariable + spec: + name: instance + allowMultiple: false + allowAllValue: false + plugin: + kind: PrometheusLabelValuesVariable + spec: + labelName: instance + matchers: + - up{job=~"$job"} + - kind: ListVariable + spec: + name: interval + plugin: + kind: StaticListVariable + spec: + values: + - 1m + - 5m + - kind: TextVariable + spec: + name: text + value: test + constant: true + panels: + defaultTimeSeriesChart: + kind: Panel + spec: + display: + name: Default Time Series Panel + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: up + seriesTest: + kind: Panel + spec: + display: + name: "~130 Series" + description: This is a line chart + plugin: + kind: TimeSeriesChart + spec: + yAxis: + format: + unit: bytes + shortValues: true + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: rate(caddy_http_response_duration_seconds_sum[$interval]) + basicEx: + kind: Panel + spec: + display: + name: Single Query + plugin: + kind: TimeSeriesChart + spec: + yAxis: + format: + unit: decimal + legend: + position: right + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: Node memory - {{device}} {{instance}} + query: + 1 - node_filesystem_free_bytes{job='$job',instance=~'$instance',fstype!="rootfs",mountpoint!~"/(run|var).*",mountpoint!=""} + / node_filesystem_size_bytes{job='$job',instance=~'$instance'} + legendEx: + kind: Panel + spec: + display: + name: Legend Example + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + yAxis: + show: true + format: + unit: bytes + shortValues: true + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: Node memory total + query: + node_memory_MemTotal_bytes{job='$job',instance=~'$instance'} + - node_memory_MemFree_bytes{job='$job',instance=~'$instance'} - + node_memory_Buffers_bytes{job='$job',instance=~'$instance'} - node_memory_Cached_bytes{job='$job',instance=~'$instance'} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: Memory (buffers) - {{instance}} + query: node_memory_Buffers_bytes{job='$job',instance=~'$instance'} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: Cached Bytes + query: node_memory_Cached_bytes{job='$job',instance=~'$instance'} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: MemFree Bytes + query: node_memory_MemFree_bytes{job='$job',instance=~'$instance'} + testNodeQuery: + kind: Panel + spec: + display: + name: Test Query + description: Description text + plugin: + kind: TimeSeriesChart + spec: + yAxis: + format: + unit: decimal + decimalPlaces: 2 + legend: + position: right + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: node_load15{instance=~"(demo.do.prometheus.io:9100)",job='$job'} + seriesNameFormat: Test {{job}} {{instance}} + testQueryAlt: + kind: Panel + spec: + display: + name: Test Query Alt + description: Description text + plugin: + kind: TimeSeriesChart + spec: + legend: + position: right + yAxis: + format: + unit: percent-decimal + decimalPlaces: 1 + thresholds: + steps: + - value: 0.4 + name: "Alert: Warning condition example" + - value: 0.75 + name: "Alert: Critical condition example" + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: node_load1{instance=~"(demo.do.prometheus.io:9100)",job='$job'} + cpuLine: + kind: Panel + spec: + display: + name: CPU - Line (Multi Series) + description: This is a line chart test + plugin: + kind: TimeSeriesChart + spec: + yAxis: + show: false + label: CPU Label + format: + unit: percent-decimal + decimalPlaces: 0 + legend: + position: bottom + thresholds: + steps: + - value: 0.2 + - value: 0.35 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: "{{mode}} mode - {{job}} {{instance}}" + query: avg without (cpu)(rate(node_cpu_seconds_total{job='$job',instance=~'$instance',mode!="nice",mode!="steal",mode!="irq"}[$interval])) + cpuGauge: + kind: Panel + spec: + display: + name: CPU - Gauge (Multi Series) + description: This is a gauge chart test + plugin: + kind: GaugeChart + spec: + calculation: last-number + format: + unit: percent-decimal + thresholds: + steps: + - value: 0.2 + - value: 0.35 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + seriesNameFormat: "{{mode}} mode - {{job}} {{instance}}" + query: avg without (cpu)(rate(node_cpu_seconds_total{job='$job',instance=~'$instance',mode!="nice",mode!="steal",mode!="irq"}[$interval])) + statSm: + kind: Panel + spec: + display: + name: Stat Sm + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: decimal + decimalPlaces: 1 + shortValues: true + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: node_time_seconds{job='$job',instance=~'$instance'} - node_boot_time_seconds{job='$job',instance=~'$instance'} + gaugeRAM: + kind: Panel + spec: + display: + name: RAM Used + description: This is a stat chart + plugin: + kind: GaugeChart + spec: + calculation: last-number + format: + unit: percent + thresholds: + steps: + - value: 85 + - value: 95 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: + 100 - ((node_memory_MemAvailable_bytes{job='$job',instance=~'$instance'} + * 100) / node_memory_MemTotal_bytes{job='$job',instance=~'$instance'}) + statRAM: + kind: Panel + spec: + display: + name: RAM Used + description: This is a stat chart + plugin: + kind: StatChart + spec: + calculation: last-number + format: + unit: percent + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: + 100 - ((node_memory_MemAvailable_bytes{job='$job',instance=~'$instance'} + * 100) / node_memory_MemTotal_bytes{job='$job',instance=~'$instance'}) + statTotalRAM: + kind: Panel + spec: + display: + name: RAM Total + description: This is a stat chart + plugin: + kind: StatChart + spec: + calculation: last-number + format: + unit: bytes + decimalPlaces: 1 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: node_memory_MemTotal_bytes{job='$job',instance=~'$instance'} + statMd: + kind: Panel + spec: + display: + name: Stat Md + plugin: + kind: StatChart + spec: + calculation: sum + format: + unit: decimal + decimalPlaces: 2 + shortValues: true + sparkline: + color: "#e65013" + width: 1.5 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: + avg(node_load15{job='node',instance=~'$instance'}) / count(count(node_cpu_seconds_total{job='node',instance=~'$instance'}) + by (cpu)) * 100 + statLg: + kind: Panel + spec: + display: + name: Stat Lg + description: This is a stat chart + plugin: + kind: StatChart + spec: + calculation: mean + format: + unit: percent + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: + (((count(count(node_cpu_seconds_total{job='$job',instance=~'$instance'}) + by (cpu))) - avg(sum by (mode)(rate(node_cpu_seconds_total{mode="idle",job='$job',instance=~'$instance'}[$interval])))) + * 100) / count(count(node_cpu_seconds_total{job='$job',instance=~'$instance'}) + by (cpu)) + gaugeEx: + kind: Panel + spec: + display: + name: Gauge Ex + description: This is a gauge chart + plugin: + kind: GaugeChart + spec: + calculation: last-number + format: + unit: percent + thresholds: + steps: + - value: 85 + - value: 95 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: + (((count(count(node_cpu_seconds_total{job='$job',instance=~'$instance'}) + by (cpu))) - avg(sum by (mode)(rate(node_cpu_seconds_total{mode="idle",job='$job',instance=~'$instance'}[$interval])))) + * 100) / count(count(node_cpu_seconds_total{job='$job',instance=~'$instance'}) + by (cpu)) + gaugeAltEx: + kind: Panel + spec: + display: + name: Gauge Alt Ex + description: GaugeChart description text + plugin: + kind: GaugeChart + spec: + calculation: last-number + format: + unit: percent-decimal + decimalPlaces: 1 + thresholds: + steps: + - value: 0.5 + name: "Alert: Warning condition example" + - value: 0.75 + name: "Alert: Critical condition example" + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: node_load15{instance=~'$instance',job='$job'} + gaugeFormatTest: + kind: Panel + spec: + display: + name: Gauge Format Test + plugin: + kind: GaugeChart + spec: + calculation: last-number + format: + unit: bytes + max: 95000000 + thresholds: + steps: + - value: 71000000 + - value: 82000000 + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: node_time_seconds{job='$job',instance=~'$instance'} - node_boot_time_seconds{job='$job',instance=~'$instance'} + layouts: + - kind: Grid + spec: + display: + title: Row 1 + collapse: + open: true + items: + - x: 0 + "y": 0 + width: 2 + height: 3 + content: + "$ref": "#/spec/panels/statRAM" + - x: 0 + "y": 4 + width: 2 + height: 3 + content: + "$ref": "#/spec/panels/statTotalRAM" + - x: 2 + "y": 0 + width: 4 + height: 6 + content: + "$ref": "#/spec/panels/statMd" + - x: 6 + "y": 0 + width: 10 + height: 6 + content: + "$ref": "#/spec/panels/statLg" + - x: 16 + "y": 0 + width: 4 + height: 6 + content: + "$ref": "#/spec/panels/gaugeFormatTest" + - x: 20 + "y": 0 + width: 4 + height: 6 + content: + "$ref": "#/spec/panels/gaugeRAM" + - kind: Grid + spec: + display: + title: Row 2 + collapse: + open: true + items: + - x: 0 + "y": 0 + width: 12 + height: 6 + content: + "$ref": "#/spec/panels/legendEx" + - x: 12 + "y": 0 + width: 12 + height: 6 + content: + "$ref": "#/spec/panels/basicEx" + - kind: Grid + spec: + display: + title: Row 3 + collapse: + open: false + items: + - x: 0 + "y": 0 + width: 24 + height: 6 + content: + "$ref": "#/spec/panels/cpuGauge" + - x: 0 + "y": 6 + width: 12 + height: 8 + content: + "$ref": "#/spec/panels/cpuLine" + - x: 12 + "y": 0 + width: 12 + height: 8 + content: + "$ref": "#/spec/panels/defaultTimeSeriesChart" \ No newline at end of file diff --git a/web/cypress/fixtures/coo/coo141_perses_dashboards/prometheus-overview-variables.yaml b/web/cypress/fixtures/coo/coo141_perses_dashboards/prometheus-overview-variables.yaml new file mode 100644 index 00000000..6c8c4439 --- /dev/null +++ b/web/cypress/fixtures/coo/coo141_perses_dashboards/prometheus-overview-variables.yaml @@ -0,0 +1,461 @@ +apiVersion: perses.dev/v1alpha2 +kind: PersesDashboard +metadata: + name: prometheus-overview + namespace: perses-dev +spec: + config: + display: + name: Prometheus / Overview + variables: + - kind: ListVariable + spec: + display: + name: job + hidden: false + allowAllValue: false + allowMultiple: false + plugin: + kind: PrometheusLabelValuesVariable + spec: + datasource: + kind: PrometheusDatasource + + labelName: job + matchers: + - prometheus_build_info{} + name: job + - kind: ListVariable + spec: + display: + name: instance + hidden: false + allowAllValue: false + allowMultiple: false + plugin: + kind: PrometheusLabelValuesVariable + spec: + datasource: + kind: PrometheusDatasource + + labelName: instance + matchers: + - prometheus_build_info{job="$job"} + name: instance + panels: + "0_0": + kind: Panel + spec: + display: + name: Prometheus Stats + plugin: + kind: Table + spec: + columnSettings: + - name: job + header: Job + - name: instance + header: Instance + - name: version + header: Version + - name: value + hide: true + - name: timestamp + hide: true + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: count by (job, instance, version) (prometheus_build_info{instance=~"$instance",job=~"$job"}) + "1_0": + kind: Panel + spec: + display: + name: Target Sync + description: Monitors target synchronization time for Prometheus instances + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (job, scrape_job, instance) ( + rate(prometheus_target_sync_length_seconds_sum{instance=~"$instance",job=~"$job"}[$__rate_interval]) + ) + seriesNameFormat: "{{job}} - {{instance}} - Metrics" + "1_1": + kind: Panel + spec: + display: + name: Targets + description: Shows discovered targets across Prometheus instances + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by (job, instance) (prometheus_sd_discovered_targets{instance=~"$instance",job=~"$job"}) + seriesNameFormat: "{{job}} - {{instance}} - Metrics" + "2_0": + kind: Panel + spec: + display: + name: Average Scrape Interval Duration + description: Shows average interval between scrapes for Prometheus targets + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |4- + rate( + prometheus_target_interval_length_seconds_sum{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + / + rate( + prometheus_target_interval_length_seconds_count{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + seriesNameFormat: "{{job}} - {{instance}} - {{interval}} Configured" + "2_1": + kind: Panel + spec: + display: + name: Scrape failures + description: Shows scrape failure metrics for Prometheus targets + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (job, instance) ( + rate( + prometheus_target_scrapes_exceeded_body_size_limit_total{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + ) + seriesNameFormat: "exceeded body size limit: {{job}} - {{instance}} - Metrics" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (job, instance) ( + rate( + prometheus_target_scrapes_exceeded_sample_limit_total{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + ) + seriesNameFormat: "exceeded sample limit: {{job}} - {{instance}} - Metrics" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (job, instance) ( + rate( + prometheus_target_scrapes_sample_duplicate_timestamp_total{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + ) + seriesNameFormat: "duplicate timestamp: {{job}} - {{instance}} - Metrics" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (job, instance) ( + rate( + prometheus_target_scrapes_sample_out_of_bounds_total{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + ) + seriesNameFormat: "out of bounds: {{job}} - {{instance}} - Metrics" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (job, instance) ( + rate( + prometheus_target_scrapes_sample_out_of_order_total{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + ) + seriesNameFormat: "out of order: {{job}} - {{instance}} - Metrics" + "2_2": + kind: Panel + spec: + display: + name: Appended Samples + description: Shows rate of samples appended to Prometheus TSDB + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + rate( + prometheus_tsdb_head_samples_appended_total{instance=~"$instance",job=~"$job"}[$__rate_interval] + ) + seriesNameFormat: "{{job}} - {{instance}} - {{remote_name}} - {{url}}" + "3_0": + kind: Panel + spec: + display: + name: Head Series + description: Shows number of series in Prometheus TSDB head + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: prometheus_tsdb_head_series{instance=~"$instance",job=~"$job"} + seriesNameFormat: "{{job}} - {{instance}} - Head Series" + "3_1": + kind: Panel + spec: + display: + name: Head Chunks + description: Shows number of chunks in Prometheus TSDB head + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: prometheus_tsdb_head_chunks{instance=~"$instance",job=~"$job"} + seriesNameFormat: "{{job}} - {{instance}} - Head Chunks" + "4_0": + kind: Panel + spec: + display: + name: Query Rate + description: Shows Prometheus query rate metrics + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + rate( + prometheus_engine_query_duration_seconds_count{instance=~"$instance",job=~"$job",slice="inner_eval"}[$__rate_interval] + ) + seriesNameFormat: "{{job}} - {{instance}} - Query Rate" + "4_1": + kind: Panel + spec: + display: + name: Stage Duration + description: Shows duration of different Prometheus query stages + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + max by (slice) ( + prometheus_engine_query_duration_seconds{instance=~"$instance",job=~"$job",quantile="0.9"} + ) + seriesNameFormat: "{{slice}} - Duration" + layouts: + - kind: Grid + spec: + display: + title: Prometheus Stats + items: + - x: 0 + "y": 0 + width: 24 + height: 8 + content: + $ref: "#/spec/panels/0_0" + - kind: Grid + spec: + display: + title: Discovery + items: + - x: 0 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/1_0" + - x: 12 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/1_1" + - kind: Grid + spec: + display: + title: Retrieval + items: + - x: 0 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/2_0" + - x: 8 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/2_1" + - x: 16 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/2_2" + - kind: Grid + spec: + display: + title: Storage + items: + - x: 0 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/3_0" + - x: 12 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/3_1" + - kind: Grid + spec: + display: + title: Query + items: + - x: 0 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/4_0" + - x: 12 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/4_1" + duration: 1h \ No newline at end of file diff --git a/web/cypress/fixtures/coo/coo141_perses_dashboards/thanos-compact-overview-1var.yaml b/web/cypress/fixtures/coo/coo141_perses_dashboards/thanos-compact-overview-1var.yaml new file mode 100644 index 00000000..caa58060 --- /dev/null +++ b/web/cypress/fixtures/coo/coo141_perses_dashboards/thanos-compact-overview-1var.yaml @@ -0,0 +1,1421 @@ +apiVersion: perses.dev/v1alpha2 +kind: PersesDashboard +metadata: + name: thanos-compact-overview + namespace: perses-dev +spec: + config: + display: + name: Thanos / Compact / Overview + variables: + - kind: ListVariable + spec: + display: + name: job + hidden: false + allowAllValue: false + allowMultiple: true + plugin: + kind: PrometheusLabelValuesVariable + spec: + datasource: + kind: PrometheusDatasource + + labelName: job + matchers: + - thanos_build_info{container="thanos-compact"} + name: job + - kind: ListVariable + spec: + display: + name: namespace + hidden: false + allowAllValue: false + allowMultiple: false + plugin: + kind: PrometheusLabelValuesVariable + spec: + datasource: + kind: PrometheusDatasource + + labelName: namespace + matchers: + - thanos_status{} + name: namespace + panels: + "0_0": + kind: Panel + spec: + display: + name: TODO Compaction Blocks + description: Shows number of blocks planned to be compacted. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by (namespace, job) (thanos_compact_todo_compaction_blocks{job=~"$job",namespace="$namespace"}) + seriesNameFormat: "{{job}} {{namespace}}" + "0_1": + kind: Panel + spec: + display: + name: TODO Compactions + description: Shows number of compaction operations to be done. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by (namespace, job) (thanos_compact_todo_compactions{job=~"$job",namespace="$namespace"}) + seriesNameFormat: "{{job}} {{namespace}}" + "0_2": + kind: Panel + spec: + display: + name: TODO Deletions + description: Shows number of blocks that have crossed their retention periods. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by (namespace, job) (thanos_compact_todo_deletion_blocks{job=~"$job",namespace="$namespace"}) + seriesNameFormat: "{{job}} {{namespace}}" + "0_3": + kind: Panel + spec: + display: + name: TODO Downsamples + description: Shows number of blocks to be downsampled. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by (namespace, job) (thanos_compact_todo_downsample_blocks{job=~"$job",namespace="$namespace"}) + seriesNameFormat: "{{job}} {{namespace}}" + "1_0": + kind: Panel + spec: + display: + name: Group Compactions + description: Shows rate of execution of compaction operations against blocks in a bucket, split by compaction resolution. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job, resolution) ( + rate(thanos_compact_group_compactions_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + seriesNameFormat: "Resolution: {{resolution}} - {{job}} {{namespace}}" + "1_1": + kind: Panel + spec: + display: + name: Group Compaction Errors + description: Shows the percentage of errors compared to the total number of executed compaction operations against blocks stored in bucket. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: percent + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |4- + sum by (namespace, job) ( + rate( + thanos_compact_group_compactions_failures_total{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + / + sum by (namespace, job) ( + rate(thanos_compact_group_compactions_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + * + 100 + seriesNameFormat: "{{job}} {{namespace}}" + "2_0": + kind: Panel + spec: + display: + name: Downsample Rate + description: Shows rate of execution of downsample operations against blocks stored in a bucket, split by resolution. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job, resolution) ( + rate(thanos_compact_downsample_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + seriesNameFormat: "Resolution: {{resolution}} - {{job}} {{namespace}}" + "2_1": + kind: Panel + spec: + display: + name: Downsample Errors + description: Shows the percentage of downsample errors compared to the total number of downsample operations done on block in buckets. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: percent + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |4- + sum by (namespace, job) ( + rate(thanos_compact_downsample_failed_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + / + sum by (namespace, job) ( + rate(thanos_compact_downsample_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + * + 100 + seriesNameFormat: "{{job}} {{namespace}}" + "2_2": + kind: Panel + spec: + display: + name: Downsample Durations + description: Shows the p50, p90, and p99 of the time it takes to complete downsample operation against blocks in a bucket, split by resolution. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.5, + sum by (namespace, job, resolution, le) ( + rate( + thanos_compact_downsample_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: "p50 Resolution: {{resolution}} - {{job}} {{namespace}}" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.9, + sum by (namespace, job, resolution, le) ( + rate( + thanos_compact_downsample_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: "p90 Resolution: {{resolution}} - {{job}} {{namespace}}" + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.99, + sum by (namespace, job, resolution, le) ( + rate( + thanos_compact_downsample_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: "p99 Resolution: {{resolution}} - {{job}} {{namespace}}" + "3_0": + kind: Panel + spec: + display: + name: Sync Meta Rate + description: Shows rate of syncing block meta files from bucket into memory. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job) ( + rate(thanos_blocks_meta_syncs_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + seriesNameFormat: "{{job}} {{namespace}}" + "3_1": + kind: Panel + spec: + display: + name: Sync Meta Errors + description: Shows percentage of errors of meta file sync operation compared to total number of meta file syncs from bucket. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: percent + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |4- + sum by (namespace, job) ( + rate(thanos_blocks_meta_sync_failures_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + / + sum by (namespace, job) ( + rate(thanos_blocks_meta_syncs_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + * + 100 + seriesNameFormat: "{{job}} {{namespace}}" + "3_2": + kind: Panel + spec: + display: + name: Sync Meta Durations + description: Shows p50, p90 and p99 durations of the time it takes to sync meta files from blocks in bucket. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.5, + sum by (namespace, job, le) ( + rate( + thanos_blocks_meta_sync_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p50 {{job}} {{namespace}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.9, + sum by (namespace, job, le) ( + rate( + thanos_blocks_meta_sync_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p90 {{job}} {{namespace}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.99, + sum by (namespace, job, le) ( + rate( + thanos_blocks_meta_sync_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p99 {{job}} {{namespace}} + "4_0": + kind: Panel + spec: + display: + name: Deletion Rate + description: Shows the deletion rate of blocks already marked for deletion. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job) ( + rate(thanos_compact_blocks_cleaned_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + seriesNameFormat: "{{job}} {{namespace}}" + "4_1": + kind: Panel + spec: + display: + name: Deletion Errors + description: Shows rate of deletion failures for blocks already marked for deletion. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job) ( + rate( + thanos_compact_block_cleanup_failures_total{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + seriesNameFormat: "{{job}} {{namespace}}" + "4_2": + kind: Panel + spec: + display: + name: Marking Rate + description: Shows the rate at which blocks are marked for deletion (from GC and retention policy). + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job) ( + rate( + thanos_compact_blocks_marked_total{job=~"$job",marker="deletion-mark.json",namespace="$namespace"}[$__rate_interval] + ) + ) + seriesNameFormat: "{{job}} {{namespace}}" + "5_0": + kind: Panel + spec: + display: + name: Bucket Operations + description: Shows rate of executions of operations against object storage bucket. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: requests/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job, operation) ( + rate(thanos_objstore_bucket_operations_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + seriesNameFormat: "{{job}} {{operation}} {{namespace}}" + "5_1": + kind: Panel + spec: + display: + name: Bucket Operation Errors + description: Shows percentage of errors of operations against object storage bucket. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: percent + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |4- + sum by (namespace, job, operation) ( + rate( + thanos_objstore_bucket_operation_failures_total{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + / + sum by (namespace, job, operation) ( + rate(thanos_objstore_bucket_operations_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + * + 100 + seriesNameFormat: "{{job}} {{operation}} {{namespace}}" + "5_2": + kind: Panel + spec: + display: + name: Bucket Operation Latency + description: Shows latency of operations against object storage bucket. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.99, + sum by (namespace, job, operation, le) ( + rate( + thanos_objstore_bucket_operation_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p99 {{job}} {{operation}} {{namespace}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.9, + sum by (namespace, job, operation, le) ( + rate( + thanos_objstore_bucket_operation_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p90 {{job}} {{operation}} {{namespace}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.5, + sum by (namespace, job, operation, le) ( + rate( + thanos_objstore_bucket_operation_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p50 {{job}} {{operation}} {{namespace}} + "6_0": + kind: Panel + spec: + display: + name: Halted Compactors + description: Shows compactors that have been halted due to unexpected errors. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: sum by (namespace, job) (thanos_compact_halted{job=~"$job",namespace="$namespace"}) + seriesNameFormat: "{{job}} {{namespace}}" + "7_0": + kind: Panel + spec: + display: + name: Garbage Collection + description: Shows rate of execution of removal of blocks, if their data is available as part of a block with a higher compaction level. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: counts/sec + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + sum by (namespace, job) ( + rate(thanos_compact_garbage_collection_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + seriesNameFormat: "{{job}} {{namespace}}" + "7_1": + kind: Panel + spec: + display: + name: Garbage Collection Errors + description: Shows the percentage of garbage collection operations that resulted in errors. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: percent + visual: + display: line + lineWidth: 0.25 + areaOpacity: 1 + palette: + mode: auto + stack: all + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |4- + sum by (namespace, job) ( + rate( + thanos_compact_garbage_collection_failures_total{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + / + sum by (namespace, job) ( + rate(thanos_compact_garbage_collection_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + ) + * + 100 + seriesNameFormat: "{{job}} {{namespace}}" + "7_2": + kind: Panel + spec: + display: + name: Garbage Collection Durations + description: Shows p50, p90 and p99 of how long it takes to execute garbage collection operations. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + yAxis: + format: + unit: seconds + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.5, + sum by (namespace, job, le) ( + rate( + thanos_compact_garbage_collection_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p50 {{job}} {{namespace}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.9, + sum by (namespace, job, le) ( + rate( + thanos_compact_garbage_collection_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p90 {{job}} {{namespace}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: |- + histogram_quantile( + 0.99, + sum by (namespace, job, le) ( + rate( + thanos_compact_garbage_collection_duration_seconds_bucket{job=~"$job",namespace="$namespace"}[$__rate_interval] + ) + ) + ) + seriesNameFormat: p99 {{job}} {{namespace}} + "8_0": + kind: Panel + spec: + display: + name: CPU Usage + description: Shows the CPU usage of the component. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + values: + - last + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: rate(process_cpu_seconds_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + seriesNameFormat: "{{pod}}" + "8_1": + kind: Panel + spec: + display: + name: Memory Usage + description: Shows various memory usage metrics of the component. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + values: + - last + yAxis: + format: + unit: bytes + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: go_memstats_alloc_bytes{job=~"$job",namespace="$namespace"} + seriesNameFormat: Alloc All {{pod}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: go_memstats_heap_alloc_bytes{job=~"$job",namespace="$namespace"} + seriesNameFormat: Alloc Heap {{pod}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: rate(go_memstats_alloc_bytes_total{job=~"$job",namespace="$namespace"}[$__rate_interval]) + seriesNameFormat: Alloc Rate All {{pod}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: rate(go_memstats_heap_alloc_bytes{job=~"$job",namespace="$namespace"}[$__rate_interval]) + seriesNameFormat: Alloc Rate Heap {{pod}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: go_memstats_stack_inuse_bytes{job=~"$job",namespace="$namespace"} + seriesNameFormat: Inuse Stack {{pod}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: go_memstats_heap_inuse_bytes{job=~"$job",namespace="$namespace"} + seriesNameFormat: Inuse Heap {{pod}} + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: process_resident_memory_bytes{job=~"$job",namespace="$namespace"} + seriesNameFormat: Resident Memory {{pod}} + "8_2": + kind: Panel + spec: + display: + name: Goroutines + description: Shows the number of goroutines being used by the component. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + values: + - last + yAxis: + format: + unit: decimal + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: go_goroutines{job=~"$job",namespace="$namespace"} + seriesNameFormat: "{{pod}}" + "8_3": + kind: Panel + spec: + display: + name: GC Duration + description: Shows the Go garbage collection pause durations for the component. + plugin: + kind: TimeSeriesChart + spec: + legend: + position: bottom + mode: table + values: + - last + yAxis: + format: + unit: seconds + visual: + display: line + lineWidth: 0.25 + areaOpacity: 0.5 + palette: + mode: auto + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + datasource: + kind: PrometheusDatasource + + query: go_gc_duration_seconds{job=~"$job",namespace="$namespace"} + seriesNameFormat: "{{quantile}} - {{pod}}" + layouts: + - kind: Grid + spec: + display: + title: TODO Operations + items: + - x: 0 + "y": 0 + width: 6 + height: 6 + content: + $ref: "#/spec/panels/0_0" + - x: 6 + "y": 0 + width: 6 + height: 6 + content: + $ref: "#/spec/panels/0_1" + - x: 12 + "y": 0 + width: 6 + height: 6 + content: + $ref: "#/spec/panels/0_2" + - x: 18 + "y": 0 + width: 6 + height: 6 + content: + $ref: "#/spec/panels/0_3" + - kind: Grid + spec: + display: + title: Group Compactions + items: + - x: 0 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/1_0" + - x: 12 + "y": 0 + width: 12 + height: 8 + content: + $ref: "#/spec/panels/1_1" + - kind: Grid + spec: + display: + title: Downsample Operations + items: + - x: 0 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/2_0" + - x: 8 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/2_1" + - x: 16 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/2_2" + - kind: Grid + spec: + display: + title: Sync Meta + items: + - x: 0 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/3_0" + - x: 8 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/3_1" + - x: 16 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/3_2" + - kind: Grid + spec: + display: + title: Block Deletion + items: + - x: 0 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/4_0" + - x: 8 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/4_1" + - x: 16 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/4_2" + - kind: Grid + spec: + display: + title: Bucket Operations + items: + - x: 0 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/5_0" + - x: 8 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/5_1" + - x: 16 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/5_2" + - kind: Grid + spec: + display: + title: Halted Compactors + items: + - x: 0 + "y": 0 + width: 24 + height: 8 + content: + $ref: "#/spec/panels/6_0" + - kind: Grid + spec: + display: + title: Garbage Collection + items: + - x: 0 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/7_0" + - x: 8 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/7_1" + - x: 16 + "y": 0 + width: 8 + height: 8 + content: + $ref: "#/spec/panels/7_2" + - kind: Grid + spec: + display: + title: Resources + items: + - x: 0 + "y": 0 + width: 6 + height: 8 + content: + $ref: "#/spec/panels/8_0" + - x: 6 + "y": 0 + width: 6 + height: 8 + content: + $ref: "#/spec/panels/8_1" + - x: 12 + "y": 0 + width: 6 + height: 8 + content: + $ref: "#/spec/panels/8_2" + - x: 18 + "y": 0 + width: 6 + height: 8 + content: + $ref: "#/spec/panels/8_3" + duration: 1h \ No newline at end of file diff --git a/web/cypress/fixtures/coo/coo141_perses_dashboards/thanos-querier-datasource.yaml b/web/cypress/fixtures/coo/coo141_perses_dashboards/thanos-querier-datasource.yaml new file mode 100644 index 00000000..3303b8e4 --- /dev/null +++ b/web/cypress/fixtures/coo/coo141_perses_dashboards/thanos-querier-datasource.yaml @@ -0,0 +1,24 @@ +apiVersion: perses.dev/v1alpha2 +kind: PersesDatasource +metadata: + name: thanos-querier-datasource + namespace: perses-dev +spec: + config: + display: + name: "Thanos Querier Datasource" + default: true + plugin: + kind: "PrometheusDatasource" + spec: + proxy: + kind: HTTPProxy + spec: + url: https://thanos-querier.openshift-monitoring.svc.cluster.local:9091 + secret: thanos-querier-datasource-secret + client: + tls: + enable: true + caCert: + type: file + certPath: /ca/service-ca.crt \ No newline at end of file diff --git a/web/cypress/fixtures/perses/constants.ts b/web/cypress/fixtures/perses/constants.ts index 9c34395c..ca231b4b 100644 --- a/web/cypress/fixtures/perses/constants.ts +++ b/web/cypress/fixtures/perses/constants.ts @@ -48,4 +48,65 @@ export const listPersesDashboardsEmptyState = { TITLE: 'No results found', BODY: 'No results match the filter criteria. Clear filters to show results.', -} \ No newline at end of file +} + +export const persesDashboardsModalTitles ={ + EDIT_DASHBOARD_VARIABLES: 'Edit Dashboard Variables', + DASHBOARD_BUILT_IN_VARIABLES: 'Dashboard Built-in Variables', + ADD_VARIABLE: 'Add Variable', + EDIT_VARIABLE: 'Edit Variable', + EDIT_DASHBOARD_DATASOURCES: 'Edit Dashboard Datasources', + ADD_DATASOURCE: 'Add Datasource', + EDIT_DATASOURCE: 'Edit Datasource', + ADD_PANEL: 'Add Panel', + EDIT_PANEL: 'Edit Panel', + DELETE_PANEL: 'Delete Panel', + ADD_PANEL_GROUP: 'Add Panel Group', + EDIT_PANEL_GROUP: 'Edit Panel Group', + DELETE_PANEL_GROUP: 'Delete Panel Group', + EDIT_DASHBOARD_JSON: 'Edit Dashboard JSON', + SAVE_DASHBOARD: 'Save Dashboard', + DISCARD_CHANGES: 'Discard Changes', + VIEW_JSON_DIALOG: 'Dashboard JSON', +} + +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_PROMQL_VARIABLE= 'Prometheus PromQL Variable', +} + +export enum persesDashboardsAddListVariableSort { + NONE = 'None', + ALPHABETICAL_ASC = 'Alphabetical, asc', + ALPHABETICAL_DESC = 'Alphabetical, desc', + NUMERICAL_ASC = 'Numerical, asc', + NUMERICAL_DESC = 'Numerical, desc', + ALPHABETICAL_CI_ASC = 'Alphabetical, case-insensitive, asc', + ALPHABETICAL_CI_DESC = 'Alphabetical, case-insensitive, desc', +} + +export const persesDashboardsRequiredFields = { + AddVariableNameField: 'String must contain at least 1 character(s)' +} + +export const persesDashboardsAddListPanelType = { + BAR_CHART: 'Bar Chart', + FLAME_CHART: 'Flame Chart', + GAUGE_CHART: 'Gauge Chart', + HEATMAP_CHART: 'HeatMap Chart', + HISTOGRAM_CHART: 'Histogram Chart', + MARKDOWN: 'Markdown', + LOGS_TABLE: 'Logs Table', + PIE_CHART: 'Pie Chart', + SCATTER_CHART: 'Scatter Chart', + STAT_CHART: 'Stat Chart', + STATUS_HISTORY_CHART: 'Status History Chart', + TABLE: 'Table', + TIME_SERIES_CHART: 'Time Series Chart', + TIME_SERIES_TABLE: 'Time Series Table', + TRACE_TABLE: 'Trace Table', + TRACING_GANTT_CHART: 'Tracing Gantt Chart', +} diff --git a/web/cypress/support/commands/operator-commands.ts b/web/cypress/support/commands/operator-commands.ts index ef2ee97e..927ace76 100644 --- a/web/cypress/support/commands/operator-commands.ts +++ b/web/cypress/support/commands/operator-commands.ts @@ -240,7 +240,7 @@ const operatorUtils = { `oc label namespace ${MCP.namespace} openshift.io/cluster-monitoring=true --overwrite=true --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, ); cy.exec( - `operator-sdk run bundle --timeout=10m --namespace ${MCP.namespace} ${Cypress.env('KONFLUX_COO_BUNDLE_IMAGE')} --kubeconfig ${Cypress.env('KUBECONFIG_PATH')} --verbose `, + `operator-sdk run bundle --timeout=10m --namespace ${MCP.namespace} --security-context-config restricted ${Cypress.env('KONFLUX_COO_BUNDLE_IMAGE')} --kubeconfig ${Cypress.env('KUBECONFIG_PATH')} --verbose `, { timeout: installTimeoutMilliseconds }, ); } else if (Cypress.env('CUSTOM_COO_BUNDLE_IMAGE')) { @@ -256,7 +256,7 @@ const operatorUtils = { `oc label namespace ${MCP.namespace} openshift.io/cluster-monitoring=true --overwrite=true --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, ); cy.exec( - `operator-sdk run bundle --timeout=10m --namespace ${MCP.namespace} ${Cypress.env('CUSTOM_COO_BUNDLE_IMAGE')} --kubeconfig ${Cypress.env('KUBECONFIG_PATH')} --verbose `, + `operator-sdk run bundle --timeout=10m --namespace ${MCP.namespace} --security-context-config restricted ${Cypress.env('CUSTOM_COO_BUNDLE_IMAGE')} --kubeconfig ${Cypress.env('KUBECONFIG_PATH')} --verbose `, { timeout: installTimeoutMilliseconds }, ); } else if (Cypress.env('FBC_STAGE_COO_IMAGE')) { @@ -283,7 +283,9 @@ const operatorUtils = { waitForCOOReady(MCP: { namespace: string }): void { cy.log('Check Cluster Observability Operator status'); - cy.exec(`sleep 60 && oc get pods -n ${MCP.namespace} | grep observability-operator | awk '{print $1}'`, { timeout: readyTimeoutMilliseconds, failOnNonZeroExit: true }) + cy.exec(`oc project ${MCP.namespace} --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.exec(`sleep 60 && oc get pods -n ${MCP.namespace} | grep observability-operator | grep -v bundle | awk '{print $1}'`, { timeout: readyTimeoutMilliseconds, failOnNonZeroExit: true }) .its('stdout') // Get the captured output string .then((podName) => { // Trim any extra whitespace (newline, etc.) @@ -306,7 +308,7 @@ const operatorUtils = { nav.sidenav.clickNavLink([section, 'Installed Operators']); }); - cy.byTestID('name-filter-input').should('be.visible').type('Cluster Observability{enter}'); + cy.byTestID('name-filter-input').should('be.visible').type('Observability{enter}'); cy.get('[data-test="status-text"]', { timeout: installTimeoutMilliseconds }).eq(0).should('contain.text', 'Succeeded', { timeout: installTimeoutMilliseconds }); }, @@ -373,20 +375,45 @@ const operatorUtils = { cy.log('Create perses-dev namespace.'); cy.exec(`oc new-project perses-dev --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Create openshift-cluster-sample-dashboard instance.'); - cy.exec(`sed 's/namespace: openshift-cluster-observability-operator/namespace: ${MCP.namespace}/g' ./cypress/fixtures/coo/openshift-cluster-sample-dashboard.yaml | oc apply -f - --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + /** + * TODO: When COO1.4.0 is released, points COO_UI_INSTALL to install dashboards on COO1.4.0 folder + */ + if (Cypress.env('COO_UI_INSTALL')) { + cy.log('COO_UI_INSTALL is set. Installing dashboards on COO1.2.0 folder'); + + cy.log('Create openshift-cluster-sample-dashboard instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo121_perses_dashboards/openshift-cluster-sample-dashboard.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create perses-dashboard-sample instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo121_perses_dashboards/perses-dashboard-sample.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create prometheus-overview-variables instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo121_perses_dashboards/prometheus-overview-variables.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create thanos-compact-overview-1var instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo121_perses_dashboards/thanos-compact-overview-1var.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create Thanos Querier instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo121_perses_dashboards/thanos-querier-datasource.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + } else { + cy.log('COO_UI_INSTALL is not set. Installing dashboards on COO1.4.0 folder'); + + cy.log('Create openshift-cluster-sample-dashboard instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo141_perses_dashboards/openshift-cluster-sample-dashboard.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Create perses-dashboard-sample instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo141_perses_dashboards/perses-dashboard-sample.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Create perses-dashboard-sample instance.'); - cy.exec(`oc apply -f ./cypress/fixtures/coo/perses-dashboard-sample.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Create prometheus-overview-variables instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo141_perses_dashboards/prometheus-overview-variables.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Create prometheus-overview-variables instance.'); - cy.exec(`oc apply -f ./cypress/fixtures/coo/prometheus-overview-variables.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Create thanos-compact-overview-1var instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo141_perses_dashboards/thanos-compact-overview-1var.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Create thanos-compact-overview-1var instance.'); - cy.exec(`oc apply -f ./cypress/fixtures/coo/thanos-compact-overview-1var.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Create Thanos Querier instance.'); + cy.exec(`oc apply -f ./cypress/fixtures/coo/coo141_perses_dashboards/thanos-querier-datasource.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Create Thanos Querier instance.'); - cy.exec(`oc apply -f ./cypress/fixtures/coo/thanos-querier-datasource.yaml --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + } cy.exec( `oc label namespace ${MCP.namespace} openshift.io/cluster-monitoring=true --overwrite=true --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, @@ -459,7 +486,8 @@ const operatorUtils = { cy.log(`Korrel8r pod is now running in namespace: ${MCP.namespace}`); }); - cy.reload(true); + cy.wait(30000); + cy.log(`Clicking the application launcher`); cy.byLegacyTestID(LegacyTestIDs.ApplicationLauncher).should('be.visible').click(); cy.byTestID(DataTestIDs.MastHeadApplicationItem).contains('Signal Correlation').should('be.visible'); }, @@ -521,22 +549,40 @@ const operatorUtils = { cy.executeAndDelete( `oc delete ${config.kind} ${config.name} --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, ); - - cy.log('Remove openshift-cluster-sample-dashboard instance.'); - cy.executeAndDelete(`sed 's/namespace: openshift-cluster-observability-operator/namespace: ${MCP.namespace}/g' ./cypress/fixtures/coo/openshift-cluster-sample-dashboard.yaml | oc delete -f - --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + if (Cypress.env('COO_UI_INSTALL')) { + cy.log('Remove openshift-cluster-sample-dashboard instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo121_perses_dashboards/openshift-cluster-sample-dashboard.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Remove perses-dashboard-sample instance.'); - cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/perses-dashboard-sample.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Remove perses-dashboard-sample instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo121_perses_dashboards/perses-dashboard-sample.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Remove prometheus-overview-variables instance.'); - cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/prometheus-overview-variables.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Remove prometheus-overview-variables instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo121_perses_dashboards/prometheus-overview-variables.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); - cy.log('Remove thanos-compact-overview-1var instance.'); - cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/thanos-compact-overview-1var.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Remove thanos-compact-overview-1var instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo121_perses_dashboards/thanos-compact-overview-1var.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Remove Thanos Querier instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/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 Thanos Querier instance.'); - cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/thanos-querier-datasource.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Remove openshift-cluster-sample-dashboard instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo141_perses_dashboards/openshift-cluster-sample-dashboard.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + cy.log('Remove perses-dashboard-sample instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo141_perses_dashboards/perses-dashboard-sample.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Remove prometheus-overview-variables instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo141_perses_dashboards/prometheus-overview-variables.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Remove thanos-compact-overview-1var instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo141_perses_dashboards/thanos-compact-overview-1var.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + + cy.log('Remove Thanos Querier instance.'); + cy.executeAndDelete(`oc delete -f ./cypress/fixtures/coo/coo141_perses_dashboards/thanos-querier-datasource.yaml --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); + } cy.log('Remove perses-dev namespace'); cy.executeAndDelete(`oc delete namespace perses-dev --ignore-not-found --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`); diff --git a/web/cypress/support/perses/00.coo_bvt_perses_admin.cy.ts b/web/cypress/support/perses/00.coo_bvt_perses_admin.cy.ts index 981ed40a..cee213e0 100644 --- a/web/cypress/support/perses/00.coo_bvt_perses_admin.cy.ts +++ b/web/cypress/support/perses/00.coo_bvt_perses_admin.cy.ts @@ -32,7 +32,7 @@ export function testBVTCOOPerses(perspective: PerspectiveConfig) { cy.changeNamespace('openshift-cluster-observability-operator'); persesDashboardsPage.clickDashboardDropdown(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0] as keyof typeof persesDashboardsDashboardDropdownCOO); cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-cluster').should('be.visible'); - persesDashboardsPage.panelGroupHeaderAssertion('Accelerators'); + persesDashboardsPage.panelGroupHeaderAssertion('Accelerators', 'Open'); persesDashboardsPage.panelHeadersAcceleratorsCommonMetricsAssertion(); persesDashboardsPage.expandPanel(persesDashboardsAcceleratorsCommonMetricsPanels.GPU_UTILIZATION); persesDashboardsPage.collapsePanel(persesDashboardsAcceleratorsCommonMetricsPanels.GPU_UTILIZATION); @@ -46,12 +46,12 @@ export function testBVTCOOPerses(perspective: PerspectiveConfig) { cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-instance').should('be.visible'); cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-interval').should('be.visible'); cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-text').should('be.visible'); - persesDashboardsPage.panelGroupHeaderAssertion('Row 1'); - persesDashboardsPage.expandPanel('RAM Used'); - persesDashboardsPage.collapsePanel('RAM Used'); - persesDashboardsPage.statChartValueAssertion('RAM Used', true); + persesDashboardsPage.panelGroupHeaderAssertion('Row 1', 'Open'); + persesDashboardsPage.expandPanel('RAM Total'); + persesDashboardsPage.collapsePanel('RAM Total'); + persesDashboardsPage.statChartValueAssertion('RAM Total', true); persesDashboardsPage.searchAndSelectVariable('job', 'node-exporter'); - persesDashboardsPage.statChartValueAssertion('RAM Used', false); + persesDashboardsPage.statChartValueAssertion('RAM Total', false); }); diff --git a/web/cypress/support/perses/00.coo_bvt_perses_admin_1.cy.ts b/web/cypress/support/perses/00.coo_bvt_perses_admin_1.cy.ts index 1251a94e..496cfbd9 100644 --- a/web/cypress/support/perses/00.coo_bvt_perses_admin_1.cy.ts +++ b/web/cypress/support/perses/00.coo_bvt_perses_admin_1.cy.ts @@ -18,7 +18,7 @@ export function testBVTCOOPerses1(perspective: PerspectiveConfig) { cy.log(`1.1. use sidebar nav to go to Observe > Dashboards (Perses)`); listPersesDashboardsPage.shouldBeLoaded(); listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2]); - persesDashboardsPage.shouldBeLoaded(); + persesDashboardsPage.shouldBeLoaded1(); }); it(`2.${perspective.name} perspective - Accelerators common metrics dashboard `, () => { @@ -26,9 +26,11 @@ export function testBVTCOOPerses1(perspective: PerspectiveConfig) { cy.changeNamespace('openshift-cluster-observability-operator'); listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2]); cy.wait(2000); + + cy.log(`2.2. Select dashboard`); persesDashboardsPage.clickDashboardDropdown(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[0] as keyof typeof persesDashboardsDashboardDropdownCOO); cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-cluster').should('be.visible'); - persesDashboardsPage.panelGroupHeaderAssertion('Accelerators'); + persesDashboardsPage.panelGroupHeaderAssertion('Accelerators', 'Open'); persesDashboardsPage.panelHeadersAcceleratorsCommonMetricsAssertion(); persesDashboardsPage.expandPanel(persesDashboardsAcceleratorsCommonMetricsPanels.GPU_UTILIZATION); persesDashboardsPage.collapsePanel(persesDashboardsAcceleratorsCommonMetricsPanels.GPU_UTILIZATION); @@ -44,13 +46,22 @@ export function testBVTCOOPerses1(perspective: PerspectiveConfig) { cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-instance').should('be.visible'); cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-interval').should('be.visible'); cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-text').should('be.visible'); - persesDashboardsPage.panelGroupHeaderAssertion('Row 1'); - persesDashboardsPage.expandPanel('RAM Used'); - persesDashboardsPage.collapsePanel('RAM Used'); - persesDashboardsPage.statChartValueAssertion('RAM Used', true); + persesDashboardsPage.panelGroupHeaderAssertion('Row 1', 'Open'); + persesDashboardsPage.expandPanel('RAM Total'); + persesDashboardsPage.collapsePanel('RAM Total'); + persesDashboardsPage.statChartValueAssertion('RAM Total', true); persesDashboardsPage.searchAndSelectVariable('job', 'node-exporter'); - persesDashboardsPage.statChartValueAssertion('RAM Used', false); - + persesDashboardsPage.statChartValueAssertion('RAM Total', false); + }); + + it(`4.${perspective.name} perspective - Download and View JSON`, () => { + cy.log(`4.1. use sidebar nav to go to Observe > Dashboards (Perses) > Download and View JSON`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2]); + persesDashboardsPage.downloadDashboard(true, persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2], 'JSON'); + persesDashboardsPage.downloadDashboard(true, persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2], 'YAML'); + persesDashboardsPage.downloadDashboard(true, persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2], 'YAML (CR)'); + persesDashboardsPage.viewJSON(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2], 'openshift-cluster-observability-operator'); + }); } diff --git a/web/cypress/support/perses/02.coo_edit_perses_admin.cy.ts b/web/cypress/support/perses/02.coo_edit_perses_admin.cy.ts new file mode 100644 index 00000000..86c3b041 --- /dev/null +++ b/web/cypress/support/perses/02.coo_edit_perses_admin.cy.ts @@ -0,0 +1,517 @@ +import { editPersesDashboardsAddVariable, persesMUIDataTestIDs, IDs, editPersesDashboardsAddDatasource } from '../../../src/components/data-test'; +import { persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev } from '../../fixtures/perses/constants'; +import { commonPages } from '../../views/common'; +import { listPersesDashboardsPage } from "../../views/list-perses-dashboards"; +import { persesDashboardsPage } from '../../views/perses-dashboards'; +import { persesDashboardsPanelGroup } from '../../views/perses-dashboards-panelgroup'; +import { persesDashboardsEditDatasources } from '../../views/perses-dashboards-edit-datasources'; +import { persesDashboardsEditVariables } from '../../views/perses-dashboards-edit-variables'; + +export interface PerspectiveConfig { + name: string; + beforeEach?: () => void; +} + +export function runCOOEditPersesTests(perspective: PerspectiveConfig) { + testCOOEditPerses(perspective); +} + +export function testCOOEditPerses(perspective: PerspectiveConfig) { + + it(`1.${perspective.name} perspective - Edit perses dashboard page`, () => { + cy.log(`1.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`1.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`1.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`1.4. Click on Edit button`); + cy.wait(15000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.assertEditModeButtons(); + persesDashboardsPage.assertEditModePanelGroupButtons('Headlines'); + //already expanded + persesDashboardsPage.assertPanelActionButtons('CPU Usage'); + // tiny panel and modal is opened. So, expand first and then assert the buttons and finally collapse + // due to modal is opened and page is refreshed, it is not easy to assert buttons in the modal + persesDashboardsPage.assertPanelActionButtons('CPU Utilisation'); + + cy.log(`1.5. Click on Cancel button`); + persesDashboardsPage.clickEditActionButton('Cancel'); + + cy.log(`1.6. Change namespace to All Projects`); + cy.changeNamespace('All Projects'); + listPersesDashboardsPage.shouldBeLoaded(); + + }); + + it(`2.${perspective.name} perspective - Edit Toolbar - Edit Variables - Add List Variable`, () => { + cy.log(`2.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`2.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`2.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`2.4. Click on Edit button`); + cy.wait(10000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickButton('Add Variable'); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working + persesDashboardsEditVariables.addListVariable('ListVariable', true, true, 'AAA', 'Test', 'Test', undefined, undefined); + + cy.log(`2.5. Run query`); + persesDashboardsEditVariables.clickButton('Run Query'); + cy.get('h4').should('contain', 'Preview Values').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardAddVariablePreviewValuesCopy).should('be.visible'); + + cy.log(`2.6. Add variable`); + persesDashboardsEditVariables.clickButton('Add'); + + cy.log(`2.7. Apply changes`); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`2.8. Save dashboard`); + persesDashboardsPage.clickEditActionButton('Save'); + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working, so selecting "All" for now + persesDashboardsPage.searchAndSelectVariable('ListVariable', 'All'); + //TODO: END testing more to check if it is time constraint or cache issue + + }); + + it(`3.${perspective.name} perspective - Edit Toolbar - Edit Variables - Add Text Variable`, () => { + cy.log(`3.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`3.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`3.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`3.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditVariables'); + + cy.log(`3.5. Click on Dashboard Built-in Variables button`); + cy.get('#'+IDs.persesDashboardEditVariablesModalBuiltinButton).should('have.attr', 'aria-expanded', 'false').click(); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('#'+IDs.persesDashboardEditVariablesModalBuiltinButton).should('have.attr', 'aria-expanded', 'true') + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('#'+IDs.persesDashboardEditVariablesModalBuiltinButton).click(); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('#'+IDs.persesDashboardEditVariablesModalBuiltinButton).should('have.attr', 'aria-expanded', 'false'); + + cy.log(`3.6. Add variable`); + persesDashboardsEditVariables.clickButton('Add Variable'); + persesDashboardsEditVariables.addTextVariable('TextVariable', true, 'Test', 'Test', 'Test'); + persesDashboardsEditVariables.clickButton('Add'); + + cy.log(`3.7. Apply changes`); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`3.8. Save dashboard`); + persesDashboardsPage.clickEditActionButton('Save'); + + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + + cy.log(`3.9. Search and type variable`); + persesDashboardsPage.searchAndTypeVariable('TextVariable', ''); + + }); + + it(`4.${perspective.name} perspective - Edit Toolbar - Edit Variables - Visibility, Move up/down, Edit and Delete Variable`, () => { + cy.log(`4.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`4.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`4.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`4.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + + cy.log(`4.5. Click on Edit Variables button`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + + cy.log(`4.6. Toggle variable visibility`); + persesDashboardsEditVariables.toggleVariableVisibility(0, false); + + cy.log(`4.7. Move variable up`); + persesDashboardsEditVariables.moveVariableUp(1); + + cy.log(`4.8. Click on Edit variable button`); + persesDashboardsEditVariables.clickEditVariableButton(0); + + cy.log(`4.9. Edit list variable`); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working + persesDashboardsEditVariables.addListVariable('ListVariable123', false, false, '123', 'Test123', 'Test123', undefined, undefined); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`4.10. Delete variable`); + persesDashboardsEditVariables.clickDeleteVariableButton(2); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`4.11. Save dashboard`); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`4.12. Search and select variable`); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working, so selecting "All" for now + persesDashboardsPage.searchAndSelectVariable('ListVariable123', 'All'); + + cy.log(`4.13. Assert variable not be visible`); + persesDashboardsPage.assertVariableNotBeVisible('cluster'); + + cy.log(`4.14. Assert variable not exist`); + persesDashboardsPage.assertVariableNotExist('TextVariable'); + + cy.log(`4.15. Recover dashboard`); + persesDashboardsPage.clickEditButton(); + + cy.log(`4.16. Click on Edit Variables button`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + + cy.log(`4.16. Toggle variable visibility`); + persesDashboardsEditVariables.toggleVariableVisibility(1, true); + + cy.log(`4.17. Delete variable`); + persesDashboardsEditVariables.clickDeleteVariableButton(0); + + cy.log(`4.17. Apply changes`); + persesDashboardsEditVariables.clickButton('Apply'); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`4.18. Assert variable be visible`); + persesDashboardsPage.assertVariableBeVisible('cluster'); + + cy.log(`4.19. Assert variable not exist`); + persesDashboardsPage.assertVariableNotExist('TextVariable'); + + }); + + it(`5.${perspective.name} perspective - Edit Toolbar - Edit Variables - Add Variable - Required field validation`, () => { + cy.log(`5.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`5.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`5.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`5.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditVariables'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('button').contains('Add Variable').should('be.visible').click(); + cy.get('input[name="'+editPersesDashboardsAddVariable.inputName+'"]').clear(); + persesDashboardsEditVariables.clickButton('Add'); + persesDashboardsEditVariables.assertRequiredFieldValidation('Name'); + persesDashboardsEditVariables.clickButton('Cancel'); + persesDashboardsEditVariables.clickButton('Cancel'); + }); + + /**TODO: https://issues.redhat.com/browse/OU-1054 is targeted for COO1.5.0, so, commenting all Datasources related scenarios + it(`6.${perspective.name} perspective - Edit Toolbar - Edit Datasources - Add and Delete Prometheus Datasource`, () => { + cy.log(`6.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`6.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`6.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`6.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditDatasources'); + + cy.log(`6.5. Verify existing datasources`); + persesDashboardsEditDatasources.assertDatasource(0, 'PrometheusLocal', 'PrometheusDatasource', ''); + + cy.log(`6.6. Add datasource`); + persesDashboardsEditDatasources.clickButton('Add Datasource'); + persesDashboardsEditDatasources.addDatasource('Datasource1', true, 'Prometheus Datasource', 'Datasource1', 'Datasource1'); + persesDashboardsEditDatasources.clickButton('Add'); + persesDashboardsEditDatasources.assertDatasource(1, 'Datasource1', 'PrometheusDatasource', 'Datasource1'); + + cy.log(`6.7. Add second datasource`); + persesDashboardsEditDatasources.clickButton('Add Datasource'); + persesDashboardsEditDatasources.addDatasource('Datasource2', true, 'Prometheus Datasource', 'Datasource2', 'Datasource2'); + persesDashboardsEditDatasources.clickButton('Add'); + persesDashboardsEditDatasources.assertDatasource(2, 'Datasource2', 'PrometheusDatasource', 'Datasource2'); + + cy.log(`6.8. Delete first datasource`); + persesDashboardsEditDatasources.clickDeleteDatasourceButton(1); + persesDashboardsEditDatasources.assertDatasourceNotExist('Datasource1'); + + persesDashboardsEditDatasources.clickButton('Apply'); + //https://issues.redhat.com/browse/OU-1160 - Datasource is not saved + // persesDashboardsPage.clickEditActionButton('Save'); + }); + + it(`7.${perspective.name} perspective - Edit Toolbar - Edit Datasources - Edit Prometheus Datasource`, () => { + cy.log(`7.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`7.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`7.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`7.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditDatasources'); + + cy.log(`7.5. Verify existing datasources`); + persesDashboardsEditDatasources.assertDatasource(0,'PrometheusLocal', 'PrometheusDatasource', ''); + + cy.log(`7.6. Edit datasource`); + persesDashboardsEditDatasources.clickEditDatasourceButton(0); + persesDashboardsEditDatasources.addDatasource('PrometheusLocal', false, 'Prometheus Datasource', 'Datasource1', 'Datasource1'); + persesDashboardsEditDatasources.clickButton('Apply'); + persesDashboardsEditDatasources.assertDatasource(0,'PrometheusLocal', 'PrometheusDatasource', 'Datasource1'); + persesDashboardsEditDatasources.clickButton('Cancel'); + persesDashboardsPage.clickEditActionButton('Cancel'); + + }); + + // it(`8.${perspective.name} perspective - Edit Toolbar - Edit Datasources - Add Tempo Datasource`, () => { + // }); + + it(`8.${perspective.name} perspective - Edit Toolbar - Edit Datasources - Required field validation`, () => { + cy.log(`8.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`8.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`8.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`8.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditDatasources'); + + cy.log(`8.5. Add datasource`); + persesDashboardsEditDatasources.clickButton('Add Datasource'); + + cy.log(`8.6. Clear out Name field`); + cy.get('input[name="'+editPersesDashboardsAddDatasource.inputName+'"]').clear(); + persesDashboardsEditDatasources.clickButton('Add'); + + cy.log(`8.7. Assert required field validation`); + persesDashboardsEditDatasources.assertRequiredFieldValidation('Name'); + persesDashboardsEditDatasources.clickButton('Cancel'); + + cy.log(`8.8. Cancel changes`); + persesDashboardsEditDatasources.clickButton('Cancel'); + persesDashboardsPage.clickEditActionButton('Cancel'); + + }); +*/ + + it(`6.${perspective.name} perspective - Edit Toolbar - Add Panel Group`, () => { + cy.log(`6.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`6.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`6.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`6.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('AddGroup'); + + cy.log(`6.5. Add panel group`); + persesDashboardsPanelGroup.addPanelGroup('PanelGroup1', 'Open', ''); + + cy.log(`6.6. Save panel group`); + persesDashboardsPage.clickEditActionButton('Save'); + persesDashboardsPage.panelGroupHeaderAssertion('PanelGroup1', 'Open'); + + cy.log(`6.7. Back and check panel group`); + //TODO: START testing more to check if it is time constraint or cache issue + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + persesDashboardsPage.panelGroupHeaderAssertion('PanelGroup1', 'Open'); + + }); + + it(`7.${perspective.name} perspective - Edit Toolbar - Edit Panel Group`, () => { + cy.log(`7.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`7.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`7.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`7.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup1', 'edit'); + persesDashboardsPanelGroup.editPanelGroup('PanelGroup2', 'Closed', ''); + persesDashboardsPage.clickEditActionButton('Save'); + persesDashboardsPage.panelGroupHeaderAssertion('PanelGroup2', 'Closed'); + + cy.log(`7.5. Back and check panel group`); + //TODO: START testing more to check if it is time constraint or cache issue + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + persesDashboardsPage.panelGroupHeaderAssertion('PanelGroup2', 'Closed'); + + }); + + it(`8.${perspective.name} perspective - Edit Toolbar - Move Panel Group Down and Up`, () => { + cy.log(`8.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`8.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`8.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`8.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup2', 'moveDown'); + + cy.log(`8.5. Save panel group`); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`8.6. Assert panel group order`); + persesDashboardsPage.assertPanelGroupOrder('Row 1', 0); + persesDashboardsPage.assertPanelGroupOrder('PanelGroup2', 1); + persesDashboardsPage.assertPanelGroupOrder('Row 2', 2); + + cy.log(`8.7. Back and check panel group order`); + //TODO: START testing more to check if it is time constraint or cache issue + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + persesDashboardsPage.assertPanelGroupOrder('Row 1', 0); + persesDashboardsPage.assertPanelGroupOrder('PanelGroup2', 1); + persesDashboardsPage.assertPanelGroupOrder('Row 2', 2); + + cy.log(`8.8. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + + cy.log(`8.9. Move panel group up`); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup2', 'moveUp'); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`8.10. Assert panel group order`); + persesDashboardsPage.assertPanelGroupOrder('PanelGroup2', 0); + persesDashboardsPage.assertPanelGroupOrder('Row 1', 1); + persesDashboardsPage.assertPanelGroupOrder('Row 2', 2); + + cy.log(`8.11. Back and check panel group order`); + //TODO: START testing more to check if it is time constraint or cache issue + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + persesDashboardsPage.assertPanelGroupOrder('PanelGroup2', 0); + persesDashboardsPage.assertPanelGroupOrder('Row 1', 1); + persesDashboardsPage.assertPanelGroupOrder('Row 2', 2); + }); + + it(`9.${perspective.name} perspective - Edit Toolbar - Delete Panel Group`, () => { + cy.log(`9.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`9.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`9.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`9.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup2', 'delete'); + persesDashboardsPanelGroup.clickDeletePanelGroupButton(); + persesDashboardsPage.clickEditActionButton('Save'); + persesDashboardsPage.assertPanelGroupNotExist('PanelGroup2'); + + cy.log(`9.5. Back and check panel group`); + //TODO: START testing more to check if it is time constraint or cache issue + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + persesDashboardsPage.assertPanelGroupNotExist('PanelGroup2'); + }); + +} diff --git a/web/cypress/support/perses/02.coo_edit_perses_admin_1.cy.ts b/web/cypress/support/perses/02.coo_edit_perses_admin_1.cy.ts new file mode 100644 index 00000000..8a3282e3 --- /dev/null +++ b/web/cypress/support/perses/02.coo_edit_perses_admin_1.cy.ts @@ -0,0 +1,318 @@ +import { IDs, editPersesDashboardsAddPanel } from '../../../src/components/data-test'; +import { persesDashboardsAddListPanelType, persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev } from '../../fixtures/perses/constants'; +import { commonPages } from '../../views/common'; +import { listPersesDashboardsPage } from "../../views/list-perses-dashboards"; +import { persesDashboardsPage } from '../../views/perses-dashboards'; +import { persesDashboardsEditDatasources } from '../../views/perses-dashboards-edit-datasources'; +import { persesDashboardsEditVariables } from '../../views/perses-dashboards-edit-variables'; +import { persesDashboardsPanel } from '../../views/perses-dashboards-panel'; +import { persesDashboardsPanelGroup } from '../../views/perses-dashboards-panelgroup'; + +export interface PerspectiveConfig { + name: string; + beforeEach?: () => void; +} + +export function runCOOEditPersesTests1(perspective: PerspectiveConfig) { + testCOOEditPerses1(perspective); +} + +export function testCOOEditPerses1(perspective: PerspectiveConfig) { + + it(`10.${perspective.name} perspective - Edit Toolbar - Add Panel`, () => { + cy.log(`10.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`10.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`10.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + + const panelTypeKeys = Object.keys(persesDashboardsAddListPanelType) as (keyof typeof persesDashboardsAddListPanelType)[]; + panelTypeKeys.forEach((typeKey) => { + const panelName = persesDashboardsAddListPanelType[typeKey]; // e.g., 'Bar Chart' + + cy.log(`10.4. Click on Edit button`); + persesDashboardsPage.clickEditButton(); + + cy.log(`10.5. Click on Add Group - PanelGroup ` + panelName); + persesDashboardsPage.clickEditActionButton('AddGroup'); + persesDashboardsPanelGroup.addPanelGroup('PanelGroup ' + panelName, 'Open', ''); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`10.6. Click on Edit button`); + persesDashboardsPage.clickEditButton(); + + cy.log(`10.7. Click on Add Panel button` + panelName); + persesDashboardsPage.clickEditActionButton('AddPanel'); + persesDashboardsPanel.addPanelShouldBeLoaded(); + persesDashboardsPanel.addPanel(panelName, 'PanelGroup ' + panelName, panelName); + persesDashboardsPage.assertPanel(panelName, 'PanelGroup ' + panelName, 'Open'); + persesDashboardsPage.clickEditActionButton('Save'); + }); + }); + + it(`11.${perspective.name} perspective - Edit Toolbar - Edit Panel`, () => { + cy.log(`11.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`11.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`11.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + + cy.log(`11.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + + const panelTypeKeys = Object.keys(persesDashboardsAddListPanelType) as (keyof typeof persesDashboardsAddListPanelType)[]; + const lastKey = panelTypeKeys[panelTypeKeys.length - 1]; // Get the last KEY from the array + const lastPanelName = persesDashboardsAddListPanelType[lastKey]; // Use the KEY to get the VALUE + + cy.log(`11.5. Click on Edit Panel button` + lastPanelName + ' to Panel1'); + persesDashboardsPage.clickPanelAction(lastPanelName, 'edit'); + persesDashboardsPanel.editPanel('Panel1', 'PanelGroup ' + lastPanelName, persesDashboardsAddListPanelType.BAR_CHART, 'Description1'); + persesDashboardsPage.assertPanel('Panel1', 'PanelGroup ' + lastPanelName, 'Open'); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`11.6. Click on Edit Panel button from Panel 1 to` + lastPanelName); + persesDashboardsPage.clickEditButton(); + + persesDashboardsPage.clickPanelAction('Panel1', 'edit'); + persesDashboardsPanel.editPanel(lastPanelName, 'PanelGroup ' + lastPanelName, lastPanelName, 'Description1'); + persesDashboardsPage.assertPanel(lastPanelName, 'PanelGroup ' + lastPanelName, 'Open'); + persesDashboardsPage.clickEditActionButton('Save'); + + }); + + it(`12.${perspective.name} perspective - Edit Toolbar - Delete Panel`, () => { + cy.log(`12.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`12.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`12.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + + const panelTypeKeys = Object.keys(persesDashboardsAddListPanelType) as (keyof typeof persesDashboardsAddListPanelType)[]; + + panelTypeKeys.reverse().forEach((typeKey) => { + const panelName = persesDashboardsAddListPanelType[typeKey]; // e.g., 'Bar Chart' + cy.log(`12.4. Delete Panel` + panelName); + persesDashboardsPage.clickEditButton(); + persesDashboardsPanel.deletePanel(panelName); + persesDashboardsPanel.clickDeletePanelButton(); + + cy.log(`12.5. Delete Panel Group` + panelName); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup ' + panelName, 'delete'); + persesDashboardsPanelGroup.clickDeletePanelGroupButton(); + persesDashboardsPage.clickEditActionButton('Save'); + }); + }); + + it(`13.${perspective.name} perspective - Edit Toolbar - Duplicate Panel`, () => { + cy.log(`13.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`13.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`13.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + + cy.log(`13.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + + cy.log(`13.5. Collapse Row 1 Panel Group`); + persesDashboardsPage.collapsePanelGroup('Row 1'); + + cy.log(`13.6. Click on Duplicate Panel button`); + persesDashboardsPage.clickPanelAction('Legend Example', 'duplicate'); + + cy.log(`13.7. Assert duplicated panel`); + persesDashboardsPage.assertDuplicatedPanel('Legend Example', 2); + + }); + + it(`14.${perspective.name} perspective - Edit Toolbar - Add Panel - Required field validation`, () => { + cy.log(`14.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`14.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`14.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[2]); + + cy.log(`14.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + + cy.log(`14.5. Click on Add Panel Group button`); + persesDashboardsPage.clickEditActionButton('AddGroup'); + persesDashboardsPanelGroup.addPanelGroup('PanelGroup Required Field Validation', 'Open', ''); + + cy.log(`14.6. Click on Add Panel button`); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup Required Field Validation', 'addPanel'); + + cy.get('input[name="'+editPersesDashboardsAddPanel.inputName+'"]').clear().type('Required Field Validation'); + + persesDashboardsPanel.clickDropdownAndSelectOption('Type', persesDashboardsAddListPanelType.BAR_CHART); + cy.get('input[name="'+editPersesDashboardsAddPanel.inputName+'"]').clear().type('Required Field Validation'); + persesDashboardsPanel.clickDropdownAndSelectOption('Type', persesDashboardsAddListPanelType.BAR_CHART); + cy.get('input[name="'+editPersesDashboardsAddPanel.inputName+'"]').clear(); + cy.get('#'+IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Add').should('be.visible').click(); + + cy.log(`14.7. Assert required field validation`); + persesDashboardsPanel.assertRequiredFieldValidation('Name'); + persesDashboardsPanel.clickButton('Cancel'); + persesDashboardsPage.clickEditActionButton('Cancel'); + }); + + it(`15.${perspective.name} perspective - Edit Toolbar - Perform changes and Cancel`, () => { + cy.log(`15.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`15.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`15.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.K8S_COMPUTE_RESOURCES_CLUSTER[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`15.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickButton('Add Variable'); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working + persesDashboardsEditVariables.addListVariable('ListVariable', true, true, 'AAA', 'Test', 'Test', undefined, undefined); + + cy.log(`15.5. Add variable`); + persesDashboardsEditVariables.clickButton('Add'); + + cy.log(`15.6. Apply changes`); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`15.7. Assert Variable before cancelling`); + persesDashboardsPage.searchAndSelectVariable('ListVariable', 'All'); + + cy.log(`15.8. Click on Add Panel Group button`); + persesDashboardsPage.clickEditActionButton('AddGroup'); + persesDashboardsPanelGroup.addPanelGroup('PanelGroup Perform Changes and Cancel', 'Open', ''); + + cy.log(`15.9. Click on Add Panel button`); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup Perform Changes and Cancel', 'addPanel'); + persesDashboardsPanel.addPanel('Panel Perform Changes and Cancel', 'PanelGroup Perform Changes and Cancel', 'Bar Chart'); + + cy.log(`15.10. Click on Cancel button`); + persesDashboardsPage.clickEditActionButton('Cancel'); + + cy.log(`15.11. Assert variable not exist`); + persesDashboardsPage.assertVariableNotExist('ListVariable'); + + cy.log(`15.12. Assert panel group not exist`); + persesDashboardsPage.assertPanelGroupNotExist('PanelGroup Perform Changes and Cancel'); + + cy.log(`15.13. Assert panel not exist`); + persesDashboardsPage.assertPanelNotExist('Panel Perform Changes and Cancel'); + + }); + + /** + * OU-886 Mark dashboards and datasources created using CRD as readonly + * + * Admin user and dev users with persesdashboard-editor-role will be able to edit dashboards using CRD. + * + */ + it(`16.${perspective.name} perspective - Try to editAccelerators and APM dashboards`, () => { + cy.log(`16.1. use sidebar nav to go to Observe > Dashboards (Perses)`); + commonPages.titleShouldHaveText('Dashboards'); + listPersesDashboardsPage.shouldBeLoaded(); + + cy.log(`16.2. Filter by Name`); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2]); + listPersesDashboardsPage.countDashboards('1'); + + cy.log(`16.3. Click on a dashboard`); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2]); + //TODO: change back to shouldBeLoaded when customizable-dashboards gets merged + // persesDashboardsPage.shouldBeLoaded1(); + + cy.log(`16.4. Click on Edit button`); + cy.wait(2000); + persesDashboardsPage.clickEditButton(); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickButton('Add Variable'); + //https://issues.redhat.com/browse/OU-1159 - Custom All Value is not working + persesDashboardsEditVariables.addListVariable('ListVariable', true, true, 'AAA', 'Test', 'Test', undefined, undefined); + + cy.log(`16.5. Add variable`); + persesDashboardsEditVariables.clickButton('Add'); + + cy.log(`16.6. Apply changes`); + persesDashboardsEditVariables.clickButton('Apply'); + + cy.log(`16.7. Assert Variable before saving`); + persesDashboardsPage.searchAndSelectVariable('ListVariable', 'All'); + + cy.log(`16.8. Click on Add Panel Group button`); + persesDashboardsPage.clickEditActionButton('AddGroup'); + persesDashboardsPanelGroup.addPanelGroup('PanelGroup Perform Changes and Save', 'Open', ''); + + cy.log(`16.9. Click on Add Panel button`); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup Perform Changes and Save', 'addPanel'); + persesDashboardsPanel.addPanel('Panel Perform Changes and Save', 'PanelGroup Perform Changes and Save', 'Bar Chart'); + + cy.log(`16.10. Click on Save button`); + persesDashboardsPage.clickEditActionButton('Save'); + + cy.log(`16.11. Back and check panel group`); + persesDashboardsPage.backToListPersesDashboardsPage(); + listPersesDashboardsPage.filter.byName(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2]); + listPersesDashboardsPage.clickDashboard(persesDashboardsDashboardDropdownCOO.ACCELERATORS_COMMON_METRICS[2]); + + cy.log(`16.12. Assert Variable before deleting`); + persesDashboardsPage.searchAndSelectVariable('ListVariable', 'All'); + + cy.log(`16.13. Assert panel group exists`); + persesDashboardsPage.panelGroupHeaderAssertion('PanelGroup Perform Changes and Save', 'Open'); + + cy.log(`16.14. Assert panel exists`); + persesDashboardsPage.assertPanel('Panel Perform Changes and Save', 'PanelGroup Perform Changes and Save', 'Open'); + + cy.log (`16.15. Click on Edit button`); + persesDashboardsPage.clickEditButton(); + + cy.log(`16.16. Delete variable`); + persesDashboardsPage.clickEditActionButton('EditVariables'); + persesDashboardsEditVariables.clickDeleteVariableButton(1); + persesDashboardsEditVariables.clickButton('Apply'); + persesDashboardsPage.assertVariableNotExist('ListVariable'); + + cy.log(`16.17. Delete panel group`); + persesDashboardsPanelGroup.clickPanelGroupAction('PanelGroup Perform Changes and Save', 'delete'); + persesDashboardsPanelGroup.clickDeletePanelGroupButton(); + persesDashboardsPage.clickEditActionButton('Save'); + persesDashboardsPage.assertPanelGroupNotExist('PanelGroup Perform Changes and Save'); + + }); + +} diff --git a/web/cypress/views/common.ts b/web/cypress/views/common.ts index e69fd524..80e21a4a 100644 --- a/web/cypress/views/common.ts +++ b/web/cypress/views/common.ts @@ -6,10 +6,16 @@ export const commonPages = { projectDropdownShouldNotExist: () => cy.byLegacyTestID('namespace-bar-dropdown').should('not.exist'), projectDropdownShouldExist: () => cy.byLegacyTestID('namespace-bar-dropdown').should('exist'), titleShouldHaveText: (title: string) => { + cy.wait(15000); cy.log('commonPages.titleShouldHaveText - ' + `${title}`); cy.bySemanticElement('h1', title).scrollIntoView().should('be.visible'); }, + titleModalShouldHaveText: (title: string) => { + cy.log('commonPages.titleModalShouldHaveText - ' + `${title}`); + cy.bySemanticElement('h2', title).scrollIntoView().should('be.visible'); + }, + linkShouldExist: (linkName: string) => { cy.log('commonPages.linkShouldExist - ' + `${linkName}`); cy.bySemanticElement('button', linkName).should('be.visible'); diff --git a/web/cypress/views/list-perses-dashboards.ts b/web/cypress/views/list-perses-dashboards.ts index 5c731118..bc9c2297 100644 --- a/web/cypress/views/list-perses-dashboards.ts +++ b/web/cypress/views/list-perses-dashboards.ts @@ -78,5 +78,6 @@ export const listPersesDashboardsPage = { const idx = index !== undefined ? index : 0; cy.log('listPersesDashboardsPage.clickDashboard'); cy.byTestID(listPersesDashboardsDataTestIDs.DashboardLinkPrefix+name).eq(idx).should('be.visible').click(); + cy.wait(15000); }, } diff --git a/web/cypress/views/perses-dashboards-edit-datasources.ts b/web/cypress/views/perses-dashboards-edit-datasources.ts new file mode 100644 index 00000000..c7c1bcfd --- /dev/null +++ b/web/cypress/views/perses-dashboards-edit-datasources.ts @@ -0,0 +1,95 @@ +import { commonPages } from "./common"; +import { persesAriaLabels, persesMUIDataTestIDs, editPersesDashboardsAddDatasource, IDs } from "../../src/components/data-test"; +import { persesDashboardsModalTitles, persesDashboardsRequiredFields } from "../fixtures/perses/constants"; + +export const persesDashboardsEditDatasources = { + + shouldBeLoaded: () => { + cy.log('persesDashboardsEditVariables.shouldBeLoaded'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.EDIT_DASHBOARD_DATASOURCES); + cy.byAriaLabel(persesAriaLabels.EditDashboardDatasourcesTable).should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('button').contains('Apply').should('be.visible').and('have.attr', 'disabled'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('button').contains('Cancel').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('button').contains('Add Datasource').should('be.visible'); + }, + + assertDatasource: (index: number, name: string, type: 'PrometheusDatasource' | 'TempoDatasource', description: string) => { + cy.log('persesDashboardsEditDatasources.assertDatasource'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('tbody').find('tr').eq(index).find('th').contains(name).should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('tbody').find('tr').eq(index).find('td').eq(0).contains(type).should('be.visible'); + if (description !== '') { + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('tbody').find('tr').eq(index).find('td').eq(1).contains(description).should('be.visible'); + } + }, + + assertDatasourceNotExist: (name: string) => { + cy.log('persesDashboardsEditDatasources.assertDatasource'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('th').contains(name).should('not.exist'); + }, + + clickButton: (button: 'Apply' | 'Cancel' | 'Add Datasource' | 'Add') => { + cy.log('persesDashboardsEditDatasources.clickButton'); + if (button === 'Cancel') { + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('button').contains(button).should('be.visible').click(); + cy.wait(1000); + cy.get('body').then((body) => { + if (body.find('#'+IDs.persesDashboardDiscardChangesDialog).length > 0 && body.find('#'+IDs.persesDashboardDiscardChangesDialog).is(':visible')) { + cy.bySemanticElement('button', 'Discard Changes').scrollIntoView().should('be.visible').click({ force: true }); + } + }); + } else { + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('button').contains(button).should('be.visible').click(); + } + }, + + addDatasource: (name: string, defaultDatasource: boolean, pluginOptions: 'Prometheus Datasource' | 'Tempo Datasource', displayLabel?: string, description?: string) => { + cy.log('persesDashboardsEditDatasources.addDatasource'); + cy.get('input[name="'+editPersesDashboardsAddDatasource.inputName+'"]').clear().type(name); + if (displayLabel !== undefined) { + cy.get('input[name="'+editPersesDashboardsAddDatasource.inputDisplayLabel+'"]').clear().type(displayLabel); + } + if (description !== undefined) { + cy.get('input[name="'+editPersesDashboardsAddDatasource.inputDescription+'"]').clear().type(description); + } + + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('input[name="'+editPersesDashboardsAddDatasource.inputDefaultDatasource+'"]').then((checkbox) => { + if ((checkbox.not(':checked') && defaultDatasource) || (checkbox.is(':checked') && !defaultDatasource)) { + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('input[name="'+editPersesDashboardsAddDatasource.inputDefaultDatasource+'"]').click(); + } + }); + + persesDashboardsEditDatasources.clickDropdownAndSelectOption('Source', pluginOptions); + + }, + + clickDropdownAndSelectOption: (label: string, option: string) => { + cy.log('persesDashboardsEditVariables.selectVariableType'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('label').contains(label).siblings('div').click(); + cy.get('li').contains(option).should('be.visible').click(); + }, + + assertRequiredFieldValidation: (field: string) => { + cy.log('persesDashboardsEditVariables.assertRequiredFieldValidation'); + + switch (field) { + case 'Name': + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('label').contains(field).siblings('p').should('have.text', persesDashboardsRequiredFields.AddVariableNameField); + break; + } + }, + + clickDiscardChangesButton: () => { + cy.log('persesDashboardsEditVariables.clickDiscardChangesButton'); + cy.bySemanticElement('button', 'Discard Changes').scrollIntoView().should('be.visible').click({ force: true }); + }, + + clickEditDatasourceButton: (index: number) => { + cy.log('persesDashboardsEditDatasources.clickEditDatasourceButton'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('[data-testid="'+persesMUIDataTestIDs.editDashboardEditVariableDatasourceEditButton+'"]').eq(index).should('be.visible').click(); + }, + + clickDeleteDatasourceButton: (index: number) => { + cy.log('persesDashboardsEditDatasources.clickDeleteDatasourceButton'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardDatasourcesModal).find('[data-testid="'+persesMUIDataTestIDs.editDashboardEditVariableDatasourceDeleteButton+'"]').eq(index).should('be.visible').click(); + }, +} diff --git a/web/cypress/views/perses-dashboards-edit-variables.ts b/web/cypress/views/perses-dashboards-edit-variables.ts new file mode 100644 index 00000000..9a1b393e --- /dev/null +++ b/web/cypress/views/perses-dashboards-edit-variables.ts @@ -0,0 +1,139 @@ +import { commonPages } from "./common"; +import { persesAriaLabels, persesMUIDataTestIDs, IDs, editPersesDashboardsAddVariable } from "../../src/components/data-test"; +import { persesDashboardsModalTitles, persesDashboardsAddListVariableSource, persesDashboardsAddListVariableSort, persesDashboardsRequiredFields } from "../fixtures/perses/constants"; + +export const persesDashboardsEditVariables = { + + shouldBeLoaded: () => { + cy.log('persesDashboardsEditVariables.shouldBeLoaded'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.EDIT_DASHBOARD_VARIABLES); + cy.byAriaLabel(persesAriaLabels.EditDashboardVariablesTable).should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('button').contains('Apply').should('be.visible').and('have.attr', 'disabled'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('button').contains('Cancel').should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('button').contains('Add Variable').should('be.visible'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.DASHBOARD_BUILT_IN_VARIABLES); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('#'+IDs.persesDashboardEditVariablesModalBuiltinButton).should('have.attr', 'aria-expanded', 'false'); + }, + + clickButton: (button: 'Apply' | 'Cancel' | 'Add Variable' | 'Add' | 'Run Query') => { + cy.log('persesDashboardsEditVariables.clickButton'); + cy.wait(3000); + if (button === 'Cancel') { + cy.get('body').then((body) => { + if (body.find('#'+IDs.persesDashboardDiscardChangesDialog).length > 0 && body.find('#'+IDs.persesDashboardDiscardChangesDialog).is(':visible')) { + cy.bySemanticElement('button', 'Discard Changes').scrollIntoView().should('be.visible').click({ force: true }); + } + }); + } else { + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('button').contains(button).should('be.visible').click(); + } + }, + + addTextVariable: (name: string, constant: boolean, displayLabel?: string, description?: string, value?: string) => { + cy.log('persesDashboardsEditVariables.addTextVariable'); + cy.get('input[name="'+editPersesDashboardsAddVariable.inputName+'"]').clear().type(name); + + const displayLabelInput = displayLabel !== undefined ? displayLabel : name; + const descriptionInput = description !== undefined ? description : name; + const valueInput = value !== undefined ? value : ''; + + cy.get('input[name="'+editPersesDashboardsAddVariable.inputDisplayLabel+'"]').clear().type(displayLabelInput); + cy.get('input[name="'+editPersesDashboardsAddVariable.inputDescription+'"]').clear().type(descriptionInput); + cy.get('input[name="'+editPersesDashboardsAddVariable.inputValue+'"]').clear().type(valueInput); + if (constant) { + cy.get('input[name="'+editPersesDashboardsAddVariable.inputConstant+'"]').click(); + } + }, + + addListVariable: ( + name: string, + allowMultiple: boolean, + allowAllValue: boolean, + customAllValue?: string, + displayLabel?: string, + description?: string, + source?: persesDashboardsAddListVariableSource, + sort?: persesDashboardsAddListVariableSort) => { + cy.log('persesDashboardsEditVariables.addListVariable'); + cy.get('input[name="'+editPersesDashboardsAddVariable.inputName+'"]').clear().type(name); + + if (displayLabel !== undefined && displayLabel !== '') { + cy.get('input[name="'+editPersesDashboardsAddVariable.inputDisplayLabel+'"]').clear().type(displayLabel); + } + if (description !== undefined && description !== '' ) { + cy.get('input[name="'+editPersesDashboardsAddVariable.inputDescription+'"]').clear().type(description); + } + persesDashboardsEditVariables.clickDropdownAndSelectOption('Type', 'List'); + + if (source !== undefined) { + persesDashboardsEditVariables.clickDropdownAndSelectOption('Source', source); + } + if (sort !== undefined) { + persesDashboardsEditVariables.clickDropdownAndSelectOption('Sort', sort); + } + if (allowMultiple) { + cy.get('input[name="'+editPersesDashboardsAddVariable.inputAllowMultiple+'"]').click(); + } + if (allowAllValue) { + cy.get('input[name="'+editPersesDashboardsAddVariable.inputAllowAllValue+'"]').click(); + if (customAllValue !== undefined && customAllValue !== '') { + cy.get('input[name="'+editPersesDashboardsAddVariable.inputCustomAllValue+'"]').clear().type(customAllValue); + } + } + }, + + /** + * + * @param label - label of the dropdown + * @param option - option to select + */ + clickDropdownAndSelectOption: (label: string, option: string) => { + cy.log('persesDashboardsEditVariables.selectVariableType'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('label').contains(label).siblings('div').click(); + cy.get('li').contains(option).should('be.visible').click(); + }, + + assertRequiredFieldValidation: (field: string) => { + cy.log('persesDashboardsEditVariables.assertRequiredFieldValidation'); + + switch (field) { + case 'Name': + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('label').contains(field).siblings('p').should('have.text', persesDashboardsRequiredFields.AddVariableNameField); + break; + } + }, + + clickDiscardChangesButton: () => { + cy.log('persesDashboardsEditVariables.clickDiscardChangesButton'); + cy.bySemanticElement('button', 'Discard Changes').scrollIntoView().should('be.visible').click({ force: true }); + }, + + toggleVariableVisibility: (index: number, visible: boolean) => { + cy.log('persesDashboardsEditVariables.toggleVariableVisibility'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('input[type="checkbox"]').eq(index).then((checkbox) => { + if ((checkbox.not(':checked') && visible) || (checkbox.is(':checked') && !visible)) { + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('input[type="checkbox"]').eq(index).click(); + } + }); + }, + + moveVariableUp: (index: number) => { + cy.log('persesDashboardsEditVariables.moveVariableUp'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('[data-testid="'+persesMUIDataTestIDs.editDashboardEditVariableMoveUpButton+'"]').eq(index).should('be.visible').click(); + }, + + moveVariableDown: (index: number) => { + cy.log('persesDashboardsEditVariables.moveVariableDown'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('[data-testid="'+persesMUIDataTestIDs.editDashboardEditVariableMoveDownButton+'"]').eq(index).should('be.visible').click(); + }, + + clickEditVariableButton: (index: number) => { + cy.log('persesDashboardsEditVariables.clickEditVariableButton'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('[data-testid="'+persesMUIDataTestIDs.editDashboardEditVariableDatasourceEditButton+'"]').eq(index).should('be.visible').click(); + }, + + clickDeleteVariableButton: (index: number) => { + cy.log('persesDashboardsEditVariables.clickDeleteVariableButton'); + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('[data-testid="'+persesMUIDataTestIDs.editDashboardEditVariableDatasourceDeleteButton+'"]').eq(index).should('be.visible').click(); + }, +} diff --git a/web/cypress/views/perses-dashboards-panel.ts b/web/cypress/views/perses-dashboards-panel.ts new file mode 100644 index 00000000..a016281f --- /dev/null +++ b/web/cypress/views/perses-dashboards-panel.ts @@ -0,0 +1,116 @@ +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"; + +export const persesDashboardsPanel = { + + addPanelShouldBeLoaded: () => { + cy.log('persesDashboardsPanel.addPanelShouldBeLoaded'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.ADD_PANEL); + cy.get('input[name="'+editPersesDashboardsAddPanel.inputName+'"]').should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelForm).find('label').contains('Group').should('be.visible'); + cy.get('input[name="'+editPersesDashboardsAddPanel.inputDescription+'"]').should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelForm).find('label').contains('Type').should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Add').should('be.visible').and('have.attr', 'disabled'); + cy.get('#'+IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Cancel').should('be.visible'); + }, + + clickButton: (button: 'Add' | 'Cancel') => { + cy.log('persesDashboardsPanel.clickButton'); + if (button === 'Cancel') { + cy.get('#'+IDs.persesDashboardAddPanelForm).siblings('div').find('button').contains(button).should('be.visible').click(); + cy.wait(1000); + cy.get('body').then((body) => { + if (body.find('#'+IDs.persesDashboardDiscardChangesDialog).length > 0 && body.find('#'+IDs.persesDashboardDiscardChangesDialog).is(':visible')) { + cy.bySemanticElement('button', 'Discard Changes').scrollIntoView().should('be.visible').click({ force: true }); + } + }); + } else { + cy.get('#'+IDs.persesDashboardAddPanelForm).siblings('div').find('button').contains(button).should('be.visible').click(); + } + }, + + clickDropdownAndSelectOption: (label: string, option: string) => { + cy.log('persesDashboardsPanel.clickDropdownAndSelectOption'); + cy.get('#'+IDs.persesDashboardAddPanelForm).find('label').contains(label).siblings('div').click(); + cy.wait(1000); + cy.get('li').contains(option).should('be.visible').click(); + }, + + assertRequiredFieldValidation: (field: string) => { + cy.log('persesDashboardsPanel.assertRequiredFieldValidation'); + + switch (field) { + case 'Name': + cy.get('#'+IDs.persesDashboardAddPanelForm).find('label').contains(field).siblings('p').should('have.text', 'Required'); + break; + } + }, + + addPanel: (name: string, group: string, type: string, description?: string) => { + cy.log('persesDashboardsPanel.addPanel'); + cy.wait(2000); + cy.get('input[name="'+editPersesDashboardsAddPanel.inputName+'"]').clear().type(name); + if (description !== undefined && description !== '') { + cy.get('input[name="'+editPersesDashboardsAddPanel.inputDescription+'"]').clear().type(description); + } + persesDashboardsPanel.clickDropdownAndSelectOption('Group', group); + persesDashboardsPanel.clickDropdownAndSelectOption('Type', type); + cy.get('#'+IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Add').should('be.visible').click(); + }, + + editPanelShouldBeLoaded: () => { + cy.log('persesDashboardsPanel.editPanelShouldBeLoaded'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.ADD_PANEL); + cy.get('input[name="'+editPersesDashboardsAddPanel.inputName+'"]').should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelForm).find('label').contains('Group').should('be.visible'); + cy.get('input[name="'+editPersesDashboardsAddPanel.inputDescription+'"]').should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelForm).find('label').contains('Type').should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Apply').should('be.visible').and('have.attr', 'disabled'); + cy.get('#'+IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Cancel').should('be.visible'); + }, + + editPanel: (name: string, group: string, type: string, description?: string) => { + cy.log('persesDashboardsPanel.editPanel'); + cy.get('input[name="'+editPersesDashboardsAddPanel.inputName+'"]').clear().type(name); + if (description !== undefined && description !== '') { + cy.get('input[name="'+editPersesDashboardsAddPanel.inputDescription+'"]').clear().type(description); + } + persesDashboardsPanel.clickDropdownAndSelectOption('Group', group); + persesDashboardsPanel.clickDropdownAndSelectOption('Type', type); + cy.get('#'+IDs.persesDashboardAddPanelForm).parent('div').find('h2').siblings('div').find('button').contains('Apply').should('be.visible').click(); + }, + + clickPanelGroupAction: (panelGroup: string, button: 'addPanel' | 'edit' | 'delete' | 'moveDown' | 'moveUp') => { + cy.log('persesDashboardsPage.clickPanelActions'); + + switch (button) { + case 'addPanel': + cy.byAriaLabel(persesAriaLabels.AddPanelToGroupPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'edit': + cy.byAriaLabel(persesAriaLabels.EditPanelGroupPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'delete': + cy.byAriaLabel(persesAriaLabels.DeletePanelGroupPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'moveDown': + cy.byAriaLabel(persesAriaLabels.MovePanelGroupPrefix + panelGroup + persesAriaLabels.MovePanelGroupDownSuffix).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'moveUp': + cy.byAriaLabel(persesAriaLabels.MovePanelGroupPrefix + panelGroup + persesAriaLabels.MovePanelGroupUpSuffix).scrollIntoView().should('be.visible').click({ force: true }); + break; + } + }, + + deletePanel: (panel: string) => { + cy.log('persesDashboardsPage.deletePanel'); + cy.byAriaLabel(persesAriaLabels.EditPanelDeleteButtonPrefix + panel).scrollIntoView().should('be.visible').click({ force: true }); + }, + + clickDeletePanelButton: () => { + cy.log('persesDashboardsPage.clickDeletePanelButton'); + cy.bySemanticElement('button', 'Delete').scrollIntoView().should('be.visible').click({ force: true }); + }, +} \ No newline at end of file diff --git a/web/cypress/views/perses-dashboards-panelgroup.ts b/web/cypress/views/perses-dashboards-panelgroup.ts new file mode 100644 index 00000000..37e9e77c --- /dev/null +++ b/web/cypress/views/perses-dashboards-panelgroup.ts @@ -0,0 +1,96 @@ +import { commonPages } from "./common"; +import { persesAriaLabels, persesMUIDataTestIDs, IDs } from "../../src/components/data-test"; +import { persesDashboardsModalTitles, persesDashboardsRequiredFields } from "../fixtures/perses/constants"; + +export const persesDashboardsPanelGroup = { + + addPanelGroupShouldBeLoaded: () => { + cy.log('persesDashboardsPanelGroup.addPanelGroupShouldBeLoaded'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.ADD_PANEL_GROUP); + cy.byDataTestID(persesMUIDataTestIDs.addPanelGroupFormName).should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).find('input').eq(1).should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).find('input').eq(2).should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).parent('div').siblings('div').find('button').contains('Apply').should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).parent('div').siblings('div').find('button').contains('Cancel').should('be.visible'); + }, + + clickButton: (button: 'Add' | 'Cancel') => { + cy.log('persesDashboardsPanelGroup.clickButton'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).parent('div').siblings('div').find('button').contains(button).should('be.visible').click(); + }, + + assertRequiredFieldValidation: (field: string) => { + cy.log('persesDashboardsPanelGroup.assertRequiredFieldValidation'); + + switch (field) { + case 'Name': + cy.byDataTestID(persesMUIDataTestIDs.editDashboardVariablesModal).find('label').contains(field).siblings('p').should('have.text', persesDashboardsRequiredFields.AddVariableNameField); + break; + } + }, + + addPanelGroup: (name: string, collapse_state: 'Open' | 'Closed', repeat_variable: string) => { + cy.log('persesDashboardsPanelGroup.addPanelGroup'); + cy.wait(2000); + cy.byDataTestID(persesMUIDataTestIDs.addPanelGroupFormName).find('input').clear().type(name); + cy.byPFRole('dialog').find('div[role="combobox"]').eq(0).click(); + cy.byPFRole('option').contains(collapse_state).click(); + if (repeat_variable !== undefined && repeat_variable !== '') { + cy.byPFRole('dialog').find('div[role="combobox"]').eq(1).click(); + cy.byPFRole('option').contains(repeat_variable).click(); + } + cy.bySemanticElement('button', 'Add').should('be.visible').click(); + }, + + editPanelGroupShouldBeLoaded: () => { + cy.log('persesDashboardsPanelGroup.editPanelGroupShouldBeLoaded'); + commonPages.titleModalShouldHaveText(persesDashboardsModalTitles.EDIT_PANEL_GROUP); + cy.byDataTestID(persesMUIDataTestIDs.addPanelGroupFormName).should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).find('input').eq(1).should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).find('input').eq(2).should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).parent('div').siblings('div').find('button').contains('Apply').should('be.visible'); + cy.get('#'+IDs.persesDashboardAddPanelGroupForm).parent('div').siblings('div').find('button').contains('Cancel').should('be.visible'); + }, + + editPanelGroup: (name: string, collapse_state: 'Open' | 'Closed', repeat_variable: string) => { + cy.log('persesDashboardsPanelGroup.editPanelGroup'); + cy.byDataTestID(persesMUIDataTestIDs.addPanelGroupFormName).find('input').clear().type(name); + cy.byPFRole('dialog').find('div[role="combobox"]').eq(0).click(); + cy.byPFRole('option').contains(collapse_state).click(); + if (repeat_variable !== undefined && repeat_variable !== '') { + cy.byPFRole('dialog').find('div[role="combobox"]').eq(1).click(); + cy.byPFRole('option').contains(repeat_variable).click(); + } + cy.bySemanticElement('button', 'Apply').should('be.visible').click(); + }, + + clickPanelGroupAction: (panelGroup: string, button: 'addPanel' | 'edit' | 'delete' | 'moveDown' | 'moveUp') => { + cy.log('persesDashboardsPage.clickPanelActions'); + + switch (button) { + case 'addPanel': + cy.byAriaLabel(persesAriaLabels.AddPanelToGroupPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'edit': + cy.byAriaLabel(persesAriaLabels.EditPanelGroupPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'delete': + cy.byAriaLabel(persesAriaLabels.DeletePanelGroupPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'moveDown': + cy.byAriaLabel(persesAriaLabels.MovePanelGroupPrefix + panelGroup + persesAriaLabels.MovePanelGroupDownSuffix).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'moveUp': + cy.byAriaLabel(persesAriaLabels.MovePanelGroupPrefix + panelGroup + persesAriaLabels.MovePanelGroupUpSuffix).scrollIntoView().should('be.visible').click({ force: true }); + break; + } + + }, + + clickDeletePanelGroupButton: () => { + cy.log('persesDashboardsPage.clickDeletePanelGroupButton'); + cy.bySemanticElement('button', 'Delete').scrollIntoView().should('be.visible').click({ force: true }); + }, + + +} \ No newline at end of file diff --git a/web/cypress/views/perses-dashboards.ts b/web/cypress/views/perses-dashboards.ts index 4eef6756..73e850fd 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 } from "../../src/components/data-test"; +import { DataTestIDs, Classes, LegacyTestIDs, persesAriaLabels, persesMUIDataTestIDs, listPersesDashboardsOUIAIDs, IDs, persesDashboardDataTestIDs, listPersesDashboardsDataTestIDs } from "../../src/components/data-test"; import { MonitoringPageTitles } from "../fixtures/monitoring/constants"; -import { listPersesDashboardsPageSubtitle } from "../fixtures/perses/constants"; +import { listPersesDashboardsPageSubtitle, persesDashboardsModalTitles } from "../fixtures/perses/constants"; import { persesDashboardsTimeRange, persesDashboardsRefreshInterval, persesDashboardsDashboardDropdownCOO, persesDashboardsDashboardDropdownPersesDev, persesDashboardsAcceleratorsCommonMetricsPanels } from "../fixtures/perses/constants"; export const persesDashboardsPage = { @@ -9,14 +9,14 @@ export const persesDashboardsPage = { shouldBeLoaded: () => { cy.log('persesDashboardsPage.shouldBeLoaded'); commonPages.titleShouldHaveText(MonitoringPageTitles.DASHBOARDS); - cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).contains(persesDashboardsTimeRange.LAST_30_MINUTES).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.ZoomInButton).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.ZoomOutButton).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.RefreshButton).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).contains(persesDashboardsRefreshInterval.OFF).should('be.visible'); - cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('input').should('be.visible'); - cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').should('be.visible'); - cy.byLegacyTestID(LegacyTestIDs.PersesDashboardSection).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).contains(persesDashboardsTimeRange.LAST_30_MINUTES).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.ZoomInButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.ZoomOutButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.RefreshButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).contains(persesDashboardsRefreshInterval.OFF).scrollIntoView().should('be.visible'); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('input').scrollIntoView().should('be.visible'); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').scrollIntoView().should('be.visible'); + cy.byLegacyTestID(LegacyTestIDs.PersesDashboardSection).scrollIntoView().should('be.visible'); }, @@ -24,91 +24,107 @@ export const persesDashboardsPage = { shouldBeLoaded1: () => { cy.log('persesDashboardsPage.shouldBeLoaded'); commonPages.titleShouldHaveText(MonitoringPageTitles.DASHBOARDS); - cy.byOUIAID(listPersesDashboardsOUIAIDs.PageHeaderSubtitle).should('contain', listPersesDashboardsPageSubtitle).should('be.visible'); + cy.byOUIAID(listPersesDashboardsOUIAIDs.PageHeaderSubtitle).scrollIntoView().should('contain', listPersesDashboardsPageSubtitle).should('be.visible'); - cy.byTestID(persesDashboardDataTestIDs.editDashboardButtonToolbar).should('be.visible'); + cy.byTestID(persesDashboardDataTestIDs.editDashboardButtonToolbar).scrollIntoView().should('be.visible'); - cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).contains(persesDashboardsTimeRange.LAST_30_MINUTES).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.ZoomInButton).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.ZoomOutButton).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.RefreshButton).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).contains(persesDashboardsRefreshInterval.OFF).should('be.visible'); + cy.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).should('be.visible'); - cy.byAriaLabel(persesAriaLabels.ViewJSONButton).should('be.visible'); + cy.get('#' + IDs.persesDashboardDownloadButton).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.ViewJSONButton).scrollIntoView().should('be.visible'); - cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('input').should('be.visible'); - cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').should('be.visible'); - cy.byLegacyTestID(LegacyTestIDs.PersesDashboardSection).should('be.visible'); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('input').scrollIntoView().should('be.visible'); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').scrollIntoView().should('be.visible'); + cy.byLegacyTestID(LegacyTestIDs.PersesDashboardSection).scrollIntoView().should('be.visible'); }, clickTimeRangeDropdown: (timeRange: persesDashboardsTimeRange) => { cy.log('persesDashboardsPage.clickTimeRangeDropdown'); - cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).should('be.visible').click({force: true}); - cy.byPFRole('option').contains(timeRange).should('be.visible').click({force: true}); + cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).scrollIntoView().should('be.visible').click({ force: true }); + cy.byPFRole('option').contains(timeRange).scrollIntoView().should('be.visible').click({ force: true }); }, timeRangeDropdownAssertion: () => { cy.log('persesDashboardsPage.timeRangeDropdownAssertion'); - cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).should('be.visible').click({force: true}); + cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).scrollIntoView().should('be.visible').click({ force: true }); const timeRanges = Object.values(persesDashboardsTimeRange); timeRanges.forEach((timeRange) => { cy.log('Time range: ' + timeRange); - cy.byPFRole('option').contains(timeRange).should('be.visible'); + cy.byPFRole('option').contains(timeRange).scrollIntoView().should('be.visible'); }); - cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).should('be.visible').click({force: true}); + cy.byAriaLabel(persesAriaLabels.TimeRangeDropdown).scrollIntoView().should('be.visible').click({ force: true }); }, clickRefreshButton: () => { cy.log('persesDashboardsPage.clickRefreshButton'); - cy.byAriaLabel(persesAriaLabels.RefreshButton).should('be.visible').click(); + cy.byAriaLabel(persesAriaLabels.RefreshButton).scrollIntoView().should('be.visible').click(); }, clickRefreshIntervalDropdown: (interval: persesDashboardsRefreshInterval) => { cy.log('persesDashboardsPage.clickRefreshIntervalDropdown'); - cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).should('be.visible').click({force: true}); - cy.byPFRole('option').contains(interval).should('be.visible').click({force: true}); + cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).scrollIntoView().should('be.visible').click({ force: true }); + cy.byPFRole('option').contains(interval).scrollIntoView().should('be.visible').click({ force: true }); }, refreshIntervalDropdownAssertion: () => { cy.log('persesDashboardsPage.refreshIntervalDropdownAssertion'); - cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).should('be.visible').click({force: true}); + cy.byAriaLabel(persesAriaLabels.RefreshIntervalDropdown).scrollIntoView().should('be.visible').click({ force: true }); const intervals = Object.values(persesDashboardsRefreshInterval); intervals.forEach((interval) => { cy.log('Refresh interval: ' + interval); - cy.byPFRole('option').contains(interval).should('be.visible'); + cy.byPFRole('option').contains(interval).scrollIntoView().should('be.visible'); }); //Closing the dropdown by clicking on the OFF option, because the dropdown is not accessible while the menu is open, even forcing it - cy.byPFRole('option').contains(persesDashboardsRefreshInterval.OFF).should('be.visible').click({force: true}); - + cy.byPFRole('option').contains(persesDashboardsRefreshInterval.OFF).scrollIntoView().should('be.visible').click({ force: true }); + }, clickDashboardDropdown: (dashboard: keyof typeof persesDashboardsDashboardDropdownCOO | keyof typeof persesDashboardsDashboardDropdownPersesDev) => { cy.log('persesDashboardsPage.clickDashboardDropdown'); - cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').should('be.visible').click({force: true}); - cy.byPFRole('option').contains(dashboard).should('be.visible').click({force: true}); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').scrollIntoView().should('be.visible').click({ force: true }); + cy.byPFRole('option').contains(dashboard).scrollIntoView().should('be.visible').click({ force: true }); }, dashboardDropdownAssertion: (constants: typeof persesDashboardsDashboardDropdownCOO | typeof persesDashboardsDashboardDropdownPersesDev) => { cy.log('persesDashboardsPage.dashboardDropdownAssertion'); - cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').should('be.visible').click({force: true}); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').scrollIntoView().should('be.visible').click({ force: true }); const dashboards = Object.values(constants); dashboards.forEach((dashboard) => { cy.log('Dashboard: ' + dashboard[0]); - cy.get(Classes.MenuItem).contains(dashboard[0]).should('be.visible'); + cy.get(Classes.MenuItem).contains(dashboard[0]).scrollIntoView().should('be.visible'); if (dashboard[1] !== '') { - cy.get(Classes.MenuItem).should('contain', dashboard[0]).and('contain', dashboard[1]); + cy.get(Classes.MenuItem).scrollIntoView().should('contain', dashboard[0]).and('contain', dashboard[1]); } }); cy.wait(1000); - cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').should('be.visible').click({force: true}); + cy.byTestID(DataTestIDs.PersesDashboardDropdown).find('button').scrollIntoView().should('be.visible').click({ force: true }); }, - panelGroupHeaderAssertion: (panelGroupHeader: string) => { + panelGroupHeaderAssertion: (panelGroupHeader: string, collapse_state: 'Open' | 'Closed') => { cy.log('persesDashboardsPage.panelGroupHeaderAssertion'); - cy.byDataTestID(persesMUIDataTestIDs.panelGroupHeader).contains(panelGroupHeader).should('be.visible'); + cy.byDataTestID(persesMUIDataTestIDs.panelGroupHeader).contains(panelGroupHeader).scrollIntoView().should('be.visible'); + if (collapse_state === 'Open') { + cy.byAriaLabel(persesAriaLabels.CollapseGroupButtonPrefix + panelGroupHeader).scrollIntoView().should('be.visible'); + } else { + cy.byAriaLabel(persesAriaLabels.OpenGroupButtonPrefix + panelGroupHeader).scrollIntoView().should('be.visible'); + } + }, + + assertPanelGroupNotExist: (panelGroup: string) => { + cy.log('persesDashboardsPage.assertPanelGroupNotExist'); + cy.byAriaLabel(persesAriaLabels.OpenGroupButtonPrefix + panelGroup).should('not.exist'); + cy.byAriaLabel(persesAriaLabels.CollapseGroupButtonPrefix + panelGroup).should('not.exist'); + }, + + assertPanelGroupOrder: (panelGroup: string, order: number) => { + cy.log('persesDashboardsPage.assertPanelGroupOrder'); + cy.byDataTestID(persesMUIDataTestIDs.panelGroupHeader).eq(order).find('h2').contains(panelGroup).scrollIntoView().should('be.visible'); }, panelHeadersAcceleratorsCommonMetricsAssertion: () => { @@ -121,14 +137,24 @@ export const persesDashboardsPage = { }); }, - expandPanel: (panel: keyof typeof persesDashboardsAcceleratorsCommonMetricsPanels | string) => { + expandPanel: (panel: string) => { cy.log('persesDashboardsPage.expandPanel'); - cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(panel).scrollIntoView().siblings('div').eq(2).find('[data-testid="ArrowExpandIcon"]').click({force: true}); + persesDashboardsPage.clickPanelAction(panel, 'expand'); }, - collapsePanel: (panel: keyof typeof persesDashboardsAcceleratorsCommonMetricsPanels | string) => { + collapsePanel: (panel: string) => { cy.log('persesDashboardsPage.collapsePanel'); - cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(panel).scrollIntoView().siblings('div').eq(2).find('[data-testid="ArrowCollapseIcon"]').click({force: true}); + persesDashboardsPage.clickPanelAction(panel, 'collapse'); + }, + + expandPanelGroup: (panelGroup: string) => { + cy.log('persesDashboardsPage.expandPanelGroup'); + cy.byAriaLabel(persesAriaLabels.OpenGroupButtonPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); + }, + + collapsePanelGroup: (panelGroup: string) => { + cy.log('persesDashboardsPage.collapsePanelGroup'); + cy.byAriaLabel(persesAriaLabels.CollapseGroupButtonPrefix + panelGroup).scrollIntoView().should('be.visible').click({ force: true }); }, statChartValueAssertion: (panel: keyof typeof persesDashboardsAcceleratorsCommonMetricsPanels | string, noData: boolean) => { @@ -143,8 +169,228 @@ export const persesDashboardsPage = { searchAndSelectVariable: (variable: string, value: string) => { cy.log('persesDashboardsPage.searchAndSelectVariable'); - cy.byDataTestID(persesMUIDataTestIDs.variableDropdown+'-'+variable).find('input').type(value); - cy.byPFRole('option').contains(value).click({force: true}); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown + '-' + variable).find('input').type(value); + cy.byPFRole('option').contains(value).click({ force: true }); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown + '-' + variable).find('button').click({ force: true }); + cy.wait(1000); + }, + + searchAndTypeVariable: (variable: string, value: string) => { + cy.log('persesDashboardsPage.searchAndTypeVariable'); + if (value !== undefined && value !== '') { + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown + '-' + variable).find('input').type(value); + } + cy.wait(1000); + }, + + assertVariableBeVisible: (variable: string) => { + cy.log('persesDashboardsPage.assertVariableBeVisible'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown + '-' + variable).should('be.visible'); + }, + + assertVariableNotExist: (variable: string) => { + cy.log('persesDashboardsPage.assertVariableNotExist'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown + '-' + variable).should('not.exist'); + }, + + assertVariableNotBeVisible: (variable: string) => { + cy.log('persesDashboardsPage.assertVariableNotBeVisible'); + cy.byDataTestID(persesMUIDataTestIDs.variableDropdown + '-' + variable).should('not.be.visible'); + }, + + clickEditButton: () => { + cy.log('persesDashboardsPage.clickEditButton'); + cy.byTestID(persesDashboardDataTestIDs.editDashboardButtonToolbar).scrollIntoView().should('be.visible').click({ force: true }); + cy.wait(2000); + }, + + assertEditModeButtons: () => { + cy.log('persesDashboardsPage.assertEditModeButtons'); + cy.byTestID(persesDashboardDataTestIDs.editDashboardButtonToolbar).should('not.exist'); + cy.byAriaLabel(persesAriaLabels.EditVariablesButton).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.EditDatasourcesButton).should('not.exist'); + cy.byAriaLabel(persesAriaLabels.AddPanelButton).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.AddGroupButton).should('be.visible'); + cy.bySemanticElement('button', 'Save').should('be.visible'); + cy.byTestID(persesDashboardDataTestIDs.cancelButtonToolbar).should('be.visible'); + }, + + clickEditActionButton: (button: 'EditVariables' | 'AddPanel' | 'AddGroup' | 'Save' | 'Cancel') => { + cy.log('persesDashboardsPage.clickEditActionButton'); + cy.wait(2000); + switch (button) { + case 'EditVariables': + cy.byAriaLabel(persesAriaLabels.EditVariablesButton).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 }); + break; + case 'AddGroup': + cy.byAriaLabel(persesAriaLabels.AddGroupButton).scrollIntoView().should('be.visible').click({ force: true }); + break; + case 'Save': + cy.bySemanticElement('button', 'Save').scrollIntoView().should('be.visible').click({ force: true }); + persesDashboardsPage.clickSaveDashboardButton(); + break; + case 'Cancel': + cy.byTestID(persesDashboardDataTestIDs.cancelButtonToolbar).scrollIntoView().should('be.visible').click({ force: true }); + cy.wait(1000); + persesDashboardsPage.clickDiscardChangesButton(); + break; + } + }, + + assertEditModePanelGroupButtons: (panelGroup: string) => { + cy.log('persesDashboardsPage.assertEditModePanelGroupButtons'); + cy.byAriaLabel(persesAriaLabels.AddPanelToGroupPrefix + panelGroup).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.EditPanelGroupPrefix + panelGroup).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.DeletePanelGroupPrefix + panelGroup).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.MovePanelGroupPrefix + panelGroup + persesAriaLabels.MovePanelGroupDownSuffix).scrollIntoView().should('be.visible'); + cy.byAriaLabel(persesAriaLabels.MovePanelGroupPrefix + panelGroup + persesAriaLabels.MovePanelGroupUpSuffix).scrollIntoView().should('be.visible'); + }, + + clickPanelAction: (panel: string, button: 'expand' | 'collapse' | 'edit' | 'duplicate' | 'delete') => { + cy.log('persesDashboardsPage.clickPanelActions'); + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(panel).siblings('div').eq(0).then((element1) => { + if (element1.find('[data-testid="MenuIcon"]').length > 0 && element1.find('[data-testid="MenuIcon"]').is(':visible')) { + cy.byAriaLabel(persesAriaLabels.EditPanelActionMenuButtonPrefix + panel).should('be.visible').click({ force: true }); + } + }); + + switch (button) { + case 'expand': + cy.byAriaLabel(persesAriaLabels.EditPanelExpandCollapseButtonPrefix + panel + persesAriaLabels.EditPanelExpandCollapseButtonSuffix).find('[data-testid="ArrowExpandIcon"]').eq(0).invoke('show').click({ force: true }); + break; + case 'collapse': + cy.byAriaLabel(persesAriaLabels.EditPanelExpandCollapseButtonPrefix + panel + persesAriaLabels.EditPanelExpandCollapseButtonSuffix).find('[data-testid="ArrowCollapseIcon"]').eq(1).should('be.visible').click({ force: true }); + break; + case 'edit': + cy.byAriaLabel(persesAriaLabels.EditPanelPrefix + panel).should('be.visible').click({ force: true }); + break; + case 'duplicate': + cy.byAriaLabel(persesAriaLabels.EditPanelDuplicateButtonPrefix + panel).should('be.visible').click({ force: true }); + break; + case 'delete': + cy.byAriaLabel(persesAriaLabels.EditPanelDeleteButtonPrefix + panel).should('be.visible').click({ force: true }); + break; + } + }, + + assertPanelActionButtons: (panel: string) => { + cy.log('persesDashboardsPage.assertPanelActionButtons'); + + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(panel).siblings('div').eq(1).then((element1) => { + if (element1.find('[data-testid="MenuIcon"]').length > 0 && element1.find('[data-testid="MenuIcon"]').is(':visible')) { + cy.byAriaLabel(persesAriaLabels.EditPanelExpandCollapseButtonPrefix + panel + persesAriaLabels.EditPanelExpandCollapseButtonSuffix).find('[data-testid="ArrowExpandIcon"]').eq(0).should('be.visible').click(); + } + cy.byAriaLabel(persesAriaLabels.EditPanelExpandCollapseButtonPrefix + panel + persesAriaLabels.EditPanelExpandCollapseButtonSuffix).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.EditPanelPrefix + panel).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.EditPanelDuplicateButtonPrefix + panel).should('be.visible'); + cy.byAriaLabel(persesAriaLabels.EditPanelDeleteButtonPrefix + panel).should('be.visible'); + + }); + }, + + clickSaveDashboardButton: () => { + cy.log('persesDashboardsPage.clickSaveDashboardButton'); + + 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 }); + } + }); + }, + + backToListPersesDashboardsPage: () => { + cy.log('persesDashboardsPage.backToListPersesDashboardsPage'); + cy.byTestID(listPersesDashboardsDataTestIDs.PersesBreadcrumbDashboardItem).scrollIntoView().should('be.visible').click({ force: true }); + }, + + clickDiscardChangesButton: () => { + cy.log('persesDashboardsPage.clickDiscardChangesButton'); + cy.get('body').then((body) => { + if (body.find('#'+IDs.persesDashboardDiscardChangesDialog).length > 0 && body.find('#'+IDs.persesDashboardDiscardChangesDialog).is(':visible')) { + cy.bySemanticElement('button', 'Discard Changes').scrollIntoView().should('be.visible').click({ force: true }); + } + }); + }, + + assertPanel: (name: string, group: string, collapse_state: 'Open' | 'Closed') => { + cy.log('persesDashboardsPage.assertPanel'); + persesDashboardsPage.panelGroupHeaderAssertion(group, collapse_state); + if (collapse_state === 'Open') { + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(name).scrollIntoView().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 }); + } + }, + + assertPanelNotExist: (name: string) => { + cy.log('persesDashboardsPage.assertPanelNotExist'); + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').contains(name).should('not.exist'); + }, + + downloadDashboard: (clearFolder: boolean, dashboardName: string, format: 'JSON' | 'YAML' | 'YAML (CR)') => { + cy.log('persesDashboardsPage.downloadDashboard'); + + if (clearFolder) { + cy.task('clearDownloads'); + } + + cy.get('#'+ IDs.persesDashboardDownloadButton).scrollIntoView().should('be.visible').click({ force: true }); + cy.byPFRole('menuitem').contains(format).should('be.visible').click({ force: true }); cy.wait(1000); + let filename: string; + if (format === 'YAML (CR)') { + filename = dashboardName + '-cr' + '.yaml'; + } else { + filename = dashboardName + '.' + format.toLowerCase(); + } + persesDashboardsPage.assertFilename(true, filename); + }, + + assertFilename: (clearFolder: boolean, fileNameExp: string) => { + cy.log('persesDashboardsPage.assertFilename'); + let downloadedFileName: string | null = null; + const downloadsFolder = Cypress.config('downloadsFolder'); + const expectedFileNamePattern = fileNameExp; + + cy.waitUntil(() => { + return cy.task('getFilesInFolder', downloadsFolder).then((currentFiles: string[]) => { + const matchingFile = currentFiles.find(file => file.includes(expectedFileNamePattern)); + if (matchingFile) { + downloadedFileName = matchingFile; + return true; + } + return false; + }); + }, { + timeout: 20000, + interval: 1000, + errorMsg: `File matching "${expectedFileNamePattern}" was not downloaded within timeout.` + }); + + cy.then(() => { + expect(downloadedFileName).to.not.be.null; + cy.task('doesFileExist', { fileName: downloadedFileName }).should('be.true'); + }); + }, + + viewJSON: (dashboardName: string, namespace: string) => { + cy.log('persesDashboardsPage.viewJSON'); + cy.byAriaLabel(persesAriaLabels.ViewJSONButton).scrollIntoView().should('be.visible').click({ force: true }); + cy.byPFRole('dialog').find('h2').contains(persesDashboardsModalTitles.VIEW_JSON_DIALOG).scrollIntoView().should('be.visible'); + cy.byAriaLabel('Close').should('be.visible').click({ force: true }); + }, + + assertDuplicatedPanel: (panel: string, amount: number) => { + cy.log('persesDashboardsPage.assertDuplicatedPanel'); + cy.byDataTestID(persesMUIDataTestIDs.panelHeader).find('h6').filter(`:contains("${panel}")`).should('have.length', amount); }, } diff --git a/web/cypress/views/troubleshooting-panel.ts b/web/cypress/views/troubleshooting-panel.ts index e11b91a5..0238a765 100644 --- a/web/cypress/views/troubleshooting-panel.ts +++ b/web/cypress/views/troubleshooting-panel.ts @@ -5,7 +5,9 @@ export const troubleshootingPanelPage = { openSignalCorrelation: () => { cy.log('troubleshootingPanelPage.openSignalCorrelation'); cy.byLegacyTestID(LegacyTestIDs.ApplicationLauncher).should('be.visible').click(); + cy.wait(3000); cy.byTestID(DataTestIDs.MastHeadApplicationItem).contains('Signal Correlation').should('be.visible').click(); + cy.wait(3000); }, signalCorrelationShouldNotBeVisible: () => { diff --git a/web/src/components/data-test.ts b/web/src/components/data-test.ts index ec4f74f6..d4aa5b5c 100644 --- a/web/src/components/data-test.ts +++ b/web/src/components/data-test.ts @@ -178,6 +178,11 @@ export const IDs = { ChartAxis1ChartLabel: 'chart-axis-1-ChartLabel', //id^=IDs.ChartAxis1ChartLabel AxisY persesDashboardCount: 'options-menu-top-pagination', persesDashboardDownloadButton: 'download-dashboard-button', + persesDashboardActionMenuModal: 'action-menu', + persesDashboardEditVariablesModalBuiltinButton: 'builtin', + persesDashboardAddPanelGroupForm: 'panel-group-editor-form', + persesDashboardAddPanelForm: 'panel-editor-form', + persesDashboardDiscardChangesDialog: 'discard-dialog', }; export const Classes = { @@ -226,13 +231,46 @@ export const persesAriaLabels = { ZoomInButton: 'Zoom in', ZoomOutButton: 'Zoom out', ViewJSONButton: 'View JSON', + EditVariablesButton: 'Edit variables', + EditDatasourcesButton: 'Edit datasources', + AddPanelButton: 'Add panel', + AddGroupButton: 'Add panel group', + OpenGroupButtonPrefix: 'expand group ', + CollapseGroupButtonPrefix: 'collapse group ', + //PanelGroup toolbar buttons + AddPanelToGroupPrefix: 'add panel to group ', + EditPanelGroupPrefix: 'edit group ', + DeletePanelGroupPrefix: 'delete group ', + MovePanelGroupPrefix: 'move group ', + MovePanelGroupDownSuffix: ' down', + MovePanelGroupUpSuffix: ' up', + EditDashboardVariablesTable: 'table of variables', + EditDashboardDatasourcesTable: 'table of datasources', + //Panel toolbar buttons + EditPanelActionMenuButtonPrefix: 'show panel actions for ', + EditPanelExpandCollapseButtonPrefix: 'toggle panel ', + EditPanelExpandCollapseButtonSuffix: ' view mode', + EditPanelPrefix: 'edit panel ', + EditPanelDuplicateButtonPrefix: 'duplicate panel ', + EditPanelDeleteButtonPrefix: 'delete panel ', + EditPanelMovePanelButtonPrefix: 'move panel ', }; //data-testid from MUI components export const persesMUIDataTestIDs = { variableDropdown: 'variable', + panelGroup: 'panel-group', panelGroupHeader: 'panel-group-header', panelHeader: 'panel', + editDashboardVariablesModal: 'variable-editor', + editDashboardDatasourcesModal: 'datasource-editor', + editDashboardAddVariableRunQueryButton: 'run_query_button', + editDashboardAddVariablePreviewValuesCopy: 'ClipboardOutlineIcon', + editDashboardEditVariableMoveDownButton: 'ArrowDownIcon', + editDashboardEditVariableMoveUpButton: 'ArrowUpIcon', + editDashboardEditVariableDatasourceEditButton: 'PencilIcon', + editDashboardEditVariableDatasourceDeleteButton: 'TrashCanIcon', + addPanelGroupFormName: 'panel-group-editor-name', }; export const persesDashboardDataTestIDs = { @@ -260,3 +298,31 @@ export const listPersesDashboardsOUIAIDs = { persesListDataViewHeaderSortButton: 'PersesDashList-DataViewTable-th', persesListDataViewTableDashboardNameTD: 'PersesDashList-DataViewTable-td-', }; + +//name attribute from MUI components +export const editPersesDashboardsAddVariable = { + inputName: 'spec.name', + inputDisplayLabel: 'spec.display.name', + inputDescription: 'spec.display.description', + //type='Text' + inputValue: 'spec.value', + inputConstant: 'spec.constant', + //type='List' + inputCapturingRegexp: 'spec.capturingRegexp', + inputAllowMultiple: 'spec.allowMultiple', + inputAllowAllValue: 'spec.allowAllValue', + inputCustomAllValue: 'spec.customAllValue', +}; + +//name attribute from MUI components +export const editPersesDashboardsAddDatasource = { + inputName: 'name', + inputDefaultDatasource: 'spec.default', + inputDisplayLabel: 'title', + inputDescription: 'description', +}; + +export const editPersesDashboardsAddPanel = { + inputName: 'panelDefinition.spec.display.name', + inputDescription: 'panelDefinition.spec.display.description', +};