From d9064828b17310f8555e78f0607de275689119b3 Mon Sep 17 00:00:00 2001 From: David Rajnoha Date: Wed, 1 Jul 2026 11:17:23 +0200 Subject: [PATCH 1/4] fix: make Incidents tab selector case-insensitive The console changed the data-test-id from "horizontal-link-incidents" to "horizontal-link-Incidents". Use the CSS `i` flag so the selector matches both casings. Co-Authored-By: Claude Opus 4.6 (1M context) --- web/cypress/views/incidents-page.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/web/cypress/views/incidents-page.ts b/web/cypress/views/incidents-page.ts index a57db8e58..78b449ccb 100644 --- a/web/cypress/views/incidents-page.ts +++ b/web/cypress/views/incidents-page.ts @@ -17,9 +17,8 @@ const _resetSearchState = () => { _quietSearch = false; }; -// Selector for the Incidents tab rendered by the Console SDK's HorizontalNav. -// The Console assigns data-test-id="horizontal-link-" to each tab. -const _INCIDENTS_TAB_SELECTOR = '[data-test-id="horizontal-link-incidents"]'; +// Case-insensitive selector — the console has shipped both "incidents" and "Incidents". +const _INCIDENTS_TAB_SELECTOR = '[data-test-id="horizontal-link-incidents" i]'; // Selector for bar group containers in the incidents chart (one per incident). const _BAR_GROUP_SELECTOR = 'g[role="presentation"][data-test*="incidents-chart-bar-"]'; From 96b1d4653f2c60d7c39584d2848be8661e0cb95f Mon Sep 17 00:00:00 2001 From: David Rajnoha Date: Wed, 1 Jul 2026 12:45:23 +0200 Subject: [PATCH 2/4] fix(tests): use data-label selectors for incidents detail table cells The detail table component never applied the data-test IDs defined in data-test.ts. Switch to data-label attribute selectors matching the actual dataLabel props rendered by IncidentsDetailsRowTable, consistent with the regression test helpers. Co-Authored-By: Claude Opus 4.6 (1M context) --- web/cypress/views/incidents-page.ts | 44 +++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/web/cypress/views/incidents-page.ts b/web/cypress/views/incidents-page.ts index 78b449ccb..d4cb3bb5a 100644 --- a/web/cypress/views/incidents-page.ts +++ b/web/cypress/views/incidents-page.ts @@ -183,21 +183,49 @@ export const incidentsPage = { incidentsDetailsLoadingSpinner: () => cy.byTestID(DataTestIDs.IncidentsDetailsTable.LoadingSpinner), incidentsDetailsRow: (index: number) => - cy.byTestID(`${DataTestIDs.IncidentsDetailsTable.Row}-${index}`), + incidentsPage.elements.incidentsDetailsTable().find('tbody tr').eq(index), incidentsDetailsAlertRuleCell: (index: number) => - cy.byTestID(`${DataTestIDs.IncidentsDetailsTable.AlertRuleCell}-${index}`), + incidentsPage.elements + .incidentsDetailsTable() + .find('tbody tr') + .eq(index) + .find('td[data-label="expanded-details-alertname"]'), incidentsDetailsAlertRuleLink: (index: number) => - cy.byTestID(`${DataTestIDs.IncidentsDetailsTable.AlertRuleLink}-${index}`), + incidentsPage.elements + .incidentsDetailsTable() + .find('tbody tr') + .eq(index) + .find('td[data-label="expanded-details-alertname"] a'), incidentsDetailsNamespaceCell: (index: number) => - cy.byTestID(`${DataTestIDs.IncidentsDetailsTable.NamespaceCell}-${index}`), + incidentsPage.elements + .incidentsDetailsTable() + .find('tbody tr') + .eq(index) + .find('td[data-label="expanded-details-namespace"]'), incidentsDetailsSeverityCell: (index: number) => - cy.byTestID(`${DataTestIDs.IncidentsDetailsTable.SeverityCell}-${index}`), + incidentsPage.elements + .incidentsDetailsTable() + .find('tbody tr') + .eq(index) + .find('td[data-label="expanded-details-severity"]'), incidentsDetailsStateCell: (index: number) => - cy.byTestID(`${DataTestIDs.IncidentsDetailsTable.StateCell}-${index}`), + incidentsPage.elements + .incidentsDetailsTable() + .find('tbody tr') + .eq(index) + .find('td[data-label="expanded-details-alertstate"]'), incidentsDetailsStartCell: (index: number) => - cy.byTestID(`${DataTestIDs.IncidentsDetailsTable.StartCell}-${index}`), + incidentsPage.elements + .incidentsDetailsTable() + .find('tbody tr') + .eq(index) + .find('td[data-label="expanded-details-firingstart"]'), incidentsDetailsEndCell: (index: number) => - cy.byTestID(`${DataTestIDs.IncidentsDetailsTable.EndCell}-${index}`), + incidentsPage.elements + .incidentsDetailsTable() + .find('tbody tr') + .eq(index) + .find('td[data-label="expanded-details-firingend"]'), // Generic selectors for incident table rows and details table rows incidentsTableRows: () => From 0a520a21d4c5965ad450afcb809504eb4c114af1 Mon Sep 17 00:00:00 2001 From: David Rajnoha Date: Wed, 15 Jul 2026 12:37:50 +0200 Subject: [PATCH 3/4] fix(tests): harden incident filter selectors and scroll visibility Extract incident IDs from data-test attributes instead of text content to avoid description text pollution. Use container existence check instead of visibility assertion for 0-height dropdown. Add scrollIntoView and .first() to fix viewport and multi-element ambiguity issues. Co-Authored-By: Claude Opus 4.6 (1M context) --- web/cypress/e2e/incidents/01.incidents.cy.ts | 3 +-- .../regression/01.reg_filtering.cy.ts | 6 +++--- .../regression/04.reg_redux_effects.cy.ts | 12 +++++------ web/cypress/views/incidents-page.ts | 20 +++++++++++-------- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/web/cypress/e2e/incidents/01.incidents.cy.ts b/web/cypress/e2e/incidents/01.incidents.cy.ts index 0beb7108c..f3e42522b 100644 --- a/web/cypress/e2e/incidents/01.incidents.cy.ts +++ b/web/cypress/e2e/incidents/01.incidents.cy.ts @@ -95,12 +95,11 @@ describe('BVT: Incidents - UI', { tags: ['@smoke', '@incidents'] }, () => { it('6. Admin perspective - Incidents page - Bar click selection walkthrough', () => { cy.log('6.1 Load multi-incident fixture and verify chart bars are clickable'); + incidentsPage.setDays('7 days'); cy.mockIncidentFixture( 'incident-scenarios/1-single-incident-firing-critical-and-warning-alerts.yaml', ); - incidentsPage.goTo(); incidentsPage.clearAllFilters(); - incidentsPage.setDays('7 days'); incidentsPage.elements.incidentsChartContainer().should('be.visible'); cy.log('6.2 Select incident bar and verify table appears with expected alerts'); diff --git a/web/cypress/e2e/incidents/regression/01.reg_filtering.cy.ts b/web/cypress/e2e/incidents/regression/01.reg_filtering.cy.ts index 6fe52699a..1ab92cb50 100644 --- a/web/cypress/e2e/incidents/regression/01.reg_filtering.cy.ts +++ b/web/cypress/e2e/incidents/regression/01.reg_filtering.cy.ts @@ -122,7 +122,7 @@ describe('Regression: Incidents Filtering', { tags: ['@incidents'] }, () => { cy.log('2.3 Select an incident by ID filter and verify table appears'); incidentsPage.selectIncidentIdFilter(ids[0]); - incidentsPage.elements.incidentsTable().should('be.visible'); + incidentsPage.elements.incidentsTable().scrollIntoView().should('be.visible'); incidentsPage.elements.incidentsChartBarsGroups().should('have.length', 1); cy.log('2.4 Clear the Incident ID filter and verify all incidents return'); @@ -144,10 +144,10 @@ describe('Regression: Incidents Filtering', { tags: ['@incidents'] }, () => { cy.mockIncidentFixture('incident-scenarios/7-comprehensive-filtering-test-scenarios.yaml'); incidentsPage.clearAllFilters(); incidentsPage.selectIncidentIdFilter('etcd-critical-warning-001'); - incidentsPage.elements.incidentsTable().should('be.visible'); + incidentsPage.elements.incidentsTable().scrollIntoView().should('be.visible'); incidentsPage.elements.incidentsTableComponentCell(0).should('contain.text', 'etcd'); incidentsPage.expandRow(0); - incidentsPage.elements.incidentsDetailsTable().should('be.visible'); + incidentsPage.elements.incidentsDetailsTable().scrollIntoView().should('be.visible'); incidentsPage.elements .incidentsDetailsTable() .should('contain.text', 'EtcdClusterUnavailable001'); diff --git a/web/cypress/e2e/incidents/regression/04.reg_redux_effects.cy.ts b/web/cypress/e2e/incidents/regression/04.reg_redux_effects.cy.ts index e53be9aac..b40310b2e 100644 --- a/web/cypress/e2e/incidents/regression/04.reg_redux_effects.cy.ts +++ b/web/cypress/e2e/incidents/regression/04.reg_redux_effects.cy.ts @@ -123,8 +123,8 @@ describe('Regression: Redux State Management', { tags: ['@incidents', '@incident .first() .click({ force: true }); - incidentsPage.elements.alertsChartContainer().should('be.visible'); - incidentsPage.elements.incidentIdFilterChip().should('be.visible'); + incidentsPage.elements.alertsChartContainer().first().scrollIntoView().should('be.visible'); + incidentsPage.elements.incidentIdFilterChip().first().scrollIntoView().should('be.visible'); dropdown.setup(); @@ -153,11 +153,11 @@ describe('Regression: Redux State Management', { tags: ['@incidents', '@incident incidentsPage.elements.incidentsChartBarsVisiblePathsNonEmpty().first().click({ force: true }); cy.log('3.4 Verify incident ID filter chip appears'); - incidentsPage.elements.incidentIdFilterChip().should('be.visible'); + incidentsPage.elements.incidentIdFilterChip().first().should('be.visible'); cy.log('3.5 Verify both Critical and Incident ID chips are present'); incidentsPage.elements.filterChipValue('Critical').should('be.visible'); - incidentsPage.elements.incidentIdFilterChip().should('be.visible'); + incidentsPage.elements.incidentIdFilterChip().first().should('be.visible'); cy.log( '3.6 Deselect Critical and Apply Warning filter (which does not match the critical incident)', @@ -174,7 +174,7 @@ describe('Regression: Redux State Management', { tags: ['@incidents', '@incident cy.log('3.8 Verify BOTH Warning filter and Incident ID filter are still applied'); incidentsPage.elements.filterChipValue('Warning').should('be.visible'); - incidentsPage.elements.incidentIdFilterChip().should('be.visible'); + incidentsPage.elements.incidentIdFilterChip().first().should('be.visible'); cy.log( 'SUCCESS: Incident ID filter was not removed when non-matching severity filter was added', @@ -187,7 +187,7 @@ describe('Regression: Redux State Management', { tags: ['@incidents', '@incident cy.log('3.10 With only Incident ID filter, incident should be visible again'); incidentsPage.elements.incidentsChartBarsGroups().should('have.length', 1); - incidentsPage.elements.incidentIdFilterChip().should('be.visible'); + incidentsPage.elements.incidentIdFilterChip().first().should('be.visible'); cy.log('SUCCESS: Incident reappears when conflicting filter removed'); }); }); diff --git a/web/cypress/views/incidents-page.ts b/web/cypress/views/incidents-page.ts index d4cb3bb5a..c3a3d284b 100644 --- a/web/cypress/views/incidents-page.ts +++ b/web/cypress/views/incidents-page.ts @@ -189,7 +189,8 @@ export const incidentsPage = { .incidentsDetailsTable() .find('tbody tr') .eq(index) - .find('td[data-label="expanded-details-alertname"]'), + .find('td[data-label="expanded-details-alertname"]') + .scrollIntoView(), incidentsDetailsAlertRuleLink: (index: number) => incidentsPage.elements .incidentsDetailsTable() @@ -445,18 +446,21 @@ export const incidentsPage = { incidentsPage.ensureFilterTypeSelected('Incident ID'); incidentsPage.elements.incidentIdFilterToggle().scrollIntoView().click({ force: true }); - incidentsPage.elements.incidentIdFilterList().should('be.visible'); + // Container has 0 height so .should('be.visible') fails on it. + // Empty list is valid (no incidents), so we wait for the container then read items. + // Extract IDs from data-test attributes to avoid reading text that includes descriptions. + const prefix = `${DataTestIDs.IncidentsPage.FiltersSelectOption}-incident id-`; return incidentsPage.elements .incidentIdFilterList() - .find('button[role="menuitem"] .pf-v6-c-menu__item-text') - .then(($texts) => { + .should('exist') + .then(($list) => { + const $items = $list.find(`[data-test^="${prefix}"]`); const ids: string[] = []; - $texts.each((_, el) => { - const text = Cypress.$(el).text().trim(); - if (text) ids.push(text); + $items.each((_, el) => { + const id = Cypress.$(el).attr('data-test')?.slice(prefix.length); + if (id) ids.push(id); }); - // Close the dropdown without selecting incidentsPage.elements.incidentIdFilterToggle().scrollIntoView().click({ force: true }); return cy.wrap(ids, _qLog()); }); From 94a4b279467b1cb1bc7140eb95a6bd38633cd93a Mon Sep 17 00:00:00 2001 From: David Rajnoha Date: Tue, 21 Jul 2026 15:04:33 +0200 Subject: [PATCH 4/4] fix(tests): keep incident selected after findIncidentWithAlert succeeds searchForAlertInIncidentByFilter unconditionally cleared all filters after checking each incident, including the one where the alert was found. This deselected the incident before callers could inspect its alert details, causing 80s timeouts on incidents-details-table. Only clear filters when moving to the next incident (alert not found). Co-Authored-By: Claude Opus 4.6 (1M context) --- web/cypress/views/incidents-page.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/web/cypress/views/incidents-page.ts b/web/cypress/views/incidents-page.ts index c3a3d284b..5c12b8358 100644 --- a/web/cypress/views/incidents-page.ts +++ b/web/cypress/views/incidents-page.ts @@ -946,8 +946,10 @@ export const incidentsPage = { .scrollIntoView() .then(() => incidentsPage.searchAllComponentsInIncident(alertName, 0)) .then((found: boolean) => { - incidentsPage.clearAllFilters(); - cy.wait(500, _qLog()); + if (!found) { + incidentsPage.clearAllFilters(); + cy.wait(500, _qLog()); + } return cy.wrap(found, _qLog()); }); },