78 lines
3.0 KiB
Python
78 lines
3.0 KiB
Python
from contextlib import contextmanager
|
|
import os
|
|
|
|
import pytest
|
|
|
|
from tests.e2e.config import E2ESettings
|
|
|
|
|
|
playwright_api = pytest.importorskip("playwright.sync_api")
|
|
|
|
# On Windows, ``localhost`` can resolve to IPv6 while Django's ephemeral live
|
|
# server is listening on IPv4. Pin the test-only server to IPv4 so navigation
|
|
# failures represent the application rather than resolver/bind ambiguity.
|
|
os.environ.setdefault("DJANGO_LIVE_TEST_SERVER_ADDRESS", "127.0.0.1:0")
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def e2e_settings():
|
|
return E2ESettings.from_environment()
|
|
|
|
|
|
@pytest.fixture
|
|
def application_base_url(live_server, e2e_settings):
|
|
"""Configured deployment URL, falling back to Django's isolated local server."""
|
|
return e2e_settings.base_url or live_server.url
|
|
|
|
|
|
@pytest.fixture
|
|
def browser_page(request, e2e_settings):
|
|
"""Return a page factory with per-test isolation and automatic failure artifacts."""
|
|
|
|
@contextmanager
|
|
def open_page(*, service_workers="block"):
|
|
with playwright_api.sync_playwright() as playwright:
|
|
launch_options = {"headless": e2e_settings.headless, "slow_mo": e2e_settings.slow_mo}
|
|
try:
|
|
browser = playwright.chromium.launch(**launch_options)
|
|
except playwright_api.Error as bundled_error:
|
|
try:
|
|
browser = playwright.chromium.launch(channel="chrome", **launch_options)
|
|
except playwright_api.Error:
|
|
raise RuntimeError(
|
|
"No Chromium browser is available. Run: python -m playwright install chromium"
|
|
) from bundled_error
|
|
context = browser.new_context(
|
|
viewport=e2e_settings.viewport,
|
|
locale="fa-IR",
|
|
timezone_id="Asia/Tehran",
|
|
service_workers=service_workers,
|
|
)
|
|
context.set_default_timeout(e2e_settings.action_timeout_ms)
|
|
context.set_default_navigation_timeout(e2e_settings.navigation_timeout_ms)
|
|
context.tracing.start(screenshots=True, snapshots=True, sources=True)
|
|
page = context.new_page()
|
|
page_errors = []
|
|
page.on("pageerror", lambda error: page_errors.append(str(error)))
|
|
safe_name = request.node.nodeid.replace("::", "__").replace("/", "_").replace("\\", "_")
|
|
artifact_dir = e2e_settings.artifact_dir / safe_name
|
|
failed = False
|
|
try:
|
|
yield page
|
|
if page_errors:
|
|
raise AssertionError(f"Browser JavaScript errors: {page_errors}")
|
|
except BaseException:
|
|
failed = True
|
|
artifact_dir.mkdir(parents=True, exist_ok=True)
|
|
page.screenshot(path=artifact_dir / "failure.png", full_page=True)
|
|
raise
|
|
finally:
|
|
if failed:
|
|
context.tracing.stop(path=artifact_dir / "trace.zip")
|
|
else:
|
|
context.tracing.stop()
|
|
context.close()
|
|
browser.close()
|
|
|
|
return open_page
|