diff --git a/src/app/store/reservedip/types/base.ts b/src/app/store/reservedip/types/base.ts index 5f00442172..2266cf2ff5 100644 --- a/src/app/store/reservedip/types/base.ts +++ b/src/app/store/reservedip/types/base.ts @@ -6,7 +6,7 @@ import type { GenericState } from "@/app/store/types/state"; export type ReservedIp = TimestampedModel & { ip: string; - mac_address?: string; + mac_address: string; comment?: string; subnet: Subnet[SubnetMeta.PK]; node_summary?: ReservedIpNodeSummary; diff --git a/src/app/subnets/views/SubnetDetails/StaticDHCPLease/ReserveDHCPLease/ReserveDHCPLease.test.tsx b/src/app/subnets/views/SubnetDetails/StaticDHCPLease/ReserveDHCPLease/ReserveDHCPLease.test.tsx index 87a94ada2d..71f236cdb3 100644 --- a/src/app/subnets/views/SubnetDetails/StaticDHCPLease/ReserveDHCPLease/ReserveDHCPLease.test.tsx +++ b/src/app/subnets/views/SubnetDetails/StaticDHCPLease/ReserveDHCPLease/ReserveDHCPLease.test.tsx @@ -76,6 +76,24 @@ it("displays an error if an out-of-range IP address is entered", async () => { ).toBeInTheDocument(); }); +it("displays an error if the IP address or the MAC address are not entered", async () => { + state.subnet.items = [factory.subnet({ id: 1, cidr: "10.0.0.0/25" })]; + renderWithBrowserRouter( + , + { state } + ); + + await userEvent.click(screen.getByRole("textbox", { name: "IP address" })); + await userEvent.click(screen.getByRole("textbox", { name: "MAC address" })); + await userEvent.tab(); + + expect(screen.getByText("IP address is required")).toBeInTheDocument(); + expect(screen.getByText("MAC address is required")).toBeInTheDocument(); +}); + it("closes the side panel when the cancel button is clicked", async () => { const setSidePanelContent = vi.fn(); renderWithBrowserRouter( @@ -202,7 +220,7 @@ it("pre-fills the form if a reserved IPv6 address's ID is present", async () => ); }); -it("disables the IP address field when editing a lease", async () => { +it("disables the IP address and MAC address fields when editing a lease", async () => { const reservedIp = factory.reservedIp({ id: 1, ip: "10.0.0.69", @@ -226,6 +244,7 @@ it("disables the IP address field when editing a lease", async () => { ); expect(screen.getByRole("textbox", { name: "IP address" })).toBeDisabled(); + expect(screen.getByRole("textbox", { name: "MAC address" })).toBeDisabled(); }); it("dispatches an action to update a reserved IP", async () => { diff --git a/src/app/subnets/views/SubnetDetails/StaticDHCPLease/ReserveDHCPLease/ReserveDHCPLease.tsx b/src/app/subnets/views/SubnetDetails/StaticDHCPLease/ReserveDHCPLease/ReserveDHCPLease.tsx index feea2f8ba9..1172dc9fae 100644 --- a/src/app/subnets/views/SubnetDetails/StaticDHCPLease/ReserveDHCPLease/ReserveDHCPLease.tsx +++ b/src/app/subnets/views/SubnetDetails/StaticDHCPLease/ReserveDHCPLease/ReserveDHCPLease.tsx @@ -148,7 +148,9 @@ const ReserveDHCPLease = ({ ); }, }), - mac_address: Yup.string().matches(MAC_ADDRESS_REGEX, "Invalid MAC address"), + mac_address: Yup.string() + .required("MAC address is required") + .matches(MAC_ADDRESS_REGEX, "Invalid MAC address"), comment: Yup.string(), }); @@ -210,7 +212,17 @@ const ReserveDHCPLease = ({ name="ip_address" required /> - +