From 95fc72173f9b8e8c7f5f36cac9284d5605c3b4ee Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Sat, 29 Mar 2025 22:59:46 -0400 Subject: [PATCH] adding tests --- .../Config/Network/Network.test.tsx | 283 ++++++++++++++++++ .../Config/{Network.tsx => Network/index.tsx} | 2 - src/pages/Config/DeviceConfig.tsx | 2 +- 3 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 src/components/PageComponents/Config/Network/Network.test.tsx rename src/components/PageComponents/Config/{Network.tsx => Network/index.tsx} (99%) diff --git a/src/components/PageComponents/Config/Network/Network.test.tsx b/src/components/PageComponents/Config/Network/Network.test.tsx new file mode 100644 index 00000000..14f54e1c --- /dev/null +++ b/src/components/PageComponents/Config/Network/Network.test.tsx @@ -0,0 +1,283 @@ +// import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +// import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +// import { Network } from '@components/PageComponents/Config/Network/index.tsx'; +// import { useDevice } from "@core/stores/deviceStore.ts"; +// import { Protobuf } from "@meshtastic/core"; + +// vi.mock('@core/stores/deviceStore', () => ({ +// useDevice: vi.fn() +// })); + +// vi.mock('@components/Form/DynamicForm', () => ({ +// DynamicForm: vi.fn(({ onSubmit }) => { +// return ( +//
+// +// +//
+// ); +// }) +// })); + +// describe('Network component', () => { +// const setWorkingConfigMock = vi.fn(); +// const mockDeviceConfig = { +// role: "CLIENT", +// buttonGpio: 0, +// buzzerGpio: 0, +// rebroadcastMode: "ALL", +// nodeInfoBroadcastSecs: 300, +// doubleTapAsButtonPress: false, +// disableTripleClick: false, +// ledHeartbeatDisabled: false, +// }; + +// beforeEach(() => { +// vi.resetAllMocks(); + +// (useDevice as any).mockReturnValue({ +// config: { +// device: mockDeviceConfig +// }, +// setWorkingConfig: setWorkingConfigMock +// }); + +// }); + +// afterEach(() => { +// vi.clearAllMocks(); +// }); + +// it('should render the Network form', () => { +// render(); +// expect(screen.getByTestId('dynamic-form')).toBeInTheDocument(); +// }); + +// it('should call setWorkingConfig when form is submitted', async () => { +// render(); + +// fireEvent.click(screen.getByTestId('submit-button')); + +// await waitFor(() => { +// expect(setWorkingConfigMock).toHaveBeenCalledWith( +// expect.objectContaining({ +// payloadVariant: { +// case: "device", +// value: expect.objectContaining({ role: "CLIENT" }) +// } +// }) +// ); +// }); +// }); + + +// it('should create config with proper structure', async () => { +// render(); + +// // Simulate form submission +// fireEvent.click(screen.getByTestId('submit-button')); + +// await waitFor(() => { +// expect(setWorkingConfigMock).toHaveBeenCalledWith( +// expect.objectContaining({ +// payloadVariant: { +// case: "network", +// value: expect.any(Object) +// } +// }) +// ); +// }); +// }); +// }); + +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import { Network } from '@components/PageComponents/Config/Network/index.tsx'; +import { useDevice } from "@core/stores/deviceStore.ts"; +import { Protobuf } from "@meshtastic/core"; + +vi.mock('@core/stores/deviceStore', () => ({ + useDevice: vi.fn() +})); + +vi.mock('@components/Form/DynamicForm', async () => { + const React = await import('react'); + const { useState } = React; + + return { + DynamicForm: ({ onSubmit, defaultValues }: any) => { + const [wifiEnabled, setWifiEnabled] = useState(defaultValues.wifiEnabled ?? false); + const [ssid, setSsid] = useState(defaultValues.wifiSsid ?? ''); + const [psk, setPsk] = useState(defaultValues.wifiPsk ?? ''); + + return ( +
{ + e.preventDefault(); + onSubmit({ + ...defaultValues, + wifiEnabled, + wifiSsid: ssid, + wifiPsk: psk, + }); + }} + data-testid="dynamic-form" + > + setWifiEnabled(e.target.checked)} + /> + setSsid(e.target.value)} + disabled={!wifiEnabled} + /> + setPsk(e.target.value)} + disabled={!wifiEnabled} + /> + +
+ ); + }, + }; +}); +; + +describe('Network component', () => { + const setWorkingConfigMock = vi.fn(); + const mockNetworkConfig = { + wifiEnabled: false, + wifiSsid: '', + wifiPsk: '', + ntpServer: '', + ethEnabled: false, + addressMode: Protobuf.Config.Config_NetworkConfig_AddressMode.DHCP, + ipv4Config: { + ip: 0, + gateway: 0, + subnet: 0, + dns: 0, + }, + enabledProtocols: + Protobuf.Config.Config_NetworkConfig_ProtocolFlags.NO_BROADCAST, + rsyslogServer: '', + }; + + beforeEach(() => { + vi.resetAllMocks(); + + (useDevice as any).mockReturnValue({ + config: { + network: mockNetworkConfig + }, + setWorkingConfig: setWorkingConfigMock + }); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it('should render the Network form', () => { + render(); + expect(screen.getByTestId('dynamic-form')).toBeInTheDocument(); + }); + + it('should disable SSID and PSK fields when wifi is off', () => { + render(); + expect(screen.getByLabelText("SSID")).toBeDisabled(); + expect(screen.getByLabelText("PSK")).toBeDisabled(); + }); + + it('should enable SSID and PSK when wifi is toggled on', async () => { + render(); + const toggle = screen.getByLabelText("WiFi Enabled"); + screen.debug() + + fireEvent.click(toggle); // turns wifiEnabled = true + + await waitFor(() => { + expect(screen.getByLabelText("SSID")).not.toBeDisabled(); + expect(screen.getByLabelText("PSK")).not.toBeDisabled(); + }); + }); + + it('should call setWorkingConfig with the right structure on submit', async () => { + render(); + + fireEvent.click(screen.getByTestId("submit-button")); + + await waitFor(() => { + expect(setWorkingConfigMock).toHaveBeenCalledWith( + expect.objectContaining({ + payloadVariant: { + case: "network", + value: expect.objectContaining({ + wifiEnabled: false, + wifiSsid: '', + wifiPsk: '', + ntpServer: '', + ethEnabled: false, + rsyslogServer: '', + }) + } + }) + ); + }); + }); + + it('should submit valid data after enabling wifi and entering SSID and PSK', async () => { + render(); + fireEvent.click(screen.getByLabelText("WiFi Enabled")); + + fireEvent.change(screen.getByLabelText("SSID"), { + target: { value: "MySSID" } + }); + + fireEvent.change(screen.getByLabelText("PSK"), { + target: { value: "MySecretPSK" } + }); + + fireEvent.click(screen.getByTestId("submit-button")); + + await waitFor(() => { + expect(setWorkingConfigMock).toHaveBeenCalledWith( + expect.objectContaining({ + payloadVariant: { + case: "network", + value: expect.objectContaining({ + wifiEnabled: true, + wifiSsid: "MySSID", + wifiPsk: "MySecretPSK" + }) + } + }) + ); + }); + }); +}); diff --git a/src/components/PageComponents/Config/Network.tsx b/src/components/PageComponents/Config/Network/index.tsx similarity index 99% rename from src/components/PageComponents/Config/Network.tsx rename to src/components/PageComponents/Config/Network/index.tsx index a52e74bd..cae121d6 100644 --- a/src/components/PageComponents/Config/Network.tsx +++ b/src/components/PageComponents/Config/Network/index.tsx @@ -12,8 +12,6 @@ import { validateSchema } from "@app/validation/validate.ts"; export const Network = () => { const { config, setWorkingConfig } = useDevice(); - console.log(config.network); - const onSubmit = (data: NetworkValidation) => { const result = validateSchema(NetworkValidationSchema, data); diff --git a/src/pages/Config/DeviceConfig.tsx b/src/pages/Config/DeviceConfig.tsx index 697b80b9..b97e8640 100644 --- a/src/pages/Config/DeviceConfig.tsx +++ b/src/pages/Config/DeviceConfig.tsx @@ -2,7 +2,7 @@ import { Bluetooth } from "@components/PageComponents/Config/Bluetooth.tsx"; import { Device } from "../../components/PageComponents/Config/Device/index.tsx"; import { Display } from "@components/PageComponents/Config/Display.tsx"; import { LoRa } from "@components/PageComponents/Config/LoRa.tsx"; -import { Network } from "@components/PageComponents/Config/Network.tsx"; +import { Network } from "../../components/PageComponents/Config/Network/index.tsx"; import { Position } from "@components/PageComponents/Config/Position.tsx"; import { Power } from "@components/PageComponents/Config/Power.tsx"; import { Security } from "../../components/PageComponents/Config/Security/Security.tsx";