Files
calminer/tests/e2e/conftest.py

88 lines
2.4 KiB
Python

import os
import subprocess
import time
from typing import Generator
import pytest
from playwright.sync_api import Browser, Page, Playwright, sync_playwright
import httpx
# Use a different port for the test server to avoid conflicts
TEST_PORT = 8001
BASE_URL = f"http://localhost:{TEST_PORT}"
@pytest.fixture(scope="session", autouse=True)
def live_server() -> Generator[str, None, None]:
"""Launch a live test server in a separate process."""
process = subprocess.Popen(
[
"uvicorn",
"main:app",
"--host",
"127.0.0.1",
f"--port={TEST_PORT}",
],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
env=os.environ.copy(),
)
deadline = time.perf_counter() + 30
last_error: Exception | None = None
while time.perf_counter() < deadline:
if process.poll() is not None:
raise RuntimeError("uvicorn server exited before becoming ready")
try:
response = httpx.get(BASE_URL, timeout=1.0)
if response.status_code < 500:
break
except Exception as exc: # noqa: BLE001
last_error = exc
time.sleep(0.5)
else:
process.terminate()
process.wait(timeout=5)
raise TimeoutError(
"Timed out waiting for uvicorn test server to start"
) from last_error
try:
yield BASE_URL
finally:
if process.poll() is None:
process.terminate()
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
process.kill()
process.wait(timeout=5)
@pytest.fixture(scope="session")
def playwright_instance() -> Generator[Playwright, None, None]:
"""Provide a Playwright instance for the test session."""
with sync_playwright() as p:
yield p
@pytest.fixture(scope="session")
def browser(
playwright_instance: Playwright,
) -> Generator[Browser, None, None]:
"""Provide a browser instance for the test session."""
browser = playwright_instance.chromium.launch()
yield browser
browser.close()
@pytest.fixture()
def page(browser: Browser, live_server: str) -> Generator[Page, None, None]:
"""Provide a new page for each test."""
page = browser.new_page(base_url=live_server)
page.goto("/")
page.wait_for_load_state("networkidle")
yield page
page.close()