diff --git a/cypress/e2e/po/components/create-edit-view.po.ts b/cypress/e2e/po/components/create-edit-view.po.ts index 899e4f2fd2..93937b0d7c 100644 --- a/cypress/e2e/po/components/create-edit-view.po.ts +++ b/cypress/e2e/po/components/create-edit-view.po.ts @@ -19,6 +19,10 @@ export default class CreateEditViewPo extends ComponentPo { return new AsyncButtonPo(this.self().find('.cru-resource-footer .role-primary')).click(); } + cancel() { + return new AsyncButtonPo(this.self().find('.cru-resource-footer .role-secondary')).click(); + } + saveAndWait() { return new AsyncButtonPo(this.self().find('.cru-resource-footer .role-primary')).action('Save', 'Saved'); } diff --git a/cypress/e2e/po/extensions/imported/cluster-edit.po.ts b/cypress/e2e/po/extensions/imported/cluster-edit.po.ts index 896f36912f..67ebe77f6a 100644 --- a/cypress/e2e/po/extensions/imported/cluster-edit.po.ts +++ b/cypress/e2e/po/extensions/imported/cluster-edit.po.ts @@ -4,21 +4,22 @@ import ResourceDetailPo from '@/cypress/e2e/po/edit/resource-detail.po'; import NameNsDescription from '@/cypress/e2e/po/components/name-ns-description.po'; import LabeledInputPo from '@/cypress/e2e/po/components/labeled-input.po'; import CheckboxInputPo from '@/cypress/e2e/po/components/checkbox-input.po'; +import RadioGroupInputPo from '@/cypress/e2e/po/components/radio-group-input.po'; /** * Edit page for imported cluster */ export default class ClusterManagerEditImportedPagePo extends PagePo { - private static createPath(clusterId: string, clusterName: string) { - return `/c/${ clusterId }/manager/provisioning.cattle.io.cluster/fleet-default/${ clusterName }`; + private static createPath(clusterId: string, ns: string, clusterName: string) { + return `/c/${ clusterId }/manager/provisioning.cattle.io.cluster/${ ns }/${ clusterName }`; } - static goTo(clusterId: string, clusterName: string ): Cypress.Chainable { - return super.goTo(ClusterManagerEditImportedPagePo.createPath(clusterId, clusterName)); + static goTo(clusterId: string, ns: string, clusterName: string ): Cypress.Chainable { + return super.goTo(ClusterManagerEditImportedPagePo.createPath(clusterId, ns, clusterName)); } - constructor(clusterId = '_', clusterName: string) { - super(ClusterManagerEditImportedPagePo.createPath(clusterId, clusterName)); + constructor(clusterId = '_', ns = 'fleet-default', clusterName: string) { + super(ClusterManagerEditImportedPagePo.createPath(clusterId, ns, clusterName)); } nameNsDescription() { @@ -37,6 +38,26 @@ export default class ClusterManagerEditImportedPagePo extends PagePo { return this.accordion(index, label).click(); } + versionManagementBanner() { + return this.self().find('[data-testid="version-management-banner"]'); + } + + versionManagementRadioButton(): RadioGroupInputPo { + return new RadioGroupInputPo('[data-testid="imported-version-management-radio"]'); + } + + enableVersionManagement() { + return this.versionManagementRadioButton().set(1); + } + + disableVersionManagement() { + return this.versionManagementRadioButton().set(2); + } + + defaultVersionManagement() { + return this.versionManagementRadioButton().set(0); + } + privateRegistryCheckbox() { return new CheckboxInputPo('[data-testid="private-registry-enable-checkbox"]'); } @@ -56,4 +77,8 @@ export default class ClusterManagerEditImportedPagePo extends PagePo { save() { return this.resourceDetail().createEditView().save(); } + + cancel() { + return this.resourceDetail().createEditView().cancel(); + } } diff --git a/cypress/e2e/po/extensions/imported/cluster-import-generic.po.ts b/cypress/e2e/po/extensions/imported/cluster-import-generic.po.ts index 475a91fcf1..8af76e5f71 100644 --- a/cypress/e2e/po/extensions/imported/cluster-import-generic.po.ts +++ b/cypress/e2e/po/extensions/imported/cluster-import-generic.po.ts @@ -11,4 +11,8 @@ export default class ClusterManagerImportGenericPagePo extends ClusterManagerImp networkingAccordion() { return this.self().find('[data-testid="networking-accordion"]'); } + + versionManagementBanner() { + return this.self().find('[data-testid="version-management-banner"]'); + } } diff --git a/cypress/e2e/tests/pages/manager/cluster-manager.spec.ts b/cypress/e2e/tests/pages/manager/cluster-manager.spec.ts index 1dc0233390..7bf03c366a 100644 --- a/cypress/e2e/tests/pages/manager/cluster-manager.spec.ts +++ b/cypress/e2e/tests/pages/manager/cluster-manager.spec.ts @@ -620,6 +620,9 @@ describe('Cluster Manager', { testIsolation: 'off', tags: ['@manager', '@adminUs importClusterPage.nameNsDescription().name().checkVisible(); importClusterPage.nameNsDescription().name().set(importGenericName); + // Issue #13614: Imported Cluster Version Mgmt: Conditionally show warning message + importClusterPage.versionManagementBanner().should('exist').and('be.visible'); + importClusterPage.create(); cy.wait('@importRequest').then((intercept) => { @@ -664,7 +667,7 @@ describe('Cluster Manager', { testIsolation: 'off', tags: ['@manager', '@adminUs }); it('can edit imported cluster and see changes afterwards', () => { - const editImportedClusterPage = new ClusterManagerEditImportedPagePo(undefined, importedClusterName); + const editImportedClusterPage = new ClusterManagerEditImportedPagePo(undefined, 'fleet-default', importedClusterName); cy.intercept('GET', '/v1-rke2-release/releases').as('getRke2Releases'); clusterList.goTo(); @@ -684,6 +687,13 @@ describe('Cluster Manager', { testIsolation: 'off', tags: ['@manager', '@adminUs // Issue #10432: Edit Cluster screen falsely gives impression imported cluster's name and description can be edited editImportedClusterPage.nameNsDescription().name().expectToBeDisabled(); + // Issue #13614: Imported Cluster Version Mgmt: Conditionally show warning message + editImportedClusterPage.versionManagementBanner().should('not.exist'); + + editImportedClusterPage.enableVersionManagement(); + editImportedClusterPage.versionManagementBanner().should('exist').and('be.visible'); + editImportedClusterPage.defaultVersionManagement(); + editImportedClusterPage.toggleAccordion(5, 'Networking'); editImportedClusterPage.ace().enable(); editImportedClusterPage.ace().enterFdqn(fqdn); @@ -799,14 +809,48 @@ describe('Cluster Manager', { testIsolation: 'off', tags: ['@manager', '@adminUs }); }); - it(`can navigate to local cluster's explore product`, () => { - const clusterName = 'local'; - const clusterDashboard = new ClusterDashboardPagePo(clusterName); + describe('Local', { tags: ['@jenkins', '@localCluster'] }, () => { + it(`can open edit for local cluster`, () => { + const editLocalClusterPage = new ClusterManagerEditImportedPagePo(undefined, 'fleet-local', 'local'); - clusterList.goTo(); - clusterList.list().explore(clusterName).click(); + cy.intercept('GET', '/v1-rke2-release/releases').as('getRke2Releases'); + clusterList.goTo(); + clusterList.list().actionMenu('local').getMenuItem('Edit Config').click(); + editLocalClusterPage.waitForPage('mode=edit'); - clusterDashboard.waitForPage(undefined, 'cluster-events'); + editLocalClusterPage.nameNsDescription().name().value().should('eq', 'local' ); + + // check accordions are properly displayed + editLocalClusterPage.accordion(2, 'Basics').should('be.visible'); + editLocalClusterPage.accordion(3, 'Member Roles').scrollIntoView().should('be.visible'); + editLocalClusterPage.accordion(4, 'Labels and Annotations').scrollIntoView().should('be.visible'); + editLocalClusterPage.accordion(5, 'Networking').scrollIntoView().should('be.visible'); + editLocalClusterPage.accordion(6, 'Registries').scrollIntoView().should('be.visible'); + editLocalClusterPage.accordion(7, 'Advanced').scrollIntoView().should('be.visible'); + + // Issue #13614: Imported Cluster Version Mgmt: Conditionally show warning message + editLocalClusterPage.versionManagementBanner().should('not.exist'); + + editLocalClusterPage.enableVersionManagement(); + editLocalClusterPage.versionManagementBanner().should('exist').and('be.visible'); + editLocalClusterPage.versionManagementBanner().should('not.contain.text', 'This change will trigger cluster agent redeployment.'); + editLocalClusterPage.disableVersionManagement(); + editLocalClusterPage.versionManagementBanner().should('exist').and('be.visible'); + editLocalClusterPage.versionManagementBanner().should('not.contain.text', 'This change will trigger cluster agent redeployment.'); + editLocalClusterPage.cancel(); + + // We should be taken back to the list page if the save was successful + clusterList.waitForPage(); + }); + it(`can navigate to local cluster's explore product`, () => { + const clusterName = 'local'; + const clusterDashboard = new ClusterDashboardPagePo(clusterName); + + clusterList.goTo(); + clusterList.list().explore(clusterName).click(); + + clusterDashboard.waitForPage(undefined, 'cluster-events'); + }); }); it('can download YAML via bulk actions', () => { diff --git a/pkg/imported/components/Basics.vue b/pkg/imported/components/Basics.vue index 7d57d146ad..da45582206 100644 --- a/pkg/imported/components/Basics.vue +++ b/pkg/imported/components/Basics.vue @@ -78,6 +78,10 @@ export default defineComponent({ type: String, required: true }, + isLocal: { + type: Boolean, + default: false + }, rules: { default: () => ({ workerConcurrency: [], @@ -172,6 +176,7 @@ export default defineComponent({ :global-setting="versionManagementGlobalSetting" :mode="mode" :old-value="versionManagementOld" + :is-local="isLocal" @version-management-changed="$emit('version-management-changed', $event)" />
{{ versionManagementInfo }} diff --git a/pkg/imported/components/__tests__/versionManagement.test.ts b/pkg/imported/components/__tests__/versionManagement.test.ts new file mode 100644 index 0000000000..690e051855 --- /dev/null +++ b/pkg/imported/components/__tests__/versionManagement.test.ts @@ -0,0 +1,203 @@ +import { shallowMount } from '@vue/test-utils'; +import VersionManagement from '@pkg/imported/components/VersionManagement.vue'; +import { _EDIT, _CREATE } from '@shell/config/query-params'; + +const mockedStore = () => { + return { + getters: { + 'i18n/t': (text: string) => { + return `${ text }`; + }, + }, + }; +}; + +const mockedRoute = { query: {} }; + +const requiredSetup = () => { + return { + global: { + mocks: { + $store: mockedStore(), + $route: mockedRoute, + $fetchState: {}, + } + } + }; +}; + +describe('version management component', () => { + it.each([ + [{ + oldValue: 'system-default', globalSetting: true, value: 'system-default' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.create.default' }], + [{ + oldValue: 'system-default', globalSetting: true, value: 'true' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.create.nonDefault' }], + [{ + oldValue: 'system-default', globalSetting: true, value: 'false' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.create.nonDefault' }], + [{ + oldValue: 'system-default', globalSetting: false, value: 'system-default' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.create.default' }], + [{ + oldValue: 'system-default', globalSetting: false, value: 'true' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.create.nonDefault' }], + [{ + oldValue: 'system-default', globalSetting: false, value: 'false' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.create.nonDefault' }] + ])('on import of a new cluster, should display correct warning depending on the selection', (config, expected) => { + const wrapper = shallowMount(VersionManagement, { + ...requiredSetup(), + propsData: { + ...config, isLocal: true, mode: _CREATE + } + }); + + const banner = wrapper.find('[data-testid="version-management-banner"]'); + + expect(banner.exists()).toBe(expected.shouldExist); + + expect(wrapper.vm.versionManagementInfo).toBe(expected.value); + }); + + it.each([ + [{ + oldValue: 'system-default', globalSetting: true, value: 'system-default' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'system-default', globalSetting: true, value: 'true' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.defaultToNonDefault' }], + [{ + oldValue: 'system-default', globalSetting: true, value: 'false' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.different imported.basics.versionManagement.banner.edit.defaultToNonDefault' }], + [{ + oldValue: 'system-default', globalSetting: false, value: 'system-default' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'system-default', globalSetting: false, value: 'true' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.different imported.basics.versionManagement.banner.edit.defaultToNonDefault' }], + [{ + oldValue: 'system-default', globalSetting: false, value: 'false' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.defaultToNonDefault' }], + [{ + oldValue: 'true', globalSetting: true, value: 'system-default' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.nonDefaultToDefault' }], + [{ + oldValue: 'true', globalSetting: true, value: 'true' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'true', globalSetting: true, value: 'false' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.different' }], + [{ + oldValue: 'true', globalSetting: false, value: 'system-default' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.different imported.basics.versionManagement.banner.edit.nonDefaultToDefault' }], + [{ + oldValue: 'true', globalSetting: false, value: 'true' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'true', globalSetting: false, value: 'false' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.different' }], + [{ + oldValue: 'false', globalSetting: true, value: 'system-default' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.different imported.basics.versionManagement.banner.edit.nonDefaultToDefault' }], + [{ + oldValue: 'false', globalSetting: true, value: 'true' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.different' }], + [{ + oldValue: 'false', globalSetting: true, value: 'false' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'false', globalSetting: false, value: 'system-default' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.nonDefaultToDefault' }], + [{ + oldValue: 'false', globalSetting: false, value: 'true' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.different' }], + [{ + oldValue: 'false', globalSetting: false, value: 'false' + }, { shouldExist: false, value: '' }], + ])('on edit of imported, should display correct warning depending on the selection', (config, expected) => { + const wrapper = shallowMount(VersionManagement, { + ...requiredSetup(), + propsData: { + ...config, isLocal: false, mode: _EDIT + } + }); + + const banner = wrapper.find('[data-testid="version-management-banner"]'); + + expect(banner.exists()).toBe(expected.shouldExist); + + expect(wrapper.vm.versionManagementInfo).toBe(expected.value); + }); + + it.each([ + [{ + oldValue: 'system-default', globalSetting: true, value: 'system-default' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'system-default', globalSetting: true, value: 'true' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.defaultToNonDefault' }], + [{ + oldValue: 'system-default', globalSetting: true, value: 'false' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.defaultToNonDefault' }], + [{ + oldValue: 'system-default', globalSetting: false, value: 'system-default' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'system-default', globalSetting: false, value: 'true' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.defaultToNonDefault' }], + [{ + oldValue: 'system-default', globalSetting: false, value: 'false' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.defaultToNonDefault' }], + [{ + oldValue: 'true', globalSetting: true, value: 'system-default' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.nonDefaultToDefault' }], + [{ + oldValue: 'true', globalSetting: true, value: 'true' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'true', globalSetting: true, value: 'false' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'true', globalSetting: false, value: 'system-default' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.nonDefaultToDefault' }], + [{ + oldValue: 'true', globalSetting: false, value: 'true' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'true', globalSetting: false, value: 'false' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'false', globalSetting: true, value: 'system-default' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.nonDefaultToDefault' }], + [{ + oldValue: 'false', globalSetting: true, value: 'true' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'false', globalSetting: true, value: 'false' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'false', globalSetting: false, value: 'system-default' + }, { shouldExist: true, value: 'imported.basics.versionManagement.banner.edit.nonDefaultToDefault' }], + [{ + oldValue: 'false', globalSetting: false, value: 'true' + }, { shouldExist: false, value: '' }], + [{ + oldValue: 'false', globalSetting: false, value: 'false' + }, { shouldExist: false, value: '' }], + ])('on edit of local, should display correct warning depending on the selection', (config, expected) => { + const wrapper = shallowMount(VersionManagement, { + ...requiredSetup(), + propsData: { + ...config, isLocal: true, mode: _EDIT + } + }); + + const banner = wrapper.find('[data-testid="version-management-banner"]'); + + expect(banner.exists()).toBe(expected.shouldExist); + + expect(wrapper.vm.versionManagementInfo).toBe(expected.value); + }); +}); diff --git a/shell/edit/provisioning.cattle.io.cluster/index.vue b/shell/edit/provisioning.cattle.io.cluster/index.vue index 1a61e14922..7d20548743 100644 --- a/shell/edit/provisioning.cattle.io.cluster/index.vue +++ b/shell/edit/provisioning.cattle.io.cluster/index.vue @@ -689,7 +689,7 @@ export default {