diff --git a/src/ui/environment/helpers/__tests__/networkConfig.test.ts b/src/ui/environment/helpers/__tests__/networkConfig.test.ts new file mode 100644 index 00000000..2c32bfab --- /dev/null +++ b/src/ui/environment/helpers/__tests__/networkConfig.test.ts @@ -0,0 +1,99 @@ +import type { Source } from "@openshift-migration-advisor/planner-sdk"; +import { describe, expect, it } from "vitest"; + +import { getNetworkConfig } from "../networkConfig"; + +describe("networkConfig helpers", () => { + describe("getNetworkConfig", () => { + it("should extract all network fields correctly with static config", () => { + const source: Partial = { + infra: { + vmNetwork: { + ipv4: { + ipAddress: "192.168.1.100", + subnetMask: "255.255.255.0", + defaultGateway: "192.168.1.1", + dns: "8.8.8.8", + }, + }, + }, + }; + + const config = getNetworkConfig(source as Source); + + expect(config).toEqual({ + networkConfigType: "static", + ipAddress: "192.168.1.100", + subnetMask: "255.255.255.0", + defaultGateway: "192.168.1.1", + dns: "8.8.8.8", + }); + }); + + it("should return dhcp when vmNetwork is undefined", () => { + const source: Partial = { + infra: { + vmNetwork: undefined, + }, + }; + + const config = getNetworkConfig(source as Source); + + expect(config).toEqual({ + networkConfigType: "dhcp", + ipAddress: "", + subnetMask: "", + defaultGateway: "", + dns: "", + }); + }); + + it("should return dhcp when infra is undefined", () => { + const source: Partial = { + infra: undefined, + }; + + const config = getNetworkConfig(source as Source); + + expect(config).toEqual({ + networkConfigType: "dhcp", + ipAddress: "", + subnetMask: "", + defaultGateway: "", + dns: "", + }); + }); + + it("should return dhcp when vmNetwork.ipv4 is undefined", () => { + const source: Partial = { + infra: { + vmNetwork: { + ipv4: undefined, + }, + }, + }; + + const config = getNetworkConfig(source as Source); + + expect(config).toEqual({ + networkConfigType: "dhcp", + ipAddress: "", + subnetMask: "", + defaultGateway: "", + dns: "", + }); + }); + + it("should handle undefined source gracefully", () => { + const config = getNetworkConfig(undefined); + + expect(config).toEqual({ + networkConfigType: "dhcp", + ipAddress: "", + subnetMask: "", + defaultGateway: "", + dns: "", + }); + }); + }); +}); diff --git a/src/ui/environment/helpers/__tests__/proxyConfig.test.ts b/src/ui/environment/helpers/__tests__/proxyConfig.test.ts index 67a97f8f..40a7c529 100644 --- a/src/ui/environment/helpers/__tests__/proxyConfig.test.ts +++ b/src/ui/environment/helpers/__tests__/proxyConfig.test.ts @@ -19,10 +19,10 @@ describe("proxyConfig helpers", () => { const config = getProxyConfig(source as Source); expect(config).toEqual({ - httpUrl: "http://proxy.example.com:8080", - httpsUrl: "https://proxy.example.com:8443", + httpProxy: "http://proxy.example.com:8080", + httpsProxy: "https://proxy.example.com:8443", noProxy: "test.example.org", - isProxyEnabled: true, + enableProxy: true, }); }); @@ -40,10 +40,10 @@ describe("proxyConfig helpers", () => { const config = getProxyConfig(source as Source); expect(config).toEqual({ - httpUrl: "", - httpsUrl: "", + httpProxy: "", + httpsProxy: "", noProxy: "", - isProxyEnabled: false, + enableProxy: false, }); }); @@ -55,14 +55,14 @@ describe("proxyConfig helpers", () => { const config = getProxyConfig(source as Source); expect(config).toEqual({ - httpUrl: "", - httpsUrl: "", + httpProxy: "", + httpsProxy: "", noProxy: "", - isProxyEnabled: false, + enableProxy: false, }); }); - it("should detect isProxyEnabled when only noProxy is set", () => { + it("should detect enableProxy when only noProxy is set", () => { const source: Partial = { infra: { proxy: { @@ -75,7 +75,7 @@ describe("proxyConfig helpers", () => { const config = getProxyConfig(source as Source); - expect(config.isProxyEnabled).toBe(true); + expect(config.enableProxy).toBe(true); expect(config.noProxy).toBe("test.example.org"); }); @@ -83,10 +83,31 @@ describe("proxyConfig helpers", () => { const config = getProxyConfig(undefined); expect(config).toEqual({ - httpUrl: "", - httpsUrl: "", + httpProxy: "", + httpsProxy: "", noProxy: "", - isProxyEnabled: false, + enableProxy: false, + }); + }); + + it("should treat whitespace-only proxy values as empty (enableProxy=false)", () => { + const source: Partial = { + infra: { + proxy: { + httpUrl: " ", + httpsUrl: " ", + noProxy: " ", + }, + }, + }; + + const config = getProxyConfig(source as Source); + + expect(config).toEqual({ + httpProxy: " ", + httpsProxy: " ", + noProxy: " ", + enableProxy: false, }); }); }); diff --git a/src/ui/environment/helpers/networkConfig.ts b/src/ui/environment/helpers/networkConfig.ts new file mode 100644 index 00000000..7a1540be --- /dev/null +++ b/src/ui/environment/helpers/networkConfig.ts @@ -0,0 +1,38 @@ +import type { Source } from "@openshift-migration-advisor/planner-sdk"; + +/** + * Type-safe helper to extract network configuration from a Source. + * This ensures we always access the network via the correct path (src.infra.vmNetwork) + * and provides compile-time safety if the SDK structure changes. + */ +export interface NetworkConfig { + networkConfigType: "dhcp" | "static"; + ipAddress: string; + subnetMask: string; + defaultGateway: string; + dns: string; +} + +/** + * Extracts network configuration from a Source object. + * Returns normalized values (empty strings instead of null/undefined). + * networkConfigType is "static" if vmNetwork.ipv4 exists, otherwise "dhcp". + */ +export const getNetworkConfig = (source: Source | undefined): NetworkConfig => { + const network = source?.infra?.vmNetwork?.ipv4; + + const ipAddress = network?.ipAddress ?? ""; + const subnetMask = network?.subnetMask ?? ""; + const defaultGateway = network?.defaultGateway ?? ""; + const dns = network?.dns ?? ""; + + const networkConfigType = network ? "static" : "dhcp"; + + return { + networkConfigType, + ipAddress, + subnetMask, + defaultGateway, + dns, + }; +}; diff --git a/src/ui/environment/helpers/proxyConfig.ts b/src/ui/environment/helpers/proxyConfig.ts index 981b9b84..468f9982 100644 --- a/src/ui/environment/helpers/proxyConfig.ts +++ b/src/ui/environment/helpers/proxyConfig.ts @@ -6,10 +6,10 @@ import type { Source } from "@openshift-migration-advisor/planner-sdk"; * and provides compile-time safety if the SDK structure changes. */ export interface ProxyConfig { - httpUrl: string; - httpsUrl: string; + httpProxy: string; + httpsProxy: string; noProxy: string; - isProxyEnabled: boolean; + enableProxy: boolean; } /** @@ -19,14 +19,16 @@ export interface ProxyConfig { export const getProxyConfig = (source: Source | undefined): ProxyConfig => { const proxy = source?.infra?.proxy; - const httpUrl = proxy?.httpUrl ?? ""; - const httpsUrl = proxy?.httpsUrl ?? ""; + const httpProxy = proxy?.httpUrl ?? ""; + const httpsProxy = proxy?.httpsUrl ?? ""; const noProxy = proxy?.noProxy ?? ""; return { - httpUrl, - httpsUrl, + httpProxy, + httpsProxy, noProxy, - isProxyEnabled: Boolean(httpUrl || httpsUrl || noProxy), + enableProxy: Boolean( + httpProxy.trim() || httpsProxy.trim() || noProxy.trim(), + ), }; }; diff --git a/src/ui/environment/views/DiscoverySourceSetupModal.tsx b/src/ui/environment/views/DiscoverySourceSetupModal.tsx index 36b3f4f2..6d9f4cab 100644 --- a/src/ui/environment/views/DiscoverySourceSetupModal.tsx +++ b/src/ui/environment/views/DiscoverySourceSetupModal.tsx @@ -25,6 +25,7 @@ import { import React, { useCallback, useEffect, useState } from "react"; import { VCenterSetupInstructions } from "../../core/components/VCenterSetupInstructions"; +import { getNetworkConfig } from "../helpers/networkConfig"; import { getProxyConfig } from "../helpers/proxyConfig"; import { normalizeSshKey, validateSshKey } from "../helpers/sshKey"; import { useEnvironmentPage } from "../view-models/EnvironmentPageContext"; @@ -393,22 +394,22 @@ export const DiscoverySourceSetupModal: React.FC< if (src) { setEnvironmentName(src.name || ""); const proxyConfig = getProxyConfig(src); - setHttpProxy(proxyConfig.httpUrl); - setHttpsProxy(proxyConfig.httpsUrl); + setHttpProxy(proxyConfig.httpProxy); + setHttpsProxy(proxyConfig.httpsProxy); setNoProxy(proxyConfig.noProxy); - setEnableProxy(proxyConfig.isProxyEnabled); + setEnableProxy(proxyConfig.enableProxy); + + const networkConfig = getNetworkConfig(src); + setNetworkConfigType(networkConfig.networkConfigType); + setIpAddress(networkConfig.ipAddress); + setSubnetMask(networkConfig.subnetMask); + setDefaultGateway(networkConfig.defaultGateway); + setDns(networkConfig.dns); setInitialValues({ sshKey: "", environmentName: src.name || "", - httpProxy: proxyConfig.httpUrl, - httpsProxy: proxyConfig.httpsUrl, - noProxy: proxyConfig.noProxy, - enableProxy: proxyConfig.isProxyEnabled, - networkConfigType: "dhcp", - dns: "", - subnetMask: "", - defaultGateway: "", - ipAddress: "", + ...proxyConfig, + ...networkConfig, }); } }