From e9ce45de672cc5c992825a5fac1f43962eb4df9b Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Wed, 20 Aug 2025 06:40:05 -0700 Subject: [PATCH 1/5] initial commit --- .../create-linode-vmHostMaintenance.spec.ts | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 packages/manager/cypress/e2e/core/linodes/create-linode-vmHostMaintenance.spec.ts diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-vmHostMaintenance.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-vmHostMaintenance.spec.ts new file mode 100644 index 00000000000..0a7916ccc25 --- /dev/null +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-vmHostMaintenance.spec.ts @@ -0,0 +1,163 @@ +import { regionFactory } from '@linode/utilities'; +import { mockGetAccountSettings } from 'support/intercepts/account'; +import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { interceptCreateLinode } from 'support/intercepts/linodes'; +import { mockGetRegions } from 'support/intercepts/regions'; +import { ui } from 'support/ui'; +import { randomString } from 'support/util/random'; + +import { accountSettingsFactory } from 'src/factories'; + +describe('vmHostMaintenance feature flag', function () { + beforeEach(() => { + mockGetAccountSettings( + accountSettingsFactory.build({ + maintenance_policy: 'linode/power_off_on', + }) + ).as('getAccountSettings'); + const mockEnabledRegion = regionFactory.build({ + capabilities: ['Linodes', 'Maintenance Policy'], + }); + const mockDisabledRegion = regionFactory.build({ + capabilities: ['Linodes'], + }); + const mockRegions = [mockEnabledRegion, mockDisabledRegion]; + cy.wrap(mockRegions).as('mockRegions'); + mockGetRegions(mockRegions).as('getRegions'); + }); + + it('Create flow when vmHostMaintenance feature flag is enabled', function () { + const enabledRegion = this.mockRegions[0]; + const disabledRegion = this.mockRegions[1]; + mockAppendFeatureFlags({ + vmHostMaintenance: { + enabled: true, + }, + }).as('getFeatureFlags'); + + interceptCreateLinode().as('createLinode'); + + cy.visitWithLogin('/linodes/create'); + cy.wait(['@getAccountSettings', '@getFeatureFlags', '@getRegions']); + + // "Host Maintenance Policy" section is present under the "Additional Options" + cy.contains('Additional Options').should('be.visible'); + cy.get('[data-qa-panel="Host Maintenance Policy"]') + .should('be.visible') + .within(() => { + cy.get('[data-qa-panel-summary="Host Maintenance Policy"]').click(); + }); + cy.get('[data-qa-autocomplete="Maintenance Policy"]') + .should('be.visible') + .within(() => { + cy.get('input[data-testid="textfield-input"]') + .should('be.visible') + .should('be.disabled'); + cy.findByText('Select a region to choose a maintenance policy.').should( + 'be.visible' + ); + ui.tooltip + .findByText("You don't have permission to change this setting.") + .should('be.visible'); + }); + + // user selects region that does not have the "Maintenance Policy" capability + ui.regionSelect.find().click(); + ui.regionSelect.find().type(`${disabledRegion.label}{enter}`); + cy.get('[data-qa-autocomplete="Maintenance Policy"]') + .should('be.visible') + .within(() => { + cy.get('input[data-testid="textfield-input"]') + .should('be.visible') + .should('be.disabled'); + cy.findByText( + 'Maintenance policy is not available in the selected region.' + ).should('be.visible'); + }); + + // user selects region that does have the "Maintenance Policy" capability + ui.regionSelect.find().click(); + ui.regionSelect.find().clear(); + ui.regionSelect.find().type(`${enabledRegion.label}{enter}`); + cy.get('[data-qa-autocomplete="Maintenance Policy"]') + .should('be.visible') + .within(() => { + cy.get('input[data-testid="textfield-input"]') + .should('be.visible') + .should('be.enabled'); + }); + + // form prerequisites + cy.get('[type="password"]').should('be.visible').scrollIntoView(); + cy.get('[id="root-password"]').type(randomString(12)); + cy.get('table[aria-label="List of Linode Plans"] tbody tr') + .first() + .within(() => { + cy.get('td') + .first() + .within(() => { + cy.get('input').should('be.enabled').click(); + }); + }); + + cy.scrollTo('bottom'); + ui.button + .findByTitle('View Code Snippets') + .should('be.visible') + .should('be.enabled') + .click(); + + // maintenance policy is included in the code snippets + ui.dialog + .findByTitle('Create Linode') + .should('be.visible') + .within(() => { + cy.get('pre code') + .should('be.visible') + .within(() => { + cy.contains('--maintenance_policy linode/migrate'); + }); + // cURL tab + ui.tabList.findTabByTitle('cURL').should('be.visible').click(); + cy.get('pre code') + .should('be.visible') + .within(() => { + cy.contains('"maintenance_policy": "linode/migrate"'); + }); + ui.button + .findByTitle('Close') + .should('be.visible') + .should('be.enabled') + .click(); + }); + // submit + ui.button + .findByTitle('Create Linode') + .should('be.visible') + .should('be.enabled') + .click(); + // POST payload should include maintenance_policy + cy.wait('@createLinode').then((intercept) => { + expect(intercept.request.body['maintenance_policy']).to.eq( + 'linode/migrate' + ); + }); + }); + + it('Create flow when vmHostMaintenance feature flag is disabled', function () { + const enabledRegion = this.mockRegions[0]; + mockAppendFeatureFlags({ + vmHostMaintenance: { + enabled: false, + }, + }).as('getFeatureFlags'); + cy.visitWithLogin('/linodes/create'); + cy.wait(['@getAccountSettings', '@getFeatureFlags', '@getRegions']); + + ui.regionSelect.find().click(); + ui.regionSelect.find().type(`${enabledRegion.label}{enter}`); + + // "Host Maintenance Policy" section is not present + cy.get('[data-qa-panel="Host Maintenance Policy"]').should('not.exist'); + }); +}); From fd2fab0b4dbbdc8d78995191e215a0b670b9138c Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Wed, 20 Aug 2025 06:49:27 -0700 Subject: [PATCH 2/5] Added changeset: Tests for Host & VM Maintenance in Linode create page --- packages/manager/.changeset/pr-12734-tests-1755697767741.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/manager/.changeset/pr-12734-tests-1755697767741.md diff --git a/packages/manager/.changeset/pr-12734-tests-1755697767741.md b/packages/manager/.changeset/pr-12734-tests-1755697767741.md new file mode 100644 index 00000000000..0dbc1731780 --- /dev/null +++ b/packages/manager/.changeset/pr-12734-tests-1755697767741.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Tests +--- + +Tests for Host & VM Maintenance in Linode create page ([#12734](https://github.com/linode/manager/pull/12734)) From 72afdd507c08786b4e5ec06bca25c2c68ff04b59 Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Mon, 25 Aug 2025 07:20:35 -0700 Subject: [PATCH 3/5] remove deprecated tooltip --- .../e2e/core/linodes/create-linode-vmHostMaintenance.spec.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-vmHostMaintenance.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-vmHostMaintenance.spec.ts index 0a7916ccc25..38d18771066 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-vmHostMaintenance.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-vmHostMaintenance.spec.ts @@ -56,9 +56,6 @@ describe('vmHostMaintenance feature flag', function () { cy.findByText('Select a region to choose a maintenance policy.').should( 'be.visible' ); - ui.tooltip - .findByText("You don't have permission to change this setting.") - .should('be.visible'); }); // user selects region that does not have the "Maintenance Policy" capability From 494be70639367d911a322e0a54dfa7a0daf208d7 Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Wed, 3 Sep 2025 12:15:52 -0400 Subject: [PATCH 4/5] refactoring after review --- ...create-linode-vm-host-maintenance.spec.ts} | 84 ++++++++----------- 1 file changed, 36 insertions(+), 48 deletions(-) rename packages/manager/cypress/e2e/core/linodes/{create-linode-vmHostMaintenance.spec.ts => create-linode-vm-host-maintenance.spec.ts} (65%) diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-vmHostMaintenance.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-vm-host-maintenance.spec.ts similarity index 65% rename from packages/manager/cypress/e2e/core/linodes/create-linode-vmHostMaintenance.spec.ts rename to packages/manager/cypress/e2e/core/linodes/create-linode-vm-host-maintenance.spec.ts index 38d18771066..4ce48e1073f 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-vmHostMaintenance.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-vm-host-maintenance.spec.ts @@ -1,41 +1,40 @@ -import { regionFactory } from '@linode/utilities'; +import { linodeFactory, regionFactory } from '@linode/utilities'; import { mockGetAccountSettings } from 'support/intercepts/account'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; -import { interceptCreateLinode } from 'support/intercepts/linodes'; +import { mockCreateLinode } from 'support/intercepts/linodes'; import { mockGetRegions } from 'support/intercepts/regions'; import { ui } from 'support/ui'; -import { randomString } from 'support/util/random'; +import { randomLabel, randomString } from 'support/util/random'; import { accountSettingsFactory } from 'src/factories'; +const mockEnabledRegion = regionFactory.build({ + capabilities: ['Linodes', 'Maintenance Policy'], +}); +const mockDisabledRegion = regionFactory.build({ + capabilities: ['Linodes'], +}); -describe('vmHostMaintenance feature flag', function () { +describe('vmHostMaintenance feature flag', () => { beforeEach(() => { mockGetAccountSettings( accountSettingsFactory.build({ maintenance_policy: 'linode/power_off_on', }) ).as('getAccountSettings'); - const mockEnabledRegion = regionFactory.build({ - capabilities: ['Linodes', 'Maintenance Policy'], - }); - const mockDisabledRegion = regionFactory.build({ - capabilities: ['Linodes'], - }); - const mockRegions = [mockEnabledRegion, mockDisabledRegion]; - cy.wrap(mockRegions).as('mockRegions'); - mockGetRegions(mockRegions).as('getRegions'); + mockGetRegions([mockEnabledRegion, mockDisabledRegion]).as('getRegions'); }); - it('Create flow when vmHostMaintenance feature flag is enabled', function () { - const enabledRegion = this.mockRegions[0]; - const disabledRegion = this.mockRegions[1]; + it('Create flow when vmHostMaintenance feature flag is enabled', () => { mockAppendFeatureFlags({ vmHostMaintenance: { enabled: true, }, }).as('getFeatureFlags'); - - interceptCreateLinode().as('createLinode'); + const mockLinode = linodeFactory.build({ + label: randomLabel(), + region: mockEnabledRegion.id, + }); + mockCreateLinode(mockLinode).as('createLinode'); cy.visitWithLogin('/linodes/create'); cy.wait(['@getAccountSettings', '@getFeatureFlags', '@getRegions']); @@ -47,42 +46,32 @@ describe('vmHostMaintenance feature flag', function () { .within(() => { cy.get('[data-qa-panel-summary="Host Maintenance Policy"]').click(); }); - cy.get('[data-qa-autocomplete="Maintenance Policy"]') + ui.autocomplete + .findByLabel('Maintenance Policy') .should('be.visible') - .within(() => { - cy.get('input[data-testid="textfield-input"]') - .should('be.visible') - .should('be.disabled'); - cy.findByText('Select a region to choose a maintenance policy.').should( - 'be.visible' - ); - }); - + .should('be.disabled'); + cy.findByText('Select a region to choose a maintenance policy.').should( + 'be.visible' + ); // user selects region that does not have the "Maintenance Policy" capability ui.regionSelect.find().click(); - ui.regionSelect.find().type(`${disabledRegion.label}{enter}`); - cy.get('[data-qa-autocomplete="Maintenance Policy"]') + ui.regionSelect.find().type(`${mockDisabledRegion.label}{enter}`); + ui.autocomplete + .findByLabel('Maintenance Policy') .should('be.visible') - .within(() => { - cy.get('input[data-testid="textfield-input"]') - .should('be.visible') - .should('be.disabled'); - cy.findByText( - 'Maintenance policy is not available in the selected region.' - ).should('be.visible'); - }); + .should('be.disabled'); + cy.findByText( + 'Maintenance policy is not available in the selected region.' + ).should('be.visible'); // user selects region that does have the "Maintenance Policy" capability ui.regionSelect.find().click(); ui.regionSelect.find().clear(); - ui.regionSelect.find().type(`${enabledRegion.label}{enter}`); - cy.get('[data-qa-autocomplete="Maintenance Policy"]') + ui.regionSelect.find().type(`${mockEnabledRegion.label}{enter}`); + ui.autocomplete + .findByLabel('Maintenance Policy') .should('be.visible') - .within(() => { - cy.get('input[data-testid="textfield-input"]') - .should('be.visible') - .should('be.enabled'); - }); + .should('be.enabled'); // form prerequisites cy.get('[type="password"]').should('be.visible').scrollIntoView(); @@ -141,8 +130,7 @@ describe('vmHostMaintenance feature flag', function () { }); }); - it('Create flow when vmHostMaintenance feature flag is disabled', function () { - const enabledRegion = this.mockRegions[0]; + it('Create flow when vmHostMaintenance feature flag is disabled', () => { mockAppendFeatureFlags({ vmHostMaintenance: { enabled: false, @@ -152,7 +140,7 @@ describe('vmHostMaintenance feature flag', function () { cy.wait(['@getAccountSettings', '@getFeatureFlags', '@getRegions']); ui.regionSelect.find().click(); - ui.regionSelect.find().type(`${enabledRegion.label}{enter}`); + ui.regionSelect.find().type(`${mockEnabledRegion.label}{enter}`); // "Host Maintenance Policy" section is not present cy.get('[data-qa-panel="Host Maintenance Policy"]').should('not.exist'); From 2ed9a6973065d5065fc6f67a3ad5143e115dd588 Mon Sep 17 00:00:00 2001 From: dmcintyr-akamai Date: Wed, 3 Sep 2025 12:29:12 -0400 Subject: [PATCH 5/5] refactoring after review --- .../create-linode-vm-host-maintenance.spec.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode-vm-host-maintenance.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode-vm-host-maintenance.spec.ts index 4ce48e1073f..7f0e8989401 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode-vm-host-maintenance.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode-vm-host-maintenance.spec.ts @@ -4,6 +4,7 @@ import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; import { mockCreateLinode } from 'support/intercepts/linodes'; import { mockGetRegions } from 'support/intercepts/regions'; import { ui } from 'support/ui'; +import { linodeCreatePage } from 'support/ui/pages'; import { randomLabel, randomString } from 'support/util/random'; import { accountSettingsFactory } from 'src/factories'; @@ -76,16 +77,11 @@ describe('vmHostMaintenance feature flag', () => { // form prerequisites cy.get('[type="password"]').should('be.visible').scrollIntoView(); cy.get('[id="root-password"]').type(randomString(12)); - cy.get('table[aria-label="List of Linode Plans"] tbody tr') - .first() - .within(() => { - cy.get('td') - .first() - .within(() => { - cy.get('input').should('be.enabled').click(); - }); - }); - + const mockPlan = { + planType: 'Shared CPU', + planLabel: 'Nanode 1 GB', + }; + linodeCreatePage.selectPlan(mockPlan.planType, mockPlan.planLabel); cy.scrollTo('bottom'); ui.button .findByTitle('View Code Snippets')