diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/HashicorpVault/HashicorpVaultEmptyPlaceholder.test.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/HashicorpVault/HashicorpVaultEmptyPlaceholder.test.tsx
new file mode 100644
index 00000000000..4214d5fda7c
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/HashicorpVault/HashicorpVaultEmptyPlaceholder.test.tsx
@@ -0,0 +1,29 @@
+import { describe, it, expect, vi } from "vitest";
+import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import HashicorpVaultEmptyPlaceholder from "./HashicorpVaultEmptyPlaceholder";
+
+describe("HashicorpVaultEmptyPlaceholder", () => {
+ it("should render the empty state message and configure button", () => {
+ render();
+ expect(screen.getByText("No Vault Configuration Found")).toBeInTheDocument();
+ expect(screen.getByRole("button", { name: /configure vault/i })).toBeInTheDocument();
+ });
+
+ it("should call onAdd when the configure button is clicked", async () => {
+ const onAdd = vi.fn();
+ const user = userEvent.setup();
+ render();
+
+ await user.click(screen.getByRole("button", { name: /configure vault/i }));
+
+ expect(onAdd).toHaveBeenCalledOnce();
+ });
+
+ it("should display the description text about Vault purpose", () => {
+ render();
+ expect(
+ screen.getByText(/Configure Hashicorp Vault to securely manage provider API keys/),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/PageVisibilitySettings.test.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/PageVisibilitySettings.test.tsx
new file mode 100644
index 00000000000..798572b2037
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/PageVisibilitySettings.test.tsx
@@ -0,0 +1,77 @@
+import { describe, it, expect, vi } from "vitest";
+import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import PageVisibilitySettings from "./PageVisibilitySettings";
+
+vi.mock("@/components/page_utils", () => ({
+ getAvailablePages: () => [
+ { page: "usage", label: "Usage", description: "View usage stats", group: "Analytics" },
+ { page: "models", label: "Models", description: "Manage models", group: "Analytics" },
+ { page: "keys", label: "API Keys", description: "Manage API keys", group: "Access" },
+ ],
+}));
+
+describe("PageVisibilitySettings", () => {
+ it("should render the not-set tag when enabledPagesInternalUsers is null", () => {
+ render(
+ ,
+ );
+ expect(screen.getByText("Not set (all pages visible)")).toBeInTheDocument();
+ });
+
+ it("should show the selected page count tag when pages are configured", () => {
+ render(
+ ,
+ );
+ expect(screen.getByText("2 pages selected")).toBeInTheDocument();
+ });
+
+ it("should show singular 'page' when exactly one page is selected", () => {
+ render(
+ ,
+ );
+ expect(screen.getByText("1 page selected")).toBeInTheDocument();
+ });
+
+ it("should call onUpdate with null when reset button is clicked", async () => {
+ const onUpdate = vi.fn();
+ const user = userEvent.setup();
+ render(
+ ,
+ );
+
+ // Expand the collapse panel first to reveal the reset button
+ await user.click(screen.getByRole("button", { name: /configure page visibility/i }));
+ await user.click(await screen.findByRole("button", { name: /reset to default/i }));
+
+ expect(onUpdate).toHaveBeenCalledWith({ enabled_ui_pages_internal_users: null });
+ });
+
+ it("should display the property description when provided", () => {
+ render(
+ ,
+ );
+ expect(screen.getByText("Controls which pages are visible")).toBeInTheDocument();
+ });
+});
diff --git a/ui/litellm-dashboard/src/components/ui/ui-loading-spinner.test.tsx b/ui/litellm-dashboard/src/components/ui/ui-loading-spinner.test.tsx
new file mode 100644
index 00000000000..73b2de54c4c
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/ui/ui-loading-spinner.test.tsx
@@ -0,0 +1,22 @@
+import { describe, it, expect } from "vitest";
+import { render, screen } from "@testing-library/react";
+import { UiLoadingSpinner } from "./ui-loading-spinner";
+
+describe("UiLoadingSpinner", () => {
+ it("should render an SVG element", () => {
+ render();
+ expect(screen.getByTestId("spinner")).toBeInTheDocument();
+ });
+
+ it("should apply custom className alongside default classes", () => {
+ render();
+ const svg = screen.getByTestId("spinner");
+ expect(svg).toHaveClass("text-red-500");
+ expect(svg).toHaveClass("animate-spin");
+ });
+
+ it("should spread additional SVG props onto the element", () => {
+ render();
+ expect(screen.getByLabelText("Loading")).toBeInTheDocument();
+ });
+});
diff --git a/ui/litellm-dashboard/src/utils/errorUtils.test.ts b/ui/litellm-dashboard/src/utils/errorUtils.test.ts
new file mode 100644
index 00000000000..ccd65717f40
--- /dev/null
+++ b/ui/litellm-dashboard/src/utils/errorUtils.test.ts
@@ -0,0 +1,40 @@
+import { describe, it, expect } from "vitest";
+import { extractErrorMessage } from "./errorUtils";
+
+describe("extractErrorMessage", () => {
+ it("should return the message from an Error instance", () => {
+ expect(extractErrorMessage(new Error("Something broke"))).toBe("Something broke");
+ });
+
+ it("should return detail when it is a string", () => {
+ expect(extractErrorMessage({ detail: "Not found" })).toBe("Not found");
+ });
+
+ it("should join msg fields from a FastAPI 422 detail array", () => {
+ const err = {
+ detail: [
+ { msg: "field required", loc: ["body", "name"], type: "value_error" },
+ { msg: "invalid type", loc: ["body", "age"], type: "type_error" },
+ ],
+ };
+ expect(extractErrorMessage(err)).toBe("field required; invalid type");
+ });
+
+ it("should extract error from nested detail object", () => {
+ expect(extractErrorMessage({ detail: { error: "bad request" } })).toBe("bad request");
+ });
+
+ it("should fall back to message property on plain objects", () => {
+ expect(extractErrorMessage({ message: "fallback msg" })).toBe("fallback msg");
+ });
+
+ it("should JSON.stringify unknown object shapes", () => {
+ expect(extractErrorMessage({ foo: "bar" })).toBe('{"foo":"bar"}');
+ });
+
+ it("should stringify primitive non-object values", () => {
+ expect(extractErrorMessage(42)).toBe("42");
+ expect(extractErrorMessage(null)).toBe("null");
+ expect(extractErrorMessage(undefined)).toBe("undefined");
+ });
+});
diff --git a/ui/litellm-dashboard/src/utils/mcpToolCrudClassification.test.ts b/ui/litellm-dashboard/src/utils/mcpToolCrudClassification.test.ts
new file mode 100644
index 00000000000..0ae8ae70bec
--- /dev/null
+++ b/ui/litellm-dashboard/src/utils/mcpToolCrudClassification.test.ts
@@ -0,0 +1,63 @@
+import { describe, it, expect } from "vitest";
+import { classifyToolOp, groupToolsByCrud } from "./mcpToolCrudClassification";
+
+describe("classifyToolOp", () => {
+ it("should classify read operations by name", () => {
+ expect(classifyToolOp("get-users")).toBe("read");
+ expect(classifyToolOp("list-items")).toBe("read");
+ expect(classifyToolOp("search documents")).toBe("read");
+ });
+
+ it("should classify delete operations by name", () => {
+ expect(classifyToolOp("delete-user")).toBe("delete");
+ expect(classifyToolOp("remove-item")).toBe("delete");
+ expect(classifyToolOp("purge-cache")).toBe("delete");
+ });
+
+ it("should classify create operations by name", () => {
+ expect(classifyToolOp("create-user")).toBe("create");
+ expect(classifyToolOp("add-item")).toBe("create");
+ expect(classifyToolOp("upload-file")).toBe("create");
+ });
+
+ it("should classify update operations by name", () => {
+ expect(classifyToolOp("update-settings")).toBe("update");
+ expect(classifyToolOp("edit-profile")).toBe("update");
+ expect(classifyToolOp("rename-file")).toBe("update");
+ });
+
+ it("should prioritize read over delete for names like get-removed-entries", () => {
+ expect(classifyToolOp("get-removed-entries")).toBe("read");
+ expect(classifyToolOp("list-deleted-items")).toBe("read");
+ });
+
+ it("should fall back to description when name is unrecognised", () => {
+ expect(classifyToolOp("mytool", "This will delete the record")).toBe("delete");
+ expect(classifyToolOp("mytool", "fetch data from the API")).toBe("read");
+ });
+
+ it("should return unknown when neither name nor description match", () => {
+ expect(classifyToolOp("my_tool")).toBe("unknown");
+ expect(classifyToolOp("my_tool", "does something")).toBe("unknown");
+ });
+});
+
+describe("groupToolsByCrud", () => {
+ it("should group tools into their CRUD categories", () => {
+ const tools = [
+ { name: "get-user", description: "" },
+ { name: "create-item", description: "" },
+ { name: "delete-record", description: "" },
+ { name: "update-settings", description: "" },
+ { name: "mysteryop", description: "" },
+ ];
+
+ const groups = groupToolsByCrud(tools);
+
+ expect(groups.read).toHaveLength(1);
+ expect(groups.create).toHaveLength(1);
+ expect(groups.delete).toHaveLength(1);
+ expect(groups.update).toHaveLength(1);
+ expect(groups.unknown).toHaveLength(1);
+ });
+});