Skip to content

Commit 28ec548

Browse files
test: [M3-10405 & M3-10406] - LKE Standard and Enterprise Cluster Create Tests for LKE-E Post-LA (linode#12831)
* Add page utils for LKE create page * Add LKE and LKE-E post-LA create tests * Add tests to confirm create flow behavior when switching LKE tiers * Added changeset: Add Cypress tests for LKE-E post-LA create flows
1 parent c18c328 commit 28ec548

File tree

7 files changed

+830
-1
lines changed

7 files changed

+830
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Tests
3+
---
4+
5+
Add Cypress tests for LKE-E post-LA create flows ([#12831](https://github.com/linode/manager/pull/12831))

packages/manager/cypress/e2e/core/kubernetes/lke-create.spec.ts

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,15 @@ import {
2424
latestKubernetesVersion,
2525
mockedLKEClusterTypes,
2626
mockedLKEEnterprisePrices,
27+
mockTieredEnterpriseVersions,
28+
mockTieredStandardVersions,
29+
mockTieredVersions,
2730
nanodeNodeCount,
2831
nanodeType,
2932
} from 'support/constants/lke';
3033
import { mockGetAccount } from 'support/intercepts/account';
3134
import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags';
35+
import { mockGetFirewalls } from 'support/intercepts/firewalls';
3236
import { mockGetLinodeTypes } from 'support/intercepts/linodes';
3337
import {
3438
mockCreateCluster,
@@ -48,11 +52,13 @@ import {
4852
mockGetRegions,
4953
} from 'support/intercepts/regions';
5054
import { ui } from 'support/ui';
55+
import { lkeClusterCreatePage } from 'support/ui/pages';
5156
import { randomItem, randomLabel, randomNumber } from 'support/util/random';
5257
import { chooseRegion, extendRegion } from 'support/util/regions';
5358

5459
import {
5560
accountFactory,
61+
firewallFactory,
5662
kubeLinodeFactory,
5763
kubernetesClusterFactory,
5864
kubernetesControlPlaneACLFactory,
@@ -64,6 +70,7 @@ import {
6470
CLUSTER_VERSIONS_DOCS_LINK,
6571
} from 'src/features/Kubernetes/constants';
6672
import { getTotalClusterMemoryCPUAndStorage } from 'src/features/Kubernetes/kubeUtils';
73+
import { extendType } from 'src/utilities/extendType';
6774
import { getTotalClusterPrice } from 'src/utilities/pricing/kubernetes';
6875

6976
import type { PriceType } from '@linode/api-v4/lib/types';
@@ -1587,6 +1594,263 @@ describe('LKE Cluster Creation with LKE-E', () => {
15871594
});
15881595
});
15891596

1597+
/*
1598+
* Tests for standard LKE create flow when the `lkeEnterprise.postLa` feature flag is enabled.
1599+
* The main change introduced by this feature flag is a new flow when adding node pools:
1600+
* Node pool size is specified inside of a configuration drawer instead of directly in the plan table,
1601+
* and additional node pool options have been added exclusively for LKE Enterprise clusters.
1602+
*/
1603+
describe('LKE cluster creation with LKE-E Post-LA', () => {
1604+
const mockRegions = [
1605+
...regionFactory.buildList(3, {
1606+
capabilities: ['Linodes', 'Kubernetes'],
1607+
}),
1608+
...regionFactory.buildList(3, {
1609+
capabilities: ['Linodes', 'Kubernetes', 'Kubernetes Enterprise'],
1610+
}),
1611+
];
1612+
1613+
const mockPlan = extendType(linodeTypeFactory.build({ class: 'standard' }));
1614+
const mockPlans = [
1615+
mockPlan,
1616+
...linodeTypeFactory
1617+
.buildList(10, { class: 'standard' })
1618+
.map((plan) => extendType(plan)),
1619+
];
1620+
1621+
beforeEach(() => {
1622+
// TODO M3-8838: Remove feature flag `lkeEnterprise` mocks, remove redundant tests as-needed.
1623+
mockAppendFeatureFlags({
1624+
lkeEnterprise: {
1625+
enabled: true,
1626+
la: true,
1627+
postLa: true,
1628+
phase2Mtc: false,
1629+
},
1630+
});
1631+
mockGetAccount(
1632+
accountFactory.build({
1633+
capabilities: ['Kubernetes Enterprise'],
1634+
})
1635+
);
1636+
mockGetKubernetesVersions(mockTieredVersions.map((version) => version.id));
1637+
mockGetTieredKubernetesVersions('standard', mockTieredStandardVersions);
1638+
mockGetTieredKubernetesVersions('enterprise', mockTieredEnterpriseVersions);
1639+
});
1640+
1641+
/*
1642+
* - Confirms that a user can create a standard LKE cluster when the LKE-E Post-LA feature is enabled.
1643+
* - Confirms that user can add and configure node pools via the Configure Node Pools drawer.
1644+
* - Confirms that LKE-E-specific node pool options are absent when configuring pools for standard clusters.
1645+
* - Confirms that outgoing cluster create API request contains the expected payload data.
1646+
* - Confirms that UI redirects to cluster details page upon successful cluster creation.
1647+
*/
1648+
it('can create standard LKE clusters with the LKE-E Post-LA feature enabled', () => {
1649+
const mockCluster = kubernetesClusterFactory.build({
1650+
label: randomLabel(),
1651+
tier: 'standard',
1652+
region: chooseRegion({
1653+
capabilities: ['Linodes', 'Kubernetes'],
1654+
regions: mockRegions,
1655+
}).id,
1656+
});
1657+
1658+
mockGetRegions(mockRegions);
1659+
mockGetLinodeTypes(mockPlans);
1660+
mockCreateCluster(mockCluster).as('createCluster');
1661+
mockGetCluster(mockCluster);
1662+
1663+
cy.visitWithLogin('/kubernetes/create');
1664+
1665+
// Configure a standard LKE cluster.
1666+
lkeClusterCreatePage.setLabel(mockCluster.label);
1667+
lkeClusterCreatePage.selectClusterTier('standard');
1668+
lkeClusterCreatePage.selectRegionById(mockCluster.region, mockRegions);
1669+
lkeClusterCreatePage.setEnableApl(false);
1670+
lkeClusterCreatePage.setEnableHighAvailability(false);
1671+
1672+
// Configure a node pool with the default pool size of 3.
1673+
// Additionally assert that LKE-E specific options are absent in the drawer,
1674+
// and that the order summary section updates to reflect the user's selection.
1675+
lkeClusterCreatePage.selectPlanTab('Shared CPU');
1676+
lkeClusterCreatePage.selectNodePoolPlan(mockPlan.formattedLabel);
1677+
lkeClusterCreatePage.withinNodePoolDrawer(mockPlan.formattedLabel, () => {
1678+
cy.findByLabelText('Update Strategy').should('not.exist');
1679+
cy.findByLabelText('Firewall').should('not.exist');
1680+
1681+
ui.button
1682+
.findByTitle('Add Pool')
1683+
.should('be.visible')
1684+
.should('be.enabled')
1685+
.click();
1686+
});
1687+
1688+
lkeClusterCreatePage.withinOrderSummary(() => {
1689+
cy.contains(mockPlan.formattedLabel)
1690+
.closest('[data-testid="node-pool-summary"]')
1691+
.within(() => {
1692+
cy.findByText('3 Nodes').should('be.visible');
1693+
cy.findByText('Edit Configuration').should('be.visible').click();
1694+
});
1695+
});
1696+
1697+
// Confirm that node pool size can be configured, and that the order summary
1698+
// UI updates upon clicking the "Update Pool" button.
1699+
lkeClusterCreatePage.withinNodePoolDrawer(mockPlan.formattedLabel, () => {
1700+
cy.findByLabelText('Add 1')
1701+
.should('be.visible')
1702+
.should('be.enabled')
1703+
.click();
1704+
1705+
ui.button
1706+
.findByTitle('Update Pool')
1707+
.should('be.visible')
1708+
.should('be.enabled')
1709+
.click();
1710+
});
1711+
1712+
lkeClusterCreatePage.withinOrderSummary(() => {
1713+
cy.contains(mockPlan.formattedLabel)
1714+
.closest('[data-testid="node-pool-summary"]')
1715+
.within(() => {
1716+
cy.findByText('4 Nodes').should('be.visible');
1717+
});
1718+
1719+
// Create the LKE cluster and confirm that the outgoing API request contains
1720+
// the expected payload data.
1721+
ui.button
1722+
.findByTitle('Create Cluster')
1723+
.should('be.visible')
1724+
.should('be.enabled')
1725+
.click();
1726+
});
1727+
1728+
cy.wait('@createCluster').then((xhr) => {
1729+
const body = xhr.request.body;
1730+
1731+
// Validate outgoing `node_pools` request payload configuration.
1732+
expect(body['node_pools']).to.be.an('array');
1733+
expect(body['node_pools']).to.have.length(1);
1734+
expect(body['node_pools'][0]!.type).to.equal(mockPlan.id);
1735+
expect(body['node_pools'][0]!.count).to.equal(4);
1736+
1737+
// Validate that the rest of the payload matches the user's input.
1738+
expect(body['region']).to.equal(mockCluster.region);
1739+
expect(body['label']).to.equal(mockCluster.label);
1740+
expect(body['tier']).to.equal('standard');
1741+
expect(body['apl_enabled']).to.be.false;
1742+
expect(body['control_plane']['acl']['enabled']).to.be.false;
1743+
expect(body['control_plane']['high_availability']).to.be.false;
1744+
});
1745+
1746+
cy.url().should(
1747+
'endWith',
1748+
`/kubernetes/clusters/${mockCluster.id}/summary`
1749+
);
1750+
});
1751+
1752+
/*
1753+
* - Confirms that regular LKE cluster creation works when a user initially configures an LKE-E cluster.
1754+
* - Configures an LKE-E cluster with LKE-E specific choices, then switches to a regular cluster before proceeding.
1755+
* - Confirms that outgoing cluster request respects user selection, cluster is created as expected.
1756+
*/
1757+
it('can switch to a standard cluster after configuring an LKE-E cluster with LKE-E Post-LA feature enabled', () => {
1758+
const mockCluster = kubernetesClusterFactory.build({
1759+
label: randomLabel(),
1760+
tier: 'standard',
1761+
region: chooseRegion({
1762+
capabilities: ['Linodes', 'Kubernetes', 'Kubernetes Enterprise'],
1763+
regions: mockRegions,
1764+
}).id,
1765+
});
1766+
1767+
const mockFirewall = firewallFactory.build();
1768+
1769+
mockGetRegions(mockRegions);
1770+
mockGetFirewalls([mockFirewall]);
1771+
mockGetLinodeTypes(mockPlans);
1772+
mockCreateCluster(mockCluster).as('createCluster');
1773+
mockGetCluster(mockCluster);
1774+
1775+
cy.visitWithLogin('/kubernetes/create');
1776+
1777+
lkeClusterCreatePage.setLabel(mockCluster.label);
1778+
lkeClusterCreatePage.selectClusterTier('enterprise');
1779+
lkeClusterCreatePage.selectRegionById(mockCluster.region, mockRegions);
1780+
lkeClusterCreatePage.selectPlanTab('Shared CPU');
1781+
1782+
// Confirm that order summary updates to reflect that Enterprise tier is selected,
1783+
// then configure a node pool.
1784+
lkeClusterCreatePage.withinOrderSummary(() => {
1785+
cy.findByText('LKE Enterprise').should('be.visible');
1786+
});
1787+
1788+
lkeClusterCreatePage.selectNodePoolPlan(mockPlan.formattedLabel);
1789+
lkeClusterCreatePage.withinNodePoolDrawer(mockPlan.formattedLabel, () => {
1790+
// Confirm that LKE-E specific options are present.
1791+
1792+
// Set "Update Strategy" to "Rolling Updates".
1793+
cy.findByText('Update Strategy').should('be.visible').click();
1794+
cy.focused().type('Rolling Updates');
1795+
ui.autocompletePopper.findByTitle('Rolling Updates').click();
1796+
1797+
// Select the existing mock firewall.
1798+
cy.findByText('Select existing firewall').click();
1799+
cy.get('[data-qa-autocomplete="Firewall"]').within(() => {
1800+
cy.findByLabelText('Firewall').type(mockFirewall.label);
1801+
ui.autocompletePopper.findByTitle(mockFirewall.label).click();
1802+
});
1803+
1804+
ui.button
1805+
.findByTitle('Add Pool')
1806+
.should('be.visible')
1807+
.should('be.enabled')
1808+
.click();
1809+
});
1810+
1811+
// Now switch to a standard LKE cluster, assert the state of the UI and
1812+
// outgoing API request after the user makes this switch.
1813+
lkeClusterCreatePage.selectClusterTier('standard');
1814+
lkeClusterCreatePage.setEnableApl(false);
1815+
lkeClusterCreatePage.setEnableHighAvailability(true);
1816+
1817+
lkeClusterCreatePage.withinOrderSummary(() => {
1818+
cy.findByText('LKE Enterprise').should('not.exist');
1819+
1820+
// Create the LKE cluster and assert that the outgoing API request contains
1821+
// the expected payload data.
1822+
ui.button
1823+
.findByTitle('Create Cluster')
1824+
.should('be.visible')
1825+
.should('be.enabled')
1826+
.click();
1827+
});
1828+
1829+
cy.wait('@createCluster').then((xhr) => {
1830+
const body = xhr.request.body;
1831+
expect(body['label']).to.equal(mockCluster.label);
1832+
expect(body['region']).to.equal(mockCluster.region);
1833+
expect(body['tier']).to.equal('standard');
1834+
expect(body['control_plane']['acl']['enabled']).to.be.false;
1835+
expect(body['control_plane']['high_availability']).to.be.true;
1836+
expect(body['apl_enabled']).to.be.false;
1837+
1838+
const nodePools = body['node_pools'];
1839+
expect(nodePools).to.be.an('array');
1840+
expect(nodePools).to.have.length(1);
1841+
expect(nodePools[0]).to.be.an('object');
1842+
expect(nodePools[0]['type']).to.equal(mockPlan.id);
1843+
expect(nodePools[0]['count']).to.equal(3);
1844+
1845+
// TODO M3-10590 - Uncomment and adjust according to chosen resolution.
1846+
// expect(nodePools[0]['update_strategy']).to.be.undefined;
1847+
// expect(nodePools[0]['firewall_id']).to.be.undefined;
1848+
});
1849+
1850+
cy.url().should('endWith', `kubernetes/clusters/${mockCluster.id}/summary`);
1851+
});
1852+
});
1853+
15901854
/**
15911855
* Returns each plan in an array which is similar to the given plan.
15921856
*

0 commit comments

Comments
 (0)