diff --git a/ui/litellm-dashboard/src/app/(dashboard)/teams/_components/default-team-settings/DefaultTeamSettingsForm.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/teams/_components/default-team-settings/DefaultTeamSettingsForm.test.tsx
index a80eb4fbe1e..7f9e9b4c55b 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/teams/_components/default-team-settings/DefaultTeamSettingsForm.test.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/teams/_components/default-team-settings/DefaultTeamSettingsForm.test.tsx
@@ -1,5 +1,5 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import React from "react";
import { beforeEach, describe, expect, it, vi } from "vitest";
@@ -139,13 +139,28 @@ describe("DefaultTeamSettingsForm", () => {
const { updateSettings } = renderForm();
await enterEditMode(user);
- fireEvent.change(await screen.findByLabelText("TPM Limit"), { target: { value: "12.5" } });
+ await user.clear(await screen.findByLabelText("TPM Limit"));
+ await user.type(screen.getByLabelText("TPM Limit"), "12.5");
await user.click(await saveButton());
expect(await screen.findByText("Must be a non-negative whole number")).toBeInTheDocument();
expect(updateSettings).not.toHaveBeenCalled();
});
+ it("keeps number-ish junk visible and rejects it instead of silently clearing the limit", async () => {
+ const user = userEvent.setup();
+ const { updateSettings } = renderForm();
+
+ await enterEditMode(user);
+ await user.clear(await screen.findByLabelText("TPM Limit"));
+ await user.type(screen.getByLabelText("TPM Limit"), "12e");
+ await user.click(await saveButton());
+
+ expect(screen.getByLabelText("TPM Limit")).toHaveValue("12e");
+ expect(await screen.findByText("Must be a non-negative whole number")).toBeInTheDocument();
+ expect(updateSettings).not.toHaveBeenCalled();
+ });
+
it("sends the models selection through unchanged, sentinel values included", async () => {
const user = userEvent.setup();
const { updateSettings } = renderForm();
@@ -223,7 +238,7 @@ describe("DefaultTeamSettingsForm", () => {
expect(NotificationsManager.fromBackend).toHaveBeenCalledWith("Set `'STORE_MODEL_IN_DB='True'` in your env."),
);
expect(await saveButton()).toBeEnabled();
- expect(screen.getByLabelText("Max Budget (USD)")).toHaveValue(250);
+ expect(screen.getByLabelText("Max Budget (USD)")).toHaveValue("250");
});
it("discards edits and returns to the read-only view when Cancel is pressed", async () => {
@@ -240,7 +255,7 @@ describe("DefaultTeamSettingsForm", () => {
expect(updateSettings).not.toHaveBeenCalled();
await enterEditMode(user);
- expect(screen.getByLabelText("Max Budget (USD)")).toHaveValue(100);
+ expect(screen.getByLabelText("Max Budget (USD)")).toHaveValue("100");
expect(await saveButton()).toBeDisabled();
});
});
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/teams/_components/default-team-settings/DefaultTeamSettingsForm.tsx b/ui/litellm-dashboard/src/app/(dashboard)/teams/_components/default-team-settings/DefaultTeamSettingsForm.tsx
index 56a7cc13844..43ec838dc59 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/teams/_components/default-team-settings/DefaultTeamSettingsForm.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/teams/_components/default-team-settings/DefaultTeamSettingsForm.tsx
@@ -175,7 +175,7 @@ const SettingsForm = ({ initialValues, updateSettings, onCancel, onSaved }: Sett
label="Max Budget (USD)"
description="Default maximum budget for new teams"
>
- {({ ref, ...field }) => }
+ {({ ref, ...field }) => }
- {({ ref, ...field }) => }
+ {({ ref, ...field }) => }
- {({ ref, ...field }) => }
+ {({ ref, ...field }) => }
{
expect(updateSettings).toHaveBeenCalledWith({ ...SAVED_BODY, max_budget: null });
});
+ it("keeps number-ish junk visible and rejects it instead of silently clearing the budget", async () => {
+ const user = userEvent.setup();
+ const { updateSettings } = renderForm();
+
+ await enterEditMode(user);
+ await user.clear(await screen.findByLabelText("Max Budget (USD)"));
+ await user.type(screen.getByLabelText("Max Budget (USD)"), "12e");
+ await user.click(await saveButton());
+
+ expect(screen.getByLabelText("Max Budget (USD)")).toHaveValue("12e");
+ expect(await screen.findByText("Must be a non-negative number")).toBeInTheDocument();
+ expect(updateSettings).not.toHaveBeenCalled();
+ });
+
it("sends the models selection through unchanged, sentinel values included", async () => {
const user = userEvent.setup();
const { updateSettings } = renderForm();
@@ -275,7 +289,7 @@ describe("DefaultUserSettingsForm", () => {
expect(NotificationsManager.fromBackend).toHaveBeenCalledWith("Team(s) not found: team-alhpa."),
);
expect(await saveButton()).toBeEnabled();
- expect(screen.getByLabelText("Max Budget (USD)")).toHaveValue(250);
+ expect(screen.getByLabelText("Max Budget (USD)")).toHaveValue("250");
});
it("discards edits and returns to the read-only view when Cancel is pressed", async () => {
@@ -293,7 +307,7 @@ describe("DefaultUserSettingsForm", () => {
expect(updateSettings).not.toHaveBeenCalled();
await enterEditMode(user);
- expect(screen.getByLabelText("Max Budget (USD)")).toHaveValue(100);
+ expect(screen.getByLabelText("Max Budget (USD)")).toHaveValue("100");
expect(await saveButton()).toBeDisabled();
});
});
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/default-user-settings/DefaultUserSettingsForm.tsx b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/default-user-settings/DefaultUserSettingsForm.tsx
index 14520b71b31..c2fbcdb1112 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/default-user-settings/DefaultUserSettingsForm.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/default-user-settings/DefaultUserSettingsForm.tsx
@@ -124,7 +124,7 @@ const TeamsField = ({ control }: { control: SettingsControl }) => {
{({ ref, ...budgetField }) => (
-
+
)}
@@ -244,7 +244,7 @@ const SettingsForm = ({ initialValues, roleOptions, updateSettings, onCancel, on
const onSubmit = form.handleSubmit((values) => mutation.mutate(values));
return (
-