Skip to content

Commit 01fa17f

Browse files
authored
Merge pull request #545 from DavidRajnoha/incident-new-ui-and-data-test-selectors
OBSINTA-795: Data Test Selectors for Incidents Page
2 parents ac52458 + f613f4b commit 01fa17f

File tree

15 files changed

+830
-330
lines changed

15 files changed

+830
-330
lines changed

web/cypress/e2e/incidents/00.coo_incidents_e2e.cy.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,24 @@ describe('BVT: Incidents - e2e', () => {
3939
it('1. Admin perspective - Incidents page - Incident with custom alert lifecycle', () => {
4040
cy.log('1.1 Navigate to Incidents page and clear filters');
4141
incidentsPage.goTo();
42-
commonPages.titleShouldHaveText('Incidents');
4342
incidentsPage.clearAllFilters();
4443

4544
const intervalMs = 60_000;
4645
const maxMinutes = 30;
4746

4847
cy.log('1.2 Wait for incident with custom alert to appear');
49-
cy.waitUntilWithCustomTimeout(
48+
cy.waitUntil(
5049
() => incidentsPage.findIncidentWithAlert(currentAlertName),
5150
{
5251
interval: intervalMs,
5352
timeout: maxMinutes * intervalMs,
54-
timeoutMessage: `Custom timeout: Incident with alert "${currentAlertName}" did not appear within ${maxMinutes} minutes.`
5553
}
5654
);
5755

5856
cy.log('1.3 Verify custom alert appears in alerts table');
5957
incidentsPage
6058
.elements
61-
.alertsTable()
59+
.incidentsTable()
6260
.contains(currentAlertName)
6361
.should('exist');
6462
});

web/cypress/e2e/incidents/01.incidents.cy.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ describe('BVT: Incidents - UI', () => {
4040
beforeEach(() => {
4141
cy.log('Navigate to Observe → Incidents');
4242
incidentsPage.goTo();
43-
commonPages.titleShouldHaveText('Incidents');
4443
});
4544

4645
it('1. Admin perspective - Incidents page - Toolbar and charts toggle functionality', () => {
@@ -59,18 +58,18 @@ describe('BVT: Incidents - UI', () => {
5958
cy.log('2.1 Set days filter to 3 days');
6059
incidentsPage.setDays('3 days');
6160

62-
cy.log('2.2 Verify filter and URL update');
63-
incidentsPage.elements.daysSelect().should('contain.text', '3 days');
64-
cy.url().should('match', /[?&]days=3\+days/);
61+
cy.log('2.2 Verify filter selection is updated');
62+
incidentsPage.elements.daysSelectToggle().should('contain.text', '3 days');
6563
});
6664

6765
it('3. Admin perspective - Incidents page - Critical filter functionality', () => {
6866
cy.log('3.1 Clear filters and toggle Critical filter');
6967
incidentsPage.clearAllFilters();
7068
incidentsPage.toggleFilter('Critical');
71-
72-
cy.log('3.2 Verify URL is updated with incident filters');
73-
cy.url().should('match', /incidentFilters=.*Critical/);
69+
// Visibility verification of the filter chip is too complex. The functionality will be
70+
// better verified in the filtering specific test.
71+
cy.log('3.2 Verify filter can be removed');
72+
incidentsPage.removeFilter('Severity', 'Critical');
7473
});
7574

7675
it('4. Admin perspective - Incidents page - Charts and alerts empty state', () => {
@@ -84,17 +83,17 @@ describe('BVT: Incidents - UI', () => {
8483
incidentsPage.elements.alertsChartEmptyState().should('exist');
8584
});
8685

87-
it('5. Admin perspective - Incidents page - Incident selection and alert details', () => {
88-
cy.mockIncidentFixture('incident-scenarios/1-single-incident-firing-critical-and-warning-alerts.yaml');
89-
90-
cy.log('5.1 Select incident and verify alert details');
86+
it('5. Admin perspective - Incidents page - Traverse Incident Table', () => {
87+
cy.log('5.1 Traverse incident table');
9188
incidentsPage.clearAllFilters();
92-
incidentsPage.selectIncidentByBarIndex(0);
93-
cy.url().should('match', /[?&]groupId=/);
94-
incidentsPage.elements.alertsChartSvg().find('path').should('exist');
9589

96-
cy.log('5.2 Verify alerts table and expand first row');
97-
incidentsPage.elements.alertsTable().should('exist');
98-
incidentsPage.expandRow(0);
90+
cy.log('5.2 Verify traversing incident table works when the alert is not present');
91+
cy.mockIncidentFixture('incident-scenarios/1-single-incident-firing-critical-and-warning-alerts.yaml');
92+
incidentsPage.findIncidentWithAlert('TargetAlert').should('be.false');
93+
94+
incidentsPage.clearAllFilters
95+
cy.log('5.3 Verify traversing incident table works when the alert is present');
96+
cy.mockIncidentFixture('incident-scenarios/6-multi-incident-target-alert-scenario.yaml');
97+
incidentsPage.findIncidentWithAlert('TargetAlert').should('be.true');
9998
});
10099
});

web/cypress/e2e/incidents/02.incidents-mocking-example.cy.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ describe('Incidents - Mocking Examples', () => {
3535
beforeEach(() => {
3636
cy.log('Navigate to Observe → Incidents');
3737
incidentsPage.goTo();
38-
commonPages.titleShouldHaveText('Incidents');
3938
});
4039

4140
it('1. Mock healthy cluster from fixture', () => {
@@ -48,7 +47,6 @@ describe('Incidents - Mocking Examples', () => {
4847
it('2. Mock single incident with critical and warning alerts', () => {
4948
cy.log('Setting up single incident with critical and warning alerts from fixture');
5049
cy.mockIncidentFixture('incident-scenarios/1-single-incident-firing-critical-and-warning-alerts.yaml');
51-
5250
cy.log('Single incident with mixed severity alerts should be visible');
5351
cy.pause();
5452
});
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
name: "Multi-Incident Cross-Namespace Target Alert Scenario"
2+
description: "Multiple incidents with varying components and severities. The final incident contains alerts from multiple namespaces including a TargetAlert for test query validation."
3+
incidents:
4+
- id: "storage-resolved-001"
5+
component: "storage"
6+
layer: "core"
7+
timeline:
8+
start: "6d"
9+
end: "4d"
10+
alerts:
11+
- name: "PersistentVolumeClaimPending001"
12+
namespace: "openshift-storage"
13+
severity: "critical"
14+
firing: false
15+
timeline:
16+
start: "6d"
17+
end: "4d"
18+
- name: "StorageNodeDiskSpaceLow001"
19+
namespace: "openshift-storage"
20+
severity: "warning"
21+
firing: false
22+
timeline:
23+
start: "138h"
24+
end: "102h"
25+
26+
- id: "network-mixed-severity-001"
27+
component: "network"
28+
layer: "core"
29+
timeline:
30+
start: "3d"
31+
alerts:
32+
- name: "NetworkInterfaceDown001"
33+
namespace: "openshift-network"
34+
severity: "critical"
35+
firing: true
36+
timeline:
37+
start: "3d"
38+
- name: "NetworkLatencyHigh001"
39+
namespace: "openshift-network"
40+
severity: "warning"
41+
firing: true
42+
timeline:
43+
start: "60h"
44+
- name: "NetworkBandwidthUtilizationHigh001"
45+
namespace: "openshift-network"
46+
severity: "info"
47+
firing: true
48+
timeline:
49+
start: "48h"
50+
51+
- id: "multi-namespace-target-001"
52+
component: "monitoring"
53+
layer: "core"
54+
timeline:
55+
start: "2d"
56+
alerts:
57+
- name: "AlertmanagerReceiversNotConfigured001"
58+
namespace: "openshift-monitoring"
59+
severity: "critical"
60+
firing: true
61+
timeline:
62+
start: "2d"
63+
- name: "PrometheusTargetDown001"
64+
namespace: "openshift-monitoring"
65+
severity: "warning"
66+
firing: true
67+
timeline:
68+
start: "42h"
69+
- name: "TargetAlert"
70+
namespace: "openshift-user-workload-monitoring"
71+
severity: "critical"
72+
firing: true
73+
timeline:
74+
start: "36h"
75+
- name: "KubeDeploymentReplicasMismatch001"
76+
namespace: "openshift-kube-apiserver"
77+
severity: "warning"
78+
firing: true
79+
timeline:
80+
start: "30h"
81+
- name: "EtcdMemberCommunicationSlow001"
82+
namespace: "openshift-etcd"
83+
severity: "info"
84+
firing: true
85+
timeline:
86+
start: "24h"
87+
- name: "NodeExporterDown001"
88+
namespace: "openshift-monitoring"
89+
severity: "warning"
90+
firing: true
91+
timeline:
92+
start: "18h"
93+
- name: "ApplicationHealthCheckFailing001"
94+
namespace: "test-application"
95+
severity: "critical"
96+
firing: true
97+
timeline:
98+
start: "12h"

web/cypress/support/incidents_prometheus_query_mocks/mock-generators.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ function buildTimelineValues(
9393
*/
9494
export function createIncidentMock(incidents: IncidentDefinition[], query?: string): PrometheusResult[] {
9595
const now = nowInClusterTimezone();
96-
9796
const results: PrometheusResult[] = [];
9897

9998
// Parse query to extract label selectors if provided

web/cypress/support/incidents_prometheus_query_mocks/prometheus-mocks.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ export function mockPrometheusQueryRange(incidents: IncidentDefinition[]): void
3333
}
3434

3535
results = query.includes('cluster:health:components:map') ? createIncidentMock(incidents, query) : createAlertDetailsMock(incidents, query);
36-
3736
const response: PrometheusResponse = {
3837
status: 'success',
3938
data: {
@@ -50,20 +49,21 @@ export function mockPrometheusQueryRange(incidents: IncidentDefinition[]): void
5049

5150
Cypress.Commands.add('mockIncidents', (incidents: IncidentDefinition[]) => {
5251
cy.log(`=== SETTING UP INCIDENT MOCKING (${incidents.length} incidents) ===`);
53-
if (!Array.isArray(incidents)) {
54-
throw new Error('mockIncidents expects an array of IncidentDefinition objects');
55-
}
52+
if (!Array.isArray(incidents)) {
53+
throw new Error('mockIncidents expects an array of IncidentDefinition objects');
54+
}
5655

57-
incidents.forEach((incident, index) => {
58-
if (!incident.id || !incident.component || !incident.layer || !incident.alerts) {
59-
throw new Error(`Invalid incident at index ${index}: missing required fields
60-
(id, component, layer, alerts)`);
61-
}
62-
});
56+
incidents.forEach((incident, index) => {
57+
if (!incident.id || !incident.component || !incident.layer || !incident.alerts) {
58+
throw new Error(`Invalid incident at index ${index}: missing required fields
59+
(id, component, layer, alerts)`);
60+
}
61+
});
6362

64-
cy.log(`=== SETTING UP INCIDENT MOCKING (${incidents.length} incidents) ===`);
65-
// The mocking is not applied until the page is reloaded and the components fetch the new data
66-
cy.reload();
63+
cy.log(`=== SETTING UP INCIDENT MOCKING (${incidents.length} incidents) ===`);
64+
mockPrometheusQueryRange(incidents);
65+
// The mocking is not applied until the page is reloaded and the components fetch the new data
66+
cy.reload();
6767
});
6868

6969
Cypress.Commands.add('mockIncidentFixture', (fixturePath: string) => {
@@ -83,6 +83,6 @@ Cypress.Commands.add('mockIncidentFixture', (fixturePath: string) => {
8383
}
8484

8585

86-
// The mocking is not applied until the page is reloaded and the components fetch the new data
87-
cy.reload();
86+
// The mocking is not applied until the page is reloaded and the components fetch the new data
87+
cy.reload();
8888
});

web/cypress/support/incidents_prometheus_query_mocks/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,4 @@ export function nowInClusterTimezone(): number {
6969
const timezone = Cypress.env('TIMEZONE') || 'UTC';
7070
const now = Math.floor(TZDate.tz(timezone).getTime() / 1000);
7171
return now;
72-
}
72+
}

0 commit comments

Comments
 (0)