This is an automated email from the ASF dual-hosted git repository.

sandeepk318 pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 290e9eae77 AMBARI-26657. Fix Add Service wizard Next button and Select 
Version/Notifications steps (#4219)
290e9eae77 is described below

commit 290e9eae77212320956454f6a93a1f18c1fa15e4
Author: Jefferson Almeida <[email protected]>
AuthorDate: Sat Sep 12 03:08:12 2026 -0300

    AMBARI-26657. Fix Add Service wizard Next button and Select 
Version/Notifications steps (#4219)
    
    * AMBARI-26657. Dedupe Select Version tabs by repository_version
    
    The Install Wizard's Select Version step showed a duplicate tab per
    stack line (e.g. two tabs pointing at the exact same install), because
    /api/v1/version_definitions genuinely returns two VersionDefinition
    entries per stack line once a stack has a registered repository_version:
    a generic default one (stack_default: true) and a more specific alias
    (stack_default: false), both carrying the identical repository_version.
    Step1.tsx rendered a tab per item straight off sortedItems with no
    deduplication, so both showed up.
    
    Group definitions.items by repository_version before sorting, keeping
    the stack_default entry when both are present.
    
    Co-Authored-By: Claude Sonnet 5 <[email protected]>
    
    * AMBARI-26657. Stop MISC > Notifications fields from blocking the wizard
    
    The Customize Services step's MISC > Notifications category (SMTP
    Host/Port/FROM Email/TO Email/etc.) always showed "This is required"
    for empty fields and blocked wizard progress, even though these fields
    are meant to be optional by default.
    
    data/configs/alert_notifications.ts already carries isRequired: false
    on every field, but addAlertNotificationProperties() in Step7/index.tsx
    never read that flag when building each property's propertyAttributes,
    so propertyAttributes.empty_value_valid was left undefined.
    ConfigUtils's validateInput() treats a missing/falsy empty_value_valid
    as required, so every empty Notifications field failed validation.
    
    Map empty_value_valid: !isRequired into each field's propertyAttributes,
    scoped to the alert_notifications property list. Also lifted the
    function out of the component closure into an exported, pure
    addAlertNotificationProperties(wizardName, updatedConfigProperties) so
    it is directly unit-testable.
    
    Co-Authored-By: Claude Sonnet 5 <[email protected]>
    
    * AMBARI-26657. Fix Add Service wizard Next button silently failing past 
step1
    
    jumpToStep() rejects any forward jump (targetStep > activeStep) unless
    called with isImperitiveJump=true. saveServicesAndContinue() called it
    without that flag when advancing past Add Service step1, so clicking
    Next after selecting services did nothing - no error, no navigation.
    
    Co-Authored-By: Claude Sonnet 5 <[email protected]>
    
    * AMBARI-26657. Fix Add Service wizard Next button failing on steps past 
step1
    
    Same root cause as the step1 fix: the addService-specific forward-
    navigation branches in Step5 (Assign Masters), Step6 (Assign Slaves and
    Clients), and Step7 (Configurations) all called jumpToStep(nextStep)
    without isImperitiveJump=true. Since canJumpFromCurrentStep() rejects
    any targetStep > activeStep unless that flag is set, clicking Next
    silently did nothing on every step of the Add Service wizard past
    step1, not just step1.
    
    Also fixes a Step7 test whose assertion had the bug baked in (expected
    jumpToStep to be called without the true flag).
    
    Co-Authored-By: Claude Sonnet 5 <[email protected]>
    
    * AMBARI-26657. Add regression tests for the forward jumpToStep fixes
    
    Cover the shared root cause behind the Add Service wizard Next-button
    fixes: useStepWizard's jumpToStep() silently no-ops on a forward jump
    unless isImperitiveJump=true is passed, which is exactly what Step4/
    Step5/Step6/Step7 were missing.
    
    - useStepWizard.test.tsx (renamed from .ts to allow JSX): asserts a
      forward jumpToStep() call is rejected without the flag and succeeds
      with it, proving the gating mechanism the fix relies on.
    - Step5.test.tsx: renders Step5 in addService mode, clicks Next, and
      asserts jumpToStep is called with (nextStep, true) - a direct
      regression test for this fix. Confirmed it fails if the fix is
      reverted (jumpToStep(nextStep) without the flag hangs on
      isNextEnabled/waitFor and the assertion never matches).
    
    Step4 and Step6 have the identical one-line fix but their existing
    test scaffolding mocks out the Table/AssignMasters children in a way
    that makes reaching the Next click non-trivial without deeper test
    restructuring; left as a manual QA item (see the wizard end-to-end
    walkthrough in the PR description) rather than force a fragile test.
    
    
    ---------
    
    Co-authored-by: Jeff Almeida <[email protected]>
---
 ...seStepWizard.test.ts => useStepWizard.test.tsx} |  41 ++++++-
 .../latest/src/screens/ClusterWizard/Step1.tsx     |  16 ++-
 .../latest/src/screens/ClusterWizard/Step4.tsx     |   2 +-
 .../src/screens/ClusterWizard/Step5.test.tsx       |  41 ++++++-
 .../latest/src/screens/ClusterWizard/Step5.tsx     |   2 +-
 .../latest/src/screens/ClusterWizard/Step6.tsx     |   2 +-
 .../src/screens/ClusterWizard/Step7/index.test.tsx |  23 +++-
 .../src/screens/ClusterWizard/Step7/index.tsx      | 130 +++++++++++----------
 .../CommonConfigs/ConfigUtils.theme.test.ts        |  59 ++++++++++
 9 files changed, 246 insertions(+), 70 deletions(-)

