Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions ui/litellm-dashboard/e2e_tests/fixtures/migratedPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
* - server-root-path mount: SERVER_ROOT_PATH=/<root> npm run e2e:migration:root
*
* Keep this in lockstep with MIGRATED_PAGES in src/utils/migratedPages.ts.
* Pending (uncomment as each PR lands): playground, and the leaf-pages batch
* (budgets, caching, cost-tracking, guardrails, guardrails-monitor, logs,
* mcp-servers, memory, policies, projects, prompts, search-tools, skills,
* tag-management, tool-policies, transform-request, ui-theme, vector-stores,
* workflows, access-groups).
* Pending (add as each PR lands): the leaf-pages batch (budgets, caching,
* cost-tracking, guardrails, guardrails-monitor, logs, mcp-servers, memory,
* policies, projects, prompts, search-tools, skills, tag-management,
* tool-policies, transform-request, ui-theme, vector-stores, workflows,
* access-groups).
*/
export const MIGRATED_E2E_SEGMENTS: string[] = ["api-reference"];
export const MIGRATED_E2E_SEGMENTS: string[] = ["api-reference", "playground"];
20 changes: 15 additions & 5 deletions ui/litellm-dashboard/e2e_tests/tests/navigation/sidebar.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ const sidebarButtons = {
[Role.ProxyAdmin]: ["Virtual Keys", "Playground", "Models", "Usage", "Teams", "Internal Users", "AI Hub"],
};

// Route segment for pages migrated to path routes; mirror of MIGRATED_PAGES in src/utils/migratedPages.ts.
const migratedPageSegments: Partial<Record<Page, string>> = {
[Page.ApiRef]: "api-reference",
[Page.LlmPlayground]: "playground",
};

function expectedUrlPattern(pageKey: Page): RegExp {
const segment = migratedPageSegments[pageKey];
return segment ? new RegExp(`/ui/${segment}/?($|\\?)`) : new RegExp(`[?&]page=${pageKey}(&|$)`);
}

const roles = [{ role: Role.ProxyAdmin, storage: ADMIN_STORAGE_PATH }];

for (const { role, storage } of roles) {
Expand All @@ -35,8 +46,7 @@ for (const { role, storage } of roles) {

await tab.click();

// Verify URL contains the correct page query parameter
await expect(page).toHaveURL(new RegExp(`[?&]page=${expectedPage}(&|$)`));
await expect(page).toHaveURL(expectedUrlPattern(expectedPage));
}
});

Expand All @@ -50,13 +60,13 @@ for (const { role, storage } of roles) {

// Test direct navigation to verify the helper function works
await navigateToPage(page, Page.ApiKeys);
await expect(page).toHaveURL(new RegExp(`[?&]page=${Page.ApiKeys}(&|$)`));
await expect(page).toHaveURL(expectedUrlPattern(Page.ApiKeys));

await navigateToPage(page, Page.Models);
await expect(page).toHaveURL(new RegExp(`[?&]page=${Page.Models}(&|$)`));
await expect(page).toHaveURL(expectedUrlPattern(Page.Models));

await navigateToPage(page, Page.LlmPlayground);
await expect(page).toHaveURL(new RegExp(`[?&]page=${Page.LlmPlayground}(&|$)`));
await expect(page).toHaveURL(expectedUrlPattern(Page.LlmPlayground));
});
});
}
3 changes: 0 additions & 3 deletions ui/litellm-dashboard/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import SidebarProvider from "@/app/(dashboard)/components/SidebarProvider";
import OldModelDashboard from "@/app/(dashboard)/models-and-endpoints/ModelsAndEndpointsView";
import PlaygroundPage from "@/app/(dashboard)/playground/page";
import AdminPanel from "@/components/AdminPanel";
import AgentsPanel from "@/components/agents";
import BudgetPanel from "@/components/budgets/budget_panel";
Expand Down Expand Up @@ -65,12 +64,12 @@
LITELLM_UI_API_DOC_BASE_URL?: string | null;
}

function CreateKeyPageContent() {

Check warning on line 67 in ui/litellm-dashboard/src/app/page.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Function 'CreateKeyPageContent' has a complexity of 44. Maximum allowed is 20
const { authLoading, token, userID, userRole, userEmail, accessToken, premiumUser, setUserRole, setUserEmail } =
useAuth();

const [teams, setTeams] = useState<Team[] | null>(null);
const [keys, setKeys] = useState<null | any[]>([]);

Check warning on line 72 in ui/litellm-dashboard/src/app/page.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Unexpected any. Specify a different type
const [organizations, setOrganizations] = useState<Organization[]>([]);
const [userModels, setUserModels] = useState<string[]>([]);
const [proxySettings, setProxySettings] = useState<ProxySettings>({
Expand All @@ -80,7 +79,7 @@

const router = useRouter();
const searchParams = useSearchParams()!;
const [modelData, setModelData] = useState<any>({ data: [] });

Check warning on line 82 in ui/litellm-dashboard/src/app/page.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Unexpected any. Specify a different type
const [createClicked, setCreateClicked] = useState<boolean>(false);

// Survey state - always show by default
Expand Down Expand Up @@ -177,7 +176,7 @@
setSidebarCollapsed(!sidebarCollapsed);
};

const addKey = (data: any) => {

Check warning on line 179 in ui/litellm-dashboard/src/app/page.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Unexpected any. Specify a different type
setKeys((prevData) => (prevData ? [...prevData, data] : [data]));
setCreateClicked(() => !createClicked);
};
Expand Down Expand Up @@ -406,8 +405,6 @@
premiumUser={premiumUser}
teams={teams}
/>
) : page == "llm-playground" ? (
<PlaygroundPage />
) : page == "users" ? (
<ViewUserDashboard
userID={userID}
Expand Down
5 changes: 4 additions & 1 deletion ui/litellm-dashboard/src/utils/migratedPages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ describe("migratedHref / legacyPageHref", () => {
expect(migratedHref("/api-reference")).toBe("/ui/api-reference");
});

it("maps both the api_ref id and the hyphenated alias to the api-reference route", async () => {
it("maps legacy page ids (and the hyphenated api-reference alias) to their route segments", async () => {
vi.doMock("@/components/networking", () => ({ serverRootPath: "/" }));
const { MIGRATED_PAGES } = await import("./migratedPages");

expect(MIGRATED_PAGES.api_ref).toBe("api-reference");
expect(MIGRATED_PAGES["api-reference"]).toBe("api-reference");
expect(MIGRATED_PAGES["llm-playground"]).toBe("playground");
});
});

Expand All @@ -49,6 +50,8 @@ describe("legacyKeyForPathname", () => {
// Resolves to the sidebar key api_ref, not the hyphenated alias, so highlighting works.
expect(legacyKeyForPathname("/ui/api-reference")).toBe("api_ref");
expect(legacyKeyForPathname("/ui/api-reference/")).toBe("api_ref");
expect(legacyKeyForPathname("/ui/playground")).toBe("llm-playground");
expect(legacyKeyForPathname("/ui/playground/")).toBe("llm-playground");
});

it("returns null for a not-yet-migrated path", async () => {
Expand Down
1 change: 1 addition & 0 deletions ui/litellm-dashboard/src/utils/migratedPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const MIGRATED_PAGES: Record<string, string> = {
api_ref: "api-reference",
// Legacy alias: older bookmarks used the hyphenated ?page=api-reference form.
"api-reference": "api-reference",
"llm-playground": "playground",
};

function uiBase(): string {
Expand Down
Loading