diff --git a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/DefaultUserSettings.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/DefaultUserSettings.test.tsx
index 06dafcfcffd..6020d0b3ba3 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/DefaultUserSettings.test.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/DefaultUserSettings.test.tsx
@@ -150,4 +150,111 @@ describe("DefaultUserSettings", () => {
expect(screen.getByText("Edit Settings")).toBeInTheDocument();
});
+
+ describe("editable fields", () => {
+ const teamsOnlySettings = {
+ values: {
+ teams: [],
+ },
+ field_schema: {
+ description: "Default user settings",
+ properties: {
+ teams: {
+ type: "array",
+ description: "Teams",
+ },
+ },
+ },
+ };
+
+ const enterEditMode = async () => {
+ mockGetInternalUserSettings.mockResolvedValue(teamsOnlySettings);
+ mockUpdateInternalUserSettings.mockResolvedValue({ settings: {} });
+
+ render();
+
+ await waitFor(() => {
+ expect(screen.getByText("Edit Settings")).toBeInTheDocument();
+ });
+
+ act(() => {
+ fireEvent.click(screen.getByText("Edit Settings"));
+ });
+ };
+
+ const savedPayload = () => mockUpdateInternalUserSettings.mock.calls[0][1] as Record;
+
+ const selectUserRole = async (optionText: string) => {
+ act(() => {
+ fireEvent.mouseDown(document.querySelector(".ant-select-selector")!);
+ });
+
+ await waitFor(() => {
+ expect(document.querySelectorAll(".ant-select-item-option").length).toBeGreaterThan(0);
+ });
+
+ const option = Array.from(document.querySelectorAll(".ant-select-item-option")).find((el) =>
+ el.textContent?.includes(optionText),
+ );
+ expect(option).toBeTruthy();
+
+ act(() => {
+ fireEvent.click(option!);
+ });
+ };
+
+ it("keeps the stored role and max budget of a team saved without an ID", async () => {
+ mockGetInternalUserSettings.mockResolvedValue({
+ ...teamsOnlySettings,
+ values: { teams: [{ team_id: "", max_budget_in_team: 25, user_role: "admin" }] },
+ });
+ mockUpdateInternalUserSettings.mockResolvedValue({ settings: {} });
+
+ render();
+
+ await waitFor(() => {
+ expect(screen.getByText("Edit Settings")).toBeInTheDocument();
+ });
+ act(() => {
+ fireEvent.click(screen.getByText("Edit Settings"));
+ });
+
+ expect(screen.getByPlaceholderText("Enter team ID")).toHaveValue("");
+ expect(screen.getByPlaceholderText("Optional")).toHaveValue("25.00");
+ expect(document.querySelector(".ant-select-selection-item")).toHaveTextContent("Admin");
+ });
+
+ it("keeps showing the selected role of a team whose ID has not been typed yet", async () => {
+ await enterEditMode();
+
+ act(() => {
+ fireEvent.click(screen.getByText("Add Team"));
+ });
+ await selectUserRole("Admin");
+
+ expect(document.querySelector(".ant-select-selection-item")).toHaveTextContent("Admin");
+ });
+
+ it("keeps the role and max budget of a team whose ID has not been typed yet", async () => {
+ await enterEditMode();
+
+ act(() => {
+ fireEvent.click(screen.getByText("Add Team"));
+ });
+
+ act(() => {
+ fireEvent.change(screen.getByPlaceholderText("Optional"), { target: { value: "25" } });
+ });
+ await selectUserRole("Admin");
+
+ act(() => {
+ fireEvent.click(screen.getByText("Save Changes"));
+ });
+
+ await waitFor(() => {
+ expect(mockUpdateInternalUserSettings).toHaveBeenCalled();
+ });
+ expect(savedPayload().teams).toEqual([{ team_id: "", max_budget_in_team: 25, user_role: "admin" }]);
+ });
+ });
});
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/DefaultUserSettings.tsx b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/DefaultUserSettings.tsx
index 7fee2e14b27..b14dadefe80 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/users/_components/DefaultUserSettings.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/users/_components/DefaultUserSettings.tsx
@@ -115,7 +115,7 @@ const DefaultUserSettings: React.FC = ({
team_id: team,
user_role: "user" as const,
};
- } else if (typeof team === "object" && team.team_id) {
+ } else if (typeof team === "object" && team !== null && "team_id" in team) {
return {
team_id: team.team_id,
max_budget_in_team: team.max_budget_in_team,