From e35c5aff15c0469d1805fefd5e11a3feb11e40f3 Mon Sep 17 00:00:00 2001 From: Joe D'Amore Date: Tue, 7 May 2024 13:54:55 -0400 Subject: [PATCH] Add PG create test --- .../create-placement-groups.spec.ts | 141 ++++++++++++++++++ .../support/intercepts/placement-groups.ts | 17 +++ 2 files changed, 158 insertions(+) create mode 100644 packages/manager/cypress/e2e/core/placementGroups/create-placement-groups.spec.ts diff --git a/packages/manager/cypress/e2e/core/placementGroups/create-placement-groups.spec.ts b/packages/manager/cypress/e2e/core/placementGroups/create-placement-groups.spec.ts new file mode 100644 index 00000000000..088b40ce4c1 --- /dev/null +++ b/packages/manager/cypress/e2e/core/placementGroups/create-placement-groups.spec.ts @@ -0,0 +1,141 @@ +import { + mockAppendFeatureFlags, + mockGetFeatureFlagClientstream, +} from 'support/intercepts/feature-flags'; +import { makeFeatureFlagData } from 'support/util/feature-flags'; +import { mockGetAccount } from 'support/intercepts/account'; +import { accountFactory, placementGroupFactory } from 'src/factories'; +import { regionFactory } from 'src/factories'; +import { ui } from 'support/ui/'; + +import type { Flags } from 'src/featureFlags'; +import { mockGetRegions } from 'support/intercepts/regions'; +import { + mockCreatePlacementGroup, + mockGetPlacementGroups, +} from 'support/intercepts/placement-groups'; +import { randomLabel, randomNumber } from 'support/util/random'; +import { chooseRegion } from 'support/util/regions'; + +const mockAccount = accountFactory.build(); + +describe('Placement Group create flow', () => { + beforeEach(() => { + // TODO Remove feature flag mocks when `placementGroups` flag is retired. + mockAppendFeatureFlags({ + placementGroups: makeFeatureFlagData({ + beta: true, + enabled: true, + }), + }); + mockGetFeatureFlagClientstream(); + mockGetAccount(mockAccount); + }); + + /* + * - Confirms Placement Group create UI flow using mock API data. + * - Confirms that outgoing Placement Group create request contains expected data. + * - Confirms that Cloud automatically updates to list new Placement Group on landing page. + */ + it('can create Placement Group', () => { + const mockRegions = regionFactory.buildList(5, { + placement_group_limits: { + maximum_pgs_per_customer: randomNumber(), + }, + capabilities: [ + 'Linodes', + 'NodeBalancers', + 'Block Storage', + 'Object Storage', + 'Kubernetes', + 'Cloud Firewall', + 'Placement Group', + 'Vlans', + 'Premium Plans', + ], + }); + + const mockPlacementGroupRegion = chooseRegion({ + regions: mockRegions, + capabilities: ['Placement Group'], + }); + + const mockPlacementGroup = placementGroupFactory.build({ + label: randomLabel(), + region: mockPlacementGroupRegion.id, + affinity_type: 'anti_affinity:local', + is_strict: true, + is_compliant: true, + }); + + const placementGroupLimitMessage = `Maximum placement groups in region: ${mockPlacementGroupRegion.placement_group_limits.maximum_pgs_per_customer}`; + const affinityTypeMessage = + 'Once you create a placement group, you cannot change its Affinity Type Enforcement setting.'; + + mockGetRegions(mockRegions); + mockGetPlacementGroups([]).as('getPlacementGroups'); + mockCreatePlacementGroup(mockPlacementGroup).as('createPlacementGroup'); + + cy.visitWithLogin('/placement-groups'); + cy.wait('@getPlacementGroups'); + + ui.button + .findByTitle('Create Placement Group') + .should('be.visible') + .should('be.enabled') + .click(); + + mockGetPlacementGroups([mockPlacementGroup]).as('getPlacementGroups'); + ui.drawer + .findByTitle('Create Placement Group') + .should('be.visible') + .within(() => { + // Confirm that create button is disabled before user selects region, etc. + ui.buttonGroup + .findButtonByTitle('Create Placement Group') + .should('be.disabled'); + + // Enter label, select region, and submit form. + cy.findByLabelText('Label').type(mockPlacementGroup.label); + + cy.findByLabelText('Region') + .click() + .type(`${mockPlacementGroupRegion.label}{enter}`); + + cy.findByText(placementGroupLimitMessage).should('be.visible'); + cy.findByText(affinityTypeMessage).should('be.visible'); + + ui.buttonGroup + .findButtonByTitle('Create Placement Group') + .should('be.visible') + .should('be.enabled') + .click(); + }); + + // Wait for outgoing API request and confirm that payload contains + // the options/data chosen by the user. + cy.wait('@createPlacementGroup').then((xhr) => { + const requestPayload = xhr.request?.body; + expect(requestPayload['affinity_type']).to.equal('anti_affinity:local'); + expect(requestPayload['is_strict']).to.equal(true); + expect(requestPayload['label']).to.equal(mockPlacementGroup.label); + expect(requestPayload['region']).to.equal(mockPlacementGroupRegion.id); + }); + + ui.toast.assertMessage( + `Placement Group ${mockPlacementGroup.label} successfully created.` + ); + + // Confirm that Cloud automatically updates to list the new Placement Group, + // and that the expected information is displayed. + cy.findByText(mockPlacementGroup.label) + .should('be.visible') + .closest('tr') + .within(() => { + cy.findByText('Anti-affinity').should('be.visible'); + cy.findByText('Strict').should('be.visible'); + cy.findByText(mockPlacementGroupRegion.label).should('be.visible'); + cy.findByText('Non-compliant').should('not.exist'); + }); + }); +}); diff --git a/packages/manager/cypress/support/intercepts/placement-groups.ts b/packages/manager/cypress/support/intercepts/placement-groups.ts index b059227446d..6f2bca0d5d1 100644 --- a/packages/manager/cypress/support/intercepts/placement-groups.ts +++ b/packages/manager/cypress/support/intercepts/placement-groups.ts @@ -21,6 +21,23 @@ export const mockGetPlacementGroups = ( ); }; +/** + * Intercept POST request to create a Placement Group and mocks response. + * + * @param placementGroup - Placement group object with which to mock response. + * + * @returns Cypress chainable. + */ +export const mockCreatePlacementGroup = ( + placementGroup: PlacementGroup +): Cypress.Chainable => { + return cy.intercept( + 'POST', + apiMatcher('placement/groups'), + makeResponse(placementGroup) + ); +}; + /** * Intercepts DELETE request to delete Placement Group and mocks response. *