diff --git a/ui/litellm-dashboard/eslint-suppressions.json b/ui/litellm-dashboard/eslint-suppressions.json
index faaf3481a0b..9a666e504f0 100644
--- a/ui/litellm-dashboard/eslint-suppressions.json
+++ b/ui/litellm-dashboard/eslint-suppressions.json
@@ -4,11 +4,6 @@
"count": 1
}
},
- "src/app/(dashboard)/access-groups/_components/AccessGroupsDetailsPage.tsx": {
- "no-restricted-imports": {
- "count": 1
- }
- },
"src/app/(dashboard)/access-groups/_components/AccessGroupsModal/AccessGroupBaseForm.tsx": {
"no-restricted-imports": {
"count": 2
@@ -24,11 +19,6 @@
"count": 1
}
},
- "src/app/(dashboard)/access-groups/_components/AccessGroupsPage.tsx": {
- "no-restricted-imports": {
- "count": 1
- }
- },
"src/app/(dashboard)/admin-panel/_components/AdminPanel.tsx": {
"no-restricted-imports": {
"count": 2
@@ -2035,11 +2025,6 @@
"count": 1
}
},
- "src/app/(dashboard)/vector-stores/_components/TestVectorStoreTab.tsx": {
- "no-restricted-imports": {
- "count": 1
- }
- },
"src/app/(dashboard)/vector-stores/_components/VectorStoreForm.tsx": {
"no-nested-ternary": {
"count": 2
@@ -2051,18 +2036,10 @@
"count": 1
}
},
- "src/app/(dashboard)/vector-stores/_components/VectorStoreTester.tsx": {
- "no-restricted-imports": {
- "count": 1
- }
- },
"src/app/(dashboard)/vector-stores/_components/index.tsx": {
"local/filename-pascal-case": {
"count": 1
},
- "no-restricted-imports": {
- "count": 1
- },
"react-hooks/set-state-in-effect": {
"count": 1
}
@@ -2998,23 +2975,10 @@
}
},
"src/components/common_components/Filters/FilterInput.tsx": {
- "no-restricted-imports": {
- "count": 1
- },
"react-hooks/set-state-in-effect": {
"count": 1
}
},
- "src/components/common_components/Filters/FiltersButton.tsx": {
- "no-restricted-imports": {
- "count": 1
- }
- },
- "src/components/common_components/Filters/ResetFiltersButton.tsx": {
- "no-restricted-imports": {
- "count": 1
- }
- },
"src/components/common_components/IconActionButton/BaseActionButton.tsx": {
"no-restricted-imports": {
"count": 1
@@ -3576,7 +3540,7 @@
"count": 1
},
"no-restricted-imports": {
- "count": 3
+ "count": 1
}
},
"src/components/page_utils.test.ts": {
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsDetailsPage.tsx b/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsDetailsPage.tsx
index 72a89093bdb..9476a8d98af 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsDetailsPage.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsDetailsPage.tsx
@@ -1,68 +1,63 @@
import { useAccessGroupDetails } from "@/app/(dashboard)/hooks/accessGroups/useAccessGroupDetails";
-import {
- Button,
- Card,
- Col,
- Descriptions,
- Empty,
- Flex,
- Layout,
- List,
- Row,
- Spin,
- Tabs,
- Tag,
- theme,
- Typography,
-} from "antd";
import { ArrowLeftIcon, BotIcon, EditIcon, KeyIcon, LayersIcon, ServerIcon, UsersIcon } from "lucide-react";
import { useState } from "react";
import DefaultProxyAdminTag from "@/components/common_components/DefaultProxyAdminTag";
+import CopyButton from "@/components/shared/CopyButton";
+import { Badge } from "@/components/ui/badge";
+import { Button } from "@/components/ui/button";
+import { Card, CardAction, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
+import { UiLoadingSpinner } from "@/components/ui/ui-loading-spinner";
import { AccessGroupEditModal } from "./AccessGroupsModal/AccessGroupEditModal";
-const { Title, Text } = Typography;
-const { Content } = Layout;
-
interface AccessGroupDetailProps {
accessGroupId: string;
onBack: () => void;
}
+const MAX_PREVIEW = 5;
+
+function ResourceList({ ids, emptyMessage }: { ids: string[]; emptyMessage: string }) {
+ if (ids.length === 0) {
+ return
{emptyMessage}
;
+ }
+ return (
+
+ {ids.map((id) => (
+
+
+ {id}
+
+
+ ))}
+
+ );
+}
+
export function AccessGroupDetail({ accessGroupId, onBack }: AccessGroupDetailProps) {
const { data: accessGroup, isLoading } = useAccessGroupDetails(accessGroupId);
- const { token } = theme.useToken();
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
const [showAllKeys, setShowAllKeys] = useState(false);
const [showAllTeams, setShowAllTeams] = useState(false);
- const MAX_PREVIEW = 5;
-
if (isLoading) {
return (
-
-
-
-
-
+
);
}
if (!accessGroup) {
return (
-
- } onClick={onBack} type="text" style={{ marginBottom: 16 }} />
-
-
+
+
+
Access group not found
+
);
}
@@ -75,224 +70,159 @@ export function AccessGroupDetail({ accessGroupId, onBack }: AccessGroupDetailPr
const displayedKeys = showAllKeys ? keyIds : keyIds.slice(0, MAX_PREVIEW);
const displayedTeams = showAllTeams ? teamIds : teamIds.slice(0, MAX_PREVIEW);
- const handleEdit = () => {
- setIsEditModalVisible(true);
- };
-
- const tabItems = [
- {
- key: "models",
- label: (
-
-
- Models
- {modelIds?.length}
-
- ),
- children:
- modelIds?.length > 0 ? (
- (
-
-
- {id}
-
-
- )}
- />
- ) : (
-
- ),
- },
- {
- key: "mcp",
- label: (
-
-
- MCP Servers
- {mcpServerIds?.length}
-
- ),
- children:
- mcpServerIds?.length > 0 ? (
- (
-
-
- {id}
-
-
- )}
- />
- ) : (
-
- ),
- },
- {
- key: "agents",
- label: (
-
-
- Agents
- {agentIds?.length}
-
- ),
- children:
- agentIds?.length > 0 ? (
- (
-
-
- {id}
-
-
- )}
- />
- ) : (
-
- ),
- },
- ];
-
return (
-
- {/* Header */}
-
-
-
} onClick={onBack} type="text" />
+
+
+
+
-
- {accessGroup.access_group_name}
-
-
- ID: {accessGroup.access_group_id}
-
+
{accessGroup.access_group_name}
+
+ ID: {accessGroup.access_group_id}
+
+
-
} onClick={handleEdit}>
+
- {/* Group Details */}
-
-
-
- {accessGroup.description || "—"}
-
+
+
+ Group Details
+
+
+
+ - Description
+ - {accessGroup.description || "—"}
+ - Created
+ -
{new Date(accessGroup.created_at).toLocaleString()}
{accessGroup.created_by && (
-
- {"by"}
+ <>
+ by
-
+ >
)}
-
-
+
+ Last Updated
+
{new Date(accessGroup.updated_at).toLocaleString()}
{accessGroup.updated_by && (
-
- {"by"}
+ <>
+ by
-
+ >
)}
-
-
-
-
-
- {/* Attached Keys & Teams */}
-
-
-
-
- Attached Keys
- {keyIds?.length}
-
- }
- extra={
- keyIds?.length > MAX_PREVIEW ? (
-
- ) : null
- }
- >
- {keyIds?.length > 0 ? (
-
- {displayedKeys.map((id) => (
-
-
- {id.length > 20 ? `${id.slice(0, 10)}...${id.slice(-6)}` : id}
-
-
- ))}
-
- ) : (
-
- )}
-
-
-
-
-
- Attached Teams
- {teamIds?.length}
-
- }
- extra={
- teamIds?.length > MAX_PREVIEW ? (
-
- ) : null
- }
- >
- {teamIds?.length > 0 ? (
-
- {displayedTeams.map((id) => (
-
-
- {id}
-
-
- ))}
-
- ) : (
-
- )}
-
-
-
-
- {/* Resources Tabs */}
-
-
+
+
+
+
+
+
+
+
+
+
+ Attached Keys
+ {keyIds.length}
+
+ {keyIds.length > MAX_PREVIEW && (
+
+
+
+ )}
+
+
+ {keyIds.length > 0 ? (
+
+ {displayedKeys.map((id) => (
+
+ {id.length > 20 ? `${id.slice(0, 10)}...${id.slice(-6)}` : id}
+
+ ))}
+
+ ) : (
+ No keys attached
+ )}
+
+
+
+
+
+
+
+ Attached Teams
+ {teamIds.length}
+
+ {teamIds.length > MAX_PREVIEW && (
+
+
+
+ )}
+
+
+ {teamIds.length > 0 ? (
+
+ {displayedTeams.map((id) => (
+
+ {id}
+
+ ))}
+
+ ) : (
+ No teams attached
+ )}
+
+
+
+
+
+
+
+
+
+
+ Models
+ {modelIds.length}
+
+
+
+ MCP Servers
+ {mcpServerIds.length}
+
+
+
+ Agents
+ {agentIds.length}
+
+
+
+
+
+
+
+
+
+
+
+
+
- {/* Edit Modal */}
setIsEditModalVisible(false)}
/>
-
+
);
}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.tsx b/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.tsx
index 0de6596f57c..f37acb3d85a 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/access-groups/_components/AccessGroupsPage.tsx
@@ -1,10 +1,11 @@
import { AccessGroupResponse, useAccessGroups } from "@/app/(dashboard)/hooks/accessGroups/useAccessGroups";
import { useDeleteAccessGroup } from "@/app/(dashboard)/hooks/accessGroups/useDeleteAccessGroup";
-import { PlusOutlined } from "@ant-design/icons";
-import { Button, Flex, Input, Layout, Space, theme, Typography } from "antd";
-import { SearchIcon } from "lucide-react";
+import { Plus, SearchIcon, X } from "lucide-react";
import { useMemo, useState } from "react";
import DeleteResourceModal from "@/components/common_components/DeleteResourceModal";
+import { PageHeader } from "@/components/shared/PageHeader";
+import { Button } from "@/components/ui/button";
+import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "@/components/ui/input-group";
import { AccessGroupDetail } from "./AccessGroupsDetailsPage";
import { AccessGroupCreateModal } from "./AccessGroupsModal/AccessGroupCreateModal";
import { AccessGroupsTable } from "./AccessGroupsTable";
@@ -12,9 +13,6 @@ import { AccessGroup } from "./types";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import { isProxyAdminRole } from "@/utils/roles";
-const { Title, Text } = Typography;
-const { Content } = Layout;
-
function mapResponseToAccessGroup(r: AccessGroupResponse): AccessGroup {
return {
id: r.access_group_id,
@@ -33,7 +31,6 @@ function mapResponseToAccessGroup(r: AccessGroupResponse): AccessGroup {
}
export function AccessGroupsPage() {
- const { token } = theme.useToken();
const { userRole } = useAuthorized();
// Admin Viewer follows the read-parity rule: see access groups, no writes.
const canModify = isProxyAdminRole(userRole ?? "");
@@ -62,31 +59,41 @@ export function AccessGroupsPage() {
}
return (
-
-
-
-
- Access Groups
-
- Manage resource permissions for your organization
-
- {canModify && (
- } onClick={() => setIsCreateModalVisible(true)}>
- Create Access Group
-
- )}
-
-
-
- }
- placeholder="Search groups by name, ID, or description..."
- style={{ maxWidth: 400 }}
- value={searchText}
- onChange={(e) => setSearchText(e.target.value)}
- allowClear
+
+
+
setIsCreateModalVisible(true)}>
+
+ Create Access Group
+
+ ) : undefined
+ }
/>
-
+
+
+
+
+
+
+
+ setSearchText(e.target.value)}
+ />
+ {searchText && (
+
+ setSearchText("")}>
+
+
+
+ )}
+
+
-
+
);
}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/organizations/OrganizationFilters.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/organizations/OrganizationFilters.test.tsx
index 37eeaf4c2af..c1eda1be670 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/organizations/OrganizationFilters.test.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/organizations/OrganizationFilters.test.tsx
@@ -106,7 +106,7 @@ describe("OrganizationFilters", () => {
org_alias: "test org",
};
- render(
+ const { container } = render(
{
/>,
);
- const filtersButton = screen.getByRole("button", { name: /^filters$/i });
- const badgeWrapper = filtersButton.closest(".ant-badge");
- expect(badgeWrapper).toBeInTheDocument();
+ expect(screen.getByRole("button", { name: /^filters$/i })).toBeInTheDocument();
+ expect(container.querySelector("sup")).toBeInTheDocument();
});
});
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/TestVectorStoreTab.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/TestVectorStoreTab.test.tsx
index c1322dced60..1d7bce34e04 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/TestVectorStoreTab.test.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/TestVectorStoreTab.test.tsx
@@ -1,4 +1,5 @@
-import { render, screen, fireEvent } from "@testing-library/react";
+import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
import { describe, it, expect, vi } from "vitest";
import TestVectorStoreTab from "./TestVectorStoreTab";
import { VectorStore } from "@/components/vector_store_management/types";
@@ -60,31 +61,24 @@ describe("TestVectorStoreTab", () => {
expect(screen.getByTestId("tester-access-token")).toHaveTextContent("test-token");
});
- it("should update VectorStoreTester when selecting different vector store", () => {
+ it("should update VectorStoreTester when selecting different vector store", async () => {
+ const user = userEvent.setup();
render();
- // Find the select component
- const selectElement = screen.getByRole("combobox");
+ await user.click(screen.getByRole("combobox"));
+ await user.click(await screen.findByText("Test Store 2"));
- // Change selection
- fireEvent.mouseDown(selectElement);
-
- // Wait for options to appear and click the second one
- const option2 = screen.getByText("Test Store 2");
- fireEvent.click(option2);
-
- // Verify the tester component updated
expect(screen.getByTestId("tester-vector-store-id")).toHaveTextContent("vs_456");
});
- it("should display vector store names in select options", () => {
+ it("should display vector store names in select options", async () => {
+ const user = userEvent.setup();
render();
- const selectElement = screen.getByRole("combobox");
- fireEvent.mouseDown(selectElement);
+ await user.click(screen.getByRole("combobox"));
- // Use getAllByText since the selected value also shows the name
- expect(screen.getAllByText("Test Store 1").length).toBeGreaterThan(0);
+ // The selected store's name may also render in the trigger, so only require at least one match.
+ expect((await screen.findAllByText("Test Store 1")).length).toBeGreaterThan(0);
expect(screen.getByText("Test Store 2")).toBeInTheDocument();
});
});
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/TestVectorStoreTab.tsx b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/TestVectorStoreTab.tsx
index 3156da0b413..fec2dc62e9c 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/TestVectorStoreTab.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/TestVectorStoreTab.tsx
@@ -1,24 +1,32 @@
import React, { useState } from "react";
-import { Card, Select, Typography } from "antd";
+import { Card, CardContent } from "@/components/ui/card";
+import {
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+} from "@/components/ui/combobox";
import { VectorStoreTester } from "./VectorStoreTester";
import { VectorStore } from "@/components/vector_store_management/types";
-const { Text, Title } = Typography;
-
interface TestVectorStoreTabProps {
accessToken: string | null;
vectorStores: VectorStore[];
}
+const storeLabel = (store: VectorStore) => store.vector_store_name || store.vector_store_id;
+
const TestVectorStoreTab: React.FC = ({ accessToken, vectorStores }) => {
- const [selectedVectorStoreId, setSelectedVectorStoreId] = useState(
- vectorStores.length > 0 ? vectorStores[0].vector_store_id : undefined,
- );
+ const [selectedVectorStore, setSelectedVectorStore] = useState(vectorStores[0] ?? null);
if (!accessToken) {
return (
- Access token is required to test vector stores.
+
+ Access token is required to test vector stores.
+
);
}
@@ -26,9 +34,11 @@ const TestVectorStoreTab: React.FC = ({ accessToken, ve
if (vectorStores.length === 0) {
return (
-
- No vector stores available. Create one first to test it.
-
+
+
+
No vector stores available. Create one first to test it.
+
+
);
}
@@ -36,36 +46,41 @@ const TestVectorStoreTab: React.FC = ({ accessToken, ve
return (
-
+
-
Select Vector Store
-
Choose a vector store to test search queries against
+
Select Vector Store
+
Choose a vector store to test search queries against
-
-
+
+
+ No matching vector stores
+
+ {(store: VectorStore) => (
+
+
+ {storeLabel(store)}
+ {store.vector_store_name && (
+ {store.vector_store_id}
+ )}
+
+
+ )}
+
+
+
+
- {selectedVectorStoreId &&
}
+ {selectedVectorStore && (
+
+ )}
);
};
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/VectorStoreTester.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/VectorStoreTester.test.tsx
new file mode 100644
index 00000000000..cbabcc6dca5
--- /dev/null
+++ b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/VectorStoreTester.test.tsx
@@ -0,0 +1,156 @@
+import { render, screen, waitFor } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { beforeEach, describe, expect, it, vi } from "vitest";
+
+import { vectorStoreSearchCall } from "@/components/networking";
+
+import { VectorStoreTester } from "./VectorStoreTester";
+
+vi.mock("@/components/networking", () => ({
+ vectorStoreSearchCall: vi.fn(),
+}));
+
+const mockWarning = vi.fn();
+vi.mock("@/components/molecules/message_manager", () => ({
+ __esModule: true,
+ default: { warning: (...args: unknown[]) => mockWarning(...args) },
+}));
+
+const mockFromBackend = vi.fn();
+const mockSuccess = vi.fn();
+vi.mock("@/components/molecules/notifications_manager", () => ({
+ __esModule: true,
+ default: {
+ fromBackend: (...args: unknown[]) => mockFromBackend(...args),
+ success: (...args: unknown[]) => mockSuccess(...args),
+ },
+}));
+
+const mockSearch = vi.mocked(vectorStoreSearchCall);
+
+const searchResponse = {
+ object: "vector_store.search_results.page",
+ search_query: "hello",
+ data: [
+ {
+ score: 0.91234,
+ content: [{ text: "the quick brown fox", type: "text" }],
+ file_id: "file-1",
+ filename: "notes.txt",
+ attributes: { source: "manual" },
+ },
+ ],
+};
+
+const EMPTY_STATE = "Test your vector store by entering a search query below";
+
+const renderTester = () => render();
+
+const queryInput = () => screen.getByPlaceholderText(/enter your search query/i);
+const searchButton = () => screen.getByRole("button", { name: /search/i });
+
+describe("VectorStoreTester", () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ mockSearch.mockResolvedValue(searchResponse);
+ });
+
+ it("shows the empty state before any search has run", () => {
+ renderTester();
+ expect(screen.getByText(EMPTY_STATE)).toBeInTheDocument();
+ expect(screen.queryByRole("button", { name: /clear history/i })).not.toBeInTheDocument();
+ });
+
+ it("does not search until a non-blank query is entered", async () => {
+ const user = userEvent.setup();
+ renderTester();
+
+ await user.click(searchButton());
+ expect(mockSearch).not.toHaveBeenCalled();
+
+ await user.type(queryInput(), "hello");
+ await user.click(searchButton());
+
+ await waitFor(() => expect(mockSearch).toHaveBeenCalledWith("sk-test", "vs_123", "hello"));
+ });
+
+ it("renders the returned result and clears the query input", async () => {
+ const user = userEvent.setup();
+ renderTester();
+
+ await user.type(queryInput(), "hello");
+ await user.click(searchButton());
+
+ expect(await screen.findByText("Result 1")).toBeInTheDocument();
+ expect(screen.getByText("1 results")).toBeInTheDocument();
+ expect(screen.getByText("Score: 0.9123")).toBeInTheDocument();
+ expect(screen.queryByText(EMPTY_STATE)).not.toBeInTheDocument();
+ await waitFor(() => expect(queryInput()).toHaveValue(""));
+ });
+
+ it("expands a result to reveal its content and metadata", async () => {
+ const user = userEvent.setup();
+ renderTester();
+
+ await user.type(queryInput(), "hello");
+ await user.click(searchButton());
+
+ expect(await screen.findByText("Result 1")).toBeInTheDocument();
+ expect(screen.queryByText("the quick brown fox")).not.toBeInTheDocument();
+
+ await user.click(screen.getByText("Result 1"));
+
+ expect(screen.getByText("the quick brown fox")).toBeInTheDocument();
+ expect(screen.getByText("File ID:").parentElement).toHaveTextContent("file-1");
+ expect(screen.getByText("Filename:").parentElement).toHaveTextContent("notes.txt");
+ });
+
+ it("warns instead of searching when the query is only whitespace", async () => {
+ const user = userEvent.setup();
+ renderTester();
+
+ await user.type(queryInput(), " ");
+ await user.type(queryInput(), "{Enter}");
+
+ expect(mockWarning).toHaveBeenCalledWith("Please enter a search query");
+ expect(mockSearch).not.toHaveBeenCalled();
+ });
+
+ it("submits on Enter but not on Shift+Enter", async () => {
+ const user = userEvent.setup();
+ renderTester();
+
+ await user.type(queryInput(), "hello");
+ await user.type(queryInput(), "{Shift>}{Enter}{/Shift}");
+ expect(mockSearch).not.toHaveBeenCalled();
+
+ await user.type(queryInput(), "{Enter}");
+ await waitFor(() => expect(mockSearch).toHaveBeenCalledTimes(1));
+ });
+
+ it("reports a failed search and keeps the history empty", async () => {
+ const user = userEvent.setup();
+ mockSearch.mockRejectedValue(new Error("boom"));
+ renderTester();
+
+ await user.type(queryInput(), "hello");
+ await user.click(searchButton());
+
+ await waitFor(() => expect(mockFromBackend).toHaveBeenCalledWith("Failed to search vector store"));
+ expect(screen.getByText(EMPTY_STATE)).toBeInTheDocument();
+ });
+
+ it("clears the search history", async () => {
+ const user = userEvent.setup();
+ renderTester();
+
+ await user.type(queryInput(), "hello");
+ await user.click(searchButton());
+ expect(await screen.findByText("Result 1")).toBeInTheDocument();
+
+ await user.click(screen.getByRole("button", { name: /clear history/i }));
+
+ expect(screen.queryByText("Result 1")).not.toBeInTheDocument();
+ expect(screen.getByText(EMPTY_STATE)).toBeInTheDocument();
+ });
+});
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/VectorStoreTester.tsx b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/VectorStoreTester.tsx
index fa4587b526c..015d58e8649 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/VectorStoreTester.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/vector-stores/_components/VectorStoreTester.tsx
@@ -1,12 +1,13 @@
import React, { useState } from "react";
-import { Button, Input, Card, Typography, Spin, Divider } from "antd";
import MessageManager from "@/components/molecules/message_manager";
-import { SendOutlined, DatabaseOutlined, LoadingOutlined, DownOutlined, RightOutlined } from "@ant-design/icons";
+import { ChevronDown, ChevronRight, Database, Send } from "lucide-react";
import { vectorStoreSearchCall } from "@/components/networking";
import NotificationsManager from "@/components/molecules/notifications_manager";
-
-const { TextArea } = Input;
-const { Text, Title } = Typography;
+import { Button } from "@/components/ui/button";
+import { Card } from "@/components/ui/card";
+import { Separator } from "@/components/ui/separator";
+import { Textarea } from "@/components/ui/textarea";
+import { UiLoadingSpinner } from "@/components/ui/ui-loading-spinner";
interface VectorStoreContent {
text: string;
@@ -98,18 +99,16 @@ export const VectorStoreTester: React.FC = ({ vectorStor
};
return (
-
-
+
+
{/* Header */}
-
+
-
-
- Test Vector Store
-
+
+ Test Vector Store
{searchHistory.length > 0 && (
-