From 3e4ae744b7b90c2faee0e3dec9289cf81e6b84d1 Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Thu, 26 Jun 2025 11:43:43 -0400 Subject: [PATCH 01/14] initial commit --- .../e2e/core/linodes/linode-alerts.spec.ts | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts diff --git a/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts b/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts new file mode 100644 index 00000000000..ecc1511699d --- /dev/null +++ b/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts @@ -0,0 +1,158 @@ +// TODO: rename this file after other outstanding PRs merged, to be consistent w/ their naming convention +// TODO: move strings to constants file +import { linodeFactory, regionFactory } from '@linode/utilities'; +import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetLinodeDetails } from 'support/intercepts/linodes'; +import { mockGetUserPreferences } from 'support/intercepts/profile'; +import { mockGetRegions } from 'support/intercepts/regions'; +import { ui } from 'support/ui'; +import { randomLabel, randomNumber } from 'support/util/random'; +/* + * UI of Linode alerts tab based on region enablement of alerts and isAclpAlertsBeta user preference + */ +describe('region enables alerts', function () { + beforeEach(() => { + mockAppendFeatureFlags({ + aclpBetaServices: { + linode: { + alerts: true, + metrics: false, + }, + }, + }).as('getFeatureFlags'); + const mockEnabledRegion = regionFactory.build({ + capabilities: ['Linodes'], + monitors: { + alerts: ['Linodes'], + }, + }); + mockGetRegions([mockEnabledRegion]).as('getRegions'); + const mockLinode = linodeFactory.build({ + id: randomNumber(), + label: randomLabel(), + region: mockEnabledRegion.id, + }); + mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode'); + cy.visitWithLogin(`/linodes/${mockLinode.id}/alerts`); + }); + it('isAclpAlertsBeta disabled', function () { + mockGetUserPreferences({ isAclpAlertsBeta: false }).as( + 'getUserPreferences' + ); + cy.wait([ + '@getFeatureFlags', + '@getRegions', + '@getLinode', + '@getUserPreferences', + ]); + ui.tabList.findTabByTitle('Alerts').within(() => { + cy.get('[data-testid="betaChip"]').should('not.exist'); + }); + cy.get('[data-reach-tab-panels]') + .should('be.visible') + .within(() => { + cy.contains('Default Alerts').should('be.visible'); + cy.get('[data-testid="notice-info"]') + .should('be.visible') + .within(() => { + cy.contains( + 'Try the new Alerts (Beta) for more options, including customizable alerts. You can switch back to the current view at any time.' + ); + }); + }); + + // upgrade from legacy alerts to ACLP alerts + ui.button + .findByTitle('Try Alerts (Beta)') + .should('be.visible') + .should('be.enabled'); + }); + + it('isAclpAlertsBeta enabled', () => { + mockGetUserPreferences({ isAclpAlertsBeta: true }).as('getUserPreferences'); + cy.wait([ + '@getFeatureFlags', + '@getRegions', + '@getLinode', + '@getUserPreferences', + ]); + ui.tabList.findTabByTitle('Alerts').within(() => { + cy.get('[data-testid="betaChip"]').should('be.visible'); + }); + cy.get('[data-reach-tab-panels]') + .should('be.visible') + .within(() => { + cy.contains('Alerts').should('be.visible'); + cy.get('[data-testid="notice-info"]') + .should('be.visible') + .within(() => { + cy.contains( + 'Welcome to Alerts (Beta) with more options and greater flexibility.' + ); + }); + // possible to downgrade from ACLP alerts to legacy alerts + ui.button + .findByTitle('Switch to legacy Alerts') + .should('be.visible') + .should('be.enabled'); + }); + }); +}); + +describe('region disables alerts. beta alerts not available regardless of user preference', function () { + beforeEach(() => { + mockAppendFeatureFlags({ + aclpBetaServices: { + linode: { + alerts: true, + metrics: false, + }, + }, + }).as('getFeatureFlags'); + const mockDisabledRegion = regionFactory.build({ + capabilities: ['Linodes'], + monitors: { + alerts: [], + }, + }); + + mockGetRegions([mockDisabledRegion]).as('getRegions'); + const mockLinode = linodeFactory.build({ + id: randomNumber(), + label: randomLabel(), + region: mockDisabledRegion.id, + }); + mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode'); + cy.visitWithLogin(`/linodes/${mockLinode.id}/alerts`); + }); + it('isAclpAlertsBeta disabled', () => { + mockGetUserPreferences({ isAclpAlertsBeta: false }).as( + 'getUserPreferences' + ); + cy.wait([ + '@getFeatureFlags', + '@getRegions', + '@getLinode', + '@getUserPreferences', + ]); + ui.tabList.findTabByTitle('Alerts').within(() => { + cy.get('[data-testid="betaChip"]').should('not.exist'); + }); + cy.get('[data-testid="notice-info"]').should('not.exist'); + }); + + it('isAclpAlertsBeta enabled', () => { + mockGetUserPreferences({ isAclpAlertsBeta: true }).as('getUserPreferences'); + cy.wait([ + '@getFeatureFlags', + '@getRegions', + '@getLinode', + '@getUserPreferences', + ]); + + ui.tabList.findTabByTitle('Alerts').within(() => { + cy.get('[data-testid="betaChip"]').should('not.exist'); + }); + cy.get('[data-testid="notice-info"]').should('not.exist'); + }); +}); From 263390eddbaea708fec9cd7ab292356a9c164fee Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Fri, 27 Jun 2025 10:59:11 -0400 Subject: [PATCH 02/14] move dupe strings to constants --- .../e2e/core/cloudpulse/aclp-support.spec.ts | 27 +++++++++-------- .../e2e/core/linodes/linode-alerts.spec.ts | 20 +++++++------ .../Linodes/AclpPreferenceToggle.test.tsx | 30 +++++++++++-------- .../manager/src/features/Linodes/constants.ts | 20 +++++++++++++ 4 files changed, 63 insertions(+), 34 deletions(-) diff --git a/packages/manager/cypress/e2e/core/cloudpulse/aclp-support.spec.ts b/packages/manager/cypress/e2e/core/cloudpulse/aclp-support.spec.ts index d5c9e977b4b..d8f57e7ddaa 100644 --- a/packages/manager/cypress/e2e/core/cloudpulse/aclp-support.spec.ts +++ b/packages/manager/cypress/e2e/core/cloudpulse/aclp-support.spec.ts @@ -13,6 +13,13 @@ import { } from 'support/util/cloudpulse'; import { randomLabel, randomNumber } from 'support/util/random'; +import { + METRICS_BETA_MODE_BANNER_TEXT, + METRICS_BETA_MODE_BUTTON_TEXT, + METRICS_LEGACY_MODE_BANNER_TEXT, + METRICS_LEGACY_MODE_BUTTON_TEXT, +} from 'src/features/Linodes/constants'; + import type { Stats } from '@linode/api-v4'; /** @@ -87,12 +94,10 @@ describe('ACLP Components UI varies according to ACLP support by region and user cy.get('[data-testid="metrics-preference-banner-text"]').should( 'be.visible' ); - cy.contains( - 'Welcome to Metrics (Beta) with more options and greater flexibility for better data analysis.' - ).should('be.visible'); + cy.contains(METRICS_BETA_MODE_BANNER_TEXT).should('be.visible'); ui.button - .findByTitle('Switch to legacy Metrics') + .findByTitle(METRICS_BETA_MODE_BUTTON_TEXT) .should('be.visible') .should('be.enabled'); // UI displays mock error msg @@ -104,8 +109,6 @@ describe('ACLP Components UI varies according to ACLP support by region and user // UI displays legacy metrics, can switch to beta view it('user preference disables aclp', function () { - const msgBeta = - 'Try the new Metrics (Beta) with more options and greater flexibility for better data analysis. You can switch back to the current view at any time.'; mockGetUserPreferences({ isAclpMetricsBeta: false }).as( 'getUserPreferences' ); @@ -136,21 +139,19 @@ describe('ACLP Components UI varies according to ACLP support by region and user ); // expect legacy metrics view of LinodeSummary component to be displayed cy.get('[data-testid="linode-summary"]').should('be.visible'); - cy.contains(msgBeta).should('be.visible'); + cy.contains(METRICS_LEGACY_MODE_BANNER_TEXT).should('be.visible'); // switch to beta metrics ui.button - .findByTitle('Try the Metrics (Beta)') + .findByTitle(METRICS_LEGACY_MODE_BUTTON_TEXT) .should('be.visible') .should('be.enabled') .click(); // wait for dashboard query to complete cy.wait('@getDashboardError'); - cy.contains( - 'Welcome to Metrics (Beta) with more options and greater flexibility for better data analysis.' - ).should('be.visible'); - cy.contains(msgBeta).should('not.exist'); + cy.contains(METRICS_BETA_MODE_BANNER_TEXT).should('be.visible'); + cy.contains(METRICS_LEGACY_MODE_BANNER_TEXT).should('not.exist'); ui.button - .findByTitle('Switch to legacy Metrics') + .findByTitle(METRICS_BETA_MODE_BUTTON_TEXT) .should('be.visible') .should('be.enabled'); }); diff --git a/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts b/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts index ecc1511699d..e2cbddeaba4 100644 --- a/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts @@ -1,5 +1,4 @@ // TODO: rename this file after other outstanding PRs merged, to be consistent w/ their naming convention -// TODO: move strings to constants file import { linodeFactory, regionFactory } from '@linode/utilities'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; import { mockGetLinodeDetails } from 'support/intercepts/linodes'; @@ -7,6 +6,13 @@ import { mockGetUserPreferences } from 'support/intercepts/profile'; import { mockGetRegions } from 'support/intercepts/regions'; import { ui } from 'support/ui'; import { randomLabel, randomNumber } from 'support/util/random'; + +import { + ALERTS_BETA_MODE_BANNER_TEXT, + ALERTS_BETA_MODE_BUTTON_TEXT, + ALERTS_LEGACY_MODE_BANNER_TEXT, + ALERTS_LEGACY_MODE_BUTTON_TEXT, +} from 'src/features/Linodes/constants'; /* * UI of Linode alerts tab based on region enablement of alerts and isAclpAlertsBeta user preference */ @@ -55,15 +61,13 @@ describe('region enables alerts', function () { cy.get('[data-testid="notice-info"]') .should('be.visible') .within(() => { - cy.contains( - 'Try the new Alerts (Beta) for more options, including customizable alerts. You can switch back to the current view at any time.' - ); + cy.contains(ALERTS_LEGACY_MODE_BANNER_TEXT); }); }); // upgrade from legacy alerts to ACLP alerts ui.button - .findByTitle('Try Alerts (Beta)') + .findByTitle(ALERTS_LEGACY_MODE_BUTTON_TEXT) .should('be.visible') .should('be.enabled'); }); @@ -86,13 +90,11 @@ describe('region enables alerts', function () { cy.get('[data-testid="notice-info"]') .should('be.visible') .within(() => { - cy.contains( - 'Welcome to Alerts (Beta) with more options and greater flexibility.' - ); + cy.contains(ALERTS_BETA_MODE_BANNER_TEXT); }); // possible to downgrade from ACLP alerts to legacy alerts ui.button - .findByTitle('Switch to legacy Alerts') + .findByTitle(ALERTS_BETA_MODE_BUTTON_TEXT) .should('be.visible') .should('be.enabled'); }); diff --git a/packages/manager/src/features/Linodes/AclpPreferenceToggle.test.tsx b/packages/manager/src/features/Linodes/AclpPreferenceToggle.test.tsx index 36dd917d080..b605bdd55f9 100644 --- a/packages/manager/src/features/Linodes/AclpPreferenceToggle.test.tsx +++ b/packages/manager/src/features/Linodes/AclpPreferenceToggle.test.tsx @@ -6,6 +6,16 @@ import { vi } from 'vitest'; import { renderWithTheme } from 'src/utilities/testHelpers'; import { AclpPreferenceToggle } from './AclpPreferenceToggle'; +import { + ALERTS_BETA_MODE_BANNER_TEXT, + ALERTS_BETA_MODE_BUTTON_TEXT, + ALERTS_LEGACY_MODE_BANNER_TEXT, + ALERTS_LEGACY_MODE_BUTTON_TEXT, + METRICS_BETA_MODE_BANNER_TEXT, + METRICS_BETA_MODE_BUTTON_TEXT, + METRICS_LEGACY_MODE_BANNER_TEXT, + METRICS_LEGACY_MODE_BUTTON_TEXT, +} from './constants'; import type { AclpPreferenceToggleType } from './AclpPreferenceToggle'; @@ -23,21 +33,17 @@ const expectedAclpPreferences: Record< > = { metrics: { preference: true, - legacyModeBannerText: - 'Try the new Metrics (Beta) with more options and greater flexibility for better data analysis. You can switch back to the current view at any time.', - betaModeBannertext: - 'Welcome to Metrics (Beta) with more options and greater flexibility for better data analysis.', - legacyModeButtonText: 'Try the Metrics (Beta)', - betaModeButtonText: 'Switch to legacy Metrics', + legacyModeBannerText: METRICS_LEGACY_MODE_BANNER_TEXT, + betaModeBannertext: METRICS_BETA_MODE_BANNER_TEXT, + legacyModeButtonText: METRICS_LEGACY_MODE_BUTTON_TEXT, + betaModeButtonText: METRICS_BETA_MODE_BUTTON_TEXT, }, alerts: { preference: true, - legacyModeBannerText: - 'Try the new Alerts (Beta) for more options, including customizable alerts. You can switch back to the current view at any time.', - betaModeBannertext: - 'Welcome to Alerts (Beta) with more options and greater flexibility.', - legacyModeButtonText: 'Try Alerts (Beta)', - betaModeButtonText: 'Switch to legacy Alerts', + legacyModeBannerText: ALERTS_LEGACY_MODE_BANNER_TEXT, + betaModeBannertext: ALERTS_BETA_MODE_BANNER_TEXT, + legacyModeButtonText: ALERTS_LEGACY_MODE_BUTTON_TEXT, + betaModeButtonText: ALERTS_BETA_MODE_BUTTON_TEXT, }, }; diff --git a/packages/manager/src/features/Linodes/constants.ts b/packages/manager/src/features/Linodes/constants.ts index 689f122a89e..ebdc4a5126d 100644 --- a/packages/manager/src/features/Linodes/constants.ts +++ b/packages/manager/src/features/Linodes/constants.ts @@ -6,3 +6,23 @@ export const PUBLIC_IP_ADDRESSES_LINODE_INTERFACE_NOT_ASSIGNED_TOOLTIP_TEXT = export const PUBLIC_IP_ADDRESSES_LINODE_INTERFACE_DEFAULT_ROUTE_TOOLTIP_TEXT = 'The noted Public IP Addresses are provisionally reserved but not the default route. To update this, please review your Interface Settings.'; + +export const METRICS_LEGACY_MODE_BANNER_TEXT = + 'Try the new Metrics (Beta) with more options and greater flexibility for better data analysis. You can switch back to the current view at any time.'; + +export const METRICS_BETA_MODE_BANNER_TEXT = + 'Welcome to Metrics (Beta) with more options and greater flexibility for better data analysis.'; + +export const METRICS_LEGACY_MODE_BUTTON_TEXT = 'Try the Metrics (Beta)'; + +export const METRICS_BETA_MODE_BUTTON_TEXT = 'Switch to legacy Metrics'; + +export const ALERTS_LEGACY_MODE_BANNER_TEXT = + 'Try the new Alerts (Beta) for more options, including customizable alerts. You can switch back to the current view at any time.'; + +export const ALERTS_BETA_MODE_BANNER_TEXT = + 'Welcome to Alerts (Beta) with more options and greater flexibility.'; + +export const ALERTS_LEGACY_MODE_BUTTON_TEXT = 'Try Alerts (Beta)'; + +export const ALERTS_BETA_MODE_BUTTON_TEXT = 'Switch to legacy Alerts'; From 70bcddaed69d62973bf821ef56a20371bd233c41 Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Tue, 1 Jul 2025 12:14:24 -0400 Subject: [PATCH 03/14] manually resolve merge conflict --- packages/manager/src/features/Linodes/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/src/features/Linodes/constants.ts b/packages/manager/src/features/Linodes/constants.ts index 4dccf5e05b2..4d8d0e42b6b 100644 --- a/packages/manager/src/features/Linodes/constants.ts +++ b/packages/manager/src/features/Linodes/constants.ts @@ -5,7 +5,7 @@ export const PUBLIC_IP_ADDRESSES_LINODE_INTERFACE_NOT_ASSIGNED_TOOLTIP_TEXT = 'The noted Public IP Addresses are provisionally reserved but not assigned to a network interface.'; export const PUBLIC_IP_ADDRESSES_LINODE_INTERFACE_DEFAULT_ROUTE_TOOLTIP_TEXT = - 'The noted Public IP Addresses are provisionally reserved but not the default route. To update this, please review your Interface Settings.'; + 'This Public IP Address is provisionally reserved but not the default route. To update this, please review your Interface Settings.'; export const METRICS_LEGACY_MODE_BANNER_TEXT = 'Try the new Metrics (Beta) with more options and greater flexibility for better data analysis. You can switch back to the current view at any time.'; From 304242da127c4d6c0dcc21b8f297cce5bfe1704c Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Tue, 1 Jul 2025 12:40:10 -0400 Subject: [PATCH 04/14] Added changeset: Linode alerts tab based on region and user preference --- packages/manager/.changeset/pr-12442-tests-1751388010586.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/manager/.changeset/pr-12442-tests-1751388010586.md diff --git a/packages/manager/.changeset/pr-12442-tests-1751388010586.md b/packages/manager/.changeset/pr-12442-tests-1751388010586.md new file mode 100644 index 00000000000..3c47b59b324 --- /dev/null +++ b/packages/manager/.changeset/pr-12442-tests-1751388010586.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Tests +--- + +Linode alerts tab based on region and user preference ([#12442](https://github.com/linode/manager/pull/12442)) From 8a30b94a5528d4edbcb4a113185634fb789a538d Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Tue, 1 Jul 2025 12:40:30 -0400 Subject: [PATCH 05/14] formatting --- .../manager/cypress/e2e/core/linodes/linode-alerts.spec.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts b/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts index e2cbddeaba4..ec2ecbf9fe3 100644 --- a/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts @@ -41,6 +41,7 @@ describe('region enables alerts', function () { mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode'); cy.visitWithLogin(`/linodes/${mockLinode.id}/alerts`); }); + it('isAclpAlertsBeta disabled', function () { mockGetUserPreferences({ isAclpAlertsBeta: false }).as( 'getUserPreferences' @@ -65,7 +66,7 @@ describe('region enables alerts', function () { }); }); - // upgrade from legacy alerts to ACLP alerts + // possible to upgrade from legacy alerts to ACLP alerts ui.button .findByTitle(ALERTS_LEGACY_MODE_BUTTON_TEXT) .should('be.visible') @@ -111,13 +112,13 @@ describe('region disables alerts. beta alerts not available regardless of user p }, }, }).as('getFeatureFlags'); + const mockDisabledRegion = regionFactory.build({ capabilities: ['Linodes'], monitors: { alerts: [], }, }); - mockGetRegions([mockDisabledRegion]).as('getRegions'); const mockLinode = linodeFactory.build({ id: randomNumber(), @@ -127,6 +128,7 @@ describe('region disables alerts. beta alerts not available regardless of user p mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode'); cy.visitWithLogin(`/linodes/${mockLinode.id}/alerts`); }); + it('isAclpAlertsBeta disabled', () => { mockGetUserPreferences({ isAclpAlertsBeta: false }).as( 'getUserPreferences' From d1a8051cf825d1875bc6997cd6032303ab0a18d4 Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Thu, 3 Jul 2025 08:20:42 -0400 Subject: [PATCH 06/14] update Default Alerts msg --- .../manager/cypress/e2e/core/linodes/linode-alerts.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts b/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts index ec2ecbf9fe3..284783d6158 100644 --- a/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts @@ -1,4 +1,3 @@ -// TODO: rename this file after other outstanding PRs merged, to be consistent w/ their naming convention import { linodeFactory, regionFactory } from '@linode/utilities'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; import { mockGetLinodeDetails } from 'support/intercepts/linodes'; @@ -58,7 +57,7 @@ describe('region enables alerts', function () { cy.get('[data-reach-tab-panels]') .should('be.visible') .within(() => { - cy.contains('Default Alerts').should('be.visible'); + cy.contains('Alerts').should('be.visible'); cy.get('[data-testid="notice-info"]') .should('be.visible') .within(() => { From 79cf7d70417cbe57574bb7b64ce8d3bc379bb112 Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Thu, 10 Jul 2025 14:17:14 -0400 Subject: [PATCH 07/14] fix tests after breaking changes --- .../e2e/core/linodes/linode-alerts.spec.ts | 427 +++++++++++++++--- .../cypress/support/intercepts/linodes.ts | 12 + .../manager/cypress/support/util/linodes.ts | 49 ++ 3 files changed, 437 insertions(+), 51 deletions(-) diff --git a/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts b/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts index 284783d6158..eaeb38f7093 100644 --- a/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts @@ -1,20 +1,56 @@ import { linodeFactory, regionFactory } from '@linode/utilities'; +import { mockGetAlertDefinition } from 'support/intercepts/cloudpulse'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; -import { mockGetLinodeDetails } from 'support/intercepts/linodes'; -import { mockGetUserPreferences } from 'support/intercepts/profile'; +import { + mockGetLinodeDetails, + mockUpdateLinode, +} from 'support/intercepts/linodes'; import { mockGetRegions } from 'support/intercepts/regions'; import { ui } from 'support/ui'; +import { assertLinodeAlertsEnabled } from 'support/util/linodes'; import { randomLabel, randomNumber } from 'support/util/random'; +import { alertFactory } from 'src/factories'; import { ALERTS_BETA_MODE_BANNER_TEXT, ALERTS_BETA_MODE_BUTTON_TEXT, ALERTS_LEGACY_MODE_BANNER_TEXT, ALERTS_LEGACY_MODE_BUTTON_TEXT, } from 'src/features/Linodes/constants'; + +const mockDisabledLegacyAlerts = { + cpu: 0, + io: 0, + network_in: 0, + network_out: 0, + transfer_quota: 0, +}; +const mockEnabledLegacyAlerts = { + cpu: 180, + io: 10000, + network_in: 10, + network_out: 10, + transfer_quota: 80, +}; + +const mockDisabledBetaAlerts = { + system: [], + user: [], +}; + +const mockEnabledBetaAlerts = { + system: [1, 2], + user: [3], +}; + /* - * UI of Linode alerts tab based on region enablement of alerts and isAclpAlertsBeta user preference + * UI of Linode alerts tab based on beta and legacy alert values in linode.alerts. Dependent on region support for alerts + * Legacy alerts = 0, Beta alerts = [], => legacy disabled + * Legacy alerts > 0, Beta alerts = [], => legacy enabled + * Legacy alerts = 0, Beta alerts > 0, => beta enabled + * Legacy alerts > 0, Beta alerts > 0, => beta enabled */ + describe('region enables alerts', function () { beforeEach(() => { mockAppendFeatureFlags({ @@ -31,26 +67,122 @@ describe('region enables alerts', function () { alerts: ['Linodes'], }, }); + cy.wrap(mockEnabledRegion).as('mockEnabledRegion'); mockGetRegions([mockEnabledRegion]).as('getRegions'); + + const alertDefinitions = [ + alertFactory.build({ + id: 1, + description: randomLabel(), + // entity_ids: ['1', '2', '3'], + label: randomLabel(), + service_type: 'linode', + severity: 1, + status: 'enabled', + type: 'system', + }), + alertFactory.build({ + id: 2, + + description: randomLabel(), + // entity_ids: ['1', '2', '3'], + label: randomLabel(), + service_type: 'linode', + severity: 1, + status: 'enabled', + type: 'system', + }), + alertFactory.build({ + id: 3, + description: randomLabel(), + // entity_ids: ['1', '2', '3'], + label: randomLabel(), + service_type: 'linode', + severity: 1, + status: 'enabled', + type: 'user', + }), + ]; + cy.wrap(alertDefinitions).as('alertDefinitions'); + mockGetAlertDefinition('linode', alertDefinitions).as( + 'getAlertDefinitions' + ); + }); + + it('Legacy alerts = 0, Beta alerts = [] => legacy disabled', function () { const mockLinode = linodeFactory.build({ id: randomNumber(), label: randomLabel(), - region: mockEnabledRegion.id, + region: this.mockEnabledRegion.id, + alerts: { + ...mockDisabledLegacyAlerts, + ...mockDisabledBetaAlerts, + }, }); mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode'); cy.visitWithLogin(`/linodes/${mockLinode.id}/alerts`); + cy.wait(['@getFeatureFlags', '@getRegions', '@getLinode']); + ui.tabList.findTabByTitle('Alerts').within(() => { + cy.get('[data-testid="betaChip"]').should('not.exist'); + }); + cy.get('[data-reach-tab-panels]') + .should('be.visible') + .within(() => { + cy.contains('Alerts').should('be.visible'); + cy.get('[data-testid="notice-info"]') + .should('be.visible') + .within(() => { + cy.contains(ALERTS_LEGACY_MODE_BANNER_TEXT); + }); + // alerts are disabled so all toggles are off + ui.toggle.find().each(($toggle) => { + cy.wrap($toggle).should('have.attr', 'data-qa-toggle', 'false'); + }); + }); + + // upgrade from legacy alerts to ACLP alerts + ui.button + .findByTitle(ALERTS_LEGACY_MODE_BUTTON_TEXT) + .should('be.visible') + .should('be.enabled') + .click(); + + ui.tabList.findTabByTitle('Alerts').within(() => { + cy.get('[data-testid="betaChip"]').should('be.visible'); + }); + cy.get('[data-reach-tab-panels]') + .should('be.visible') + .within(() => { + cy.contains('Alerts').should('be.visible'); + cy.get('[data-testid="notice-info"]') + .should('be.visible') + .within(() => { + cy.contains(ALERTS_BETA_MODE_BANNER_TEXT); + }); + // possible to downgrade from ACLP alerts to legacy alerts + ui.button + .findByTitle(ALERTS_BETA_MODE_BUTTON_TEXT) + .should('be.visible') + .should('be.enabled'); + + cy.wait(['@getAlertDefinitions']); + assertLinodeAlertsEnabled(this.alertDefinitions); + }); }); - it('isAclpAlertsBeta disabled', function () { - mockGetUserPreferences({ isAclpAlertsBeta: false }).as( - 'getUserPreferences' - ); - cy.wait([ - '@getFeatureFlags', - '@getRegions', - '@getLinode', - '@getUserPreferences', - ]); + it('Legacy alerts > 0, Beta alerts = [] => legacy enabled. can upgrade to beta disabled', function () { + const mockLinode = linodeFactory.build({ + id: randomNumber(), + label: randomLabel(), + region: this.mockEnabledRegion.id, + alerts: { + // legacy alerts are enabled if value > 0 + ...mockEnabledLegacyAlerts, + }, + }); + mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode'); + cy.visitWithLogin(`/linodes/${mockLinode.id}/alerts`); + cy.wait(['@getFeatureFlags', '@getRegions', '@getLinode']); ui.tabList.findTabByTitle('Alerts').within(() => { cy.get('[data-testid="betaChip"]').should('not.exist'); }); @@ -63,23 +195,76 @@ describe('region enables alerts', function () { .within(() => { cy.contains(ALERTS_LEGACY_MODE_BANNER_TEXT); }); + + // alerts are enabled so all toggles are on if val > 0 + ui.toggle.find().each(($toggle) => { + cy.wrap($toggle).should('have.attr', 'data-qa-toggle', 'true'); + }); }); - // possible to upgrade from legacy alerts to ACLP alerts + // upgrade from legacy alerts to ACLP alerts ui.button .findByTitle(ALERTS_LEGACY_MODE_BUTTON_TEXT) .should('be.visible') - .should('be.enabled'); + .should('be.enabled') + .click(); + ui.tabList.findTabByTitle('Alerts').within(() => { + cy.get('[data-testid="betaChip"]').should('be.visible'); + }); + cy.get('[data-reach-tab-panels]') + .should('be.visible') + .within(() => { + cy.contains('Alerts').should('be.visible'); + cy.get('[data-testid="notice-info"]') + .should('be.visible') + .within(() => { + cy.contains(ALERTS_BETA_MODE_BANNER_TEXT); + }); + cy.wait(['@getAlertDefinitions']); + // toggles in table are off but can be turned on + assertLinodeAlertsEnabled(this.alertDefinitions); + + mockUpdateLinode(mockLinode.id).as('updateLinode'); + ui.button + .findByTitle('Save') + .should('be.visible') + .should('be.enabled') + .click(); + }); + + // TODO: modal maybe shouldnt appear in all scenarios + // TODO: content of request.body not match prod, 'alerts' attribute missing here + ui.dialog + .findByTitle('Save Alerts?') + .should('be.visible') + .within(() => { + ui.button.findByTitle('Save').should('be.visible').click(); + }); + cy.wait('@updateLinode').then((xhr) => { + // can save changes. new beta alerts added in assertLinodeAlertsEnabled tests + const edits = xhr.request.body; + expect(JSON.stringify(edits.system)).to.equal( + JSON.stringify(mockEnabledBetaAlerts.system) + ); + expect(JSON.stringify(edits.user)).to.equal( + JSON.stringify(mockEnabledBetaAlerts.user) + ); + }); }); - it('isAclpAlertsBeta enabled', () => { - mockGetUserPreferences({ isAclpAlertsBeta: true }).as('getUserPreferences'); - cy.wait([ - '@getFeatureFlags', - '@getRegions', - '@getLinode', - '@getUserPreferences', - ]); + it('Legacy alerts = 0, Beta alerts > 0, => beta disabled', function () { + const mockLinode = linodeFactory.build({ + id: randomNumber(), + label: randomLabel(), + region: this.mockEnabledRegion.id, + alerts: { + ...mockDisabledLegacyAlerts, + ...mockEnabledBetaAlerts, + }, + }); + mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode'); + cy.visitWithLogin(`/linodes/${mockLinode.id}/alerts`); + cy.wait(['@getFeatureFlags', '@getRegions', '@getLinode']); ui.tabList.findTabByTitle('Alerts').within(() => { cy.get('[data-testid="betaChip"]').should('be.visible'); }); @@ -92,16 +277,124 @@ describe('region enables alerts', function () { .within(() => { cy.contains(ALERTS_BETA_MODE_BANNER_TEXT); }); - // possible to downgrade from ACLP alerts to legacy alerts + cy.wait(['@getAlertDefinitions']); + assertLinodeAlertsEnabled(this.alertDefinitions); + }); + + // downgrade from ACLP alerts to legacy alerts + ui.button + .findByTitle(ALERTS_BETA_MODE_BUTTON_TEXT) + .should('be.visible') + .should('be.enabled') + .click(); + + ui.tabList.findTabByTitle('Alerts').within(() => { + cy.get('[data-testid="betaChip"]').should('not.exist'); + }); + cy.get('[data-reach-tab-panels]') + .should('be.visible') + .within(() => { + cy.contains('Alerts').should('be.visible'); + cy.get('[data-testid="notice-info"]') + .should('be.visible') + .within(() => { + cy.contains(ALERTS_LEGACY_MODE_BANNER_TEXT); + }); + // alerts are disabled so all toggles are off + ui.toggle.find().each(($toggle) => { + cy.wrap($toggle) + .should('have.attr', 'data-qa-toggle', 'false') + .should('be.visible') + .should('be.enabled') + .click(); + }); + // possible to upgrade to beta ui.button - .findByTitle(ALERTS_BETA_MODE_BUTTON_TEXT) + .findByTitle(ALERTS_LEGACY_MODE_BUTTON_TEXT) .should('be.visible') .should('be.enabled'); + + // can save changes + ui.button.findByTitle('Save').should('be.visible').should('be.enabled'); + }); + }); + + it('Legacy alerts > 0, Beta alerts > 0, => beta disabled. can downgrade to legacy enabled', function () { + const mockLinode = linodeFactory.build({ + id: randomNumber(), + label: randomLabel(), + region: this.mockEnabledRegion.id, + alerts: { + ...mockEnabledLegacyAlerts, + ...mockEnabledBetaAlerts, + }, + }); + mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode'); + cy.visitWithLogin(`/linodes/${mockLinode.id}/alerts`); + cy.wait(['@getFeatureFlags', '@getRegions', '@getLinode']); + ui.tabList.findTabByTitle('Alerts').within(() => { + cy.get('[data-testid="betaChip"]').should('be.visible'); + }); + cy.get('[data-reach-tab-panels]') + .should('be.visible') + .within(() => { + cy.contains('Alerts').should('be.visible'); + cy.get('[data-testid="notice-info"]') + .should('be.visible') + .within(() => { + cy.contains(ALERTS_BETA_MODE_BANNER_TEXT); + }); + cy.wait(['@getAlertDefinitions']); + assertLinodeAlertsEnabled(this.alertDefinitions); + // downgrade from ACLP alerts to legacy alerts + ui.button + .findByTitle(ALERTS_BETA_MODE_BUTTON_TEXT) + .should('be.visible') + .should('be.enabled') + .click(); + }); + + // beta alerts UI loaded + ui.tabList.findTabByTitle('Alerts').within(() => { + cy.get('[data-testid="betaChip"]').should('not.exist'); + }); + cy.get('[data-reach-tab-panels]') + .should('be.visible') + .within(() => { + cy.contains('Alerts').should('be.visible'); + cy.get('[data-testid="notice-info"]') + .should('be.visible') + .within(() => { + cy.contains(ALERTS_LEGACY_MODE_BANNER_TEXT); + }); + // turn the toggles off + ui.toggle + .find() + .should('have.attr', 'data-qa-toggle', 'true') + .should('be.visible') + .click({ multiple: true }); + ui.toggle.find().should('have.attr', 'data-qa-toggle', 'false'); + + mockUpdateLinode(mockLinode.id).as('updateLinode'); + cy.scrollTo('bottom'); + // save changes + ui.button + .findByTitle('Save') + .should('be.visible') + .should('be.enabled') + .click(); }); + // TODO: not prompted by Save Alerts? dialog + cy.wait('@updateLinode').then((xhr) => { + // can save changes. new beta alerts added in assertLinodeAlertsEnabled tests + const actual = xhr.request.body; + const expected = { alerts: mockDisabledLegacyAlerts }; + expect(JSON.stringify(actual)).to.equal(JSON.stringify(expected)); + }); }); }); -describe('region disables alerts. beta alerts not available regardless of user preference', function () { +describe('region disables alerts. beta alerts not available regardless of linode settings', function () { beforeEach(() => { mockAppendFeatureFlags({ aclpBetaServices: { @@ -118,44 +411,76 @@ describe('region disables alerts. beta alerts not available regardless of user p alerts: [], }, }); + cy.wrap(mockDisabledRegion).as('mockDisabledRegion'); mockGetRegions([mockDisabledRegion]).as('getRegions'); + }); + + it('Legacy alerts = 0, Beta alerts > 0, => legacy disabled', function () { const mockLinode = linodeFactory.build({ id: randomNumber(), label: randomLabel(), - region: mockDisabledRegion.id, + region: this.mockDisabledRegion.id, + alerts: { + ...mockDisabledLegacyAlerts, + ...mockEnabledBetaAlerts, + }, }); mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode'); cy.visitWithLogin(`/linodes/${mockLinode.id}/alerts`); - }); - - it('isAclpAlertsBeta disabled', () => { - mockGetUserPreferences({ isAclpAlertsBeta: false }).as( - 'getUserPreferences' - ); - cy.wait([ - '@getFeatureFlags', - '@getRegions', - '@getLinode', - '@getUserPreferences', - ]); + cy.wait(['@getFeatureFlags', '@getRegions', '@getLinode']); ui.tabList.findTabByTitle('Alerts').within(() => { cy.get('[data-testid="betaChip"]').should('not.exist'); }); - cy.get('[data-testid="notice-info"]').should('not.exist'); + cy.get('[data-reach-tab-panels]') + .should('be.visible') + .within(() => { + cy.contains('Alerts').should('be.visible'); + cy.get('[data-testid="notice-info"]').should('not.exist'); + // not possible to upgrade or downgrade + cy.findByText(ALERTS_LEGACY_MODE_BUTTON_TEXT).should('not.exist'); + cy.findByText(ALERTS_BETA_MODE_BUTTON_TEXT).should('not.exist'); + // alerts are disabled so all toggles are off but are not readonly + ui.toggle.find().each(($toggle) => { + cy.wrap($toggle) + .should('have.attr', 'data-qa-toggle', 'false') + .should('be.visible') + .should('be.enabled') + .click(); + cy.wrap($toggle).should('have.attr', 'data-qa-toggle', 'true'); + }); + }); }); - it('isAclpAlertsBeta enabled', () => { - mockGetUserPreferences({ isAclpAlertsBeta: true }).as('getUserPreferences'); - cy.wait([ - '@getFeatureFlags', - '@getRegions', - '@getLinode', - '@getUserPreferences', - ]); - + it('Legacy alerts > 0, Beta alerts = 0, => legacy disabled', function () { + const mockLinode = linodeFactory.build({ + id: randomNumber(), + label: randomLabel(), + region: this.mockDisabledRegion.id, + alerts: { ...mockEnabledLegacyAlerts }, + }); + mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode'); + cy.visitWithLogin(`/linodes/${mockLinode.id}/alerts`); + cy.wait(['@getFeatureFlags', '@getRegions', '@getLinode']); ui.tabList.findTabByTitle('Alerts').within(() => { cy.get('[data-testid="betaChip"]').should('not.exist'); }); - cy.get('[data-testid="notice-info"]').should('not.exist'); + cy.get('[data-reach-tab-panels]') + .should('be.visible') + .within(() => { + cy.contains('Alerts').should('be.visible'); + cy.get('[data-testid="notice-info"]').should('not.exist'); + // not possible to upgrade or downgrade + cy.findByText(ALERTS_LEGACY_MODE_BUTTON_TEXT).should('not.exist'); + cy.findByText(ALERTS_BETA_MODE_BUTTON_TEXT).should('not.exist'); + // alerts are disabled so all toggles are off but are not readonly + ui.toggle.find().each(($toggle) => { + cy.wrap($toggle) + .should('have.attr', 'data-qa-toggle', 'true') + .should('be.visible') + .should('be.enabled') + .click(); + cy.wrap($toggle).should('have.attr', 'data-qa-toggle', 'false'); + }); + }); }); }); diff --git a/packages/manager/cypress/support/intercepts/linodes.ts b/packages/manager/cypress/support/intercepts/linodes.ts index f6d42673ea7..c613c747fed 100644 --- a/packages/manager/cypress/support/intercepts/linodes.ts +++ b/packages/manager/cypress/support/intercepts/linodes.ts @@ -779,3 +779,15 @@ export const mockGetLinodeStats = ( makeResponse(stats) ); }; + +/** + * Intercepts PUT request to edit details of a linode + * + * @param linodeId - ID of Linode for intercepted request. + * + * @returns Cypress chainable. + */ +export const mockUpdateLinode = (linodeId: number): Cypress.Chainable => { + console.log('intercepting mockUpdateLinode'); + return cy.intercept('PUT', apiMatcher(`linode/instances/${linodeId}`)); +}; diff --git a/packages/manager/cypress/support/util/linodes.ts b/packages/manager/cypress/support/util/linodes.ts index 73e2dfee084..2d1b2051f8c 100644 --- a/packages/manager/cypress/support/util/linodes.ts +++ b/packages/manager/cypress/support/util/linodes.ts @@ -30,6 +30,7 @@ import { chooseRegion } from 'support/util/regions'; import { depaginate } from './paginate'; import type { + Alert, Config, CreateLinodeRequest, InterfacePayload, @@ -338,3 +339,51 @@ export const assertNewLinodeInterfacesIsAvailable = ( cy.findByText(networkConnectionSectionText).should(expectedBehavior); cy.findByText(networkConnectionDescriptionText).should(expectedBehavior); }; + +/** + * Validates the table cell contents against the alerts provided + * + * @param linodeInterfacesEnabled - Indicator if Linode Interfaces feature is enabled. + */ +export const assertLinodeAlertsEnabled = (alertDefinitions: Alert[]) => { + cy.get('table[data-testid="alert-table"]') + .should('be.visible') + .get('tbody > tr') + .should('have.length', 3) + .each((row, index) => { + // match alert definitions to table cell contents + cy.wrap(row).within(() => { + cy.get('td') + .eq(0) + .within(() => { + // each alert's toggle should be editable + ui.toggle + .find() + .should('have.attr', 'data-qa-toggle', 'false') + .should('be.visible') + .should('be.enabled') + .click(); + ui.toggle.find().should('have.attr', 'data-qa-toggle', 'true'); + }); + cy.get('td') + .eq(1) + .within(() => { + cy.findByText(alertDefinitions[index].label).should('be.visible'); + }); + cy.get('td') + .eq(2) + .within(() => { + const rule = alertDefinitions[index].rule_criteria.rules[0]; + const str = `${rule.label} = ${rule.threshold} ${rule.unit}`; + cy.findByText(str).should('be.visible'); + }); + cy.get('td') + .eq(3) + .within(() => { + cy.findByText(alertDefinitions[index].type, { + exact: false, + }).should('be.visible'); + }); + }); + }); +}; From be6e48a60766183f9a123676b6ba35e2d27fdd97 Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Mon, 14 Jul 2025 13:09:51 -0400 Subject: [PATCH 08/14] cleanup --- .../e2e/core/linodes/linode-alerts.spec.ts | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts b/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts index eaeb38f7093..7bcf67e6d3f 100644 --- a/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts @@ -74,7 +74,6 @@ describe('region enables alerts', function () { alertFactory.build({ id: 1, description: randomLabel(), - // entity_ids: ['1', '2', '3'], label: randomLabel(), service_type: 'linode', severity: 1, @@ -85,7 +84,6 @@ describe('region enables alerts', function () { id: 2, description: randomLabel(), - // entity_ids: ['1', '2', '3'], label: randomLabel(), service_type: 'linode', severity: 1, @@ -95,7 +93,6 @@ describe('region enables alerts', function () { alertFactory.build({ id: 3, description: randomLabel(), - // entity_ids: ['1', '2', '3'], label: randomLabel(), service_type: 'linode', severity: 1, @@ -232,24 +229,25 @@ describe('region enables alerts', function () { .click(); }); - // TODO: modal maybe shouldnt appear in all scenarios + // TODO: this test passes but modal behavior will change when properly implemented in api (M3-10195) + // ui.dialog + // .findByTitle('Save Alerts?') + // .should('be.visible') + // .within(() => { + // ui.button.findByTitle('Save').should('be.visible') + // .click(); + // }); // TODO: content of request.body not match prod, 'alerts' attribute missing here - ui.dialog - .findByTitle('Save Alerts?') - .should('be.visible') - .within(() => { - ui.button.findByTitle('Save').should('be.visible').click(); - }); - cy.wait('@updateLinode').then((xhr) => { - // can save changes. new beta alerts added in assertLinodeAlertsEnabled tests - const edits = xhr.request.body; - expect(JSON.stringify(edits.system)).to.equal( - JSON.stringify(mockEnabledBetaAlerts.system) - ); - expect(JSON.stringify(edits.user)).to.equal( - JSON.stringify(mockEnabledBetaAlerts.user) - ); - }); + // cy.wait('@updateLinode').then((xhr) => { + // // can save changes. new beta alerts added in assertLinodeAlertsEnabled tests + // const edits = xhr.request.body; + // expect(JSON.stringify(edits.system)).to.equal( + // JSON.stringify(mockEnabledBetaAlerts.system) + // ); + // expect(JSON.stringify(edits.user)).to.equal( + // JSON.stringify(mockEnabledBetaAlerts.user) + // ); + // }); }); it('Legacy alerts = 0, Beta alerts > 0, => beta disabled', function () { @@ -384,13 +382,13 @@ describe('region enables alerts', function () { .should('be.enabled') .click(); }); - // TODO: not prompted by Save Alerts? dialog - cy.wait('@updateLinode').then((xhr) => { - // can save changes. new beta alerts added in assertLinodeAlertsEnabled tests - const actual = xhr.request.body; - const expected = { alerts: mockDisabledLegacyAlerts }; - expect(JSON.stringify(actual)).to.equal(JSON.stringify(expected)); - }); + // TODO: this test passes but modal behavior will change when properly implemented in api (M3-10195) + // cy.wait('@updateLinode').then((xhr) => { + // // can save changes. new beta alerts added in assertLinodeAlertsEnabled tests + // const actual = xhr.request.body; + // const expected = { alerts: mockDisabledLegacyAlerts }; + // expect(JSON.stringify(actual)).to.equal(JSON.stringify(expected)); + // }); }); }); From a9ba8ac880ce64b33c118870cf9169b1e8938921 Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Tue, 15 Jul 2025 09:00:27 -0400 Subject: [PATCH 09/14] rename file --- .../e2e/core/linodes/{linode-alerts.spec.ts => alerts-edit.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/manager/cypress/e2e/core/linodes/{linode-alerts.spec.ts => alerts-edit.ts} (100%) diff --git a/packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts b/packages/manager/cypress/e2e/core/linodes/alerts-edit.ts similarity index 100% rename from packages/manager/cypress/e2e/core/linodes/linode-alerts.spec.ts rename to packages/manager/cypress/e2e/core/linodes/alerts-edit.ts From 68601292a9e5e6af8c4fefee089f9f4a5863ce9c Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Wed, 16 Jul 2025 07:58:58 -0400 Subject: [PATCH 10/14] rename file. fix comments accuracy. --- .../e2e/core/linodes/{alerts-edit.ts => alerts-edit.spec.ts} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename packages/manager/cypress/e2e/core/linodes/{alerts-edit.ts => alerts-edit.spec.ts} (99%) diff --git a/packages/manager/cypress/e2e/core/linodes/alerts-edit.ts b/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts similarity index 99% rename from packages/manager/cypress/e2e/core/linodes/alerts-edit.ts rename to packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts index 7bcf67e6d3f..bac872eb3e7 100644 --- a/packages/manager/cypress/e2e/core/linodes/alerts-edit.ts +++ b/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts @@ -47,8 +47,8 @@ const mockEnabledBetaAlerts = { * UI of Linode alerts tab based on beta and legacy alert values in linode.alerts. Dependent on region support for alerts * Legacy alerts = 0, Beta alerts = [], => legacy disabled * Legacy alerts > 0, Beta alerts = [], => legacy enabled - * Legacy alerts = 0, Beta alerts > 0, => beta enabled - * Legacy alerts > 0, Beta alerts > 0, => beta enabled + * Legacy alerts = 0, Beta alerts > 0, => beta disabled + * Legacy alerts > 0, Beta alerts > 0, => beta disabled */ describe('region enables alerts', function () { From 187cddfb2a976744f97693af24ff3f05eec9f294 Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Thu, 17 Jul 2025 11:12:19 -0400 Subject: [PATCH 11/14] comments claraification --- .../cypress/e2e/core/linodes/alerts-edit.spec.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts b/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts index bac872eb3e7..992b5122cd8 100644 --- a/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts @@ -45,10 +45,12 @@ const mockEnabledBetaAlerts = { /* * UI of Linode alerts tab based on beta and legacy alert values in linode.alerts. Dependent on region support for alerts - * Legacy alerts = 0, Beta alerts = [], => legacy disabled - * Legacy alerts > 0, Beta alerts = [], => legacy enabled - * Legacy alerts = 0, Beta alerts > 0, => beta disabled - * Legacy alerts > 0, Beta alerts > 0, => beta disabled + * Legacy alerts = 0, Beta alerts = [] (empty arrays or no values at all) => legacy disabled for `beta` stage OR beta disabled for `ga` stage + * Legacy alerts > 0, Beta alerts = [] (empty arrays or no values at all) => legacy enabled + * Legacy alerts = 0, Beta alerts has values (either system, user, or both) => beta disabled + * Legacy alerts > 0, Beta alerts has values (either system, user, or both) => beta disabled + * + * Note: Here, "disabled" means that all toggles are in the OFF state, but it's still editable (not read-only) */ describe('region enables alerts', function () { From 4305e27fce4bf0949fa231ef919285ab17ac890e Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Thu, 17 Jul 2025 11:32:41 -0400 Subject: [PATCH 12/14] cleanup after pr review --- .../manager/cypress/e2e/core/linodes/alerts-edit.spec.ts | 6 +++--- packages/manager/cypress/support/intercepts/linodes.ts | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts b/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts index 992b5122cd8..fe13ed18d64 100644 --- a/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts @@ -53,7 +53,7 @@ const mockEnabledBetaAlerts = { * Note: Here, "disabled" means that all toggles are in the OFF state, but it's still editable (not read-only) */ -describe('region enables alerts', function () { +xdescribe('region enables alerts', function () { beforeEach(() => { mockAppendFeatureFlags({ aclpBetaServices: { @@ -451,7 +451,7 @@ describe('region disables alerts. beta alerts not available regardless of linode }); }); - it('Legacy alerts > 0, Beta alerts = 0, => legacy disabled', function () { + it('Legacy alerts > 0, Beta alerts = 0, => legacy enabled', function () { const mockLinode = linodeFactory.build({ id: randomNumber(), label: randomLabel(), @@ -472,7 +472,7 @@ describe('region disables alerts. beta alerts not available regardless of linode // not possible to upgrade or downgrade cy.findByText(ALERTS_LEGACY_MODE_BUTTON_TEXT).should('not.exist'); cy.findByText(ALERTS_BETA_MODE_BUTTON_TEXT).should('not.exist'); - // alerts are disabled so all toggles are off but are not readonly + // legacy alerts are enabled ui.toggle.find().each(($toggle) => { cy.wrap($toggle) .should('have.attr', 'data-qa-toggle', 'true') diff --git a/packages/manager/cypress/support/intercepts/linodes.ts b/packages/manager/cypress/support/intercepts/linodes.ts index c613c747fed..d57a0f76908 100644 --- a/packages/manager/cypress/support/intercepts/linodes.ts +++ b/packages/manager/cypress/support/intercepts/linodes.ts @@ -788,6 +788,5 @@ export const mockGetLinodeStats = ( * @returns Cypress chainable. */ export const mockUpdateLinode = (linodeId: number): Cypress.Chainable => { - console.log('intercepting mockUpdateLinode'); return cy.intercept('PUT', apiMatcher(`linode/instances/${linodeId}`)); }; From 6882f2d4404be6cd3048562d3aafa13571673ce0 Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Thu, 17 Jul 2025 13:59:19 -0400 Subject: [PATCH 13/14] fix beta alerts enablement --- .../e2e/core/linodes/alerts-edit.spec.ts | 33 ++++++++++--------- .../manager/cypress/support/util/linodes.ts | 6 ++-- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts b/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts index fe13ed18d64..73c597e8ad4 100644 --- a/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts @@ -8,7 +8,7 @@ import { import { mockGetRegions } from 'support/intercepts/regions'; import { ui } from 'support/ui'; import { assertLinodeAlertsEnabled } from 'support/util/linodes'; -import { randomLabel, randomNumber } from 'support/util/random'; +import { randomLabel } from 'support/util/random'; import { alertFactory } from 'src/factories'; import { @@ -18,6 +18,7 @@ import { ALERTS_LEGACY_MODE_BUTTON_TEXT, } from 'src/features/Linodes/constants'; +const MOCK_LINODE_ID = 2; const mockDisabledLegacyAlerts = { cpu: 0, io: 0, @@ -47,13 +48,13 @@ const mockEnabledBetaAlerts = { * UI of Linode alerts tab based on beta and legacy alert values in linode.alerts. Dependent on region support for alerts * Legacy alerts = 0, Beta alerts = [] (empty arrays or no values at all) => legacy disabled for `beta` stage OR beta disabled for `ga` stage * Legacy alerts > 0, Beta alerts = [] (empty arrays or no values at all) => legacy enabled - * Legacy alerts = 0, Beta alerts has values (either system, user, or both) => beta disabled - * Legacy alerts > 0, Beta alerts has values (either system, user, or both) => beta disabled + * Legacy alerts = 0, Beta alerts has values (either system, user, or both) => beta enabled + * Legacy alerts > 0, Beta alerts has values (either system, user, or both) => beta enabled * * Note: Here, "disabled" means that all toggles are in the OFF state, but it's still editable (not read-only) */ -xdescribe('region enables alerts', function () { +describe('region enables alerts', function () { beforeEach(() => { mockAppendFeatureFlags({ aclpBetaServices: { @@ -81,16 +82,17 @@ xdescribe('region enables alerts', function () { severity: 1, status: 'enabled', type: 'system', + entity_ids: [MOCK_LINODE_ID.toString()], }), alertFactory.build({ id: 2, - description: randomLabel(), label: randomLabel(), service_type: 'linode', severity: 1, status: 'enabled', type: 'system', + entity_ids: [MOCK_LINODE_ID.toString()], }), alertFactory.build({ id: 3, @@ -100,6 +102,7 @@ xdescribe('region enables alerts', function () { severity: 1, status: 'enabled', type: 'user', + entity_ids: [MOCK_LINODE_ID.toString()], }), ]; cy.wrap(alertDefinitions).as('alertDefinitions'); @@ -108,9 +111,9 @@ xdescribe('region enables alerts', function () { ); }); - it('Legacy alerts = 0, Beta alerts = [] => legacy disabled', function () { + xit('Legacy alerts = 0, Beta alerts = [] => legacy disabled', function () { const mockLinode = linodeFactory.build({ - id: randomNumber(), + id: MOCK_LINODE_ID, label: randomLabel(), region: this.mockEnabledRegion.id, alerts: { @@ -169,9 +172,9 @@ xdescribe('region enables alerts', function () { }); }); - it('Legacy alerts > 0, Beta alerts = [] => legacy enabled. can upgrade to beta disabled', function () { + it('Legacy alerts > 0, Beta alerts = [] => legacy enabled. can upgrade to beta enabled', function () { const mockLinode = linodeFactory.build({ - id: randomNumber(), + id: MOCK_LINODE_ID, label: randomLabel(), region: this.mockEnabledRegion.id, alerts: { @@ -252,9 +255,9 @@ xdescribe('region enables alerts', function () { // }); }); - it('Legacy alerts = 0, Beta alerts > 0, => beta disabled', function () { + it('Legacy alerts = 0, Beta alerts > 0, => beta enabled', function () { const mockLinode = linodeFactory.build({ - id: randomNumber(), + id: 2, label: randomLabel(), region: this.mockEnabledRegion.id, alerts: { @@ -319,9 +322,9 @@ xdescribe('region enables alerts', function () { }); }); - it('Legacy alerts > 0, Beta alerts > 0, => beta disabled. can downgrade to legacy enabled', function () { + it('Legacy alerts > 0, Beta alerts > 0, => beta enabled. can downgrade to legacy enabled', function () { const mockLinode = linodeFactory.build({ - id: randomNumber(), + id: MOCK_LINODE_ID, label: randomLabel(), region: this.mockEnabledRegion.id, alerts: { @@ -417,7 +420,7 @@ describe('region disables alerts. beta alerts not available regardless of linode it('Legacy alerts = 0, Beta alerts > 0, => legacy disabled', function () { const mockLinode = linodeFactory.build({ - id: randomNumber(), + id: MOCK_LINODE_ID, label: randomLabel(), region: this.mockDisabledRegion.id, alerts: { @@ -453,7 +456,7 @@ describe('region disables alerts. beta alerts not available regardless of linode it('Legacy alerts > 0, Beta alerts = 0, => legacy enabled', function () { const mockLinode = linodeFactory.build({ - id: randomNumber(), + id: MOCK_LINODE_ID, label: randomLabel(), region: this.mockDisabledRegion.id, alerts: { ...mockEnabledLegacyAlerts }, diff --git a/packages/manager/cypress/support/util/linodes.ts b/packages/manager/cypress/support/util/linodes.ts index 2d1b2051f8c..174ed08ea9e 100644 --- a/packages/manager/cypress/support/util/linodes.ts +++ b/packages/manager/cypress/support/util/linodes.ts @@ -356,14 +356,14 @@ export const assertLinodeAlertsEnabled = (alertDefinitions: Alert[]) => { cy.get('td') .eq(0) .within(() => { - // each alert's toggle should be editable + // each alert's toggle should be enabled/on/true and editable ui.toggle .find() - .should('have.attr', 'data-qa-toggle', 'false') + .should('have.attr', 'data-qa-toggle', 'true') .should('be.visible') .should('be.enabled') .click(); - ui.toggle.find().should('have.attr', 'data-qa-toggle', 'true'); + ui.toggle.find().should('have.attr', 'data-qa-toggle', 'false'); }); cy.get('td') .eq(1) From a6d9ca5706fcba6d3d3ef37d282813ebe7a534e4 Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Fri, 18 Jul 2025 09:39:00 -0400 Subject: [PATCH 14/14] cleanup --- .../e2e/core/linodes/alerts-edit.spec.ts | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts b/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts index 73c597e8ad4..29418530955 100644 --- a/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/alerts-edit.spec.ts @@ -111,7 +111,7 @@ describe('region enables alerts', function () { ); }); - xit('Legacy alerts = 0, Beta alerts = [] => legacy disabled', function () { + it('Legacy alerts = 0, Beta alerts = [] => legacy disabled', function () { const mockLinode = linodeFactory.build({ id: MOCK_LINODE_ID, label: randomLabel(), @@ -223,7 +223,7 @@ describe('region enables alerts', function () { cy.contains(ALERTS_BETA_MODE_BANNER_TEXT); }); cy.wait(['@getAlertDefinitions']); - // toggles in table are off but can be turned on + // toggles in table are on but can be turned off assertLinodeAlertsEnabled(this.alertDefinitions); mockUpdateLinode(mockLinode.id).as('updateLinode'); @@ -234,7 +234,7 @@ describe('region enables alerts', function () { .click(); }); - // TODO: this test passes but modal behavior will change when properly implemented in api (M3-10195) + // TODO: this test passes but modal behavior may change when properly implemented in api (M3-10195) // ui.dialog // .findByTitle('Save Alerts?') // .should('be.visible') @@ -247,10 +247,10 @@ describe('region enables alerts', function () { // // can save changes. new beta alerts added in assertLinodeAlertsEnabled tests // const edits = xhr.request.body; // expect(JSON.stringify(edits.system)).to.equal( - // JSON.stringify(mockEnabledBetaAlerts.system) + // JSON.stringify([]) // ); // expect(JSON.stringify(edits.user)).to.equal( - // JSON.stringify(mockEnabledBetaAlerts.user) + // JSON.stringify([]) // ); // }); }); @@ -387,13 +387,23 @@ describe('region enables alerts', function () { .should('be.enabled') .click(); }); - // TODO: this test passes but modal behavior will change when properly implemented in api (M3-10195) - // cy.wait('@updateLinode').then((xhr) => { - // // can save changes. new beta alerts added in assertLinodeAlertsEnabled tests - // const actual = xhr.request.body; - // const expected = { alerts: mockDisabledLegacyAlerts }; - // expect(JSON.stringify(actual)).to.equal(JSON.stringify(expected)); + // TODO: this test passes but modal behavior may change when properly implemented in api (M3-10195) + // ui.dialog + // .findByTitle('Are you sure you want to save legacy Alerts?') + // .should('be.visible') + // .within(() => { + // ui.button.findByTitle('Confirm').should('be.visible') + // .click(); // }); + // TODO: this test passes but modal behavior will change when properly implemented in api (M3-10195) + // TODO: this test passes but modal behavior may change when properly implemented in api (M3-10195) + // ui.dialog + // .findByTitle('Save Alerts?') + // .should('be.visible') + // .within(() => { + // ui.button.findByTitle('Save').should('be.visible') + // .click(); + // }); }); });