litellm/tests/e2e/management/conftest.py
Yassin Kortam 442fdc181e
docs(tests/e2e): align docs with the hard-fail-on-dead-proxy contract and scope the no-unit-tests rule (#33755)
The e2e docs claimed `e2e`-marked tests skip when no proxy answers the
liveness probe, but the harness has always hard-failed: conftest.py's
pytest_runtest_setup calls pytest.fail, its module docstring states
"hard failures only ... never skip", and logging/conftest.py forbids
skipping outright. Align the docs to the code so the single most
important contract reads the same everywhere; a dead proxy turns a run
red instead of being silently skipped and mistaken for a pass. The
per-suite conftest docstrings that described the shared hook as a
"proxy liveness skip" are corrected to "liveness gate" for the same
reason.

Also scope the no-unit-tests hard rule to what it means: never
substitute a unit test for e2e feature coverage, while explicitly
allowing tests that cover the harness itself (e.g.
coverage_registry/test_collector.py), which carry no e2e marker and
run whether or not a proxy is up.

No product code and no harness logic changed.

Resolves LIT-4554
2026-07-17 12:56:10 -07:00

63 lines
2.2 KiB
Python

"""Management suite fixtures: the client plus a logged-in dashboard page.
Lifecycle/liveness gate/marker live in the parent conftest. The browser fixtures drive
the dashboard the proxy serves at /ui, so browser tests exercise exactly what an
end user sees. playwright is an optional dependency loaded behind importorskip
inside the fixture, so the API tests in this suite collect and run without it:
uv pip install playwright && uv run playwright install chromium
"""
from typing import TYPE_CHECKING, Iterator
import pytest
from e2e_config import UI_BASE_URL, UI_PASSWORD, UI_USERNAME
from management_client import ManagementClient, build_client
if TYPE_CHECKING:
from playwright.sync_api import Browser, Page
def pytest_configure(config: pytest.Config) -> None:
config.addinivalue_line(
"markers",
"covers: registry cell a test covers, e.g. mgmt.key.generate.persists",
)
@pytest.fixture(scope="session")
def client() -> ManagementClient:
return build_client()
@pytest.fixture(scope="session")
def browser() -> "Iterator[Browser]":
pytest.importorskip("playwright.sync_api", reason="playwright not installed")
from playwright.sync_api import sync_playwright
with sync_playwright() as playwright:
launched = playwright.chromium.launch()
yield launched
launched.close()
@pytest.fixture
def ui_page(browser: "Browser") -> "Iterator[Page]":
context = browser.new_context()
try:
page = context.new_page()
# Split deploys serve the Next.js dashboard on the UI service, not the
# data-plane gateway (which 404s /ui). Login is a client-rendered form
# that appears after LoadingScreen; wait on the placeholder, not #id
# (Ant Design Input does not always set id="username").
page.goto(f"{UI_BASE_URL}/ui/login")
username = page.get_by_placeholder("Enter your username")
username.wait_for(state="visible", timeout=30_000)
username.fill(UI_USERNAME)
page.get_by_placeholder("Enter your password").fill(UI_PASSWORD)
page.get_by_role("button", name="Login", exact=True).click()
page.wait_for_function("() => document.cookie.includes('token=')")
yield page
finally:
context.close()