Adding e2e tests for sidebar

This commit is contained in:
yuneng-jiang 2025-12-30 12:19:25 -08:00
parent c7734cb8bd
commit c049f6a073
8 changed files with 84 additions and 21 deletions

3
.gitignore vendored
View File

@ -102,4 +102,5 @@ litellm/proxy/_experimental/out/guardrails/index.html
scripts/test_vertex_ai_search.py
LAZY_LOADING_IMPROVEMENTS.md
**/test-results
**/playwright-report
**/playwright-report
**/*.storageState.json

View File

@ -1,20 +0,0 @@
import { test, expect } from "@playwright/test";
test("login and save auth state", async ({ page }) => {
await page.goto("http://localhost:4000/ui");
await page.getByPlaceholder("Enter your username").fill("admin");
await page.getByPlaceholder("Enter your password").fill("gm");
const loginButton = page.getByRole("button", { name: "Login" });
await expect(loginButton).toBeEnabled();
await loginButton.click();
// Assert successful login (important)
await expect(page.getByText("AI Gateway")).toBeVisible();
// 🔐 Save auth state
await page.context().storageState({
path: "storageState.json",
});
});

View File

@ -0,0 +1,6 @@
export enum Role {
ProxyAdmin = "proxy_admin",
ProxyAdminViewer = "proxy_admin_viewer",
InternalUser = "internal_user",
InternalUserViewer = "internal_user_viewer",
}

View File

@ -0,0 +1,10 @@
import { Role } from "./roles";
const isCI = !!process.env.CI;
export const users = {
[Role.ProxyAdmin]: {
email: "admin",
password: isCI ? "gm" : "sk-1234",
},
};

View File

@ -0,0 +1,18 @@
import { chromium } from "@playwright/test";
import { users } from "./fixtures/users";
import { Role } from "./fixtures/roles";
async function globalSetup() {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto("http://localhost:4000/ui/login");
await page.getByPlaceholder("Enter your username").fill(users[Role.ProxyAdmin].email);
await page.getByPlaceholder("Enter your password").fill(users[Role.ProxyAdmin].password);
const loginButton = page.getByRole("button", { name: "Login" });
await loginButton.click();
await page.waitForSelector("text=AI Gateway");
await page.context().storageState({ path: "admin.storageState.json" });
await browser.close();
}
export default globalSetup;

View File

@ -44,4 +44,5 @@ export default defineConfig({
expect: {
timeout: 10 * 1000,
},
globalSetup: require.resolve("./globalSetup"),
});

View File

@ -0,0 +1,13 @@
import { expect, test } from "@playwright/test";
import { users } from "../../fixtures/users";
import { Role } from "../../fixtures/roles";
test("user can log in", async ({ page }) => {
await page.goto("http://localhost:4000/ui/login");
await page.getByPlaceholder("Enter your username").fill(users[Role.ProxyAdmin].email);
await page.getByPlaceholder("Enter your password").fill(users[Role.ProxyAdmin].password);
const loginButton = page.getByRole("button", { name: "Login" });
await expect(loginButton).toBeEnabled();
await loginButton.click();
await expect(page.getByText("AI Gateway")).toBeVisible();
});

View File

@ -0,0 +1,34 @@
import test, { expect } from "@playwright/test";
import { Role } from "../../fixtures/roles";
const sidebarButtons = {
[Role.ProxyAdmin]: [
"Virtual Keys",
"Playground",
"Models",
"Usage",
"Teams",
"Internal User",
"Settings",
"Experimental",
"API Reference",
"AI Hub",
],
};
const roles = [{ role: Role.ProxyAdmin, storage: "admin.storageState.json" }];
for (const { role, storage } of roles) {
test.describe(`${role} sidebar`, () => {
test.use({ storageState: storage });
test("can see and navigate all sidebar buttons", async ({ page }) => {
await page.goto("http://localhost:4000/ui");
for (const button of sidebarButtons[role as keyof typeof sidebarButtons]) {
const tab = page.getByRole("menuitem", { name: button });
await expect(tab).toBeVisible();
await tab.click();
}
});
});
}