Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: [M3-6052] - Add LKE cluster update and delete integration tests #9054

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1da1d4d
Add LKE get and delete mock utilities
Apr 17, 2023
711c4c2
Add WIP LKE deletion integration tests
Apr 17, 2023
a779620
Add WIP deletion integration test from summary page
Apr 17, 2023
e09f54d
Add mock util to retrieve LKE node pools
Apr 24, 2023
77a385d
Add integration test for LKE deletion via details page
Apr 24, 2023
7f9f82d
Add LKE landing page integration tests
Apr 24, 2023
ad38595
Ignore Cypress download files
Apr 24, 2023
378bada
Add Cypress downloaded file utils
Apr 24, 2023
a3dd67c
Add integration test to verify kubeconfig download flow via landing page
Apr 24, 2023
13512fc
Add util to mock kubeconfig GET request
Apr 24, 2023
2ad1631
Don't use factory for kubeconfig response
Apr 24, 2023
8ff8c4f
Add LKE mock utils to update cluster, get Kubernetes versions, and re…
Apr 24, 2023
6e3a4b6
Add WIP LKE update integration tests for HA upgrade, version upgrade,…
Apr 24, 2023
71207f1
Merge branch 'develop' into M3-6052-lke-update-delete
Apr 24, 2023
bb991f8
Add mock utils for creating and deleting LKE node pools
Apr 24, 2023
e54bf43
Add QA data attributes for node pool sections
Apr 24, 2023
c26267a
Add LKE integration tests for adding and removing node pools
Apr 24, 2023
e541f8c
Add WIP integration test for resizing, autoscaling, and recycling nod…
Apr 24, 2023
f57f11c
Add LKE mock util to update node pools
Apr 25, 2023
cf88b2f
Add QA data attributes for node pool rows
Apr 25, 2023
aaf5bce
Add Kubernetes dashboard response factory
Apr 25, 2023
bf20cce
Add LKE mock utils to recycle nodes and retrieve dashboard and API URLs
Apr 25, 2023
4d50cc1
Add LKE integration tests for recycling, resizing, and toggling autos…
Apr 25, 2023
d740f52
Remove unused import
Apr 25, 2023
d510cad
Dismiss LKE node recycle dialog upon confirmation
Apr 26, 2023
25710b9
Add changelog entry
Apr 26, 2023
6d4c4d9
Merge branch 'develop' into M3-6052-lke-update-delete
May 1, 2023
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ packages/manager/test-report.xml
**/manager/config/development.json
**/manager/config/staging.json
**/manager/cypress/videos/
**/manager/cypress/downloads/

# ignore all screenshots except records
# we ignore the png files, not the whole folder recursively
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Event entities should only be linked for true labels
- Radio button hover effect #9031
- Prevent form submission unless action was taken (IP transfer & IP sharing modals) #5976
- Recycle LKE Node confirmation dialog gets dismissed upon submission #9054
- Inability to edit and save Linode Configurations #9053

### Tech Stories:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @file LKE creation end-to-end tests.
*/

import { KubernetesCluster } from '@linode/api-v4/types';
import { KubernetesCluster } from '@linode/api-v4';
import { LkePlanDescription } from 'support/api/lke';
import { lkeClusterPlans } from 'support/constants/lke';
import { regionsFriendly } from 'support/constants/regions';
Expand Down
106 changes: 106 additions & 0 deletions packages/manager/cypress/e2e/kubernetes/lke-delete.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { kubernetesClusterFactory } from 'src/factories';
import {
mockGetCluster,
mockGetClusters,
mockDeleteCluster,
} from 'support/intercepts/lke';
import { ui } from 'support/ui';
import { randomLabel } from 'support/util/random';

/*
* Fills out and submits Type to Confirm deletion dialog for cluster with the given label.
*/
const completeTypeToConfirmDialog = (clusterLabel: string) => {
const deletionWarning = `Deleting a cluster is permanent and can't be undone.`;

ui.dialog
.findByTitle(`Delete Cluster ${clusterLabel}`)
.should('be.visible')
.within(() => {
cy.findByText(deletionWarning, { exact: false }).should('be.visible');
cy.findByLabelText('Cluster Name')
.should('be.visible')
.click()
.type(clusterLabel);

ui.buttonGroup
.findButtonByTitle('Delete Cluster')
.should('be.visible')
.should('be.enabled')
.click();
});
};

