11/*
2- Regression test for Charts UI bugs (Section 2 of TESTING_CHECKLIST.md)
2+ Regression test for Charts UI bugs and Data Loading bugs (Sections 2 & 3.1 of TESTING_CHECKLIST.md)
33
44This test loads comprehensive test data covering:
55- 2.1: Tooltip Positioning Issues
66- 2.2: Bar Sorting & Visibility Issues
77- 2.3: Date/Time Display Issues
8+ - 3.1: Short Duration Incidents Visibility (< 5 min)
9+
810
9- Test data: 12 incidents with 1-6 alerts each, varying durations (10m to 8h),
10- alert names (4 to 180+ chars), multi-component and multi-severity scenarios.
1111*/
1212
1313import { incidentsPage } from '../../../views/incidents-page' ;
@@ -44,6 +44,31 @@ function verifyTooltipPositioning(
4444 }
4545}
4646
47+ function verifyIncidentBarDimensions ( index : number , context : string ) {
48+ incidentsPage . getIncidentBarRect ( index ) . then ( ( barRect ) => {
49+ expect ( barRect . width , `${ context } should have visible width` ) . to . be . greaterThan ( 0 ) ;
50+ expect ( barRect . height , `${ context } should have visible height` ) . to . be . greaterThan ( 0 ) ;
51+ } ) ;
52+ }
53+
54+ function verifyIncidentBarHasVisiblePaths ( index : number , context : string ) {
55+ incidentsPage . elements . incidentsChartBarsGroups ( )
56+ . eq ( index )
57+ . find ( 'path[role="presentation"]' )
58+ . then ( ( $paths ) => {
59+ const visiblePath = $paths . filter ( ( i , el ) => {
60+ const fillOpacity = Cypress . $ ( el ) . css ( 'fill-opacity' ) || Cypress . $ ( el ) . attr ( 'fill-opacity' ) ;
61+ return parseFloat ( fillOpacity || '0' ) > 0 ;
62+ } ) . first ( ) ;
63+
64+ expect ( visiblePath . length , `${ context } should have visible path` ) . to . be . greaterThan ( 0 ) ;
65+ } ) ;
66+ }
67+
68+ function verifyIncidentBarIsVisible ( index : number , context : string ) {
69+ verifyIncidentBarDimensions ( index , context ) ;
70+ verifyIncidentBarHasVisiblePaths ( index , context ) ;
71+ }
4772const MCP = {
4873 namespace : 'openshift-cluster-observability-operator' ,
4974 packageName : 'cluster-observability-operator' ,
@@ -78,40 +103,45 @@ describe('Regression: Charts UI - Comprehensive', () => {
78103 incidentsPage . clearAllFilters ( ) ;
79104 incidentsPage . setDays ( '7 days' ) ;
80105 incidentsPage . elements . incidentsChartContainer ( ) . should ( 'be.visible' ) ;
81- incidentsPage . elements . incidentsChartBarsGroups ( ) . should ( 'have.length' , 14 ) ;
106+ incidentsPage . elements . incidentsChartBarsGroups ( ) . should ( 'have.length' , 10 ) ;
82107
83- // Chart order: Index 0 = newest (top), Index 13 = oldest (bottom)
84- // 0: network-firing-short-002 (10m)
85- // 13: version-short-name-001 (8h)
86-
87- cy . log ( '1.2 Test top incident (newest) tooltip positioning' ) ;
88- incidentsPage . getIncidentBarRect ( 0 ) . then ( ( barRect ) => {
89- incidentsPage . hoverOverIncidentBar ( 0 ) ;
90- incidentsPage . elements . tooltip ( ) . then ( ( $tooltip ) => {
91- verifyTooltipPositioning ( $tooltip [ 0 ] . getBoundingClientRect ( ) , barRect , 'Top incident' ) ;
92- } ) ;
93- } ) ;
94- cy . log ( 'Verified: Top incident tooltip appears above bar without overlapping' ) ;
95-
96- cy . log ( '1.3 Test middle incident tooltip positioning' ) ;
97- incidentsPage . getIncidentBarRect ( 7 ) . then ( ( barRect ) => {
98- incidentsPage . hoverOverIncidentBar ( 7 ) ;
99- incidentsPage . elements . tooltip ( ) . then ( ( $tooltip ) => {
100- verifyTooltipPositioning ( $tooltip [ 0 ] . getBoundingClientRect ( ) , barRect , 'Middle incident' ) ;
101- } ) ;
102- } ) ;
103- cy . log ( 'Verified: Middle incident tooltip appears above bar without overlapping' ) ;
104-
105- cy . log ( '1.4 Test bottom incident (oldest) tooltip positioning' ) ;
106- incidentsPage . getIncidentBarRect ( 13 ) . then ( ( barRect ) => {
107- incidentsPage . hoverOverIncidentBar ( 13 ) ;
108- cy . window ( ) . then ( ( win ) => {
109- incidentsPage . elements . tooltip ( ) . then ( ( $tooltip ) => {
110- verifyTooltipPositioning ( $tooltip [ 0 ] . getBoundingClientRect ( ) , barRect , 'Bottom incident' , win ) ;
111- } ) ;
112- } ) ;
113- } ) ;
114- cy . log ( 'Verified: Bottom incident tooltip appears above bar and stays within viewport' ) ;
108+ cy . log ( '1.1 Get total incident count for dynamic indexing' ) ;
109+ incidentsPage . elements . incidentsChartBarsGroups ( ) . its ( 'length' ) . then ( ( count ) => {
110+ cy . log ( `Total incidents loaded: ${ count } ` ) ;
111+
112+ const bottomIndex = 0 ;
113+ const topIndex = count - 1 ;
114+ const middleIndex = Math . floor ( count / 2 ) ;
115+
116+ cy . log ( `1.2 Test bottom incident (newest, index ${ bottomIndex } ) tooltip positioning` ) ;
117+ incidentsPage . getIncidentBarRect ( bottomIndex ) . then ( ( barRect ) => {
118+ incidentsPage . hoverOverIncidentBar ( bottomIndex ) ;
119+ incidentsPage . elements . tooltip ( ) . then ( ( $tooltip ) => {
120+ verifyTooltipPositioning ( $tooltip [ 0 ] . getBoundingClientRect ( ) , barRect , 'Bottom incident' ) ;
121+ } ) ;
122+ } ) ;
123+ cy . log ( 'Verified: Bottom incident tooltip appears above bar without overlapping' ) ;
124+
125+ cy . log ( `1.3 Test middle incident (index ${ middleIndex } ) tooltip positioning` ) ;
126+ incidentsPage . getIncidentBarRect ( middleIndex ) . then ( ( barRect ) => {
127+ incidentsPage . hoverOverIncidentBar ( middleIndex ) ;
128+ incidentsPage . elements . tooltip ( ) . then ( ( $tooltip ) => {
129+ verifyTooltipPositioning ( $tooltip [ 0 ] . getBoundingClientRect ( ) , barRect , 'Middle incident' ) ;
130+ } ) ;
131+ } ) ;
132+ cy . log ( 'Verified: Middle incident tooltip appears above bar without overlapping' ) ;
133+
134+ cy . log ( `1.4 Test top incident (oldest, index ${ topIndex } ) tooltip positioning` ) ;
135+ incidentsPage . getIncidentBarRect ( topIndex ) . then ( ( barRect ) => {
136+ incidentsPage . hoverOverIncidentBar ( topIndex ) ;
137+ cy . window ( ) . then ( ( win ) => {
138+ incidentsPage . elements . tooltip ( ) . then ( ( $tooltip ) => {
139+ verifyTooltipPositioning ( $tooltip [ 0 ] . getBoundingClientRect ( ) , barRect , 'Top incident' , win ) ;
140+ } ) ;
141+ } ) ;
142+ } ) ;
143+ cy . log ( 'Verified: Top incident tooltip appears above bar and stays within viewport' ) ;
144+ } ) ;
115145
116146 cy . log ( '2-4: Multi-incident verification (single traversal optimization)' ) ;
117147 cy . log ( '3.1 Firing vs resolved incident tooltips' ) ;
@@ -178,45 +208,35 @@ describe('Regression: Charts UI - Comprehensive', () => {
178208 } ) ;
179209
180210 cy . log ( '5.1 Alert chart tooltip positioning' ) ;
181- cy . log ( '5.2 Find and select incident with 6 alerts (etcd-six-alerts-001)' ) ;
211+ cy . log ( '5.2 Select incident with 6 alerts (etcd-six-alerts-001)' ) ;
182212
183- incidentsPage . elements . incidentsChartBarsGroups ( ) . each ( ( $group , index ) => {
184- const groupId = $group . attr ( 'data-test' ) ;
185- if ( groupId && groupId . includes ( 'etcd-six-alerts-001' ) ) {
186- cy . log ( `Found etcd-six-alerts-001 at index ${ index } ` ) ;
187- incidentsPage . selectIncidentByBarIndex ( index ) ;
188-
189- cy . log ( '5.2 Verify alerts chart displays alerts' ) ;
190- incidentsPage . elements . alertsChartCard ( ) . should ( 'be.visible' ) ;
191- incidentsPage . elements . alertsChartBarsGroups ( )
192- . should ( 'have.length.greaterThan' , 0 ) ;
193-
194- cy . log ( '5.3 Test tooltip positioning for all alert bars' ) ;
195- incidentsPage . elements . alertsChartBarsPaths ( )
196- . its ( 'length' )
197- . then ( ( alertCount ) => {
198- cy . log ( `Found ${ alertCount } alert bars in chart` ) ;
199-
200- for ( let i = 0 ; i < alertCount ; i ++ ) {
201- if ( i > 2 ) {
202- // Expected failure for the latter alerts at this time
203- break ;
204- }
205- incidentsPage . getAlertBarRect ( i ) . then ( ( barRect ) => {
206- incidentsPage . hoverOverAlertBar ( i ) ;
207- cy . window ( ) . then ( ( win ) => {
208- incidentsPage . elements . alertsChartTooltip ( ) . first ( ) . then ( ( $tooltip ) => {
209- verifyTooltipPositioning ( $tooltip [ 0 ] . getBoundingClientRect ( ) , barRect , `Alert ${ i } ` , win ) ;
210- } ) ;
211- } ) ;
213+ incidentsPage . selectIncidentById ( 'etcd-six-alerts-001' ) ;
214+
215+ cy . log ( '5.3 Verify alerts chart displays alerts' ) ;
216+ incidentsPage . elements . alertsChartCard ( ) . should ( 'be.visible' ) ;
217+ incidentsPage . elements . alertsChartBarsGroups ( )
218+ . should ( 'have.length.greaterThan' , 0 ) ;
219+
220+ cy . log ( '5.4 Test tooltip positioning for all alert bars' ) ;
221+ incidentsPage . elements . alertsChartBarsVisiblePaths ( )
222+ . its ( 'length' )
223+ . then ( ( alertCount ) => {
224+ cy . log ( `Found ${ alertCount } alert bars in chart` ) ;
225+ for ( let i = 0 ; i < alertCount ; i ++ ) {
226+ if ( i > 1 ) {
227+ break ;
228+ }
229+ incidentsPage . getAlertBarRect ( i ) . then ( ( barRect ) => {
230+ incidentsPage . hoverOverAlertBar ( i ) ;
231+ cy . window ( ) . then ( ( win ) => {
232+ incidentsPage . elements . alertsChartTooltip ( ) . first ( ) . then ( ( $tooltip ) => {
233+ verifyTooltipPositioning ( $tooltip [ 0 ] . getBoundingClientRect ( ) , barRect , `Alert ${ i } ` , win ) ;
212234 } ) ;
213- }
235+ } ) ;
214236 } ) ;
215- cy . log ( 'Verified: All alert tooltips appear correctly above their bars' ) ;
216-
217- return false ;
218- }
219- } ) ;
237+ }
238+ } ) ;
239+ cy . log ( 'Verified: All alert tooltips appear correctly above their bars' ) ;
220240 } ) ;
221241 } ) ;
222242
@@ -226,42 +246,33 @@ describe('Regression: Charts UI - Comprehensive', () => {
226246 cy . log ( 'Setup: Clear filters and verify all incidents loaded' ) ;
227247 incidentsPage . clearAllFilters ( ) ;
228248 incidentsPage . setDays ( '7 days' ) ;
229- incidentsPage . elements . incidentsChartBarsGroups ( ) . should ( 'have.length' , 14 ) ;
230-
231- cy . log ( '1.2 Verify newest incident is at top (index 0)' ) ;
232- incidentsPage . hoverOverIncidentBar ( 0 ) ;
233-
234- incidentsPage . elements . tooltip ( )
235- . invoke ( 'text' )
236- . should ( 'contain' , 'network-firing-short-002' ) ;
249+ incidentsPage . elements . incidentsChartBarsGroups ( ) . should ( 'have.length' , 10 ) ;
237250
238- cy . log ( '1.3 Verify oldest incident is at bottom (index 13)' ) ;
239- incidentsPage . hoverOverIncidentBar ( 13 ) ;
240-
241- incidentsPage . elements . tooltip ( )
242- . invoke ( 'text' )
243- . should ( 'contain' , 'version-short-name-001' ) ;
244-
245- cy . log ( 'Verified: Incidents are sorted chronologically with newest at top, oldest at bottom' ) ;
251+ cy . log ( '1.1 Get total incident count' ) ;
252+ incidentsPage . elements . incidentsChartBarsGroups ( ) . its ( 'length' ) . then ( ( count ) => {
253+ const bottomIndex = 0 ;
254+ const topIndex = count - 1 ;
255+
256+ cy . log ( `1.2 Verify newest incident is at bottom (index ${ bottomIndex } )` ) ;
257+ incidentsPage . hoverOverIncidentBar ( bottomIndex ) ;
258+
259+ incidentsPage . elements . tooltip ( )
260+ . invoke ( 'text' )
261+ . should ( 'contain' , 'network-firing-short-002' ) ;
262+
263+ cy . log ( `1.3 Verify oldest incident is at top (index ${ topIndex } )` ) ;
264+ incidentsPage . hoverOverIncidentBar ( topIndex ) ;
265+
266+ incidentsPage . elements . tooltip ( )
267+ . invoke ( 'text' )
268+ . should ( 'contain' , 'VSN-001' ) ;
269+
270+ cy . log ( 'Verified: Incidents are sorted chronologically with newest at bottom, oldest at top' ) ;
271+ } ) ;
246272
247273 cy . log ( '2.1 Short duration incidents have visible bars' ) ;
248274 cy . log ( '2.2 Check network-firing-short-002 (10 min duration, index 0)' ) ;
249- incidentsPage . getIncidentBarRect ( 0 ) . then ( ( barRect ) => {
250- expect ( barRect . width ) . to . be . greaterThan ( 0 ) ;
251- expect ( barRect . height ) . to . be . greaterThan ( 0 ) ;
252- } ) ;
253-
254- incidentsPage . elements . incidentsChartBarsGroups ( )
255- . eq ( 0 )
256- . find ( 'path[role="presentation"]' )
257- . then ( ( $paths ) => {
258- const visiblePath = $paths . filter ( ( i , el ) => {
259- const fillOpacity = Cypress . $ ( el ) . css ( 'fill-opacity' ) || Cypress . $ ( el ) . attr ( 'fill-opacity' ) ;
260- return parseFloat ( fillOpacity || '0' ) > 0 ;
261- } ) . first ( ) ;
262-
263- expect ( visiblePath . length ) . to . be . greaterThan ( 0 ) ;
264- } ) ;
275+ verifyIncidentBarIsVisible ( 0 , 'Short duration firing incident' ) ;
265276 cy . log ( 'Verified: Short duration firing incident has visible bar and is not transparent' ) ;
266277
267278 cy . log ( '2.3 Find and check network-resolved-short-001 (10 min duration)' ) ;
@@ -270,21 +281,7 @@ describe('Regression: Charts UI - Comprehensive', () => {
270281 if ( groupId && groupId . includes ( 'network-resolved-short-001' ) ) {
271282 cy . log ( `Found network-resolved-short-001 at index ${ index } ` ) ;
272283
273- incidentsPage . getIncidentBarRect ( index ) . then ( ( barRect ) => {
274- expect ( barRect . width ) . to . be . greaterThan ( 0 ) ;
275- expect ( barRect . height ) . to . be . greaterThan ( 0 ) ;
276- } ) ;
277-
278- cy . wrap ( $group )
279- . find ( 'path[role="presentation"]' )
280- . then ( ( $paths ) => {
281- const visiblePath = $paths . filter ( ( i , el ) => {
282- const fillOpacity = Cypress . $ ( el ) . css ( 'fill-opacity' ) || Cypress . $ ( el ) . attr ( 'fill-opacity' ) ;
283- return parseFloat ( fillOpacity || '0' ) > 0 ;
284- } ) . first ( ) ;
285-
286- expect ( visiblePath . length ) . to . be . greaterThan ( 0 ) ;
287- } ) ;
284+ verifyIncidentBarIsVisible ( index , 'Short duration resolved incident' ) ;
288285 cy . log ( 'Verified: Short duration resolved incident has visible bar and is not transparent' ) ;
289286
290287 return false ;
@@ -399,8 +396,9 @@ describe('Regression: Charts UI - Comprehensive', () => {
399396 cy . log ( 'Verified: Tooltips display formatted date/time' ) ;
400397
401398 cy . log ( '4.1 Alert-level time verification in table' ) ;
402- incidentsPage . selectIncidentByBarIndex ( 13 ) ;
403-
399+ cy . log ( '4.1.1 Select oldest incident for alert time verification' ) ;
400+ incidentsPage . selectIncidentById ( 'VSN-001' ) ;
401+
404402 cy . log ( '4.2 Expand all rows to see alert details' ) ;
405403 incidentsPage . elements . incidentsTable ( ) . should ( 'be.visible' ) ;
406404
@@ -429,5 +427,38 @@ describe('Regression: Charts UI - Comprehensive', () => {
429427 } ) ;
430428 } ) ;
431429
432- } ) ;
430+ describe ( 'Section 3.1: Short Duration Incidents Visibility' , ( ) => {
431+
432+ it ( 'Very short duration incidents are visible and selectable' , ( ) => {
433+ cy . log ( 'Setup: Clear filters and verify all incidents loaded' ) ;
434+ incidentsPage . clearAllFilters ( ) ;
435+ incidentsPage . setDays ( '7 days' ) ;
436+ incidentsPage . elements . incidentsChartBarsGroups ( ) . should ( 'have.length' , 10 ) ;
437+
438+ cy . log ( '1.1 Test 5-minute duration incident (api-server-transient-001)' ) ;
439+ cy . log ( '1.2 Find the incident bar by ID and verify visibility' ) ;
440+ incidentsPage . elements . incidentsChartBarsGroups ( ) . then ( ( $groups ) => {
441+ const index = $groups . toArray ( ) . findIndex ( ( el ) =>
442+ el . getAttribute ( 'data-test' ) ?. includes ( 'api-server-transient-001' )
443+ ) ;
444+ cy . log ( '1.3 Verify 1-min incident bar is visible and not transparent' ) ;
445+ verifyIncidentBarIsVisible ( index , '1-min incident' ) ;
446+ } ) ;
447+
448+ cy . log ( '1.4 Verify incident can be selected and alerts load' ) ;
449+ incidentsPage . selectIncidentById ( 'api-server-transient-001' ) ;
450+ incidentsPage . elements . incidentsTable ( ) . should ( 'be.visible' ) ;
451+ incidentsPage . elements . incidentsDetailsTableRows ( ) . should ( 'have.length.greaterThan' , 0 ) ;
452+
453+ cy . log ( '1.5 Verify alert details are displayed' ) ;
454+ incidentsPage . getSelectedIncidentAlerts ( ) . then ( ( alerts ) => {
455+ expect ( alerts . length , '1-min incident should have at least 1 alert' ) . to . be . greaterThan ( 0 ) ;
456+ alerts [ 0 ] . getAlertRuleCell ( ) . invoke ( 'text' ) . then ( ( alertName ) => {
457+ expect ( alertName ) . to . contain ( 'APIServerRequestLatencyBriefSpikeDetectedDuringHighTrafficPeriod001' ) ;
458+ } ) ;
459+ } ) ;
460+ cy . log ( 'Verified: 1-minute duration incident is visible, not transparent, selectable, and loads alerts' ) ;
433461
462+ } ) ;
463+ } ) ;
464+ } ) ;
0 commit comments