Merge pull request #17682 from BerriAI/litellm_ui_ai_hub_link_input

[Fix] Swap URL Input and Display Name inputs
This commit is contained in:
yuneng-jiang
2025-12-08 17:27:11 -08:00
committed by GitHub
2 changed files with 89 additions and 15 deletions
@@ -0,0 +1,74 @@
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Modal } from "antd";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import UsefulLinksManagement from "./useful_links_management";
import NotificationsManager from "./molecules/notifications_manager";
import { getPublicModelHubInfo, updateUsefulLinksCall, getProxyBaseUrl } from "./networking";
vi.mock("./networking", () => ({
getPublicModelHubInfo: vi.fn(),
updateUsefulLinksCall: vi.fn(),
getProxyBaseUrl: vi.fn(),
}));
vi.mock("./molecules/notifications_manager", () => ({
__esModule: true,
default: {
success: vi.fn(),
fromBackend: vi.fn(),
},
}));
const mockedGetPublicModelHubInfo = vi.mocked(getPublicModelHubInfo);
const mockedUpdateUsefulLinksCall = vi.mocked(updateUsefulLinksCall);
const mockedGetProxyBaseUrl = vi.mocked(getProxyBaseUrl);
const mockedNotifications = vi.mocked(NotificationsManager);
let modalSuccessSpy: any;
describe("UsefulLinksManagement", () => {
beforeEach(() => {
mockedGetPublicModelHubInfo.mockResolvedValue({
docs_title: "Docs",
custom_docs_description: null,
litellm_version: "1.0.0",
useful_links: {},
});
mockedUpdateUsefulLinksCall.mockResolvedValue({});
mockedGetProxyBaseUrl.mockReturnValue("https://proxy.example.com");
modalSuccessSpy = vi.spyOn(Modal, "success").mockImplementation(() => ({ destroy: vi.fn() }) as any);
});
afterEach(() => {
modalSuccessSpy.mockRestore();
vi.clearAllMocks();
});
it("should render link management for admin users", async () => {
render(<UsefulLinksManagement accessToken="token" userRole="Admin" />);
expect(await screen.findByText("Link Management")).toBeInTheDocument();
await waitFor(() => expect(mockedGetPublicModelHubInfo).toHaveBeenCalled());
});
it("should add a new link when fields are valid", async () => {
const user = userEvent.setup();
render(<UsefulLinksManagement accessToken="token" userRole="Admin" />);
const displayNameInput = await screen.findByPlaceholderText("Friendly name");
const urlInput = screen.getByPlaceholderText("https://example.com");
await user.type(displayNameInput, "Docs");
await user.type(urlInput, "https://docs.example.com");
await user.click(screen.getByRole("button", { name: /add link/i }));
await waitFor(() =>
expect(mockedUpdateUsefulLinksCall).toHaveBeenCalledWith("token", { Docs: "https://docs.example.com" }),
);
expect(await screen.findByText("Docs")).toBeInTheDocument();
expect(screen.getByText("https://docs.example.com")).toBeInTheDocument();
expect(mockedNotifications.success).toHaveBeenCalledWith("Link added successfully");
});
});
@@ -210,21 +210,6 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
<div className="mb-6">
<Text className="text-sm font-medium text-gray-700 mb-2">Add New Link</Text>
<div className="grid grid-cols-3 gap-4">
<div>
<label className="block text-xs text-gray-500 mb-1">URL</label>
<input
type="text"
value={newLink.url}
onChange={(e) =>
setNewLink({
...newLink,
url: e.target.value,
})
}
placeholder="https://example.com"
className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm"
/>
</div>
<div>
<label className="block text-xs text-gray-500 mb-1">Display Name</label>
<input
@@ -240,6 +225,21 @@ const UsefulLinksManagement: React.FC<UsefulLinksManagementProps> = ({ accessTok
className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm"
/>
</div>
<div>
<label className="block text-xs text-gray-500 mb-1">URL</label>
<input
type="text"
value={newLink.url}
onChange={(e) =>
setNewLink({
...newLink,
url: e.target.value,
})
}
placeholder="https://example.com"
className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm"
/>
</div>
<div className="flex items-end">
<button
onClick={handleAddLink}