mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-03-16 12:27:49 +08:00
### What problem does this PR solve? Playwright tests previously depended on cross-file execution order (`auth -> provider -> dataset -> chat`). This change makes setup explicit and idempotent via fixtures so tests can run independently. - Added/standardized prerequisite fixtures in `test/playwright/conftest.py`: - `ensure_auth_context`, `ensure_model_provider_configured`, `ensure_dataset_ready`, `ensure_chat_ready` - Made provisioning reusable/idempotent with `RUN_ID`-based resource naming. - Synced auth envs (`E2E_ADMIN_EMAIL`, `E2E_ADMIN_PASSWORD`) into seeded creds. - Fixed provider cache freshness (`auth_header`/`page` refresh on cache hit). Also included minimal stability fixes: - dataset create stale-element click handling, - search wait logic for results/empty-state, - agent create-menu handling, - agent run-step retry when run UI doesn’t open first click. ### Type of change - [x] Test fix - [x] Refactoring --------- Co-authored-by: Liu An <asiro@qq.com>
83 lines
2.5 KiB
Python
83 lines
2.5 KiB
Python
import os
|
|
|
|
import pytest
|
|
from playwright.sync_api import expect
|
|
|
|
RESULT_TIMEOUT_MS = 15000
|
|
|
|
|
|
def _wait_for_login_complete(page, timeout_ms: int = RESULT_TIMEOUT_MS) -> None:
|
|
wait_js = """
|
|
() => {
|
|
const path = window.location.pathname || '';
|
|
if (path.includes('/login')) return false;
|
|
const token = localStorage.getItem('Token');
|
|
const auth = localStorage.getItem('Authorization');
|
|
return Boolean((token && token.length) || (auth && auth.length));
|
|
}
|
|
"""
|
|
page.wait_for_function(wait_js, timeout=timeout_ms)
|
|
|
|
|
|
def ensure_authed(
|
|
page,
|
|
login_url: str,
|
|
active_auth_context,
|
|
auth_click,
|
|
seeded_user_credentials=None,
|
|
timeout_ms: int = RESULT_TIMEOUT_MS,
|
|
) -> None:
|
|
if seeded_user_credentials:
|
|
email, password = seeded_user_credentials
|
|
else:
|
|
email = os.getenv("SEEDED_USER_EMAIL") or os.getenv("E2E_ADMIN_EMAIL")
|
|
password = os.getenv("SEEDED_USER_PASSWORD") or os.getenv(
|
|
"E2E_ADMIN_PASSWORD"
|
|
)
|
|
if not email or not password:
|
|
pytest.skip("SEEDED_USER_EMAIL/SEEDED_USER_PASSWORD not set.")
|
|
|
|
token_wait_js = """
|
|
() => {
|
|
const token = localStorage.getItem('Token');
|
|
const auth = localStorage.getItem('Authorization');
|
|
return Boolean((token && token.length) || (auth && auth.length));
|
|
}
|
|
"""
|
|
|
|
try:
|
|
if "/login" not in page.url:
|
|
page.wait_for_function(token_wait_js, timeout=2000)
|
|
return
|
|
except Exception:
|
|
pass
|
|
|
|
page.goto(login_url, wait_until="domcontentloaded")
|
|
|
|
if "/login" not in page.url:
|
|
return
|
|
|
|
form, _ = active_auth_context()
|
|
email_input = form.locator(
|
|
"input[data-testid='auth-email'], [data-testid='auth-email'] input"
|
|
)
|
|
password_input = form.locator(
|
|
"input[data-testid='auth-password'], [data-testid='auth-password'] input"
|
|
)
|
|
expect(email_input).to_have_count(1)
|
|
expect(password_input).to_have_count(1)
|
|
email_input.fill(email)
|
|
password_input.fill(password)
|
|
password_input.blur()
|
|
|
|
submit_button = form.locator(
|
|
"button[data-testid='auth-submit'], [data-testid='auth-submit'] button, [data-testid='auth-submit']"
|
|
)
|
|
expect(submit_button).to_have_count(1)
|
|
auth_click(submit_button, "submit_login")
|
|
|
|
_wait_for_login_complete(page, timeout_ms=timeout_ms)
|
|
expect(page.locator("form[data-testid='auth-form'][data-active='true']")).to_have_count(
|
|
0, timeout=timeout_ms
|
|
)
|