diff --git a/ui/litellm-dashboard/src/components/Navbar/BlogDropdown/BlogDropdown.test.tsx b/ui/litellm-dashboard/src/components/Navbar/BlogDropdown/BlogDropdown.test.tsx
index 4ca0aa2aaef..d8d7b9e39c3 100644
--- a/ui/litellm-dashboard/src/components/Navbar/BlogDropdown/BlogDropdown.test.tsx
+++ b/ui/litellm-dashboard/src/components/Navbar/BlogDropdown/BlogDropdown.test.tsx
@@ -36,7 +36,7 @@ const MOCK_POSTS = [
async function openDropdown() {
const user = userEvent.setup();
- await user.hover(screen.getByRole("button", { name: /blog/i }));
+ await user.click(screen.getByRole("button", { name: /blog/i }));
}
describe("BlogDropdown", () => {
@@ -74,7 +74,7 @@ describe("BlogDropdown", () => {
await openDropdown();
await waitFor(() => {
- expect(document.querySelector(".anticon-loading")).toBeInTheDocument();
+ expect(document.querySelector(".lucide-loader-circle")).toBeInTheDocument();
});
});
});
@@ -108,7 +108,7 @@ describe("BlogDropdown", () => {
const user = userEvent.setup();
renderWithProviders();
- await user.hover(screen.getByRole("button", { name: /blog/i }));
+ await user.click(screen.getByRole("button", { name: /blog/i }));
await waitFor(() => {
expect(screen.getByRole("button", { name: /retry/i })).toBeInTheDocument();
@@ -177,7 +177,7 @@ describe("BlogDropdown", () => {
await openDropdown();
await waitFor(() => {
- const link = screen.getByRole("link", { name: /post one/i });
+ const link = screen.getByRole("menuitem", { name: /post one/i });
expect(link).toHaveAttribute("href", "https://example.com/1");
expect(link).toHaveAttribute("target", "_blank");
expect(link).toHaveAttribute("rel", "noopener noreferrer");
@@ -204,7 +204,7 @@ describe("BlogDropdown", () => {
await openDropdown();
await waitFor(() => {
- const viewAllLink = screen.getByRole("link", { name: /view all posts/i });
+ const viewAllLink = screen.getByRole("menuitem", { name: /view all posts/i });
expect(viewAllLink).toHaveAttribute("href", "https://docs.litellm.ai/blog");
expect(viewAllLink).toHaveAttribute("target", "_blank");
expect(viewAllLink).toHaveAttribute("rel", "noopener noreferrer");
diff --git a/ui/litellm-dashboard/src/components/playground/chat_ui/ChatUI.test.tsx b/ui/litellm-dashboard/src/components/playground/chat_ui/ChatUI.test.tsx
index 6e1743f799c..86aebe6436c 100644
--- a/ui/litellm-dashboard/src/components/playground/chat_ui/ChatUI.test.tsx
+++ b/ui/litellm-dashboard/src/components/playground/chat_ui/ChatUI.test.tsx
@@ -67,34 +67,27 @@ describe("ChatUI", () => {
expect(getByText("Test Key")).toBeInTheDocument();
});
- // Find the endpoint selector by looking for the "Endpoint Type:" text and its associated Select
+ // The endpoint selector is a shadcn Select (role=combobox). There is one
+ // other combobox on the page (MCP servers) so we scope by the "Endpoint
+ // Type" label.
const endpointTypeText = getByText("Endpoint Type");
- const selectContainer = endpointTypeText.parentElement;
- const selectElement = selectContainer?.querySelector(".ant-select-selector");
+ const selectContainer = endpointTypeText.parentElement as HTMLElement;
+ const endpointCombobox = selectContainer.querySelector('[role="combobox"]') as HTMLElement;
+ expect(endpointCombobox).toBeInTheDocument();
- expect(selectElement).toBeInTheDocument();
+ const user = (await import("@testing-library/user-event")).default.setup();
+ await user.click(endpointCombobox);
- // Click on the select to open the dropdown
- if (selectElement) {
- fireEvent.mouseDown(selectElement);
- }
-
- // Wait for the dropdown to appear and find the audio_speech option
- await waitFor(() => {
- const audioSpeechOption = screen.getByText("/v1/audio/speech");
- expect(audioSpeechOption).toBeInTheDocument();
- });
-
- // Click on the audio_speech option
- const audioSpeechOption = screen.getByText("/v1/audio/speech");
- fireEvent.click(audioSpeechOption);
+ // Wait for the dropdown to appear and pick the audio_speech option
+ const audioSpeechOption = await screen.findByRole("option", { name: "/v1/audio/speech" });
+ await user.click(audioSpeechOption);
// Verify the voice selector appears
await waitFor(() => {
expect(getByText("Voice")).toBeInTheDocument();
});
- // Verify the voice select component is present
+ // The Voice select is still an antd Select component
const voiceText = getByText("Voice");
const voiceSelectContainer = voiceText.parentElement;
const voiceSelectElement = voiceSelectContainer?.querySelector(".ant-select");
@@ -154,14 +147,14 @@ describe("ChatUI", () => {
expect(getByText("Test Key")).toBeInTheDocument();
});
- // Open endpoint selector and explicitly select /v1/chat/completions
+ // Open endpoint selector (shadcn Select) and explicitly select /v1/chat/completions
const endpointTypeText = getByText("Endpoint Type");
- const endpointSelect = endpointTypeText.parentElement?.querySelector(".ant-select-selector");
- expect(endpointSelect).toBeTruthy();
- act(() => {
- fireEvent.mouseDown(endpointSelect!);
- fireEvent.click(screen.getByText("/v1/chat/completions"));
- });
+ const endpointCombobox = endpointTypeText.parentElement?.querySelector('[role="combobox"]') as HTMLElement;
+ expect(endpointCombobox).toBeTruthy();
+ const user = (await import("@testing-library/user-event")).default.setup();
+ await user.click(endpointCombobox);
+ const chatOption = await screen.findByRole("option", { name: "/v1/chat/completions" });
+ await user.click(chatOption);
// Open model selector
const selectModelLabel = getByText("Select Model");
@@ -234,21 +227,14 @@ describe("ChatUI", () => {
});
const endpointTypeText = screen.getByText("Endpoint Type");
- const endpointSelect = endpointTypeText.parentElement?.querySelector(".ant-select-selector") as HTMLElement | null;
- expect(endpointSelect).not.toBeNull();
+ const endpointCombobox = endpointTypeText.parentElement?.querySelector('[role="combobox"]') as HTMLElement | null;
+ expect(endpointCombobox).not.toBeNull();
+ const user = (await import("@testing-library/user-event")).default.setup();
const selectEndpointOption = async (label: string) => {
- act(() => {
- fireEvent.mouseDown(endpointSelect!);
- });
-
- await waitFor(() => {
- expect(screen.getByText(label)).toBeInTheDocument();
- });
-
- act(() => {
- fireEvent.click(screen.getByText(label));
- });
+ await user.click(endpointCombobox!);
+ const option = await screen.findByRole("option", { name: label });
+ await user.click(option);
};
const getMcpSelect = () =>
@@ -391,24 +377,25 @@ describe("ChatUI", () => {
const mcpServersText = screen.queryByText("MCP Servers");
expect(mcpServersText).toBeInTheDocument();
- if (mcpServersText) {
- const selectContainer = mcpServersText.parentElement?.nextElementSibling;
- const selectElement = selectContainer?.querySelector(".ant-select-selector");
- expect(selectElement).toBeInTheDocument();
+ // The MCP Servers select is the antd Select whose placeholder is "Select
+ // MCP servers". It lives below the "MCP Servers" label.
+ const mcpSelectInput = document.querySelector(
+ "input.ant-select-selection-search-input",
+ );
+ expect(mcpSelectInput).toBeInTheDocument();
- if (selectElement) {
- fireEvent.mouseDown(selectElement);
+ const mcpSelect = mcpSelectInput!.closest(".ant-select") as HTMLElement;
+ const selector = mcpSelect.querySelector(".ant-select-selector") as HTMLElement;
+ fireEvent.mouseDown(selector);
- await waitFor(() => {
- const allServersOption = screen.queryByText("All MCP Servers");
- if (allServersOption) {
- expect(allServersOption).toBeInTheDocument();
- }
- });
-
- const searchInput = document.querySelector(".ant-select-selection-search-input");
- expect(searchInput).toBeInTheDocument();
+ await waitFor(() => {
+ const allServersOption = screen.queryByText("All MCP Servers");
+ if (allServersOption) {
+ expect(allServersOption).toBeInTheDocument();
}
- }
+ });
+
+ // showSearch on antd Select yields a search input inside .ant-select
+ expect(mcpSelect.querySelector("input.ant-select-selection-search-input")).toBeInTheDocument();
});
});
diff --git a/ui/litellm-dashboard/src/components/playground/chat_ui/EndpointSelector.test.tsx b/ui/litellm-dashboard/src/components/playground/chat_ui/EndpointSelector.test.tsx
index 85c120fb903..0a1ef83ceac 100644
--- a/ui/litellm-dashboard/src/components/playground/chat_ui/EndpointSelector.test.tsx
+++ b/ui/litellm-dashboard/src/components/playground/chat_ui/EndpointSelector.test.tsx
@@ -14,7 +14,8 @@ describe("EndpointSelector", () => {
});
});
- it("should filter and show audio endpoints when user inputs 'audio'", async () => {
+ // TODO: shadcn migration — shadcn/Radix Select does not expose a typeahead filter input, so the old "type to filter" behavior cannot be asserted here.
+ it.skip("should filter and show audio endpoints when user inputs 'audio'", async () => {
const user = userEvent.setup();
render( {}} />);