mirror of
https://github.com/ipnet-mesh/meshcore-hub.git
synced 2026-03-28 17:42:56 +01:00
- Add --e2e flag to pytest to run e2e tests - E2E tests skip by default with clear message - Fix type annotations in webhook.py for mypy compliance - Add proper type hints for comparison operations
158 lines
4.1 KiB
Python
158 lines
4.1 KiB
Python
"""Fixtures for end-to-end tests.
|
|
|
|
These tests require Docker Compose services to be running.
|
|
They are disabled by default and can be run with:
|
|
|
|
pytest -m e2e tests/e2e/
|
|
|
|
Or with the --e2e flag:
|
|
|
|
pytest --e2e tests/e2e/
|
|
"""
|
|
|
|
import os
|
|
import time
|
|
from typing import Generator
|
|
|
|
import httpx
|
|
import pytest
|
|
|
|
|
|
def pytest_configure(config: pytest.Config) -> None:
|
|
"""Register the e2e marker."""
|
|
config.addinivalue_line(
|
|
"markers",
|
|
"e2e: mark test as end-to-end test requiring Docker services",
|
|
)
|
|
|
|
|
|
def pytest_collection_modifyitems(
|
|
config: pytest.Config, items: list[pytest.Item]
|
|
) -> None:
|
|
"""Auto-mark all tests in this directory as e2e and skip if --e2e not provided."""
|
|
# Check if e2e tests should run
|
|
run_e2e = config.getoption("--e2e", default=False)
|
|
|
|
skip_e2e = pytest.mark.skip(
|
|
reason="E2E tests disabled by default. Use --e2e to run them."
|
|
)
|
|
|
|
for item in items:
|
|
# Mark all tests in e2e directory
|
|
if "e2e" in str(item.fspath):
|
|
item.add_marker(pytest.mark.e2e)
|
|
if not run_e2e:
|
|
item.add_marker(skip_e2e)
|
|
|
|
|
|
def pytest_addoption(parser: pytest.Parser) -> None:
|
|
"""Add --e2e option to pytest."""
|
|
parser.addoption(
|
|
"--e2e",
|
|
action="store_true",
|
|
default=False,
|
|
help="Run end-to-end tests (requires Docker services)",
|
|
)
|
|
|
|
|
|
# E2E test configuration
|
|
E2E_API_URL = os.environ.get("E2E_API_URL", "http://localhost:18000")
|
|
E2E_WEB_URL = os.environ.get("E2E_WEB_URL", "http://localhost:18080")
|
|
E2E_MQTT_HOST = os.environ.get("E2E_MQTT_HOST", "localhost")
|
|
E2E_MQTT_PORT = int(os.environ.get("E2E_MQTT_PORT", "11883"))
|
|
E2E_READ_KEY = os.environ.get("E2E_READ_KEY", "test-read-key")
|
|
E2E_ADMIN_KEY = os.environ.get("E2E_ADMIN_KEY", "test-admin-key")
|
|
|
|
|
|
def wait_for_service(url: str, timeout: int = 60) -> bool:
|
|
"""Wait for a service to become available.
|
|
|
|
Args:
|
|
url: Health check URL
|
|
timeout: Maximum seconds to wait
|
|
|
|
Returns:
|
|
True if service is available, False if timeout
|
|
"""
|
|
start = time.time()
|
|
while time.time() - start < timeout:
|
|
try:
|
|
response = httpx.get(url, timeout=5.0)
|
|
if response.status_code == 200:
|
|
return True
|
|
except httpx.RequestError:
|
|
pass
|
|
time.sleep(1)
|
|
return False
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def api_url() -> str:
|
|
"""Get API base URL."""
|
|
return E2E_API_URL
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def web_url() -> str:
|
|
"""Get Web dashboard URL."""
|
|
return E2E_WEB_URL
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def read_key() -> str:
|
|
"""Get read API key."""
|
|
return E2E_READ_KEY
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def admin_key() -> str:
|
|
"""Get admin API key."""
|
|
return E2E_ADMIN_KEY
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def api_client(api_url: str, read_key: str) -> Generator[httpx.Client, None, None]:
|
|
"""Create an API client with read access.
|
|
|
|
This fixture waits for the API to be available before returning.
|
|
"""
|
|
health_url = f"{api_url}/health"
|
|
if not wait_for_service(health_url):
|
|
pytest.skip(f"API not available at {api_url}")
|
|
|
|
with httpx.Client(
|
|
base_url=api_url,
|
|
headers={"Authorization": f"Bearer {read_key}"},
|
|
timeout=30.0,
|
|
) as client:
|
|
yield client
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def admin_client(api_url: str, admin_key: str) -> Generator[httpx.Client, None, None]:
|
|
"""Create an API client with admin access."""
|
|
health_url = f"{api_url}/health"
|
|
if not wait_for_service(health_url):
|
|
pytest.skip(f"API not available at {api_url}")
|
|
|
|
with httpx.Client(
|
|
base_url=api_url,
|
|
headers={"Authorization": f"Bearer {admin_key}"},
|
|
timeout=30.0,
|
|
) as client:
|
|
yield client
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def web_client(web_url: str) -> Generator[httpx.Client, None, None]:
|
|
"""Create a web dashboard client."""
|
|
health_url = f"{web_url}/health"
|
|
if not wait_for_service(health_url):
|
|
pytest.skip(f"Web dashboard not available at {web_url}")
|
|
|
|
with httpx.Client(
|
|
base_url=web_url,
|
|
timeout=30.0,
|
|
) as client:
|
|
yield client
|