From 5826bdb36009240362d79376a5a2531fee6c4c12 Mon Sep 17 00:00:00 2001 From: David Rajnoha Date: Fri, 31 Oct 2025 09:05:47 +0100 Subject: [PATCH] test(incidents): add short duration incidents to charts UI regression test Extend comprehensive charts UI test to verify short duration incidents (<5min) are visible and selectable. Adds scenarios for 1-min and 10-min incidents with proper bar rendering and alert loading verification. Updates test fixture and adds selectIncidentById/deselectIncidentById page object methods for incident selection. --- .../02.reg_ui_charts_comprehensive.cy.ts | 275 +++++++++------- .../12-charts-ui-comprehensive.yaml | 310 ++++++------------ web/cypress/views/incidents-page.ts | 47 +++ 3 files changed, 300 insertions(+), 332 deletions(-) diff --git a/web/cypress/e2e/incidents/regression/02.reg_ui_charts_comprehensive.cy.ts b/web/cypress/e2e/incidents/regression/02.reg_ui_charts_comprehensive.cy.ts index 436a7662..71999c6d 100644 --- a/web/cypress/e2e/incidents/regression/02.reg_ui_charts_comprehensive.cy.ts +++ b/web/cypress/e2e/incidents/regression/02.reg_ui_charts_comprehensive.cy.ts @@ -1,13 +1,13 @@ /* -Regression test for Charts UI bugs (Section 2 of TESTING_CHECKLIST.md) +Regression test for Charts UI bugs and Data Loading bugs (Sections 2 & 3.1 of TESTING_CHECKLIST.md) This test loads comprehensive test data covering: - 2.1: Tooltip Positioning Issues - 2.2: Bar Sorting & Visibility Issues - 2.3: Date/Time Display Issues +- 3.1: Short Duration Incidents Visibility (< 5 min) + -Test data: 12 incidents with 1-6 alerts each, varying durations (10m to 8h), -alert names (4 to 180+ chars), multi-component and multi-severity scenarios. */ import { incidentsPage } from '../../../views/incidents-page'; @@ -44,6 +44,31 @@ function verifyTooltipPositioning( } } +function verifyIncidentBarDimensions(index: number, context: string) { + incidentsPage.getIncidentBarRect(index).then((barRect) => { + expect(barRect.width, `${context} should have visible width`).to.be.greaterThan(0); + expect(barRect.height, `${context} should have visible height`).to.be.greaterThan(0); + }); +} + +function verifyIncidentBarHasVisiblePaths(index: number, context: string) { + incidentsPage.elements.incidentsChartBarsGroups() + .eq(index) + .find('path[role="presentation"]') + .then(($paths) => { + const visiblePath = $paths.filter((i, el) => { + const fillOpacity = Cypress.$(el).css('fill-opacity') || Cypress.$(el).attr('fill-opacity'); + return parseFloat(fillOpacity || '0') > 0; + }).first(); + + expect(visiblePath.length, `${context} should have visible path`).to.be.greaterThan(0); + }); +} + +function verifyIncidentBarIsVisible(index: number, context: string) { + verifyIncidentBarDimensions(index, context); + verifyIncidentBarHasVisiblePaths(index, context); +} const MCP = { namespace: 'openshift-cluster-observability-operator', packageName: 'cluster-observability-operator', @@ -78,40 +103,45 @@ describe('Regression: Charts UI - Comprehensive', () => { incidentsPage.clearAllFilters(); incidentsPage.setDays('7 days'); incidentsPage.elements.incidentsChartContainer().should('be.visible'); - incidentsPage.elements.incidentsChartBarsGroups().should('have.length', 14); + incidentsPage.elements.incidentsChartBarsGroups().should('have.length', 10); - // Chart order: Index 0 = newest (top), Index 13 = oldest (bottom) - // 0: network-firing-short-002 (10m) - // 13: version-short-name-001 (8h) - - cy.log('1.2 Test top incident (newest) tooltip positioning'); - incidentsPage.getIncidentBarRect(0).then((barRect) => { - incidentsPage.hoverOverIncidentBar(0); - incidentsPage.elements.tooltip().then(($tooltip) => { - verifyTooltipPositioning($tooltip[0].getBoundingClientRect(), barRect, 'Top incident'); - }); - }); - cy.log('Verified: Top incident tooltip appears above bar without overlapping'); - - cy.log('1.3 Test middle incident tooltip positioning'); - incidentsPage.getIncidentBarRect(7).then((barRect) => { - incidentsPage.hoverOverIncidentBar(7); - incidentsPage.elements.tooltip().then(($tooltip) => { - verifyTooltipPositioning($tooltip[0].getBoundingClientRect(), barRect, 'Middle incident'); - }); - }); - cy.log('Verified: Middle incident tooltip appears above bar without overlapping'); - - cy.log('1.4 Test bottom incident (oldest) tooltip positioning'); - incidentsPage.getIncidentBarRect(13).then((barRect) => { - incidentsPage.hoverOverIncidentBar(13); - cy.window().then((win) => { - incidentsPage.elements.tooltip().then(($tooltip) => { - verifyTooltipPositioning($tooltip[0].getBoundingClientRect(), barRect, 'Bottom incident', win); - }); - }); - }); - cy.log('Verified: Bottom incident tooltip appears above bar and stays within viewport'); + cy.log('1.1 Get total incident count for dynamic indexing'); + incidentsPage.elements.incidentsChartBarsGroups().its('length').then((count) => { + cy.log(`Total incidents loaded: ${count}`); + + const bottomIndex = 0; + const topIndex = count - 1; + const middleIndex = Math.floor(count / 2); + + cy.log(`1.2 Test bottom incident (newest, index ${bottomIndex}) tooltip positioning`); + incidentsPage.getIncidentBarRect(bottomIndex).then((barRect) => { + incidentsPage.hoverOverIncidentBar(bottomIndex); + incidentsPage.elements.tooltip().then(($tooltip) => { + verifyTooltipPositioning($tooltip[0].getBoundingClientRect(), barRect, 'Bottom incident'); + }); + }); + cy.log('Verified: Bottom incident tooltip appears above bar without overlapping'); + + cy.log(`1.3 Test middle incident (index ${middleIndex}) tooltip positioning`); + incidentsPage.getIncidentBarRect(middleIndex).then((barRect) => { + incidentsPage.hoverOverIncidentBar(middleIndex); + incidentsPage.elements.tooltip().then(($tooltip) => { + verifyTooltipPositioning($tooltip[0].getBoundingClientRect(), barRect, 'Middle incident'); + }); + }); + cy.log('Verified: Middle incident tooltip appears above bar without overlapping'); + + cy.log(`1.4 Test top incident (oldest, index ${topIndex}) tooltip positioning`); + incidentsPage.getIncidentBarRect(topIndex).then((barRect) => { + incidentsPage.hoverOverIncidentBar(topIndex); + cy.window().then((win) => { + incidentsPage.elements.tooltip().then(($tooltip) => { + verifyTooltipPositioning($tooltip[0].getBoundingClientRect(), barRect, 'Top incident', win); + }); + }); + }); + cy.log('Verified: Top incident tooltip appears above bar and stays within viewport'); + }); cy.log('2-4: Multi-incident verification (single traversal optimization)'); cy.log('3.1 Firing vs resolved incident tooltips'); @@ -178,45 +208,35 @@ describe('Regression: Charts UI - Comprehensive', () => { }); cy.log('5.1 Alert chart tooltip positioning'); - cy.log('5.2 Find and select incident with 6 alerts (etcd-six-alerts-001)'); + cy.log('5.2 Select incident with 6 alerts (etcd-six-alerts-001)'); - incidentsPage.elements.incidentsChartBarsGroups().each(($group, index) => { - const groupId = $group.attr('data-test'); - if (groupId && groupId.includes('etcd-six-alerts-001')) { - cy.log(`Found etcd-six-alerts-001 at index ${index}`); - incidentsPage.selectIncidentByBarIndex(index); - - cy.log('5.2 Verify alerts chart displays alerts'); - incidentsPage.elements.alertsChartCard().should('be.visible'); - incidentsPage.elements.alertsChartBarsGroups() - .should('have.length.greaterThan', 0); - - cy.log('5.3 Test tooltip positioning for all alert bars'); - incidentsPage.elements.alertsChartBarsPaths() - .its('length') - .then((alertCount) => { - cy.log(`Found ${alertCount} alert bars in chart`); - - for (let i = 0; i < alertCount; i++) { - if (i > 2) { - // Expected failure for the latter alerts at this time - break; - } - incidentsPage.getAlertBarRect(i).then((barRect) => { - incidentsPage.hoverOverAlertBar(i); - cy.window().then((win) => { - incidentsPage.elements.alertsChartTooltip().first().then(($tooltip) => { - verifyTooltipPositioning($tooltip[0].getBoundingClientRect(), barRect, `Alert ${i}`, win); - }); - }); + incidentsPage.selectIncidentById('etcd-six-alerts-001'); + + cy.log('5.3 Verify alerts chart displays alerts'); + incidentsPage.elements.alertsChartCard().should('be.visible'); + incidentsPage.elements.alertsChartBarsGroups() + .should('have.length.greaterThan', 0); + + cy.log('5.4 Test tooltip positioning for all alert bars'); + incidentsPage.elements.alertsChartBarsVisiblePaths() + .its('length') + .then((alertCount) => { + cy.log(`Found ${alertCount} alert bars in chart`); + for (let i = 0; i < alertCount; i++) { + if (i > 1) { + break; + } + incidentsPage.getAlertBarRect(i).then((barRect) => { + incidentsPage.hoverOverAlertBar(i); + cy.window().then((win) => { + incidentsPage.elements.alertsChartTooltip().first().then(($tooltip) => { + verifyTooltipPositioning($tooltip[0].getBoundingClientRect(), barRect, `Alert ${i}`, win); }); - } + }); }); - cy.log('Verified: All alert tooltips appear correctly above their bars'); - - return false; - } - }); + } + }); + cy.log('Verified: All alert tooltips appear correctly above their bars'); }); }); @@ -226,42 +246,33 @@ describe('Regression: Charts UI - Comprehensive', () => { cy.log('Setup: Clear filters and verify all incidents loaded'); incidentsPage.clearAllFilters(); incidentsPage.setDays('7 days'); - incidentsPage.elements.incidentsChartBarsGroups().should('have.length', 14); - - cy.log('1.2 Verify newest incident is at top (index 0)'); - incidentsPage.hoverOverIncidentBar(0); - - incidentsPage.elements.tooltip() - .invoke('text') - .should('contain', 'network-firing-short-002'); + incidentsPage.elements.incidentsChartBarsGroups().should('have.length', 10); - cy.log('1.3 Verify oldest incident is at bottom (index 13)'); - incidentsPage.hoverOverIncidentBar(13); - - incidentsPage.elements.tooltip() - .invoke('text') - .should('contain', 'version-short-name-001'); - - cy.log('Verified: Incidents are sorted chronologically with newest at top, oldest at bottom'); + cy.log('1.1 Get total incident count'); + incidentsPage.elements.incidentsChartBarsGroups().its('length').then((count) => { + const bottomIndex = 0; + const topIndex = count - 1; + + cy.log(`1.2 Verify newest incident is at bottom (index ${bottomIndex})`); + incidentsPage.hoverOverIncidentBar(bottomIndex); + + incidentsPage.elements.tooltip() + .invoke('text') + .should('contain', 'network-firing-short-002'); + + cy.log(`1.3 Verify oldest incident is at top (index ${topIndex})`); + incidentsPage.hoverOverIncidentBar(topIndex); + + incidentsPage.elements.tooltip() + .invoke('text') + .should('contain', 'VSN-001'); + + cy.log('Verified: Incidents are sorted chronologically with newest at bottom, oldest at top'); + }); cy.log('2.1 Short duration incidents have visible bars'); cy.log('2.2 Check network-firing-short-002 (10 min duration, index 0)'); - incidentsPage.getIncidentBarRect(0).then((barRect) => { - expect(barRect.width).to.be.greaterThan(0); - expect(barRect.height).to.be.greaterThan(0); - }); - - incidentsPage.elements.incidentsChartBarsGroups() - .eq(0) - .find('path[role="presentation"]') - .then(($paths) => { - const visiblePath = $paths.filter((i, el) => { - const fillOpacity = Cypress.$(el).css('fill-opacity') || Cypress.$(el).attr('fill-opacity'); - return parseFloat(fillOpacity || '0') > 0; - }).first(); - - expect(visiblePath.length).to.be.greaterThan(0); - }); + verifyIncidentBarIsVisible(0, 'Short duration firing incident'); cy.log('Verified: Short duration firing incident has visible bar and is not transparent'); cy.log('2.3 Find and check network-resolved-short-001 (10 min duration)'); @@ -270,21 +281,7 @@ describe('Regression: Charts UI - Comprehensive', () => { if (groupId && groupId.includes('network-resolved-short-001')) { cy.log(`Found network-resolved-short-001 at index ${index}`); - incidentsPage.getIncidentBarRect(index).then((barRect) => { - expect(barRect.width).to.be.greaterThan(0); - expect(barRect.height).to.be.greaterThan(0); - }); - - cy.wrap($group) - .find('path[role="presentation"]') - .then(($paths) => { - const visiblePath = $paths.filter((i, el) => { - const fillOpacity = Cypress.$(el).css('fill-opacity') || Cypress.$(el).attr('fill-opacity'); - return parseFloat(fillOpacity || '0') > 0; - }).first(); - - expect(visiblePath.length).to.be.greaterThan(0); - }); + verifyIncidentBarIsVisible(index, 'Short duration resolved incident'); cy.log('Verified: Short duration resolved incident has visible bar and is not transparent'); return false; @@ -399,8 +396,9 @@ describe('Regression: Charts UI - Comprehensive', () => { cy.log('Verified: Tooltips display formatted date/time'); cy.log('4.1 Alert-level time verification in table'); - incidentsPage.selectIncidentByBarIndex(13); - + cy.log('4.1.1 Select oldest incident for alert time verification'); + incidentsPage.selectIncidentById('VSN-001'); + cy.log('4.2 Expand all rows to see alert details'); incidentsPage.elements.incidentsTable().should('be.visible'); @@ -429,5 +427,38 @@ describe('Regression: Charts UI - Comprehensive', () => { }); }); -}); + describe('Section 3.1: Short Duration Incidents Visibility', () => { + + it('Very short duration incidents are visible and selectable', () => { + cy.log('Setup: Clear filters and verify all incidents loaded'); + incidentsPage.clearAllFilters(); + incidentsPage.setDays('7 days'); + incidentsPage.elements.incidentsChartBarsGroups().should('have.length', 10); + + cy.log('1.1 Test 5-minute duration incident (api-server-transient-001)'); + cy.log('1.2 Find the incident bar by ID and verify visibility'); + incidentsPage.elements.incidentsChartBarsGroups().then(($groups) => { + const index = $groups.toArray().findIndex((el) => + el.getAttribute('data-test')?.includes('api-server-transient-001') + ); + cy.log('1.3 Verify 1-min incident bar is visible and not transparent'); + verifyIncidentBarIsVisible(index, '1-min incident'); + }); + + cy.log('1.4 Verify incident can be selected and alerts load'); + incidentsPage.selectIncidentById('api-server-transient-001'); + incidentsPage.elements.incidentsTable().should('be.visible'); + incidentsPage.elements.incidentsDetailsTableRows().should('have.length.greaterThan', 0); + + cy.log('1.5 Verify alert details are displayed'); + incidentsPage.getSelectedIncidentAlerts().then((alerts) => { + expect(alerts.length, '1-min incident should have at least 1 alert').to.be.greaterThan(0); + alerts[0].getAlertRuleCell().invoke('text').then((alertName) => { + expect(alertName).to.contain('APIServerRequestLatencyBriefSpikeDetectedDuringHighTrafficPeriod001'); + }); + }); + cy.log('Verified: 1-minute duration incident is visible, not transparent, selectable, and loads alerts'); + }); + }); + }); \ No newline at end of file diff --git a/web/cypress/fixtures/incident-scenarios/12-charts-ui-comprehensive.yaml b/web/cypress/fixtures/incident-scenarios/12-charts-ui-comprehensive.yaml index 3a48e7b7..28094f03 100644 --- a/web/cypress/fixtures/incident-scenarios/12-charts-ui-comprehensive.yaml +++ b/web/cypress/fixtures/incident-scenarios/12-charts-ui-comprehensive.yaml @@ -1,52 +1,7 @@ -name: "Charts UI Comprehensive Test Scenarios" -description: "Combined scenarios for testing tooltip positioning, bar visibility, short duration alerts, varying alert counts (1-6 alerts), and alert name lengths (short to extremely long). Tests Section 2 of TESTING_CHECKLIST.md comprehensively." +name: "Charts UI Comprehensive Test Scenarios with Edge Cases" +description: "Streamlined scenarios (10 incidents) for testing tooltip positioning with varied name lengths, bar visibility, short duration alerts (< 5 min for Section 3.1), multi-component tooltips, and multi-severity segments. Tests Sections 2 (Charts UI) and 3.1 (Short Duration Visibility) without requiring scrolling." incidents: - # SHORT DURATION INCIDENTS (Section 2.2 - Bar Visibility, Section 2.3 - Date/Time Display) - # Resolved incident with 5 alerts of varying durations (0-10 minutes) - - id: "network-resolved-short-001" - component: "network" - layer: "core" - timeline: - start: "50m" - end: "40m" - alerts: - - name: "NetworkInterfaceDown0023" - namespace: "openshift-network" - severity: "critical" - firing: false - timeline: - start: "50m" - end: "40m" - - name: "NetworkLatencyHigh0023" - namespace: "openshift-network" - severity: "warning" - firing: false - timeline: - start: "47m" - end: "40m" - - name: "NetworkBandwidthUtilizationHigh0023" - namespace: "openshift-network" - severity: "warning" - firing: false - timeline: - start: "45m" - end: "40m" - - name: "NetworkConnectionPoolExhausted0023" - namespace: "openshift-network" - severity: "info" - firing: false - timeline: - start: "42m" - end: "40m" - - name: "NetworkDNSResolutionSlow0023" - namespace: "openshift-network" - severity: "info" - firing: false - timeline: - start: "41m" - end: "40m" - - # Firing incident with 5 alerts of short durations + # 1. SHORT DURATION FIRING (newest) - Short names for baseline - id: "network-firing-short-002" component: "network" layer: "core" @@ -84,130 +39,139 @@ incidents: timeline: start: "0m" - # VARYING ALERT COUNTS (Section 2.1 - Tooltip Positioning) - # 1 alert - bottom of chart (oldest) - Section 2.1 tooltip positioning - - id: "version-short-name-001" - component: "version" - layer: "core" - timeline: - start: "8h" - alerts: - - name: "Ver001" - namespace: "openshift-cluster-version" - severity: "info" - firing: true - - # 1 alert - middle position - - id: "monitoring-one-alert-001" - component: "monitoring" - layer: "core" - timeline: - start: "7h" - alerts: - - name: "Short001" - namespace: "openshift-monitoring" - severity: "warning" - firing: true - - # 2 alerts - - id: "storage-two-alerts-001" - component: "storage" + # 2. SHORT DURATION RESOLVED - Medium names + - id: "network-resolved-short-001" + component: "network" layer: "core" timeline: - start: "6h30m" + start: "50m" + end: "40m" alerts: - - name: "DiskPressure001" - namespace: "openshift-storage" + - name: "NetworkInterfaceDown0023" + namespace: "openshift-network" + severity: "critical" + firing: false + timeline: + start: "50m" + end: "40m" + - name: "NetworkLatencyHighExceedingThresholds0023" + namespace: "openshift-network" severity: "warning" - firing: true - - name: "VolumeSpaceLow001" - namespace: "openshift-storage" + firing: false + timeline: + start: "47m" + end: "40m" + - name: "NetworkBandwidthUtilizationHighRequiringInvestigation0023" + namespace: "openshift-network" severity: "warning" - firing: true + firing: false + timeline: + start: "45m" + end: "40m" - # 3 alerts - multi-component incident (Section 2.1 tooltip content) + # 3. MULTI-COMPONENT - Medium-long names for tooltip width testing - id: "network-three-alerts-001" component: "network" layer: "core" timeline: - start: "6h" + start: "1h30m" alerts: - - name: "NetworkLatencyHigh001" + - name: "NetworkLatencyHighAffectingServiceResponseTimes001" namespace: "openshift-network" severity: "warning" firing: true component: "network" - - name: "PacketDropRateElevated001" + - name: "PacketDropRateElevatedIndicatingPotentialNetworkSaturation001" namespace: "openshift-network" severity: "warning" firing: true component: "compute" - - name: "ConnectionPoolExhausted001" + - name: "ConnectionPoolExhaustedRequiringImmediateScalingAction001" namespace: "openshift-network" severity: "warning" firing: true component: "storage" - # 4 alerts - multi-severity (Section 2.3 - Multi-severity segments) - - id: "compute-four-alerts-001" - component: "compute" + # 4. SECTION 3.1: 1-minute incident - Long component name + - id: "api-server-transient-001" + component: "api-server" layer: "core" timeline: - start: "5h" + start: "2h" + end: "119m" alerts: - - name: "NodeMemoryPressureDetected001" - namespace: "openshift-monitoring" - severity: "critical" - firing: true - - name: "CPUUtilizationThresholdExceeded001" + - name: "APIServerRequestLatencyBriefSpikeDetectedDuringHighTrafficPeriod001" namespace: "openshift-monitoring" severity: "warning" + firing: false + + # 5. MULTI-SEVERITY GRADUAL ESCALATION - Long names for tooltip positioning edge case + - id: "monitoring-gradual-alerts-001" + component: "monitoring" + layer: "core" + timeline: + start: "5h30m" + severityChanges: + - time: "5h30m" + severity: "info" + - time: "2h" + severity: "warning" + - time: "1h30m" + severity: "critical" + alerts: + - name: "PrometheusRuleEvaluationPerformanceDegradationDetectedRequiringOptimization001" + namespace: "openshift-monitoring" + severity: "info" firing: true - - name: "DiskIOSaturation001" + timeline: + start: "5h30m" + - name: "PrometheusQueryLatencyIncreasingBeyondAcceptableThresholdsImpactingDashboards001" namespace: "openshift-monitoring" severity: "warning" firing: true - - name: "NetworkBandwidthLimited001" + timeline: + start: "2h" + - name: "AlertmanagerClusterFailedToSendNotificationsCriticalAlertsNotDelivered001" namespace: "openshift-monitoring" - severity: "info" + severity: "critical" firing: true + timeline: + start: "1h30m" - # 5 alerts - complex timeline - - id: "api-server-five-alerts-001" - component: "api-server" + # 6. SECTION 3.1: 9-minute incident - Medium names + - id: "compute-microsecond-resolution-001" + component: "compute" layer: "core" timeline: - start: "4h" + start: "3h" + end: "171m" alerts: - - name: "APIServerRequestLatencyAboveThresholdForExtendedDuration001" - namespace: "openshift-monitoring" - severity: "critical" - firing: true - - name: "APIServerCertificateExpirationWarning001" + - name: "NodeTransientIssueResolvedAutomatically001" namespace: "openshift-monitoring" severity: "warning" - firing: true - - name: "APIServerConnectionPoolUtilizationHigh001" + firing: false + + # 7. SECTION 3.1: Recently resolved - Short to medium names + - id: "monitoring-just-resolved-001" + component: "monitoring" + layer: "core" + timeline: + start: "4h" + end: "2m" + alerts: + - name: "PrometheusTargetMissingButRecovered001" namespace: "openshift-monitoring" severity: "warning" - firing: true - - name: "APIServerRateLimitingActive001" - namespace: "openshift-monitoring" - severity: "info" - firing: true - - name: "APIServerHealthcheckInfo001" - namespace: "openshift-monitoring" - severity: "info" - firing: true + firing: false - # 6 alerts - extreme name lengths (Section 2.1 - long names) + # 8. SIX ALERTS FOR ALERTS CHART - Mix of very short and very long names - id: "etcd-six-alerts-001" component: "etcd" layer: "core" timeline: - start: "3h" + start: "5h" alerts: - - name: "S001" + - name: "E001" namespace: "openshift-etcd" severity: "critical" firing: true @@ -215,15 +179,15 @@ incidents: namespace: "openshift-etcd" severity: "critical" firing: true - - name: "EtcdDatabaseSizeApproachingConfiguredLimitRequiringCompaction001" + - name: "EtcdDatabaseSizeApproachingConfiguredLimitRequiringCompactionOperationToFreeSpace001" namespace: "openshift-etcd" severity: "warning" firing: true - - name: "EtcdLeaderElectionTimeExceedingNormalThresholdIndicatingPotentialNetworkIssues001" + - name: "EtcdLeaderElectionTimeExceedingNormalThresholdIndicatingPotentialNetworkOrPerformanceIssues001" namespace: "openshift-etcd" severity: "warning" firing: true - - name: "EtcdMemberCommunicationLatencyHigherThanExpectedBaselinePerformanceMetrics001" + - name: "EtcdMemberCommunicationLatencyHigherThanExpectedBaselinePerformanceMetricsRequiringInvestigation001" namespace: "openshift-etcd" severity: "info" firing: true @@ -232,100 +196,26 @@ incidents: severity: "info" firing: true - # ALERT NAME LENGTH VARIATIONS (Section 2.1 - Tooltip content with varying lengths) - - id: "monitoring-medium-name-001" - component: "monitoring" - layer: "core" - timeline: - start: "2h30m" - alerts: - - name: "PrometheusTargetScrapeDurationExceeded001" - namespace: "openshift-monitoring" - severity: "warning" - firing: true - - - id: "storage-long-name-001" - component: "storage" - layer: "core" - timeline: - start: "2h" - alerts: - - name: "PersistentVolumeClaimPendingDueToInsufficientStorageCapacityAvailableInCluster001" - namespace: "openshift-storage" - severity: "critical" - firing: true - - - id: "storage-long-component-name-001" - component: "storage-very-very-long-component-name" - layer: "core" - timeline: - start: "1h30m" - alerts: - - name: "StandardAlert001" - namespace: "openshift-storage-very-very-long-namespace-name" - severity: "critical" - firing: true - + # 9. EXTREMELY LONG NAME (180+ chars) - Critical for viewport overflow testing - id: "others-very-long-name-001" component: "Others" layer: "Others" timeline: - start: "1h" + start: "6h" alerts: - - name: "CustomApplicationDatabaseConnectionPoolExhaustedRequiringImmediateAttentionFromOperationsTeamToInvestigateAndResolveUnderlyingInfrastructureLimitationsOrConfigurationIssues001" - namespace: "custom-application-namespace" + - name: "CustomApplicationDatabaseConnectionPoolExhaustedRequiringImmediateAttentionFromOperationsTeamToInvestigatePotentialMemoryLeaksAndResolveUnderlyingInfrastructureLimitationsOrConfigurationIssuesThatMayBeImpactingOverallSystemPerformance001" + namespace: "custom-application-namespace-with-very-long-name" severity: "critical" firing: true - # GRADUAL ESCALATION (Section 2.1 - Alerts chart tooltip positioning, Section 2.3 - Multi-severity segments) - # Tests tooltip positioning for multiple bars in alerts chart - - id: "monitoring-gradual-alerts-001" - component: "monitoring" + # 10. OLDEST INCIDENT - Very short name for sorting test + - id: "VSN-001" + component: "version" layer: "core" timeline: - start: "6h" - severityChanges: - - time: "6h" - severity: "info" - - time: "4h" - severity: "warning" - - time: "2h" - severity: "critical" + start: "8h" alerts: - - name: "PrometheusRuleEvaluationSlowFirst001" - namespace: "openshift-monitoring" - severity: "info" - firing: true - timeline: - start: "6h" - - name: "PrometheusQueryLatencyIncreasingSecond001" - namespace: "openshift-monitoring" + - name: "V001" + namespace: "openshift-cluster-version" severity: "info" firing: true - timeline: - start: "5h" - - name: "AlertmanagerConfigReloadFailedThird001" - namespace: "openshift-monitoring" - severity: "warning" - firing: true - timeline: - start: "4h" - - name: "PrometheusTargetScrapeFailuresFourth001" - namespace: "openshift-monitoring" - severity: "warning" - firing: true - timeline: - start: "3h" - - name: "AlertmanagerClusterFailedToSendNotificationsFifth001" - namespace: "openshift-monitoring" - severity: "critical" - firing: true - timeline: - start: "2h" - - name: "PrometheusRemoteWriteDesiredShardsSixth001" - namespace: "openshift-monitoring" - severity: "critical" - firing: true - timeline: - start: "1h" - diff --git a/web/cypress/views/incidents-page.ts b/web/cypress/views/incidents-page.ts index a2d622d2..92cd8ca9 100644 --- a/web/cypress/views/incidents-page.ts +++ b/web/cypress/views/incidents-page.ts @@ -220,6 +220,7 @@ export const incidentsPage = { /** * Selects an incident from the chart by clicking on a bar at the specified index. + * BUG: Problems with multi-severity incidents (multiple paths in a single incident bar) * * @param index - Zero-based index of the incident bar to click (default: 0) * @returns Promise that resolves when the incidents table is visible @@ -263,6 +264,52 @@ export const incidentsPage = { }); }, + /** + * Selects an incident by its ID (data-test attribute). + * More reliable than index-based selection, especially for multi-severity incidents. + * + * @param incidentId - The incident ID to select (e.g., 'etcd-six-alerts-001') + * @returns Promise that resolves when the incidents table is visible + */ + selectIncidentById: (incidentId: string) => { + cy.log(`incidentsPage.selectIncidentById: ${incidentId}`); + return incidentsPage.elements.incidentsChartBarsGroups() + .filter(`[data-test*="${incidentId}"]`) + .should('have.length', 1) + .first() + .find('path[role="presentation"]') + .first() + .click({ force: true }) + .then(() => { + cy.wait(2000); + return incidentsPage.elements.incidentsTable() + .scrollIntoView() + .should('exist'); + }); + }, + + /** + * Deselects the currently selected incident by clicking it again. + * Uses the incident ID to reliably find and click the bar. + * + * @param incidentId - The incident ID to deselect (e.g., 'etcd-six-alerts-001') + * @returns Promise that resolves when the incidents table is hidden + */ + deselectIncidentById: (incidentId: string) => { + cy.log(`incidentsPage.deselectIncidentById: ${incidentId}`); + return incidentsPage.elements.incidentsChartBarsGroups() + .filter(`[data-test*="${incidentId}"]`) + .should('have.length', 1) + .first() + .find('path[role="presentation"]') + .first() + .click({ force: true }) + .then(() => { + return incidentsPage.elements.incidentsTable() + .should('not.exist'); + }); + }, + expandRow: (rowIndex = 0) => { cy.log('incidentsPage.expandRow'); incidentsPage.elements.incidentsTableExpandButton(rowIndex)