Skip to content

Commit 73b8366

Browse files
committed
fix(cypress): metric change workaround
cluster:health:components:map was changed to cluster_health_components_map. This commit updates the mocking to return the new metric and supports running tests in environments with old backend and new frontend. This workaround is by default disabled and will be fully removed after the COO 1.3.0 release
1 parent 01fa17f commit 73b8366

File tree

9 files changed

+114
-4
lines changed

9 files changed

+114
-4
lines changed

web/cypress.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export default defineConfig({
2222
LOGIN_USERNAME: process.env.CYPRESS_LOGIN_USERS.split(',')[0].split(':')[0],
2323
LOGIN_PASSWORD: process.env.CYPRESS_LOGIN_USERS.split(',')[0].split(':')[1],
2424
TIMEZONE: process.env.CYPRESS_TIMEZONE || 'UTC',
25+
MOCK_NEW_METRICS: process.env.CYPRESS_MOCK_NEW_METRICS || 'false',
2526
typeDelay: 200,
2627
},
2728
fixturesFolder: 'cypress/fixtures',

web/cypress/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ Set the following var to specify the cluster timezone for incident timeline calc
6767
export CYPRESS_TIMEZONE=<timezone>
6868
```
6969

70+
Set the following var to transform old metric names to new format in mocks (temporary workaround for testing against locally built instances).
71+
```bash
72+
export CYPRESS_MOCK_NEW_METRICS=false
73+
```
74+
7075
Set the following var to enable Cypress session management for faster test execution.
7176
```bash
7277
export CYPRESS_SESSION=true

web/cypress/configure-env.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ print_current_config() {
173173
print_var "CYPRESS_CUSTOM_COO_BUNDLE_IMAGE" "${CYPRESS_CUSTOM_COO_BUNDLE_IMAGE-}"
174174
print_var "CYPRESS_MCP_CONSOLE_IMAGE" "${CYPRESS_MCP_CONSOLE_IMAGE-}"
175175
print_var "CYPRESS_TIMEZONE" "${CYPRESS_TIMEZONE-}"
176+
print_var "CYPRESS_MOCK_NEW_METRICS" "${CYPRESS_MOCK_NEW_METRICS-}"
176177
print_var "CYPRESS_SESSION" "${CYPRESS_SESSION-}"
177178
print_var "CYPRESS_SKIP_KBV_INSTALL" "${CYPRESS_SKIP_KBV_INSTALL-}"
178179
print_var "CYPRESS_KBV_UI_INSTALL" "${CYPRESS_KBV_UI_INSTALL-}"
@@ -220,6 +221,7 @@ main() {
220221
local def_custom_coo_bundle=${CYPRESS_CUSTOM_COO_BUNDLE_IMAGE-}
221222
local def_mcp_console_image=${CYPRESS_MCP_CONSOLE_IMAGE-}
222223
local def_timezone=${CYPRESS_TIMEZONE-}
224+
local def_mock_new_metrics=${CYPRESS_MOCK_NEW_METRICS-}
223225
local def_session=${CYPRESS_SESSION-}
224226
local def_skip_kbv=${CYPRESS_SKIP_KBV_INSTALL-}
225227
local def_kbv_ui_install=${CYPRESS_KBV_UI_INSTALL-}
@@ -416,6 +418,11 @@ main() {
416418
local timezone
417419
timezone=$(ask "Cluster timezone (CYPRESS_TIMEZONE)" "${def_timezone:-UTC}")
418420

421+
local mock_new_metrics_ans
422+
mock_new_metrics_ans=$(ask_yes_no "Transform old metric names to new format in mocks? (sets CYPRESS_MOCK_NEW_METRICS)" "$(bool_to_default_yn "$def_mock_new_metrics")")
423+
local mock_new_metrics="false"
424+
[[ "$mock_new_metrics_ans" == "y" ]] && mock_new_metrics="true"
425+
419426
local session_ans
420427
session_ans=$(ask_yes_no "Enable Cypress session management for faster test execution? (sets CYPRESS_SESSION)" "$(bool_to_default_yn "$def_session")")
421428
local session="false"
@@ -464,6 +471,7 @@ main() {
464471
if [[ -n "$timezone" ]]; then
465472
export_lines+=("export CYPRESS_TIMEZONE='$(printf %s "$timezone" | escape_for_single_quotes)'" )
466473
fi
474+
export_lines+=("export CYPRESS_MOCK_NEW_METRICS='$(printf %s "$mock_new_metrics" | escape_for_single_quotes)'" )
467475
export_lines+=("export CYPRESS_SESSION='$(printf %s "$session" | escape_for_single_quotes)'" )
468476

469477
if [[ -n "$skip_kbv_install" ]]; then
@@ -511,6 +519,7 @@ main() {
511519
[[ -n "${CYPRESS_CUSTOM_COO_BUNDLE_IMAGE-}$custom_coo_bundle" ]] && echo " CYPRESS_CUSTOM_COO_BUNDLE_IMAGE=${CYPRESS_CUSTOM_COO_BUNDLE_IMAGE:-$custom_coo_bundle}"
512520
[[ -n "${CYPRESS_MCP_CONSOLE_IMAGE-}$mcp_console_image" ]] && echo " CYPRESS_MCP_CONSOLE_IMAGE=${CYPRESS_MCP_CONSOLE_IMAGE:-$mcp_console_image}"
513521
[[ -n "${CYPRESS_TIMEZONE-}$timezone" ]] && echo " CYPRESS_TIMEZONE=${CYPRESS_TIMEZONE:-$timezone}"
522+
echo " CYPRESS_MOCK_NEW_METRICS=${CYPRESS_MOCK_NEW_METRICS:-$mock_new_metrics}"
514523
echo " CYPRESS_SESSION=${CYPRESS_SESSION:-$session}"
515524
echo " CYPRESS_SKIP_KBV_INSTALL=${CYPRESS_SKIP_KBV_INSTALL:-$skip_kbv_install}"
516525
echo " CYPRESS_KBV_UI_INSTALL=${CYPRESS_KBV_UI_INSTALL:-$kbv_ui_install}"

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ describe('BVT: Incidents - e2e', () => {
3737
});
3838

3939
it('1. Admin perspective - Incidents page - Incident with custom alert lifecycle', () => {
40+
cy.transformMetrics();
4041
cy.log('1.1 Navigate to Incidents page and clear filters');
4142
incidentsPage.goTo();
4243
incidentsPage.clearAllFilters();

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ describe('BVT: Incidents - UI', () => {
4040
beforeEach(() => {
4141
cy.log('Navigate to Observe → Incidents');
4242
incidentsPage.goTo();
43+
// Temporary workaround for testing against locally built instances.
44+
cy.transformMetrics();
4345
});
4446

4547
it('1. Admin perspective - Incidents page - Toolbar and charts toggle functionality', () => {

web/cypress/fixtures/export.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,8 @@ export CYPRESS_MCP_CONSOLE_IMAGE=<Monitoring Console Plugin image>
3636
# Set the following var to specify the cluster timezone for incident timeline calculations. Defaults to UTC if not specified.
3737
export CYPRESS_TIMEZONE=<timezone>
3838

39+
# Set the following var to transform old metric names to new format in mocks (for testing against locally built instances)
40+
export CYPRESS_MOCK_NEW_METRICS=false
41+
3942
# Set the following var to enable Cypress session management for faster test execution.
4043
export CYPRESS_SESSION=true

web/cypress/support/incidents_prometheus_query_mocks/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,24 @@ const incidents: IncidentDefinition[] = [
4141
cy.mockIncidents(incidents);
4242
```
4343

44+
### Metric Transformation for Locally Built Instances
45+
46+
```typescript
47+
// Transform old metric names to new format (for testing against locally built instances)
48+
cy.transformMetrics();
49+
50+
// Then visit the page or perform actions that trigger Prometheus queries
51+
cy.visit('/monitoring/incidents');
52+
```
53+
4454
## Key Features
4555

4656
- **Schema Validation**: All YAML fixtures are validated against JSON Schema
4757
- **Query Filtering**: Mock data is filtered based on Prometheus query parameters
4858
- **Timeline Support**: Define incident start/end times and severity changes
4959
- **Timezone Configuration**: Set timezone via `CYPRESS_TIMEZONE` environment variable
5060
- **Multiple Query Types**: Supports both `cluster:health:components:map` and `ALERTS` queries
61+
- **Metric Transformation**: Transform old metric names to new format via `cy.transformMetrics()`
5162

5263
## File Structure
5364

@@ -104,6 +115,31 @@ export CYPRESS_TIMEZONE="Asia/Tokyo"
104115

105116
Default: UTC (if `CYPRESS_TIMEZONE` is not set)
106117

118+
### Metric Transformation
119+
120+
Enable transformation of old metric names to new format for testing against locally built instances:
121+
122+
```bash
123+
export CYPRESS_MOCK_NEW_METRICS=true
124+
```
125+
126+
When enabled, `cy.transformMetrics()` will intercept Prometheus queries and transform both request and response:
127+
- **Request**: `cluster:health:components:map``cluster_health_components_map`
128+
- **Response**: `cluster:health:components:map``cluster_health_components_map`
129+
130+
**Usage:**
131+
```typescript
132+
// Call before visiting pages that make Prometheus queries
133+
cy.transformMetrics();
134+
cy.visit('/monitoring/incidents');
135+
```
136+
137+
**Use Cases:**
138+
- **`CYPRESS_MOCK_NEW_METRICS=false`** (default): Test against current release/backend
139+
- **`CYPRESS_MOCK_NEW_METRICS=true`**: Test against locally built instances with new metric format
140+
141+
Default: `false` (if `CYPRESS_MOCK_NEW_METRICS` is not set)
142+
107143
## YAML Fixture Format
108144

109145
```yaml

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { IncidentDefinition, PrometheusResult } from './types';
33
import { severityToValue, parseQueryLabels } from './utils';
44
import { nowInClusterTimezone } from './utils';
5+
import { NEW_METRIC_NAME, OLD_METRIC_NAME } from './prometheus-mocks';
56

67
/**
78
* Generates 5-minute interval timestamps between start and end time
@@ -98,6 +99,8 @@ export function createIncidentMock(incidents: IncidentDefinition[], query?: stri
9899
// Parse query to extract label selectors if provided
99100
const queryLabels = query ? parseQueryLabels(query) : {};
100101

102+
const versioned_metric = query?.includes(NEW_METRIC_NAME) ? NEW_METRIC_NAME : OLD_METRIC_NAME;
103+
101104
incidents.forEach(incident => {
102105
// Filter incidents based on query parameters
103106
if (queryLabels.group_id) {
@@ -113,7 +116,7 @@ export function createIncidentMock(incidents: IncidentDefinition[], query?: stri
113116

114117
incident.alerts.forEach(alert => {
115118
const metric: Record<string, string> = {
116-
__name__: 'cluster:health:components:map',
119+
__name__: versioned_metric,
117120
component: incident.component,
118121
layer: incident.layer,
119122
group_id: incident.id,

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

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,40 @@ declare global {
77
interface Chainable {
88
mockIncidents(incidents: IncidentDefinition[]): Chainable<Element>;
99
mockIncidentFixture(fixturePath: string): Chainable<Element>;
10+
transformMetrics(): Chainable<Element>;
1011
}
1112
}
1213
}
1314

15+
export const NEW_METRIC_NAME = 'cluster_health_components_map';
16+
export const OLD_METRIC_NAME = 'cluster:health:components:map';
17+
const MOCK_QUERY = '/api/prometheus/api/v1/query_range*';
18+
1419
/**
1520
* Main mocking function - sets up cy.intercept for Prometheus query_range API
1621
* Intercepts the query_range API and returns the mock data for the incidents
1722
* @param incidents
1823
*/
1924
export function mockPrometheusQueryRange(incidents: IncidentDefinition[]): void {
20-
cy.intercept('GET', '/api/prometheus/api/v1/query_range*', (req) => {
25+
cy.intercept('GET', MOCK_QUERY, (req) => {
2126
const url = new URL(req.url, window.location.origin);
2227
const query = url.searchParams.get('query') || '';
2328

2429
console.log(`INTERCEPTED: ${req.method} ${req.url}`);
2530
console.log(`Query: ${query}`);
2631

2732
let results: any[];
33+
34+
const versioned_metric = query.includes(NEW_METRIC_NAME)
35+
? NEW_METRIC_NAME: OLD_METRIC_NAME;
2836

29-
if (!(query.includes('cluster:health:components:map') || query.includes('ALERTS{'))) {
37+
if (!(query.includes(versioned_metric) || query.includes('ALERTS{'))) {
3038
console.log(`Passing through non-mocked query`);
3139
req.continue();
3240
return;
3341
}
3442

35-
results = query.includes('cluster:health:components:map') ? createIncidentMock(incidents, query) : createAlertDetailsMock(incidents, query);
43+
results = query.includes(versioned_metric) ? createIncidentMock(incidents, query) : createAlertDetailsMock(incidents, query);
3644
const response: PrometheusResponse = {
3745
status: 'success',
3846
data: {
@@ -85,4 +93,46 @@ Cypress.Commands.add('mockIncidentFixture', (fixturePath: string) => {
8593

8694
// The mocking is not applied until the page is reloaded and the components fetch the new data
8795
cy.reload();
96+
});
97+
98+
Cypress.Commands.add('transformMetrics', () => {
99+
cy.log('=== SETTING UP METRIC TRANSFORMATION ===');
100+
const mockNewMetrics = Cypress.env('MOCK_NEW_METRICS') === true;
101+
102+
if (!mockNewMetrics) {
103+
cy.log('CYPRESS_MOCK_NEW_METRICS is disabled, skipping transformation');
104+
return;
105+
}
106+
107+
cy.log('Transforming old metric queries to new format');
108+
109+
cy.intercept('GET', MOCK_QUERY, (req) => {
110+
const url = new URL(req.url, window.location.origin);
111+
const query = url.searchParams.get('query') || '';
112+
const hasNewMetric = query.includes(NEW_METRIC_NAME);
113+
114+
if (hasNewMetric) {
115+
const transformedQuery = query.replace(new RegExp(NEW_METRIC_NAME, 'g'), OLD_METRIC_NAME);
116+
console.log(`Transforming metric query: ${query} -> ${transformedQuery}`);
117+
118+
// Update the URL with the transformed query
119+
url.searchParams.set('query', transformedQuery);
120+
req.url = url.toString();
121+
122+
// Also transform the response to use new metric names
123+
req.continue((res) => {
124+
if (res.body?.data?.result) {
125+
res.body.data.result.forEach((result: any) => {
126+
if (result?.metric?.__name__ === OLD_METRIC_NAME) {
127+
console.log(`Transforming response metric name: ${OLD_METRIC_NAME} -> ${NEW_METRIC_NAME}`);
128+
result.metric.__name__ = NEW_METRIC_NAME;
129+
}
130+
});
131+
}
132+
res.send();
133+
});
134+
} else {
135+
req.continue();
136+
}
137+
});
88138
});

0 commit comments

Comments
 (0)