diff --git a/ambari-web/latest/src/hooks/useStepWizard.test.ts 
b/ambari-web/latest/src/hooks/useStepWizard.test.tsx
similarity index 60%
rename from ambari-web/latest/src/hooks/useStepWizard.test.ts
rename to ambari-web/latest/src/hooks/useStepWizard.test.tsx
index 9a9e2719ca..5336bd44a7 100644
--- a/ambari-web/latest/src/hooks/useStepWizard.test.ts
+++ b/ambari-web/latest/src/hooks/useStepWizard.test.tsx
@@ -16,8 +16,11 @@
  * limitations under the License.
  */
 
+import { act, renderHook } from "@testing-library/react";
+import type { PropsWithChildren } from "react";
+import { MemoryRouter } from "react-router-dom";
 import { describe, expect, it } from "vitest";
-import {
+import useStepWizard, {
   getAdjacentVisibleStep,
   getVisibleStepNumbers,
 } from "./useStepWizard";
@@ -48,3 +51,39 @@ describe("step wizard navigation", () => {
     expect(getAdjacentVisibleStep(steps, 2, 1)).toBe(3);
   });
 });
+
+describe("jumpToStep forward-jump gating (AMBARI-26657)", () => {
+  function wrapper({ children }: PropsWithChildren) {
+    return <MemoryRouter>{children}</MemoryRouter>;
+  }
+
+  const threeSteps = () => ({
+    0: step(),
+    1: step(),
+    2: step(),
+  });
+
+  it("does not advance on a forward jump called without isImperitiveJump", () 
=> {
+    const { result } = renderHook(() => useStepWizard(threeSteps(), 0), {
+      wrapper,
+    });
+
+    act(() => {
+      result.current.jumpToStep(2);
+    });
+
+    expect(result.current.activeStep).toBe(0);
+  });
+
+  it("advances on a forward jump called with isImperitiveJump=true", () => {
+    const { result } = renderHook(() => useStepWizard(threeSteps(), 0), {
+      wrapper,
+    });
+
+    act(() => {
+      result.current.jumpToStep(2, true);
+    });
+
+    expect(result.current.activeStep).toBe(2);
+  });
+});
diff --git a/ambari-web/latest/src/screens/ClusterWizard/Step1.tsx 
b/ambari-web/latest/src/screens/ClusterWizard/Step1.tsx
index 1f44f1f343..1f5af954a4 100644
--- a/ambari-web/latest/src/screens/ClusterWizard/Step1.tsx
+++ b/ambari-web/latest/src/screens/ClusterWizard/Step1.tsx
@@ -193,7 +193,21 @@ export default function Step1({ wizardName = 
"clusterCreation" }) {
         }
         const definitions: VersionDefinitionResponse =
           await VersionsApi.getVersionDefinitions(stackName);
