diff --git a/ui/litellm-dashboard/src/components/common_components/user_search_modal.test.tsx b/ui/litellm-dashboard/src/components/common_components/user_search_modal.test.tsx index 98b85c738b4..6b71d5ab1d2 100644 --- a/ui/litellm-dashboard/src/components/common_components/user_search_modal.test.tsx +++ b/ui/litellm-dashboard/src/components/common_components/user_search_modal.test.tsx @@ -252,4 +252,23 @@ describe("UserSearchModal out-of-order search results", () => { role: "user", }); }); + + it("stops loading once the box is cleared and the abandoned search answers", async () => { + const user = userEvent.setup(); + render(); + + const input = getEmailSearchInput(); + await user.click(input); + await user.type(input, "ali"); + await waitFor(() => expect(answers.has("ali")).toBe(true), { timeout: 3000 }); + await screen.findByText("Loading..."); + + await user.clear(input); + await screen.findByText("No results"); + + await answerFor("ali", [{ user_id: "u-jones", user_email: "alice.jones@example.com" }]); + + expect(screen.queryByRole("option")).not.toBeInTheDocument(); + expect(screen.getByText("No results")).toBeInTheDocument(); + }); }); diff --git a/ui/litellm-dashboard/src/components/common_components/user_search_modal.tsx b/ui/litellm-dashboard/src/components/common_components/user_search_modal.tsx index 71d38c6db25..41cbd58ba53 100644 --- a/ui/litellm-dashboard/src/components/common_components/user_search_modal.tsx +++ b/ui/litellm-dashboard/src/components/common_components/user_search_modal.tsx @@ -87,6 +87,7 @@ const UserSearchModal: React.FC = ({ if (!searchText) { setUserOptions([]); + setLoading(false); return; } diff --git a/ui/litellm-dashboard/src/components/organisms/create_key_button.integration.test.tsx b/ui/litellm-dashboard/src/components/organisms/create_key_button.integration.test.tsx index aa59dbb024f..8072a90fcad 100644 --- a/ui/litellm-dashboard/src/components/organisms/create_key_button.integration.test.tsx +++ b/ui/litellm-dashboard/src/components/organisms/create_key_button.integration.test.tsx @@ -835,6 +835,34 @@ describe("CreateKey", () => { expect(screen.queryByTitle("alice.jones@example.com (u-jones)")).not.toBeInTheDocument(); expect(screen.getByTitle("alice.smith@example.com (u-smith)")).toBeInTheDocument(); }); + + it("stops searching once the box is cleared and the abandoned search answers", async () => { + const answers = new Map void>(); + vi.mocked(userFilterUICall).mockImplementation( + (_accessToken, params) => + new Promise((resolve) => { + answers.set(params.get("user_email") ?? "", resolve); + }) as never, + ); + + const user = userEvent.setup(); + renderCreateKey({ autoOpenCreate: true, prefillData: { owned_by: "another_user" } }); + const search = antdSearchInput(await screen.findByText("Type email to search for users")); + + await user.type(search, "ali"); + await waitFor(() => expect(answers.has("ali")).toBe(true), { timeout: 3000 }); + await screen.findByText("Searching..."); + + await user.clear(search); + await screen.findByText("No users found"); + + await act(async () => { + answers.get("ali")?.([{ user_id: "u-jones", user_email: "alice.jones@example.com" }]); + }); + + expect(screen.queryByTitle("alice.jones@example.com (u-jones)")).not.toBeInTheDocument(); + expect(screen.getByText("No users found")).toBeInTheDocument(); + }); }); describe("created key display", () => { diff --git a/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx b/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx index 73438c244c1..62ad62e0f83 100644 --- a/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx +++ b/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx @@ -563,6 +563,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp if (!searchText) { setUserOptions([]); + setUserSearchLoading(false); return; }