From d2202469cd6bf8880ce770dc0a9eb2807d85489b Mon Sep 17 00:00:00 2001 From: PeterYurkovich Date: Wed, 12 Aug 2026 07:40:20 -0400 Subject: [PATCH 1/4] refactor: move test files to feature folders --- .../alerts_acm.cy.ts} | 0 .../alerts_bvt.cy.ts} | 2 +- .../alerts_ivt.cy.ts} | 25 +---- .../e2e/alerts/alerts_regression.cy.ts | 60 ++++++++++++ .../alerts_virtualization_bvt.cy.ts} | 32 ++----- web/cypress/e2e/coo/01.coo_bvt.cy.ts | 45 --------- ...01.incidents.cy.ts => incidents_bvt.cy.ts} | 0 ...ncidents_e2e.cy.ts => incidents_e2e.cy.ts} | 0 ....cy.ts => incidents_mocking_example.cy.ts} | 0 ...mark.cy.ts => performance_benchmark.cy.ts} | 0 ...gh.cy.ts => performance_walkthrough.cy.ts} | 2 +- ..._alerts.cy.ts => end_and_resolution.cy.ts} | 0 ...01.reg_filtering.cy.ts => filtering.cy.ts} | 0 ...ip_boundary_times.cy.ts => interval.cy.ts} | 0 ...ls.cy.ts => permission_and_silences.cy.ts} | 0 ..._testing_ui.cy.ts => stress_test_ui.cy.ts} | 0 ...dux_effects.cy.ts => ui_interaction.cy.ts} | 0 ...mprehensive.cy.ts => ui_regressions.cy.ts} | 0 .../legacy_dashboards_regression.cy.ts} | 10 +- ...ashboards_virtualization_regression.cy.ts} | 26 +----- .../e2e/metrics/metrics_regression.cy.ts | 91 +++++++++++++++++++ .../metrics_virtualization_ivt.cy.ts} | 64 +++++++++---- .../regression/01.reg_alerts_admin.cy.ts | 36 -------- .../regression/01.reg_alerts_dev.cy.ts | 32 ------- .../regression/02.reg_metrics_admin_1.cy.ts | 49 ---------- .../regression/02.reg_metrics_admin_2.cy.ts | 49 ---------- .../lightspeed_integration.cy.ts} | 0 .../perses_dashboards_bvt.cy.ts} | 0 .../perses_dashboards_create.cy.ts} | 0 .../perses_dashboards_datasources.cy.ts} | 0 .../perses_dashboards_edit.cy.ts} | 0 .../perses_dashboards_import.cy.ts} | 0 .../perses_dashboards_list.cy.ts} | 0 ...erses_dashboards_virtualization_ivt.cy.ts} | 33 ++----- .../rbac/perses_dashboards_user1.cy.ts} | 4 +- .../rbac/perses_dashboards_user2.cy.ts} | 6 +- .../rbac/perses_dashboards_user3.cy.ts} | 7 +- .../rbac/perses_dashboards_user4.cy.ts} | 6 +- .../rbac/perses_dashboards_user5.cy.ts} | 6 +- .../rbac/perses_dashboards_user6.cy.ts} | 6 +- .../admin_perspective_bvt.cy.ts} | 0 web/cypress/e2e/shared/coo_submenus.cy.ts | 57 ++++++++++++ 42 files changed, 301 insertions(+), 347 deletions(-) rename web/cypress/e2e/{coo/02.acm_alerting_ui.cy.ts => alerts/alerts_acm.cy.ts} (100%) rename web/cypress/e2e/{monitoring/00.bvt_dev.cy.ts => alerts/alerts_bvt.cy.ts} (90%) rename web/cypress/e2e/{virtualization/01.coo_ivt_alerts.cy.ts => alerts/alerts_ivt.cy.ts} (81%) create mode 100644 web/cypress/e2e/alerts/alerts_regression.cy.ts rename web/cypress/e2e/{virtualization/00.coo_ivt.cy.ts => alerts/alerts_virtualization_bvt.cy.ts} (72%) delete mode 100644 web/cypress/e2e/coo/01.coo_bvt.cy.ts rename web/cypress/e2e/incidents/{01.incidents.cy.ts => incidents_bvt.cy.ts} (100%) rename web/cypress/e2e/incidents/{00.coo_incidents_e2e.cy.ts => incidents_e2e.cy.ts} (100%) rename web/cypress/e2e/incidents/{02.incidents-mocking-example.cy.ts => incidents_mocking_example.cy.ts} (100%) rename web/cypress/e2e/incidents/performance/{01.performance_benchmark.cy.ts => performance_benchmark.cy.ts} (100%) rename web/cypress/e2e/incidents/performance/{02.performance_walkthrough.cy.ts => performance_walkthrough.cy.ts} (98%) rename web/cypress/e2e/incidents/regression/{03-04.reg_e2e_firing_alerts.cy.ts => end_and_resolution.cy.ts} (100%) rename web/cypress/e2e/incidents/regression/{01.reg_filtering.cy.ts => filtering.cy.ts} (100%) rename web/cypress/e2e/incidents/regression/{02.reg_ui_tooltip_boundary_times.cy.ts => interval.cy.ts} (100%) rename web/cypress/e2e/incidents/regression/{03.reg_api_calls.cy.ts => permission_and_silences.cy.ts} (100%) rename web/cypress/e2e/incidents/regression/{05.reg_stress_testing_ui.cy.ts => stress_test_ui.cy.ts} (100%) rename web/cypress/e2e/incidents/regression/{04.reg_redux_effects.cy.ts => ui_interaction.cy.ts} (100%) rename web/cypress/e2e/incidents/regression/{02.reg_ui_charts_comprehensive.cy.ts => ui_regressions.cy.ts} (100%) rename web/cypress/e2e/{monitoring/regression/03.reg_legacy_dashboards_admin.cy.ts => legacy-dashboards/legacy_dashboards_regression.cy.ts} (83%) rename web/cypress/e2e/{virtualization/03.coo_ivt_legacy_dashboards.cy.ts => legacy-dashboards/legacy_dashboards_virtualization_regression.cy.ts} (85%) create mode 100644 web/cypress/e2e/metrics/metrics_regression.cy.ts rename web/cypress/e2e/{virtualization/02.coo_ivt_metrics_1.cy.ts => metrics/metrics_virtualization_ivt.cy.ts} (63%) delete mode 100644 web/cypress/e2e/monitoring/regression/01.reg_alerts_admin.cy.ts delete mode 100644 web/cypress/e2e/monitoring/regression/01.reg_alerts_dev.cy.ts delete mode 100644 web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_1.cy.ts delete mode 100644 web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_2.cy.ts rename web/cypress/e2e/{coo/03.coo_lightspeed_show_timeseries.cy.ts => perses-dashboards/lightspeed_integration.cy.ts} (100%) rename web/cypress/e2e/{perses/00.coo_bvt_perses_admin.cy.ts => perses-dashboards/perses_dashboards_bvt.cy.ts} (100%) rename web/cypress/e2e/{perses/03.coo_create_perses_admin.cy.ts => perses-dashboards/perses_dashboards_create.cy.ts} (100%) rename web/cypress/e2e/{perses/05.coo_tempo_loki_admin.cy.ts => perses-dashboards/perses_dashboards_datasources.cy.ts} (100%) rename web/cypress/e2e/{perses/02.coo_edit_perses_admin.cy.ts => perses-dashboards/perses_dashboards_edit.cy.ts} (100%) rename web/cypress/e2e/{perses/04.coo_import_perses_admin.cy.ts => perses-dashboards/perses_dashboards_import.cy.ts} (100%) rename web/cypress/e2e/{perses/01.coo_list_perses_admin.cy.ts => perses-dashboards/perses_dashboards_list.cy.ts} (100%) rename web/cypress/e2e/{virtualization/04.coo_ivt_perses.cy.ts => perses-dashboards/perses_dashboards_virtualization_ivt.cy.ts} (72%) rename web/cypress/e2e/{perses/99.coo_rbac_perses_user1.cy.ts => perses-dashboards/rbac/perses_dashboards_user1.cy.ts} (93%) rename web/cypress/e2e/{perses/99.coo_rbac_perses_user2.cy.ts => perses-dashboards/rbac/perses_dashboards_user2.cy.ts} (93%) rename web/cypress/e2e/{perses/99.coo_rbac_perses_user3.cy.ts => perses-dashboards/rbac/perses_dashboards_user3.cy.ts} (92%) rename web/cypress/e2e/{perses/99.coo_rbac_perses_user4.cy.ts => perses-dashboards/rbac/perses_dashboards_user4.cy.ts} (93%) rename web/cypress/e2e/{perses/99.coo_rbac_perses_user5.cy.ts => perses-dashboards/rbac/perses_dashboards_user5.cy.ts} (93%) rename web/cypress/e2e/{perses/99.coo_rbac_perses_user6.cy.ts => perses-dashboards/rbac/perses_dashboards_user6.cy.ts} (93%) rename web/cypress/e2e/{monitoring/00.bvt_admin.cy.ts => shared/admin_perspective_bvt.cy.ts} (100%) create mode 100644 web/cypress/e2e/shared/coo_submenus.cy.ts diff --git a/web/cypress/e2e/coo/02.acm_alerting_ui.cy.ts b/web/cypress/e2e/alerts/alerts_acm.cy.ts similarity index 100% rename from web/cypress/e2e/coo/02.acm_alerting_ui.cy.ts rename to web/cypress/e2e/alerts/alerts_acm.cy.ts diff --git a/web/cypress/e2e/monitoring/00.bvt_dev.cy.ts b/web/cypress/e2e/alerts/alerts_bvt.cy.ts similarity index 90% rename from web/cypress/e2e/monitoring/00.bvt_dev.cy.ts rename to web/cypress/e2e/alerts/alerts_bvt.cy.ts index ab142a647..4a27cb66d 100644 --- a/web/cypress/e2e/monitoring/00.bvt_dev.cy.ts +++ b/web/cypress/e2e/alerts/alerts_bvt.cy.ts @@ -8,7 +8,7 @@ const MP = { operatorName: 'Cluster Monitoring Operator', }; -describe('BVT: Monitoring - Namespaced', { tags: ['@alerting'] }, () => { +describe('BVT: Monitoring - Namespaced', { tags: ['@alerting', '@metrics'] }, () => { before(() => { cy.beforeBlock(MP); }); diff --git a/web/cypress/e2e/virtualization/01.coo_ivt_alerts.cy.ts b/web/cypress/e2e/alerts/alerts_ivt.cy.ts similarity index 81% rename from web/cypress/e2e/virtualization/01.coo_ivt_alerts.cy.ts rename to web/cypress/e2e/alerts/alerts_ivt.cy.ts index 090700965..b700b9b29 100644 --- a/web/cypress/e2e/virtualization/01.coo_ivt_alerts.cy.ts +++ b/web/cypress/e2e/alerts/alerts_ivt.cy.ts @@ -34,39 +34,18 @@ const KBV = { }; describe( - 'Installation: COO and setting up Monitoring Plugin', - { tags: ['@alerting', '@virtualization', '@slow', '@coo'] }, + 'Regression: Monitoring - Alerts (Virtualization)', + { tags: ['@alerting', '@slow', '@virtualization', '@coo'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP); - }); - - it('1. Installation: COO and setting up Monitoring Plugin', () => { cy.log('Installation: COO and setting up Monitoring Plugin'); - }); - }, -); - -describe( - 'IVT: Monitoring UIPlugin + Virtualization', - { tags: ['@alerting', '@virtualization', '@slow', '@coo'] }, - () => { - before(() => { cy.beforeBlockVirtualization(KBV); - }); - - it('1. Virtualization perspective - Observe Menu', () => { cy.log('Virtualization perspective - Observe Menu and verify all submenus'); cy.switchPerspective('Virtualization', 'Fleet virtualization'); guidedTour.closeKubevirtTour(); }); - }, -); -describe( - 'Regression: Monitoring - Alerts (Virtualization)', - { tags: ['@alerting', '@slow', '@virtualization', '@coo'] }, - () => { beforeEach(() => { cy.visit('/'); cy.validateLogin(); diff --git a/web/cypress/e2e/alerts/alerts_regression.cy.ts b/web/cypress/e2e/alerts/alerts_regression.cy.ts new file mode 100644 index 000000000..049a7e602 --- /dev/null +++ b/web/cypress/e2e/alerts/alerts_regression.cy.ts @@ -0,0 +1,60 @@ +import { runAllRegressionCorePlatformAlertsTests } from '../../support/monitoring/01.reg_alerts.cy'; +import { alerts } from '../../fixtures/monitoring/alert'; +import { runAllRegressionAlertsTestsNamespace } from '../../support/monitoring/04.reg_alerts_namespace.cy'; +import { commonPages } from '../../views/common'; +import { nav } from '../../views/nav'; + +const MP = { + namespace: 'openshift-monitoring', + operatorName: 'Cluster Monitoring Operator', +}; + +// Test suite for Core platform perspective +describe( + 'Regression: Monitoring - Alerts (Core platform)', + { tags: ['@alerting', '@metrics'] }, + () => { + before(() => { + cy.beforeBlock(MP); + cy.switchPerspective('Core platform'); + }); + + beforeEach(() => { + alerts.getWatchdogAlert(); + nav.sidenav.clickNavLink(['Observe', 'Metrics']); + commonPages.titleShouldHaveText('Metrics'); + cy.changeNamespace('All Projects'); + nav.sidenav.clickNavLink(['Observe', 'Alerting']); + commonPages.titleShouldHaveText('Alerting'); + alerts.getWatchdogAlert(); + }); + + // Run tests in Core platform perspective + runAllRegressionCorePlatformAlertsTests({ + name: 'Administrator', + }); + }, +); + +describe( + 'Regression: Monitoring - Alerts Namespaced (Administrator)', + { tags: ['@alerting'] }, + () => { + before(() => { + cy.beforeBlock(MP); + }); + + beforeEach(() => { + alerts.getWatchdogAlert(); + nav.sidenav.clickNavLink(['Observe', 'Alerting']); + commonPages.titleShouldHaveText('Alerting'); + alerts.getWatchdogAlert(); + cy.changeNamespace(MP.namespace); + }); + + // Run tests in Administrator perspective + runAllRegressionAlertsTestsNamespace({ + name: 'Administrator', + }); + }, +); diff --git a/web/cypress/e2e/virtualization/00.coo_ivt.cy.ts b/web/cypress/e2e/alerts/alerts_virtualization_bvt.cy.ts similarity index 72% rename from web/cypress/e2e/virtualization/00.coo_ivt.cy.ts rename to web/cypress/e2e/alerts/alerts_virtualization_bvt.cy.ts index 8a379395e..b37ddbfd9 100644 --- a/web/cypress/e2e/virtualization/00.coo_ivt.cy.ts +++ b/web/cypress/e2e/alerts/alerts_virtualization_bvt.cy.ts @@ -3,6 +3,7 @@ import { guidedTour } from '../../views/tour'; import { alerts } from '../../fixtures/monitoring/alert'; import { nav } from '../../views/nav'; import { commonPages } from '../../views/common'; +import { troubleshootingPanelPage } from 'cypress/views/troubleshooting-panel'; // Set constants for the operators that need to be installed for tests. const MCP = { @@ -34,41 +35,24 @@ const KBV = { }; describe( - 'Installation: COO and setting up Monitoring Plugin', - { tags: ['@virtualization', '@coo', '@slow'] }, + 'IVT: Monitoring + Virtualization', + { tags: ['@metrics', '@alerting', '@slow', '@virtualization', '@coo'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP); - }); - - it('1. Installation: COO and setting up Monitoring Plugin', () => { cy.log('Installation: COO and setting up Monitoring Plugin'); + cy.beforeBlockVirtualization(KBV); + cy.log('Virtualization perspective - Observe Menu and verify all submenus'); + cy.switchPerspective('Virtualization', 'Fleet virtualization'); + guidedTour.closeKubevirtTour(); }); - }, -); - -describe('Installation: Virtualization', { tags: ['@virtualization', '@coo', '@slow'] }, () => { - before(() => { - cy.beforeBlockVirtualization(KBV); - }); - - it('1. Virtualization perspective - Observe Menu', () => { - cy.log('Virtualization perspective - Observe Menu and verify all submenus'); - cy.switchPerspective('Virtualization', 'Fleet virtualization'); - guidedTour.closeKubevirtTour(); - }); -}); - -describe( - 'IVT: Monitoring + Virtualization', - { tags: ['@metrics', '@alerting', '@virtualization', '@coo'] }, - () => { beforeEach(() => { cy.visit('/'); guidedTour.close(); cy.validateLogin(); cy.switchPerspective('Virtualization', 'Fleet virtualization'); guidedTour.closeKubevirtTour(); + troubleshootingPanelPage.signalCorrelationShouldNotBeVisible(); nav.sidenav.clickNavLink(['Observe', 'Metrics']); commonPages.titleShouldHaveText('Metrics'); cy.changeNamespace('All Projects'); diff --git a/web/cypress/e2e/coo/01.coo_bvt.cy.ts b/web/cypress/e2e/coo/01.coo_bvt.cy.ts deleted file mode 100644 index eba132f12..000000000 --- a/web/cypress/e2e/coo/01.coo_bvt.cy.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { commonPages } from '../../views/common'; -import { nav } from '../../views/nav'; -import { troubleshootingPanelPage } from '../../views/troubleshooting-panel'; - -// Set constants for the operators that need to be installed for tests. -const MCP = { - namespace: Cypress.env('COO_NAMESPACE'), - packageName: 'cluster-observability-operator', - operatorName: 'Cluster Observability Operator', - config: { - kind: 'UIPlugin', - name: 'monitoring', - }, -}; - -const MP = { - namespace: 'openshift-monitoring', - operatorName: 'Cluster Monitoring Operator', -}; - -describe('BVT: COO', { tags: ['@alerting', '@acm-alerting', '@coo'] }, () => { - before(() => { - cy.beforeBlockCOO(MCP, MP); - }); - - it('1. Admin perspective - Observe Menu', () => { - cy.log('Admin perspective - Observe Menu and verify all submenus'); - cy.reload(true); - cy.wait(10000); - nav.sidenav.clickNavLink(['Observe', 'Alerting']); - commonPages.titleShouldHaveText('Alerting'); - nav.tabs.switchTab('Silences'); - nav.tabs.switchTab('Alerting rules'); - nav.tabs.switchTab('Incidents'); - nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); - commonPages.titleShouldHaveText('Dashboards'); - nav.sidenav.clickNavLink(['Observe', 'Alerting']); - troubleshootingPanelPage.openSignalCorrelation(); - troubleshootingPanelPage.troubleshootingPanelPageShouldBeLoadedEnabled(); - }); - - /** - * TODO: To be replaced by COO validation such as Dashboards (Perses) scenarios - */ -}); diff --git a/web/cypress/e2e/incidents/01.incidents.cy.ts b/web/cypress/e2e/incidents/incidents_bvt.cy.ts similarity index 100% rename from web/cypress/e2e/incidents/01.incidents.cy.ts rename to web/cypress/e2e/incidents/incidents_bvt.cy.ts diff --git a/web/cypress/e2e/incidents/00.coo_incidents_e2e.cy.ts b/web/cypress/e2e/incidents/incidents_e2e.cy.ts similarity index 100% rename from web/cypress/e2e/incidents/00.coo_incidents_e2e.cy.ts rename to web/cypress/e2e/incidents/incidents_e2e.cy.ts diff --git a/web/cypress/e2e/incidents/02.incidents-mocking-example.cy.ts b/web/cypress/e2e/incidents/incidents_mocking_example.cy.ts similarity index 100% rename from web/cypress/e2e/incidents/02.incidents-mocking-example.cy.ts rename to web/cypress/e2e/incidents/incidents_mocking_example.cy.ts diff --git a/web/cypress/e2e/incidents/performance/01.performance_benchmark.cy.ts b/web/cypress/e2e/incidents/performance/performance_benchmark.cy.ts similarity index 100% rename from web/cypress/e2e/incidents/performance/01.performance_benchmark.cy.ts rename to web/cypress/e2e/incidents/performance/performance_benchmark.cy.ts diff --git a/web/cypress/e2e/incidents/performance/02.performance_walkthrough.cy.ts b/web/cypress/e2e/incidents/performance/performance_walkthrough.cy.ts similarity index 98% rename from web/cypress/e2e/incidents/performance/02.performance_walkthrough.cy.ts rename to web/cypress/e2e/incidents/performance/performance_walkthrough.cy.ts index efc987fa1..3c23ef05a 100644 --- a/web/cypress/e2e/incidents/performance/02.performance_walkthrough.cy.ts +++ b/web/cypress/e2e/incidents/performance/performance_walkthrough.cy.ts @@ -2,7 +2,7 @@ Performance walkthrough: measures rendering cost of interactive operations (filter toggling, time range switching, table row expansion) under load. -Unlike 01.performance_benchmark which measures initial chart render time, +Unlike performance_benchmark which measures initial chart render time, this test measures incremental re-render cost during a realistic user session. Verifies: OBSINTA-1006 diff --git a/web/cypress/e2e/incidents/regression/03-04.reg_e2e_firing_alerts.cy.ts b/web/cypress/e2e/incidents/regression/end_and_resolution.cy.ts similarity index 100% rename from web/cypress/e2e/incidents/regression/03-04.reg_e2e_firing_alerts.cy.ts rename to web/cypress/e2e/incidents/regression/end_and_resolution.cy.ts diff --git a/web/cypress/e2e/incidents/regression/01.reg_filtering.cy.ts b/web/cypress/e2e/incidents/regression/filtering.cy.ts similarity index 100% rename from web/cypress/e2e/incidents/regression/01.reg_filtering.cy.ts rename to web/cypress/e2e/incidents/regression/filtering.cy.ts diff --git a/web/cypress/e2e/incidents/regression/02.reg_ui_tooltip_boundary_times.cy.ts b/web/cypress/e2e/incidents/regression/interval.cy.ts similarity index 100% rename from web/cypress/e2e/incidents/regression/02.reg_ui_tooltip_boundary_times.cy.ts rename to web/cypress/e2e/incidents/regression/interval.cy.ts diff --git a/web/cypress/e2e/incidents/regression/03.reg_api_calls.cy.ts b/web/cypress/e2e/incidents/regression/permission_and_silences.cy.ts similarity index 100% rename from web/cypress/e2e/incidents/regression/03.reg_api_calls.cy.ts rename to web/cypress/e2e/incidents/regression/permission_and_silences.cy.ts diff --git a/web/cypress/e2e/incidents/regression/05.reg_stress_testing_ui.cy.ts b/web/cypress/e2e/incidents/regression/stress_test_ui.cy.ts similarity index 100% rename from web/cypress/e2e/incidents/regression/05.reg_stress_testing_ui.cy.ts rename to web/cypress/e2e/incidents/regression/stress_test_ui.cy.ts diff --git a/web/cypress/e2e/incidents/regression/04.reg_redux_effects.cy.ts b/web/cypress/e2e/incidents/regression/ui_interaction.cy.ts similarity index 100% rename from web/cypress/e2e/incidents/regression/04.reg_redux_effects.cy.ts rename to web/cypress/e2e/incidents/regression/ui_interaction.cy.ts diff --git a/web/cypress/e2e/incidents/regression/02.reg_ui_charts_comprehensive.cy.ts b/web/cypress/e2e/incidents/regression/ui_regressions.cy.ts similarity index 100% rename from web/cypress/e2e/incidents/regression/02.reg_ui_charts_comprehensive.cy.ts rename to web/cypress/e2e/incidents/regression/ui_regressions.cy.ts diff --git a/web/cypress/e2e/monitoring/regression/03.reg_legacy_dashboards_admin.cy.ts b/web/cypress/e2e/legacy-dashboards/legacy_dashboards_regression.cy.ts similarity index 83% rename from web/cypress/e2e/monitoring/regression/03.reg_legacy_dashboards_admin.cy.ts rename to web/cypress/e2e/legacy-dashboards/legacy_dashboards_regression.cy.ts index eac3d5a38..2eb3450be 100644 --- a/web/cypress/e2e/monitoring/regression/03.reg_legacy_dashboards_admin.cy.ts +++ b/web/cypress/e2e/legacy-dashboards/legacy_dashboards_regression.cy.ts @@ -1,7 +1,7 @@ -import { runAllRegressionLegacyDashboardsTests } from '../../../support/monitoring/03.reg_legacy_dashboards.cy'; -import { runAllRegressionLegacyDashboardsTestsNamespace } from '../../../support/monitoring/06.reg_legacy_dashboards_namespace.cy'; -import { commonPages } from '../../../views/common'; -import { nav } from '../../../views/nav'; +import { runAllRegressionLegacyDashboardsTests } from '../../support/monitoring/03.reg_legacy_dashboards.cy'; +import { runAllRegressionLegacyDashboardsTestsNamespace } from '../../support/monitoring/06.reg_legacy_dashboards_namespace.cy'; +import { commonPages } from '../../views/common'; +import { nav } from '../../views/nav'; const MP = { namespace: 'openshift-monitoring', @@ -39,7 +39,7 @@ describe( // Test suite for Administrator perspective describe( 'Regression: Monitoring - Legacy Dashboards Namespaced (Administrator)', - { tags: ['@legacy-dashboards'] }, + { tags: ['@legacy-dashboards', '@metrics'] }, () => { before(() => { cy.beforeBlock(MP); diff --git a/web/cypress/e2e/virtualization/03.coo_ivt_legacy_dashboards.cy.ts b/web/cypress/e2e/legacy-dashboards/legacy_dashboards_virtualization_regression.cy.ts similarity index 85% rename from web/cypress/e2e/virtualization/03.coo_ivt_legacy_dashboards.cy.ts rename to web/cypress/e2e/legacy-dashboards/legacy_dashboards_virtualization_regression.cy.ts index 97dcb3705..cea866733 100644 --- a/web/cypress/e2e/virtualization/03.coo_ivt_legacy_dashboards.cy.ts +++ b/web/cypress/e2e/legacy-dashboards/legacy_dashboards_virtualization_regression.cy.ts @@ -33,39 +33,17 @@ const KBV = { }; describe( - 'Installation: COO and setting up Monitoring Plugin', - { tags: ['@virtualization', '@slow', '@coo'] }, + 'Regression: Monitoring - Legacy Dashboards (Virtualization)', + { tags: ['@legacy-dashboards', '@slow', '@virtualization', '@coo'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP); - }); - - it('1. Installation: COO and setting up Monitoring Plugin', () => { cy.log('Installation: COO and setting up Monitoring Plugin'); - }); - }, -); - -describe( - 'IVT: Monitoring UIPlugin + Virtualization', - { tags: ['@virtualization', '@slow', '@coo'] }, - () => { - before(() => { cy.beforeBlockVirtualization(KBV); - }); - - it('1. Virtualization perspective - Observe Menu', () => { cy.log('Virtualization perspective - Observe Menu and verify all submenus'); cy.switchPerspective('Virtualization', 'Fleet virtualization'); guidedTour.closeKubevirtTour(); }); - }, -); - -describe( - 'Regression: Monitoring - Legacy Dashboards (Virtualization)', - { tags: ['@legacy-dashboards', '@slow', '@virtualization', '@coo'] }, - () => { beforeEach(() => { cy.visit('/'); cy.validateLogin(); diff --git a/web/cypress/e2e/metrics/metrics_regression.cy.ts b/web/cypress/e2e/metrics/metrics_regression.cy.ts new file mode 100644 index 000000000..512c53d64 --- /dev/null +++ b/web/cypress/e2e/metrics/metrics_regression.cy.ts @@ -0,0 +1,91 @@ +import { runAllRegressionMetricsTests2 } from '../../support/monitoring/02.reg_metrics_2.cy'; +import { runAllRegressionMetricsTests1 } from '../../support/monitoring/02.reg_metrics_1.cy'; +import { runAllRegressionMetricsTestsNamespace1 } from '../../support/monitoring/05.reg_metrics_namespace_1.cy'; +import { commonPages } from '../../views/common'; +import { nav } from '../../views/nav'; +import { runAllRegressionMetricsTestsNamespace2 } from '../../support/monitoring/05.reg_metrics_namespace_2.cy'; + +const MP = { + namespace: 'openshift-monitoring', + operatorName: 'Cluster Monitoring Operator', +}; + +// Test suite for Administrator perspective +describe('Regression: Monitoring - Metrics (Administrator)', { tags: ['@metrics'] }, () => { + before(() => { + cy.beforeBlock(MP); + }); + + beforeEach(() => { + nav.sidenav.clickNavLink(['Observe', 'Metrics']); + commonPages.titleShouldHaveText('Metrics'); + cy.changeNamespace('All Projects'); + }); + + // Run tests in Administrator perspective + runAllRegressionMetricsTests1({ + name: 'Administrator', + }); +}); + +// Test suite for Administrator perspective +describe( + 'Regression: Monitoring - Metrics Namespaced (Administrator)', + { tags: ['@metrics'] }, + () => { + before(() => { + cy.beforeBlock(MP); + }); + + beforeEach(() => { + nav.sidenav.clickNavLink(['Observe', 'Metrics']); + commonPages.titleShouldHaveText('Metrics'); + cy.changeNamespace(MP.namespace); + }); + + // Run tests in Administrator perspective + runAllRegressionMetricsTestsNamespace1({ + name: 'Administrator', + }); + }, +); + +// Test suite for Administrator perspective +describe('Regression: Monitoring - Metrics (Administrator)', { tags: ['@metrics'] }, () => { + before(() => { + cy.beforeBlock(MP); + }); + + beforeEach(() => { + nav.sidenav.clickNavLink(['Observe', 'Metrics']); + commonPages.titleShouldHaveText('Metrics'); + cy.changeNamespace('All Projects'); + }); + + // Run tests in Administrator perspective + runAllRegressionMetricsTests2({ + name: 'Administrator', + }); +}); + +// Test suite for Administrator perspective +describe( + 'Regression: Monitoring - Metrics Namespaced (Administrator)', + { tags: ['@metrics'] }, + () => { + before(() => { + cy.beforeBlock(MP); + }); + + beforeEach(() => { + nav.sidenav.clickNavLink(['Observe', 'Metrics']); + commonPages.titleShouldHaveText('Metrics'); + cy.changeNamespace(MP.namespace); + }); + + // Run tests in Administrator perspective + runAllRegressionMetricsTestsNamespace2({ + name: 'Administrator', + }); + }, +); diff --git a/web/cypress/e2e/virtualization/02.coo_ivt_metrics_1.cy.ts b/web/cypress/e2e/metrics/metrics_virtualization_ivt.cy.ts similarity index 63% rename from web/cypress/e2e/virtualization/02.coo_ivt_metrics_1.cy.ts rename to web/cypress/e2e/metrics/metrics_virtualization_ivt.cy.ts index 9c84c795c..c9e97f79d 100644 --- a/web/cypress/e2e/virtualization/02.coo_ivt_metrics_1.cy.ts +++ b/web/cypress/e2e/metrics/metrics_virtualization_ivt.cy.ts @@ -1,9 +1,11 @@ +import { runAllRegressionMetricsTests2 } from '../../support/monitoring/02.reg_metrics_2.cy'; import { alerts } from '../../fixtures/monitoring/alert'; import { runAllRegressionMetricsTests1 } from '../../support/monitoring/02.reg_metrics_1.cy'; import { runAllRegressionMetricsTestsNamespace1 } from '../../support/monitoring/05.reg_metrics_namespace_1.cy'; import { commonPages } from '../../views/common'; import { nav } from '../../views/nav'; import { guidedTour } from '../../views/tour'; +import { runAllRegressionMetricsTestsNamespace2 } from '../../support/monitoring/05.reg_metrics_namespace_2.cy'; // Set constants for the operators that need to be installed for tests. const MCP = { @@ -34,39 +36,69 @@ const KBV = { }; describe( - 'Installation: COO and setting up Monitoring Plugin', - { tags: ['@virtualization', '@slow', '@coo'] }, + 'Regression: Monitoring - Metrics (Virtualization)', + { tags: ['@metrics', '@slow', '@virtualization', '@coo'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP); + cy.log('Installation: COO and setting up Monitoring Plugin'); + cy.beforeBlockVirtualization(KBV); + cy.log('Virtualization perspective - Observe Menu and verify all submenus'); + cy.switchPerspective('Virtualization'); + guidedTour.closeKubevirtTour(); + }); + beforeEach(() => { + cy.visit('/'); + cy.validateLogin(); + cy.switchPerspective('Virtualization'); + guidedTour.closeKubevirtTour(); + alerts.getWatchdogAlert(); + nav.sidenav.clickNavLink(['Observe', 'Metrics']); + commonPages.titleShouldHaveText('Metrics'); + cy.changeNamespace('All Projects'); + alerts.getWatchdogAlert(); }); - it('1. Installation: COO and setting up Monitoring Plugin', () => { - cy.log('Installation: COO and setting up Monitoring Plugin'); + runAllRegressionMetricsTests1({ + name: 'Virtualization', }); }, ); describe( - 'IVT: Monitoring UIPlugin + Virtualization', - { tags: ['@virtualization', '@slow', '@coo'] }, + 'Regression: Monitoring - Metrics Namespaced (Virtualization)', + { tags: ['@metrics', '@slow', '@virtualization', '@coo'] }, () => { - before(() => { - cy.beforeBlockVirtualization(KBV); + beforeEach(() => { + cy.visit('/'); + cy.validateLogin(); + cy.switchPerspective('Virtualization'); + guidedTour.closeKubevirtTour(); + alerts.getWatchdogAlert(); + nav.sidenav.clickNavLink(['Observe', 'Metrics']); + commonPages.titleShouldHaveText('Metrics'); + cy.changeNamespace(MP.namespace); + alerts.getWatchdogAlert(); }); - it('1. Virtualization perspective - Observe Menu', () => { - cy.log('Virtualization perspective - Observe Menu and verify all submenus'); - cy.switchPerspective('Virtualization', 'Fleet virtualization'); - guidedTour.closeKubevirtTour(); + runAllRegressionMetricsTestsNamespace1({ + name: 'Virtualization', }); }, ); describe( 'Regression: Monitoring - Metrics (Virtualization)', - { tags: ['@metrics', '@slow', '@virtualization', '@coo'] }, + { tags: ['@metrics', '@slow', '@virtualization'] }, () => { + before(() => { + cy.beforeBlockCOO(MCP, MP); + cy.log('Installation: COO and setting up Monitoring Plugin'); + cy.beforeBlockVirtualization(KBV); + cy.log('Virtualization perspective - Observe Menu and verify all submenus'); + cy.switchPerspective('Virtualization', 'Fleet virtualization'); + guidedTour.closeKubevirtTour(); + }); beforeEach(() => { cy.visit('/'); cy.validateLogin(); @@ -79,7 +111,7 @@ describe( alerts.getWatchdogAlert(); }); - runAllRegressionMetricsTests1({ + runAllRegressionMetricsTests2({ name: 'Virtualization', }); }, @@ -87,7 +119,7 @@ describe( describe( 'Regression: Monitoring - Metrics Namespaced (Virtualization)', - { tags: ['@metrics', '@slow', '@virtualization', '@coo'] }, + { tags: ['@metrics', '@slow', '@virtualization'] }, () => { beforeEach(() => { cy.visit('/'); @@ -101,7 +133,7 @@ describe( alerts.getWatchdogAlert(); }); - runAllRegressionMetricsTestsNamespace1({ + runAllRegressionMetricsTestsNamespace2({ name: 'Virtualization', }); }, diff --git a/web/cypress/e2e/monitoring/regression/01.reg_alerts_admin.cy.ts b/web/cypress/e2e/monitoring/regression/01.reg_alerts_admin.cy.ts deleted file mode 100644 index b24a4bfd3..000000000 --- a/web/cypress/e2e/monitoring/regression/01.reg_alerts_admin.cy.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { alerts } from '../../../fixtures/monitoring/alert'; -import { runAllRegressionCorePlatformAlertsTests } from '../../../support/monitoring/01.reg_alerts.cy'; -import { commonPages } from '../../../views/common'; -import { nav } from '../../../views/nav'; - -const MP = { - namespace: 'openshift-monitoring', - operatorName: 'Cluster Monitoring Operator', -}; - -// Test suite for Core platform perspective -describe( - 'Regression: Monitoring - Alerts (Core platform)', - { tags: ['@alerting', '@metrics'] }, - () => { - before(() => { - cy.beforeBlock(MP); - cy.switchPerspective('Core platform'); - }); - - beforeEach(() => { - alerts.getWatchdogAlert(); - nav.sidenav.clickNavLink(['Observe', 'Metrics']); - commonPages.titleShouldHaveText('Metrics'); - cy.changeNamespace('All Projects'); - nav.sidenav.clickNavLink(['Observe', 'Alerting']); - commonPages.titleShouldHaveText('Alerting'); - alerts.getWatchdogAlert(); - }); - - // Run tests in Core platform perspective - runAllRegressionCorePlatformAlertsTests({ - name: 'Core platform', - }); - }, -); diff --git a/web/cypress/e2e/monitoring/regression/01.reg_alerts_dev.cy.ts b/web/cypress/e2e/monitoring/regression/01.reg_alerts_dev.cy.ts deleted file mode 100644 index 80e031fdf..000000000 --- a/web/cypress/e2e/monitoring/regression/01.reg_alerts_dev.cy.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { alerts } from '../../../fixtures/monitoring/alert'; -import { runAllRegressionAlertsTestsNamespace } from '../../../support/monitoring/04.reg_alerts_namespace.cy'; -import { commonPages } from '../../../views/common'; -import { nav } from '../../../views/nav'; - -const MP = { - namespace: 'openshift-monitoring', - operatorName: 'Cluster Monitoring Operator', -}; - -describe( - 'Regression: Monitoring - Alerts Namespaced (Administrator)', - { tags: ['@alerting'] }, - () => { - before(() => { - cy.beforeBlock(MP); - }); - - beforeEach(() => { - alerts.getWatchdogAlert(); - nav.sidenav.clickNavLink(['Observe', 'Alerting']); - commonPages.titleShouldHaveText('Alerting'); - alerts.getWatchdogAlert(); - cy.changeNamespace(MP.namespace); - }); - - // Run tests in Administrator perspective - runAllRegressionAlertsTestsNamespace({ - name: 'Administrator', - }); - }, -); diff --git a/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_1.cy.ts b/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_1.cy.ts deleted file mode 100644 index 09a4ef6f7..000000000 --- a/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_1.cy.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { runAllRegressionMetricsTests1 } from '../../../support/monitoring/02.reg_metrics_1.cy'; -import { runAllRegressionMetricsTestsNamespace1 } from '../../../support/monitoring/05.reg_metrics_namespace_1.cy'; -import { commonPages } from '../../../views/common'; -import { nav } from '../../../views/nav'; - -const MP = { - namespace: 'openshift-monitoring', - operatorName: 'Cluster Monitoring Operator', -}; - -// Test suite for Administrator perspective -describe('Regression: Monitoring - Metrics (Administrator)', { tags: ['@metrics'] }, () => { - before(() => { - cy.beforeBlock(MP); - }); - - beforeEach(() => { - nav.sidenav.clickNavLink(['Observe', 'Metrics']); - commonPages.titleShouldHaveText('Metrics'); - cy.changeNamespace('All Projects'); - }); - - // Run tests in Administrator perspective - runAllRegressionMetricsTests1({ - name: 'Administrator', - }); -}); - -// Test suite for Administrator perspective -describe( - 'Regression: Monitoring - Metrics Namespaced (Administrator)', - { tags: ['@metrics'] }, - () => { - before(() => { - cy.beforeBlock(MP); - }); - - beforeEach(() => { - nav.sidenav.clickNavLink(['Observe', 'Metrics']); - commonPages.titleShouldHaveText('Metrics'); - cy.changeNamespace(MP.namespace); - }); - - // Run tests in Administrator perspective - runAllRegressionMetricsTestsNamespace1({ - name: 'Administrator', - }); - }, -); diff --git a/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_2.cy.ts b/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_2.cy.ts deleted file mode 100644 index d5d7cfcdf..000000000 --- a/web/cypress/e2e/monitoring/regression/02.reg_metrics_admin_2.cy.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { runAllRegressionMetricsTests2 } from '../../../support/monitoring/02.reg_metrics_2.cy'; -import { runAllRegressionMetricsTestsNamespace2 } from '../../../support/monitoring/05.reg_metrics_namespace_2.cy'; -import { commonPages } from '../../../views/common'; -import { nav } from '../../../views/nav'; - -const MP = { - namespace: 'openshift-monitoring', - operatorName: 'Cluster Monitoring Operator', -}; - -// Test suite for Administrator perspective -describe('Regression: Monitoring - Metrics (Administrator)', { tags: ['@metrics'] }, () => { - before(() => { - cy.beforeBlock(MP); - }); - - beforeEach(() => { - nav.sidenav.clickNavLink(['Observe', 'Metrics']); - commonPages.titleShouldHaveText('Metrics'); - cy.changeNamespace('All Projects'); - }); - - // Run tests in Administrator perspective - runAllRegressionMetricsTests2({ - name: 'Administrator', - }); -}); - -// Test suite for Administrator perspective -describe( - 'Regression: Monitoring - Metrics Namespaced (Administrator)', - { tags: ['@metrics'] }, - () => { - before(() => { - cy.beforeBlock(MP); - }); - - beforeEach(() => { - nav.sidenav.clickNavLink(['Observe', 'Metrics']); - commonPages.titleShouldHaveText('Metrics'); - cy.changeNamespace(MP.namespace); - }); - - // Run tests in Administrator perspective - runAllRegressionMetricsTestsNamespace2({ - name: 'Administrator', - }); - }, -); diff --git a/web/cypress/e2e/coo/03.coo_lightspeed_show_timeseries.cy.ts b/web/cypress/e2e/perses-dashboards/lightspeed_integration.cy.ts similarity index 100% rename from web/cypress/e2e/coo/03.coo_lightspeed_show_timeseries.cy.ts rename to web/cypress/e2e/perses-dashboards/lightspeed_integration.cy.ts diff --git a/web/cypress/e2e/perses/00.coo_bvt_perses_admin.cy.ts b/web/cypress/e2e/perses-dashboards/perses_dashboards_bvt.cy.ts similarity index 100% rename from web/cypress/e2e/perses/00.coo_bvt_perses_admin.cy.ts rename to web/cypress/e2e/perses-dashboards/perses_dashboards_bvt.cy.ts diff --git a/web/cypress/e2e/perses/03.coo_create_perses_admin.cy.ts b/web/cypress/e2e/perses-dashboards/perses_dashboards_create.cy.ts similarity index 100% rename from web/cypress/e2e/perses/03.coo_create_perses_admin.cy.ts rename to web/cypress/e2e/perses-dashboards/perses_dashboards_create.cy.ts diff --git a/web/cypress/e2e/perses/05.coo_tempo_loki_admin.cy.ts b/web/cypress/e2e/perses-dashboards/perses_dashboards_datasources.cy.ts similarity index 100% rename from web/cypress/e2e/perses/05.coo_tempo_loki_admin.cy.ts rename to web/cypress/e2e/perses-dashboards/perses_dashboards_datasources.cy.ts diff --git a/web/cypress/e2e/perses/02.coo_edit_perses_admin.cy.ts b/web/cypress/e2e/perses-dashboards/perses_dashboards_edit.cy.ts similarity index 100% rename from web/cypress/e2e/perses/02.coo_edit_perses_admin.cy.ts rename to web/cypress/e2e/perses-dashboards/perses_dashboards_edit.cy.ts diff --git a/web/cypress/e2e/perses/04.coo_import_perses_admin.cy.ts b/web/cypress/e2e/perses-dashboards/perses_dashboards_import.cy.ts similarity index 100% rename from web/cypress/e2e/perses/04.coo_import_perses_admin.cy.ts rename to web/cypress/e2e/perses-dashboards/perses_dashboards_import.cy.ts diff --git a/web/cypress/e2e/perses/01.coo_list_perses_admin.cy.ts b/web/cypress/e2e/perses-dashboards/perses_dashboards_list.cy.ts similarity index 100% rename from web/cypress/e2e/perses/01.coo_list_perses_admin.cy.ts rename to web/cypress/e2e/perses-dashboards/perses_dashboards_list.cy.ts diff --git a/web/cypress/e2e/virtualization/04.coo_ivt_perses.cy.ts b/web/cypress/e2e/perses-dashboards/perses_dashboards_virtualization_ivt.cy.ts similarity index 72% rename from web/cypress/e2e/virtualization/04.coo_ivt_perses.cy.ts rename to web/cypress/e2e/perses-dashboards/perses_dashboards_virtualization_ivt.cy.ts index 92654ba0a..16c0172fd 100644 --- a/web/cypress/e2e/virtualization/04.coo_ivt_perses.cy.ts +++ b/web/cypress/e2e/perses-dashboards/perses_dashboards_virtualization_ivt.cy.ts @@ -1,3 +1,4 @@ +// Not finished import { nav } from '../../views/nav'; import { runBVTCOOPersesTests1 } from '../../support/perses/00.coo_bvt_perses_admin.cy'; import { guidedTour } from '../../views/tour'; @@ -33,36 +34,18 @@ const KBV = { }; describe( - 'Installation: COO and setting up Monitoring Plugin', - { tags: ['@virtualization', '@slow'] }, + 'IVT: COO - Dashboards (Perses) - Virtualization perspective', + { tags: ['@perses-dashboards', '@slow', '@virtualization', '@coo'] }, + () => { before(() => { cy.beforeBlockCOO(MCP, MP); - cy.cleanupPersesTestDashboardsBeforeTests(); - }); - - it('1. Installation: COO and setting up Monitoring Plugin', () => { cy.log('Installation: COO and setting up Monitoring Plugin'); + cy.beforeBlockVirtualization(KBV); + cy.log('Virtualization perspective - Observe Menu and verify all submenus'); + cy.switchPerspective('Virtualization', 'Fleet virtualization'); + guidedTour.closeKubevirtTour(); }); - }, -); - -describe('Installation: Virtualization', { tags: ['@virtualization', '@slow'] }, () => { - before(() => { - cy.beforeBlockVirtualization(KBV); - }); - - it('1. Installation: Virtualization', () => { - cy.log('Installation: Virtualization'); - cy.switchPerspective('Virtualization', 'Fleet virtualization'); - guidedTour.closeKubevirtTour(); - }); -}); - -describe( - 'IVT: COO - Dashboards (Perses) - Virtualization perspective', - { tags: ['@perses-dashboards', '@slow', '@virtualization', '@coo'] }, - () => { beforeEach(() => { cy.visit('/'); guidedTour.close(); diff --git a/web/cypress/e2e/perses/99.coo_rbac_perses_user1.cy.ts b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user1.cy.ts similarity index 93% rename from web/cypress/e2e/perses/99.coo_rbac_perses_user1.cy.ts rename to web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user1.cy.ts index 927d1b542..26d81c771 100644 --- a/web/cypress/e2e/perses/99.coo_rbac_perses_user1.cy.ts +++ b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user1.cy.ts @@ -1,5 +1,5 @@ -import { nav } from '../../views/nav'; -import { runCOORBACPersesTestsDevUser1 } from '../../support/perses/99.coo_rbac_perses_user1.cy'; +import { nav } from '../../../views/nav'; +import { runCOORBACPersesTestsDevUser1 } from '../../../support/perses/99.coo_rbac_perses_user1.cy'; // Set constants for the operators that need to be installed for tests. const MCP = { diff --git a/web/cypress/e2e/perses/99.coo_rbac_perses_user2.cy.ts b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user2.cy.ts similarity index 93% rename from web/cypress/e2e/perses/99.coo_rbac_perses_user2.cy.ts rename to web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user2.cy.ts index 17db97ae2..dd56a12f1 100644 --- a/web/cypress/e2e/perses/99.coo_rbac_perses_user2.cy.ts +++ b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user2.cy.ts @@ -1,6 +1,6 @@ -import { nav } from '../../views/nav'; -import { runCOORBACPersesTestsDevUser2 } from '../../support/perses/99.coo_rbac_perses_user2.cy'; -import { operatorAuthUtils } from '../../support/commands/auth-commands'; +import { nav } from '../../../views/nav'; +import { runCOORBACPersesTestsDevUser2 } from '../../../support/perses/99.coo_rbac_perses_user2.cy'; +import { operatorAuthUtils } from '../../../support/commands/auth-commands'; // Set constants for the operators that need to be installed for tests. // const MCP = { diff --git a/web/cypress/e2e/perses/99.coo_rbac_perses_user3.cy.ts b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user3.cy.ts similarity index 92% rename from web/cypress/e2e/perses/99.coo_rbac_perses_user3.cy.ts rename to web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user3.cy.ts index 64363f45f..b099c2feb 100644 --- a/web/cypress/e2e/perses/99.coo_rbac_perses_user3.cy.ts +++ b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user3.cy.ts @@ -1,6 +1,6 @@ -import { nav } from '../../views/nav'; -import { runCOORBACPersesTestsDevUser3 } from '../../support/perses/99.coo_rbac_perses_user3.cy'; -import { operatorAuthUtils } from '../../support/commands/auth-commands'; +import { nav } from '../../../views/nav'; +import { runCOORBACPersesTestsDevUser3 } from '../../../support/perses/99.coo_rbac_perses_user3.cy'; +import { operatorAuthUtils } from '../../../support/commands/auth-commands'; // Set constants for the operators that need to be installed for tests. // const MCP = { @@ -71,6 +71,7 @@ describe( beforeEach(() => { cy.switchPerspective('Core platform'); + // Why do we check Dashboards first? nav.sidenav.clickNavLink(['Observe', 'Dashboards']); cy.wait(2000); nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); diff --git a/web/cypress/e2e/perses/99.coo_rbac_perses_user4.cy.ts b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user4.cy.ts similarity index 93% rename from web/cypress/e2e/perses/99.coo_rbac_perses_user4.cy.ts rename to web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user4.cy.ts index a3c396802..d62d9df95 100644 --- a/web/cypress/e2e/perses/99.coo_rbac_perses_user4.cy.ts +++ b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user4.cy.ts @@ -1,6 +1,6 @@ -import { nav } from '../../views/nav'; -import { runCOORBACPersesTestsDevUser4 } from '../../support/perses/99.coo_rbac_perses_user4.cy'; -import { operatorAuthUtils } from '../../support/commands/auth-commands'; +import { nav } from '../../../views/nav'; +import { runCOORBACPersesTestsDevUser4 } from '../../../support/perses/99.coo_rbac_perses_user4.cy'; +import { operatorAuthUtils } from '../../../support/commands/auth-commands'; // Set constants for the operators that need to be installed for tests. // const MCP = { diff --git a/web/cypress/e2e/perses/99.coo_rbac_perses_user5.cy.ts b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user5.cy.ts similarity index 93% rename from web/cypress/e2e/perses/99.coo_rbac_perses_user5.cy.ts rename to web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user5.cy.ts index 46466d622..6f90e0002 100644 --- a/web/cypress/e2e/perses/99.coo_rbac_perses_user5.cy.ts +++ b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user5.cy.ts @@ -1,6 +1,6 @@ -import { nav } from '../../views/nav'; -import { runCOORBACPersesTestsDevUser5 } from '../../support/perses/99.coo_rbac_perses_user5.cy'; -import { operatorAuthUtils } from '../../support/commands/auth-commands'; +import { nav } from '../../../views/nav'; +import { runCOORBACPersesTestsDevUser5 } from '../../../support/perses/99.coo_rbac_perses_user5.cy'; +import { operatorAuthUtils } from '../../../support/commands/auth-commands'; // Set constants for the operators that need to be installed for tests. // const MCP = { diff --git a/web/cypress/e2e/perses/99.coo_rbac_perses_user6.cy.ts b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user6.cy.ts similarity index 93% rename from web/cypress/e2e/perses/99.coo_rbac_perses_user6.cy.ts rename to web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user6.cy.ts index fc79ca4d8..e3dd785f8 100644 --- a/web/cypress/e2e/perses/99.coo_rbac_perses_user6.cy.ts +++ b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user6.cy.ts @@ -1,6 +1,6 @@ -import { nav } from '../../views/nav'; -import { runCOORBACPersesTestsDevUser6 } from '../../support/perses/99.coo_rbac_perses_user6.cy'; -import { operatorAuthUtils } from '../../support/commands/auth-commands'; +import { nav } from '../../../views/nav'; +import { runCOORBACPersesTestsDevUser6 } from '../../../support/perses/99.coo_rbac_perses_user6.cy'; +import { operatorAuthUtils } from '../../../support/commands/auth-commands'; // Set constants for the operators that need to be installed for tests. // const MCP = { diff --git a/web/cypress/e2e/monitoring/00.bvt_admin.cy.ts b/web/cypress/e2e/shared/admin_perspective_bvt.cy.ts similarity index 100% rename from web/cypress/e2e/monitoring/00.bvt_admin.cy.ts rename to web/cypress/e2e/shared/admin_perspective_bvt.cy.ts diff --git a/web/cypress/e2e/shared/coo_submenus.cy.ts b/web/cypress/e2e/shared/coo_submenus.cy.ts new file mode 100644 index 000000000..b41ab3c4c --- /dev/null +++ b/web/cypress/e2e/shared/coo_submenus.cy.ts @@ -0,0 +1,57 @@ +import { commonPages } from '../../views/common'; +import { nav } from '../../views/nav'; +import { troubleshootingPanelPage } from '../../views/troubleshooting-panel'; + +// Set constants for the operators that need to be installed for tests. +const MCP = { + namespace: Cypress.env('COO_NAMESPACE'), + packageName: 'cluster-observability-operator', + operatorName: 'Cluster Observability Operator', + config: { + kind: 'UIPlugin', + name: 'monitoring', + }, +}; + +const MP = { + namespace: 'openshift-monitoring', + operatorName: 'Cluster Monitoring Operator', +}; + +describe( + 'BVT: COO', + { + tags: [ + '@alerting', + '@cluster-health-analyzer', + '@perses-dashboards', + '@legacy-dashboards', + '@coo', + ], + }, + () => { + before(() => { + cy.beforeBlockCOO(MCP, MP); + }); + + it('1. Admin perspective - Observe Menu', () => { + cy.log('Admin perspective - Observe Menu and verify all submenus'); + cy.reload(true); + cy.wait(10000); + nav.sidenav.clickNavLink(['Observe', 'Alerting']); + commonPages.titleShouldHaveText('Alerting'); + nav.tabs.switchTab('Silences'); + nav.tabs.switchTab('Alerting rules'); + nav.tabs.switchTab('Incidents'); + nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); + commonPages.titleShouldHaveText('Dashboards'); + nav.sidenav.clickNavLink(['Observe', 'Alerting']); + troubleshootingPanelPage.openSignalCorrelation(); + troubleshootingPanelPage.troubleshootingPanelPageShouldBeLoadedEnabled(); + }); + + /** + * TODO: To be replaced by COO validation such as Dashboards (Perses) scenarios + */ + }, +); From 51af2720bfef3a7dda37d9d31c8f76a1b8a0b338 Mon Sep 17 00:00:00 2001 From: PeterYurkovich Date: Tue, 25 Aug 2026 17:33:16 -0400 Subject: [PATCH 2/4] feat: add lint rule for ordering tags --- web/cypress/e2e/alerts/alerts_acm.cy.ts | 2 +- web/cypress/e2e/alerts/alerts_ivt.cy.ts | 2 +- .../alerts/alerts_virtualization_bvt.cy.ts | 2 +- web/cypress/e2e/coo/02.acm_perses.cy.ts | 2 +- web/cypress/e2e/incidents/incidents_e2e.cy.ts | 2 +- .../regression/end_and_resolution.cy.ts | 2 +- .../e2e/incidents/regression/interval.cy.ts | 2 +- ...dashboards_virtualization_regression.cy.ts | 4 +- .../metrics/metrics_virtualization_ivt.cy.ts | 4 +- .../perses_dashboards_datasources.cy.ts | 2 +- ...perses_dashboards_virtualization_ivt.cy.ts | 2 +- web/cypress/e2e/shared/coo_submenus.cy.ts | 2 +- .../virtualization/02.coo_ivt_metrics_2.cy.ts | 8 +- web/cypress/support/test-tags.d.ts | 32 ----- web/cypress/support/test-tags.ts | 27 +++++ web/eslint-rules/cypress-tag-order.spec.ts | 76 ++++++++++++ web/eslint-rules/cypress-tag-order.ts | 112 ++++++++++++++++++ web/eslint-rules/cypress-tags-array.spec.ts | 25 ++++ web/eslint-rules/cypress-tags-array.ts | 47 ++++++++ web/eslint.config.ts | 17 +++ 20 files changed, 322 insertions(+), 50 deletions(-) delete mode 100644 web/cypress/support/test-tags.d.ts create mode 100644 web/cypress/support/test-tags.ts create mode 100644 web/eslint-rules/cypress-tag-order.spec.ts create mode 100644 web/eslint-rules/cypress-tag-order.ts create mode 100644 web/eslint-rules/cypress-tags-array.spec.ts create mode 100644 web/eslint-rules/cypress-tags-array.ts diff --git a/web/cypress/e2e/alerts/alerts_acm.cy.ts b/web/cypress/e2e/alerts/alerts_acm.cy.ts index fd200d879..f7846f6cf 100644 --- a/web/cypress/e2e/alerts/alerts_acm.cy.ts +++ b/web/cypress/e2e/alerts/alerts_acm.cy.ts @@ -24,7 +24,7 @@ const MP = { }; const expectedAlerts = ['Watchdog', 'Watchdog-spoke', 'ClusterCPUHealth-jb']; -describe('ACM Alerting UI', { tags: ['@alerting', '@acm-alerting', '@coo'] }, () => { +describe('ACM Alerting UI', { tags: ['@acm-alerting', '@alerting', '@coo'] }, () => { before(() => { cy.beforeBlockACM(MCP, MP); }); diff --git a/web/cypress/e2e/alerts/alerts_ivt.cy.ts b/web/cypress/e2e/alerts/alerts_ivt.cy.ts index b700b9b29..81515638a 100644 --- a/web/cypress/e2e/alerts/alerts_ivt.cy.ts +++ b/web/cypress/e2e/alerts/alerts_ivt.cy.ts @@ -35,7 +35,7 @@ const KBV = { describe( 'Regression: Monitoring - Alerts (Virtualization)', - { tags: ['@alerting', '@slow', '@virtualization', '@coo'] }, + { tags: ['@alerting', '@coo', '@slow', '@virtualization'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP); diff --git a/web/cypress/e2e/alerts/alerts_virtualization_bvt.cy.ts b/web/cypress/e2e/alerts/alerts_virtualization_bvt.cy.ts index b37ddbfd9..af4954799 100644 --- a/web/cypress/e2e/alerts/alerts_virtualization_bvt.cy.ts +++ b/web/cypress/e2e/alerts/alerts_virtualization_bvt.cy.ts @@ -36,7 +36,7 @@ const KBV = { describe( 'IVT: Monitoring + Virtualization', - { tags: ['@metrics', '@alerting', '@slow', '@virtualization', '@coo'] }, + { tags: ['@alerting', '@metrics', '@coo', '@slow', '@virtualization'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP); diff --git a/web/cypress/e2e/coo/02.acm_perses.cy.ts b/web/cypress/e2e/coo/02.acm_perses.cy.ts index e0c82483b..c243e7b45 100644 --- a/web/cypress/e2e/coo/02.acm_perses.cy.ts +++ b/web/cypress/e2e/coo/02.acm_perses.cy.ts @@ -18,7 +18,7 @@ const MP = { operatorName: 'Cluster Monitoring Operator', }; -describe('ACM - Perses', { tags: ['@coo', '@perses-dashboards'] }, () => { +describe('ACM - Perses', { tags: ['@perses-dashboards', '@coo'] }, () => { before(() => { cy.beforeBlockACM(MCP, MP); cy.switchPerspective('Core platform'); diff --git a/web/cypress/e2e/incidents/incidents_e2e.cy.ts b/web/cypress/e2e/incidents/incidents_e2e.cy.ts index f6cf6664d..fd0f6a75f 100644 --- a/web/cypress/e2e/incidents/incidents_e2e.cy.ts +++ b/web/cypress/e2e/incidents/incidents_e2e.cy.ts @@ -20,7 +20,7 @@ const MP = { operatorName: 'Cluster Monitoring Operator', }; -describe('BVT: Incidents - e2e', { tags: ['@slow', '@cluster-health-analyzer', '@coo'] }, () => { +describe('BVT: Incidents - e2e', { tags: ['@cluster-health-analyzer', '@coo', '@slow'] }, () => { let currentAlertName: string; before(() => { diff --git a/web/cypress/e2e/incidents/regression/end_and_resolution.cy.ts b/web/cypress/e2e/incidents/regression/end_and_resolution.cy.ts index 3496ec6ca..f1eb8ec51 100644 --- a/web/cypress/e2e/incidents/regression/end_and_resolution.cy.ts +++ b/web/cypress/e2e/incidents/regression/end_and_resolution.cy.ts @@ -36,7 +36,7 @@ const MP = { describe( 'Regression: Time-Based Alert Resolution (E2E with Firing Alerts)', - { tags: ['@cluster-health-analyzer', '@slow', '@coo'] }, + { tags: ['@cluster-health-analyzer', '@coo', '@slow'] }, () => { let currentAlertName: string; diff --git a/web/cypress/e2e/incidents/regression/interval.cy.ts b/web/cypress/e2e/incidents/regression/interval.cy.ts index e14001afb..41d94117d 100644 --- a/web/cypress/e2e/incidents/regression/interval.cy.ts +++ b/web/cypress/e2e/incidents/regression/interval.cy.ts @@ -30,7 +30,7 @@ const MP = { describe( 'Regression: Mixed Severity Interval Boundary Times', - { tags: ['@cluster-health-analyzer', '@xfail', '@coo'] }, + { tags: ['@cluster-health-analyzer', '@coo', '@xfail'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP, { dashboards: false, troubleshootingPanel: false }); diff --git a/web/cypress/e2e/legacy-dashboards/legacy_dashboards_virtualization_regression.cy.ts b/web/cypress/e2e/legacy-dashboards/legacy_dashboards_virtualization_regression.cy.ts index cea866733..2d3923386 100644 --- a/web/cypress/e2e/legacy-dashboards/legacy_dashboards_virtualization_regression.cy.ts +++ b/web/cypress/e2e/legacy-dashboards/legacy_dashboards_virtualization_regression.cy.ts @@ -34,7 +34,7 @@ const KBV = { describe( 'Regression: Monitoring - Legacy Dashboards (Virtualization)', - { tags: ['@legacy-dashboards', '@slow', '@virtualization', '@coo'] }, + { tags: ['@legacy-dashboards', '@coo', '@slow', '@virtualization'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP); @@ -62,7 +62,7 @@ describe( describe( 'Regression: Monitoring - Legacy Dashboards Namespaced (Virtualization)', - { tags: ['@legacy-dashboards', '@slow', '@virtualization', '@coo'] }, + { tags: ['@legacy-dashboards', '@coo', '@slow', '@virtualization'] }, () => { beforeEach(() => { cy.visit('/'); diff --git a/web/cypress/e2e/metrics/metrics_virtualization_ivt.cy.ts b/web/cypress/e2e/metrics/metrics_virtualization_ivt.cy.ts index c9e97f79d..3b85db247 100644 --- a/web/cypress/e2e/metrics/metrics_virtualization_ivt.cy.ts +++ b/web/cypress/e2e/metrics/metrics_virtualization_ivt.cy.ts @@ -37,7 +37,7 @@ const KBV = { describe( 'Regression: Monitoring - Metrics (Virtualization)', - { tags: ['@metrics', '@slow', '@virtualization', '@coo'] }, + { tags: ['@metrics', '@coo', '@slow', '@virtualization'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP); @@ -67,7 +67,7 @@ describe( describe( 'Regression: Monitoring - Metrics Namespaced (Virtualization)', - { tags: ['@metrics', '@slow', '@virtualization', '@coo'] }, + { tags: ['@metrics', '@coo', '@slow', '@virtualization'] }, () => { beforeEach(() => { cy.visit('/'); diff --git a/web/cypress/e2e/perses-dashboards/perses_dashboards_datasources.cy.ts b/web/cypress/e2e/perses-dashboards/perses_dashboards_datasources.cy.ts index 846657280..1bff57b53 100644 --- a/web/cypress/e2e/perses-dashboards/perses_dashboards_datasources.cy.ts +++ b/web/cypress/e2e/perses-dashboards/perses_dashboards_datasources.cy.ts @@ -43,7 +43,7 @@ const CLO = { describe( 'COO - Dashboards (Perses) - Perses Global Datasources with Tempo and Loki', - { tags: ['@perses-dashboards', '@xfail', '@coo'] }, + { tags: ['@perses-dashboards', '@coo', '@xfail'] }, () => { before(() => { cy.beforeBlockTempo(TEMPO); diff --git a/web/cypress/e2e/perses-dashboards/perses_dashboards_virtualization_ivt.cy.ts b/web/cypress/e2e/perses-dashboards/perses_dashboards_virtualization_ivt.cy.ts index 16c0172fd..4d04dea10 100644 --- a/web/cypress/e2e/perses-dashboards/perses_dashboards_virtualization_ivt.cy.ts +++ b/web/cypress/e2e/perses-dashboards/perses_dashboards_virtualization_ivt.cy.ts @@ -35,7 +35,7 @@ const KBV = { describe( 'IVT: COO - Dashboards (Perses) - Virtualization perspective', - { tags: ['@perses-dashboards', '@slow', '@virtualization', '@coo'] }, + { tags: ['@perses-dashboards', '@coo', '@slow', '@virtualization'] }, () => { before(() => { diff --git a/web/cypress/e2e/shared/coo_submenus.cy.ts b/web/cypress/e2e/shared/coo_submenus.cy.ts index b41ab3c4c..f3d94f499 100644 --- a/web/cypress/e2e/shared/coo_submenus.cy.ts +++ b/web/cypress/e2e/shared/coo_submenus.cy.ts @@ -24,8 +24,8 @@ describe( tags: [ '@alerting', '@cluster-health-analyzer', - '@perses-dashboards', '@legacy-dashboards', + '@perses-dashboards', '@coo', ], }, diff --git a/web/cypress/e2e/virtualization/02.coo_ivt_metrics_2.cy.ts b/web/cypress/e2e/virtualization/02.coo_ivt_metrics_2.cy.ts index 46ebf954a..755f97d28 100644 --- a/web/cypress/e2e/virtualization/02.coo_ivt_metrics_2.cy.ts +++ b/web/cypress/e2e/virtualization/02.coo_ivt_metrics_2.cy.ts @@ -35,7 +35,7 @@ const KBV = { describe( 'Installation: COO and setting up Monitoring Plugin', - { tags: ['@virtualization', '@slow', '@coo'] }, + { tags: ['@coo', '@slow', '@virtualization'] }, () => { before(() => { cy.beforeBlockCOO(MCP, MP); @@ -49,7 +49,7 @@ describe( describe( 'IVT: Monitoring UIPlugin + Virtualization', - { tags: ['@virtualization', '@slow', '@coo'] }, + { tags: ['@coo', '@slow', '@virtualization'] }, () => { before(() => { cy.beforeBlockVirtualization(KBV); @@ -65,7 +65,7 @@ describe( describe( 'Regression: Monitoring - Metrics (Virtualization)', - { tags: ['@metrics', '@slow', '@virtualization', '@coo'] }, + { tags: ['@metrics', '@coo', '@slow', '@virtualization'] }, () => { beforeEach(() => { cy.visit('/'); @@ -87,7 +87,7 @@ describe( describe( 'Regression: Monitoring - Metrics Namespaced (Virtualization)', - { tags: ['@metrics', '@slow', '@virtualization', '@coo'] }, + { tags: ['@metrics', '@coo', '@slow', '@virtualization'] }, () => { beforeEach(() => { cy.visit('/'); diff --git a/web/cypress/support/test-tags.d.ts b/web/cypress/support/test-tags.d.ts deleted file mode 100644 index 4207b1824..000000000 --- a/web/cypress/support/test-tags.d.ts +++ /dev/null @@ -1,32 +0,0 @@ -type BasicTag = '@flaky' | '@xfail' | '@slow'; - -type HighLevelComponentTag = - | '@coo' - | '@virtualization' - | '@ols' - | '@acm-alerting' - | '@alerting' - | '@legacy-dashboards' - | '@metrics' - | '@targets' - | '@perses-dashboards' - | '@cluster-health-analyzer'; - -type SpecificFeatureTag = `@${string}-${string}`; - -type JiraTag = `@JIRA-${string}`; - -type AllowedTag = BasicTag | HighLevelComponentTag | SpecificFeatureTag | JiraTag; -type TestTags = AllowedTag | AllowedTag[]; - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -declare namespace Cypress { - interface SuiteConfigOverrides { - tags?: TestTags; - } - interface TestConfigOverrides { - tags?: TestTags; - } -} - -export {}; diff --git a/web/cypress/support/test-tags.ts b/web/cypress/support/test-tags.ts new file mode 100644 index 000000000..fd18b998c --- /dev/null +++ b/web/cypress/support/test-tags.ts @@ -0,0 +1,27 @@ +export const MODIFIER_TAGS = [ + '@flaky', + '@xfail', + '@slow', + '@coo', + '@virtualization', + '@ols', +] as const; + +export const HIGH_LEVEL_COMPONENT_TAGS = [ + '@acm-alerting', + '@alerting', + '@legacy-dashboards', + '@metrics', + '@targets', + '@perses-dashboards', + '@cluster-health-analyzer', +] as const; + +export type BasicTag = (typeof MODIFIER_TAGS)[number]; + +export type HighLevelComponentTag = (typeof HIGH_LEVEL_COMPONENT_TAGS)[number]; + +export type SpecificFeatureTag = `@${string}-${string}`; + +export type AllowedTag = BasicTag | HighLevelComponentTag | SpecificFeatureTag; +export type TestTags = AllowedTag | AllowedTag[]; diff --git a/web/eslint-rules/cypress-tag-order.spec.ts b/web/eslint-rules/cypress-tag-order.spec.ts new file mode 100644 index 000000000..c31ab6baa --- /dev/null +++ b/web/eslint-rules/cypress-tag-order.spec.ts @@ -0,0 +1,76 @@ +import { RuleTester } from 'eslint'; +import { classifyTag, cypressTagOrder, sortTags } from './cypress-tag-order'; + +describe('classifyTag', () => { + it('classifies modifier tags', () => { + expect(classifyTag('@slow')).toBe('modifier'); + expect(classifyTag('@smoke')).toBe('modifier'); + }); + + it('classifies high level component tags as features', () => { + expect(classifyTag('@monitoring')).toBe('feature'); + expect(classifyTag('@cluster-health-analyzer')).toBe('feature'); + }); + + it('classifies @x-y specific feature tags as features', () => { + expect(classifyTag('@perses-dev')).toBe('feature'); + expect(classifyTag('@JIRA-1234')).toBe('feature'); + }); + + it('classifies unrecognized tags as unknown', () => { + expect(classifyTag('@perses')).toBe('unknown'); + expect(classifyTag('@acm')).toBe('unknown'); + expect(classifyTag('@ols')).toBe('unknown'); + }); +}); + +describe('sortTags', () => { + it('sorts features alphabetically before modifiers alphabetically', () => { + expect(sortTags(['@slow', '@virtualization', '@demo', '@alerts'])).toEqual([ + '@alerts', + '@virtualization', + '@demo', + '@slow', + ]); + }); + + it('places unknown tags last', () => { + expect(sortTags(['@slow', '@perses', '@alerts'])).toEqual(['@alerts', '@slow', '@perses']); + }); +}); + +const ruleTester = new RuleTester({ + languageOptions: { ecmaVersion: 2021, sourceType: 'module' }, +}); + +ruleTester.run('cypress-tag-order', cypressTagOrder, { + valid: [ + { code: "describe('x', { tags: ['@alerts', '@virtualization', '@demo', '@slow'] }, () => {})" }, + { code: "describe('x', { tags: ['@monitoring'] }, () => {})" }, + { code: "describe('x', { tags: ['@slow'] }, () => {})" }, + { code: "it('x', { tags: ['@perses-dev', '@slow'] }, () => {})" }, + { code: "it('x', { tags: ['@alerts', '@coo'] }, () => {})" }, + ], + invalid: [ + { + code: "describe('x', { tags: ['@slow', '@alerts'] }, () => {})", + output: "describe('x', { tags: ['@alerts', '@slow'] }, () => {})", + errors: [{ messageId: 'tagsNotSorted' }], + }, + { + code: "describe('x', { tags: ['@virtualization', '@alerts'] }, () => {})", + output: "describe('x', { tags: ['@alerts', '@virtualization'] }, () => {})", + errors: [{ messageId: 'tagsNotSorted' }], + }, + { + code: "it('x', { tags: ['@slow', '@demo'] }, () => {})", + output: "it('x', { tags: ['@demo', '@slow'] }, () => {})", + errors: [{ messageId: 'tagsNotSorted' }], + }, + { + code: "describe('x', { tags: ['@perses', '@alerts'] }, () => {})", + output: "describe('x', { tags: ['@alerts', '@perses'] }, () => {})", + errors: [{ messageId: 'tagsNotSorted' }, { messageId: 'unknownTag' }], + }, + ], +}); diff --git a/web/eslint-rules/cypress-tag-order.ts b/web/eslint-rules/cypress-tag-order.ts new file mode 100644 index 000000000..5a51ea4b5 --- /dev/null +++ b/web/eslint-rules/cypress-tag-order.ts @@ -0,0 +1,112 @@ +import type { Rule } from 'eslint'; +import type { ArrayExpression, Property } from 'estree'; +import { HIGH_LEVEL_COMPONENT_TAGS, MODIFIER_TAGS } from '../cypress/support/test-tags'; + +const MODIFIER_SET: ReadonlySet = new Set(MODIFIER_TAGS); +const FEATURE_SET: ReadonlySet = new Set(HIGH_LEVEL_COMPONENT_TAGS); +const SPECIFIC_FEATURE_RE = /^@[^\s-]+-[^\s]+$/; + +export type TagKind = 'feature' | 'modifier' | 'unknown'; + +export function classifyTag(tag: string): TagKind { + if (MODIFIER_SET.has(tag)) { + return 'modifier'; + } + if (FEATURE_SET.has(tag) || SPECIFIC_FEATURE_RE.test(tag)) { + return 'feature'; + } + return 'unknown'; +} + +export function sortTags(tags: string[]): string[] { + const features = tags.filter((t) => classifyTag(t) === 'feature').sort(); + const modifiers = tags.filter((t) => classifyTag(t) === 'modifier').sort(); + const unknowns = tags.filter((t) => classifyTag(t) === 'unknown'); + return [...features, ...modifiers, ...unknowns]; +} + +function isTagsProperty(node: Property): boolean { + const key = node.key; + if (key.type === 'Identifier') { + return key.name === 'tags'; + } + if (key.type === 'Literal') { + return key.value === 'tags'; + } + return false; +} + +export const cypressTagOrder: Rule.RuleModule = { + meta: { + type: 'suggestion', + fixable: 'code', + docs: { + description: + 'Sort Cypress tags: feature tags alphabetically, then modifier tags alphabetically', + }, + schema: [], + messages: { + unknownTag: "Tag '{{tag}}' is not a recognized tag. See cypress/support/test-tags.ts.", + tagsNotSorted: + 'Cypress tags must be sorted: feature tags alphabetically, then modifier tags ' + + 'alphabetically. Expected: [{{expected}}].', + }, + }, + create(context) { + const sourceCode = context.sourceCode ?? context.getSourceCode(); + + return { + Property(node: Property) { + if (!isTagsProperty(node) || node.value.type !== 'ArrayExpression') { + return; + } + const array = node.value as ArrayExpression; + const elements = array.elements; + + const stringElements = elements.filter( + (el): el is ArrayExpression['elements'][number] & { type: 'Literal' } => + el != null && el.type === 'Literal' && typeof el.value === 'string', + ); + if (stringElements.length !== elements.length || stringElements.length === 0) { + return; + } + + const tags = stringElements.map((el) => String((el as { value: string }).value)); + + for (const [index, tag] of tags.entries()) { + if (classifyTag(tag) === 'unknown') { + context.report({ + node: stringElements[index], + messageId: 'unknownTag', + data: { tag }, + }); + } + } + + const sorted = sortTags(tags); + if (tags.some((tag, i) => tag !== sorted[i])) { + context.report({ + node: array, + messageId: 'tagsNotSorted', + data: { expected: sorted.map((t) => `'${t}'`).join(', ') }, + fix(fixer) { + const rawByTag = new Map(); + stringElements.forEach((el, i) => { + rawByTag.set(tags[i], sourceCode.getText(el)); + }); + const used = new Map(); + const newText = sorted + .map((tag) => { + const count = used.get(tag) ?? 0; + used.set(tag, count + 1); + return rawByTag.get(tag) ?? `'${tag}'`; + }) + .join(', '); + return fixer.replaceText(array, `[${newText}]`); + }, + }); + } + }, + }; + }, +}; diff --git a/web/eslint-rules/cypress-tags-array.spec.ts b/web/eslint-rules/cypress-tags-array.spec.ts new file mode 100644 index 000000000..b74f6e374 --- /dev/null +++ b/web/eslint-rules/cypress-tags-array.spec.ts @@ -0,0 +1,25 @@ +import { RuleTester } from 'eslint'; +import { cypressTagsArray } from './cypress-tags-array'; + +const ruleTester = new RuleTester({ + languageOptions: { ecmaVersion: 2021, sourceType: 'module' }, +}); + +ruleTester.run('cypress-tags-array', cypressTagsArray, { + valid: [ + { code: "describe('x', { tags: ['@monitoring'] }, () => {})" }, + { code: "describe('x', { tags: ['@alerts', '@slow'] }, () => {})" }, + ], + invalid: [ + { + code: "describe('x', { tags: '@monitoring' }, () => {})", + output: "describe('x', { tags: ['@monitoring'] }, () => {})", + errors: [{ messageId: 'tagsMustBeArray' }], + }, + { + code: "it('x', { tags: '@slow' }, () => {})", + output: "it('x', { tags: ['@slow'] }, () => {})", + errors: [{ messageId: 'tagsMustBeArray' }], + }, + ], +}); diff --git a/web/eslint-rules/cypress-tags-array.ts b/web/eslint-rules/cypress-tags-array.ts new file mode 100644 index 000000000..53c081798 --- /dev/null +++ b/web/eslint-rules/cypress-tags-array.ts @@ -0,0 +1,47 @@ +import type { Rule } from 'eslint'; +import type { Property } from 'estree'; + +function isTagsProperty(node: Property): boolean { + const key = node.key; + if (key.type === 'Identifier') { + return key.name === 'tags'; + } + if (key.type === 'Literal') { + return key.value === 'tags'; + } + return false; +} + +export const cypressTagsArray: Rule.RuleModule = { + meta: { + type: 'suggestion', + fixable: 'code', + docs: { + description: 'Require Cypress tags to be declared as an array, even for a single tag', + }, + schema: [], + messages: { + tagsMustBeArray: 'Cypress tags must be declared as an array (e.g. tags: [{{value}}]).', + }, + }, + create(context) { + const sourceCode = context.sourceCode ?? context.getSourceCode(); + + return { + Property(node: Property) { + if (!isTagsProperty(node) || node.value.type === 'ArrayExpression') { + return; + } + const valueText = sourceCode.getText(node.value); + context.report({ + node: node.value, + messageId: 'tagsMustBeArray', + data: { value: valueText }, + fix(fixer) { + return fixer.replaceText(node.value, `[${valueText}]`); + }, + }); + }, + }; + }, +}; diff --git a/web/eslint.config.ts b/web/eslint.config.ts index 9a78fa4a2..22cb2e747 100644 --- a/web/eslint.config.ts +++ b/web/eslint.config.ts @@ -13,6 +13,8 @@ import importPlugin from 'eslint-plugin-import'; import { importBoundaryZones } from './eslint-rules/import-boundary-zones'; import { fileNaming } from './eslint-rules/file-naming'; import { requireFeatureOwners } from './eslint-rules/require-feature-owners'; +import { cypressTagOrder } from './eslint-rules/cypress-tag-order'; +import { cypressTagsArray } from './eslint-rules/cypress-tags-array'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -193,6 +195,21 @@ export default defineConfig([ 'local-rules/require-feature-owners': 'error', }, }, + { + files: ['cypress/**/*.ts', 'cypress/**/*.tsx'], + plugins: { + 'local-rules': { + rules: { + 'cypress-tag-order': cypressTagOrder, + 'cypress-tags-array': cypressTagsArray, + }, + } as any, + }, + rules: { + 'local-rules/cypress-tag-order': 'error', + 'local-rules/cypress-tags-array': 'error', + }, + }, { files: ['src/features/**/*.ts', 'src/features/**/*.tsx'], plugins: { From 906179356623a847de90096fc0cabd4d204fefbe Mon Sep 17 00:00:00 2001 From: PeterYurkovich Date: Tue, 25 Aug 2026 17:40:32 -0400 Subject: [PATCH 3/4] fix: wrap up loose comments and fix coderabbit suggestion --- .../metrics/metrics_virtualization_ivt.cy.ts | 185 +++++++++--------- ...perses_dashboards_virtualization_ivt.cy.ts | 1 - .../rbac/perses_dashboards_user3.cy.ts | 1 - 3 files changed, 89 insertions(+), 98 deletions(-) diff --git a/web/cypress/e2e/metrics/metrics_virtualization_ivt.cy.ts b/web/cypress/e2e/metrics/metrics_virtualization_ivt.cy.ts index 3b85db247..f4251c370 100644 --- a/web/cypress/e2e/metrics/metrics_virtualization_ivt.cy.ts +++ b/web/cypress/e2e/metrics/metrics_virtualization_ivt.cy.ts @@ -35,106 +35,99 @@ const KBV = { }, }; -describe( - 'Regression: Monitoring - Metrics (Virtualization)', - { tags: ['@metrics', '@coo', '@slow', '@virtualization'] }, - () => { - before(() => { - cy.beforeBlockCOO(MCP, MP); - cy.log('Installation: COO and setting up Monitoring Plugin'); - cy.beforeBlockVirtualization(KBV); - cy.log('Virtualization perspective - Observe Menu and verify all submenus'); - cy.switchPerspective('Virtualization'); - guidedTour.closeKubevirtTour(); - }); - beforeEach(() => { - cy.visit('/'); - cy.validateLogin(); - cy.switchPerspective('Virtualization'); - guidedTour.closeKubevirtTour(); - alerts.getWatchdogAlert(); - nav.sidenav.clickNavLink(['Observe', 'Metrics']); - commonPages.titleShouldHaveText('Metrics'); - cy.changeNamespace('All Projects'); - alerts.getWatchdogAlert(); - }); +describe('Regression: Monitoring - Metrics (Virtualization)', () => { + before(() => { + cy.beforeBlockCOO(MCP, MP); + cy.log('Installation: COO and setting up Monitoring Plugin'); + cy.beforeBlockVirtualization(KBV); + cy.log('Virtualization perspective - Observe Menu and verify all submenus'); + }); - runAllRegressionMetricsTests1({ - name: 'Virtualization', - }); - }, -); + describe( + 'Regression: Monitoring - Metrics (Virtualization)', + { tags: ['@metrics', '@coo', '@slow', '@virtualization'] }, + () => { + beforeEach(() => { + cy.visit('/'); + cy.validateLogin(); + cy.switchPerspective('Virtualization'); + guidedTour.closeKubevirtTour(); + alerts.getWatchdogAlert(); + nav.sidenav.clickNavLink(['Observe', 'Metrics']); + commonPages.titleShouldHaveText('Metrics'); + cy.changeNamespace('All Projects'); + alerts.getWatchdogAlert(); + }); -describe( - 'Regression: Monitoring - Metrics Namespaced (Virtualization)', - { tags: ['@metrics', '@coo', '@slow', '@virtualization'] }, - () => { - beforeEach(() => { - cy.visit('/'); - cy.validateLogin(); - cy.switchPerspective('Virtualization'); - guidedTour.closeKubevirtTour(); - alerts.getWatchdogAlert(); - nav.sidenav.clickNavLink(['Observe', 'Metrics']); - commonPages.titleShouldHaveText('Metrics'); - cy.changeNamespace(MP.namespace); - alerts.getWatchdogAlert(); - }); + runAllRegressionMetricsTests1({ + name: 'Virtualization', + }); + }, + ); - runAllRegressionMetricsTestsNamespace1({ - name: 'Virtualization', - }); - }, -); + describe( + 'Regression: Monitoring - Metrics Namespaced (Virtualization)', + { tags: ['@metrics', '@coo', '@slow', '@virtualization'] }, + () => { + beforeEach(() => { + cy.visit('/'); + cy.validateLogin(); + cy.switchPerspective('Virtualization'); + guidedTour.closeKubevirtTour(); + alerts.getWatchdogAlert(); + nav.sidenav.clickNavLink(['Observe', 'Metrics']); + commonPages.titleShouldHaveText('Metrics'); + cy.changeNamespace(MP.namespace); + alerts.getWatchdogAlert(); + }); -describe( - 'Regression: Monitoring - Metrics (Virtualization)', - { tags: ['@metrics', '@slow', '@virtualization'] }, - () => { - before(() => { - cy.beforeBlockCOO(MCP, MP); - cy.log('Installation: COO and setting up Monitoring Plugin'); - cy.beforeBlockVirtualization(KBV); - cy.log('Virtualization perspective - Observe Menu and verify all submenus'); - cy.switchPerspective('Virtualization', 'Fleet virtualization'); - guidedTour.closeKubevirtTour(); - }); - beforeEach(() => { - cy.visit('/'); - cy.validateLogin(); - cy.switchPerspective('Virtualization', 'Fleet virtualization'); - guidedTour.closeKubevirtTour(); - alerts.getWatchdogAlert(); - nav.sidenav.clickNavLink(['Observe', 'Metrics']); - commonPages.titleShouldHaveText('Metrics'); - cy.changeNamespace('All Projects'); - alerts.getWatchdogAlert(); - }); + runAllRegressionMetricsTestsNamespace1({ + name: 'Virtualization', + }); + }, + ); - runAllRegressionMetricsTests2({ - name: 'Virtualization', - }); - }, -); + describe( + 'Regression: Monitoring - Metrics (Virtualization)', + { tags: ['@metrics', '@slow', '@virtualization'] }, + () => { + beforeEach(() => { + cy.visit('/'); + cy.validateLogin(); + cy.switchPerspective('Virtualization', 'Fleet virtualization'); + guidedTour.closeKubevirtTour(); + alerts.getWatchdogAlert(); + nav.sidenav.clickNavLink(['Observe', 'Metrics']); + commonPages.titleShouldHaveText('Metrics'); + cy.changeNamespace('All Projects'); + alerts.getWatchdogAlert(); + }); -describe( - 'Regression: Monitoring - Metrics Namespaced (Virtualization)', - { tags: ['@metrics', '@slow', '@virtualization'] }, - () => { - beforeEach(() => { - cy.visit('/'); - cy.validateLogin(); - cy.switchPerspective('Virtualization', 'Fleet virtualization'); - guidedTour.closeKubevirtTour(); - alerts.getWatchdogAlert(); - nav.sidenav.clickNavLink(['Observe', 'Metrics']); - commonPages.titleShouldHaveText('Metrics'); - cy.changeNamespace(MP.namespace); - alerts.getWatchdogAlert(); - }); + runAllRegressionMetricsTests2({ + name: 'Virtualization', + }); + }, + ); - runAllRegressionMetricsTestsNamespace2({ - name: 'Virtualization', - }); - }, -); + describe( + 'Regression: Monitoring - Metrics Namespaced (Virtualization)', + { tags: ['@metrics', '@slow', '@virtualization'] }, + () => { + beforeEach(() => { + cy.visit('/'); + cy.validateLogin(); + cy.switchPerspective('Virtualization', 'Fleet virtualization'); + guidedTour.closeKubevirtTour(); + alerts.getWatchdogAlert(); + nav.sidenav.clickNavLink(['Observe', 'Metrics']); + commonPages.titleShouldHaveText('Metrics'); + cy.changeNamespace(MP.namespace); + alerts.getWatchdogAlert(); + }); + + runAllRegressionMetricsTestsNamespace2({ + name: 'Virtualization', + }); + }, + ); +}); diff --git a/web/cypress/e2e/perses-dashboards/perses_dashboards_virtualization_ivt.cy.ts b/web/cypress/e2e/perses-dashboards/perses_dashboards_virtualization_ivt.cy.ts index 4d04dea10..9afbaaa66 100644 --- a/web/cypress/e2e/perses-dashboards/perses_dashboards_virtualization_ivt.cy.ts +++ b/web/cypress/e2e/perses-dashboards/perses_dashboards_virtualization_ivt.cy.ts @@ -1,4 +1,3 @@ -// Not finished import { nav } from '../../views/nav'; import { runBVTCOOPersesTests1 } from '../../support/perses/00.coo_bvt_perses_admin.cy'; import { guidedTour } from '../../views/tour'; diff --git a/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user3.cy.ts b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user3.cy.ts index b099c2feb..c997985f6 100644 --- a/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user3.cy.ts +++ b/web/cypress/e2e/perses-dashboards/rbac/perses_dashboards_user3.cy.ts @@ -71,7 +71,6 @@ describe( beforeEach(() => { cy.switchPerspective('Core platform'); - // Why do we check Dashboards first? nav.sidenav.clickNavLink(['Observe', 'Dashboards']); cy.wait(2000); nav.sidenav.clickNavLink(['Observe', 'Dashboards (Perses)']); From 64cd42518020e1bac7cc4863dc29f5e365c7cc31 Mon Sep 17 00:00:00 2001 From: PeterYurkovich Date: Tue, 25 Aug 2026 18:26:44 -0400 Subject: [PATCH 4/4] fix: unit tests --- web/eslint-rules/cypress-tag-order.spec.ts | 42 +++++++++++--------- web/eslint-rules/cypress-tag-order.ts | 18 +++------ web/eslint-rules/cypress-tags-array.spec.ts | 1 + web/eslint-rules/cypress-tags-array.ts | 18 +++------ web/eslint-rules/cypress-tags-helper.ts | 43 +++++++++++++++++++++ 5 files changed, 79 insertions(+), 43 deletions(-) create mode 100644 web/eslint-rules/cypress-tags-helper.ts diff --git a/web/eslint-rules/cypress-tag-order.spec.ts b/web/eslint-rules/cypress-tag-order.spec.ts index c31ab6baa..053594ebf 100644 --- a/web/eslint-rules/cypress-tag-order.spec.ts +++ b/web/eslint-rules/cypress-tag-order.spec.ts @@ -4,11 +4,14 @@ import { classifyTag, cypressTagOrder, sortTags } from './cypress-tag-order'; describe('classifyTag', () => { it('classifies modifier tags', () => { expect(classifyTag('@slow')).toBe('modifier'); - expect(classifyTag('@smoke')).toBe('modifier'); + expect(classifyTag('@coo')).toBe('modifier'); + expect(classifyTag('@virtualization')).toBe('modifier'); + expect(classifyTag('@ols')).toBe('modifier'); }); it('classifies high level component tags as features', () => { - expect(classifyTag('@monitoring')).toBe('feature'); + expect(classifyTag('@alerting')).toBe('feature'); + expect(classifyTag('@metrics')).toBe('feature'); expect(classifyTag('@cluster-health-analyzer')).toBe('feature'); }); @@ -20,22 +23,22 @@ describe('classifyTag', () => { it('classifies unrecognized tags as unknown', () => { expect(classifyTag('@perses')).toBe('unknown'); expect(classifyTag('@acm')).toBe('unknown'); - expect(classifyTag('@ols')).toBe('unknown'); + expect(classifyTag('@monitoring')).toBe('unknown'); }); }); describe('sortTags', () => { it('sorts features alphabetically before modifiers alphabetically', () => { - expect(sortTags(['@slow', '@virtualization', '@demo', '@alerts'])).toEqual([ - '@alerts', - '@virtualization', - '@demo', + expect(sortTags(['@slow', '@metrics', '@coo', '@alerting'])).toEqual([ + '@alerting', + '@metrics', + '@coo', '@slow', ]); }); it('places unknown tags last', () => { - expect(sortTags(['@slow', '@perses', '@alerts'])).toEqual(['@alerts', '@slow', '@perses']); + expect(sortTags(['@slow', '@perses', '@alerting'])).toEqual(['@alerting', '@slow', '@perses']); }); }); @@ -45,31 +48,32 @@ const ruleTester = new RuleTester({ ruleTester.run('cypress-tag-order', cypressTagOrder, { valid: [ - { code: "describe('x', { tags: ['@alerts', '@virtualization', '@demo', '@slow'] }, () => {})" }, - { code: "describe('x', { tags: ['@monitoring'] }, () => {})" }, + { code: "describe('x', { tags: ['@alerting', '@metrics', '@coo', '@slow'] }, () => {})" }, + { code: "describe('x', { tags: ['@alerting'] }, () => {})" }, { code: "describe('x', { tags: ['@slow'] }, () => {})" }, { code: "it('x', { tags: ['@perses-dev', '@slow'] }, () => {})" }, - { code: "it('x', { tags: ['@alerts', '@coo'] }, () => {})" }, + { code: "it('x', { tags: ['@alerting', '@coo'] }, () => {})" }, + { code: "const config = { tags: ['@slow', '@alerting'] };" }, ], invalid: [ { - code: "describe('x', { tags: ['@slow', '@alerts'] }, () => {})", - output: "describe('x', { tags: ['@alerts', '@slow'] }, () => {})", + code: "describe('x', { tags: ['@slow', '@alerting'] }, () => {})", + output: "describe('x', { tags: ['@alerting', '@slow'] }, () => {})", errors: [{ messageId: 'tagsNotSorted' }], }, { - code: "describe('x', { tags: ['@virtualization', '@alerts'] }, () => {})", - output: "describe('x', { tags: ['@alerts', '@virtualization'] }, () => {})", + code: "describe('x', { tags: ['@virtualization', '@alerting'] }, () => {})", + output: "describe('x', { tags: ['@alerting', '@virtualization'] }, () => {})", errors: [{ messageId: 'tagsNotSorted' }], }, { - code: "it('x', { tags: ['@slow', '@demo'] }, () => {})", - output: "it('x', { tags: ['@demo', '@slow'] }, () => {})", + code: "it('x', { tags: ['@slow', '@metrics'] }, () => {})", + output: "it('x', { tags: ['@metrics', '@slow'] }, () => {})", errors: [{ messageId: 'tagsNotSorted' }], }, { - code: "describe('x', { tags: ['@perses', '@alerts'] }, () => {})", - output: "describe('x', { tags: ['@alerts', '@perses'] }, () => {})", + code: "describe('x', { tags: ['@perses', '@alerting'] }, () => {})", + output: "describe('x', { tags: ['@alerting', '@perses'] }, () => {})", errors: [{ messageId: 'tagsNotSorted' }, { messageId: 'unknownTag' }], }, ], diff --git a/web/eslint-rules/cypress-tag-order.ts b/web/eslint-rules/cypress-tag-order.ts index 5a51ea4b5..4b95fd9e7 100644 --- a/web/eslint-rules/cypress-tag-order.ts +++ b/web/eslint-rules/cypress-tag-order.ts @@ -1,6 +1,7 @@ import type { Rule } from 'eslint'; import type { ArrayExpression, Property } from 'estree'; import { HIGH_LEVEL_COMPONENT_TAGS, MODIFIER_TAGS } from '../cypress/support/test-tags'; +import { isTagsInCallOptions, isTagsProperty } from './cypress-tags-helper'; const MODIFIER_SET: ReadonlySet = new Set(MODIFIER_TAGS); const FEATURE_SET: ReadonlySet = new Set(HIGH_LEVEL_COMPONENT_TAGS); @@ -25,17 +26,6 @@ export function sortTags(tags: string[]): string[] { return [...features, ...modifiers, ...unknowns]; } -function isTagsProperty(node: Property): boolean { - const key = node.key; - if (key.type === 'Identifier') { - return key.name === 'tags'; - } - if (key.type === 'Literal') { - return key.value === 'tags'; - } - return false; -} - export const cypressTagOrder: Rule.RuleModule = { meta: { type: 'suggestion', @@ -57,7 +47,11 @@ export const cypressTagOrder: Rule.RuleModule = { return { Property(node: Property) { - if (!isTagsProperty(node) || node.value.type !== 'ArrayExpression') { + if ( + !isTagsProperty(node) || + !isTagsInCallOptions(node) || + node.value.type !== 'ArrayExpression' + ) { return; } const array = node.value as ArrayExpression; diff --git a/web/eslint-rules/cypress-tags-array.spec.ts b/web/eslint-rules/cypress-tags-array.spec.ts index b74f6e374..0d9150642 100644 --- a/web/eslint-rules/cypress-tags-array.spec.ts +++ b/web/eslint-rules/cypress-tags-array.spec.ts @@ -9,6 +9,7 @@ ruleTester.run('cypress-tags-array', cypressTagsArray, { valid: [ { code: "describe('x', { tags: ['@monitoring'] }, () => {})" }, { code: "describe('x', { tags: ['@alerts', '@slow'] }, () => {})" }, + { code: "const config = { tags: '@internal' };" }, ], invalid: [ { diff --git a/web/eslint-rules/cypress-tags-array.ts b/web/eslint-rules/cypress-tags-array.ts index 53c081798..23bb400b6 100644 --- a/web/eslint-rules/cypress-tags-array.ts +++ b/web/eslint-rules/cypress-tags-array.ts @@ -1,16 +1,6 @@ import type { Rule } from 'eslint'; import type { Property } from 'estree'; - -function isTagsProperty(node: Property): boolean { - const key = node.key; - if (key.type === 'Identifier') { - return key.name === 'tags'; - } - if (key.type === 'Literal') { - return key.value === 'tags'; - } - return false; -} +import { isTagsInCallOptions, isTagsProperty } from './cypress-tags-helper'; export const cypressTagsArray: Rule.RuleModule = { meta: { @@ -29,7 +19,11 @@ export const cypressTagsArray: Rule.RuleModule = { return { Property(node: Property) { - if (!isTagsProperty(node) || node.value.type === 'ArrayExpression') { + if ( + !isTagsProperty(node) || + !isTagsInCallOptions(node) || + node.value.type === 'ArrayExpression' + ) { return; } const valueText = sourceCode.getText(node.value); diff --git a/web/eslint-rules/cypress-tags-helper.ts b/web/eslint-rules/cypress-tags-helper.ts new file mode 100644 index 000000000..e8b597c92 --- /dev/null +++ b/web/eslint-rules/cypress-tags-helper.ts @@ -0,0 +1,43 @@ +import type { CallExpression, Expression, Node, Property, Super } from 'estree'; + +const SUPPORTED_CALLS: ReadonlySet = new Set(['describe', 'it', 'context', 'specify']); + +export function isTagsProperty(node: Property): boolean { + const key = node.key; + if (key.type === 'Identifier') { + return key.name === 'tags'; + } + if (key.type === 'Literal') { + return key.value === 'tags'; + } + return false; +} + +function calleeName(callee: Expression | Super): string | undefined { + if (callee.type === 'Identifier') { + return callee.name; + } + if (callee.type === 'MemberExpression') { + return calleeName(callee.object); + } + return undefined; +} + +function isSupportedCall(node: CallExpression): boolean { + const name = calleeName(node.callee); + return name !== undefined && SUPPORTED_CALLS.has(name); +} + +type WithParent = Node & { parent?: WithParent }; + +export function isTagsInCallOptions(node: Property): boolean { + const objectExpression = (node as WithParent).parent; + if (objectExpression?.type !== 'ObjectExpression') { + return false; + } + const call = objectExpression.parent; + if (call?.type !== 'CallExpression') { + return false; + } + return call.arguments.includes(objectExpression as never) && isSupportedCall(call); +}