From ba01b9d9e74de3cb4eaa2857d13e80aed6a6f167 Mon Sep 17 00:00:00 2001 From: momesgin Date: Tue, 12 Mar 2024 15:03:41 -0700 Subject: [PATCH] Error handling for contentLibrary, tag and network fields (#10599) * error handling for contentLibrary, tag and network fields * fix typo Co-authored-by: Phillip Rak --------- Co-authored-by: Mo Mesgin Co-authored-by: Phillip Rak --- .../__tests__/vmwarevsphere.test.ts | 36 ++++++++++++------- shell/machine-config/vmwarevsphere.vue | 10 ++++-- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/shell/machine-config/__tests__/vmwarevsphere.test.ts b/shell/machine-config/__tests__/vmwarevsphere.test.ts index 3c2dfca2ba8..1aeb3361903 100644 --- a/shell/machine-config/__tests__/vmwarevsphere.test.ts +++ b/shell/machine-config/__tests__/vmwarevsphere.test.ts @@ -183,16 +183,20 @@ describe('component: vmwarevsphere', () => { describe('resetValueIfNecessary', () => { const hostsystemOptions = ['', '/Datacenter/host/Cluster/111.11.11.1']; const folderOptions = ['', '/Datacenter/vm', '/Datacenter/vm/sub-folder']; + const contentLibraryOptions = ['', 'some-content-library']; + const networkOptions = ['', 'some-network']; + const tagOptions = ['', 'some-tag']; - it('should add errors to validationError collection when values are no in the options', () => { + it('should add errors to validationError collection when values are NOT in the options', () => { const setup = { ...defaultEditSetup, propsData: { ...defaultEditSetup.propsData, value: { ...defaultEditSetup.propsData.value, - hostsystem: 'something that is not included in the options', - folder: 'again, something that is not included in the options' + hostsystem: 'something that is not included in the options', + folder: 'same as above', + constentLibrary: 'same as above' } } }; @@ -200,18 +204,19 @@ describe('component: vmwarevsphere', () => { const wrapper = mount(vmwarevsphere, setup); const hostsystemContent = wrapper.vm.mapHostOptionsToContent(hostsystemOptions); - - wrapper.vm.resetValueIfNecessary('hostsystem', hostsystemContent, hostsystemOptions); - const folderContent = wrapper.vm.mapHostOptionsToContent(folderOptions); + const contentLibraryContent = wrapper.vm.mapPathOptionsToContent(contentLibraryOptions); + wrapper.vm.resetValueIfNecessary('hostsystem', hostsystemContent, hostsystemOptions); wrapper.vm.resetValueIfNecessary('folder', folderContent, folderOptions); + wrapper.vm.resetValueIfNecessary('contentLibrary', contentLibraryContent, contentLibraryOptions); expect(wrapper.vm.$data.validationErrors[poolId]).toContain('hostsystem'); expect(wrapper.vm.$data.validationErrors[poolId]).toContain('folder'); + expect(wrapper.vm.$data.validationErrors[poolId]).toContain('contentLibrary'); }); - describe('hostsystem and folder', () => { + describe('hostsystem, folder, contentLibrary, network and tag', () => { const testCases = [null, '']; it.each(testCases)('should NOT be added to validationError collection if they are null or ""', (data) => { @@ -221,8 +226,11 @@ describe('component: vmwarevsphere', () => { ...defaultEditSetup.propsData, value: { ...defaultEditSetup.propsData.value, - hostsystem: data, - folder: data + hostsystem: data, + folder: data, + contentLibrary: data, + network: [data], + tag: [data] } } }; @@ -230,12 +238,16 @@ describe('component: vmwarevsphere', () => { const wrapper = mount(vmwarevsphere, setup); const hostsystemContent = wrapper.vm.mapHostOptionsToContent(hostsystemOptions); - - wrapper.vm.resetValueIfNecessary('hostsystem', hostsystemContent, hostsystemOptions); - const folderContent = wrapper.vm.mapHostOptionsToContent(folderOptions); + const contentLibraryContent = wrapper.vm.mapPathOptionsToContent(contentLibraryOptions); + const networkContent = wrapper.vm.mapPathOptionsToContent(networkOptions); + const tagContent = wrapper.vm.mapPathOptionsToContent(tagOptions); + wrapper.vm.resetValueIfNecessary('hostsystem', hostsystemContent, hostsystemOptions); wrapper.vm.resetValueIfNecessary('folder', folderContent, folderOptions); + wrapper.vm.resetValueIfNecessary('contentLibrary', contentLibraryContent, contentLibraryOptions); + wrapper.vm.resetValueIfNecessary('network', networkContent, networkOptions, true); + wrapper.vm.resetValueIfNecessary('tag', tagContent, tagOptions, true); expect(wrapper.vm.$data.validationErrors[poolId]).toBeUndefined(); }); diff --git a/shell/machine-config/vmwarevsphere.vue b/shell/machine-config/vmwarevsphere.vue index ca19f1474eb..e6a76d0eecb 100644 --- a/shell/machine-config/vmwarevsphere.vue +++ b/shell/machine-config/vmwarevsphere.vue @@ -16,6 +16,7 @@ import { integerString, keyValueStrings } from '@shell/utils/computed'; import { _CREATE, _EDIT, _VIEW } from '@shell/config/query-params'; export const SENTINEL = '__SENTINEL__'; +const NULLABLE_EMPTY_FIELDS = ['contentLibrary', 'folder', 'hostsystem']; const VAPP_MODE = { DISABLED: 'disabled', AUTO: 'auto', @@ -655,9 +656,12 @@ export default { if (!isValueInContent()) { const value = isArray ? [] : content[0]?.value; - // null and "" are valid values for hostsystem and folder - const isNullOrEmpty = ['folder', 'hostsystem'].includes(key) && (this.value[key] === null || this.value[key] === ''); - const shouldHandleError = [_EDIT, _VIEW].includes(this.mode) && !isNullOrEmpty && !this.poolCreateMode; + const isNullOrEmpty = NULLABLE_EMPTY_FIELDS.includes(key) && (this.value[key] === null || this.value[key] === ''); + const shouldHandleError = + [_EDIT, _VIEW].includes(this.mode) && // error messages should only be displayed in Edit or View mode + !this.poolCreateMode && // almost identical to Create mode + !isNullOrEmpty && // null and empty string are valid values for some fields e.g. contentLibrary, folder and hostsystem + !isArray; // this flag is used for network and tag fields, and should not display error for them if ((this.mode === _CREATE || this.poolCreateMode) && value !== SENTINEL) { set(this.value, key, value);