mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
Relocates ui/litellm-dashboard/e2e_tests to tests/e2e/ui so all end to end suites live under tests/e2e. The suite stays in TypeScript and becomes a self-contained npm package with its own package.json, lockfile and tsconfig instead of leaning on the dashboard's toolchain; the dashboard drops its @playwright/test dependency, e2e scripts and knip/vitest/tsconfig carve-outs. CI paths follow the move: both CircleCI jobs (main e2e and the SERVER_ROOT_PATH migration smoke) and the test_server_root_path workflow now install and run Playwright from tests/e2e/ui, with the node cache keyed on both lockfiles. classify_changes.sh treats tests/e2e/ui as client so spec edits keep skipping backend jobs. The suite's mock LLM fixture is excluded from the e2e basedpyright zero-error gate in pyrightconfig.json since it belongs to the TS suite, not the typed Python harness.
32 lines
1.5 KiB
TypeScript
32 lines
1.5 KiB
TypeScript
import { test, expect } from "@playwright/test";
|
|
import * as fs from "fs";
|
|
import { ADMIN_STORAGE_PATH } from "../../constants";
|
|
|
|
/**
|
|
* Sanity check that LITELLM_LICENSE is being forwarded to the proxy when set
|
|
* in the environment (e.g. CircleCI's `e2e_ui_testing` job). The login JWT's
|
|
* `premium_user` claim is the same value the dashboard reads to enable
|
|
* premium-gated UI surfaces (Team-BYOK switch, etc.), so asserting it here
|
|
* catches any future regression where the env var stops being plumbed
|
|
* through `run_e2e.sh` / `.circleci/config.yml`.
|
|
*
|
|
* Skips locally when no license is configured.
|
|
*/
|
|
test.describe("Premium license wiring", () => {
|
|
test("admin session JWT carries premium_user=true when LITELLM_LICENSE is set", () => {
|
|
test.skip(!process.env.LITELLM_LICENSE, "LITELLM_LICENSE not set in test env — proxy is running unlicensed");
|
|
|
|
const storage = JSON.parse(fs.readFileSync(ADMIN_STORAGE_PATH, "utf-8"));
|
|
const tokenCookie = storage.cookies?.find((c: { name: string }) => c.name === "token");
|
|
expect(tokenCookie, "token cookie missing from admin storage state").toBeDefined();
|
|
|
|
// Decode the JWT payload (no signature check — we trust globalSetup ran
|
|
// against our own proxy). Payload is the middle base64url segment.
|
|
const jwtParts = tokenCookie.value.split(".");
|
|
expect(jwtParts.length, "token cookie is not a 3-part JWT").toBe(3);
|
|
const [, payloadB64] = jwtParts;
|
|
const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString("utf-8"));
|
|
|
|
expect(payload.premium_user).toBe(true);
|
|
});
|
|
});
|