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
/>
-
+