From 404efaf52254e26ac365b2b0222c853bc76943b1 Mon Sep 17 00:00:00 2001 From: ryan-crabbe-berri Date: Wed, 27 May 2026 14:13:44 -0700 Subject: [PATCH 1/2] test(e2e): cover navbar Logout flow as proxy admin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Logout button under the navbar User dropdown was an uncovered manual-QA step. This test signs in as admin, opens the dropdown, clicks Logout, then navigates to a protected page and asserts the redirect to /ui/login — proving the session was cleared. --- .../e2e_tests/tests/auth/logout.spec.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 ui/litellm-dashboard/e2e_tests/tests/auth/logout.spec.ts diff --git a/ui/litellm-dashboard/e2e_tests/tests/auth/logout.spec.ts b/ui/litellm-dashboard/e2e_tests/tests/auth/logout.spec.ts new file mode 100644 index 000000000000..55dd578e48ae --- /dev/null +++ b/ui/litellm-dashboard/e2e_tests/tests/auth/logout.spec.ts @@ -0,0 +1,33 @@ +import { test, expect } from "@playwright/test"; +import { ADMIN_STORAGE_PATH } from "../../constants"; + +test.describe("Logout", () => { + test.use({ storageState: ADMIN_STORAGE_PATH }); + + test("Clicking Logout clears the session and forces re-login on a protected page", async ({ page }) => { + await page.goto("/ui"); + await expect(page.getByText("Virtual Keys")).toBeVisible({ timeout: 10_000 }); + + // Open the navbar User dropdown — same synthetic-hover trick as login.spec.ts + // because antd's hover trigger closes the popup between Playwright actions. + const userTrigger = page.locator("nav").getByRole("button").filter({ hasText: /^User$/ }); + await userTrigger.evaluate((el: HTMLElement) => { + el.dispatchEvent(new MouseEvent("mouseover", { bubbles: true })); + el.dispatchEvent(new MouseEvent("mouseenter", { bubbles: true })); + }); + + const popup = page.locator(".ant-dropdown:visible").filter({ + has: page.locator(".bg-white.rounded-lg.shadow-lg"), + }).first(); + await expect(popup).toBeVisible({ timeout: 5_000 }); + + // Click Logout — the handler clears the auth cookie and navigates via + // window.location.href = PROXY_LOGOUT_URL (empty string in the e2e env). + await popup.getByText("Logout", { exact: true }).click(); + + // The cookie is now gone — visiting a protected page must redirect to /ui/login. + await page.goto("/ui?page=llm-playground", { waitUntil: "domcontentloaded" }); + await expect(page).toHaveURL(/\/ui\/login/); + await expect(page.getByRole("heading", { name: "Login" })).toBeVisible({ timeout: 10_000 }); + }); +}); From 666a4eb0fe261523a9414a322cbcd69fee6a0ce0 Mon Sep 17 00:00:00 2001 From: ryan-crabbe-berri Date: Fri, 29 May 2026 09:46:40 -0700 Subject: [PATCH 2/2] test(e2e): fix logout dropdown trigger and account-menu selector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The button never rendered the literal text "User" (it shows initials + display name), and the antd Dropdown uses trigger={["click"]}, so the synthetic mouseover/mouseenter never opened the popup. Open it with a real click on the button's aria-label ("Account menu — ..."). --- .../e2e_tests/tests/auth/logout.spec.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/ui/litellm-dashboard/e2e_tests/tests/auth/logout.spec.ts b/ui/litellm-dashboard/e2e_tests/tests/auth/logout.spec.ts index 55dd578e48ae..fefadf275486 100644 --- a/ui/litellm-dashboard/e2e_tests/tests/auth/logout.spec.ts +++ b/ui/litellm-dashboard/e2e_tests/tests/auth/logout.spec.ts @@ -8,13 +8,10 @@ test.describe("Logout", () => { await page.goto("/ui"); await expect(page.getByText("Virtual Keys")).toBeVisible({ timeout: 10_000 }); - // Open the navbar User dropdown — same synthetic-hover trick as login.spec.ts - // because antd's hover trigger closes the popup between Playwright actions. - const userTrigger = page.locator("nav").getByRole("button").filter({ hasText: /^User$/ }); - await userTrigger.evaluate((el: HTMLElement) => { - el.dispatchEvent(new MouseEvent("mouseover", { bubbles: true })); - el.dispatchEvent(new MouseEvent("mouseenter", { bubbles: true })); - }); + // Open the navbar User dropdown. The trigger button exposes an aria-label + // of "Account menu — — signed in as ", and the antd Dropdown + // is declared with trigger={["click"]}, so a plain click opens the popup. + await page.getByRole("button", { name: /Account menu/i }).click(); const popup = page.locator(".ant-dropdown:visible").filter({ has: page.locator(".bg-white.rounded-lg.shadow-lg"),