diff --git a/test-cypress/fixtures/cluster/save-cluster-configuration-response.json b/test-cypress/fixtures/cluster/save-cluster-configuration-response.json new file mode 100644 index 000000000..d566fecea --- /dev/null +++ b/test-cypress/fixtures/cluster/save-cluster-configuration-response.json @@ -0,0 +1,10 @@ +{ + "electionMinTimeout": 5000, + "electionRangeTimeout": 3000, + "heartbeatInterval": 1500, + "messageSizeKB": 64, + "verificationTimeout": 1200, + "transactionLogMaximumSizeGB": 50, + "batchUpdateInterval": 2000, + "nodes": ["pc-desktop:7300", "pc-desktop:7301", "pc-desktop:7302"] +} diff --git a/test-cypress/integration/cluster/cluster-configuration.spec.js b/test-cypress/integration/cluster/cluster-configuration.spec.js deleted file mode 100644 index d4eb09d83..000000000 --- a/test-cypress/integration/cluster/cluster-configuration.spec.js +++ /dev/null @@ -1,277 +0,0 @@ -import {ClusterPageSteps} from "../../steps/cluster/cluster-page-steps"; -import {GlobalOperationsStatusesStub} from "../../stubs/global-operations-statuses-stub"; -import {ClusterStubs} from "../../stubs/cluster/cluster-stubs"; -import {RemoteLocationStubs} from "../../stubs/cluster/remote-location-stubs"; -import {DeleteClusterDialogSteps} from "../../steps/cluster/delete-cluster-dialog-steps"; -import {ClusterConfigurationSteps} from "../../steps/cluster/cluster-configuration-steps"; -import {ModalDialogSteps} from "../../steps/modal-dialog-steps"; -import {ApplicationSteps} from "../../steps/application-steps"; - -describe('Cluster configuration', () => { - - let repositoryId; - - beforeEach(() => { - repositoryId = 'cluster-repo' + Date.now(); - GlobalOperationsStatusesStub.stubNoOperationsResponse(repositoryId); - }); - - it('Should display cluster configuration', () => { - // Given there is an existing cluster created - ClusterStubs.stubClusterConfig(); - ClusterStubs.stubClusterGroupStatus(); - ClusterStubs.stubClusterNodeStatus(); - RemoteLocationStubs.stubRemoteLocationFilter(); - RemoteLocationStubs.stubRemoteLocationStatusInCluster(); - // Given I have opened the cluster management page - ClusterPageSteps.visit(); - // When I click on edit properties - ClusterPageSteps.previewClusterConfig(); - // Then I should see cluster configuration with 3 tabs - ClusterConfigurationSteps.getClusterConfig().should('be.visible'); - ClusterConfigurationSteps.getTabs().should('have.length', 3); - ClusterConfigurationSteps.getActiveTab().should('have.text', 'Properties'); - ClusterConfigurationSteps.getClusterPropertiesTabContent().should('be.visible'); - ClusterConfigurationSteps.selectTab(1); - ClusterConfigurationSteps.getActiveTab().should('have.text', 'Nodes'); - ClusterConfigurationSteps.getClusterNodesTabContent().should('be.visible'); - ClusterConfigurationSteps.selectTab(2); - ClusterConfigurationSteps.getActiveTab().should('have.text', 'Multi-region'); - ClusterConfigurationSteps.getMultiRegionTabContent().should('be.visible'); - }); - - context('Properties', () => { - beforeEach(() => { - // Given there is an existing cluster created - ClusterStubs.stubClusterConfig(); - ClusterStubs.stubClusterGroupStatus(); - ClusterStubs.stubClusterNodeStatus(); - RemoteLocationStubs.stubRemoteLocationFilter(); - RemoteLocationStubs.stubRemoteLocationStatusInCluster(); - }); - - it('Should be able to delete cluster', () => { - // Given I have opened the cluster management page - ClusterPageSteps.visit(); - - ClusterPageSteps.getClusterPage().should('be.visible'); - ClusterPageSteps.getCreateClusterButton().should('not.have.class', 'no-cluster'); - // When I click on delete cluster - ClusterPageSteps.previewClusterConfig(); - ClusterConfigurationSteps.getClusterConfig().should('be.visible'); - ClusterConfigurationSteps.deleteCluster(); - // Then I expect a confirmation dialog to appear - DeleteClusterDialogSteps.getDialog().should('be.visible'); - // When I confirm - ClusterStubs.stubDeleteCluster(); - ClusterStubs.stubNoClusterGroupStatus(); - ClusterStubs.stubNoClusterNodeStatus(); - DeleteClusterDialogSteps.confirmDeleteCluster(); - // Then Cluster should be deleted - ClusterStubs.stubNoClusterConfig(); - RemoteLocationStubs.stubRemoteLocationStatusNotCluster(); - DeleteClusterDialogSteps.getDialog().should('not.exist'); - ClusterPageSteps.getRemoveNodesButton().should('not.exist'); - ClusterPageSteps.getAddNodesButton().should('not.exist'); - ClusterPageSteps.getReplaceNodesButton().should('not.exist'); - ClusterPageSteps.getPreviewClusterConfigButton().should('not.exist'); - ClusterPageSteps.getCreateClusterButton().should('have.class', 'no-cluster'); - }); - - it('Should be able to edit cluster properties', () => { - // Given I have opened the cluster management page - ClusterPageSteps.visit(); - // When I click on edit properties - ClusterPageSteps.previewClusterConfig(); - ClusterConfigurationSteps.getClusterConfig().should('be.visible'); - // When I press edit properties - ClusterConfigurationSteps.editProperties(); - // Then I expect a modal to be shown - ClusterConfigurationSteps.getModal().should('be.visible'); - // I can set values in form fields - ClusterConfigurationSteps.setFieldValue('electionMinTimeout', '5000'); - ClusterConfigurationSteps.setFieldValue('electionRangeTimeout', '3000'); - // Verify a field validation error appears if left empty - ClusterConfigurationSteps.getFieldByName('heartbeatInterval').clear(); - ClusterConfigurationSteps.verifyFieldError('heartbeatInterval', 'This field is required'); - // And Save button is disabled - ClusterConfigurationSteps.getSaveButton().should('be.disabled'); - // Set value for required field to enable Save button - ClusterConfigurationSteps.setFieldValue('heartbeatInterval', '1500'); - // And Save button is disabled - ClusterConfigurationSteps.getSaveButton().should('be.enabled'); - ClusterConfigurationSteps.setFieldValue('messageSizeKB', '64'); - ClusterConfigurationSteps.setFieldValue('verificationTimeout', '1200'); - ClusterConfigurationSteps.setFieldValue('transactionLogMaximumSizeGB', '50'); - ClusterConfigurationSteps.setFieldValue('batchUpdateInterval', '2000'); - - // Click Save button to submit - ClusterStubs.stubSaveClusterConfiguration(); - ClusterConfigurationSteps.save(); - const expectedRequestBody = { - electionMinTimeout: 5000, - electionRangeTimeout: 3000, - heartbeatInterval: 1500, - messageSizeKB: 64, - verificationTimeout: 1200, - transactionLogMaximumSizeGB: 50, - batchUpdateInterval: 2000 - }; - cy.wait('@save-cluster-properties').then((interception) => { - expect(interception.request.body).to.deep.equal(expectedRequestBody); - }); - // And the modal is closed - ClusterConfigurationSteps.getModal().should('not.exist'); - }); - }); - - context('Nodes', () => { - beforeEach(() => { - // Given there is an existing cluster created - ClusterStubs.stubClusterConfig(); - ClusterStubs.stubClusterGroupStatus(); - ClusterStubs.stubClusterNodeStatus(); - RemoteLocationStubs.stubRemoteLocationFilter(); - RemoteLocationStubs.stubRemoteLocationStatusInCluster(); - }); - it('should display the nodes list with correct node information in the modal', () => { - // Given I have opened the cluster management page - ClusterPageSteps.visit(); - // When I click on edit properties and open Nodes tab - ClusterPageSteps.previewClusterConfig(); - ClusterConfigurationSteps.selectTab(1); - // I expect to see - ClusterConfigurationSteps.getNodesListHeader().should('contain.text', 'Nodes list'); - ClusterConfigurationSteps.assertNodesCount(3); - - const nodeData = [ - { - url: 'http://pc-desktop:7200', - rpcAddress: 'pc-desktop:7300', - state: 'FOLLOWER', - local: true - }, - { - url: 'http://pc-desktop:7201', - rpcAddress: 'pc-desktop:7301', - state: 'LEADER', - local: false - }, - { - url: 'http://pc-desktop:7202', - rpcAddress: 'pc-desktop:7302', - state: 'FOLLOWER', - local: false - } - ]; - - nodeData.forEach((data, index) => { - ClusterConfigurationSteps.getNodeLink(index) - .should('have.attr', 'href', data.url) - .and('contain.text', data.url); - - ClusterConfigurationSteps.getNodeRPCAddress(index) - .should('contain.text', data.rpcAddress); - - ClusterConfigurationSteps.getNodeState(index) - .should('contain.text', data.state); - - if (data.local) { - ClusterConfigurationSteps.isNodeLocal(index).should('exist'); - } else { - ClusterConfigurationSteps.isNodeLocal(index).should('not.exist'); - } - }); - }); - }); - - context('Multi-region', () => { - beforeEach(() => { - // Given there is an existing cluster created - ClusterStubs.stubClusterConfig(); - ClusterStubs.stubClusterGroupStatus(); - ClusterStubs.stubClusterNodeStatus(); - RemoteLocationStubs.stubRemoteLocationFilter(); - RemoteLocationStubs.stubRemoteLocationStatusInCluster(); - }); - - context('Primary cluster', () => { - it('should be able to add and delete tags', () => { - const tagName = 'test'; - // Given I have opened the cluster management page - ClusterPageSteps.visit(); - // When I click on edit properties and open Nodes tab - ClusterPageSteps.previewClusterConfig(); - ClusterConfigurationSteps.selectTab(2); - // I expect to see - ClusterConfigurationSteps.getMultiRegionHeader().should('contain.text', 'Primary cluster'); - ClusterConfigurationSteps.getAddTagButton().should('be.visible').and('not.be.disabled'); - ClusterConfigurationSteps.getEnableSecondaryModeButton().should('be.visible').and('not.be.disabled'); - ClusterConfigurationSteps.getTagsTable().should('not.exist'); - - ClusterStubs.stubAddTag(tagName); - ClusterConfigurationSteps.clickAddTagButton(); - ClusterConfigurationSteps.typeTag(tagName); - ClusterConfigurationSteps.clickSubmitTagButton(); - cy.wait('@add-tag').then((interception) => { - expect(interception.request.body).to.deep.equal({tag: tagName}); - }); - - ClusterStubs.stubClusterGroupStatusWithTag(); - cy.wait('@3-nodes-cluster-group-status-tag').then(() => { - // Assert the tags table contains the expected tag - ClusterConfigurationSteps.getTagsTable().should('be.visible'); - ClusterConfigurationSteps.getTagsTableRows().should('contain.text', tagName); - }); - // And expect success message to be displayed. - ApplicationSteps.getSuccessNotifications().contains(`Successfully added to cluster primary identifier tag: ${tagName}`); - - //When I delete the tag - ClusterConfigurationSteps.clickDeleteTagButton(); - // I expect to see deleting confirmation dialog. - ModalDialogSteps.getDialogHeader().should('contain', `Delete identifier tag ${tagName}`); - ModalDialogSteps.getDialogBody().should('contain', 'Deleting identifier tag would stop any secondary cluster identified with it from pulling updates.'); - - // When I confirm - ClusterStubs.stubDeleteTag(tagName); - ModalDialogSteps.getConfirmButton().click(); - cy.wait('@delete-tag').then((interception) => { - expect(interception.request.body).to.deep.equal({tag: tagName}); - }); - }); - }); - - context('Secondary cluster', () => { - it('should be able to switch modes', () => { - ClusterStubs.stubEnableSecondaryMode(); - const rpcAddress = 'node-name:7300'; - const tag = 'us-central'; - - // Given I have opened the cluster management page - ClusterPageSteps.visit(); - // When I click on edit properties and open Nodes tab - ClusterPageSteps.previewClusterConfig(); - ClusterConfigurationSteps.selectTab(2); - // I click enable secondary mode btn - ClusterConfigurationSteps.clickEnableSecondaryModeButton(); - // I expect to see enable secondary mode confirmation dialog. - ModalDialogSteps.getDialogHeader().should('contain', `Enable secondary mode`); - ModalDialogSteps.getDialogBody().should('contain', 'By enabling secondary mode this cluster would become a read-only replica of the specified primary cluster.'); - // When I confirm I expect to see configuration modal - ModalDialogSteps.getConfirmButton().click(); - ModalDialogSteps.getDialogHeader().should('contain', `Secondary cluster settings`); - ClusterConfigurationSteps.getEnableButton().should('be.disabled'); - ClusterConfigurationSteps.typeRpcAddress(rpcAddress); - ClusterConfigurationSteps.getEnableButton().should('be.disabled'); - ClusterConfigurationSteps.typePrimaryTag(tag); - ClusterConfigurationSteps.getEnableButton().should('not.be.disabled'); - ClusterConfigurationSteps.clickEnableButton(); - cy.wait('@enable-secondary-mode').then((interception) => { - expect(interception.request.body).to.deep.equal({primaryNode: rpcAddress, tag}); - }); - // And expect success message to be displayed. - ApplicationSteps.getSuccessNotifications().contains(`Successfully enabled secondary mode`); - }); - }); - }); -}); diff --git a/test-cypress/integration/cluster/cluster-configuration/cluster-configuration-multi-region.spec.js b/test-cypress/integration/cluster/cluster-configuration/cluster-configuration-multi-region.spec.js new file mode 100644 index 000000000..7186fcbd5 --- /dev/null +++ b/test-cypress/integration/cluster/cluster-configuration/cluster-configuration-multi-region.spec.js @@ -0,0 +1,97 @@ +import {ClusterPageSteps} from "../../../steps/cluster/cluster-page-steps"; +import {GlobalOperationsStatusesStub} from "../../../stubs/global-operations-statuses-stub"; +import {ClusterStubs} from "../../../stubs/cluster/cluster-stubs"; +import {RemoteLocationStubs} from "../../../stubs/cluster/remote-location-stubs"; +import {ClusterConfigurationSteps} from "../../../steps/cluster/cluster-configuration-steps"; +import {ModalDialogSteps} from "../../../steps/modal-dialog-steps"; +import {ApplicationSteps} from "../../../steps/application-steps"; + +describe('Cluster configuration', () => { + let repositoryId; + + beforeEach(() => { + repositoryId = 'cluster-repo' + Date.now(); + GlobalOperationsStatusesStub.stubNoOperationsResponse(repositoryId); + // Given there is an existing cluster created + ClusterStubs.stubClusterConfig(); + ClusterStubs.stubClusterGroupStatus(); + ClusterStubs.stubClusterNodeStatus(); + RemoteLocationStubs.stubRemoteLocationFilter(); + RemoteLocationStubs.stubRemoteLocationStatusInCluster(); + }); + + it('should be able to add and delete tags', () => { + const tagName = 'test'; + // Given I have opened the cluster management page + ClusterPageSteps.visit(); + // When I click on edit properties and open Multi-region tab + ClusterPageSteps.previewClusterConfig(); + ClusterConfigurationSteps.selectMultiRegionConfigTab(); + // I expect to see + ClusterConfigurationSteps.getMultiRegionHeader().should('contain.text', 'Primary cluster'); + ClusterConfigurationSteps.getAddTagButton().should('be.visible').and('not.be.disabled'); + ClusterConfigurationSteps.getEnableSecondaryModeButton().should('be.visible').and('be.enabled'); + ClusterConfigurationSteps.getTagsTable().should('not.exist'); + + ClusterStubs.stubAddTag(tagName); + ClusterConfigurationSteps.clickAddTagButton(); + ClusterConfigurationSteps.typeTag(tagName); + ClusterConfigurationSteps.clickSubmitTagButton(); + cy.wait('@add-tag').then((interception) => { + expect(interception.request.body).to.deep.equal({tag: tagName}); + }); + + ClusterStubs.stubClusterGroupStatusWithTag(); + cy.wait('@3-nodes-cluster-group-status-tag'); + // Assert the tags table contains the expected tag + ClusterConfigurationSteps.getTagsTable().should('be.visible'); + ClusterConfigurationSteps.getTagsTableRows().should('contain.text', tagName); + + // And expect success message to be displayed. + ApplicationSteps.getSuccessNotifications().contains(`Successfully added to cluster primary identifier tag: ${tagName}`); + + //When I delete the tag + ClusterConfigurationSteps.clickDeleteTagButton(); + // I expect to see deleting confirmation dialog. + ModalDialogSteps.getDialogHeader().should('contain', `Delete identifier tag ${tagName}`); + ModalDialogSteps.getDialogBody().should('contain', 'Deleting identifier tag would stop any secondary cluster identified with it from pulling updates.'); + + // When I confirm + ClusterStubs.stubDeleteTag(tagName); + ModalDialogSteps.clickOnConfirmButton(); + cy.wait('@delete-tag').then((interception) => { + expect(interception.request.body).to.deep.equal({tag: tagName}); + }); + }); + + it('should be able to switch modes', () => { + ClusterStubs.stubEnableSecondaryMode(); + const rpcAddress = 'node-name:7300'; + const tag = 'us-central'; + + // Given I have opened the cluster management page + ClusterPageSteps.visit(); + // When I click on edit properties and open Nodes tab + ClusterPageSteps.previewClusterConfig(); + ClusterConfigurationSteps.selectMultiRegionConfigTab(); + // I click enable secondary mode btn + ClusterConfigurationSteps.clickEnableSecondaryModeButton(); + // I expect to see enable secondary mode confirmation dialog. + ModalDialogSteps.getDialogHeader().should('contain', `Enable secondary mode`); + ModalDialogSteps.getDialogBody().should('contain', 'By enabling secondary mode this cluster would become a read-only replica of the specified primary cluster.'); + // When I confirm I expect to see configuration modal + ModalDialogSteps.getConfirmButton().click(); + ModalDialogSteps.getDialogHeader().should('contain', `Secondary cluster settings`); + ClusterConfigurationSteps.getEnableButton().should('be.disabled'); + ClusterConfigurationSteps.typeRpcAddress(rpcAddress); + ClusterConfigurationSteps.getEnableButton().should('be.disabled'); + ClusterConfigurationSteps.typePrimaryTag(tag); + ClusterConfigurationSteps.getEnableButton().should('not.be.disabled'); + ClusterConfigurationSteps.clickEnableButton(); + cy.wait('@enable-secondary-mode').then((interception) => { + expect(interception.request.body).to.deep.equal({primaryNode: rpcAddress, tag}); + }); + // And expect success message to be displayed. + ApplicationSteps.getSuccessNotifications().contains(`Successfully enabled secondary mode`); + }); +}); diff --git a/test-cypress/integration/cluster/cluster-configuration/cluster-configuration-nodes.spec.js b/test-cypress/integration/cluster/cluster-configuration/cluster-configuration-nodes.spec.js new file mode 100644 index 000000000..d79ec6123 --- /dev/null +++ b/test-cypress/integration/cluster/cluster-configuration/cluster-configuration-nodes.spec.js @@ -0,0 +1,70 @@ +import {ClusterPageSteps} from "../../../steps/cluster/cluster-page-steps"; +import {GlobalOperationsStatusesStub} from "../../../stubs/global-operations-statuses-stub"; +import {ClusterStubs} from "../../../stubs/cluster/cluster-stubs"; +import {RemoteLocationStubs} from "../../../stubs/cluster/remote-location-stubs"; +import {ClusterConfigurationSteps} from "../../../steps/cluster/cluster-configuration-steps"; + +describe('Cluster configuration', () => { + let repositoryId; + + beforeEach(() => { + repositoryId = 'cluster-repo' + Date.now(); + GlobalOperationsStatusesStub.stubNoOperationsResponse(repositoryId); + // Given there is an existing cluster created + ClusterStubs.stubClusterConfig(); + ClusterStubs.stubClusterGroupStatus(); + ClusterStubs.stubClusterNodeStatus(); + RemoteLocationStubs.stubRemoteLocationFilter(); + RemoteLocationStubs.stubRemoteLocationStatusInCluster(); + }); + + it('should display the nodes list with correct node information in the modal', () => { + // Given I have opened the cluster management page + ClusterPageSteps.visit(); + // When I click on edit properties and open Nodes tab + ClusterPageSteps.previewClusterConfig(); + ClusterConfigurationSteps.selectNodesTab(); + // I expect to see + ClusterConfigurationSteps.getNodesListHeader().should('contain.text', 'Nodes list'); + ClusterConfigurationSteps.assertNodesCount(3); + + const nodeData = [ + { + url: 'http://pc-desktop:7200', + rpcAddress: 'pc-desktop:7300', + state: 'FOLLOWER', + local: true + }, + { + url: 'http://pc-desktop:7201', + rpcAddress: 'pc-desktop:7301', + state: 'LEADER', + local: false + }, + { + url: 'http://pc-desktop:7202', + rpcAddress: 'pc-desktop:7302', + state: 'FOLLOWER', + local: false + } + ]; + + nodeData.forEach((data, index) => { + ClusterConfigurationSteps.getNodeLink(index) + .should('have.attr', 'href', data.url) + .and('contain.text', data.url); + + ClusterConfigurationSteps.getNodeRPCAddress(index) + .should('contain.text', data.rpcAddress); + + ClusterConfigurationSteps.getNodeState(index) + .should('contain.text', data.state); + + if (data.local) { + ClusterConfigurationSteps.isNodeLocal(index).should('exist'); + } else { + ClusterConfigurationSteps.isNodeLocal(index).should('not.exist'); + } + }); + }); +}); diff --git a/test-cypress/integration/cluster/cluster-configuration/cluster-configuration-properties.spec.js b/test-cypress/integration/cluster/cluster-configuration/cluster-configuration-properties.spec.js new file mode 100644 index 000000000..081aa89b8 --- /dev/null +++ b/test-cypress/integration/cluster/cluster-configuration/cluster-configuration-properties.spec.js @@ -0,0 +1,95 @@ +import {ClusterPageSteps} from "../../../steps/cluster/cluster-page-steps"; +import {GlobalOperationsStatusesStub} from "../../../stubs/global-operations-statuses-stub"; +import {ClusterStubs} from "../../../stubs/cluster/cluster-stubs"; +import {RemoteLocationStubs} from "../../../stubs/cluster/remote-location-stubs"; +import {DeleteClusterDialogSteps} from "../../../steps/cluster/delete-cluster-dialog-steps"; +import {ClusterConfigurationSteps} from "../../../steps/cluster/cluster-configuration-steps"; + +describe('Cluster configuration', () => { + let repositoryId; + + beforeEach(() => { + repositoryId = 'cluster-repo' + Date.now(); + GlobalOperationsStatusesStub.stubNoOperationsResponse(repositoryId); + // Given there is an existing cluster created + ClusterStubs.stubClusterConfig(); + ClusterStubs.stubClusterGroupStatus(); + ClusterStubs.stubClusterNodeStatus(); + RemoteLocationStubs.stubRemoteLocationFilter(); + RemoteLocationStubs.stubRemoteLocationStatusInCluster(); + }); + + it('Should be able to delete cluster', () => { + // Given I have opened the cluster management page + ClusterPageSteps.visit(); + + ClusterPageSteps.getClusterPage().should('be.visible'); + ClusterPageSteps.getCreateClusterButton().should('not.have.class', 'no-cluster'); + // When I click on delete cluster + ClusterPageSteps.previewClusterConfig(); + ClusterConfigurationSteps.getClusterConfig().should('be.visible'); + ClusterConfigurationSteps.deleteCluster(); + // Then I expect a confirmation dialog to appear + DeleteClusterDialogSteps.getDialog().should('be.visible'); + // When I confirm + ClusterStubs.stubDeleteCluster(); + ClusterStubs.stubNoClusterGroupStatus(); + ClusterStubs.stubNoClusterNodeStatus(); + DeleteClusterDialogSteps.confirmDeleteCluster(); + // Then Cluster should be deleted + ClusterStubs.stubNoClusterConfig(); + RemoteLocationStubs.stubRemoteLocationStatusNotCluster(); + DeleteClusterDialogSteps.getDialog().should('not.exist'); + ClusterPageSteps.getRemoveNodesButton().should('not.exist'); + ClusterPageSteps.getAddNodesButton().should('not.exist'); + ClusterPageSteps.getReplaceNodesButton().should('not.exist'); + ClusterPageSteps.getPreviewClusterConfigButton().should('not.exist'); + ClusterPageSteps.getCreateClusterButton().should('have.class', 'no-cluster'); + }); + + it('Should be able to edit cluster properties', () => { + // Given I have opened the cluster management page + ClusterPageSteps.visit(); + // When I click on edit properties + ClusterPageSteps.previewClusterConfig(); + ClusterConfigurationSteps.getClusterConfig().should('be.visible'); + // When I press edit properties + ClusterConfigurationSteps.editProperties(); + // Then I expect a modal to be shown + ClusterConfigurationSteps.getModal().should('be.visible'); + // I can set values in form fields + ClusterConfigurationSteps.setFieldValue('electionMinTimeout', '5000'); + ClusterConfigurationSteps.setFieldValue('electionRangeTimeout', '3000'); + // Verify a field validation error appears if left empty + ClusterConfigurationSteps.getFieldByName('heartbeatInterval').clear(); + ClusterConfigurationSteps.verifyFieldError('heartbeatInterval', 'This field is required'); + // And Save button is disabled + ClusterConfigurationSteps.getSaveButton().should('be.disabled'); + // Set value for required field to enable Save button + ClusterConfigurationSteps.setFieldValue('heartbeatInterval', '1500'); + // And Save button is disabled + ClusterConfigurationSteps.getSaveButton().should('be.enabled'); + ClusterConfigurationSteps.setFieldValue('messageSizeKB', '64'); + ClusterConfigurationSteps.setFieldValue('verificationTimeout', '1200'); + ClusterConfigurationSteps.setFieldValue('transactionLogMaximumSizeGB', '50'); + ClusterConfigurationSteps.setFieldValue('batchUpdateInterval', '2000'); + + // Click Save button to submit + ClusterStubs.stubSaveClusterConfiguration(); + ClusterConfigurationSteps.save(); + const expectedRequestBody = { + electionMinTimeout: 5000, + electionRangeTimeout: 3000, + heartbeatInterval: 1500, + messageSizeKB: 64, + verificationTimeout: 1200, + transactionLogMaximumSizeGB: 50, + batchUpdateInterval: 2000 + }; + cy.wait('@save-cluster-properties').then((interception) => { + expect(interception.request.body).to.deep.equal(expectedRequestBody); + }); + // And the modal is closed + ClusterConfigurationSteps.getModal().should('not.exist'); + }); +}); diff --git a/test-cypress/integration/cluster/cluster-configuration/cluster-configuration.spec.js b/test-cypress/integration/cluster/cluster-configuration/cluster-configuration.spec.js new file mode 100644 index 000000000..45eaa8ac1 --- /dev/null +++ b/test-cypress/integration/cluster/cluster-configuration/cluster-configuration.spec.js @@ -0,0 +1,38 @@ +import {ClusterPageSteps} from "../../../steps/cluster/cluster-page-steps"; +import {GlobalOperationsStatusesStub} from "../../../stubs/global-operations-statuses-stub"; +import {ClusterStubs} from "../../../stubs/cluster/cluster-stubs"; +import {RemoteLocationStubs} from "../../../stubs/cluster/remote-location-stubs"; +import {ClusterConfigurationSteps} from "../../../steps/cluster/cluster-configuration-steps"; + +describe('Cluster configuration', () => { + + let repositoryId; + beforeEach(() => { + repositoryId = 'cluster-repo' + Date.now(); + GlobalOperationsStatusesStub.stubNoOperationsResponse(repositoryId); + }); + + it('Should display cluster configuration', () => { + // Given there is an existing cluster created + ClusterStubs.stubClusterConfig(); + ClusterStubs.stubClusterGroupStatus(); + ClusterStubs.stubClusterNodeStatus(); + RemoteLocationStubs.stubRemoteLocationFilter(); + RemoteLocationStubs.stubRemoteLocationStatusInCluster(); + // Given I have opened the cluster management page + ClusterPageSteps.visit(); + // When I click on edit properties + ClusterPageSteps.previewClusterConfig(); + // Then I should see cluster configuration with 3 tabs + ClusterConfigurationSteps.getClusterConfig().should('be.visible'); + ClusterConfigurationSteps.getTabs().should('have.length', 3); + ClusterConfigurationSteps.getActiveTab().should('have.text', 'Properties'); + ClusterConfigurationSteps.getClusterPropertiesTabContent().should('be.visible'); + ClusterConfigurationSteps.selectTab(1); + ClusterConfigurationSteps.getActiveTab().should('have.text', 'Nodes'); + ClusterConfigurationSteps.getClusterNodesTabContent().should('be.visible'); + ClusterConfigurationSteps.selectTab(2); + ClusterConfigurationSteps.getActiveTab().should('have.text', 'Multi-region'); + ClusterConfigurationSteps.getMultiRegionTabContent().should('be.visible'); + }); +}); diff --git a/test-cypress/steps/cluster/cluster-configuration-steps.js b/test-cypress/steps/cluster/cluster-configuration-steps.js index f806eedf6..c7ecc16aa 100644 --- a/test-cypress/steps/cluster/cluster-configuration-steps.js +++ b/test-cypress/steps/cluster/cluster-configuration-steps.js @@ -23,6 +23,14 @@ export class ClusterConfigurationSteps { return this.getTabs().eq(index).click(); } + static selectNodesTab() { + return this.selectTab(1); + } + + static selectMultiRegionConfigTab() { + return this.selectTab(2); + } + static getClusterPropertiesTabContent() { return cy.get('cluster-properties'); } diff --git a/test-cypress/stubs/cluster/cluster-stubs.js b/test-cypress/stubs/cluster/cluster-stubs.js index 2bc6a85aa..dba42b40c 100644 --- a/test-cypress/stubs/cluster/cluster-stubs.js +++ b/test-cypress/stubs/cluster/cluster-stubs.js @@ -183,24 +183,11 @@ export class ClusterStubs extends Stubs { }).as('2-nodes-cluster-created'); } - static stubSaveClusterConfiguration(expectedRequestBody) { - cy.intercept({ - method: 'PATCH', - url: '/rest/cluster/config' - }, (req) => { - req.reply({ - statusCode: 200, - body: { - electionMinTimeout: 5000, - electionRangeTimeout: 3000, - heartbeatInterval: 1500, - messageSizeKB: 64, - verificationTimeout: 1200, - transactionLogMaximumSizeGB: 50, - batchUpdateInterval: 2000, - nodes: ["pc-desktop:7300", "pc-desktop:7301", "pc-desktop:7302"] - } - }); + static stubSaveClusterConfiguration() { + cy.intercept('/rest/cluster/config', { + fixture: '/cluster/save-cluster-configuration-response.json', + statusCode: 200, + method: 'PATCH' }).as('save-cluster-properties'); }