mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-26 01:12:21 +00:00
test(e2e/ui): give the logout specs their own admin session (#42930)
#42463 made Logout revoke the dashboard session key on the server. Both logout specs ran on the shared ADMIN_STORAGE_PATH session that globalSetup mints once, so clicking Logout revoked the key every later admin spec reuses. The CircleCI run is serial, and from the auth/ folder on, every admin-session spec failed with "Invalid proxy server token passed" (80 failures, up from 7) while the internal-user, internal-viewer and team-admin specs kept passing. Each logout spec now starts from an empty storage state and logs in through the login page, so the session it revokes is its own. The login steps live in a shared logInThroughLoginPage helper next to the other onboarding helpers.
This commit is contained in:
parent
12960f3edf
commit
259f954f56
3 changed files with 24 additions and 6 deletions
|
|
@ -57,3 +57,13 @@ export async function expectUnrestrictedDashboard(page: Page): Promise<void> {
|
|||
expect(info.ok(), `Read own user with dashboard session: HTTP ${info.status()}`).toBe(true);
|
||||
expect((await info.json()).user_id).toBe(session.user_id);
|
||||
}
|
||||
|
||||
export async function logInThroughLoginPage(page: Page, email: string, password: string): Promise<void> {
|
||||
await page.goto(`${rootPath()}/ui/login`);
|
||||
await page.getByPlaceholder("Enter your username").fill(email);
|
||||
await page.getByPlaceholder("Enter your password").fill(password);
|
||||
await page.getByRole("button", { name: "Login", exact: true }).click();
|
||||
await page.waitForURL((url) => url.pathname.startsWith(`${rootPath()}/ui`) && !url.pathname.includes("/login"), {
|
||||
timeout: 30_000,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import { ADMIN_STORAGE_PATH } from "../../constants";
|
||||
import { Role, users } from "../../fixtures/users";
|
||||
import { logInThroughLoginPage } from "../../helpers/userOnboarding";
|
||||
|
||||
test.describe("Logout", () => {
|
||||
test.use({ storageState: ADMIN_STORAGE_PATH });
|
||||
test.use({ storageState: { cookies: [], origins: [] } });
|
||||
|
||||
test("Clicking Logout clears the session and forces re-login on a protected page", async ({ page }) => {
|
||||
const admin = users[Role.ProxyAdmin];
|
||||
await logInThroughLoginPage(page, admin.email, admin.password);
|
||||
|
||||
await page.goto("/ui");
|
||||
// Scope to the sidebar; the top-bar breadcrumb also shows "Virtual Keys".
|
||||
await expect(page.getByRole("complementary").getByText("Virtual Keys")).toBeVisible({ timeout: 10_000 });
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import { ADMIN_STORAGE_PATH } from "../../constants";
|
||||
import { Role, users } from "../../fixtures/users";
|
||||
import { logInThroughLoginPage } from "../../helpers/userOnboarding";
|
||||
|
||||
/**
|
||||
* Runs as part of the standard e2e suite: both `run_e2e.sh` and the CircleCI
|
||||
|
|
@ -16,9 +17,12 @@ const LOGOUT_URL = process.env.PROXY_LOGOUT_URL ?? "";
|
|||
test.skip(!LOGOUT_URL, "Requires PROXY_LOGOUT_URL env var");
|
||||
|
||||
test.describe("PROXY_LOGOUT_URL redirect", () => {
|
||||
test.use({ storageState: ADMIN_STORAGE_PATH });
|
||||
test.use({ storageState: { cookies: [], origins: [] } });
|
||||
|
||||
test("Logout clears the session and redirects to PROXY_LOGOUT_URL", async ({ page }) => {
|
||||
const admin = users[Role.ProxyAdmin];
|
||||
await logInThroughLoginPage(page, admin.email, admin.password);
|
||||
|
||||
const target = new URL(LOGOUT_URL);
|
||||
|
||||
// Stub the external logout destination so the assertion doesn't depend on
|
||||
|
|
@ -46,8 +50,8 @@ test.describe("PROXY_LOGOUT_URL redirect", () => {
|
|||
await expect(page.getByRole("complementary").getByText("Virtual Keys")).toBeVisible({ timeout: 15_000 });
|
||||
await settingsLoaded;
|
||||
|
||||
// Pre-condition: we start authenticated. The admin storage state carries a
|
||||
// `token` cookie, so a real logout has something to tear down.
|
||||
// Pre-condition: we start authenticated. The fresh login set a `token`
|
||||
// cookie, so a real logout has something to tear down.
|
||||
const tokensBefore = (await page.context().cookies()).filter((c) => c.name === "token");
|
||||
expect(tokensBefore.length, "should start logged in with a token cookie").toBeGreaterThan(0);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue