@@ -212,8 +212,18 @@ export const incidentsPage = {
212212 } ,
213213
214214 goTo : ( ) => {
215- cy . log ( 'incidentsPage.goTo' ) ;
215+ if ( ! _quietSearch ) cy . log ( 'incidentsPage.goTo' ) ;
216216 nav . sidenav . clickNavLink ( [ 'Observe' , 'Alerting' ] ) ;
217+ // Wait for the Incidents tab to be registered by the dynamic plugin.
218+ // After session restore the plugin may need up to 2 min to re-register.
219+ cy . waitUntil (
220+ ( ) =>
221+ Cypress . $ (
222+ '.pf-v6-c-tabs__item:contains("Incidents"), ' +
223+ '.co-m-horizontal-nav__menu-item:contains("Incidents")' ,
224+ ) . length > 0 ,
225+ { interval : 2000 , timeout : 180000 } ,
226+ ) ;
217227 nav . tabs . switchTab ( 'Incidents' ) ;
218228 incidentsPage . elements . daysSelectToggle ( ) . should ( 'be.visible' ) ;
219229 } ,
@@ -399,42 +409,45 @@ export const incidentsPage = {
399409 } ,
400410
401411 /**
402- * Selects an incident from the chart by clicking on a bar at the specified index.
403- * BUG: Problems with multi-severity incidents (multiple paths in a single incident bar)
412+ * Selects an incident from the chart by clicking on a bar group at the
413+ * specified index. Uses bar groups (one per incident) instead of flattened
414+ * paths to correctly handle multi-severity incidents.
404415 *
405416 * @param index - Zero-based index of the incident bar to click (default: 0)
406417 * @returns Promise that resolves when the incidents table is visible
407418 */
408419 selectIncidentByBarIndex : ( index = 0 ) => {
409- if ( ! _quietSearch )
410- cy . log ( `incidentsPage.selectIncidentByBarIndex: ${ index } (clicking visible path elements)` ) ;
420+ if ( ! _quietSearch ) cy . log ( `incidentsPage.selectIncidentByBarIndex: ${ index } ` ) ;
411421
412422 return incidentsPage . elements
413- . incidentsChartBarsVisiblePaths ( )
423+ . incidentsChartBarsGroups ( )
414424 . should ( 'have.length.greaterThan' , index )
415- . then ( ( $paths ) => {
416- if ( index >= $paths . length ) {
417- throw new Error ( `Index ${ index } exceeds available paths (${ $paths . length } )` ) ;
418- }
419-
420- return cy . wrap ( $paths . eq ( index ) , _qLog ( ) ) . click ( { force : true , ..._qLog ( ) } ) ;
425+ . eq ( index )
426+ . find ( 'path[role="presentation"]' )
427+ . filter ( ( _ , el ) => {
428+ const opacity = Cypress . $ ( el ) . css ( 'fill-opacity' ) || Cypress . $ ( el ) . attr ( 'fill-opacity' ) ;
429+ return parseFloat ( opacity || '0' ) > 0 ;
421430 } )
431+ . first ( )
432+ . click ( { force : true , ..._qLog ( ) } )
422433 . then ( ( ) => {
423434 cy . wait ( 2000 , _qLog ( ) ) ;
424435 return incidentsPage . elements . incidentsTable ( ) . scrollIntoView ( ) . should ( 'exist' ) ;
425436 } ) ;
426437 } ,
427438
428- deselectIncidentByBar : ( ) => {
439+ deselectIncidentByBar : ( index = 0 ) => {
429440 if ( ! _quietSearch ) cy . log ( 'incidentsPage.deselectIncidentByBar' ) ;
430441 return incidentsPage . elements
431- . incidentsChartBarsVisiblePaths ( )
432- . then ( ( $paths ) => {
433- if ( $paths . length === 0 ) {
434- throw new Error ( 'No paths found in incidents chart' ) ;
435- }
436- return cy . wrap ( $paths . eq ( 0 ) , _qLog ( ) ) . click ( { force : true , ... _qLog ( ) } ) ;
442+ . incidentsChartBarsGroups ( )
443+ . eq ( index )
444+ . find ( 'path[role="presentation"]' )
445+ . filter ( ( _ , el ) => {
446+ const opacity = Cypress . $ ( el ) . css ( 'fill-opacity' ) || Cypress . $ ( el ) . attr ( 'fill-opacity' ) ;
447+ return parseFloat ( opacity || '0' ) > 0 ;
437448 } )
449+ . first ( )
450+ . click ( { force : true , ..._qLog ( ) } )
438451 . then ( ( ) => {
439452 return incidentsPage . elements . incidentsTable ( ) . should ( 'not.exist' ) ;
440453 } ) ;
@@ -653,8 +666,10 @@ export const incidentsPage = {
653666
654667 prepareIncidentsPageForSearch : ( ) => {
655668 if ( ! _quietSearch ) cy . log ( 'incidentsPage.prepareIncidentsPageForSearch: Setting up page...' ) ;
656- // Force a hard page reload to release browser DOM memory from previous search iterations.
657- cy . reload ( { log : false } ) ;
669+ // Use SPA navigation instead of cy.reload() — the Incidents component is a
670+ // dynamic plugin chunk, and cy.reload() causes the Console to re-resolve all
671+ // plugins from scratch, which silently fails in headless CI (blank page).
672+ // OOM is handled by _quietSearch suppressing DOM snapshots, not by reload.
658673 incidentsPage . goTo ( ) ;
659674 incidentsPage . setDays ( incidentsPage . SEARCH_CONFIG . DEFAULT_DAYS ) ;
660675 incidentsPage . elements . incidentsChartContainer ( ) . should ( 'be.visible' ) ;
@@ -821,7 +836,7 @@ export const incidentsPage = {
821836 if ( found ) {
822837 return cy . wrap ( true , _qLog ( ) ) ;
823838 }
824- incidentsPage . deselectIncidentByBar ( ) ;
839+ incidentsPage . deselectIncidentByBar ( currentIndex ) ;
825840 cy . wait ( 500 , _qLog ( ) ) ;
826841 return searchNextIncidentBar ( currentIndex + 1 ) ;
827842 } ) ;
@@ -859,16 +874,19 @@ export const incidentsPage = {
859874
860875 incidentsPage . prepareIncidentsPageForSearch ( ) ;
861876
862- return incidentsPage . elements
863- . incidentsChartBarsVisiblePaths ( )
864- . then ( ( $paths ) => {
865- const totalPaths = $paths . length ;
866- if ( totalPaths === 0 ) {
867- cy . log ( 'No visible incident bar paths found in chart' ) ;
877+ // Check for bar groups without asserting existence — an empty chart is
878+ // valid (e.g. when mocking empty incidents or before detection fires).
879+ return cy
880+ . get ( 'body' , _qLog ( ) )
881+ . then ( ( $body ) => {
882+ const barSelector = 'g[role="presentation"][data-test*="incidents-chart-bar-"]' ;
883+ const totalIncidents = $body . find ( barSelector ) . length ;
884+ if ( totalIncidents === 0 ) {
885+ if ( ! _quietSearch ) cy . log ( 'No incident bar groups found in chart' ) ;
868886 return cy . wrap ( false , { log : false } ) ;
869887 }
870888
871- return incidentsPage . traverseAllIncidentsBars ( alertName , totalPaths ) ;
889+ return incidentsPage . traverseAllIncidentsBars ( alertName , totalIncidents ) ;
872890 } )
873891 . then ( ( found : boolean ) => {
874892 if ( found ) {
0 commit comments