Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
260 changes: 260 additions & 0 deletions packages/manager/cypress/e2e/core/linodes/migrate-linode.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
import { authenticate } from 'support/api/authentication';
import {
mockGetLinodeDisks,
mockGetLinodeVolumes,
mockMigrateLinode,
} from 'support/intercepts/linodes';
import { ui } from 'support/ui';
import {
mockAppendFeatureFlags,
mockGetFeatureFlagClientstream,
} from 'support/intercepts/feature-flags';
import { makeFeatureFlagData } from 'support/util/feature-flags';
import { apiMatcher } from 'support/util/intercepts';
import { linodeFactory } from '@src/factories';
import { mockGetLinodeDetails } from 'support/intercepts/linodes';
import { getClick, fbtClick, containsClick } from 'support/helpers';
import { selectRegionString } from 'support/ui/constants';
import { getRegionById } from 'support/util/regions';
import {
dcPricingMockLinodeTypes,
dcPricingCurrentPriceLabel,
dcPricingNewPriceLabel,
} from 'support/constants/dc-specific-pricing';
import { mockGetLinodeType } from 'support/intercepts/linodes';
import { linodeDiskFactory } from '@src/factories';

authenticate();
describe('Migrate linodes', () => {
/*
* - Confirms DC-specific pricing does not show up during Linode migration when the feature flag is not enabled.
* - TODO This test should be updated to ignore the pricing information when the feature is released.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we mean that this test just not exist once DC-pricing goes live? The other two test cases test that pricing information is shown and isn't shown depending on region prices.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think so.

*/
it('can migrate linodes without DC-specific pricing comparison information when feature flag is disabled', () => {
const initialRegion = getRegionById('us-west');
const newRegion = getRegionById('us-east');

const mockLinode = linodeFactory.build({
region: initialRegion.id,
type: dcPricingMockLinodeTypes[0].id,
});

const mockLinodeDisks = linodeDiskFactory.buildList(3);

mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode');

// TODO Remove feature flag mocks once DC pricing is live.
mockAppendFeatureFlags({
dcSpecificPricing: makeFeatureFlagData(false),
}).as('getFeatureFlags');
mockGetFeatureFlagClientstream().as('getClientStream');

// Mock request to get Linode volumes and disks
mockGetLinodeDisks(mockLinode.id, mockLinodeDisks).as('getLinodeDisks');
mockGetLinodeVolumes(mockLinode.id, []).as('getLinodeVolumes');

// Mock requests to get individual types.
mockGetLinodeType(dcPricingMockLinodeTypes[0]);
mockGetLinodeType(dcPricingMockLinodeTypes[1]);

cy.visitWithLogin(`/linodes/${mockLinode.id}?migrate=true`);
cy.wait([
'@getClientStream',
'@getFeatureFlags',
'@getLinode',
'@getLinodeDisks',
'@getLinodeVolumes',
]);

ui.button.findByTitle('Enter Migration Queue').should('be.disabled');
cy.findByText(`${initialRegion.label}`).should('be.visible');
getClick('[data-qa-checked="false"]');
cy.findByText(`North America: ${initialRegion.label}`).should('be.visible');
containsClick(selectRegionString);

ui.regionSelect.findItemByRegionLabel(newRegion.label).click();

cy.findByText(dcPricingCurrentPriceLabel).should('not.exist');
const currentPrice = dcPricingMockLinodeTypes[0].region_prices.find(
(regionPrice) => regionPrice.id === initialRegion.id
);
cy.get('[data-testid="current-price-panel"]').should('not.exist');
cy.findByText(`$${currentPrice.monthly.toFixed(2)}`).should('not.exist');
cy.findByText(`$${currentPrice.hourly}`).should('not.exist');
cy.findByText(
`$${dcPricingMockLinodeTypes[0].addons.backups.price.monthly.toFixed(2)}`
).should('not.exist');

cy.findByText(dcPricingNewPriceLabel).should('not.exist');
const newPrice = dcPricingMockLinodeTypes[1].region_prices.find(
(linodeType) => linodeType.id === newRegion.id
);
cy.get('[data-testid="new-price-panel"]').should('not.exist');
cy.findByText(`$${newPrice.monthly.toFixed(2)}`).should('not.exist');
cy.findByText(`$${newPrice.hourly}`).should('not.exist');
cy.findByText(
`$${dcPricingMockLinodeTypes[1].addons.backups.price.monthly.toFixed(2)}`
).should('not.exist');

// intercept migration request and stub it, respond with 200
cy.intercept(
'POST',
apiMatcher(`linode/instances/${mockLinode.id}/migrate`),
{
statusCode: 200,
}
).as('migrateReq');

fbtClick('Enter Migration Queue');
cy.wait('@migrateReq').its('response.statusCode').should('eq', 200);
});

/*
* - Confirms DC-specific pricing UI flow works as expected during Linode migration.
* - Confirms that pricing comparison is shown in "Region" section when migration occurs in DCs with different price structures.
*/
it('shows DC-specific pricing information when migrating linodes between differently priced DCs', () => {
const initialRegion = getRegionById('us-west');
const newRegion = getRegionById('us-east');

const mockLinode = linodeFactory.build({
region: initialRegion.id,
type: dcPricingMockLinodeTypes[0].id,
});

const mockLinodeDisks = linodeDiskFactory.buildList(3);

mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode');

// TODO: DC Pricing - M3-7073: Remove feature flag mocks once DC pricing is live.
mockAppendFeatureFlags({
dcSpecificPricing: makeFeatureFlagData(true),
}).as('getFeatureFlags');
mockGetFeatureFlagClientstream().as('getClientStream');

// Mock request to get Linode volumes and disks
mockGetLinodeDisks(mockLinode.id, mockLinodeDisks).as('getLinodeDisks');
mockGetLinodeVolumes(mockLinode.id, []).as('getLinodeVolumes');

// Mock requests to get get individual types.
mockGetLinodeType(dcPricingMockLinodeTypes[0]);
mockGetLinodeType(dcPricingMockLinodeTypes[1]);

cy.visitWithLogin(`/linodes/${mockLinode.id}?migrate=true`);
cy.wait([
'@getClientStream',
'@getFeatureFlags',
'@getLinode',
'@getLinodeDisks',
'@getLinodeVolumes',
]);

ui.button.findByTitle('Enter Migration Queue').should('be.disabled');
cy.findByText(`${initialRegion.label}`).should('be.visible');
getClick('[data-qa-checked="false"]');
cy.findByText(`North America: ${initialRegion.label}`).should('be.visible');
containsClick(selectRegionString);

ui.regionSelect.findItemByRegionLabel(newRegion.label).click();

cy.findByText(dcPricingCurrentPriceLabel).should('be.visible');
const currentPrice = dcPricingMockLinodeTypes[0].region_prices.find(
(regionPrice) => regionPrice.id === initialRegion.id
);
cy.get('[data-testid="current-price-panel"]').within(() => {
cy.findByText(`$${currentPrice.monthly.toFixed(2)}`).should('be.visible');
cy.findByText(`$${currentPrice.hourly}`).should('be.visible');
cy.findByText(
`$${dcPricingMockLinodeTypes[0].addons.backups.price.monthly.toFixed(
2
)}`
).should('be.visible');
});

cy.findByText(dcPricingNewPriceLabel).should('be.visible');
const newPrice = dcPricingMockLinodeTypes[1].region_prices.find(
(linodeType) => linodeType.id === newRegion.id
);
cy.get('[data-testid="new-price-panel"]').within(() => {
cy.findByText(`$${newPrice.monthly.toFixed(2)}`).should('be.visible');
cy.findByText(`$${newPrice.hourly}`).should('be.visible');
cy.findByText(
`$${dcPricingMockLinodeTypes[1].addons.backups.price.monthly.toFixed(
2
)}`
).should('be.visible');
});

// intercept migration request and stub it, respond with 200
mockMigrateLinode(mockLinode.id).as('migrateReq');

fbtClick('Enter Migration Queue');
cy.wait('@migrateReq').its('response.statusCode').should('eq', 200);
});

/*
* - Confirms DC-specific pricing UI flow works as expected during Linode migration.
* - Confirms that pricing comparison is not shown in "Region" section if migration occurs in a DC with the same price structure.
*/
it('shows DC-specific pricing information when migrating linodes within the same DC', () => {
const initialRegion = getRegionById('us-southeast');
const newRegion = getRegionById('us-central');

const mockLinode = linodeFactory.build({
region: initialRegion.id,
type: dcPricingMockLinodeTypes[0].id,
});

const mockLinodeDisks = linodeDiskFactory.buildList(3);

mockGetLinodeDetails(mockLinode.id, mockLinode).as('getLinode');

// TODO: DC Pricing - M3-7073: Remove feature flag mocks once DC pricing is live.
mockAppendFeatureFlags({
dcSpecificPricing: makeFeatureFlagData(true),
}).as('getFeatureFlags');
mockGetFeatureFlagClientstream().as('getClientStream');

// Mock request to get Linode volumes and disks
mockGetLinodeDisks(mockLinode.id, mockLinodeDisks).as('getLinodeDisks');
mockGetLinodeVolumes(mockLinode.id, []).as('getLinodeVolumes');

// Mock requests to get individual types.
mockGetLinodeType(dcPricingMockLinodeTypes[0]);
mockGetLinodeType(dcPricingMockLinodeTypes[1]);

cy.visitWithLogin(`/linodes/${mockLinode.id}?migrate=true`);
cy.wait([
'@getClientStream',
'@getFeatureFlags',
'@getLinode',
'@getLinodeDisks',
'@getLinodeVolumes',
]);

ui.button.findByTitle('Enter Migration Queue').should('be.disabled');
cy.findByText(`${initialRegion.label}`).should('be.visible');
getClick('[data-qa-checked="false"]');

// Confirm that user cannot select the Linode's current DC when migrating.
cy.findByText('New Region').click().type(`${initialRegion.label}{enter}`);
cy.findByText('No results').should('be.visible');
// Confirm that DC pricing information does not show up
cy.findByText(dcPricingCurrentPriceLabel).should('not.exist');
cy.get('[data-testid="current-price-panel"]').should('not.exist');
cy.findByText(dcPricingNewPriceLabel).should('not.exist');
cy.get('[data-testid="new-price-panel"]').should('not.exist');
// Change region selection to another region with the same price structure.
cy.findByText('New Region').click().type(`${newRegion.label}{enter}`);
// Confirm that DC pricing information still does not show up.
cy.findByText(dcPricingCurrentPriceLabel).should('not.exist');
cy.get('[data-testid="current-price-panel"]').should('not.exist');
cy.findByText(dcPricingNewPriceLabel).should('not.exist');
cy.get('[data-testid="new-price-panel"]').should('not.exist');
// Confirm that migration queue button is enabled.
ui.button
.findByTitle('Enter Migration Queue')
.should('be.visible')
.should('be.enabled');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ export const dcPricingDocsLabel = 'How Data Center Pricing Works';
/** DC-specific pricing docs link destination. */
export const dcPricingDocsUrl = 'https://www.linode.com/pricing';

/** DC-specific pricing current price label. */
export const dcPricingCurrentPriceLabel = 'Current Price';

/** DC-specific pricing new price label. */
export const dcPricingNewPriceLabel = 'New Price';

/** DC-specific pricing Linode type mocks. */
export const dcPricingMockLinodeTypes = linodeTypeFactory.buildList(3, {
region_prices: [
Expand Down
19 changes: 19 additions & 0 deletions packages/manager/cypress/support/intercepts/linodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,22 @@ export const mockGetLinodeType = (
makeResponse(type)
);
};

/**
* Intercepts POST request to migrate a Linode.
*
* @param linodeId - ID of Linode being cloned.
*
* @returns Cypress chainable.
*/
export const mockMigrateLinode = (
linodeId: number
): Cypress.Chainable<null> => {
return cy.intercept(
'POST',
apiMatcher(`linode/instances/${linodeId}/migrate`),
{
statusCode: 200,
}
);
};