describe('LKE cluster deletion', () => {
/*
* - Confirms LKE cluster deletion flow via landing page.
* - Confirms that landing page updates to reflect deleted cluster.
*/
it('can delete an LKE cluster from summary page', () => {
const mockCluster = kubernetesClusterFactory.build({
label: randomLabel(),
});

mockGetClusters([mockCluster]).as('getClusters');
mockDeleteCluster(mockCluster.id).as('deleteCluster');
cy.visitWithLogin('/kubernetes/clusters');
cy.wait('@getClusters');

// Find mock cluster in table, click its "Delete" button.
cy.findByText(mockCluster.label)
.should('be.visible')
.closest('tr')
.within(() => {
ui.button
.findByTitle('Delete')
.should('be.enabled')
.should('be.visible')
.click();
});

// Fill out and submit type-to-confirm.
mockGetClusters([]).as('getClusters');
completeTypeToConfirmDialog(mockCluster.label);

// Confirm that cluster is no longer listed on landing page.
cy.wait(['@deleteCluster', '@getClusters']);
cy.findByText(mockCluster.label).should('not.exist');

// Confirm that Kubernetes welcome page is shown when there are no clusters.
cy.findByText('Fully managed Kubernetes infrastructure').should(
'be.visible'
);

ui.button
.findByTitle('Create Cluster')
.should('be.visible')
.should('be.enabled');
});

/*
* - Confirms LKE cluster deletion flow via details page.
* - Confirms that user is redirected to landing page upon cluster deletion.
*/
it('can delete an LKE cluster from landing page', () => {
const mockCluster = kubernetesClusterFactory.build({
label: randomLabel(),
});

// Navigate to details page for mocked LKE cluster.
mockGetCluster(mockCluster).as('getCluster');
mockDeleteCluster(mockCluster.id).as('deleteCluster');
cy.visitWithLogin(`/kubernetes/clusters/${mockCluster.id}/summary`);
cy.wait('@getCluster');

// Press "Delete Cluster" button, complete type-to-confirm, and confirm redirect.
ui.button
.findByTitle('Delete Cluster')
.should('be.visible')
.should('be.enabled')
.click();

completeTypeToConfirmDialog(mockCluster.label);
cy.wait('@deleteCluster');
cy.url().should('endWith', 'kubernetes/clusters');
});
});
108 changes: 108 additions & 0 deletions packages/manager/cypress/e2e/kubernetes/lke-landing-page.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import type { KubernetesCluster } from '@linode/api-v4';
import {
mockGetClusters,
mockGetClusterPools,
mockGetKubeconfig,
} from 'support/intercepts/lke';
import { kubernetesClusterFactory, nodePoolFactory } from 'src/factories';
import { regionsMap } from 'support/constants/regions';
import { readDownload } from 'support/util/downloads';
import { ui } from 'support/ui';

describe('LKE landing page', () => {
/*
* - Confirms that LKE clusters are listed on landing page.
*/
it('lists LKE clusters', () => {
const mockClusters = kubernetesClusterFactory.buildList(10);
mockGetClusters(mockClusters).as('getClusters');

mockClusters.forEach((cluster: KubernetesCluster) => {
mockGetClusterPools(cluster.id, nodePoolFactory.buildList(3));
});

cy.visitWithLogin('/kubernetes/clusters');
cy.wait('@getClusters');

mockClusters.forEach((cluster: KubernetesCluster) => {
cy.findByText(cluster.label)
.should('be.visible')
.closest('tr')
.within(() => {
cy.findByText(regionsMap[cluster.region]).should('be.visible');
cy.findByText(cluster.k8s_version).should('be.visible');

ui.button
.findByTitle('Download kubeconfig')
.should('be.visible')
.should('be.enabled');

ui.button
.findByTitle('Delete')
.should('be.visible')
.should('be.enabled');
});
});
});

/*
* - Confirms that welcome page is shown when no LKE clusters exist.
* - Confirms that core page elements (create button, guides, playlist, etc.) are present.
*/
it('shows welcome page when there are no LKE clusters', () => {
mockGetClusters([]).as('getClusters');
cy.visitWithLogin('/kubernetes/clusters');
cy.wait('@getClusters');

cy.findByText('Fully managed Kubernetes infrastructure').should(
'be.visible'
);

ui.button
.findByTitle('Create Cluster')
.should('be.visible')
.should('be.enabled');

cy.findByText('Getting Started Guides').should('be.visible');
cy.findByText('Video Playlist').should('be.visible');
});

/*
* - Confirms UI flow for Kubeconfig file downloading using mocked data.
* - Confirms that downloaded Kubeconfig contains expected content.
*/
it('can download kubeconfig', () => {
const mockCluster = kubernetesClusterFactory.build();
const mockClusterNodePools = nodePoolFactory.buildList(2);
const mockKubeconfigFilename = `${mockCluster.label}-kubeconfig.yaml`;
const mockKubeconfigContents = '---'; // Valid YAML.
const mockKubeconfigResponse = {
kubeconfig: btoa(mockKubeconfigContents),
};

mockGetClusters([mockCluster]).as('getClusters');
mockGetClusterPools(mockCluster.id, mockClusterNodePools).as(
'getNodePools'
);
mockGetKubeconfig(mockCluster.id, mockKubeconfigResponse).as(
'getKubeconfig'
);

cy.visitWithLogin('/kubernetes/clusters');
cy.wait(['@getClusters', '@getNodePools']);

cy.findByText(mockCluster.label)
.should('be.visible')
.closest('tr')
.within(() => {
ui.button
.findByTitle('Download kubeconfig')
.should('be.visible')
.should('be.enabled')
.click();
});

cy.wait('@getKubeconfig');
readDownload(mockKubeconfigFilename).should('eq', mockKubeconfigContents);
});
});
Loading