diff --git a/ui/litellm-dashboard/src/components/add_model/AddModelForm.test.tsx b/ui/litellm-dashboard/src/components/add_model/AddModelForm.test.tsx
new file mode 100644
index 00000000000..6f63fcfa549
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/add_model/AddModelForm.test.tsx
@@ -0,0 +1,276 @@
+import { renderHook, screen, waitFor, renderWithProviders } from "../../../tests/test-utils";
+import userEvent from "@testing-library/user-event";
+import { Form } from "antd";
+import type { UploadProps } from "antd/es/upload";
+import { describe, expect, it, vi } from "vitest";
+import type { Team } from "../key_team_helpers/key_list";
+import type { CredentialItem } from "../networking";
+import { Providers } from "../provider_info_helpers";
+import AddModelForm from "./AddModelForm";
+
+vi.mock("../molecules/models/ProviderLogo", () => ({
+ ProviderLogo: ({ provider, className }: { provider: string; className?: string }) => (
+
+ {provider}
+
+ ),
+}));
+
+vi.mock("../networking", async () => {
+ const actual = await vi.importActual("../networking");
+ return {
+ ...actual,
+ getGuardrailsList: vi.fn().mockResolvedValue({
+ guardrails: [{ guardrail_name: "test-guardrail-1" }, { guardrail_name: "test-guardrail-2" }],
+ }),
+ tagListCall: vi.fn().mockResolvedValue({}),
+ modelAvailableCall: vi.fn().mockResolvedValue({
+ data: [{ id: "model-group-1" }, { id: "model-group-2" }],
+ }),
+ modelHubCall: vi.fn().mockResolvedValue({
+ data: [
+ { model_group: "gpt-4", mode: "chat" },
+ { model_group: "gpt-3.5-turbo", mode: "chat" },
+ ],
+ }),
+ getProviderCreateMetadata: vi.fn().mockResolvedValue([
+ {
+ provider: "OpenAI",
+ provider_display_name: "OpenAI",
+ litellm_provider: "openai",
+ default_model_placeholder: "gpt-3.5-turbo",
+ credential_fields: [],
+ },
+ ]),
+ };
+});
+
+vi.mock("@/app/(dashboard)/hooks/providers/useProviderFields", () => ({
+ useProviderFields: vi.fn().mockReturnValue({
+ data: [
+ {
+ provider: "OpenAI",
+ provider_display_name: "OpenAI",
+ litellm_provider: "openai",
+ default_model_placeholder: "gpt-3.5-turbo",
+ credential_fields: [],
+ },
+ ],
+ isLoading: false,
+ error: null,
+ }),
+}));
+
+vi.mock("@/app/(dashboard)/hooks/useAuthorized", () => ({
+ default: vi.fn(),
+}));
+
+vi.mock("@/app/(dashboard)/hooks/guardrails/useGuardrails", () => ({
+ useGuardrails: vi.fn().mockReturnValue({
+ data: [{ guardrail_name: "test-guardrail" }],
+ isLoading: false,
+ error: null,
+ }),
+}));
+
+vi.mock("@/app/(dashboard)/hooks/tags/useTags", () => ({
+ useTags: vi.fn().mockReturnValue({
+ data: { tag1: ["model1", "model2"] },
+ isLoading: false,
+ error: null,
+ }),
+}));
+
+const mockAuthorizedUser = (userRole: string, userId: string, premiumUser: boolean) => ({
+ token: "test-token",
+ accessToken: "test-access-token",
+ userId,
+ userEmail: "test@example.com",
+ userRole,
+ premiumUser,
+ disabledPersonalKeyCreation: false,
+ showSSOBanner: false,
+});
+
+const testTeam: Team = {
+ team_id: "team-1",
+ team_alias: "Test Team",
+ models: ["gpt-4"],
+ max_budget: 100,
+ budget_duration: "monthly",
+ tpm_limit: null,
+ rpm_limit: null,
+ organization_id: "org-1",
+ created_at: "2024-01-01T00:00:00Z",
+ keys: [],
+ members_with_roles: [],
+};
+
+const createTestProps = (userRole = "proxy_admin", userId = "user-1", isTeamAdmin = false) => {
+ const { result } = renderHook(() => Form.useForm());
+ const [form] = result.current;
+
+ const teams = [
+ {
+ ...testTeam,
+ members_with_roles: isTeamAdmin ? [{ user_id: userId, role: "admin" }] : [],
+ },
+ ];
+
+ const credentials: CredentialItem[] = [
+ {
+ credential_name: "test-credential",
+ credential_values: {},
+ credential_info: {
+ custom_llm_provider: "openai",
+ description: "Test credential",
+ },
+ },
+ ];
+
+ const uploadProps: UploadProps = {
+ beforeUpload: () => false,
+ showUploadList: false,
+ };
+
+ return {
+ form,
+ handleOk: vi.fn(),
+ setSelectedProvider: vi.fn(),
+ setProviderModelsFn: vi.fn(),
+ getPlaceholder: vi.fn((provider: Providers) => `Enter ${provider} model name`),
+ setShowAdvancedSettings: vi.fn(),
+ selectedProvider: Providers.OpenAI,
+ providerModels: ["gpt-4", "gpt-3.5-turbo"],
+ showAdvancedSettings: false,
+ teams,
+ credentials,
+ uploadProps,
+ userRole,
+ userId,
+ };
+};
+
+describe("AddModelForm", () => {
+ it("should render", async () => {
+ const mockUseAuthorized = vi.mocked(await import("@/app/(dashboard)/hooks/useAuthorized"));
+ mockUseAuthorized.default.mockReturnValue(mockAuthorizedUser("proxy_admin", "user-1", true));
+
+ const props = createTestProps();
+
+ renderWithProviders();
+
+ expect(await screen.findByRole("heading", { name: "Add Model" })).toBeInTheDocument();
+ });
+
+ it("should show proxy admin only (not team admin) - should not see Select Team dropdown unless switch is toggled", async () => {
+ const mockUseAuthorized = vi.mocked(await import("@/app/(dashboard)/hooks/useAuthorized"));
+ mockUseAuthorized.default.mockReturnValue(mockAuthorizedUser("proxy_admin", "user-1", true));
+
+ const props = createTestProps("proxy_admin", "user-1", false);
+
+ renderWithProviders();
+
+ await screen.findByText("Provider");
+
+ expect(screen.queryByText("Team Selection Required")).not.toBeInTheDocument();
+ expect(screen.queryByText("Select Team")).not.toBeInTheDocument();
+
+ const teamSwitch = screen.getByRole("switch");
+ expect(teamSwitch).toBeInTheDocument();
+
+ expect(screen.queryByText("Select Team")).not.toBeInTheDocument();
+
+ await userEvent.click(teamSwitch);
+
+ expect(await screen.findByText("Select Team")).toBeInTheDocument();
+ });
+
+ it("should show proxy admin who is also team admin - should not see Select Team dropdown unless switch is toggled", async () => {
+ const mockUseAuthorized = vi.mocked(await import("@/app/(dashboard)/hooks/useAuthorized"));
+ mockUseAuthorized.default.mockReturnValue(mockAuthorizedUser("proxy_admin", "user-1", true));
+
+ const props = createTestProps("proxy_admin", "user-1", true);
+
+ renderWithProviders();
+
+ await screen.findByText("Provider");
+
+ expect(screen.queryByText("Team Selection Required")).not.toBeInTheDocument();
+ expect(screen.queryByText("Select Team")).not.toBeInTheDocument();
+
+ const teamSwitch = screen.getByRole("switch");
+ expect(teamSwitch).toBeInTheDocument();
+
+ expect(screen.queryByText("Select Team")).not.toBeInTheDocument();
+
+ await userEvent.click(teamSwitch);
+
+ expect(await screen.findByText("Select Team")).toBeInTheDocument();
+ });
+
+ it("should show team admin (not proxy admin) - should see alert and team select, must select team before seeing remaining fields", async () => {
+ const mockUseAuthorized = vi.mocked(await import("@/app/(dashboard)/hooks/useAuthorized"));
+ mockUseAuthorized.default.mockReturnValue(mockAuthorizedUser("team_member", "user-1", true));
+
+ const props = createTestProps("team_member", "user-1", true);
+
+ renderWithProviders();
+
+ await screen.findByRole("heading", { name: "Add Model" });
+
+ expect(screen.getByText("Team Selection Required")).toBeInTheDocument();
+
+ expect(screen.getByText("Select Team")).toBeInTheDocument();
+
+ expect(screen.queryByText("Provider")).not.toBeInTheDocument();
+
+ const teamSelect = screen.getByRole("combobox");
+ await userEvent.click(teamSelect);
+ await userEvent.click(screen.getByText("Test Team"));
+
+ await waitFor(() => {
+ expect(screen.getByText("Provider")).toBeInTheDocument();
+ });
+ });
+
+ it("should show team admin (not proxy admin) - should not see team-BYOK switch", async () => {
+ const mockUseAuthorized = vi.mocked(await import("@/app/(dashboard)/hooks/useAuthorized"));
+ mockUseAuthorized.default.mockReturnValue(mockAuthorizedUser("team_member", "user-1", true));
+
+ const props = createTestProps("team_member", "user-1", true);
+
+ renderWithProviders();
+
+ await screen.findByText("Select Team");
+
+ const teamSelect = screen.getByRole("combobox");
+ await userEvent.click(teamSelect);
+ await userEvent.click(screen.getByText("Test Team"));
+
+ await waitFor(() => {
+ expect(screen.getByText("Provider")).toBeInTheDocument();
+ });
+
+ expect(screen.queryByRole("switch")).not.toBeInTheDocument();
+ });
+
+ it("should handle non-admin, non-team-admin users - should not see team selection or switch", async () => {
+ const mockUseAuthorized = vi.mocked(await import("@/app/(dashboard)/hooks/useAuthorized"));
+ mockUseAuthorized.default.mockReturnValue(mockAuthorizedUser("user", "user-1", false));
+
+ const props = createTestProps("user", "user-1", false);
+
+ renderWithProviders();
+
+ await screen.findByRole("heading", { name: "Add Model" });
+
+ expect(screen.queryByText("Team Selection Required")).not.toBeInTheDocument();
+
+ expect(screen.queryByText("Select Team")).not.toBeInTheDocument();
+
+ expect(screen.queryByText("Provider")).not.toBeInTheDocument();
+
+ expect(screen.queryByRole("switch")).not.toBeInTheDocument();
+ });
+});