-        const sortedItems = [...(definitions.items || [])].sort((a: any, b: 
any) => {
+        // Ambari's /version_definitions advertises the same repository_version
+        // twice for a stack line that already has one: once as the generic
+        // "<stack>-<stack_version>" default (stack_default=true) and once as
+        // the more specific "<stack>-<stack_version>-<repository_version>"
+        // alias (stack_default=false) - both resolve to the same install.
+        // Keep one tab per repository_version, preferring the default entry.
+        const dedupedByRepoVersion = new Map<string, any>();
+        (definitions.items || []).forEach((item: any) => {
+          const key = item.VersionDefinition.repository_version || 
item.VersionDefinition.id;
+          const existing = dedupedByRepoVersion.get(key);
+          if (!existing || (item.VersionDefinition.stack_default && 
!existing.VersionDefinition.stack_default)) {
+            dedupedByRepoVersion.set(key, item);
+          }
+        });
+        const sortedItems = Array.from(dedupedByRepoVersion.values()).sort((a: 
any, b: any) => {
           const versionA = parseFloat(a.VersionDefinition.id.split("-")[1]);
           const versionB = parseFloat(b.VersionDefinition.id.split("-")[1]);
 
diff --git a/ambari-web/latest/src/screens/ClusterWizard/Step4.tsx 
b/ambari-web/latest/src/screens/ClusterWizard/Step4.tsx
index c7ad1820cd..7cc8717f86 100644
--- a/ambari-web/latest/src/screens/ClusterWizard/Step4.tsx
+++ b/ambari-web/latest/src/screens/ClusterWizard/Step4.tsx
@@ -152,7 +152,7 @@ export default function Step4({ wizardName = 
"clusterCreation" }) {
     if (wizardName === "addService") {
       const nextStep = nextAddServiceStep(1, flow);
       await Promise.resolve(flushStateToDb("jump", nextStep));
-      jumpToStep(nextStep);
+      jumpToStep(nextStep, true);
     } else {
       await Promise.resolve(flushStateToDb("next"));
       handleNextImperitive();
diff --git a/ambari-web/latest/src/screens/ClusterWizard/Step5.test.tsx 
b/ambari-web/latest/src/screens/ClusterWizard/Step5.test.tsx
index d03eadbc7c..0821c82f44 100644
--- a/ambari-web/latest/src/screens/ClusterWizard/Step5.test.tsx
+++ b/ambari-web/latest/src/screens/ClusterWizard/Step5.test.tsx
@@ -17,8 +17,8 @@
  */
 
 import { createContext } from "react";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react";
-import { beforeEach, describe, expect, it, vi } from "vitest";
+import { cleanup, fireEvent, render, screen, waitFor } from 
"@testing-library/react";
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
 import { ContextWrapper } from ".";
 
 const mocks = vi.hoisted(() => ({
@@ -51,6 +51,7 @@ describe("Assign Masters validation", () => {
     vi.clearAllMocks();
     mocks.flushStateToDb.mockResolvedValue(undefined);
   });
+  afterEach(() => cleanup());
 
   it("requires Continue Anyway before advancing with matching issues", async 
() => {
     const value = {
@@ -104,5 +105,41 @@ describe("Assign Masters validation", () => {
       expect(mocks.handleNextImperitive).toHaveBeenCalledOnce();
     });
   });
+
+  it("jumps forward with isImperitiveJump=true when advancing the Add Service 
wizard (AMBARI-26657)", async () => {
+    const jumpToStep = vi.fn();
+    const value = {
+      state: {
+        addServiceSteps: {
+          SERVICES: { data: { services: {}, addServiceFlow: {} } },
+        },
+      },
+      dispatch: vi.fn(),
+      flushStateToDb: mocks.flushStateToDb,
+      installedHosts: [],
+      installedServices: [],
+      stepWizardUtilities: {
+        currentStep: { canGoBack: true, name: "MASTERS" },
+        handleNextImperitive: mocks.handleNextImperitive,
+        handleBackImperitive: vi.fn(),
+        jumpToStep,
+      },
+    };
+    const WizardContext = createContext(value);
+
+    render(
+      <ContextWrapper.Provider value={{ Context: WizardContext }}>
+        <WizardContext.Provider value={value}>
+          <Step5 wizardName="addService" />
+        </WizardContext.Provider>
+      </ContextWrapper.Provider>,
+    );
+
+    fireEvent.click(screen.getByRole("button", { name: "NEXT" }));
+
+    await waitFor(() => {
+      expect(jumpToStep).toHaveBeenCalledWith(3, true);
+    });
+  });
 });
 
diff --git a/ambari-web/latest/src/screens/ClusterWizard/Step5.tsx 
b/ambari-web/latest/src/screens/ClusterWizard/Step5.tsx
index 53d4fb391f..9638ef0d8e 100644
--- a/ambari-web/latest/src/screens/ClusterWizard/Step5.tsx
+++ b/ambari-web/latest/src/screens/ClusterWizard/Step5.tsx
@@ -143,7 +143,7 @@ function Step5({ wizardName = "clusterCreation" }) {
           if (wizardName === "addService") {
             const nextStep = nextAddServiceStep(2, addServiceFlow);
             await Promise.resolve(flushStateToDb("jump", nextStep));
-            jumpToStep(nextStep);
+            jumpToStep(nextStep, true);
           } else if (hasValidationIssues) {
             setShowValidationIssuesModal(true);
           } else {
diff --git a/ambari-web/latest/src/screens/ClusterWizard/Step6.tsx 
b/ambari-web/latest/src/screens/ClusterWizard/Step6.tsx
index 9f235856dd..77f842cca5 100644
--- a/ambari-web/latest/src/screens/ClusterWizard/Step6.tsx
+++ b/ambari-web/latest/src/screens/ClusterWizard/Step6.tsx
@@ -446,7 +446,7 @@ function Step6({ wizardName = "clusterCreation" }: 
Step6Props) {
     if (wizardName === "addService") {
       const nextStep = nextAddServiceStep(3, addServiceFlow);
       await Promise.resolve(flushStateToDb("jump", nextStep));
-      jumpToStep(nextStep);
+      jumpToStep(nextStep, true);
     } else {
       await Promise.resolve(flushStateToDb("next"));
       handleNextImperitive();
diff --git a/ambari-web/latest/src/screens/ClusterWizard/Step7/index.test.tsx 
b/ambari-web/latest/src/screens/ClusterWizard/Step7/index.test.tsx
index 81fe76cf35..3d8b3c6c52 100644
--- a/ambari-web/latest/src/screens/ClusterWizard/Step7/index.test.tsx
+++ b/ambari-web/latest/src/screens/ClusterWizard/Step7/index.test.tsx
@@ -229,6 +229,7 @@ vi.mock("../../../components/StepWizard/WizardFooter", () 
=> ({
 }));
 
 import Step7, {
+  addAlertNotificationProperties,
   findNextEnabledConfigurationTab,
   findPreviousEnabledConfigurationTab,
 } from ".";
@@ -748,7 +749,7 @@ describe("Step 7 Theme fallback", () => {
     expect(mocks.dispatch.mock.invocationCallOrder.at(-1)).toBeLessThan(
       mocks.flushStateToDb.mock.invocationCallOrder[0]
     );
-    expect(mocks.jumpToStep).toHaveBeenCalledWith(5);
+    expect(mocks.jumpToStep).toHaveBeenCalledWith(5, true);
   });
 
   it("loads installed and newly selected Add Service context while 
recommending only new services", async () => {
@@ -789,3 +790,23 @@ describe("Step 7 Theme fallback", () => {
     });
   });
 });
+
+describe("addAlertNotificationProperties", () => {
+  it("marks every visible MISC > Notifications field as optional by default", 
() => {
+    const result = addAlertNotificationProperties("clusterCreation", {});
+
+    const notificationProperties = result.MISC.Notifications.properties;
+    const visibleFieldNames = ["mail.smtp.host", "mail.smtp.port", 
"mail.smtp.from", "ambari.dispatch.recipients"];
+
+    visibleFieldNames.forEach((propertyName) => {
+      
expect(notificationProperties[propertyName].propertyAttributes.empty_value_valid).toBe(true);
+      expect(notificationProperties[propertyName].value).toBe("");
+    });
+  });
+
+  it("does not add a Notifications category for the add service wizard", () => 
{
+    const result = addAlertNotificationProperties("addService", {});
+
+    expect(result.MISC).toBeUndefined();
+  });
+});
diff --git a/ambari-web/latest/src/screens/ClusterWizard/Step7/index.tsx 
b/ambari-web/latest/src/screens/ClusterWizard/Step7/index.tsx
index 720bb43842..c9d2448fc7 100644
--- a/ambari-web/latest/src/screens/ClusterWizard/Step7/index.tsx
+++ b/ambari-web/latest/src/screens/ClusterWizard/Step7/index.tsx
@@ -167,6 +167,72 @@ export const findInitialConfigurationTab = (disabledTabs: 
string[]) => {
   return "allConfigurations";
 };
 
+/**
+ * Add alert notification properties
+ * Note: In add service wizard, notification properties should not be added 
(matching Ember.js behavior)
+ */
+export const addAlertNotificationProperties = (
+  wizardName: string,
+  updatedConfigProperties: ConfigPropertiesType,
+): ConfigPropertiesType => {
+  // Skip adding notification properties in add service wizard
+  // This matches Ember.js behavior where Notifications category is removed 
from MISC in addServiceController
+  if (wizardName === "addService") {
+    return updatedConfigProperties;
+  }
+
+  // Create a deep clone to avoid modifying the original
+  const result = cloneDeep(updatedConfigProperties);
+
+  alert_notifications.forEach((property) => {
+    const {
+      serviceName,
+      name,
+      category,
+      displayName,
+      displayType,
+      filename,
+      isVisible,
+      isRequired,
+    } = property;
+
+    if (!result[serviceName]) {
+      result[serviceName] = {};
+    }
+    if (!result[serviceName][category]) {
+      result[serviceName][category] = {
+        errors: 0,
+        properties: {},
+      };
+    }
+
+    if (isVisible) {
+      result[serviceName][category].properties[name] = {
+        propertyName: name,
+        propertyDisplayname: displayName || "",
+        propertyValue: "",
+        propertyAttributes: {
+          type: displayType || "string",
+          overridable: false,
+          // Mirrors classic's alert_notification.js: every Notifications 
field is
+          // optional until notification_configs_view.js's opt-in toggle flips 
it
+          // (that toggle isn't ported here, so these stay permanently 
optional).
+          empty_value_valid: !isRequired,
+        },
+        previousValue: "",
+        value: displayType === "checkbox" ? "false" : "",
+        final: "false",
+        savedFinal: "false",
+        fileName: filename,
+        type: filename,
+        isEditable: true,
+      };
+    }
+  });
+
+  return result;
+};
+
 const preserveEditedConfigValues = (
   nextConfigs: ConfigPropertiesType,
   currentConfigs: ConfigPropertiesType,
@@ -1569,66 +1635,6 @@ export default function Step7({ wizardName = 
"clusterCreation" }: PropTypes) {
     return result;
   };
 
-  /**
-   * Add alert notification properties
-   * Note: In add service wizard, notification properties should not be added 
(matching Ember.js behavior)
-   */
-  const addAlertNotificationProperties = (
-    updatedConfigProperties: ConfigPropertiesType
-  ) => {
-    // Skip adding notification properties in add service wizard
-    // This matches Ember.js behavior where Notifications category is removed 
from MISC in addServiceController
-    if (wizardName === "addService") {
-      return updatedConfigProperties;
-    }
-
-    // Create a deep clone to avoid modifying the original
-    const result = cloneDeep(updatedConfigProperties);
-
-    alert_notifications.forEach((property) => {
-      const {
-        serviceName,
-        name,
-        category,
-        displayName,
-        displayType,
-        filename,
-        isVisible,
-      } = property;
-
-      if (!result[serviceName]) {
-        result[serviceName] = {};
-      }
-      if (!result[serviceName][category]) {
-        result[serviceName][category] = {
-          errors: 0,
-          properties: {},
-        };
-      }
-
-      if (isVisible) {
-        result[serviceName][category].properties[name] = {
-          propertyName: name,
-          propertyDisplayname: displayName || "",
-          propertyValue: "",
-          propertyAttributes: {
-            type: displayType || "string",
-            overridable: false,
-          },
-          previousValue: "",
-          value: displayType === "checkbox" ? "false" : "",
-          final: "false",
-          savedFinal: "false",
-          fileName: filename,
-          type: filename,
-          isEditable: true,
-        };
-      }
-    });
-
-    return result;
-  };
-
   /**
    * Process stack level configurations
    */
@@ -2327,7 +2333,7 @@ export default function Step7({ wizardName = 
"clusterCreation" }: PropTypes) {
       updatedConfigProperties = 
addServiceConfigCategories(configPropertiesCopy, updatedConfigProperties);
       updatedConfigProperties = 
organizePropertiesByCategories(configPropertiesCopy, updatedConfigProperties);
       updatedConfigProperties = addRemainingProperties(configPropertiesCopy, 
updatedConfigProperties);
-      updatedConfigProperties = 
addAlertNotificationProperties(updatedConfigProperties);
+      updatedConfigProperties = addAlertNotificationProperties(wizardName, 
updatedConfigProperties);
       updatedConfigProperties = await 
processStackLevelConfigurations(updatedConfigProperties);
       updatedConfigProperties = onLoadOverrides(updatedConfigProperties);
       updatedConfigProperties = initializeValues(updatedConfigProperties);
@@ -2526,7 +2532,7 @@ export default function Step7({ wizardName = 
"clusterCreation" }: PropTypes) {
     if (wizardName === "addService") {
       const nextStep = nextAddServiceStep(4, addServiceFlow);
       await Promise.resolve(flushStateToDb("jump", nextStep));
-      jumpToStep(nextStep);
+      jumpToStep(nextStep, true);
     } else {
       await Promise.resolve(flushStateToDb("next"));
       handleNextImperitive();
diff --git 
a/ambari-web/latest/src/screens/CommonConfigs/ConfigUtils.theme.test.ts 
b/ambari-web/latest/src/screens/CommonConfigs/ConfigUtils.theme.test.ts
index 6cd934f446..19540d0974 100644
--- a/ambari-web/latest/src/screens/CommonConfigs/ConfigUtils.theme.test.ts
+++ b/ambari-web/latest/src/screens/CommonConfigs/ConfigUtils.theme.test.ts
@@ -23,9 +23,11 @@ import {
   getThemePlacementProperty,
   setTabErrorCounts,
   updateVisibilityForDependsOn,
+  validateInput,
 } from "./ConfigUtils";
 import { ConfigPropertiesType } from "./types";
 import { normalizeDefaultThemeResponse } from "./themeEngine";
+import { alert_notifications } from "../../data/configs/alert_notifications";
 
 type Placement = {
   config: string;
@@ -606,3 +608,60 @@ describe("Service Theme config visibility", () => {
     );
   });
 });
+
+describe("MISC > Notifications properties default to optional (matches 
classic's untoggled default)", () => {
+  // Mirrors ambari-web/classic/app/data/configs/alert_notification.js, where 
every field is
+  // hardcoded isRequired:false and notification_configs_view.js only flips 
that when the user
+  // opts in via createNotification (not ported here) - see 
data/configs/alert_notifications.ts.
+  const visibleNotificationFields = alert_notifications.filter(
+    (property) => property.isVisible,
+  );
+
+  it("has at least one visible SMTP/notification field to guard", () => {
+    expect(visibleNotificationFields.length).toBeGreaterThan(0);
+  });
+
+  it.each(visibleNotificationFields.map((property) => [property.name, 
property]))(
+    "%s is not required when left empty",
+    (_name, property: any) => {
+      const wizardProperty = {
+        propertyName: property.name,
+        propertyDisplayname: property.displayName || "",
+        propertyValue: "",
+        previousValue: "",
+        value: property.displayType === "checkbox" ? "false" : "",
+        isVisible: true,
+        isHidden: false,
+        isEditable: true,
+        propertyAttributes: {
+          type: property.displayType || "string",
+          overridable: false,
+          empty_value_valid: !property.isRequired,
+        },
+      };
+
+      expect(validateInput(wizardProperty, "")).toBe("");
+    },
+  );
+
+  it("would have blocked the wizard before empty_value_valid was wired up from 
isRequired", () => {
+    const propertyMissingEmptyValueValid = {
+      propertyName: "mail.smtp.host",
+      propertyDisplayname: "SMTP Host",
+      propertyValue: "",
+      previousValue: "",
+      value: "",
+      isVisible: true,
+      isHidden: false,
+      isEditable: true,
+      propertyAttributes: {
+        type: "host",
+        overridable: false,
+      },
+    };
+
+    expect(validateInput(propertyMissingEmptyValueValid, "")).toBe(
+      "This is required",
+    );
+  });
+});


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to